From 49c223c9f237af9c022fb509d141b43970e2ab30 Mon Sep 17 00:00:00 2001 From: Marius Constantin Date: Mon, 19 Feb 2024 11:20:35 +0100 Subject: [PATCH 01/55] RUM-3246 Extract the dd-trace-core module from the java agent --- LICENSE-3rdparty.csv | 3 + .../dd-sdk-android-trace/build.gradle.kts | 2 +- .../transitiveDependencies | 17 +- features/dd-trace-core/.gitignore | 18 + features/dd-trace-core/api/apiSurface | 0 features/dd-trace-core/api/dd-trace-core.api | 6358 +++++++++++++++++ features/dd-trace-core/build.gradle.kts | 52 + features/dd-trace-core/consumer-rules.pro | 4 + features/dd-trace-core/lint.xml | 6 + .../trace/advice/ActiveRequestContext.java | 10 + .../trace/advice/RequiresRequestContext.java | 19 + .../main/java/datadog/trace/api/Config.java | 4165 +++++++++++ .../datadog/trace/api/ConfigCollector.java | 57 + .../datadog/trace/api/ConfigDefaults.java | 222 + .../java/datadog/trace/api/ConfigOrigin.java | 18 + .../java/datadog/trace/api/ConfigSetting.java | 52 + .../trace/api/CorrelationIdentifier.java | 29 + .../java/datadog/trace/api/DD128bTraceId.java | 178 + .../java/datadog/trace/api/DD64bTraceId.java | 126 + .../main/java/datadog/trace/api/DDSpanId.java | 87 + .../java/datadog/trace/api/DDSpanTypes.java | 36 + .../main/java/datadog/trace/api/DDTags.java | 64 + .../datadog/trace/api/DDTraceApiInfo.java | 27 + .../java/datadog/trace/api/DDTraceId.java | 104 + .../datadog/trace/api/DisableTestTrace.java | 21 + .../java/datadog/trace/api/DynamicConfig.java | 393 + .../trace/api/EndpointCheckpointer.java | 21 + .../trace/api/EndpointCheckpointerHolder.java | 67 + .../datadog/trace/api/EndpointTracker.java | 16 + .../java/datadog/trace/api/EventTracker.java | 113 + .../java/datadog/trace/api/Functions.java | 145 + .../java/datadog/trace/api/GlobalTracer.java | 95 + .../trace/api/IdGenerationStrategy.java | 117 + .../datadog/trace/api/InstrumenterConfig.java | 498 ++ .../trace/api/MethodFilterConfigParser.java | 141 + .../datadog/trace/api/NoOpStatsDClient.java | 46 + .../src/main/java/datadog/trace/api/Pair.java | 53 + .../main/java/datadog/trace/api/Platform.java | 350 + .../datadog/trace/api/ProductActivation.java | 29 + .../datadog/trace/api/PropagationStyle.java | 31 + .../trace/api/ResolverCacheConfig.java | 128 + .../main/java/datadog/trace/api/Stateful.java | 18 + .../java/datadog/trace/api/StatsDClient.java | 32 + .../trace/api/StatsDClientManager.java | 16 + .../main/java/datadog/trace/api/Trace.java | 25 + .../java/datadog/trace/api/TraceConfig.java | 41 + .../trace/api/TracePropagationStyle.java | 50 + .../main/java/datadog/trace/api/Tracer.java | 24 + .../trace/api/UserEventTrackingMode.java | 17 + .../java/datadog/trace/api/WellKnownTags.java | 52 + .../datadog/trace/api/WithGlobalTracer.java | 42 + .../datadog/trace/api/cache/CHMCache.java | 43 + .../java/datadog/trace/api/cache/DDCache.java | 21 + .../datadog/trace/api/cache/DDCaches.java | 85 + .../trace/api/cache/DDPartialKeyCache.java | 49 + .../trace/api/cache/FixedSizeCache.java | 175 + .../api/cache/FixedSizePartialKeyCache.java | 123 + .../api/cache/FixedSizeWeakKeyCache.java | 129 + .../api/cache/FixedSizeWeightedCache.java | 192 + .../api/cache/QualifiedClassNameCache.java | 61 + .../trace/api/cache/RadixTreeCache.java | 72 + .../trace/api/civisibility/CIConstants.java | 7 + .../trace/api/civisibility/CIVisibility.java | 50 + .../trace/api/civisibility/DDTest.java | 53 + .../trace/api/civisibility/DDTestModule.java | 91 + .../trace/api/civisibility/DDTestSession.java | 70 + .../trace/api/civisibility/DDTestSuite.java | 73 + .../civisibility/InstrumentationBridge.java | 31 + .../civisibility/config/Configurations.java | 107 + .../config/ModuleExecutionSettings.java | 98 + .../civisibility/config/TestIdentifier.java | 87 + .../civisibility/coverage/CoverageBridge.java | 97 + .../coverage/CoverageDataSupplier.java | 5 + .../coverage/CoverageProbeStore.java | 15 + .../api/civisibility/coverage/TestReport.java | 42 + .../coverage/TestReportFileEntry.java | 91 + .../coverage/TestReportHolder.java | 8 + .../events/BuildEventsHandler.java | 60 + .../events/TestEventsHandler.java | 88 + .../api/civisibility/noop/NoOpDDTest.java | 21 + .../civisibility/noop/NoOpDDTestModule.java | 31 + .../civisibility/noop/NoOpDDTestSession.java | 27 + .../civisibility/noop/NoOpDDTestSuite.java | 29 + .../civisibility/retry/TestRetryPolicy.java | 7 + .../trace/api/config/AppSecConfig.java | 28 + .../trace/api/config/CiVisibilityConfig.java | 78 + .../trace/api/config/CrashTrackingConfig.java | 26 + .../datadog/trace/api/config/CwsConfig.java | 10 + .../trace/api/config/DebuggerConfig.java | 34 + .../trace/api/config/GeneralConfig.java | 83 + .../datadog/trace/api/config/IastConfig.java | 25 + .../trace/api/config/JmxFetchConfig.java | 28 + .../trace/api/config/ProfilingConfig.java | 204 + .../trace/api/config/RemoteConfigConfig.java | 17 + .../config/TraceInstrumentationConfig.java | 139 + .../trace/api/config/TracerConfig.java | 135 + .../datadog/trace/api/config/UsmConfig.java | 9 + .../trace/api/env/CapturedEnvironment.java | 77 + .../experimental/DataStreamsCheckpointer.java | 49 + .../DataStreamsContextCarrier.java | 31 + .../datadog/trace/api/flare/TracerFlare.java | 84 + .../trace/api/function/TriConsumer.java | 5 + .../trace/api/function/TriFunction.java | 5 + .../api/gateway/BlockResponseFunction.java | 22 + .../trace/api/gateway/CallbackProvider.java | 17 + .../datadog/trace/api/gateway/EventType.java | 29 + .../datadog/trace/api/gateway/Events.java | 214 + .../java/datadog/trace/api/gateway/Flow.java | 98 + .../datadog/trace/api/gateway/IGSpanInfo.java | 20 + .../api/gateway/InstrumentationGateway.java | 438 ++ .../trace/api/gateway/RequestContext.java | 47 + .../trace/api/gateway/RequestContextSlot.java | 7 + .../trace/api/gateway/Subscription.java | 15 + .../api/gateway/SubscriptionService.java | 22 + .../datadog/trace/api/git/CommitInfo.java | 93 + .../trace/api/git/EmbeddedGitInfoBuilder.java | 77 + .../java/datadog/trace/api/git/GitInfo.java | 80 + .../datadog/trace/api/git/GitInfoBuilder.java | 9 + .../trace/api/git/GitInfoProvider.java | 167 + .../java/datadog/trace/api/git/GitUtils.java | 228 + .../datadog/trace/api/git/PersonInfo.java | 103 + .../datadog/trace/api/git/RawParseUtils.java | 392 + .../api/git/UserSuppliedGitInfoBuilder.java | 108 + .../trace/api/http/StoredBodyFactories.java | 125 + .../trace/api/http/StoredBodySupplier.java | 10 + .../trace/api/http/StoredByteBody.java | 310 + .../trace/api/http/StoredCharBody.java | 209 + .../datadog/trace/api/iast/IastCallSites.java | 14 + .../datadog/trace/api/iast/IastContext.java | 45 + .../trace/api/iast/IastDetectionMode.java | 85 + .../trace/api/iast/IastEnabledChecks.java | 25 + .../datadog/trace/api/iast/IastModule.java | 13 + .../trace/api/iast/InstrumentationBridge.java | 224 + .../datadog/trace/api/iast/Propagation.java | 10 + .../java/datadog/trace/api/iast/Sink.java | 13 + .../java/datadog/trace/api/iast/Source.java | 13 + .../datadog/trace/api/iast/SourceTypes.java | 110 + .../datadog/trace/api/iast/Taintable.java | 61 + .../trace/api/iast/VulnerabilityMarks.java | 21 + .../trace/api/iast/VulnerabilityTypes.java | 175 + .../api/iast/propagation/CodecModule.java | 19 + .../iast/propagation/PropagationModule.java | 185 + .../api/iast/propagation/StringModule.java | 55 + .../api/iast/sink/ApplicationModule.java | 10 + .../api/iast/sink/CommandInjectionModule.java | 17 + .../api/iast/sink/HeaderInjectionModule.java | 10 + .../iast/sink/HstsMissingHeaderModule.java | 3 + .../trace/api/iast/sink/HttpCookieModule.java | 13 + .../api/iast/sink/HttpRequestEndModule.java | 33 + .../iast/sink/HttpResponseHeaderModule.java | 13 + .../api/iast/sink/InsecureCookieModule.java | 3 + .../api/iast/sink/LdapInjectionModule.java | 12 + .../api/iast/sink/NoHttpOnlyCookieModule.java | 3 + .../api/iast/sink/NoSameSiteCookieModule.java | 3 + .../api/iast/sink/PathTraversalModule.java | 22 + .../api/iast/sink/SqlInjectionModule.java | 14 + .../trace/api/iast/sink/SsrfModule.java | 12 + .../api/iast/sink/StacktraceLeakModule.java | 10 + .../sink/TrustBoundaryViolationModule.java | 10 + .../iast/sink/UnvalidatedRedirectModule.java | 19 + .../trace/api/iast/sink/WeakCipherModule.java | 10 + .../trace/api/iast/sink/WeakHashModule.java | 10 + .../api/iast/sink/WeakRandomnessModule.java | 10 + .../api/iast/sink/XContentTypeModule.java | 3 + .../api/iast/sink/XPathInjectionModule.java | 9 + .../trace/api/iast/sink/XssModule.java | 19 + .../trace/api/iast/telemetry/IastMetric.java | 188 + .../iast/telemetry/IastMetricCollector.java | 238 + .../trace/api/iast/telemetry/Verbosity.java | 24 + .../datadog/trace/api/iast/util/Cookie.java | 66 + .../datadog/trace/api/intake/TrackType.java | 7 + .../interceptor/AbstractTraceInterceptor.java | 38 + .../trace/api/interceptor/MutableSpan.java | 78 + .../api/interceptor/TraceInterceptor.java | 22 + .../trace/api/internal/InternalTracer.java | 33 + .../trace/api/internal/TraceSegment.java | 90 + .../api/internal/util/LongStringUtils.java | 172 + .../trace/api/metrics/CoreCounter.java | 25 + .../trace/api/metrics/SpanMetricRegistry.java | 33 + .../api/metrics/SpanMetricRegistryImpl.java | 48 + .../trace/api/metrics/SpanMetrics.java | 19 + .../trace/api/metrics/SpanMetricsImpl.java | 72 + .../trace/api/naming/NamingSchema.java | 258 + .../datadog/trace/api/naming/SpanNaming.java | 51 + .../trace/api/naming/v0/CacheNamingV0.java | 43 + .../trace/api/naming/v0/ClientNamingV0.java | 46 + .../trace/api/naming/v0/CloudNamingV0.java | 51 + .../trace/api/naming/v0/DatabaseNamingV0.java | 37 + .../api/naming/v0/MessagingNamingV0.java | 65 + .../trace/api/naming/v0/NamingSchemaV0.java | 63 + .../api/naming/v0/PeerServiceNamingV0.java | 21 + .../trace/api/naming/v0/ServerNamingV0.java | 51 + .../trace/api/naming/v1/CacheNamingV1.java | 18 + .../trace/api/naming/v1/ClientNamingV1.java | 34 + .../trace/api/naming/v1/CloudNamingV1.java | 55 + .../trace/api/naming/v1/DatabaseNamingV1.java | 41 + .../api/naming/v1/MessagingNamingV1.java | 54 + .../trace/api/naming/v1/NamingSchemaV1.java | 55 + .../api/naming/v1/PeerServiceNamingV1.java | 113 + .../trace/api/naming/v1/ServerNamingV1.java | 20 + .../trace/api/normalize/AntPathMatcher.java | 351 + .../AntPatternHttpPathNormalizer.java | 64 + .../api/normalize/HttpPathNormalizer.java | 9 + .../api/normalize/HttpResourceNames.java | 126 + .../trace/api/normalize/SQLNormalizer.java | 124 + .../normalize/SimpleHttpPathNormalizer.java | 91 + .../trace/api/profiling/ObservableType.java | 4 + .../trace/api/profiling/Profiling.java | 41 + .../trace/api/profiling/ProfilingContext.java | 38 + .../profiling/ProfilingContextAttribute.java | 9 + .../api/profiling/ProfilingListener.java | 10 + .../api/profiling/ProfilingListeners.java | 44 + .../profiling/ProfilingListenersRegistry.java | 28 + .../trace/api/profiling/ProfilingScope.java | 9 + .../api/profiling/ProfilingSnapshot.java | 8 + .../trace/api/profiling/QueueTiming.java | 8 + .../trace/api/profiling/RecordingData.java | 97 + .../api/profiling/RecordingDataListener.java | 30 + .../api/profiling/RecordingInputStream.java | 34 + .../trace/api/profiling/RecordingType.java | 15 + .../datadog/trace/api/profiling/Timer.java | 20 + .../datadog/trace/api/profiling/Timing.java | 19 + .../TransientProfilingContextHolder.java | 3 + .../trace/api/profiling/package-info.java | 6 + .../trace/api/sampling/AdaptiveSampler.java | 317 + .../trace/api/sampling/ConstantSampler.java | 25 + .../trace/api/sampling/PrioritySampling.java | 20 + .../datadog/trace/api/sampling/Sampler.java | 25 + .../trace/api/sampling/SamplingMechanism.java | 58 + .../trace/api/sampling/SamplingRule.java | 65 + .../scopemanager/ExtendedScopeListener.java | 13 + .../trace/api/scopemanager/ScopeListener.java | 15 + .../api/telemetry/CoreMetricCollector.java | 72 + .../api/telemetry/IntegrationsCollector.java | 50 + .../trace/api/telemetry/LogCollector.java | 107 + .../trace/api/telemetry/MetricCollector.java | 113 + .../api/telemetry/WafMetricCollector.java | 189 + .../api/time/ControllableTimeSource.java | 35 + .../trace/api/time/SystemTimeSource.java | 29 + .../datadog/trace/api/time/TimeSource.java | 22 + .../trace/appsec/api/blocking/Blocking.java | 137 + .../api/blocking/BlockingContentType.java | 21 + .../appsec/api/blocking/BlockingDetails.java | 22 + .../api/blocking/BlockingException.java | 23 + .../appsec/api/blocking/BlockingService.java | 37 + .../trace/bootstrap/ActiveSubsystems.java | 5 + .../config/provider/AgentArgsInjector.java | 42 + .../config/provider/AgentArgsParser.java | 44 + .../CapturedEnvironmentConfigSource.java | 26 + .../config/provider/ConfigConverter.java | 403 ++ .../config/provider/ConfigProvider.java | 487 ++ .../provider/EnvironmentConfigSource.java | 18 + .../provider/PropertiesConfigSource.java | 35 + .../SystemPropertiesConfigSource.java | 18 + .../api/AgentDataStreamsMonitoring.java | 40 + .../instrumentation/api/AgentHistogram.java | 24 + .../instrumentation/api/AgentPropagation.java | 55 + .../instrumentation/api/AgentScope.java | 32 + .../api/AgentScopeManager.java | 21 + .../instrumentation/api/AgentSpan.java | 225 + .../instrumentation/api/AgentSpanLink.java | 71 + .../instrumentation/api/AgentTrace.java | 7 + .../instrumentation/api/AgentTracer.java | 1226 ++++ .../api/AttachableWrapper.java | 15 + .../instrumentation/api/Backlog.java | 30 + .../instrumentation/api/ErrorPriorities.java | 8 + .../instrumentation/api/InboxItem.java | 3 + .../api/InstrumentationTags.java | 114 + .../api/InternalSpanTypes.java | 47 + .../instrumentation/api/PathwayContext.java | 37 + .../instrumentation/api/ProfilerContext.java | 17 + .../api/ProfilingContextIntegration.java | 64 + .../api/ResourceNamePriorities.java | 13 + .../instrumentation/api/SamplerConstants.java | 9 + .../instrumentation/api/ScopeSource.java | 17 + .../instrumentation/api/ScopeState.java | 7 + .../instrumentation/api/ScopeStateAware.java | 5 + .../instrumentation/api/SpanLink.java | 95 + .../api/SpanLinkAttributes.java | 122 + .../instrumentation/api/StatsPoint.java | 79 + .../instrumentation/api/TagContext.java | 274 + .../bootstrap/instrumentation/api/Tags.java | 114 + .../instrumentation/api/TaskWrapper.java | 15 + .../instrumentation/api/URIDataAdapter.java | 43 + .../api/URIDataAdapterBase.java | 48 + .../api/URIDefaultDataAdapter.java | 57 + .../api/URIRawDataAdapter.java | 55 + .../instrumentation/api/URIUtils.java | 302 + .../instrumentation/api/UTF8BytesString.java | 134 + .../api/UnparseableURIDataAdapter.java | 66 + .../instrumentation/api/WriterConstants.java | 12 + .../CiVisibilityApmProtocolInterceptor.java | 45 + .../CiVisibilityTraceInterceptor.java | 56 + .../common/GitMetadataTraceInterceptor.java | 38 + .../trace/common/metrics/AggregateMetric.java | 78 + .../trace/common/metrics/Aggregator.java | 194 + .../datadog/trace/common/metrics/Batch.java | 89 + .../trace/common/metrics/EventListener.java | 12 + .../trace/common/metrics/InboxItem.java | 31 + .../trace/common/metrics/MetricKey.java | 87 + .../trace/common/metrics/MetricWriter.java | 11 + .../common/metrics/MetricsAggregator.java | 18 + .../common/metrics/NoOpMetricsAggregator.java | 34 + .../metrics/SerializingMetricWriter.java | 136 + .../datadog/trace/common/metrics/Sink.java | 8 + .../trace/common/sampling/AllSampler.java | 17 + .../common/sampling/DeterministicSampler.java | 69 + .../common/sampling/ForcePrioritySampler.java | 25 + .../common/sampling/PrioritySampler.java | 7 + .../common/sampling/PrioritySampling.java | 22 + .../sampling/RateByServiceTraceSampler.java | 168 + .../trace/common/sampling/RateSampler.java | 5 + .../sampling/RuleBasedTraceSampler.java | 158 + .../trace/common/sampling/Sampler.java | 97 + .../trace/common/sampling/SamplingRule.java | 140 + .../common/sampling/SingleSpanSampler.java | 93 + .../common/sampling/SpanSamplingRules.java | 207 + .../common/sampling/TraceSamplingRules.java | 163 + .../writer/CompositePayloadDispatcher.java | 45 + .../common/writer/DDSpanJsonAdapter.java | 111 + .../trace/common/writer/ListWriter.java | 167 + .../trace/common/writer/LoggingWriter.java | 52 + .../datadog/trace/common/writer/Payload.java | 99 + .../common/writer/PayloadDispatcher.java | 16 + .../common/writer/PayloadDispatcherImpl.java | 129 + .../trace/common/writer/PrintingWriter.java | 66 + .../trace/common/writer/RemoteApi.java | 152 + .../trace/common/writer/RemoteMapper.java | 66 + .../common/writer/RemoteMapperDiscovery.java | 7 + .../common/writer/RemoteResponseListener.java | 8 + .../common/writer/SpanSamplingWorker.java | 193 + .../common/writer/TraceProcessingWorker.java | 299 + .../common/writer/TraceStructureWriter.java | 227 + .../datadog/trace/common/writer/Writer.java | 36 + .../common/writer/ddagent/FlushEvent.java | 15 + .../common/writer/ddagent/Prioritization.java | 153 + .../ddagent/PrioritizationStrategy.java | 19 + .../common/writer/ddagent/TraceMapper.java | 15 + .../datadog/trace/context/TraceScope.java | 62 + .../java/datadog/trace/core/CoreSpan.java | 90 + .../java/datadog/trace/core/CoreTracer.java | 1456 ++++ .../main/java/datadog/trace/core/DDSpan.java | 824 +++ .../datadog/trace/core/DDSpanContext.java | 935 +++ .../java/datadog/trace/core/DDSpanLink.java | 137 + .../datadog/trace/core/DDTraceCoreInfo.java | 36 + .../trace/core/LongRunningTracesTracker.java | 149 + .../java/datadog/trace/core/Metadata.java | 87 + .../datadog/trace/core/MetadataConsumer.java | 11 + .../java/datadog/trace/core/PendingTrace.java | 500 ++ .../trace/core/PendingTraceBuffer.java | 302 + .../java/datadog/trace/core/StatusLogger.java | 203 + .../DataStreamContextExtractor.java | 60 + .../DataStreamContextInjector.java | 109 + .../DataStreamsContextCarrierAdapter.java | 31 + .../datastreams/DataStreamsMonitoring.java | 40 + .../datastreams/DatastreamsPayloadWriter.java | 7 + .../datastreams/DefaultPathwayContext.java | 435 ++ .../MsgPackDatastreamsPayloadWriter.java | 169 + .../datastreams/NoOpDataStreamMonitoring.java | 77 + .../trace/core/datastreams/SchemaSampler.java | 29 + .../trace/core/datastreams/StatsBucket.java | 59 + .../trace/core/datastreams/StatsGroup.java | 70 + .../trace/core/datastreams/TagsProcessor.java | 118 + .../trace/core/histogram/Histogram.java | 59 + .../trace/core/histogram/Histograms.java | 22 + .../trace/core/monitor/HealthMetrics.java | 83 + .../trace/core/monitor/MonitoringImpl.java | 66 + .../trace/core/monitor/StatsDCounter.java | 27 + .../core/monitor/ThreadLocalRecording.java | 32 + .../datadog/trace/core/monitor/Timer.java | 90 + .../datadog/trace/core/monitor/Utils.java | 14 + .../trace/core/propagation/B3HttpCodec.java | 357 + .../trace/core/propagation/B3TraceId.java | 73 + .../core/propagation/ContextInterpreter.java | 304 + .../core/propagation/CorePropagation.java | 97 + .../core/propagation/DatadogHttpCodec.java | 245 + .../core/propagation/ExtractedContext.java | 103 + .../core/propagation/HaystackHttpCodec.java | 288 + .../trace/core/propagation/HttpCodec.java | 354 + .../core/propagation/NoOpCorePropagation.java | 59 + .../trace/core/propagation/NoneCodec.java | 23 + .../core/propagation/PropagationTags.java | 104 + .../core/propagation/TagContextExtractor.java | 30 + .../trace/core/propagation/W3CHttpCodec.java | 373 + .../trace/core/propagation/XRayHttpCodec.java | 266 + .../propagation/ptags/DatadogPTagsCodec.java | 186 + .../core/propagation/ptags/PTagsCodec.java | 212 + .../core/propagation/ptags/PTagsFactory.java | 317 + .../core/propagation/ptags/TagElement.java | 40 + .../trace/core/propagation/ptags/TagKey.java | 146 + .../core/propagation/ptags/TagValue.java | 216 + .../core/propagation/ptags/W3CPTagsCodec.java | 745 ++ .../scopemanager/AbstractContinuation.java | 34 + .../scopemanager/ConcurrentContinuation.java | 95 + .../core/scopemanager/ContinuableScope.java | 207 + .../scopemanager/ContinuableScopeManager.java | 384 + .../core/scopemanager/ContinuingScope.java | 27 + .../trace/core/scopemanager/ScopeStack.java | 127 + .../core/scopemanager/SingleContinuation.java | 61 + .../trace/core/taginterceptor/RuleFlags.java | 55 + .../core/taginterceptor/TagInterceptor.java | 323 + .../core/tagprocessor/BaseServiceAdder.java | 30 + .../tagprocessor/PeerServiceCalculator.java | 59 + .../core/tagprocessor/PostProcessorChain.java | 29 + .../core/tagprocessor/QueryObfuscator.java | 73 + .../core/tagprocessor/TagsPostProcessor.java | 13 + .../TagsPostProcessorFactory.java | 44 + .../datadog/trace/core/util/GlobPattern.java | 47 + .../datadog/trace/core/util/LRUCache.java | 46 + .../java/datadog/trace/core/util/Matcher.java | 7 + .../datadog/trace/core/util/Matchers.java | 69 + .../core/util/NoneSystemAccessProvider.java | 8 + .../trace/core/util/SimpleRateLimiter.java | 82 + .../datadog/trace/core/util/SystemAccess.java | 59 + .../trace/core/util/SystemAccessProvider.java | 15 + .../datadog/trace/core/util/TagsMatcher.java | 42 + .../datadog/trace/ddagent/DroppingPolicy.java | 16 + .../datadog/trace/lambda/LambdaHandler.java | 184 + .../ReadFromInputStreamJsonAdapter.java | 34 + .../SkipUnsupportedTypeJsonAdapter.java | 39 + .../trace/logging/GlobalLogLevelSwitcher.java | 53 + .../java/datadog/trace/logging/LogLevel.java | 39 + .../trace/logging/LogLevelSwitcher.java | 18 + .../logging/LoggingSettingsDescription.java | 20 + .../java/datadog/trace/monitor/Counter.java | 14 + .../datadog/trace/monitor/Monitoring.java | 46 + .../datadog/trace/monitor/NoOpCounter.java | 16 + .../datadog/trace/monitor/NoOpRecording.java | 26 + .../java/datadog/trace/monitor/Recording.java | 22 + .../datadog/trace/relocate/api/IOLogger.java | 117 + .../trace/relocate/api/RatelimitedLogger.java | 70 + .../serialization/ByteBufferConsumer.java | 8 + .../datadog/trace/serialization/Codec.java | 295 + .../trace/serialization/EncodingCache.java | 7 + .../trace/serialization/FlushingBuffer.java | 107 + .../trace/serialization/GrowableBuffer.java | 128 + .../datadog/trace/serialization/Mapper.java | 8 + .../trace/serialization/MessageFormatter.java | 7 + .../trace/serialization/StreamingBuffer.java | 36 + .../trace/serialization/ValueWriter.java | 8 + .../datadog/trace/serialization/Writable.java | 67 + .../serialization/WritableFormatter.java | 3 + .../serialization/msgpack/MsgPackWriter.java | 581 ++ .../trace/util/AgentProxySelector.java | 36 + .../trace/util/AgentTaskScheduler.java | 348 + .../trace/util/AgentThreadFactory.java | 115 + .../datadog/trace/util/ClassNameTrie.java | 927 +++ .../datadog/trace/util/CollectionUtils.java | 53 + .../java/datadog/trace/util/FNV64Hash.java | 54 + .../datadog/trace/util/MethodHandles.java | 176 + .../java/datadog/trace/util/PidHelper.java | 68 + .../datadog/trace/util/ProcessSupervisor.java | 150 + .../java/datadog/trace/util/ProcessUtils.java | 51 + .../main/java/datadog/trace/util/Strings.java | 359 + .../java/datadog/trace/util/TagsHelper.java | 83 + .../java/datadog/trace/util/TraceUtils.java | 216 + .../util/stacktrace/AbstractStackWalker.java | 23 + .../util/stacktrace/DefaultStackWalker.java | 20 + .../trace/util/stacktrace/StackUtils.java | 88 + .../trace/util/stacktrace/StackWalker.java | 12 + .../util/stacktrace/StackWalkerFactory.java | 63 + .../FatalAgentMisconfigurationError.java | 15 + features/dd-trace-core/transitiveDependencies | 32 + gradle/libs.versions.toml | 22 + settings.gradle.kts | 3 + 465 files changed, 52636 insertions(+), 2 deletions(-) create mode 100644 features/dd-trace-core/.gitignore create mode 100644 features/dd-trace-core/api/apiSurface create mode 100644 features/dd-trace-core/api/dd-trace-core.api create mode 100644 features/dd-trace-core/build.gradle.kts create mode 100644 features/dd-trace-core/consumer-rules.pro create mode 100644 features/dd-trace-core/lint.xml create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/advice/ActiveRequestContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/advice/RequiresRequestContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/Config.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/ConfigCollector.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/ConfigDefaults.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/ConfigOrigin.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/ConfigSetting.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/CorrelationIdentifier.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/DD128bTraceId.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/DD64bTraceId.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanId.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanTypes.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/DDTags.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceApiInfo.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceId.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/DisableTestTrace.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/DynamicConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointerHolder.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/EndpointTracker.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/EventTracker.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/Functions.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/GlobalTracer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/InstrumenterConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/MethodFilterConfigParser.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/NoOpStatsDClient.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/Pair.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/ProductActivation.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/ResolverCacheConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/Stateful.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClient.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClientManager.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/Trace.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/TraceConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/Tracer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/UserEventTrackingMode.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/WellKnownTags.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/WithGlobalTracer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/CHMCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCaches.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDPartialKeyCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizePartialKeyCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeakKeyCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeightedCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/QualifiedClassNameCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/RadixTreeCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIConstants.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIVisibility.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTest.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSession.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSuite.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/InstrumentationBridge.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/Configurations.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/TestIdentifier.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageBridge.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReport.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportHolder.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/BuildEventsHandler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/TestEventsHandler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTest.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/retry/TestRetryPolicy.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/AppSecConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/CrashTrackingConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/CwsConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/DebuggerConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/GeneralConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/IastConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/JmxFetchConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/ProfilingConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/RemoteConfigConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/TracerConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/config/UsmConfig.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/env/CapturedEnvironment.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsCheckpointer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsContextCarrier.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/flare/TracerFlare.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/function/TriConsumer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/function/TriFunction.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/BlockResponseFunction.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/CallbackProvider.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/EventType.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Events.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Flow.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/IGSpanInfo.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContextSlot.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Subscription.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/gateway/SubscriptionService.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/CommitInfo.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/EmbeddedGitInfoBuilder.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfo.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoBuilder.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoProvider.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/GitUtils.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/PersonInfo.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/RawParseUtils.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodyFactories.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodySupplier.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredByteBody.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredCharBody.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastCallSites.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastDetectionMode.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastEnabledChecks.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/InstrumentationBridge.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/Propagation.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/Sink.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/Source.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/SourceTypes.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/Taintable.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityMarks.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityTypes.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/CodecModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/PropagationModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/StringModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/ApplicationModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/CommandInjectionModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HeaderInjectionModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpCookieModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpRequestEndModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/InsecureCookieModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/LdapInjectionModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/PathTraversalModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SqlInjectionModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SsrfModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/StacktraceLeakModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakCipherModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakHashModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakRandomnessModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XContentTypeModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XPathInjectionModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XssModule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetric.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/Verbosity.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/iast/util/Cookie.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/intake/TrackType.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/AbstractTraceInterceptor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/MutableSpan.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/TraceInterceptor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/internal/InternalTracer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/internal/TraceSegment.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/internal/util/LongStringUtils.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/metrics/CoreCounter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistry.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistryImpl.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetrics.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricsImpl.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/NamingSchema.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/SpanNaming.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CacheNamingV0.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ClientNamingV0.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CloudNamingV0.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/DatabaseNamingV0.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/NamingSchemaV0.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ServerNamingV0.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CacheNamingV1.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ClientNamingV1.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CloudNamingV1.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/DatabaseNamingV1.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/NamingSchemaV1.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ServerNamingV1.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPathMatcher.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpPathNormalizer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpResourceNames.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SQLNormalizer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Profiling.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContextAttribute.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListener.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListeners.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListenersRegistry.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingScope.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingSnapshot.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/QueueTiming.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingData.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingDataListener.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingInputStream.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingType.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timing.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/TransientProfilingContextHolder.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/package-info.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/sampling/AdaptiveSampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/sampling/ConstantSampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/sampling/PrioritySampling.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/sampling/Sampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingMechanism.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingRule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ExtendedScopeListener.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ScopeListener.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/CoreMetricCollector.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/IntegrationsCollector.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/LogCollector.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/MetricCollector.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/WafMetricCollector.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/time/ControllableTimeSource.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/time/SystemTimeSource.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/time/TimeSource.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/Blocking.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingContentType.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingDetails.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingException.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingService.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/ActiveSubsystems.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsParser.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Backlog.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InboxItem.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeState.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLink.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TagContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIUtils.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/GitMetadataTraceInterceptor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/AggregateMetric.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Aggregator.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Batch.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/EventListener.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricKey.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricWriter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricsAggregator.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/SerializingMetricWriter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Sink.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/AllSampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/DeterministicSampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/ForcePrioritySampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampling.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateByServiceTraceSampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateSampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RuleBasedTraceSampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/Sampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SamplingRule.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SingleSpanSampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SpanSamplingRules.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/sampling/TraceSamplingRules.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/CompositePayloadDispatcher.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/DDSpanJsonAdapter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/ListWriter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/LoggingWriter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcher.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcherImpl.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/PrintingWriter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteApi.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapper.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapperDiscovery.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteResponseListener.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/SpanSamplingWorker.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceProcessingWorker.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceStructureWriter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/Writer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/FlushEvent.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/Prioritization.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapper.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/context/TraceScope.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanLink.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/DDTraceCoreInfo.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/LongRunningTracesTracker.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/Metadata.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/MetadataConsumer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/PendingTrace.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/PendingTraceBuffer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/StatusLogger.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextExtractor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextInjector.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/MsgPackDatastreamsPayloadWriter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/SchemaSampler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsBucket.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsGroup.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/TagsProcessor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histogram.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histograms.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/monitor/MonitoringImpl.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/monitor/StatsDCounter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/monitor/ThreadLocalRecording.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Timer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Utils.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ContextInterpreter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/DatadogHttpCodec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ExtractedContext.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HttpCodec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoOpCorePropagation.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoneCodec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/PropagationTags.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/TagContextExtractor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/W3CHttpCodec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/XRayHttpCodec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsCodec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsFactory.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagElement.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagKey.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagValue.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/AbstractContinuation.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ConcurrentContinuation.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuingScope.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/SingleContinuation.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/RuleFlags.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/TagInterceptor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/BaseServiceAdder.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PostProcessorChain.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/QueryObfuscator.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/util/GlobPattern.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/util/LRUCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/util/Matcher.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/util/Matchers.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/util/NoneSystemAccessProvider.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/util/SimpleRateLimiter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccess.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccessProvider.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/util/TagsMatcher.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/ddagent/DroppingPolicy.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/lambda/SkipUnsupportedTypeJsonAdapter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/logging/GlobalLogLevelSwitcher.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevelSwitcher.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/logging/LoggingSettingsDescription.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/monitor/Counter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/monitor/Monitoring.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpCounter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpRecording.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/monitor/Recording.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/relocate/api/IOLogger.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/relocate/api/RatelimitedLogger.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/ByteBufferConsumer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/Codec.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/EncodingCache.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/FlushingBuffer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/GrowableBuffer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/Mapper.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/MessageFormatter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/StreamingBuffer.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/ValueWriter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/Writable.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/WritableFormatter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/msgpack/MsgPackWriter.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/AgentProxySelector.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/AgentTaskScheduler.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/AgentThreadFactory.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/ClassNameTrie.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/CollectionUtils.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/FNV64Hash.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/MethodHandles.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/PidHelper.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/ProcessSupervisor.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/ProcessUtils.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/TagsHelper.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/TraceUtils.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/AbstractStackWalker.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/DefaultStackWalker.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackUtils.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalker.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalkerFactory.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java create mode 100644 features/dd-trace-core/transitiveDependencies diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index 39b6becff5..bc77e471f2 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -44,6 +44,7 @@ import,androidx.viewpager,Apache-2.0,Copyright 2018 The Android Open Source Proj import,androidx.work,Apache-2.0,Copyright 2018 The Android Open Source Project import,com.github.bumptech.glide,"Simplified BSD License/The Apache Software License, Version 2.0","Copyright 2014 Google, Inc. All rights reserved, Copyright (c) 2013. Bump Technologies Inc. All Rights Reserved." import,com.facebook.fresco,MIT,"Copyright (c) Facebook, Inc. and its affiliates" +import,com.github.spotbugs,"GNU LESSER GENERAL PUBLIC LICENSE, Version 2.1","Copyright (C) 1991, 1999 Free Software Foundation, Inc." import,com.google.android.material,Apache-2.0,Copyright 2018 The Android Open Source Project import,com.google.code.gson,Apache-2.0,Copyright 2008 Google Inc import,com.google.guava,Apache-2.0,Copyright 2009 The Guava Authors @@ -90,6 +91,7 @@ import(test),com.github.xgouchet.Elmyr,MIT,Copyright 2017-2019 Xavier F. Gouchet import(test),com.google.android.apps.common.testing.accessibility.framework,Apache-2.0,Copyright 2018 The Android Open Source Project import(test),com.google.code.findbugs,Apache-2.0,"Copyright (C) 2006, University of Maryland" import(test),com.parse.bolts,"BSD License","Copyright (c) Facebook, Inc. and its affiliates." +import(test),com.google.re2j,"Go License","Copyright (c) 2009 The Go Authors. All rights reserved." import(test),greatest,ICT,"Copyright (c) 2011-2018 Scott Vokes " import(test),javax.inject,Apache-2.0,Copyright (C) 2009 The JSR-330 Expert Group import(test),junit,EPL-1.0,Copyright © 2002-2019 JUnit @@ -101,6 +103,7 @@ import(test),org.assertj,Apache-2.0,Copyright 2012-2019 the original author or a import(test),org.ccil.cowan.tagsoup,Apache-2.0,Copyright 2002-2008 by John Cowan import(test),org.hamcrest,BSD-3-Clause,Copyright (c) 2000-2015 www.hamcrest.org import(test),org.jacoco,EPL-2.0,"Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors" +import(test),org.jctools,"Apache-2.0","Copyright 2023 Datadog, Inc." import(test),org.junit,EPL-2.0,Copyright 2015-2019 the original author or authors import(test),org.junit.jupiter,EPL-2.0,Copyright 2015-2019 the original author or authors import(test),org.junit.platform,EPL-2.0,Copyright 2015-2019 the original author or authors diff --git a/features/dd-sdk-android-trace/build.gradle.kts b/features/dd-sdk-android-trace/build.gradle.kts index 987865b335..e85de819d3 100644 --- a/features/dd-sdk-android-trace/build.gradle.kts +++ b/features/dd-sdk-android-trace/build.gradle.kts @@ -41,7 +41,6 @@ android { defaultConfig { consumerProguardFiles("consumer-rules.pro") } - namespace = "com.datadog.android.trace" sourceSets.named("test") { @@ -52,6 +51,7 @@ android { dependencies { api(project(":dd-sdk-android-core")) + implementation(project(":features:dd-trace-core")) implementation(libs.kotlin) implementation(libs.gson) implementation(libs.androidXAnnotation) diff --git a/features/dd-sdk-android-trace/transitiveDependencies b/features/dd-sdk-android-trace/transitiveDependencies index 9e6270370a..cd26cca254 100644 --- a/features/dd-sdk-android-trace/transitiveDependencies +++ b/features/dd-sdk-android-trace/transitiveDependencies @@ -1,13 +1,28 @@ Dependencies List androidx.annotation:annotation:1.3.0 : 30 Kb +com.github.spotbugs:spotbugs-annotations:4.2.0 : 14 Kb +com.github.spotbugs:spotbugs:4.2.0 : 3 Mb +com.google.code.findbugs:jsr305:3.0.2 : 19 Kb com.google.code.gson:gson:2.10.1 : 276 Kb io.opentracing:opentracing-api:0.32.0 : 18 Kb io.opentracing:opentracing-noop:0.32.0 : 10 Kb io.opentracing:opentracing-util:0.32.0 : 10 Kb +net.jcip:jcip-annotations:1.0 : 2 Kb +org.apache.bcel:bcel:6.5.0 : 678 Kb +org.apache.commons:commons-lang3:3.11 : 564 Kb +org.apache.commons:commons-text:1.9 : 211 Kb +org.dom4j:dom4j:2.1.3 : 316 Kb org.jetbrains.kotlin:kotlin-stdlib-common:1.8.10 : 212 Kb org.jetbrains.kotlin:kotlin-stdlib:1.8.10 : 1598 Kb org.jetbrains:annotations:13.0 : 17 Kb +org.json:json:20200518 : 64 Kb +org.ow2.asm:asm-analysis:9.0 : 32 Kb +org.ow2.asm:asm-commons:9.0 : 69 Kb +org.ow2.asm:asm-tree:9.0 : 51 Kb +org.ow2.asm:asm-util:9.0 : 82 Kb +org.ow2.asm:asm:9.0 : 118 Kb +org.slf4j:slf4j-api:1.7.30 : 40 Kb -Total transitive dependencies size : 2 Mb +Total transitive dependencies size : 7 Mb diff --git a/features/dd-trace-core/.gitignore b/features/dd-trace-core/.gitignore new file mode 100644 index 0000000000..e5614b9871 --- /dev/null +++ b/features/dd-trace-core/.gitignore @@ -0,0 +1,18 @@ +# Built application files +*.apk +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +build/ diff --git a/features/dd-trace-core/api/apiSurface b/features/dd-trace-core/api/apiSurface new file mode 100644 index 0000000000..e69de29bb2 diff --git a/features/dd-trace-core/api/dd-trace-core.api b/features/dd-trace-core/api/dd-trace-core.api new file mode 100644 index 0000000000..6cb2342e7d --- /dev/null +++ b/features/dd-trace-core/api/dd-trace-core.api @@ -0,0 +1,6358 @@ +public class datadog/appsec/api/blocking/Blocking { + public static fun forUser (Ljava/lang/String;)Ldatadog/appsec/api/blocking/Blocking$UserBlockingSpec; + public static fun setBlockingService (Ldatadog/appsec/api/blocking/BlockingService;)V + public static fun tryCommitBlockingResponse (ILdatadog/appsec/api/blocking/BlockingContentType;)Z + public static fun tryCommitBlockingResponse (ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z +} + +public class datadog/appsec/api/blocking/Blocking$UserBlockingSpec { + public fun blockIfMatch ()V + public fun shouldBlock ()Ldatadog/appsec/api/blocking/BlockingDetails; +} + +public final class datadog/appsec/api/blocking/BlockingContentType : java/lang/Enum { + public static final field AUTO Ldatadog/appsec/api/blocking/BlockingContentType; + public static final field HTML Ldatadog/appsec/api/blocking/BlockingContentType; + public static final field JSON Ldatadog/appsec/api/blocking/BlockingContentType; + public static final field NONE Ldatadog/appsec/api/blocking/BlockingContentType; + public static fun valueOf (Ljava/lang/String;)Ldatadog/appsec/api/blocking/BlockingContentType; + public static fun values ()[Ldatadog/appsec/api/blocking/BlockingContentType; +} + +public class datadog/appsec/api/blocking/BlockingDetails { + public final field blockingContentType Ldatadog/appsec/api/blocking/BlockingContentType; + public final field extraHeaders Ljava/util/Map; + public final field statusCode I + public fun (ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)V +} + +public class datadog/appsec/api/blocking/BlockingException : java/lang/RuntimeException { + public fun ()V + public fun (Ljava/lang/String;)V + public fun (Ljava/lang/String;Ljava/lang/Throwable;)V + public fun (Ljava/lang/Throwable;)V +} + +public abstract interface class datadog/appsec/api/blocking/BlockingService { + public static final field NOOP Ldatadog/appsec/api/blocking/BlockingService; + public abstract fun shouldBlockUser (Ljava/lang/String;)Ldatadog/appsec/api/blocking/BlockingDetails; + public abstract fun tryCommitBlockingResponse (ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z +} + +public class datadog/appsec/api/blocking/BlockingService$BlockingServiceNoop : datadog/appsec/api/blocking/BlockingService { + public fun shouldBlockUser (Ljava/lang/String;)Ldatadog/appsec/api/blocking/BlockingDetails; + public fun tryCommitBlockingResponse (ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z +} + +public class datadog/container/ContainerInfo { + public field cGroups Ljava/util/List; + public field containerId Ljava/lang/String; + public field podId Ljava/lang/String; + public fun ()V + public static fun fromDefaultProcFile ()Ldatadog/container/ContainerInfo; + public static fun get ()Ldatadog/container/ContainerInfo; + public fun getCGroups ()Ljava/util/List; + public fun getContainerId ()Ljava/lang/String; + public fun getPodId ()Ljava/lang/String; + public static fun isRunningInContainer ()Z + public static fun parse (Ljava/lang/String;)Ldatadog/container/ContainerInfo; + public fun setContainerId (Ljava/lang/String;)V + public fun setPodId (Ljava/lang/String;)V + public fun setcGroups (Ljava/util/List;)V +} + +public class datadog/container/ContainerInfo$CGroupInfo { + public field containerId Ljava/lang/String; + public field controllers Ljava/util/List; + public field id I + public field path Ljava/lang/String; + public field podId Ljava/lang/String; + public fun ()V + public fun getContainerId ()Ljava/lang/String; + public fun getControllers ()Ljava/util/List; + public fun getId ()I + public fun getPath ()Ljava/lang/String; + public fun getPodId ()Ljava/lang/String; + public fun setContainerId (Ljava/lang/String;)V + public fun setControllers (Ljava/util/List;)V + public fun setId (I)V + public fun setPath (Ljava/lang/String;)V + public fun setPodId (Ljava/lang/String;)V +} + +public class datadog/container/ServerlessInfo { + public fun ()V + public static fun get ()Ldatadog/container/ServerlessInfo; + public fun getFunctionName ()Ljava/lang/String; + public fun hasExtension ()Z + public fun isRunningInServerlessEnvironment ()Z +} + +public abstract interface annotation class datadog/trace/advice/ActiveRequestContext : java/lang/annotation/Annotation { +} + +public abstract interface annotation class datadog/trace/advice/RequiresRequestContext : java/lang/annotation/Annotation { + public abstract fun value ()Ldatadog/trace/api/gateway/RequestContextSlot; +} + +public class datadog/trace/api/Config { + public static final field PREFIX Ljava/lang/String; + public fun configProvider ()Ldatadog/trace/bootstrap/config/provider/ConfigProvider; + public static fun get ()Ldatadog/trace/api/Config; + public static fun get (Ljava/util/Properties;)Ldatadog/trace/api/Config; + public fun getAgentHost ()Ljava/lang/String; + public fun getAgentNamedPipe ()Ljava/lang/String; + public fun getAgentPort ()I + public fun getAgentTimeout ()I + public fun getAgentUnixDomainSocket ()Ljava/lang/String; + public fun getAgentUrl ()Ljava/lang/String; + public fun getApiKey ()Ljava/lang/String; + public fun getApiSecurityRequestSampleRate ()F + public fun getAppSecActivation ()Ldatadog/trace/api/ProductActivation; + public fun getAppSecHttpBlockedTemplateHtml ()Ljava/lang/String; + public fun getAppSecHttpBlockedTemplateJson ()Ljava/lang/String; + public fun getAppSecObfuscationParameterKeyRegexp ()Ljava/lang/String; + public fun getAppSecObfuscationParameterValueRegexp ()Ljava/lang/String; + public fun getAppSecReportMaxTimeout ()I + public fun getAppSecReportMinTimeout ()I + public fun getAppSecRulesFile ()Ljava/lang/String; + public fun getAppSecTraceRateLimit ()I + public fun getAppSecUserEventsTrackingMode ()Ldatadog/trace/api/UserEventTrackingMode; + public fun getAppSecWafTimeout ()I + public fun getApplicationKey ()Ljava/lang/String; + public fun getBaggageMapping ()Ljava/util/Map; + public fun getCiVisibilityAdditionalChildProcessJvmArgs ()Ljava/lang/String; + public fun getCiVisibilityAgentJarFile ()Ljava/io/File; + public fun getCiVisibilityAgentJarUri ()Ljava/lang/String; + public fun getCiVisibilityAgentlessUrl ()Ljava/lang/String; + public fun getCiVisibilityBackendApiTimeoutMillis ()J + public fun getCiVisibilityCodeCoverageExcludedPackages ()[Ljava/lang/String; + public fun getCiVisibilityCodeCoverageExcludes ()Ljava/util/List; + public fun getCiVisibilityCodeCoverageIncludedPackages ()[Ljava/lang/String; + public fun getCiVisibilityCodeCoverageIncludes ()Ljava/util/List; + public fun getCiVisibilityCodeCoverageReportDumpDir ()Ljava/lang/String; + public fun getCiVisibilityCompilerPluginVersion ()Ljava/lang/String; + public fun getCiVisibilityCoverageRootPackagesLimit ()I + public fun getCiVisibilityDebugPort ()Ljava/lang/Integer; + public fun getCiVisibilityFlakyRetryCount ()I + public fun getCiVisibilityGitCommandTimeoutMillis ()J + public fun getCiVisibilityGitRemoteName ()Ljava/lang/String; + public fun getCiVisibilityGitUploadTimeoutMillis ()J + public fun getCiVisibilityInjectedTracerVersion ()Ljava/lang/String; + public fun getCiVisibilityJacocoGradleSourceSets ()Ljava/util/List; + public fun getCiVisibilityJacocoPluginVersion ()Ljava/lang/String; + public fun getCiVisibilityJvmInfoCacheSize ()I + public fun getCiVisibilityModuleExecutionSettingsCacheSize ()I + public fun getCiVisibilityModuleId ()Ljava/lang/Long; + public fun getCiVisibilityModuleName ()Ljava/lang/String; + public fun getCiVisibilityResourceFolderNames ()Ljava/util/List; + public fun getCiVisibilitySessionId ()Ljava/lang/Long; + public fun getCiVisibilitySignalServerHost ()Ljava/lang/String; + public fun getCiVisibilitySignalServerPort ()I + public fun getClockSyncPeriod ()I + public fun getConfigFileStatus ()Ljava/lang/String; + public fun getCwsTlsRefresh ()I + public fun getDBMPropagationMode ()Ljava/lang/String; + public fun getDataStreamsBucketDurationNanoseconds ()J + public fun getDataStreamsBucketDurationSeconds ()F + public fun getDebuggerCaptureTimeout ()I + public fun getDebuggerDiagnosticsInterval ()I + public fun getDebuggerExcludeFiles ()Ljava/lang/String; + public fun getDebuggerMaxPayloadSize ()J + public fun getDebuggerPollInterval ()I + public fun getDebuggerProbeFileLocation ()Ljava/lang/String; + public fun getDebuggerRedactedIdentifiers ()Ljava/lang/String; + public fun getDebuggerRedactedTypes ()Ljava/lang/String; + public fun getDebuggerSymbolFlushThreshold ()I + public fun getDebuggerSymbolIncludes ()Ljava/lang/String; + public fun getDebuggerUploadBatchSize ()I + public fun getDebuggerUploadFlushInterval ()I + public fun getDebuggerUploadTimeout ()I + public fun getDogStatsDArgs ()Ljava/util/List; + public fun getDogStatsDNamedPipe ()Ljava/lang/String; + public fun getDogStatsDPath ()Ljava/lang/String; + public fun getDogStatsDStartDelay ()I + public fun getEnumValue (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Enum;)Ljava/lang/Enum; + public fun getEnv ()Ljava/lang/String; + public fun getFinalCrashTrackingTelemetryUrl ()Ljava/lang/String; + public fun getFinalDebuggerProbeUrl ()Ljava/lang/String; + public fun getFinalDebuggerSnapshotUrl ()Ljava/lang/String; + public fun getFinalDebuggerSymDBUrl ()Ljava/lang/String; + public fun getFinalProfilingUrl ()Ljava/lang/String; + public fun getFinalRemoteConfigUrl ()Ljava/lang/String; + public fun getGlobalTags ()Ljava/util/Map; + public fun getGrpcClientErrorStatuses ()Ljava/util/BitSet; + public fun getGrpcIgnoredInboundMethods ()Ljava/util/Set; + public fun getGrpcIgnoredOutboundMethods ()Ljava/util/Set; + public fun getGrpcServerErrorStatuses ()Ljava/util/BitSet; + public fun getHealthMetricsStatsdHost ()Ljava/lang/String; + public fun getHealthMetricsStatsdPort ()Ljava/lang/Integer; + public fun getHostName ()Ljava/lang/String; + public fun getHttpClientErrorStatuses ()Ljava/util/BitSet; + public fun getHttpClientPathResourceNameMapping ()Ljava/util/Map; + public fun getHttpResourceRemoveTrailingSlash ()Z + public fun getHttpServerErrorStatuses ()Ljava/util/BitSet; + public fun getHttpServerPathResourceNameMapping ()Ljava/util/Map; + public fun getIastActivation ()Ldatadog/trace/api/ProductActivation; + public fun getIastMaxConcurrentRequests ()I + public fun getIastMaxRangeCount ()I + public fun getIastRedactionNamePattern ()Ljava/lang/String; + public fun getIastRedactionValuePattern ()Ljava/lang/String; + public fun getIastRequestSampling ()F + public fun getIastTelemetryVerbosity ()Ldatadog/trace/api/iast/telemetry/Verbosity; + public fun getIastTruncationMaxValueLength ()I + public fun getIastVulnerabilitiesPerRequest ()I + public fun getIastWeakCipherAlgorithms ()Ljava/util/regex/Pattern; + public fun getIastWeakHashAlgorithms ()Ljava/util/Set; + public fun getIdGenerationStrategy ()Ldatadog/trace/api/IdGenerationStrategy; + public fun getInstrumentationAnalyticsSampleRate ([Ljava/lang/String;)F + public fun getJmsUnacknowledgedMaxAge ()I + public fun getJmxFetchCheckPeriod ()Ljava/lang/Integer; + public fun getJmxFetchConfigDir ()Ljava/lang/String; + public fun getJmxFetchConfigs ()Ljava/util/List; + public fun getJmxFetchInitialRefreshBeansPeriod ()Ljava/lang/Integer; + public fun getJmxFetchMetricsConfigs ()Ljava/util/List; + public fun getJmxFetchMultipleRuntimeServicesLimit ()I + public fun getJmxFetchRefreshBeansPeriod ()Ljava/lang/Integer; + public fun getJmxFetchStatsdHost ()Ljava/lang/String; + public fun getJmxFetchStatsdPort ()Ljava/lang/Integer; + public fun getLocalRootSpanTags ()Ljava/util/Map; + public fun getLongRunningTraceFlushInterval ()J + public fun getMergedCrashTrackingTags ()Ljava/util/Map; + public fun getMergedJmxTags ()Ljava/util/Map; + public fun getMergedProfilingTags ()Ljava/util/Map; + public fun getMergedSpanTags ()Ljava/util/Map; + public fun getMetricsIgnoredResources ()Ljava/util/Set; + public fun getNoProxyHosts ()Ljava/util/Set; + public fun getObfuscationQueryRegexp ()Ljava/lang/String; + public fun getPartialFlushMinSpans ()I + public fun getPeerServiceComponentOverrides ()Ljava/util/Map; + public fun getPeerServiceMapping ()Ljava/util/Map; + public fun getPlayReportHttpStatus ()Z + public fun getPrimaryTag ()Ljava/lang/String; + public fun getPrioritySamplingForce ()Ljava/lang/String; + public fun getProcessId ()Ljava/lang/Long; + public fun getProfilingDirectAllocationSampleLimit ()I + public fun getProfilingExceptionHistogramMaxCollectionSize ()I + public fun getProfilingExceptionHistogramTopItems ()I + public fun getProfilingExceptionSampleLimit ()I + public fun getProfilingProxyHost ()Ljava/lang/String; + public fun getProfilingProxyPassword ()Ljava/lang/String; + public fun getProfilingProxyPort ()I + public fun getProfilingProxyUsername ()Ljava/lang/String; + public fun getProfilingStartDelay ()I + public fun getProfilingTemplateOverrideFile ()Ljava/lang/String; + public fun getProfilingUploadCompression ()Ljava/lang/String; + public fun getProfilingUploadPeriod ()I + public fun getProfilingUploadTimeout ()I + public fun getPropagationStylesToExtract ()Ljava/util/Set; + public fun getPropagationStylesToInject ()Ljava/util/Set; + public fun getRemoteConfigMaxPayloadSizeBytes ()J + public fun getRemoteConfigPollIntervalSeconds ()F + public fun getRemoteConfigTargetsKey ()Ljava/lang/String; + public fun getRemoteConfigTargetsKeyId ()Ljava/lang/String; + public fun getRequestHeaderTags ()Ljava/util/Map; + public fun getResponseHeaderTags ()Ljava/util/Map; + public fun getRootContextServiceName ()Ljava/lang/String; + public fun getRuntimeId ()Ljava/lang/String; + public fun getRuntimeVersion ()Ljava/lang/String; + public fun getScopeDepthLimit ()I + public fun getScopeIterationKeepAlive ()I + public fun getServiceMapping ()Ljava/util/Map; + public fun getServiceName ()Ljava/lang/String; + public fun getSite ()Ljava/lang/String; + public fun getSpanAttributeSchemaVersion ()I + public fun getSpanSamplingRules ()Ljava/lang/String; + public fun getSpanSamplingRulesFile ()Ljava/lang/String; + public fun getSplitByTags ()Ljava/util/Set; + public fun getStartTimeMillis ()J + public fun getStatsDClientQueueSize ()Ljava/lang/Integer; + public fun getStatsDClientSocketBuffer ()Ljava/lang/Integer; + public fun getStatsDClientSocketTimeout ()Ljava/lang/Integer; + public fun getTelemetryExtendedHeartbeatInterval ()J + public fun getTelemetryHeartbeatInterval ()F + public fun getTelemetryMetricsInterval ()F + public fun getTraceAgentArgs ()Ljava/util/List; + public fun getTraceAgentPath ()Ljava/lang/String; + public fun getTraceClientIpHeader ()Ljava/lang/String; + public fun getTraceFlushIntervalSeconds ()F + public fun getTracePropagationStylesToExtract ()Ljava/util/Set; + public fun getTracePropagationStylesToInject ()Ljava/util/Set; + public fun getTraceRateLimit ()I + public fun getTraceSampleRate ()Ljava/lang/Double; + public fun getTraceSamplingOperationRules ()Ljava/util/Map; + public fun getTraceSamplingRules ()Ljava/lang/String; + public fun getTraceSamplingServiceRules ()Ljava/util/Map; + public fun getTracerMetricsMaxAggregates ()I + public fun getTracerMetricsMaxPending ()I + public fun getVersion ()Ljava/lang/String; + public fun getWellKnownTags ()Ldatadog/trace/api/WellKnownTags; + public fun getWriterType ()Ljava/lang/String; + public fun getxDatadogTagsMaxLength ()I + public fun isAgentConfiguredUsingDefault ()Z + public fun isApiSecurityEnabled ()Z + public fun isAppSecReportingInband ()Z + public fun isAppSecWafMetrics ()Z + public fun isAwsPropagationEnabled ()Z + public fun isAzureAppServices ()Z + public fun isCiVisibilityAgentlessEnabled ()Z + public fun isCiVisibilityAutoConfigurationEnabled ()Z + public fun isCiVisibilityBuildInstrumentationEnabled ()Z + public fun isCiVisibilityCiProviderIntegrationEnabled ()Z + public fun isCiVisibilityCodeCoverageEnabled ()Z + public fun isCiVisibilityCodeCoveragePercentageCalculationEnabled ()Z + public fun isCiVisibilityCompilerPluginAutoConfigurationEnabled ()Z + public fun isCiVisibilityCoverageSegmentsEnabled ()Z + public fun isCiVisibilityEnabled ()Z + public fun isCiVisibilityFlakyRetryEnabled ()Z + public fun isCiVisibilityGitUnshallowDefer ()Z + public fun isCiVisibilityGitUnshallowEnabled ()Z + public fun isCiVisibilityGitUploadEnabled ()Z + public fun isCiVisibilityItrEnabled ()Z + public fun isCiVisibilityJacocoPluginVersionProvided ()Z + public fun isCiVisibilityRepoIndexSharingEnabled ()Z + public fun isCiVisibilitySourceDataEnabled ()Z + public fun isCiVisibilitySourceDataRootCheckEnabled ()Z + public fun isCiVisibilityTraceSanitationEnabled ()Z + public fun isClientIpEnabled ()Z + public fun isCrashTrackingAgentless ()Z + public fun isCwsEnabled ()Z + public fun isDataStreamsEnabled ()Z + public fun isDatadogProfilerEnabled ()Z + public static fun isDatadogProfilerEnablementOverridden ()Z + public static fun isDatadogProfilerSafeInCurrentEnvironment ()Z + public fun isDbClientSplitByHost ()Z + public fun isDbClientSplitByInstance ()Z + public fun isDbClientSplitByInstanceTypeSuffix ()Z + public fun isDebugEnabled ()Z + public fun isDebuggerClassFileDumpEnabled ()Z + public fun isDebuggerEnabled ()Z + public fun isDebuggerInstrumentTheWorld ()Z + public fun isDebuggerMetricsEnabled ()Z + public fun isDebuggerSymbolEnabled ()Z + public fun isDebuggerSymbolForceUpload ()Z + public fun isDebuggerVerifyByteCode ()Z + public fun isElasticsearchBodyAndParamsEnabled ()Z + public fun isElasticsearchBodyEnabled ()Z + public fun isElasticsearchParamsEnabled ()Z + public fun isEnabled (ZLjava/lang/String;Ljava/lang/String;)Z + public fun isEndToEndDurationEnabled (Z[Ljava/lang/String;)Z + public fun isGrpcServerTrimPackageResource ()Z + public fun isHealthMetricsEnabled ()Z + public fun isHttpClientSplitByDomain ()Z + public fun isHttpClientTagHeaders ()Z + public fun isHttpClientTagQueryString ()Z + public fun isHttpServerDecodedResourcePreserveSpaces ()Z + public fun isHttpServerRawQueryString ()Z + public fun isHttpServerRawResource ()Z + public fun isHttpServerRouteBasedNaming ()Z + public fun isHttpServerTagQueryString ()Z + public fun isHystrixMeasuredEnabled ()Z + public fun isHystrixTagsEnabled ()Z + public fun isIastDebugEnabled ()Z + public fun isIastDeduplicationEnabled ()Z + public fun isIastRedactionEnabled ()Z + public fun isIastStacktraceLeakSuppress ()Z + public fun isIgniteCacheIncludeKeys ()Z + public fun isInjectBaggageAsTagsEnabled ()Z + public fun isIntegrationSynapseLegacyOperationName ()Z + public fun isJaxRsExceptionAsErrorEnabled ()Z + public fun isJmsPropagationDisabledForDestination (Ljava/lang/String;)Z + public fun isJmsPropagationEnabled ()Z + public fun isJmxFetchEnabled ()Z + public fun isJmxFetchIntegrationEnabled (Ljava/lang/Iterable;Z)Z + public fun isJmxFetchMultipleRuntimeServicesEnabled ()Z + public fun isKafkaClientBase64DecodingEnabled ()Z + public fun isKafkaClientPropagationDisabledForTopic (Ljava/lang/String;)Z + public fun isKafkaClientPropagationEnabled ()Z + public fun isLegacyTracingEnabled (Z[Ljava/lang/String;)Z + public fun isLogExtractHeaderNames ()Z + public fun isLogsInjectionEnabled ()Z + public fun isLongRunningTraceEnabled ()Z + public fun isMessageBrokerSplitByDestination ()Z + public fun isPeerServiceDefaultsEnabled ()Z + public fun isPerfMetricsEnabled ()Z + public fun isPrioritySamplingEnabled ()Z + public fun isProfilingAgentless ()Z + public fun isProfilingEnabled ()Z + public fun isProfilingExcludeAgentThreads ()Z + public fun isProfilingRecordExceptionMessage ()Z + public fun isProfilingStartForceFirst ()Z + public fun isProfilingTimelineEventsEnabled ()Z + public fun isProfilingUploadSummaryOn413Enabled ()Z + public fun isPropagationEnabled (Z[Ljava/lang/String;)Z + public fun isRabbitIncludeRoutingKeyInResource ()Z + public fun isRabbitPropagationDisabledForDestination (Ljava/lang/String;)Z + public fun isRabbitPropagationEnabled ()Z + public fun isRemoteConfigEnabled ()Z + public fun isRemoteConfigIntegrityCheckEnabled ()Z + public fun isRemoveIntegrationServiceNamesEnabled ()Z + public fun isReportHostName ()Z + public fun isRequestHeaderTagsCommaAllowed ()Z + public fun isRuleEnabled (Ljava/lang/String;)Z + public fun isRuleEnabled (Ljava/lang/String;Z)Z + public fun isRuntimeMetricsEnabled ()Z + public fun isSamplingMechanismValidationDisabled ()Z + public fun isScopeInheritAsyncPropagation ()Z + public fun isScopeStrictMode ()Z + public fun isServiceNameSetByUser ()Z + public fun isServletAsyncTimeoutError ()Z + public fun isServletPrincipalEnabled ()Z + public fun isSparkTaskHistogramEnabled ()Z + public fun isSpringDataRepositoryInterfaceResourceName ()Z + public fun isSqsPropagationEnabled ()Z + public fun isStartupLogsEnabled ()Z + public fun isTelemetryDebugRequestsEnabled ()Z + public fun isTelemetryDependencyServiceEnabled ()Z + public fun isTelemetryEnabled ()Z + public fun isTelemetryLogCollectionEnabled ()Z + public fun isTelemetryMetricsEnabled ()Z + public fun isTimeInQueueEnabled (Z[Ljava/lang/String;)Z + public fun isTrace128bitTraceIdGenerationEnabled ()Z + public fun isTraceAgentV05Enabled ()Z + public fun isTraceAnalyticsEnabled ()Z + public fun isTraceAnalyticsIntegrationEnabled (Ljava/util/SortedSet;Z)Z + public fun isTraceAnalyticsIntegrationEnabled (Z[Ljava/lang/String;)Z + public fun isTraceClientIpResolverEnabled ()Z + public fun isTraceEnabled ()Z + public fun isTraceGitMetadataEnabled ()Z + public fun isTracePropagationExtractFirst ()Z + public fun isTracePropagationStyleB3PaddingEnabled ()Z + public fun isTraceResolverEnabled ()Z + public fun isTraceStrictWritesEnabled ()Z + public fun isTracerMetricsBufferingEnabled ()Z + public fun isTracerMetricsEnabled ()Z + public fun isTriageEnabled ()Z + public fun isUsmEnabled ()Z + public static fun jmxFetchIntegrationEnabled (Ljava/util/SortedSet;Z)Z + public fun toString ()Ljava/lang/String; + public static fun traceAnalyticsIntegrationEnabled (Ljava/util/SortedSet;Z)Z +} + +public class datadog/trace/api/ConfigCollector { + public fun ()V + public fun collect ()Ljava/util/Map; + public static fun get ()Ldatadog/trace/api/ConfigCollector; + public fun put (Ljava/lang/String;Ljava/lang/Object;Ldatadog/trace/api/ConfigOrigin;)V + public fun putAll (Ljava/util/Map;Ldatadog/trace/api/ConfigOrigin;)V +} + +public final class datadog/trace/api/ConfigDefaults { + public static final field DEFAULT_AGENT_HOST Ljava/lang/String; + public static final field DEFAULT_AGENT_TIMEOUT I + public static final field DEFAULT_AGENT_WRITER_TYPE Ljava/lang/String; + public static final field DEFAULT_ASYNC_PROPAGATING Z + public static final field DEFAULT_DOGSTATSD_PORT I + public static final field DEFAULT_DOGSTATSD_SOCKET_PATH Ljava/lang/String; + public static final field DEFAULT_IAST_DEDUPLICATION_ENABLED Z + public static final field DEFAULT_IAST_MAX_CONCURRENT_REQUESTS I + public static final field DEFAULT_IAST_MAX_RANGE_COUNT I + public static final field DEFAULT_IAST_REQUEST_SAMPLING I + public static final field DEFAULT_IAST_VULNERABILITIES_PER_REQUEST I + public static final field DEFAULT_SERVICE_NAME Ljava/lang/String; + public static final field DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME Ljava/lang/String; + public static final field DEFAULT_STARTUP_LOGS_ENABLED Z + public static final field DEFAULT_TRACE_AGENT_PORT I + public static final field DEFAULT_TRACE_AGENT_SOCKET_PATH Ljava/lang/String; + public static final field DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH I +} + +public final class datadog/trace/api/ConfigOrigin : java/lang/Enum { + public static final field DEFAULT Ldatadog/trace/api/ConfigOrigin; + public static final field ENV Ldatadog/trace/api/ConfigOrigin; + public static final field JVM_PROP Ldatadog/trace/api/ConfigOrigin; + public static final field REMOTE Ldatadog/trace/api/ConfigOrigin; + public final field value Ljava/lang/String; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/ConfigOrigin; + public static fun values ()[Ldatadog/trace/api/ConfigOrigin; +} + +public final class datadog/trace/api/ConfigSetting { + public final field key Ljava/lang/String; + public final field origin Ldatadog/trace/api/ConfigOrigin; + public final field value Ljava/lang/Object; + public fun (Ljava/lang/String;Ljava/lang/Object;Ldatadog/trace/api/ConfigOrigin;)V + public fun equals (Ljava/lang/Object;)Z + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public class datadog/trace/api/CorrelationIdentifier { + public fun ()V + public static fun getSpanId ()Ljava/lang/String; + public static fun getSpanIdKey ()Ljava/lang/String; + public static fun getTraceId ()Ljava/lang/String; + public static fun getTraceIdKey ()Ljava/lang/String; +} + +public class datadog/trace/api/DD128bTraceId : datadog/trace/api/DDTraceId { + public static final field ZERO Ldatadog/trace/api/DD128bTraceId; + public fun equals (Ljava/lang/Object;)Z + public static fun from (JJ)Ldatadog/trace/api/DD128bTraceId; + public static fun fromHex (Ljava/lang/String;)Ldatadog/trace/api/DD128bTraceId; + public static fun fromHex (Ljava/lang/String;IIZ)Ldatadog/trace/api/DD128bTraceId; + public fun hashCode ()I + public fun toHexString ()Ljava/lang/String; + public fun toHexStringPadded (I)Ljava/lang/String; + public fun toHighOrderLong ()J + public fun toLong ()J + public fun toString ()Ljava/lang/String; +} + +public class datadog/trace/api/DD64bTraceId : datadog/trace/api/DDTraceId { + public static final field MAX Ldatadog/trace/api/DD64bTraceId; + public fun equals (Ljava/lang/Object;)Z + public static fun from (J)Ldatadog/trace/api/DD64bTraceId; + public static fun from (Ljava/lang/String;)Ldatadog/trace/api/DD64bTraceId; + public static fun fromHex (Ljava/lang/String;)Ldatadog/trace/api/DD64bTraceId; + public fun hashCode ()I + public fun toHexString ()Ljava/lang/String; + public fun toHexStringPadded (I)Ljava/lang/String; + public fun toHighOrderLong ()J + public fun toLong ()J + public fun toString ()Ljava/lang/String; +} + +public final class datadog/trace/api/DDSpanId { + public static final field MAX J + public static final field ZERO J + public static fun from (Ljava/lang/String;)J + public static fun fromHex (Ljava/lang/String;)J + public static fun fromHex (Ljava/lang/String;IIZ)J + public static fun toHexString (J)Ljava/lang/String; + public static fun toHexStringPadded (J)Ljava/lang/String; + public static fun toString (J)Ljava/lang/String; +} + +public class datadog/trace/api/DDSpanTypes { + public static final field AEROSPIKE Ljava/lang/String; + public static final field CACHE Ljava/lang/String; + public static final field CASSANDRA Ljava/lang/String; + public static final field COUCHBASE Ljava/lang/String; + public static final field DATANUCLEUS Ljava/lang/String; + public static final field ELASTICSEARCH Ljava/lang/String; + public static final field GRAPHQL Ljava/lang/String; + public static final field HIBERNATE Ljava/lang/String; + public static final field HTTP_CLIENT Ljava/lang/String; + public static final field HTTP_SERVER Ljava/lang/String; + public static final field MEMCACHED Ljava/lang/String; + public static final field MESSAGE_BROKER Ljava/lang/String; + public static final field MESSAGE_CLIENT Ljava/lang/String; + public static final field MESSAGE_CONSUMER Ljava/lang/String; + public static final field MESSAGE_PRODUCER Ljava/lang/String; + public static final field MONGO Ljava/lang/String; + public static final field OPENSEARCH Ljava/lang/String; + public static final field REDIS Ljava/lang/String; + public static final field RPC Ljava/lang/String; + public static final field SOAP Ljava/lang/String; + public static final field SQL Ljava/lang/String; + public static final field TEST Ljava/lang/String; + public static final field TEST_MODULE_END Ljava/lang/String; + public static final field TEST_SESSION_END Ljava/lang/String; + public static final field TEST_SUITE_END Ljava/lang/String; + public static final field VULNERABILITY Ljava/lang/String; + public static final field WEB_SERVLET Ljava/lang/String; + public fun ()V +} + +public class datadog/trace/api/DDTags { + public static final field ANALYTICS_SAMPLE_RATE Ljava/lang/String; + public static final field BASE_SERVICE Ljava/lang/String; + public static final field CI_ENV_VARS Ljava/lang/String; + public static final field CI_ITR_TESTS_SKIPPED Ljava/lang/String; + public static final field DB_STATEMENT Ljava/lang/String; + public static final field ERROR_MSG Ljava/lang/String; + public static final field ERROR_STACK Ljava/lang/String; + public static final field ERROR_TYPE Ljava/lang/String; + public static final field EVENT_SAMPLE_RATE Ljava/lang/String; + public static final field HTTP_FRAGMENT Ljava/lang/String; + public static final field HTTP_QUERY Ljava/lang/String; + public static final field INTERNAL_GIT_COMMIT_SHA Ljava/lang/String; + public static final field INTERNAL_GIT_REPOSITORY_URL Ljava/lang/String; + public static final field LANGUAGE_TAG_KEY Ljava/lang/String; + public static final field LANGUAGE_TAG_VALUE Ljava/lang/String; + public static final field LIBRARY_VERSION_TAG_KEY Ljava/lang/String; + public static final field MANUAL_DROP Ljava/lang/String; + public static final field MANUAL_KEEP Ljava/lang/String; + public static final field MEASURED Ljava/lang/String; + public static final field ORIGIN_KEY Ljava/lang/String; + public static final field PATHWAY_HASH Ljava/lang/String; + public static final field PEER_SERVICE_REMAPPED_FROM Ljava/lang/String; + public static final field PEER_SERVICE_SOURCE Ljava/lang/String; + public static final field PID_TAG Ljava/lang/String; + public static final field PROFILING_CONTEXT_ENGINE Ljava/lang/String; + public static final field PROFILING_ENABLED Ljava/lang/String; + public static final field RESOURCE_NAME Ljava/lang/String; + public static final field RUNTIME_ID_TAG Ljava/lang/String; + public static final field RUNTIME_VERSION_TAG Ljava/lang/String; + public static final field SCHEMA_DEFINITION Ljava/lang/String; + public static final field SCHEMA_ID Ljava/lang/String; + public static final field SCHEMA_OPERATION Ljava/lang/String; + public static final field SCHEMA_TOPIC Ljava/lang/String; + public static final field SCHEMA_TYPE Ljava/lang/String; + public static final field SCHEMA_VERSION_TAG_KEY Ljava/lang/String; + public static final field SCHEMA_WEIGHT Ljava/lang/String; + public static final field SERVICE_NAME Ljava/lang/String; + public static final field SPAN_LINKS Ljava/lang/String; + public static final field SPAN_TYPE Ljava/lang/String; + public static final field THREAD_ID Ljava/lang/String; + public static final field THREAD_NAME Ljava/lang/String; + public static final field TRACE_START_TIME Ljava/lang/String; + public static final field USER_NAME Ljava/lang/String; + public fun ()V +} + +public class datadog/trace/api/DDTraceApiInfo { + public static final field VERSION Ljava/lang/String; + public fun ()V +} + +public abstract class datadog/trace/api/DDTraceId { + public static final field ONE Ldatadog/trace/api/DDTraceId; + public static final field ZERO Ldatadog/trace/api/DDTraceId; + public fun ()V + public static fun from (J)Ldatadog/trace/api/DDTraceId; + public static fun from (Ljava/lang/String;)Ldatadog/trace/api/DDTraceId; + public static fun fromHex (Ljava/lang/String;)Ldatadog/trace/api/DDTraceId; + public abstract fun toHexString ()Ljava/lang/String; + public abstract fun toHexStringPadded (I)Ljava/lang/String; + public abstract fun toHighOrderLong ()J + public abstract fun toLong ()J + public abstract fun toString ()Ljava/lang/String; +} + +public abstract interface annotation class datadog/trace/api/DisableTestTrace : java/lang/annotation/Annotation { + public abstract fun reason ()Ljava/lang/String; +} + +public final class datadog/trace/api/DynamicConfig { + public fun captureTraceConfig ()Ldatadog/trace/api/DynamicConfig$Snapshot; + public static fun create ()Ldatadog/trace/api/DynamicConfig$Builder; + public static fun create (Ljava/util/function/BiFunction;)Ldatadog/trace/api/DynamicConfig$Builder; + public fun current ()Ldatadog/trace/api/DynamicConfig$Builder; + public fun initial ()Ldatadog/trace/api/DynamicConfig$Builder; + public fun resetTraceConfig ()V + public fun toString ()Ljava/lang/String; +} + +public final class datadog/trace/api/DynamicConfig$Builder { + public fun apply ()Ldatadog/trace/api/DynamicConfig; + public fun setBaggageMapping (Ljava/util/Collection;)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setBaggageMapping (Ljava/util/Map;)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setDataStreamsEnabled (Z)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setHeaderTags (Ljava/util/Collection;)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setHeaderTags (Ljava/util/Map;)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setLogsInjectionEnabled (Z)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setRuntimeMetricsEnabled (Z)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setServiceMapping (Ljava/util/Collection;)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setServiceMapping (Ljava/util/Map;)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setSpanSamplingRules (Ljava/util/List;)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setTraceSampleRate (Ljava/lang/Double;)Ldatadog/trace/api/DynamicConfig$Builder; + public fun setTraceSamplingRules (Ljava/util/List;)Ldatadog/trace/api/DynamicConfig$Builder; +} + +public class datadog/trace/api/DynamicConfig$Snapshot : datadog/trace/api/TraceConfig { + protected fun (Ldatadog/trace/api/DynamicConfig$Builder;Ldatadog/trace/api/DynamicConfig$Snapshot;)V + public fun getBaggageMapping ()Ljava/util/Map; + public fun getRequestHeaderTags ()Ljava/util/Map; + public fun getResponseHeaderTags ()Ljava/util/Map; + public fun getServiceMapping ()Ljava/util/Map; + public fun getSpanSamplingRules ()Ljava/util/List; + public fun getTraceSampleRate ()Ljava/lang/Double; + public fun getTraceSamplingRules ()Ljava/util/List; + public fun isDataStreamsEnabled ()Z + public fun isLogsInjectionEnabled ()Z + public fun isRuntimeMetricsEnabled ()Z + public fun toString ()Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/EndpointCheckpointer { + public abstract fun onRootSpanFinished (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/api/EndpointTracker;)V + public abstract fun onRootSpanStarted (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/api/EndpointTracker; +} + +public final class datadog/trace/api/EndpointCheckpointerHolder : datadog/trace/api/EndpointCheckpointer { + public fun (Ldatadog/trace/api/EndpointCheckpointer;)V + public static fun create ()Ldatadog/trace/api/EndpointCheckpointerHolder; + public fun onRootSpanFinished (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/api/EndpointTracker;)V + public fun onRootSpanStarted (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/api/EndpointTracker; + public fun register (Ldatadog/trace/api/EndpointCheckpointer;)V +} + +public abstract interface class datadog/trace/api/EndpointTracker { + public static final field NO_OP Ldatadog/trace/api/EndpointTracker; + public abstract fun endpointWritten (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)V +} + +public class datadog/trace/api/EventTracker { + public static final field NO_EVENT_TRACKER Ldatadog/trace/api/EventTracker; + public fun trackCustomEvent (Ljava/lang/String;Ljava/util/Map;)V + public fun trackLoginFailureEvent (Ljava/lang/String;ZLjava/util/Map;)V + public fun trackLoginSuccessEvent (Ljava/lang/String;Ljava/util/Map;)V +} + +public final class datadog/trace/api/Functions { + public static final field UTF8_ENCODE Ljava/util/function/Function; +} + +public abstract class datadog/trace/api/Functions$Concatenate { + public fun ()V + public fun concatenate (Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; +} + +public abstract class datadog/trace/api/Functions$Join : java/util/function/BiFunction { + protected final field joiner Ljava/lang/CharSequence; + protected final field transformer Ljava/util/function/Function; + protected fun (Ljava/lang/CharSequence;Ljava/util/function/Function;)V + public fun apply (Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + public synthetic fun apply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun curry (Ljava/lang/CharSequence;)Ljava/util/function/Function; +} + +public final class datadog/trace/api/Functions$LowerCase : java/util/function/Function { + public static final field INSTANCE Ldatadog/trace/api/Functions$LowerCase; + public fun ()V + public synthetic fun apply (Ljava/lang/Object;)Ljava/lang/Object; + public fun apply (Ljava/lang/String;)Ljava/lang/String; +} + +public final class datadog/trace/api/Functions$Prefix : datadog/trace/api/Functions$Concatenate, java/util/function/Function { + public fun (Ljava/lang/CharSequence;)V + public fun (Ljava/lang/CharSequence;Ljava/util/function/Function;)V + public fun apply (Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + public synthetic fun apply (Ljava/lang/Object;)Ljava/lang/Object; +} + +public class datadog/trace/api/Functions$PrefixJoin : datadog/trace/api/Functions$Join { + public static final field ZERO Ldatadog/trace/api/Functions$PrefixJoin; + public fun (Ljava/lang/CharSequence;Ljava/util/function/Function;)V + public fun curry (Ljava/lang/CharSequence;)Ljava/util/function/Function; + public static fun of (Ljava/lang/CharSequence;Ljava/util/function/Function;)Ldatadog/trace/api/Functions$PrefixJoin; + public static fun of (Ljava/lang/String;)Ldatadog/trace/api/Functions$PrefixJoin; +} + +public final class datadog/trace/api/Functions$Suffix : datadog/trace/api/Functions$Concatenate, java/util/function/Function { + public fun (Ljava/lang/CharSequence;Ljava/util/function/Function;)V + public fun (Ljava/lang/String;)V + public fun apply (Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + public synthetic fun apply (Ljava/lang/Object;)Ljava/lang/Object; +} + +public class datadog/trace/api/Functions$SuffixJoin : datadog/trace/api/Functions$Join { + public static final field ZERO Ldatadog/trace/api/Functions$SuffixJoin; + public fun (Ljava/lang/CharSequence;Ljava/util/function/Function;)V + public fun curry (Ljava/lang/CharSequence;)Ljava/util/function/Function; + public static fun of (Ljava/lang/CharSequence;)Ldatadog/trace/api/Functions$SuffixJoin; + public static fun of (Ljava/lang/CharSequence;Ljava/util/function/Function;)Ldatadog/trace/api/Functions$SuffixJoin; +} + +public final class datadog/trace/api/Functions$ToString : java/util/function/Function { + public fun ()V + public synthetic fun apply (Ljava/lang/Object;)Ljava/lang/Object; + public fun apply (Ljava/lang/Object;)Ljava/lang/String; +} + +public class datadog/trace/api/GlobalTracer { + public fun ()V + public static fun forceRegister (Ldatadog/trace/api/Tracer;)V + public static fun get ()Ldatadog/trace/api/Tracer; + public static fun getEventTracker ()Ldatadog/trace/api/EventTracker; + public static fun registerIfAbsent (Ldatadog/trace/api/Tracer;)V +} + +public abstract class datadog/trace/api/IdGenerationStrategy { + protected final field traceId128BitGenerationEnabled Z + public static fun fromName (Ljava/lang/String;)Ldatadog/trace/api/IdGenerationStrategy; + public static fun fromName (Ljava/lang/String;Z)Ldatadog/trace/api/IdGenerationStrategy; + protected fun generateHighOrderBits ()J + public fun generateSpanId ()J + public fun generateTraceId ()Ldatadog/trace/api/DDTraceId; + protected abstract fun getNonZeroPositiveLong ()J +} + +public class datadog/trace/api/InstrumenterConfig { + public static fun get ()Ldatadog/trace/api/InstrumenterConfig; + public fun getAppSecActivation ()Ldatadog/trace/api/ProductActivation; + public fun getExcludedClassLoaders ()Ljava/util/Set; + public fun getExcludedClasses ()Ljava/util/List; + public fun getExcludedClassesFile ()Ljava/lang/String; + public fun getExcludedCodeSources ()Ljava/util/List; + public fun getHttpURLConnectionClassName ()Ljava/lang/String; + public fun getIastActivation ()Ldatadog/trace/api/ProductActivation; + public fun getJdbcConnectionClassName ()Ljava/lang/String; + public fun getJdbcPreparedStatementClassName ()Ljava/lang/String; + public fun getResolverCacheDir ()Ljava/lang/String; + public fun getResolverMemoPoolSize ()I + public fun getResolverNoMatchesSize ()I + public fun getResolverOutlinePoolSize ()I + public fun getResolverResetInterval ()I + public fun getResolverTypePoolSize ()I + public fun getTraceAnnotations ()Ljava/lang/String; + public fun getTraceExecutors ()Ljava/util/List; + public fun getTraceMethods ()Ljava/util/Map; + public fun getTraceThreadPoolExecutorsExclude ()Ljava/util/Set; + public fun isCiVisibilityEnabled ()Z + public fun isDirectAllocationProfilingEnabled ()Z + public fun isIntegrationEnabled (Ljava/lang/Iterable;Z)Z + public fun isIntegrationShortcutMatchingEnabled (Ljava/lang/Iterable;Z)Z + public fun isIntegrationsEnabled ()Z + public fun isInternalExitOnFailure ()Z + public fun isLegacyInstallerEnabled ()Z + public fun isLegacyInstrumentationEnabled (Z[Ljava/lang/String;)Z + public fun isLogs128bTraceIdEnabled ()Z + public fun isMethodMeasured (Ljava/lang/reflect/Method;)Z + public fun isProfilingEnabled ()Z + public fun isResolverMemoizingEnabled ()Z + public fun isResolverNamesAreUnique ()Z + public fun isResolverOutliningEnabled ()Z + public fun isResolverUseLoadClass ()Z + public fun isResolverUseUrlCaches ()Ljava/lang/Boolean; + public fun isRuntimeContextFieldInjection ()Z + public fun isSerialVersionUIDFieldInjection ()Z + public fun isTelemetryEnabled ()Z + public fun isTraceAnnotationAsync ()Z + public fun isTraceEnabled ()Z + public fun isTraceExecutorsAll ()Z + public fun isTraceOtelEnabled ()Z + public fun isUsmEnabled ()Z + public fun toString ()Ljava/lang/String; +} + +public final class datadog/trace/api/MethodFilterConfigParser { + public fun ()V + public static fun parse (Ljava/lang/String;)Ljava/util/Map; +} + +public final class datadog/trace/api/Pair { + public fun equals (Ljava/lang/Object;)Z + public fun getLeft ()Ljava/lang/Object; + public fun getRight ()Ljava/lang/Object; + public fun hasLeft ()Z + public fun hasRight ()Z + public fun hashCode ()I + public static fun of (Ljava/lang/Object;Ljava/lang/Object;)Ldatadog/trace/api/Pair; +} + +public final class datadog/trace/api/Platform { + public fun ()V + public static fun getLangVersion ()Ljava/lang/String; + public static fun getRuntimePatches ()Ljava/lang/String; + public static fun getRuntimeVendor ()Ljava/lang/String; + public static fun getRuntimeVersion ()Ljava/lang/String; + public static fun hasJfr ()Z + public static fun isGraalVM ()Z + public static fun isIbm8 ()Z + public static fun isJ9 ()Z + public static fun isJavaVersion (I)Z + public static fun isJavaVersion (II)Z + public static fun isJavaVersion (III)Z + public static fun isJavaVersionAtLeast (I)Z + public static fun isJavaVersionAtLeast (II)Z + public static fun isJavaVersionAtLeast (III)Z + public static fun isJavaVersionBetween (II)Z + public static fun isJavaVersionBetween (IIII)Z + public static fun isJavaVersionBetween (IIIIII)Z + public static fun isLinux ()Z + public static fun isMac ()Z + public static fun isNativeImage ()Z + public static fun isNativeImageBuilder ()Z + public static fun isOracleJDK8 ()Z + public static fun isWindows ()Z +} + +public final class datadog/trace/api/Platform$GC : java/lang/Enum { + public static final field CMS Ldatadog/trace/api/Platform$GC; + public static final field G1 Ldatadog/trace/api/Platform$GC; + public static final field PARALLEL Ldatadog/trace/api/Platform$GC; + public static final field SERIAL Ldatadog/trace/api/Platform$GC; + public static final field SHENANDOAH Ldatadog/trace/api/Platform$GC; + public static final field UNKNOWN Ldatadog/trace/api/Platform$GC; + public static final field Z Ldatadog/trace/api/Platform$GC; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/Platform$GC; + public static fun values ()[Ldatadog/trace/api/Platform$GC; +} + +public final class datadog/trace/api/ProductActivation : java/lang/Enum { + public static final field ENABLED_INACTIVE Ldatadog/trace/api/ProductActivation; + public static final field FULLY_DISABLED Ldatadog/trace/api/ProductActivation; + public static final field FULLY_ENABLED Ldatadog/trace/api/ProductActivation; + public static fun fromString (Ljava/lang/String;)Ldatadog/trace/api/ProductActivation; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/ProductActivation; + public static fun values ()[Ldatadog/trace/api/ProductActivation; +} + +public final class datadog/trace/api/PropagationStyle : java/lang/Enum { + public static final field B3 Ldatadog/trace/api/PropagationStyle; + public static final field DATADOG Ldatadog/trace/api/PropagationStyle; + public static final field HAYSTACK Ldatadog/trace/api/PropagationStyle; + public static final field XRAY Ldatadog/trace/api/PropagationStyle; + public fun getNewStyles ()Ljava/util/List; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/PropagationStyle; + public static fun valueOfConfigName (Ljava/lang/String;)Ldatadog/trace/api/PropagationStyle; + public static fun values ()[Ldatadog/trace/api/PropagationStyle; +} + +public abstract class datadog/trace/api/ResolverCacheConfig : java/lang/Enum { + public static final field LARGE Ldatadog/trace/api/ResolverCacheConfig; + public static final field LEGACY Ldatadog/trace/api/ResolverCacheConfig; + public static final field MEMOS Ldatadog/trace/api/ResolverCacheConfig; + public static final field NO_MEMOS Ldatadog/trace/api/ResolverCacheConfig; + public static final field SMALL Ldatadog/trace/api/ResolverCacheConfig; + public abstract fun memoPoolSize ()I + public abstract fun noMatchesSize ()I + public abstract fun outlinePoolSize ()I + public abstract fun typePoolSize ()I + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/ResolverCacheConfig; + public static fun values ()[Ldatadog/trace/api/ResolverCacheConfig; +} + +public abstract interface class datadog/trace/api/Stateful : java/lang/AutoCloseable { + public static final field DEFAULT Ldatadog/trace/api/Stateful; + public abstract fun activate (Ljava/lang/Object;)V + public abstract fun close ()V +} + +public abstract interface class datadog/trace/api/StatsDClient : java/io/Closeable { + public static final field NO_OP Ldatadog/trace/api/StatsDClient; + public abstract fun close ()V + public abstract fun count (Ljava/lang/String;J[Ljava/lang/String;)V + public abstract fun distribution (Ljava/lang/String;D[Ljava/lang/String;)V + public abstract fun distribution (Ljava/lang/String;J[Ljava/lang/String;)V + public abstract fun error (Ljava/lang/Exception;)V + public abstract fun gauge (Ljava/lang/String;D[Ljava/lang/String;)V + public abstract fun gauge (Ljava/lang/String;J[Ljava/lang/String;)V + public abstract fun getErrorCount ()I + public abstract fun histogram (Ljava/lang/String;D[Ljava/lang/String;)V + public abstract fun histogram (Ljava/lang/String;J[Ljava/lang/String;)V + public abstract fun incrementCounter (Ljava/lang/String;[Ljava/lang/String;)V + public abstract fun serviceCheck (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/StatsDClientManager { + public fun statsDClient (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)Ldatadog/trace/api/StatsDClient; + public abstract fun statsDClient (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Z)Ldatadog/trace/api/StatsDClient; +} + +public abstract interface annotation class datadog/trace/api/Trace : java/lang/annotation/Annotation { + public abstract fun measured ()Z + public abstract fun noParent ()Z + public abstract fun operationName ()Ljava/lang/String; + public abstract fun resourceName ()Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/TraceConfig { + public abstract fun getBaggageMapping ()Ljava/util/Map; + public abstract fun getRequestHeaderTags ()Ljava/util/Map; + public abstract fun getResponseHeaderTags ()Ljava/util/Map; + public abstract fun getServiceMapping ()Ljava/util/Map; + public abstract fun getSpanSamplingRules ()Ljava/util/List; + public abstract fun getTraceSampleRate ()Ljava/lang/Double; + public abstract fun getTraceSamplingRules ()Ljava/util/List; + public abstract fun isDataStreamsEnabled ()Z + public abstract fun isLogsInjectionEnabled ()Z + public abstract fun isRuntimeMetricsEnabled ()Z +} + +public final class datadog/trace/api/TracePropagationStyle : java/lang/Enum { + public static final field B3MULTI Ldatadog/trace/api/TracePropagationStyle; + public static final field B3SINGLE Ldatadog/trace/api/TracePropagationStyle; + public static final field DATADOG Ldatadog/trace/api/TracePropagationStyle; + public static final field HAYSTACK Ldatadog/trace/api/TracePropagationStyle; + public static final field NONE Ldatadog/trace/api/TracePropagationStyle; + public static final field TRACECONTEXT Ldatadog/trace/api/TracePropagationStyle; + public static final field XRAY Ldatadog/trace/api/TracePropagationStyle; + public fun toString ()Ljava/lang/String; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/TracePropagationStyle; + public static fun valueOfDisplayName (Ljava/lang/String;)Ldatadog/trace/api/TracePropagationStyle; + public static fun values ()[Ldatadog/trace/api/TracePropagationStyle; +} + +public abstract interface class datadog/trace/api/Tracer { + public abstract fun addTraceInterceptor (Ldatadog/trace/api/interceptor/TraceInterceptor;)Z + public abstract fun getSpanId ()Ljava/lang/String; + public abstract fun getTraceId ()Ljava/lang/String; +} + +public final class datadog/trace/api/UserEventTrackingMode : java/lang/Enum { + public static final field DISABLED Ldatadog/trace/api/UserEventTrackingMode; + public static final field EXTENDED Ldatadog/trace/api/UserEventTrackingMode; + public static final field SAFE Ldatadog/trace/api/UserEventTrackingMode; + public static fun fromString (Ljava/lang/String;)Ldatadog/trace/api/UserEventTrackingMode; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/UserEventTrackingMode; + public static fun values ()[Ldatadog/trace/api/UserEventTrackingMode; +} + +public class datadog/trace/api/WellKnownTags { + public fun (Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;)V + public fun getEnv ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun getHostname ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun getLanguage ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun getRuntimeId ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun getService ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun getVersion ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; +} + +public class datadog/trace/api/WithGlobalTracer { + public static fun registerOrExecute (Ldatadog/trace/api/WithGlobalTracer$Callback;)V +} + +public abstract interface class datadog/trace/api/WithGlobalTracer$Callback { + public abstract fun withTracer (Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$TracerAPI;)V +} + +public abstract interface class datadog/trace/api/cache/DDCache { + public abstract fun clear ()V + public abstract fun computeIfAbsent (Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object; + public abstract fun visit (Ljava/util/function/BiConsumer;)V +} + +public final class datadog/trace/api/cache/DDCaches { + public static fun newFixedSizeArrayKeyCache (I)Ldatadog/trace/api/cache/DDCache; + public static fun newFixedSizeCache (I)Ldatadog/trace/api/cache/DDCache; + public static fun newFixedSizeIdentityCache (I)Ldatadog/trace/api/cache/DDCache; + public static fun newFixedSizePartialKeyCache (I)Ldatadog/trace/api/cache/DDPartialKeyCache; + public static fun newFixedSizeWeakKeyCache (I)Ldatadog/trace/api/cache/DDCache; + public static fun newFixedSizeWeightedCache (ILjava/util/function/ToIntFunction;I)Ldatadog/trace/api/cache/DDCache; + public static fun newUnboundedCache (I)Ldatadog/trace/api/cache/DDCache; +} + +public abstract interface class datadog/trace/api/cache/DDPartialKeyCache { + public abstract fun clear ()V + public abstract fun computeIfAbsent (Ljava/lang/Object;IILdatadog/trace/api/cache/DDPartialKeyCache$Hasher;Ldatadog/trace/api/cache/DDPartialKeyCache$Comparator;Ldatadog/trace/api/cache/DDPartialKeyCache$Producer;)Ljava/lang/Object; +} + +public abstract interface class datadog/trace/api/cache/DDPartialKeyCache$Comparator { + public abstract fun test (Ljava/lang/Object;IILjava/lang/Object;)Z +} + +public abstract interface class datadog/trace/api/cache/DDPartialKeyCache$Hasher { + public abstract fun apply (Ljava/lang/Object;II)I +} + +public abstract interface class datadog/trace/api/cache/DDPartialKeyCache$Producer { + public abstract fun apply (Ljava/lang/Object;III)Ljava/lang/Object; +} + +public final class datadog/trace/api/cache/QualifiedClassNameCache : java/lang/ClassValue { + public fun (Ljava/util/function/Function;Ldatadog/trace/api/Functions$Join;)V + public fun (Ljava/util/function/Function;Ldatadog/trace/api/Functions$Join;I)V + public fun getClassName (Ljava/lang/Class;)Ljava/lang/CharSequence; + public fun getQualifiedName (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/CharSequence; +} + +public final class datadog/trace/api/cache/RadixTreeCache { + public static final field HTTP_STATUSES Ldatadog/trace/api/cache/RadixTreeCache; + public static final field PORTS Ldatadog/trace/api/cache/RadixTreeCache; + public static final field UNSET_PORT I + public static final field UNSET_STATUS I + public fun (IILjava/util/function/IntFunction;[I)V + public fun get (I)Ljava/lang/Object; +} + +public abstract interface class datadog/trace/api/civisibility/CIConstants { + public static final field TEST_FAIL Ljava/lang/String; + public static final field TEST_PASS Ljava/lang/String; + public static final field TEST_SKIP Ljava/lang/String; +} + +public class datadog/trace/api/civisibility/CIVisibility { + public fun ()V + public static fun registerSessionFactory (Ldatadog/trace/api/civisibility/CIVisibility$SessionFactory;)V + public static fun startSession (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTestSession; + public static fun startSession (Ljava/lang/String;Ljava/nio/file/Path;Ljava/lang/String;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTestSession; +} + +public abstract interface class datadog/trace/api/civisibility/CIVisibility$SessionFactory { + public abstract fun startSession (Ljava/lang/String;Ljava/nio/file/Path;Ljava/lang/String;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTestSession; +} + +public abstract interface class datadog/trace/api/civisibility/DDTest { + public abstract fun end (Ljava/lang/Long;)V + public abstract fun setErrorInfo (Ljava/lang/Throwable;)V + public abstract fun setSkipReason (Ljava/lang/String;)V + public abstract fun setTag (Ljava/lang/String;Ljava/lang/Object;)V +} + +public abstract interface class datadog/trace/api/civisibility/DDTestModule { + public abstract fun end (Ljava/lang/Long;)V + public abstract fun setErrorInfo (Ljava/lang/Throwable;)V + public abstract fun setSkipReason (Ljava/lang/String;)V + public abstract fun setTag (Ljava/lang/String;Ljava/lang/Object;)V + public fun testSuiteStart (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTestSuite; + public abstract fun testSuiteStart (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Long;Z)Ldatadog/trace/api/civisibility/DDTestSuite; +} + +public abstract interface class datadog/trace/api/civisibility/DDTestSession { + public abstract fun end (Ljava/lang/Long;)V + public abstract fun setErrorInfo (Ljava/lang/Throwable;)V + public abstract fun setSkipReason (Ljava/lang/String;)V + public abstract fun setTag (Ljava/lang/String;Ljava/lang/Object;)V + public abstract fun testModuleStart (Ljava/lang/String;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTestModule; +} + +public abstract interface class datadog/trace/api/civisibility/DDTestSuite { + public abstract fun end (Ljava/lang/Long;)V + public abstract fun setErrorInfo (Ljava/lang/Throwable;)V + public abstract fun setSkipReason (Ljava/lang/String;)V + public abstract fun setTag (Ljava/lang/String;Ljava/lang/Object;)V + public abstract fun testStart (Ljava/lang/String;Ljava/lang/reflect/Method;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTest; +} + +public abstract class datadog/trace/api/civisibility/InstrumentationBridge { + public static final field ITR_SKIP_REASON Ljava/lang/String; + public static final field ITR_UNSKIPPABLE_TAG Ljava/lang/String; + public fun ()V + public static fun createBuildEventsHandler ()Ldatadog/trace/api/civisibility/events/BuildEventsHandler; + public static fun createTestEventsHandler (Ljava/lang/String;)Ldatadog/trace/api/civisibility/events/TestEventsHandler; + public static fun registerBuildEventsHandlerFactory (Ldatadog/trace/api/civisibility/events/BuildEventsHandler$Factory;)V + public static fun registerTestEventsHandlerFactory (Ldatadog/trace/api/civisibility/events/TestEventsHandler$Factory;)V +} + +public final class datadog/trace/api/civisibility/config/Configurations { + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)V + public fun equals (Ljava/lang/Object;)Z + public fun getCustom ()Ljava/util/Map; + public fun getOsArchitecture ()Ljava/lang/String; + public fun getOsPlatform ()Ljava/lang/String; + public fun getOsVersion ()Ljava/lang/String; + public fun getRuntimeArchitecture ()Ljava/lang/String; + public fun getRuntimeName ()Ljava/lang/String; + public fun getRuntimeVendor ()Ljava/lang/String; + public fun getRuntimeVersion ()Ljava/lang/String; + public fun getTestBundle ()Ljava/lang/String; + public fun hashCode ()I +} + +public class datadog/trace/api/civisibility/config/ModuleExecutionSettings { + public static final field EMPTY Ldatadog/trace/api/civisibility/config/ModuleExecutionSettings; + public fun (ZZLjava/util/Map;Ljava/util/Map;Ljava/util/Collection;Ljava/util/List;)V + public fun equals (Ljava/lang/Object;)Z + public fun getCoverageEnabledPackages ()Ljava/util/List; + public fun getFlakyTests ()Ljava/util/Collection; + public fun getFlakyTests (Ljava/lang/String;)Ljava/util/Collection; + public fun getSkippableTests (Ljava/lang/String;)Ljava/util/Collection; + public fun getSkippableTestsByModule ()Ljava/util/Map; + public fun getSystemProperties ()Ljava/util/Map; + public fun hashCode ()I + public fun isCodeCoverageEnabled ()Z + public fun isItrEnabled ()Z +} + +public class datadog/trace/api/civisibility/config/TestIdentifier { + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/civisibility/config/Configurations;)V + public fun equals (Ljava/lang/Object;)Z + public fun getConfigurations ()Ldatadog/trace/api/civisibility/config/Configurations; + public fun getName ()Ljava/lang/String; + public fun getParameters ()Ljava/lang/String; + public fun getSuite ()Ljava/lang/String; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public abstract class datadog/trace/api/civisibility/coverage/CoverageBridge { + public fun ()V + public static fun currentCoverageProbeStoreRecord (Ljava/lang/Class;)V + public static fun currentCoverageProbeStoreRecord (Ljava/lang/Class;JI)V + public static fun currentCoverageProbeStoreRecordNonCode (Ljava/lang/String;)V + public static fun getCoverageData ()[B + public static fun getCoverageProbeStoreRegistry ()Ldatadog/trace/api/civisibility/coverage/CoverageProbeStore$Registry; + public static fun registerCoverageDataSupplier (Ldatadog/trace/api/civisibility/coverage/CoverageDataSupplier;)V + public static fun registerCoverageProbeStoreRegistry (Ldatadog/trace/api/civisibility/coverage/CoverageProbeStore$Registry;)V + public static fun removeThreadLocalCoverageProbeStore ()V + public static fun setThreadLocalCoverageProbeStore (Ldatadog/trace/api/civisibility/coverage/CoverageProbeStore;)V +} + +public abstract interface class datadog/trace/api/civisibility/coverage/CoverageDataSupplier { + public abstract fun get ()[B +} + +public abstract interface class datadog/trace/api/civisibility/coverage/CoverageProbeStore : datadog/trace/api/civisibility/coverage/TestReportHolder { + public abstract fun record (Ljava/lang/Class;)V + public abstract fun record (Ljava/lang/Class;JI)V + public abstract fun recordNonCodeResource (Ljava/lang/String;)V + public abstract fun report (Ljava/lang/Long;Ljava/lang/Long;J)V +} + +public abstract interface class datadog/trace/api/civisibility/coverage/CoverageProbeStore$Registry { + public abstract fun setTotalProbeCount (Ljava/lang/String;I)V +} + +public class datadog/trace/api/civisibility/coverage/TestReport { + public fun (Ljava/lang/Long;Ljava/lang/Long;JLjava/util/Collection;)V + public fun getSpanId ()J + public fun getTestReportFileEntries ()Ljava/util/Collection; + public fun getTestSessionId ()Ljava/lang/Long; + public fun getTestSuiteId ()Ljava/lang/Long; + public fun isNotEmpty ()Z +} + +public class datadog/trace/api/civisibility/coverage/TestReportFileEntry { + public fun (Ljava/lang/String;Ljava/util/List;)V + public fun getSegments ()Ljava/util/Collection; + public fun getSourceFileName ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; +} + +public class datadog/trace/api/civisibility/coverage/TestReportFileEntry$Segment : java/lang/Comparable { + public fun (IIIII)V + public fun compareTo (Ldatadog/trace/api/civisibility/coverage/TestReportFileEntry$Segment;)I + public synthetic fun compareTo (Ljava/lang/Object;)I + public fun getEndColumn ()I + public fun getEndLine ()I + public fun getNumberOfExecutions ()I + public fun getStartColumn ()I + public fun getStartLine ()I + public fun toString ()Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/civisibility/coverage/TestReportHolder { + public abstract fun getReport ()Ldatadog/trace/api/civisibility/coverage/TestReport; +} + +public abstract interface class datadog/trace/api/civisibility/events/BuildEventsHandler { + public abstract fun getModuleExecutionSettings (Ljava/lang/Object;Ljava/nio/file/Path;)Ldatadog/trace/api/civisibility/config/ModuleExecutionSettings; + public abstract fun getModuleInfo (Ljava/lang/Object;Ljava/lang/String;)Ldatadog/trace/api/civisibility/events/BuildEventsHandler$ModuleInfo; + public abstract fun onTestModuleFail (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Throwable;)V + public abstract fun onTestModuleFinish (Ljava/lang/Object;Ljava/lang/String;)V + public abstract fun onTestModuleSkip (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V + public abstract fun onTestModuleStart (Ljava/lang/Object;Ljava/lang/String;Ljava/util/Collection;Ljava/util/Map;)Ldatadog/trace/api/civisibility/events/BuildEventsHandler$ModuleInfo; + public abstract fun onTestSessionFail (Ljava/lang/Object;Ljava/lang/Throwable;)V + public abstract fun onTestSessionFinish (Ljava/lang/Object;)V + public abstract fun onTestSessionStart (Ljava/lang/Object;Ljava/lang/String;Ljava/nio/file/Path;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)V +} + +public abstract interface class datadog/trace/api/civisibility/events/BuildEventsHandler$Factory { + public abstract fun create ()Ldatadog/trace/api/civisibility/events/BuildEventsHandler; +} + +public final class datadog/trace/api/civisibility/events/BuildEventsHandler$ModuleInfo { + public final field moduleId J + public final field sessionId J + public final field signalServerHost Ljava/lang/String; + public final field signalServerPort I + public fun (JJLjava/lang/String;I)V +} + +public abstract interface class datadog/trace/api/civisibility/events/TestEventsHandler : java/io/Closeable { + public abstract fun close ()V + public abstract fun onTestFailure (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Throwable;)V + public abstract fun onTestFinish (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;)V + public abstract fun onTestIgnore (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Collection;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/reflect/Method;Ljava/lang/String;)V + public abstract fun onTestSkip (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V + public abstract fun onTestStart (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Collection;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/reflect/Method;)V + public abstract fun onTestSuiteFailure (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Throwable;)V + public abstract fun onTestSuiteFinish (Ljava/lang/String;Ljava/lang/Class;)V + public abstract fun onTestSuiteSkip (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)V + public abstract fun onTestSuiteStart (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/util/Collection;Z)V + public abstract fun retryPolicy (Ldatadog/trace/api/civisibility/config/TestIdentifier;)Ldatadog/trace/api/civisibility/retry/TestRetryPolicy; + public abstract fun skip (Ldatadog/trace/api/civisibility/config/TestIdentifier;)Z +} + +public abstract interface class datadog/trace/api/civisibility/events/TestEventsHandler$Factory { + public abstract fun create (Ljava/lang/String;)Ldatadog/trace/api/civisibility/events/TestEventsHandler; +} + +public class datadog/trace/api/civisibility/noop/NoOpDDTest : datadog/trace/api/civisibility/DDTest { + public fun ()V + public fun end (Ljava/lang/Long;)V + public fun setErrorInfo (Ljava/lang/Throwable;)V + public fun setSkipReason (Ljava/lang/String;)V + public fun setTag (Ljava/lang/String;Ljava/lang/Object;)V +} + +public class datadog/trace/api/civisibility/noop/NoOpDDTestModule : datadog/trace/api/civisibility/DDTestModule { + public fun ()V + public fun end (Ljava/lang/Long;)V + public fun setErrorInfo (Ljava/lang/Throwable;)V + public fun setSkipReason (Ljava/lang/String;)V + public fun setTag (Ljava/lang/String;Ljava/lang/Object;)V + public fun testSuiteStart (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Long;Z)Ldatadog/trace/api/civisibility/DDTestSuite; +} + +public class datadog/trace/api/civisibility/noop/NoOpDDTestSession : datadog/trace/api/civisibility/DDTestSession { + public static final field INSTANCE Ldatadog/trace/api/civisibility/DDTestSession; + public fun ()V + public fun end (Ljava/lang/Long;)V + public fun setErrorInfo (Ljava/lang/Throwable;)V + public fun setSkipReason (Ljava/lang/String;)V + public fun setTag (Ljava/lang/String;Ljava/lang/Object;)V + public fun testModuleStart (Ljava/lang/String;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTestModule; +} + +public class datadog/trace/api/civisibility/noop/NoOpDDTestSuite : datadog/trace/api/civisibility/DDTestSuite { + public fun ()V + public fun end (Ljava/lang/Long;)V + public fun setErrorInfo (Ljava/lang/Throwable;)V + public fun setSkipReason (Ljava/lang/String;)V + public fun setTag (Ljava/lang/String;Ljava/lang/Object;)V + public fun testStart (Ljava/lang/String;Ljava/lang/reflect/Method;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTest; +} + +public abstract interface class datadog/trace/api/civisibility/retry/TestRetryPolicy { + public abstract fun retry (Z)Z + public abstract fun retryPossible ()Z +} + +public final class datadog/trace/api/config/AppSecConfig { + public static final field API_SECURITY_ENABLED Ljava/lang/String; + public static final field API_SECURITY_REQUEST_SAMPLE_RATE Ljava/lang/String; + public static final field APPSEC_AUTOMATED_USER_EVENTS_TRACKING Ljava/lang/String; + public static final field APPSEC_ENABLED Ljava/lang/String; + public static final field APPSEC_HTTP_BLOCKED_TEMPLATE_HTML Ljava/lang/String; + public static final field APPSEC_HTTP_BLOCKED_TEMPLATE_JSON Ljava/lang/String; + public static final field APPSEC_IP_ADDR_HEADER Ljava/lang/String; + public static final field APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP Ljava/lang/String; + public static final field APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP Ljava/lang/String; + public static final field APPSEC_REPORTING_INBAND Ljava/lang/String; + public static final field APPSEC_REPORT_TIMEOUT_SEC Ljava/lang/String; + public static final field APPSEC_RULES_FILE Ljava/lang/String; + public static final field APPSEC_TRACE_RATE_LIMIT Ljava/lang/String; + public static final field APPSEC_WAF_METRICS Ljava/lang/String; + public static final field APPSEC_WAF_TIMEOUT Ljava/lang/String; +} + +public final class datadog/trace/api/config/CiVisibilityConfig { + public static final field CIVISIBILITY_ADDITIONAL_CHILD_PROCESS_JVM_ARGS Ljava/lang/String; + public static final field CIVISIBILITY_AGENTLESS_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_AGENTLESS_URL Ljava/lang/String; + public static final field CIVISIBILITY_AGENT_JAR_URI Ljava/lang/String; + public static final field CIVISIBILITY_AUTO_CONFIGURATION_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS Ljava/lang/String; + public static final field CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_CIPROVIDER_INTEGRATION_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_CODE_COVERAGE_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_CODE_COVERAGE_EXCLUDES Ljava/lang/String; + public static final field CIVISIBILITY_CODE_COVERAGE_INCLUDES Ljava/lang/String; + public static final field CIVISIBILITY_CODE_COVERAGE_PERCENTAGE_CALCULATION_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_CODE_COVERAGE_REPORT_DUMP_DIR Ljava/lang/String; + public static final field CIVISIBILITY_CODE_COVERAGE_ROOT_PACKAGES_LIMIT Ljava/lang/String; + public static final field CIVISIBILITY_CODE_COVERAGE_SEGMENTS_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_COMPILER_PLUGIN_VERSION Ljava/lang/String; + public static final field CIVISIBILITY_DEBUG_PORT Ljava/lang/String; + public static final field CIVISIBILITY_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_FLAKY_RETRY_COUNT Ljava/lang/String; + public static final field CIVISIBILITY_FLAKY_RETRY_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS Ljava/lang/String; + public static final field CIVISIBILITY_GIT_REMOTE_NAME Ljava/lang/String; + public static final field CIVISIBILITY_GIT_UNSHALLOW_DEFER Ljava/lang/String; + public static final field CIVISIBILITY_GIT_UNSHALLOW_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_GIT_UPLOAD_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS Ljava/lang/String; + public static final field CIVISIBILITY_INJECTED_TRACER_VERSION Ljava/lang/String; + public static final field CIVISIBILITY_ITR_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_JACOCO_GRADLE_SOURCE_SETS Ljava/lang/String; + public static final field CIVISIBILITY_JACOCO_PLUGIN_VERSION Ljava/lang/String; + public static final field CIVISIBILITY_JVM_INFO_CACHE_SIZE Ljava/lang/String; + public static final field CIVISIBILITY_MODULE_EXECUTION_SETTINGS_CACHE_SIZE Ljava/lang/String; + public static final field CIVISIBILITY_MODULE_ID Ljava/lang/String; + public static final field CIVISIBILITY_MODULE_NAME Ljava/lang/String; + public static final field CIVISIBILITY_REPO_INDEX_SHARING_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_RESOURCE_FOLDER_NAMES Ljava/lang/String; + public static final field CIVISIBILITY_SESSION_ID Ljava/lang/String; + public static final field CIVISIBILITY_SIGNAL_SERVER_HOST Ljava/lang/String; + public static final field CIVISIBILITY_SIGNAL_SERVER_PORT Ljava/lang/String; + public static final field CIVISIBILITY_SOURCE_DATA_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED Ljava/lang/String; + public static final field CIVISIBILITY_TRACE_SANITATION_ENABLED Ljava/lang/String; +} + +public final class datadog/trace/api/config/CrashTrackingConfig { + public static final field CRASH_TRACKING_AGENTLESS Ljava/lang/String; + public static final field CRASH_TRACKING_AGENTLESS_DEFAULT Z + public static final field CRASH_TRACKING_PROXY_HOST Ljava/lang/String; + public static final field CRASH_TRACKING_PROXY_PASSWORD Ljava/lang/String; + public static final field CRASH_TRACKING_PROXY_PORT Ljava/lang/String; + public static final field CRASH_TRACKING_PROXY_USERNAME Ljava/lang/String; + public static final field CRASH_TRACKING_TAGS Ljava/lang/String; + public static final field CRASH_TRACKING_UPLOAD_TIMEOUT Ljava/lang/String; + public static final field CRASH_TRACKING_UPLOAD_TIMEOUT_DEFAULT I +} + +public final class datadog/trace/api/config/CwsConfig { + public static final field CWS_ENABLED Ljava/lang/String; + public static final field CWS_TLS_REFRESH Ljava/lang/String; +} + +public final class datadog/trace/api/config/DebuggerConfig { + public static final field DEBUGGER_CAPTURE_TIMEOUT Ljava/lang/String; + public static final field DEBUGGER_CLASSFILE_DUMP_ENABLED Ljava/lang/String; + public static final field DEBUGGER_DIAGNOSTICS_INTERVAL Ljava/lang/String; + public static final field DEBUGGER_ENABLED Ljava/lang/String; + public static final field DEBUGGER_EXCLUDE_FILES Ljava/lang/String; + public static final field DEBUGGER_INSTRUMENT_THE_WORLD Ljava/lang/String; + public static final field DEBUGGER_MAX_PAYLOAD_SIZE Ljava/lang/String; + public static final field DEBUGGER_METRICS_ENABLED Ljava/lang/String; + public static final field DEBUGGER_POLL_INTERVAL Ljava/lang/String; + public static final field DEBUGGER_PROBE_FILE_LOCATION Ljava/lang/String; + public static final field DEBUGGER_PROBE_URL Ljava/lang/String; + public static final field DEBUGGER_REDACTED_IDENTIFIERS Ljava/lang/String; + public static final field DEBUGGER_REDACTED_TYPES Ljava/lang/String; + public static final field DEBUGGER_SNAPSHOT_URL Ljava/lang/String; + public static final field DEBUGGER_SYMBOL_ENABLED Ljava/lang/String; + public static final field DEBUGGER_SYMBOL_FLUSH_THRESHOLD Ljava/lang/String; + public static final field DEBUGGER_SYMBOL_FORCE_UPLOAD Ljava/lang/String; + public static final field DEBUGGER_SYMBOL_INCLUDES Ljava/lang/String; + public static final field DEBUGGER_UPLOAD_BATCH_SIZE Ljava/lang/String; + public static final field DEBUGGER_UPLOAD_FLUSH_INTERVAL Ljava/lang/String; + public static final field DEBUGGER_UPLOAD_TIMEOUT Ljava/lang/String; + public static final field DEBUGGER_VERIFY_BYTECODE Ljava/lang/String; +} + +public final class datadog/trace/api/config/GeneralConfig { + public static final field API_KEY Ljava/lang/String; + public static final field API_KEY_FILE Ljava/lang/String; + public static final field APPLICATION_KEY Ljava/lang/String; + public static final field APPLICATION_KEY_FILE Ljava/lang/String; + public static final field AZURE_APP_SERVICES Ljava/lang/String; + public static final field CONFIGURATION_FILE Ljava/lang/String; + public static final field DATA_STREAMS_BUCKET_DURATION_SECONDS Ljava/lang/String; + public static final field DATA_STREAMS_ENABLED Ljava/lang/String; + public static final field DOGSTATSD_ARGS Ljava/lang/String; + public static final field DOGSTATSD_HOST Ljava/lang/String; + public static final field DOGSTATSD_NAMED_PIPE Ljava/lang/String; + public static final field DOGSTATSD_PATH Ljava/lang/String; + public static final field DOGSTATSD_PORT Ljava/lang/String; + public static final field DOGSTATSD_START_DELAY Ljava/lang/String; + public static final field ENV Ljava/lang/String; + public static final field GLOBAL_TAGS Ljava/lang/String; + public static final field HEALTH_METRICS_ENABLED Ljava/lang/String; + public static final field HEALTH_METRICS_STATSD_HOST Ljava/lang/String; + public static final field HEALTH_METRICS_STATSD_PORT Ljava/lang/String; + public static final field INTERNAL_EXIT_ON_FAILURE Ljava/lang/String; + public static final field PERF_METRICS_ENABLED Ljava/lang/String; + public static final field PRIMARY_TAG Ljava/lang/String; + public static final field RUNTIME_ID_ENABLED Ljava/lang/String; + public static final field RUNTIME_METRICS_ENABLED Ljava/lang/String; + public static final field SERVICE_NAME Ljava/lang/String; + public static final field SITE Ljava/lang/String; + public static final field STARTUP_LOGS_ENABLED Ljava/lang/String; + public static final field STATSD_CLIENT_QUEUE_SIZE Ljava/lang/String; + public static final field STATSD_CLIENT_SOCKET_BUFFER Ljava/lang/String; + public static final field STATSD_CLIENT_SOCKET_TIMEOUT Ljava/lang/String; + public static final field TAGS Ljava/lang/String; + public static final field TELEMETRY_DEBUG_REQUESTS_ENABLED Ljava/lang/String; + public static final field TELEMETRY_DEPENDENCY_COLLECTION_ENABLED Ljava/lang/String; + public static final field TELEMETRY_ENABLED Ljava/lang/String; + public static final field TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL Ljava/lang/String; + public static final field TELEMETRY_HEARTBEAT_INTERVAL Ljava/lang/String; + public static final field TELEMETRY_LOG_COLLECTION_ENABLED Ljava/lang/String; + public static final field TELEMETRY_METRICS_ENABLED Ljava/lang/String; + public static final field TELEMETRY_METRICS_INTERVAL Ljava/lang/String; + public static final field TRACER_METRICS_BUFFERING_ENABLED Ljava/lang/String; + public static final field TRACER_METRICS_ENABLED Ljava/lang/String; + public static final field TRACER_METRICS_IGNORED_RESOURCES Ljava/lang/String; + public static final field TRACER_METRICS_MAX_AGGREGATES Ljava/lang/String; + public static final field TRACER_METRICS_MAX_PENDING Ljava/lang/String; + public static final field TRACE_DEBUG Ljava/lang/String; + public static final field TRACE_TRIAGE Ljava/lang/String; + public static final field VERSION Ljava/lang/String; +} + +public final class datadog/trace/api/config/IastConfig { + public static final field IAST_DEBUG_ENABLED Ljava/lang/String; + public static final field IAST_DEDUPLICATION_ENABLED Ljava/lang/String; + public static final field IAST_DETECTION_MODE Ljava/lang/String; + public static final field IAST_ENABLED Ljava/lang/String; + public static final field IAST_MAX_CONCURRENT_REQUESTS Ljava/lang/String; + public static final field IAST_MAX_RANGE_COUNT Ljava/lang/String; + public static final field IAST_REDACTION_ENABLED Ljava/lang/String; + public static final field IAST_REDACTION_NAME_PATTERN Ljava/lang/String; + public static final field IAST_REDACTION_VALUE_PATTERN Ljava/lang/String; + public static final field IAST_REQUEST_SAMPLING Ljava/lang/String; + public static final field IAST_STACKTRACE_LEAK_SUPPRESS Ljava/lang/String; + public static final field IAST_TELEMETRY_VERBOSITY Ljava/lang/String; + public static final field IAST_TRUNCATION_MAX_VALUE_LENGTH Ljava/lang/String; + public static final field IAST_VULNERABILITIES_PER_REQUEST Ljava/lang/String; + public static final field IAST_WEAK_CIPHER_ALGORITHMS Ljava/lang/String; + public static final field IAST_WEAK_HASH_ALGORITHMS Ljava/lang/String; +} + +public final class datadog/trace/api/config/JmxFetchConfig { + public static final field JMX_FETCH_CHECK_PERIOD Ljava/lang/String; + public static final field JMX_FETCH_CONFIG Ljava/lang/String; + public static final field JMX_FETCH_CONFIG_DIR Ljava/lang/String; + public static final field JMX_FETCH_ENABLED Ljava/lang/String; + public static final field JMX_FETCH_INITIAL_REFRESH_BEANS_PERIOD Ljava/lang/String; + public static final field JMX_FETCH_METRICS_CONFIGS Ljava/lang/String; + public static final field JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED Ljava/lang/String; + public static final field JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT Ljava/lang/String; + public static final field JMX_FETCH_REFRESH_BEANS_PERIOD Ljava/lang/String; + public static final field JMX_FETCH_START_DELAY Ljava/lang/String; + public static final field JMX_FETCH_STATSD_HOST Ljava/lang/String; + public static final field JMX_FETCH_STATSD_PORT Ljava/lang/String; + public static final field JMX_TAGS Ljava/lang/String; +} + +public final class datadog/trace/api/config/ProfilingConfig { + public static final field PROFILING_AGENTLESS Ljava/lang/String; + public static final field PROFILING_AGENTLESS_DEFAULT Z + public static final field PROFILING_ALLOCATION_ENABLED Ljava/lang/String; + public static final field PROFILING_API_KEY_FILE_OLD Ljava/lang/String; + public static final field PROFILING_API_KEY_FILE_VERY_OLD Ljava/lang/String; + public static final field PROFILING_API_KEY_OLD Ljava/lang/String; + public static final field PROFILING_API_KEY_VERY_OLD Ljava/lang/String; + public static final field PROFILING_AUXILIARY_TYPE Ljava/lang/String; + public static final field PROFILING_AUXILIARY_TYPE_DEFAULT Ljava/lang/String; + public static final field PROFILING_CONTEXT_ATTRIBUTES Ljava/lang/String; + public static final field PROFILING_CONTEXT_ATTRIBUTES_RESOURCE_NAME_ENABLED Ljava/lang/String; + public static final field PROFILING_CONTEXT_ATTRIBUTES_SPAN_NAME_ENABLED Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_ALLOC_ENABLED Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_ALLOC_ENABLED_DEFAULT Z + public static final field PROFILING_DATADOG_PROFILER_ALLOC_INTERVAL Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_ALLOC_INTERVAL_DEFAULT I + public static final field PROFILING_DATADOG_PROFILER_CPU_ENABLED Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_CPU_ENABLED_DEFAULT Z + public static final field PROFILING_DATADOG_PROFILER_CPU_INTERVAL Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_CPU_INTERVAL_DEFAULT I + public static final field PROFILING_DATADOG_PROFILER_CSTACK Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_CSTACK_DEFAULT Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_ENABLED Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_LIBPATH Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_LINE_NUMBERS Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_LINE_NUMBERS_DEFAULT Z + public static final field PROFILING_DATADOG_PROFILER_LIVEHEAP_CAPACITY Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_LIVEHEAP_CAPACITY_DEFAULT I + public static final field PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED_DEFAULT Z + public static final field PROFILING_DATADOG_PROFILER_LIVEHEAP_INTERVAL Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_LIVEHEAP_TRACK_HEAPSIZE Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_LIVEHEAP_TRACK_HEAPSIZE_DEFAFULT Z + public static final field PROFILING_DATADOG_PROFILER_LOG_LEVEL Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_LOG_LEVEL_DEFAULT Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_MEMLEAK_CAPACITY Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_MEMLEAK_ENABLED Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_MEMLEAK_INTERVAL Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_SAFEMODE Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_SAFEMODE_DEFAULT I + public static final field PROFILING_DATADOG_PROFILER_SCHEDULING_EVENT Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_SCHEDULING_EVENT_INTERVAL Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_SCRATCH Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_SCRATCH_DEFAULT Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_STACKDEPTH Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_WALL_COLLAPSING Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_WALL_COLLAPSING_DEFAULT Z + public static final field PROFILING_DATADOG_PROFILER_WALL_CONTEXT_FILTER Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_WALL_CONTEXT_FILTER_DEFAULT Z + public static final field PROFILING_DATADOG_PROFILER_WALL_ENABLED Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_WALL_ENABLED_DEFAULT Z + public static final field PROFILING_DATADOG_PROFILER_WALL_INTERVAL Ljava/lang/String; + public static final field PROFILING_DATADOG_PROFILER_WALL_INTERVAL_DEFAULT I + public static final field PROFILING_DEBUG_DUMP_PATH Ljava/lang/String; + public static final field PROFILING_DEBUG_JFR_DISABLED Ljava/lang/String; + public static final field PROFILING_DIRECT_ALLOCATION_ENABLED Ljava/lang/String; + public static final field PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT Z + public static final field PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT Ljava/lang/String; + public static final field PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT I + public static final field PROFILING_DISABLED_EVENTS Ljava/lang/String; + public static final field PROFILING_ENABLED Ljava/lang/String; + public static final field PROFILING_ENABLED_DEFAULT Z + public static final field PROFILING_ENABLED_EVENTS Ljava/lang/String; + public static final field PROFILING_ENDPOINT_COLLECTION_ENABLED Ljava/lang/String; + public static final field PROFILING_ENDPOINT_COLLECTION_ENABLED_DEFAULT Z + public static final field PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE Ljava/lang/String; + public static final field PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE_DEFAULT I + public static final field PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS Ljava/lang/String; + public static final field PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS_DEFAULT I + public static final field PROFILING_EXCEPTION_RECORD_MESSAGE Ljava/lang/String; + public static final field PROFILING_EXCEPTION_RECORD_MESSAGE_DEFAULT Z + public static final field PROFILING_EXCEPTION_SAMPLE_LIMIT Ljava/lang/String; + public static final field PROFILING_EXCEPTION_SAMPLE_LIMIT_DEFAULT I + public static final field PROFILING_EXCLUDE_AGENT_THREADS Ljava/lang/String; + public static final field PROFILING_HEAP_ENABLED Ljava/lang/String; + public static final field PROFILING_HEAP_ENABLED_DEFAULT Z + public static final field PROFILING_HEAP_HISTOGRAM_ENABLED Ljava/lang/String; + public static final field PROFILING_HEAP_HISTOGRAM_ENABLED_DEFAULT Z + public static final field PROFILING_HEAP_HISTOGRAM_MODE Ljava/lang/String; + public static final field PROFILING_HEAP_HISTOGRAM_MODE_DEFAULT Ljava/lang/String; + public static final field PROFILING_HOTSPOTS_ENABLED Ljava/lang/String; + public static final field PROFILING_JFR_REPOSITORY_MAXSIZE Ljava/lang/String; + public static final field PROFILING_JFR_REPOSITORY_MAXSIZE_DEFAULT I + public static final field PROFILING_PROXY_HOST Ljava/lang/String; + public static final field PROFILING_PROXY_PASSWORD Ljava/lang/String; + public static final field PROFILING_PROXY_PORT Ljava/lang/String; + public static final field PROFILING_PROXY_PORT_DEFAULT I + public static final field PROFILING_PROXY_USERNAME Ljava/lang/String; + public static final field PROFILING_QUEUEING_TIME_ENABLED Ljava/lang/String; + public static final field PROFILING_QUEUEING_TIME_ENABLED_DEFAULT Z + public static final field PROFILING_QUEUEING_TIME_THRESHOLD_MILLIS Ljava/lang/String; + public static final field PROFILING_QUEUEING_TIME_THRESHOLD_MILLIS_DEFAULT J + public static final field PROFILING_STACKDEPTH Ljava/lang/String; + public static final field PROFILING_STACKDEPTH_DEFAULT I + public static final field PROFILING_START_DELAY Ljava/lang/String; + public static final field PROFILING_START_DELAY_DEFAULT I + public static final field PROFILING_START_FORCE_FIRST Ljava/lang/String; + public static final field PROFILING_START_FORCE_FIRST_DEFAULT Z + public static final field PROFILING_TAGS Ljava/lang/String; + public static final field PROFILING_TEMPLATE_OVERRIDE_FILE Ljava/lang/String; + public static final field PROFILING_TIMELINE_EVENTS_ENABLED Ljava/lang/String; + public static final field PROFILING_TIMELINE_EVENTS_ENABLED_DEFAULT Z + public static final field PROFILING_ULTRA_MINIMAL Ljava/lang/String; + public static final field PROFILING_UPLOAD_COMPRESSION Ljava/lang/String; + public static final field PROFILING_UPLOAD_COMPRESSION_DEFAULT Ljava/lang/String; + public static final field PROFILING_UPLOAD_PERIOD Ljava/lang/String; + public static final field PROFILING_UPLOAD_PERIOD_DEFAULT I + public static final field PROFILING_UPLOAD_SUMMARY_ON_413 Ljava/lang/String; + public static final field PROFILING_UPLOAD_SUMMARY_ON_413_DEFAULT Z + public static final field PROFILING_UPLOAD_TIMEOUT Ljava/lang/String; + public static final field PROFILING_UPLOAD_TIMEOUT_DEFAULT I + public static final field PROFILING_URL Ljava/lang/String; +} + +public class datadog/trace/api/config/RemoteConfigConfig { + public static final field REMOTE_CONFIG_ENABLED Ljava/lang/String; + public static final field REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED Ljava/lang/String; + public static final field REMOTE_CONFIG_MAX_PAYLOAD_SIZE Ljava/lang/String; + public static final field REMOTE_CONFIG_POLL_INTERVAL_SECONDS Ljava/lang/String; + public static final field REMOTE_CONFIG_TARGETS_KEY Ljava/lang/String; + public static final field REMOTE_CONFIG_TARGETS_KEY_ID Ljava/lang/String; + public static final field REMOTE_CONFIG_URL Ljava/lang/String; +} + +public final class datadog/trace/api/config/TraceInstrumentationConfig { + public static final field DB_CLIENT_HOST_SPLIT_BY_HOST Ljava/lang/String; + public static final field DB_CLIENT_HOST_SPLIT_BY_INSTANCE Ljava/lang/String; + public static final field DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX Ljava/lang/String; + public static final field DB_DBM_PROPAGATION_MODE_MODE Ljava/lang/String; + public static final field ELASTICSEARCH_BODY_AND_PARAMS_ENABLED Ljava/lang/String; + public static final field ELASTICSEARCH_BODY_ENABLED Ljava/lang/String; + public static final field ELASTICSEARCH_PARAMS_ENABLED Ljava/lang/String; + public static final field GOOGLE_PUBSUB_IGNORED_GRPC_METHODS Ljava/lang/String; + public static final field GRPC_CLIENT_ERROR_STATUSES Ljava/lang/String; + public static final field GRPC_IGNORED_INBOUND_METHODS Ljava/lang/String; + public static final field GRPC_IGNORED_OUTBOUND_METHODS Ljava/lang/String; + public static final field GRPC_SERVER_ERROR_STATUSES Ljava/lang/String; + public static final field GRPC_SERVER_TRIM_PACKAGE_RESOURCE Ljava/lang/String; + public static final field HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN Ljava/lang/String; + public static final field HTTP_CLIENT_TAG_HEADERS Ljava/lang/String; + public static final field HTTP_CLIENT_TAG_QUERY_STRING Ljava/lang/String; + public static final field HTTP_SERVER_DECODED_RESOURCE_PRESERVE_SPACES Ljava/lang/String; + public static final field HTTP_SERVER_RAW_QUERY_STRING Ljava/lang/String; + public static final field HTTP_SERVER_RAW_RESOURCE Ljava/lang/String; + public static final field HTTP_SERVER_ROUTE_BASED_NAMING Ljava/lang/String; + public static final field HTTP_SERVER_TAG_QUERY_STRING Ljava/lang/String; + public static final field HTTP_URL_CONNECTION_CLASS_NAME Ljava/lang/String; + public static final field HYSTRIX_MEASURED_ENABLED Ljava/lang/String; + public static final field HYSTRIX_TAGS_ENABLED Ljava/lang/String; + public static final field IGNITE_CACHE_INCLUDE_KEYS Ljava/lang/String; + public static final field INTEGRATIONS_ENABLED Ljava/lang/String; + public static final field INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME Ljava/lang/String; + public static final field JAX_RS_EXCEPTION_AS_ERROR_ENABLED Ljava/lang/String; + public static final field JDBC_CONNECTION_CLASS_NAME Ljava/lang/String; + public static final field JDBC_PREPARED_STATEMENT_CLASS_NAME Ljava/lang/String; + public static final field JMS_PROPAGATION_DISABLED_QUEUES Ljava/lang/String; + public static final field JMS_PROPAGATION_DISABLED_TOPICS Ljava/lang/String; + public static final field JMS_UNACKNOWLEDGED_MAX_AGE Ljava/lang/String; + public static final field KAFKA_CLIENT_BASE64_DECODING_ENABLED Ljava/lang/String; + public static final field KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS Ljava/lang/String; + public static final field LEGACY_INSTALLER_ENABLED Ljava/lang/String; + public static final field LOGS_INJECTION_ENABLED Ljava/lang/String; + public static final field MEASURE_METHODS Ljava/lang/String; + public static final field MESSAGE_BROKER_SPLIT_BY_DESTINATION Ljava/lang/String; + public static final field OBFUSCATION_QUERY_STRING_REGEXP Ljava/lang/String; + public static final field PLAY_REPORT_HTTP_STATUS Ljava/lang/String; + public static final field RABBIT_INCLUDE_ROUTINGKEY_IN_RESOURCE Ljava/lang/String; + public static final field RABBIT_PROPAGATION_DISABLED_EXCHANGES Ljava/lang/String; + public static final field RABBIT_PROPAGATION_DISABLED_QUEUES Ljava/lang/String; + public static final field RESOLVER_CACHE_CONFIG Ljava/lang/String; + public static final field RESOLVER_CACHE_DIR Ljava/lang/String; + public static final field RESOLVER_NAMES_ARE_UNIQUE Ljava/lang/String; + public static final field RESOLVER_RESET_INTERVAL Ljava/lang/String; + public static final field RESOLVER_USE_LOADCLASS Ljava/lang/String; + public static final field RESOLVER_USE_URL_CACHES Ljava/lang/String; + public static final field RUNTIME_CONTEXT_FIELD_INJECTION Ljava/lang/String; + public static final field SERIALVERSIONUID_FIELD_INJECTION Ljava/lang/String; + public static final field SERVLET_ASYNC_TIMEOUT_ERROR Ljava/lang/String; + public static final field SERVLET_PRINCIPAL_ENABLED Ljava/lang/String; + public static final field SERVLET_ROOT_CONTEXT_SERVICE_NAME Ljava/lang/String; + public static final field SPARK_TASK_HISTOGRAM_ENABLED Ljava/lang/String; + public static final field SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME Ljava/lang/String; + public static final field TRACE_128_BIT_TRACEID_LOGGING_ENABLED Ljava/lang/String; + public static final field TRACE_ANNOTATIONS Ljava/lang/String; + public static final field TRACE_ANNOTATION_ASYNC Ljava/lang/String; + public static final field TRACE_CLASSES_EXCLUDE Ljava/lang/String; + public static final field TRACE_CLASSES_EXCLUDE_FILE Ljava/lang/String; + public static final field TRACE_CLASSLOADERS_EXCLUDE Ljava/lang/String; + public static final field TRACE_CODESOURCES_EXCLUDE Ljava/lang/String; + public static final field TRACE_ENABLED Ljava/lang/String; + public static final field TRACE_EXECUTORS Ljava/lang/String; + public static final field TRACE_EXECUTORS_ALL Ljava/lang/String; + public static final field TRACE_METHODS Ljava/lang/String; + public static final field TRACE_OTEL_ENABLED Ljava/lang/String; + public static final field TRACE_TESTS_ENABLED Ljava/lang/String; + public static final field TRACE_THREAD_POOL_EXECUTORS_EXCLUDE Ljava/lang/String; +} + +public final class datadog/trace/api/config/TracerConfig { + public static final field AGENT_HOST Ljava/lang/String; + public static final field AGENT_NAMED_PIPE Ljava/lang/String; + public static final field AGENT_PORT_LEGACY Ljava/lang/String; + public static final field AGENT_TIMEOUT Ljava/lang/String; + public static final field AGENT_UNIX_DOMAIN_SOCKET Ljava/lang/String; + public static final field BAGGAGE_MAPPING Ljava/lang/String; + public static final field CLIENT_IP_ENABLED Ljava/lang/String; + public static final field CLOCK_SYNC_PERIOD Ljava/lang/String; + public static final field ENABLE_TRACE_AGENT_V05 Ljava/lang/String; + public static final field HEADER_TAGS Ljava/lang/String; + public static final field HTTP_CLIENT_ERROR_STATUSES Ljava/lang/String; + public static final field HTTP_SERVER_ERROR_STATUSES Ljava/lang/String; + public static final field ID_GENERATION_STRATEGY Ljava/lang/String; + public static final field PARTIAL_FLUSH_ENABLED Ljava/lang/String; + public static final field PARTIAL_FLUSH_MIN_SPANS Ljava/lang/String; + public static final field PRIORITIZATION_TYPE Ljava/lang/String; + public static final field PRIORITY_SAMPLING Ljava/lang/String; + public static final field PRIORITY_SAMPLING_FORCE Ljava/lang/String; + public static final field PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED Ljava/lang/String; + public static final field PROPAGATION_STYLE_EXTRACT Ljava/lang/String; + public static final field PROPAGATION_STYLE_INJECT Ljava/lang/String; + public static final field PROXY_NO_PROXY Ljava/lang/String; + public static final field REQUEST_HEADER_TAGS Ljava/lang/String; + public static final field REQUEST_HEADER_TAGS_COMMA_ALLOWED Ljava/lang/String; + public static final field RESPONSE_HEADER_TAGS Ljava/lang/String; + public static final field SAMPLING_MECHANISM_VALIDATION_DISABLED Ljava/lang/String; + public static final field SCOPE_DEPTH_LIMIT Ljava/lang/String; + public static final field SCOPE_INHERIT_ASYNC_PROPAGATION Ljava/lang/String; + public static final field SCOPE_ITERATION_KEEP_ALIVE Ljava/lang/String; + public static final field SCOPE_STRICT_MODE Ljava/lang/String; + public static final field SECURE_RANDOM Ljava/lang/String; + public static final field SERVICE_MAPPING Ljava/lang/String; + public static final field SPAN_SAMPLING_RULES Ljava/lang/String; + public static final field SPAN_SAMPLING_RULES_FILE Ljava/lang/String; + public static final field SPAN_TAGS Ljava/lang/String; + public static final field SPLIT_BY_TAGS Ljava/lang/String; + public static final field TRACE_128_BIT_TRACEID_GENERATION_ENABLED Ljava/lang/String; + public static final field TRACE_AGENT_ARGS Ljava/lang/String; + public static final field TRACE_AGENT_PATH Ljava/lang/String; + public static final field TRACE_AGENT_PORT Ljava/lang/String; + public static final field TRACE_AGENT_URL Ljava/lang/String; + public static final field TRACE_ANALYTICS_ENABLED Ljava/lang/String; + public static final field TRACE_CLIENT_IP_HEADER Ljava/lang/String; + public static final field TRACE_CLIENT_IP_RESOLVER_ENABLED Ljava/lang/String; + public static final field TRACE_FLUSH_INTERVAL Ljava/lang/String; + public static final field TRACE_GIT_METADATA_ENABLED Ljava/lang/String; + public static final field TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING Ljava/lang/String; + public static final field TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH Ljava/lang/String; + public static final field TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING Ljava/lang/String; + public static final field TRACE_LONG_RUNNING_ENABLED Ljava/lang/String; + public static final field TRACE_LONG_RUNNING_FLUSH_INTERVAL Ljava/lang/String; + public static final field TRACE_PEER_SERVICE_COMPONENT_OVERRIDES Ljava/lang/String; + public static final field TRACE_PEER_SERVICE_DEFAULTS_ENABLED Ljava/lang/String; + public static final field TRACE_PEER_SERVICE_MAPPING Ljava/lang/String; + public static final field TRACE_PROPAGATION_EXTRACT_FIRST Ljava/lang/String; + public static final field TRACE_PROPAGATION_STYLE Ljava/lang/String; + public static final field TRACE_PROPAGATION_STYLE_EXTRACT Ljava/lang/String; + public static final field TRACE_PROPAGATION_STYLE_INJECT Ljava/lang/String; + public static final field TRACE_RATE_LIMIT Ljava/lang/String; + public static final field TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED Ljava/lang/String; + public static final field TRACE_REPORT_HOSTNAME Ljava/lang/String; + public static final field TRACE_RESOLVER_ENABLED Ljava/lang/String; + public static final field TRACE_SAMPLE_RATE Ljava/lang/String; + public static final field TRACE_SAMPLING_OPERATION_RULES Ljava/lang/String; + public static final field TRACE_SAMPLING_RULES Ljava/lang/String; + public static final field TRACE_SAMPLING_SERVICE_RULES Ljava/lang/String; + public static final field TRACE_SPAN_ATTRIBUTE_SCHEMA Ljava/lang/String; + public static final field TRACE_STRICT_WRITES_ENABLED Ljava/lang/String; + public static final field TRACE_X_DATADOG_TAGS_MAX_LENGTH Ljava/lang/String; + public static final field WRITER_BAGGAGE_INJECT Ljava/lang/String; + public static final field WRITER_TYPE Ljava/lang/String; +} + +public final class datadog/trace/api/config/UsmConfig { + public static final field USM_ENABLED Ljava/lang/String; +} + +public class datadog/trace/api/env/CapturedEnvironment { + public static fun get ()Ldatadog/trace/api/env/CapturedEnvironment; + public fun getProperties ()Ljava/util/Map; +} + +public abstract interface class datadog/trace/api/experimental/DataStreamsCheckpointer { + public static fun get ()Ldatadog/trace/api/experimental/DataStreamsCheckpointer; + public abstract fun setConsumeCheckpoint (Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/experimental/DataStreamsContextCarrier;)V + public abstract fun setProduceCheckpoint (Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/experimental/DataStreamsContextCarrier;)V +} + +public final class datadog/trace/api/experimental/DataStreamsCheckpointer$NoOp : datadog/trace/api/experimental/DataStreamsCheckpointer { + public static final field INSTANCE Ldatadog/trace/api/experimental/DataStreamsCheckpointer; + public fun ()V + public fun setConsumeCheckpoint (Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/experimental/DataStreamsContextCarrier;)V + public fun setProduceCheckpoint (Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/experimental/DataStreamsContextCarrier;)V +} + +public abstract interface class datadog/trace/api/experimental/DataStreamsContextCarrier { + public abstract fun entries ()Ljava/util/Set; + public abstract fun set (Ljava/lang/String;Ljava/lang/String;)V +} + +public final class datadog/trace/api/experimental/DataStreamsContextCarrier$NoOp : datadog/trace/api/experimental/DataStreamsContextCarrier { + public static final field INSTANCE Ldatadog/trace/api/experimental/DataStreamsContextCarrier; + public fun entries ()Ljava/util/Set; + public fun set (Ljava/lang/String;Ljava/lang/String;)V +} + +public final class datadog/trace/api/flare/TracerFlare { + public fun ()V + public static fun addBinary (Ljava/util/zip/ZipOutputStream;Ljava/lang/String;[B)V + public static fun addReporter (Ldatadog/trace/api/flare/TracerFlare$Reporter;)V + public static fun addReportsToFlare (Ljava/util/zip/ZipOutputStream;)V + public static fun addText (Ljava/util/zip/ZipOutputStream;Ljava/lang/String;Ljava/lang/String;)V + public static fun cleanupAfterFlare ()V + public static fun prepareForFlare ()V +} + +public abstract interface class datadog/trace/api/flare/TracerFlare$Reporter { + public abstract fun addReportToFlare (Ljava/util/zip/ZipOutputStream;)V + public fun cleanupAfterFlare ()V + public fun prepareForFlare ()V +} + +public abstract interface class datadog/trace/api/function/TriConsumer { + public abstract fun accept (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V +} + +public abstract interface class datadog/trace/api/function/TriFunction { + public abstract fun apply (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +} + +public abstract interface class datadog/trace/api/gateway/BlockResponseFunction { + public abstract fun tryCommitBlockingResponse (Ldatadog/trace/api/internal/TraceSegment;ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z +} + +public abstract interface class datadog/trace/api/gateway/CallbackProvider { + public abstract fun getCallback (Ldatadog/trace/api/gateway/EventType;)Ljava/lang/Object; +} + +public class datadog/trace/api/gateway/CallbackProvider$CallbackProviderNoop : datadog/trace/api/gateway/CallbackProvider { + public static final field INSTANCE Ldatadog/trace/api/gateway/CallbackProvider; + public fun getCallback (Ldatadog/trace/api/gateway/EventType;)Ljava/lang/Object; +} + +public class datadog/trace/api/gateway/EventType { + protected fun (Ljava/lang/String;I)V + public fun getName ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; +} + +public final class datadog/trace/api/gateway/Events { + public static final field EVENTS Ldatadog/trace/api/gateway/Events; + public static fun get ()Ldatadog/trace/api/gateway/Events; + public fun grpcServerRequestMessage ()Ldatadog/trace/api/gateway/EventType; + public fun requestBodyDone ()Ldatadog/trace/api/gateway/EventType; + public fun requestBodyProcessed ()Ldatadog/trace/api/gateway/EventType; + public fun requestBodyStart ()Ldatadog/trace/api/gateway/EventType; + public fun requestClientSocketAddress ()Ldatadog/trace/api/gateway/EventType; + public fun requestEnded ()Ldatadog/trace/api/gateway/EventType; + public fun requestHeader ()Ldatadog/trace/api/gateway/EventType; + public fun requestHeaderDone ()Ldatadog/trace/api/gateway/EventType; + public fun requestInferredClientAddress ()Ldatadog/trace/api/gateway/EventType; + public fun requestMethodUriRaw ()Ldatadog/trace/api/gateway/EventType; + public fun requestPathParams ()Ldatadog/trace/api/gateway/EventType; + public fun requestStarted ()Ldatadog/trace/api/gateway/EventType; + public fun responseHeader ()Ldatadog/trace/api/gateway/EventType; + public fun responseHeaderDone ()Ldatadog/trace/api/gateway/EventType; + public fun responseStarted ()Ldatadog/trace/api/gateway/EventType; +} + +public abstract interface class datadog/trace/api/gateway/Flow { + public abstract fun getAction ()Ldatadog/trace/api/gateway/Flow$Action; + public abstract fun getResult ()Ljava/lang/Object; +} + +public abstract interface class datadog/trace/api/gateway/Flow$Action { + public abstract fun isBlocking ()Z +} + +public class datadog/trace/api/gateway/Flow$Action$Noop : datadog/trace/api/gateway/Flow$Action { + public static field INSTANCE Ldatadog/trace/api/gateway/Flow$Action; + public fun isBlocking ()Z +} + +public class datadog/trace/api/gateway/Flow$Action$RequestBlockingAction : datadog/trace/api/gateway/Flow$Action { + public fun (ILdatadog/appsec/api/blocking/BlockingContentType;)V + public fun (ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)V + public static fun forRedirect (ILjava/lang/String;)Ldatadog/trace/api/gateway/Flow$Action$RequestBlockingAction; + public fun getBlockingContentType ()Ldatadog/appsec/api/blocking/BlockingContentType; + public fun getExtraHeaders ()Ljava/util/Map; + public fun getStatusCode ()I + public fun isBlocking ()Z +} + +public class datadog/trace/api/gateway/Flow$ResultFlow : datadog/trace/api/gateway/Flow { + public fun (Ljava/lang/Object;)V + public static fun empty ()Ldatadog/trace/api/gateway/Flow$ResultFlow; + public fun getAction ()Ldatadog/trace/api/gateway/Flow$Action; + public fun getResult ()Ljava/lang/Object; +} + +public abstract interface class datadog/trace/api/gateway/IGSpanInfo { + public abstract fun getRequestBlockingAction ()Ldatadog/trace/api/gateway/Flow$Action$RequestBlockingAction; + public abstract fun getSpanId ()J + public abstract fun getTags ()Ljava/util/Map; + public abstract fun getTraceId ()Ldatadog/trace/api/DDTraceId; + public abstract fun setRequestBlockingAction (Ldatadog/trace/api/gateway/Flow$Action$RequestBlockingAction;)V + public abstract fun setTag (Ljava/lang/String;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; +} + +public class datadog/trace/api/gateway/InstrumentationGateway { + public fun ()V + public fun getCallbackProvider (Ldatadog/trace/api/gateway/RequestContextSlot;)Ldatadog/trace/api/gateway/CallbackProvider; + public fun getSubscriptionService (Ldatadog/trace/api/gateway/RequestContextSlot;)Ldatadog/trace/api/gateway/SubscriptionService; + public fun getUniversalCallbackProvider ()Ldatadog/trace/api/gateway/CallbackProvider; + public static fun mergeFlows (Ldatadog/trace/api/gateway/Flow;Ldatadog/trace/api/gateway/Flow;)Ldatadog/trace/api/gateway/Flow; + public static fun wrap (Ldatadog/trace/api/gateway/EventType;Ljava/lang/Object;)Ljava/lang/Object; +} + +public abstract interface class datadog/trace/api/gateway/RequestContext : java/io/Closeable { + public abstract fun getBlockResponseFunction ()Ldatadog/trace/api/gateway/BlockResponseFunction; + public abstract fun getData (Ldatadog/trace/api/gateway/RequestContextSlot;)Ljava/lang/Object; + public abstract fun getTraceSegment ()Ldatadog/trace/api/internal/TraceSegment; + public abstract fun setBlockResponseFunction (Ldatadog/trace/api/gateway/BlockResponseFunction;)V +} + +public class datadog/trace/api/gateway/RequestContext$Noop : datadog/trace/api/gateway/RequestContext { + public static final field INSTANCE Ldatadog/trace/api/gateway/RequestContext; + public fun close ()V + public fun getBlockResponseFunction ()Ldatadog/trace/api/gateway/BlockResponseFunction; + public fun getData (Ldatadog/trace/api/gateway/RequestContextSlot;)Ljava/lang/Object; + public fun getTraceSegment ()Ldatadog/trace/api/internal/TraceSegment; + public fun setBlockResponseFunction (Ldatadog/trace/api/gateway/BlockResponseFunction;)V +} + +public final class datadog/trace/api/gateway/RequestContextSlot : java/lang/Enum { + public static final field APPSEC Ldatadog/trace/api/gateway/RequestContextSlot; + public static final field CI_VISIBILITY Ldatadog/trace/api/gateway/RequestContextSlot; + public static final field IAST Ldatadog/trace/api/gateway/RequestContextSlot; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/gateway/RequestContextSlot; + public static fun values ()[Ldatadog/trace/api/gateway/RequestContextSlot; +} + +public abstract interface class datadog/trace/api/gateway/Subscription { + public abstract fun cancel ()V +} + +public class datadog/trace/api/gateway/Subscription$SubscriptionNoop : datadog/trace/api/gateway/Subscription { + public static final field INSTANCE Ldatadog/trace/api/gateway/Subscription; + public fun cancel ()V +} + +public abstract interface class datadog/trace/api/gateway/SubscriptionService { + public abstract fun registerCallback (Ldatadog/trace/api/gateway/EventType;Ljava/lang/Object;)Ldatadog/trace/api/gateway/Subscription; + public abstract fun reset ()V +} + +public class datadog/trace/api/gateway/SubscriptionService$SubscriptionServiceNoop : datadog/trace/api/gateway/SubscriptionService { + public static final field INSTANCE Ldatadog/trace/api/gateway/SubscriptionService; + public fun registerCallback (Ldatadog/trace/api/gateway/EventType;Ljava/lang/Object;)Ldatadog/trace/api/gateway/Subscription; + public fun reset ()V +} + +public class datadog/trace/api/git/CommitInfo { + public static final field NOOP Ldatadog/trace/api/git/CommitInfo; + public fun (Ljava/lang/String;)V + public fun (Ljava/lang/String;Ldatadog/trace/api/git/PersonInfo;Ldatadog/trace/api/git/PersonInfo;Ljava/lang/String;)V + public fun equals (Ljava/lang/Object;)Z + public fun getAuthor ()Ldatadog/trace/api/git/PersonInfo; + public fun getCommitter ()Ldatadog/trace/api/git/PersonInfo; + public fun getFullMessage ()Ljava/lang/String; + public fun getSha ()Ljava/lang/String; + public fun hashCode ()I + public fun isEmpty ()Z + public fun toString ()Ljava/lang/String; +} + +public class datadog/trace/api/git/EmbeddedGitInfoBuilder : datadog/trace/api/git/GitInfoBuilder { + public fun ()V + public fun build (Ljava/lang/String;)Ldatadog/trace/api/git/GitInfo; + public fun order ()I +} + +public class datadog/trace/api/git/GitInfo { + public static final field DD_GIT_BRANCH Ljava/lang/String; + public static final field DD_GIT_COMMIT_AUTHOR_DATE Ljava/lang/String; + public static final field DD_GIT_COMMIT_AUTHOR_EMAIL Ljava/lang/String; + public static final field DD_GIT_COMMIT_AUTHOR_NAME Ljava/lang/String; + public static final field DD_GIT_COMMIT_COMMITTER_DATE Ljava/lang/String; + public static final field DD_GIT_COMMIT_COMMITTER_EMAIL Ljava/lang/String; + public static final field DD_GIT_COMMIT_COMMITTER_NAME Ljava/lang/String; + public static final field DD_GIT_COMMIT_MESSAGE Ljava/lang/String; + public static final field DD_GIT_COMMIT_SHA Ljava/lang/String; + public static final field DD_GIT_REPOSITORY_URL Ljava/lang/String; + public static final field DD_GIT_TAG Ljava/lang/String; + public static final field NOOP Ldatadog/trace/api/git/GitInfo; + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/git/CommitInfo;)V + public fun equals (Ljava/lang/Object;)Z + public fun getBranch ()Ljava/lang/String; + public fun getCommit ()Ldatadog/trace/api/git/CommitInfo; + public fun getRepositoryURL ()Ljava/lang/String; + public fun getTag ()Ljava/lang/String; + public fun hashCode ()I + public fun isEmpty ()Z +} + +public abstract interface class datadog/trace/api/git/GitInfoBuilder { + public abstract fun build (Ljava/lang/String;)Ldatadog/trace/api/git/GitInfo; + public abstract fun order ()I +} + +public class datadog/trace/api/git/GitInfoProvider { + public static final field INSTANCE Ldatadog/trace/api/git/GitInfoProvider; + public fun ()V + public fun getGitInfo ()Ldatadog/trace/api/git/GitInfo; + public fun getGitInfo (Ljava/lang/String;)Ldatadog/trace/api/git/GitInfo; + public fun invalidateCache ()V + public fun registerGitInfoBuilder (Ldatadog/trace/api/git/GitInfoBuilder;)V +} + +public class datadog/trace/api/git/GitUtils { + public fun ()V + public static fun filterSensitiveInfo (Ljava/lang/String;)Ljava/lang/String; + public static fun inflate ([B)[B + public static fun isTagReference (Ljava/lang/String;)Z + public static fun isValidCommitSha (Ljava/lang/String;)Z + public static fun normalizeBranch (Ljava/lang/String;)Ljava/lang/String; + public static fun normalizeTag (Ljava/lang/String;)Ljava/lang/String; + public static fun splitAuthorAndEmail (Ljava/lang/String;)Ldatadog/trace/api/git/PersonInfo; +} + +public class datadog/trace/api/git/PersonInfo { + public static final field NOOP Ldatadog/trace/api/git/PersonInfo; + public fun ()V + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun (Ljava/lang/String;Ljava/lang/String;JI)V + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + public fun equals (Ljava/lang/Object;)Z + public fun getEmail ()Ljava/lang/String; + public fun getIso8601Date ()Ljava/lang/String; + public fun getName ()Ljava/lang/String; + public fun hashCode ()I + public fun isEmpty ()Z + public fun toString ()Ljava/lang/String; +} + +public final class datadog/trace/api/git/RawParseUtils { + public static final field AUTHOR [B + public static final field COMMITTER [B + public static final fun author ([BI)I + public static fun commitMessage ([BI)I + public static fun committer ([BI)I + public static fun decode ([BII)Ljava/lang/String; + public static fun extractBinaryString ([BII)Ljava/lang/String; + public static fun findByte ([BB)I + public static fun lastIndexOfTrim ([BCI)I + public static fun match ([BI[B)I + public static fun next ([BIC)I + public static fun nextLF ([BI)I + public static fun nextLF ([BIC)I + public static fun parseBase10 ([BI)I + public static fun parseLongBase10 ([BI)J + public static fun parseTimeZoneOffset ([BI)I + public static fun tagMessage ([BI)I +} + +public class datadog/trace/api/git/UserSuppliedGitInfoBuilder : datadog/trace/api/git/GitInfoBuilder { + public fun ()V + public fun build (Ljava/lang/String;)Ldatadog/trace/api/git/GitInfo; + public fun order ()I +} + +public class datadog/trace/api/http/StoredBodyFactories { + public static fun maybeCreateForByte (Ljava/nio/charset/Charset;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;)Ldatadog/trace/api/http/StoredByteBody; + public static fun maybeCreateForByte (Ljava/nio/charset/Charset;Ljava/lang/Object;)Ldatadog/trace/api/http/StoredByteBody; + public static fun maybeCreateForChar (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;)Ldatadog/trace/api/http/StoredCharBody; + public static fun maybeCreateForChar (Ljava/lang/Object;)Ldatadog/trace/api/http/StoredCharBody; + public static fun maybeDeliverBodyInOneGo (Ljava/lang/String;Ldatadog/trace/api/gateway/RequestContext;)Ldatadog/trace/api/gateway/Flow; + public static fun maybeDeliverBodyInOneGo (Ljava/util/function/Supplier;Ldatadog/trace/api/gateway/RequestContext;)Ldatadog/trace/api/gateway/Flow; +} + +public class datadog/trace/api/http/StoredBodyFactories$ConstantBodySupplier : datadog/trace/api/http/StoredBodySupplier { + public fun (Ljava/util/function/Supplier;)V + public fun get ()Ljava/lang/CharSequence; + public synthetic fun get ()Ljava/lang/Object; +} + +public abstract interface class datadog/trace/api/http/StoredBodySupplier : java/util/function/Supplier { + public abstract fun get ()Ljava/lang/CharSequence; + public synthetic fun get ()Ljava/lang/Object; +} + +public class datadog/trace/api/http/StoredByteBody : datadog/trace/api/http/StoredBodySupplier { + public fun (Ldatadog/trace/api/gateway/RequestContext;Ljava/util/function/BiFunction;Ljava/util/function/BiFunction;Ljava/nio/charset/Charset;I)V + public fun appendData (I)V + public fun appendData (Ldatadog/trace/api/http/StoredByteBody$ByteBufferWriteCallback;I)V + public fun appendData ([BII)V + public fun get ()Ljava/lang/CharSequence; + public synthetic fun get ()Ljava/lang/Object; + public fun maybeNotify ()Ldatadog/trace/api/gateway/Flow; + public fun maybeNotifyAndBlock ()V + public fun setCharset (Ljava/nio/charset/Charset;)V +} + +public abstract interface class datadog/trace/api/http/StoredByteBody$ByteBufferWriteCallback { + public abstract fun put (Ljava/nio/ByteBuffer;)V +} + +public class datadog/trace/api/http/StoredCharBody : datadog/trace/api/http/StoredBodySupplier { + public fun (Ldatadog/trace/api/gateway/RequestContext;Ljava/util/function/BiFunction;Ljava/util/function/BiFunction;I)V + public fun appendData (I)V + public fun appendData (Ljava/lang/String;)V + public fun appendData (Ljava/nio/CharBuffer;)V + public fun appendData ([CII)V + public synthetic fun get ()Ljava/lang/CharSequence; + public synthetic fun get ()Ljava/lang/Object; + public fun get ()Ljava/nio/CharBuffer; + public fun maybeNotify ()Ldatadog/trace/api/gateway/Flow; + public fun maybeNotifyAndBlock ()V +} + +public abstract interface class datadog/trace/api/iast/IastCallSites { +} + +public abstract interface class datadog/trace/api/iast/IastCallSites$HasTelemetry { + public abstract fun setVerbosity (Ldatadog/trace/api/iast/telemetry/Verbosity;)V +} + +public abstract interface class datadog/trace/api/iast/IastContext { +} + +public abstract class datadog/trace/api/iast/IastContext$Provider { + public static fun get ()Ldatadog/trace/api/iast/IastContext; + public static fun get (Ldatadog/trace/api/gateway/RequestContext;)Ldatadog/trace/api/iast/IastContext; + public static fun get (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/api/iast/IastContext; +} + +public abstract class datadog/trace/api/iast/IastDetectionMode : java/lang/Enum { + public static final field DEFAULT Ldatadog/trace/api/iast/IastDetectionMode; + public static final field FULL Ldatadog/trace/api/iast/IastDetectionMode; + public static final field UNLIMITED I + public abstract fun getIastMaxConcurrentRequests (Ldatadog/trace/bootstrap/config/provider/ConfigProvider;)I + public abstract fun getIastMaxRangeCount (Ldatadog/trace/bootstrap/config/provider/ConfigProvider;)I + public abstract fun getIastRequestSampling (Ldatadog/trace/bootstrap/config/provider/ConfigProvider;)F + public abstract fun getIastVulnerabilitiesPerRequest (Ldatadog/trace/bootstrap/config/provider/ConfigProvider;)I + public abstract fun isIastDeduplicationEnabled (Ldatadog/trace/bootstrap/config/provider/ConfigProvider;)Z + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/iast/IastDetectionMode; + public static fun values ()[Ldatadog/trace/api/iast/IastDetectionMode; +} + +public abstract class datadog/trace/api/iast/IastEnabledChecks { + public static fun isMajorJavaVersionAtLeast (Ljava/lang/String;)Z +} + +public abstract interface class datadog/trace/api/iast/IastModule { + public static final field LOG Lorg/slf4j/Logger; + public fun onUnexpectedException (Ljava/lang/String;Ljava/lang/Throwable;)V +} + +public abstract class datadog/trace/api/iast/InstrumentationBridge { + public static field APPLICATION Ldatadog/trace/api/iast/sink/ApplicationModule; + public static field CODEC Ldatadog/trace/api/iast/propagation/CodecModule; + public static field COMMAND_INJECTION Ldatadog/trace/api/iast/sink/CommandInjectionModule; + public static field HEADER_INJECTION Ldatadog/trace/api/iast/sink/HeaderInjectionModule; + public static field HSTS_MISSING_HEADER_MODULE Ldatadog/trace/api/iast/sink/HstsMissingHeaderModule; + public static field INSECURE_COOKIE Ldatadog/trace/api/iast/sink/InsecureCookieModule; + public static field LDAP_INJECTION Ldatadog/trace/api/iast/sink/LdapInjectionModule; + public static field NO_HTTPONLY_COOKIE Ldatadog/trace/api/iast/sink/NoHttpOnlyCookieModule; + public static field NO_SAMESITE_COOKIE Ldatadog/trace/api/iast/sink/NoSameSiteCookieModule; + public static field PATH_TRAVERSAL Ldatadog/trace/api/iast/sink/PathTraversalModule; + public static field PROPAGATION Ldatadog/trace/api/iast/propagation/PropagationModule; + public static field RESPONSE_HEADER_MODULE Ldatadog/trace/api/iast/sink/HttpResponseHeaderModule; + public static field SQL_INJECTION Ldatadog/trace/api/iast/sink/SqlInjectionModule; + public static field SSRF Ldatadog/trace/api/iast/sink/SsrfModule; + public static field STACKTRACE_LEAK_MODULE Ldatadog/trace/api/iast/sink/StacktraceLeakModule; + public static field STRING Ldatadog/trace/api/iast/propagation/StringModule; + public static field TRUST_BOUNDARY_VIOLATION Ldatadog/trace/api/iast/sink/TrustBoundaryViolationModule; + public static field UNVALIDATED_REDIRECT Ldatadog/trace/api/iast/sink/UnvalidatedRedirectModule; + public static field WEAK_CIPHER Ldatadog/trace/api/iast/sink/WeakCipherModule; + public static field WEAK_HASH Ldatadog/trace/api/iast/sink/WeakHashModule; + public static field WEAK_RANDOMNESS Ldatadog/trace/api/iast/sink/WeakRandomnessModule; + public static field XPATH_INJECTION Ldatadog/trace/api/iast/sink/XPathInjectionModule; + public static field XSS Ldatadog/trace/api/iast/sink/XssModule; + public static field X_CONTENT_TYPE_HEADER_MODULE Ldatadog/trace/api/iast/sink/XContentTypeModule; + public static fun clearIastModules ()V + public static fun getIastModule (Ljava/lang/Class;)Ldatadog/trace/api/iast/IastModule; + public static fun registerIastModule (Ldatadog/trace/api/iast/IastModule;)V +} + +public abstract interface annotation class datadog/trace/api/iast/Propagation : java/lang/annotation/Annotation { +} + +public abstract interface annotation class datadog/trace/api/iast/Sink : java/lang/annotation/Annotation { + public abstract fun value ()B +} + +public abstract interface annotation class datadog/trace/api/iast/Source : java/lang/annotation/Annotation { + public abstract fun value ()B +} + +public abstract class datadog/trace/api/iast/SourceTypes { + public static final field GRPC_BODY B + public static final field GRPC_BODY_STRING Ljava/lang/String; + public static final field NONE B + public static final field REQUEST_BODY B + public static final field REQUEST_BODY_STRING Ljava/lang/String; + public static final field REQUEST_COOKIE_NAME B + public static final field REQUEST_COOKIE_NAME_STRING Ljava/lang/String; + public static final field REQUEST_COOKIE_VALUE B + public static final field REQUEST_COOKIE_VALUE_STRING Ljava/lang/String; + public static final field REQUEST_HEADER_NAME B + public static final field REQUEST_HEADER_NAME_STRING Ljava/lang/String; + public static final field REQUEST_HEADER_VALUE B + public static final field REQUEST_HEADER_VALUE_STRING Ljava/lang/String; + public static final field REQUEST_MATRIX_PARAMETER B + public static final field REQUEST_MATRIX_PARAMETER_STRING Ljava/lang/String; + public static final field REQUEST_MULTIPART_PARAMETER B + public static final field REQUEST_MULTIPART_PARAMETER_STRING Ljava/lang/String; + public static final field REQUEST_PARAMETER_NAME B + public static final field REQUEST_PARAMETER_NAME_STRING Ljava/lang/String; + public static final field REQUEST_PARAMETER_VALUE B + public static final field REQUEST_PARAMETER_VALUE_STRING Ljava/lang/String; + public static final field REQUEST_PATH B + public static final field REQUEST_PATH_PARAMETER B + public static final field REQUEST_PATH_PARAMETER_STRING Ljava/lang/String; + public static final field REQUEST_PATH_STRING Ljava/lang/String; + public static final field REQUEST_QUERY B + public static final field REQUEST_QUERY_STRING Ljava/lang/String; + public static final field REQUEST_URI B + public static final field REQUEST_URI_STRING Ljava/lang/String; + public static fun namedSource (B)B + public static fun toString (B)Ljava/lang/String; + public static fun values ()[B +} + +public abstract interface class datadog/trace/api/iast/Taintable { + public abstract fun $$DD$getSource ()Ldatadog/trace/api/iast/Taintable$Source; + public abstract fun $$DD$setSource (Ldatadog/trace/api/iast/Taintable$Source;)V + public fun $DD$isTainted ()Z +} + +public class datadog/trace/api/iast/Taintable$DebugLogger { + public fun ()V + public static fun logTaint (Ldatadog/trace/api/iast/Taintable;)V +} + +public abstract interface class datadog/trace/api/iast/Taintable$Source { + public abstract fun getName ()Ljava/lang/String; + public abstract fun getOrigin ()B + public abstract fun getValue ()Ljava/lang/String; +} + +public class datadog/trace/api/iast/VulnerabilityMarks { + public static final field COMMAND_INJECTION_MARK I + public static final field HEADER_INJECTION_MARK I + public static final field LDAP_INJECTION_MARK I + public static final field NOT_MARKED I + public static final field PATH_TRAVERSAL_MARK I + public static final field SQL_INJECTION_MARK I + public static final field SSRF_MARK I + public static final field TRUST_BOUNDARY_VIOLATION I + public static final field UNVALIDATED_REDIRECT_MARK I + public static final field XPATH_INJECTION_MARK I + public static final field XSS_MARK I +} + +public abstract class datadog/trace/api/iast/VulnerabilityTypes { + public static final field ADMIN_CONSOLE_ACTIVE B + public static final field ADMIN_CONSOLE_ACTIVE_STRING Ljava/lang/String; + public static final field COMMAND_INJECTION B + public static final field COMMAND_INJECTION_STRING Ljava/lang/String; + public static final field DEFAULT_HTML_ESCAPE_INVALID B + public static final field DEFAULT_HTML_ESCAPE_INVALID_STRING Ljava/lang/String; + public static final field DIRECTORY_LISTING_LEAK B + public static final field DIRECTORY_LISTING_LEAK_STRING Ljava/lang/String; + public static final field HEADER_INJECTION B + public static final field HEADER_INJECTION_STRING Ljava/lang/String; + public static final field HSTS_HEADER_MISSING B + public static final field HSTS_HEADER_MISSING_STRING Ljava/lang/String; + public static final field INSECURE_COOKIE B + public static final field INSECURE_COOKIE_STRING Ljava/lang/String; + public static final field INSECURE_JSP_LAYOUT B + public static final field INSECURE_JSP_LAYOUT_STRING Ljava/lang/String; + public static final field LDAP_INJECTION B + public static final field LDAP_INJECTION_STRING Ljava/lang/String; + public static final field NO_HTTPONLY_COOKIE B + public static final field NO_HTTPONLY_COOKIE_STRING Ljava/lang/String; + public static final field NO_SAMESITE_COOKIE B + public static final field NO_SAMESITE_COOKIE_STRING Ljava/lang/String; + public static final field PATH_TRAVERSAL B + public static final field PATH_TRAVERSAL_STRING Ljava/lang/String; + public static final field RESPONSE_HEADER B + public static final field RESPONSE_HEADER_TYPES [B + public static final field SESSION_TIMEOUT B + public static final field SESSION_TIMEOUT_STRING Ljava/lang/String; + public static final field SPRING_RESPONSE B + public static final field SPRING_RESPONSE_TYPES [B + public static final field SQL_INJECTION B + public static final field SQL_INJECTION_STRING Ljava/lang/String; + public static final field SSRF B + public static final field SSRF_STRING Ljava/lang/String; + public static final field STACKTRACE_LEAK B + public static final field STACKTRACE_LEAK_STRING Ljava/lang/String; + public static final field TRUST_BOUNDARY_VIOLATION B + public static final field TRUST_BOUNDARY_VIOLATION_STRING Ljava/lang/String; + public static final field UNVALIDATED_REDIRECT B + public static final field UNVALIDATED_REDIRECT_STRING Ljava/lang/String; + public static final field VERB_TAMPERING B + public static final field VERB_TAMPERING_STRING Ljava/lang/String; + public static final field WEAK_CIPHER B + public static final field WEAK_CIPHER_STRING Ljava/lang/String; + public static final field WEAK_HASH B + public static final field WEAK_HASH_STRING Ljava/lang/String; + public static final field WEAK_RANDOMNESS B + public static final field WEAK_RANDOMNESS_STRING Ljava/lang/String; + public static final field XCONTENTTYPE_HEADER_MISSING B + public static final field XCONTENTTYPE_HEADER_MISSING_STRING Ljava/lang/String; + public static final field XPATH_INJECTION B + public static final field XPATH_INJECTION_STRING Ljava/lang/String; + public static final field XSS B + public static final field XSS_STRING Ljava/lang/String; + public static fun toString (B)Ljava/lang/String; + public static fun values ()[B +} + +public abstract interface class datadog/trace/api/iast/propagation/CodecModule : datadog/trace/api/iast/IastModule { + public abstract fun onBase64Decode ([B[B)V + public abstract fun onBase64Encode ([B[B)V + public abstract fun onStringFromBytes ([BLjava/lang/String;Ljava/lang/String;)V + public abstract fun onStringGetBytes (Ljava/lang/String;Ljava/lang/String;[B)V + public abstract fun onUrlDecode (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/propagation/PropagationModule : datadog/trace/api/iast/IastModule { + public abstract fun findSource (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;)Ldatadog/trace/api/iast/Taintable$Source; + public abstract fun findSource (Ljava/lang/Object;)Ldatadog/trace/api/iast/Taintable$Source; + public abstract fun isTainted (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;)Z + public abstract fun isTainted (Ljava/lang/Object;)Z + public abstract fun taint (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;B)V + public abstract fun taint (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;BLjava/lang/CharSequence;)V + public abstract fun taint (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;BLjava/lang/CharSequence;Ljava/lang/CharSequence;)V + public abstract fun taint (Ljava/lang/Object;B)V + public abstract fun taint (Ljava/lang/Object;BLjava/lang/CharSequence;)V + public abstract fun taint (Ljava/lang/Object;BLjava/lang/CharSequence;Ljava/lang/CharSequence;)V + public abstract fun taintDeeply (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;BLjava/util/function/Predicate;)I + public abstract fun taintDeeply (Ljava/lang/Object;BLjava/util/function/Predicate;)I + public abstract fun taintIfAnyTainted (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;[Ljava/lang/Object;)V + public abstract fun taintIfAnyTainted (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;[Ljava/lang/Object;ZI)V + public abstract fun taintIfAnyTainted (Ljava/lang/Object;[Ljava/lang/Object;)V + public abstract fun taintIfAnyTainted (Ljava/lang/Object;[Ljava/lang/Object;ZI)V + public abstract fun taintIfTainted (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;Ljava/lang/Object;)V + public abstract fun taintIfTainted (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;Ljava/lang/Object;B)V + public abstract fun taintIfTainted (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;Ljava/lang/Object;BLjava/lang/CharSequence;)V + public abstract fun taintIfTainted (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;Ljava/lang/Object;BLjava/lang/CharSequence;Ljava/lang/CharSequence;)V + public abstract fun taintIfTainted (Ldatadog/trace/api/iast/IastContext;Ljava/lang/Object;Ljava/lang/Object;ZI)V + public abstract fun taintIfTainted (Ljava/lang/Object;Ljava/lang/Object;)V + public abstract fun taintIfTainted (Ljava/lang/Object;Ljava/lang/Object;B)V + public abstract fun taintIfTainted (Ljava/lang/Object;Ljava/lang/Object;BLjava/lang/CharSequence;)V + public abstract fun taintIfTainted (Ljava/lang/Object;Ljava/lang/Object;BLjava/lang/CharSequence;Ljava/lang/CharSequence;)V + public abstract fun taintIfTainted (Ljava/lang/Object;Ljava/lang/Object;ZI)V +} + +public abstract interface class datadog/trace/api/iast/propagation/StringModule : datadog/trace/api/iast/IastModule { + public abstract fun onSplit (Ljava/lang/String;[Ljava/lang/String;)V + public abstract fun onStringBuilderAppend (Ljava/lang/CharSequence;Ljava/lang/CharSequence;)V + public abstract fun onStringBuilderInit (Ljava/lang/CharSequence;Ljava/lang/CharSequence;)V + public abstract fun onStringBuilderToString (Ljava/lang/CharSequence;Ljava/lang/String;)V + public abstract fun onStringConcat (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + public abstract fun onStringConcatFactory (Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;[I)V + public abstract fun onStringConstructor (Ljava/lang/String;Ljava/lang/String;)V + public abstract fun onStringFormat (Ljava/lang/Iterable;[Ljava/lang/Object;Ljava/lang/String;)V + public abstract fun onStringFormat (Ljava/lang/String;[Ljava/lang/Object;Ljava/lang/String;)V + public abstract fun onStringFormat (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;Ljava/lang/String;)V + public abstract fun onStringJoin (Ljava/lang/String;Ljava/lang/CharSequence;[Ljava/lang/CharSequence;)V + public abstract fun onStringRepeat (Ljava/lang/String;ILjava/lang/String;)V + public abstract fun onStringSubSequence (Ljava/lang/String;IILjava/lang/CharSequence;)V + public abstract fun onStringToLowerCase (Ljava/lang/String;Ljava/lang/String;)V + public abstract fun onStringToUpperCase (Ljava/lang/String;Ljava/lang/String;)V + public abstract fun onStringTrim (Ljava/lang/String;Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/sink/ApplicationModule : datadog/trace/api/iast/IastModule { + public abstract fun onRealPath (Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/sink/CommandInjectionModule : datadog/trace/api/iast/IastModule { + public abstract fun onProcessBuilderStart (Ljava/util/List;)V + public abstract fun onRuntimeExec ([Ljava/lang/String;)V + public abstract fun onRuntimeExec ([Ljava/lang/String;[Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/sink/HeaderInjectionModule : datadog/trace/api/iast/IastModule { + public abstract fun onHeader (Ljava/lang/String;Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/sink/HstsMissingHeaderModule : datadog/trace/api/iast/sink/HttpRequestEndModule { +} + +public abstract interface class datadog/trace/api/iast/sink/HttpCookieModule : datadog/trace/api/iast/IastModule { + public abstract fun getType ()Ljava/lang/Object; + public abstract fun isVulnerable (Ldatadog/trace/api/iast/util/Cookie;)Z +} + +public abstract interface class datadog/trace/api/iast/sink/HttpRequestEndModule : datadog/trace/api/iast/IastModule { + public fun isHtmlResponse (Ljava/lang/String;)Z + public fun isIgnorableResponseCode (Ljava/lang/Integer;)Z + public abstract fun onRequestEnd (Ljava/lang/Object;Ldatadog/trace/api/gateway/IGSpanInfo;)V +} + +public abstract interface class datadog/trace/api/iast/sink/HttpResponseHeaderModule : datadog/trace/api/iast/IastModule { + public abstract fun onCookie (Ldatadog/trace/api/iast/util/Cookie;)V + public abstract fun onHeader (Ljava/lang/String;Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/sink/InsecureCookieModule : datadog/trace/api/iast/sink/HttpCookieModule { +} + +public abstract interface class datadog/trace/api/iast/sink/LdapInjectionModule : datadog/trace/api/iast/IastModule { + public abstract fun onDirContextSearch (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V +} + +public abstract interface class datadog/trace/api/iast/sink/NoHttpOnlyCookieModule : datadog/trace/api/iast/sink/HttpCookieModule { +} + +public abstract interface class datadog/trace/api/iast/sink/NoSameSiteCookieModule : datadog/trace/api/iast/sink/HttpCookieModule { +} + +public abstract interface class datadog/trace/api/iast/sink/PathTraversalModule : datadog/trace/api/iast/IastModule { + public abstract fun onPathTraversal (Ljava/io/File;Ljava/lang/String;)V + public abstract fun onPathTraversal (Ljava/lang/String;)V + public abstract fun onPathTraversal (Ljava/lang/String;Ljava/lang/String;)V + public abstract fun onPathTraversal (Ljava/lang/String;[Ljava/lang/String;)V + public abstract fun onPathTraversal (Ljava/net/URI;)V +} + +public abstract interface class datadog/trace/api/iast/sink/SqlInjectionModule : datadog/trace/api/iast/IastModule { + public static final field DATABASE_PARAMETER Ljava/lang/String; + public abstract fun onJdbcQuery (Ljava/lang/String;)V + public abstract fun onJdbcQuery (Ljava/lang/String;Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/sink/SsrfModule : datadog/trace/api/iast/IastModule { + public abstract fun onURLConnection (Ljava/lang/Object;)V + public abstract fun onURLConnection (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V +} + +public abstract interface class datadog/trace/api/iast/sink/StacktraceLeakModule : datadog/trace/api/iast/IastModule { + public abstract fun onStacktraceLeak (Ljava/lang/Throwable;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/sink/TrustBoundaryViolationModule : datadog/trace/api/iast/IastModule { + public abstract fun onSessionValue (Ljava/lang/String;Ljava/lang/Object;)V +} + +public abstract interface class datadog/trace/api/iast/sink/UnvalidatedRedirectModule : datadog/trace/api/iast/IastModule { + public abstract fun onHeader (Ljava/lang/String;Ljava/lang/String;)V + public abstract fun onRedirect (Ljava/lang/String;)V + public abstract fun onRedirect (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + public abstract fun onURIRedirect (Ljava/net/URI;)V +} + +public abstract interface class datadog/trace/api/iast/sink/WeakCipherModule : datadog/trace/api/iast/IastModule { + public abstract fun onCipherAlgorithm (Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/sink/WeakHashModule : datadog/trace/api/iast/IastModule { + public abstract fun onHashingAlgorithm (Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/sink/WeakRandomnessModule : datadog/trace/api/iast/IastModule { + public abstract fun onWeakRandom (Ljava/lang/Class;)V +} + +public abstract interface class datadog/trace/api/iast/sink/XContentTypeModule : datadog/trace/api/iast/sink/HttpRequestEndModule { +} + +public abstract interface class datadog/trace/api/iast/sink/XPathInjectionModule : datadog/trace/api/iast/IastModule { + public abstract fun onExpression (Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/iast/sink/XssModule : datadog/trace/api/iast/IastModule { + public abstract fun onXss (Ljava/lang/CharSequence;Ljava/lang/String;I)V + public abstract fun onXss (Ljava/lang/String;)V + public abstract fun onXss (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + public abstract fun onXss (Ljava/lang/String;[Ljava/lang/Object;)V + public abstract fun onXss ([C)V +} + +public final class datadog/trace/api/iast/telemetry/IastMetric : java/lang/Enum { + public static final field EXECUTED_PROPAGATION Ldatadog/trace/api/iast/telemetry/IastMetric; + public static final field EXECUTED_SINK Ldatadog/trace/api/iast/telemetry/IastMetric; + public static final field EXECUTED_SOURCE Ldatadog/trace/api/iast/telemetry/IastMetric; + public static final field EXECUTED_TAINTED Ldatadog/trace/api/iast/telemetry/IastMetric; + public static final field INSTRUMENTED_PROPAGATION Ldatadog/trace/api/iast/telemetry/IastMetric; + public static final field INSTRUMENTED_SINK Ldatadog/trace/api/iast/telemetry/IastMetric; + public static final field INSTRUMENTED_SOURCE Ldatadog/trace/api/iast/telemetry/IastMetric; + public static final field REQUEST_TAINTED Ldatadog/trace/api/iast/telemetry/IastMetric; + public static final field TAINTED_FLAT_MODE Ldatadog/trace/api/iast/telemetry/IastMetric; + public static fun count ()I + public fun getIndex (B)I + public fun getName ()Ljava/lang/String; + public fun getScope ()Ldatadog/trace/api/iast/telemetry/IastMetric$Scope; + public fun getTag ()Ldatadog/trace/api/iast/telemetry/IastMetric$Tag; + public fun isCommon ()Z + public fun isEnabled (Ldatadog/trace/api/iast/telemetry/Verbosity;)Z + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/iast/telemetry/IastMetric; + public static fun values ()[Ldatadog/trace/api/iast/telemetry/IastMetric; +} + +public final class datadog/trace/api/iast/telemetry/IastMetric$Scope { + public static final field GLOBAL Ldatadog/trace/api/iast/telemetry/IastMetric$Scope; + public static final field REQUEST Ldatadog/trace/api/iast/telemetry/IastMetric$Scope; + public fun getName ()Ljava/lang/String; +} + +public class datadog/trace/api/iast/telemetry/IastMetric$Tag { + public static final field SOURCE_TYPE Ldatadog/trace/api/iast/telemetry/IastMetric$Tag; + public static final field VULNERABILITY_TYPE Ldatadog/trace/api/iast/telemetry/IastMetric$Tag; + public fun getName ()Ljava/lang/String; + public fun getValues ()[B + public fun isWrapped (B)Z + public fun toString (B)Ljava/lang/String; + public fun unwrap (B)[B +} + +public class datadog/trace/api/iast/telemetry/IastMetricCollector : datadog/trace/api/telemetry/MetricCollector { + public fun ()V + protected fun (Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/atomic/AtomicLongArray;)V + public static fun add (Ldatadog/trace/api/iast/telemetry/IastMetric;BI)V + public static fun add (Ldatadog/trace/api/iast/telemetry/IastMetric;BILjava/lang/Object;)V + public static fun add (Ldatadog/trace/api/iast/telemetry/IastMetric;I)V + public static fun add (Ldatadog/trace/api/iast/telemetry/IastMetric;ILjava/lang/Object;)V + public fun addMetric (Ldatadog/trace/api/iast/telemetry/IastMetric;BI)V + public fun drain ()Ljava/util/Collection; + public static fun get ()Ldatadog/trace/api/iast/telemetry/IastMetricCollector; + public fun merge (Ljava/util/Collection;)V + public fun prepareMetrics ()V +} + +public abstract interface class datadog/trace/api/iast/telemetry/IastMetricCollector$HasMetricCollector { + public abstract fun getMetricCollector ()Ldatadog/trace/api/iast/telemetry/IastMetricCollector; +} + +public class datadog/trace/api/iast/telemetry/IastMetricCollector$IastMetricData : datadog/trace/api/telemetry/MetricCollector$Metric { + public fun (Ldatadog/trace/api/iast/telemetry/IastMetric;BJ)V + public static fun computeTag (Ldatadog/trace/api/iast/telemetry/IastMetric;B)Ljava/lang/String; + public fun getMetric ()Ldatadog/trace/api/iast/telemetry/IastMetric; + public fun getSpanTag ()Ljava/lang/String; + public fun getTagValue ()B +} + +public final class datadog/trace/api/iast/telemetry/Verbosity : java/lang/Enum { + public static final field DEBUG Ldatadog/trace/api/iast/telemetry/Verbosity; + public static final field INFORMATION Ldatadog/trace/api/iast/telemetry/Verbosity; + public static final field MANDATORY Ldatadog/trace/api/iast/telemetry/Verbosity; + public static final field OFF Ldatadog/trace/api/iast/telemetry/Verbosity; + public fun isDebugEnabled ()Z + public fun isEnabled (Ldatadog/trace/api/iast/telemetry/Verbosity;)Z + public fun isInformationEnabled ()Z + public fun isMandatoryEnabled ()Z + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/iast/telemetry/Verbosity; + public static fun values ()[Ldatadog/trace/api/iast/telemetry/Verbosity; +} + +public class datadog/trace/api/iast/util/Cookie { + public fun (Ljava/lang/String;ZZLjava/lang/String;)V + public fun getCookieName ()Ljava/lang/String; + public fun getSameSite ()Ljava/lang/String; + public fun isHttpOnly ()Z + public fun isSecure ()Z + public static fun named (Ljava/lang/String;)Ldatadog/trace/api/iast/util/Cookie$Builder; +} + +public class datadog/trace/api/iast/util/Cookie$Builder { + public fun (Ljava/lang/String;)V + public fun build ()Ldatadog/trace/api/iast/util/Cookie; + public fun httpOnly (Z)Ldatadog/trace/api/iast/util/Cookie$Builder; + public fun sameSite (Ljava/lang/String;)Ldatadog/trace/api/iast/util/Cookie$Builder; + public fun secure (Z)Ldatadog/trace/api/iast/util/Cookie$Builder; +} + +public final class datadog/trace/api/intake/TrackType : java/lang/Enum { + public static final field CITESTCOV Ldatadog/trace/api/intake/TrackType; + public static final field CITESTCYCLE Ldatadog/trace/api/intake/TrackType; + public static final field NOOP Ldatadog/trace/api/intake/TrackType; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/intake/TrackType; + public static fun values ()[Ldatadog/trace/api/intake/TrackType; +} + +public abstract class datadog/trace/api/interceptor/AbstractTraceInterceptor : datadog/trace/api/interceptor/TraceInterceptor { + protected fun (Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority;)V + public fun priority ()I +} + +public final class datadog/trace/api/interceptor/AbstractTraceInterceptor$Priority : java/lang/Enum { + public static final field CI_VISIBILITY_APM Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority; + public static final field CI_VISIBILITY_TRACE Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority; + public static final field DD_INTAKE Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority; + public static final field GIT_METADATA Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority; + public static final field SERVICE_NAME_COLLECTING Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority; + public static fun values ()[Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority; +} + +public abstract interface class datadog/trace/api/interceptor/MutableSpan { + public abstract fun getDurationNano ()J + public abstract fun getLocalRootSpan ()Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun getOperationName ()Ljava/lang/CharSequence; + public abstract fun getResourceName ()Ljava/lang/CharSequence; + public abstract fun getRootSpan ()Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun getSamplingPriority ()Ljava/lang/Integer; + public abstract fun getServiceName ()Ljava/lang/String; + public abstract fun getSpanType ()Ljava/lang/String; + public abstract fun getStartTime ()J + public fun getTag (Ljava/lang/String;)Ljava/lang/Object; + public abstract fun getTags ()Ljava/util/Map; + public abstract fun isError ()Z + public abstract fun setError (Z)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setMetric (Ljava/lang/CharSequence;D)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setMetric (Ljava/lang/CharSequence;I)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setMetric (Ljava/lang/CharSequence;J)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setOperationName (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setResourceName (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setSamplingPriority (I)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setServiceName (Ljava/lang/String;)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setTag (Ljava/lang/String;Z)Ldatadog/trace/api/interceptor/MutableSpan; +} + +public abstract interface class datadog/trace/api/interceptor/TraceInterceptor { + public abstract fun onTraceComplete (Ljava/util/Collection;)Ljava/util/Collection; + public abstract fun priority ()I +} + +public abstract interface class datadog/trace/api/internal/InternalTracer { + public abstract fun addScopeListener (Ljava/lang/Runnable;Ljava/lang/Runnable;)V + public abstract fun flush ()V + public abstract fun flushMetrics ()V + public abstract fun getDataStreamsCheckpointer ()Ldatadog/trace/api/experimental/DataStreamsCheckpointer; + public abstract fun getProfilingContext ()Ldatadog/trace/api/profiling/Profiling; + public abstract fun getTraceSegment ()Ldatadog/trace/api/internal/TraceSegment; +} + +public abstract interface class datadog/trace/api/internal/TraceSegment { + public abstract fun effectivelyBlocked ()V + public abstract fun setDataCurrent (Ljava/lang/String;Ljava/lang/Object;)V + public abstract fun setDataTop (Ljava/lang/String;Ljava/lang/Object;)V + public fun setTagCurrent (Ljava/lang/String;Ljava/lang/Object;)V + public abstract fun setTagCurrent (Ljava/lang/String;Ljava/lang/Object;Z)V + public fun setTagTop (Ljava/lang/String;Ljava/lang/Object;)V + public abstract fun setTagTop (Ljava/lang/String;Ljava/lang/Object;Z)V +} + +public class datadog/trace/api/internal/TraceSegment$NoOp : datadog/trace/api/internal/TraceSegment { + public static final field INSTANCE Ldatadog/trace/api/internal/TraceSegment; + public fun effectivelyBlocked ()V + public fun setDataCurrent (Ljava/lang/String;Ljava/lang/Object;)V + public fun setDataTop (Ljava/lang/String;Ljava/lang/Object;)V + public fun setTagCurrent (Ljava/lang/String;Ljava/lang/Object;Z)V + public fun setTagTop (Ljava/lang/String;Ljava/lang/Object;Z)V +} + +public class datadog/trace/api/internal/util/LongStringUtils { + public static fun numberFormatOutOfLongRange (Ljava/lang/CharSequence;)Ljava/lang/NumberFormatException; + public static fun parseUnsignedLong (Ljava/lang/String;)J + public static fun parseUnsignedLongHex (Ljava/lang/CharSequence;)J + public static fun parseUnsignedLongHex (Ljava/lang/CharSequence;IIZ)J + public static fun toHexStringPadded (JI)Ljava/lang/String; + public static fun toHexStringPadded (JJI)Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/metrics/CoreCounter { + public abstract fun getName ()Ljava/lang/String; + public abstract fun getValue ()J + public abstract fun getValueAndReset ()J +} + +public abstract interface class datadog/trace/api/metrics/SpanMetricRegistry { + public static final field NOOP Ldatadog/trace/api/metrics/SpanMetricRegistry; + public abstract fun get (Ljava/lang/String;)Ldatadog/trace/api/metrics/SpanMetrics; + public static fun getInstance ()Ldatadog/trace/api/metrics/SpanMetricRegistry; + public fun summary ()Ljava/lang/String; +} + +public class datadog/trace/api/metrics/SpanMetricRegistryImpl : datadog/trace/api/metrics/SpanMetricRegistry { + public fun get (Ljava/lang/String;)Ldatadog/trace/api/metrics/SpanMetrics; + public static fun getInstance ()Ldatadog/trace/api/metrics/SpanMetricRegistryImpl; + public fun getSpanMetrics ()Ljava/util/Collection; + public fun summary ()Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/metrics/SpanMetrics { + public static final field NOOP Ldatadog/trace/api/metrics/SpanMetrics; + public abstract fun onSpanCreated ()V + public abstract fun onSpanFinished ()V +} + +public class datadog/trace/api/metrics/SpanMetricsImpl : datadog/trace/api/metrics/SpanMetrics { + public fun (Ljava/lang/String;)V + public fun getCounters ()Ljava/util/Collection; + public fun getInstrumentationName ()Ljava/lang/String; + public fun onSpanCreated ()V + public fun onSpanFinished ()V +} + +public abstract interface class datadog/trace/api/naming/NamingSchema { + public abstract fun allowInferredServices ()Z + public abstract fun cache ()Ldatadog/trace/api/naming/NamingSchema$ForCache; + public abstract fun client ()Ldatadog/trace/api/naming/NamingSchema$ForClient; + public abstract fun cloud ()Ldatadog/trace/api/naming/NamingSchema$ForCloud; + public abstract fun database ()Ldatadog/trace/api/naming/NamingSchema$ForDatabase; + public abstract fun messaging ()Ldatadog/trace/api/naming/NamingSchema$ForMessaging; + public abstract fun peerService ()Ldatadog/trace/api/naming/NamingSchema$ForPeerService; + public abstract fun server ()Ldatadog/trace/api/naming/NamingSchema$ForServer; +} + +public abstract interface class datadog/trace/api/naming/NamingSchema$ForCache { + public abstract fun operation (Ljava/lang/String;)Ljava/lang/String; + public abstract fun service (Ljava/lang/String;)Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/naming/NamingSchema$ForClient { + public abstract fun operationForComponent (Ljava/lang/String;)Ljava/lang/String; + public abstract fun operationForProtocol (Ljava/lang/String;)Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/naming/NamingSchema$ForCloud { + public abstract fun operationForFaas (Ljava/lang/String;)Ljava/lang/String; + public abstract fun operationForRequest (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + public abstract fun serviceForRequest (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/naming/NamingSchema$ForDatabase { + public abstract fun normalizedName (Ljava/lang/String;)Ljava/lang/String; + public abstract fun operation (Ljava/lang/String;)Ljava/lang/String; + public abstract fun service (Ljava/lang/String;)Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/naming/NamingSchema$ForMessaging { + public abstract fun inboundOperation (Ljava/lang/String;)Ljava/lang/String; + public abstract fun inboundService (Ljava/lang/String;Z)Ljava/lang/String; + public abstract fun outboundOperation (Ljava/lang/String;)Ljava/lang/String; + public abstract fun outboundService (Ljava/lang/String;Z)Ljava/lang/String; + public abstract fun timeInQueueOperation (Ljava/lang/String;)Ljava/lang/String; + public abstract fun timeInQueueService (Ljava/lang/String;)Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/naming/NamingSchema$ForPeerService { + public abstract fun supports ()Z + public abstract fun tags (Ljava/util/Map;)Ljava/util/Map; +} + +public abstract interface class datadog/trace/api/naming/NamingSchema$ForServer { + public abstract fun operationForComponent (Ljava/lang/String;)Ljava/lang/String; + public abstract fun operationForProtocol (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/SpanNaming { + public static final field SCHEMA_MAX_VERSION I + public static final field SCHEMA_MIN_VERSION I + public static fun instance ()Ldatadog/trace/api/naming/SpanNaming; + public fun namingSchema ()Ldatadog/trace/api/naming/NamingSchema; + public fun version ()I +} + +public class datadog/trace/api/naming/v0/CacheNamingV0 : datadog/trace/api/naming/NamingSchema$ForCache { + public fun (Z)V + public fun operation (Ljava/lang/String;)Ljava/lang/String; + public fun service (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v0/ClientNamingV0 : datadog/trace/api/naming/NamingSchema$ForClient { + public fun ()V + public fun operationForComponent (Ljava/lang/String;)Ljava/lang/String; + public fun operationForProtocol (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v0/CloudNamingV0 : datadog/trace/api/naming/NamingSchema$ForCloud { + public fun (Z)V + public fun operationForFaas (Ljava/lang/String;)Ljava/lang/String; + public fun operationForRequest (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + public fun serviceForRequest (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v0/DatabaseNamingV0 : datadog/trace/api/naming/NamingSchema$ForDatabase { + public fun (Z)V + public fun normalizedName (Ljava/lang/String;)Ljava/lang/String; + public fun operation (Ljava/lang/String;)Ljava/lang/String; + public fun service (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v0/MessagingNamingV0 : datadog/trace/api/naming/NamingSchema$ForMessaging { + public fun (Z)V + public fun inboundOperation (Ljava/lang/String;)Ljava/lang/String; + public fun inboundService (Ljava/lang/String;Z)Ljava/lang/String; + public fun outboundOperation (Ljava/lang/String;)Ljava/lang/String; + public fun outboundService (Ljava/lang/String;Z)Ljava/lang/String; + public fun timeInQueueOperation (Ljava/lang/String;)Ljava/lang/String; + public fun timeInQueueService (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v0/NamingSchemaV0 : datadog/trace/api/naming/NamingSchema { + public fun ()V + public fun allowInferredServices ()Z + public fun cache ()Ldatadog/trace/api/naming/NamingSchema$ForCache; + public fun client ()Ldatadog/trace/api/naming/NamingSchema$ForClient; + public fun cloud ()Ldatadog/trace/api/naming/NamingSchema$ForCloud; + public fun database ()Ldatadog/trace/api/naming/NamingSchema$ForDatabase; + public fun messaging ()Ldatadog/trace/api/naming/NamingSchema$ForMessaging; + public fun peerService ()Ldatadog/trace/api/naming/NamingSchema$ForPeerService; + public fun server ()Ldatadog/trace/api/naming/NamingSchema$ForServer; +} + +public class datadog/trace/api/naming/v0/PeerServiceNamingV0 : datadog/trace/api/naming/NamingSchema$ForPeerService { + public fun ()V + public fun supports ()Z + public fun tags (Ljava/util/Map;)Ljava/util/Map; +} + +public class datadog/trace/api/naming/v0/ServerNamingV0 : datadog/trace/api/naming/NamingSchema$ForServer { + public fun ()V + public fun operationForComponent (Ljava/lang/String;)Ljava/lang/String; + public fun operationForProtocol (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v1/CacheNamingV1 : datadog/trace/api/naming/NamingSchema$ForCache { + public fun ()V + public fun operation (Ljava/lang/String;)Ljava/lang/String; + public fun service (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v1/ClientNamingV1 : datadog/trace/api/naming/NamingSchema$ForClient { + public fun ()V + public fun operationForComponent (Ljava/lang/String;)Ljava/lang/String; + public fun operationForProtocol (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v1/CloudNamingV1 : datadog/trace/api/naming/NamingSchema$ForCloud { + public fun ()V + public fun operationForFaas (Ljava/lang/String;)Ljava/lang/String; + public fun operationForRequest (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + public fun serviceForRequest (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v1/DatabaseNamingV1 : datadog/trace/api/naming/NamingSchema$ForDatabase { + public fun ()V + public fun normalizedName (Ljava/lang/String;)Ljava/lang/String; + public fun operation (Ljava/lang/String;)Ljava/lang/String; + public fun service (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v1/MessagingNamingV1 : datadog/trace/api/naming/NamingSchema$ForMessaging { + public fun ()V + public fun inboundOperation (Ljava/lang/String;)Ljava/lang/String; + public fun inboundService (Ljava/lang/String;Z)Ljava/lang/String; + public fun outboundOperation (Ljava/lang/String;)Ljava/lang/String; + public fun outboundService (Ljava/lang/String;Z)Ljava/lang/String; + public fun timeInQueueOperation (Ljava/lang/String;)Ljava/lang/String; + public fun timeInQueueService (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/naming/v1/NamingSchemaV1 : datadog/trace/api/naming/NamingSchema { + public fun ()V + public fun allowInferredServices ()Z + public fun cache ()Ldatadog/trace/api/naming/NamingSchema$ForCache; + public fun client ()Ldatadog/trace/api/naming/NamingSchema$ForClient; + public fun cloud ()Ldatadog/trace/api/naming/NamingSchema$ForCloud; + public fun database ()Ldatadog/trace/api/naming/NamingSchema$ForDatabase; + public fun messaging ()Ldatadog/trace/api/naming/NamingSchema$ForMessaging; + public fun peerService ()Ldatadog/trace/api/naming/NamingSchema$ForPeerService; + public fun server ()Ldatadog/trace/api/naming/NamingSchema$ForServer; +} + +public class datadog/trace/api/naming/v1/PeerServiceNamingV1 : datadog/trace/api/naming/NamingSchema$ForPeerService { + public fun (Ljava/util/Map;)V + public fun supports ()Z + public fun tags (Ljava/util/Map;)Ljava/util/Map; +} + +public class datadog/trace/api/naming/v1/ServerNamingV1 : datadog/trace/api/naming/NamingSchema$ForServer { + public fun ()V + public fun operationForComponent (Ljava/lang/String;)Ljava/lang/String; + public fun operationForProtocol (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/api/normalize/HttpResourceNames { + public static final field DEFAULT_RESOURCE_NAME Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static fun computeForClient (Ljava/lang/CharSequence;Ljava/lang/CharSequence;Z)Ldatadog/trace/api/Pair; + public static fun computeForServer (Ljava/lang/CharSequence;Ljava/lang/CharSequence;Z)Ldatadog/trace/api/Pair; + public static fun join (Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + public static fun setForClient (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun setForServer (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; +} + +public final class datadog/trace/api/normalize/SQLNormalizer { + public fun ()V + public static fun normalize (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static fun normalizeCharSequence (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; +} + +public final class datadog/trace/api/normalize/SimpleHttpPathNormalizer { + public fun normalize (Ljava/lang/String;Z)Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/profiling/ObservableType { +} + +public abstract interface class datadog/trace/api/profiling/Profiling { + public fun createContextAttribute (Ljava/lang/String;)Ldatadog/trace/api/profiling/ProfilingContextAttribute; + public static fun get ()Ldatadog/trace/api/profiling/Profiling; + public fun newScope ()Ldatadog/trace/api/profiling/ProfilingScope; +} + +public final class datadog/trace/api/profiling/Profiling$NoOp : datadog/trace/api/profiling/Profiling { + public static final field INSTANCE Ldatadog/trace/api/profiling/Profiling$NoOp; + public fun ()V +} + +public abstract interface class datadog/trace/api/profiling/ProfilingContext { + public fun clearContextValue (Ldatadog/trace/api/profiling/ProfilingContextAttribute;)V + public fun clearContextValue (Ljava/lang/String;)V + public fun setContextValue (Ldatadog/trace/api/profiling/ProfilingContextAttribute;Ljava/lang/String;)V + public fun setContextValue (Ljava/lang/String;Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/api/profiling/ProfilingContextAttribute { +} + +public final class datadog/trace/api/profiling/ProfilingContextAttribute$NoOp : datadog/trace/api/profiling/ProfilingContextAttribute { + public static final field INSTANCE Ldatadog/trace/api/profiling/ProfilingContextAttribute$NoOp; + public fun ()V +} + +public abstract interface class datadog/trace/api/profiling/ProfilingListener { + public abstract fun onData (Ljava/lang/Object;)V +} + +public final class datadog/trace/api/profiling/ProfilingListeners { + public fun addListener (Ldatadog/trace/api/profiling/ProfilingListener;)V + public fun fireOnData (Ldatadog/trace/api/profiling/ObservableType;)V + public fun removeListener (Ldatadog/trace/api/profiling/ProfilingListener;)V +} + +public final class datadog/trace/api/profiling/ProfilingListenersRegistry { + public static fun getHost (Ljava/lang/Class;)Ldatadog/trace/api/profiling/ProfilingListeners; +} + +public abstract interface class datadog/trace/api/profiling/ProfilingScope : datadog/trace/api/profiling/ProfilingContext, java/lang/AutoCloseable { + public static final field NO_OP Ldatadog/trace/api/profiling/ProfilingScope; + public abstract fun close ()V +} + +public abstract interface class datadog/trace/api/profiling/ProfilingSnapshot : datadog/trace/api/profiling/ObservableType { +} + +public final class datadog/trace/api/profiling/ProfilingSnapshot$Kind : java/lang/Enum { + public static final field ON_SHUTDOWN Ldatadog/trace/api/profiling/ProfilingSnapshot$Kind; + public static final field PERIODIC Ldatadog/trace/api/profiling/ProfilingSnapshot$Kind; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/profiling/ProfilingSnapshot$Kind; + public static fun values ()[Ldatadog/trace/api/profiling/ProfilingSnapshot$Kind; +} + +public abstract interface class datadog/trace/api/profiling/QueueTiming : datadog/trace/api/profiling/Timing { + public abstract fun setScheduler (Ljava/lang/Class;)V + public abstract fun setTask (Ljava/lang/Object;)V +} + +public abstract class datadog/trace/api/profiling/RecordingData : datadog/trace/api/profiling/ProfilingSnapshot { + protected final field end Ljava/time/Instant; + protected final field kind Ldatadog/trace/api/profiling/ProfilingSnapshot$Kind; + protected final field start Ljava/time/Instant; + public fun (Ljava/time/Instant;Ljava/time/Instant;Ldatadog/trace/api/profiling/ProfilingSnapshot$Kind;)V + public final fun getEnd ()Ljava/time/Instant; + public final fun getKind ()Ldatadog/trace/api/profiling/ProfilingSnapshot$Kind; + public abstract fun getName ()Ljava/lang/String; + public final fun getStart ()Ljava/time/Instant; + public abstract fun getStream ()Ldatadog/trace/api/profiling/RecordingInputStream; + public abstract fun release ()V + public final fun toString ()Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/profiling/RecordingDataListener { + public abstract fun onNewData (Ldatadog/trace/api/profiling/RecordingType;Ldatadog/trace/api/profiling/RecordingData;Z)V +} + +public class datadog/trace/api/profiling/RecordingInputStream : java/io/BufferedInputStream { + public fun (Ljava/io/InputStream;)V + public fun isEmpty ()Z +} + +public final class datadog/trace/api/profiling/RecordingType : java/lang/Enum { + public static final field CONTINUOUS Ldatadog/trace/api/profiling/RecordingType; + public fun getName ()Ljava/lang/String; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/profiling/RecordingType; + public static fun values ()[Ldatadog/trace/api/profiling/RecordingType; +} + +public abstract interface class datadog/trace/api/profiling/Timer { + public abstract fun start (Ldatadog/trace/api/profiling/Timer$TimerType;)Ldatadog/trace/api/profiling/Timing; +} + +public final class datadog/trace/api/profiling/Timer$NoOp : datadog/trace/api/profiling/Timer { + public static final field INSTANCE Ldatadog/trace/api/profiling/Timer; + public fun ()V + public fun start (Ldatadog/trace/api/profiling/Timer$TimerType;)Ldatadog/trace/api/profiling/Timing; +} + +public final class datadog/trace/api/profiling/Timer$TimerType : java/lang/Enum { + public static final field QUEUEING Ldatadog/trace/api/profiling/Timer$TimerType; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/api/profiling/Timer$TimerType; + public static fun values ()[Ldatadog/trace/api/profiling/Timer$TimerType; +} + +public abstract interface class datadog/trace/api/profiling/Timing : java/lang/AutoCloseable { + public abstract fun close ()V +} + +public class datadog/trace/api/profiling/Timing$NoOp : datadog/trace/api/profiling/QueueTiming, datadog/trace/api/profiling/Timing { + public static final field INSTANCE Ldatadog/trace/api/profiling/Timing; + public fun ()V + public fun close ()V + public fun setScheduler (Ljava/lang/Class;)V + public fun setTask (Ljava/lang/Object;)V +} + +public abstract interface class datadog/trace/api/profiling/TransientProfilingContextHolder { +} + +public class datadog/trace/api/sampling/AdaptiveSampler : datadog/trace/api/sampling/Sampler { + public fun (Ljava/time/Duration;IIILdatadog/trace/api/sampling/AdaptiveSampler$ConfigListener;)V + protected fun (Ljava/time/Duration;IIILdatadog/trace/api/sampling/AdaptiveSampler$ConfigListener;Ldatadog/trace/util/AgentTaskScheduler;Z)V + public fun (Ljava/time/Duration;IIIZ)V + public fun drop ()Z + public fun keep ()Z + public fun sample ()Z + public fun start ()V +} + +public abstract interface class datadog/trace/api/sampling/AdaptiveSampler$ConfigListener { + public abstract fun onWindowRoll (JJJDD)V +} + +public class datadog/trace/api/sampling/ConstantSampler : datadog/trace/api/sampling/Sampler { + public fun (Z)V + public fun drop ()Z + public fun keep ()Z + public fun sample ()Z +} + +public class datadog/trace/api/sampling/PrioritySampling { + public static final field SAMPLER_DROP B + public static final field SAMPLER_KEEP B + public static final field UNSET B + public static final field USER_DROP B + public static final field USER_KEEP B +} + +public abstract interface class datadog/trace/api/sampling/Sampler { + public abstract fun drop ()Z + public abstract fun keep ()Z + public abstract fun sample ()Z +} + +public class datadog/trace/api/sampling/SamplingMechanism { + public static final field AGENT_RATE B + public static final field APPSEC B + public static final field DATA_JOBS B + public static final field DEFAULT B + public static final field EXTERNAL_OVERRIDE B + public static final field MANUAL B + public static final field REMOTE_AUTO_RATE B + public static final field REMOTE_USER_RATE B + public static final field RULE B + public static final field SPAN_SAMPLING_RATE B + public static final field UNKNOWN B + public static fun validateWithSamplingPriority (II)Z +} + +public abstract interface class datadog/trace/api/sampling/SamplingRule { + public static final field MATCH_ALL Ljava/lang/String; + public abstract fun getName ()Ljava/lang/String; + public abstract fun getResource ()Ljava/lang/String; + public abstract fun getSampleRate ()D + public abstract fun getService ()Ljava/lang/String; + public abstract fun getTags ()Ljava/util/Map; + public static fun normalizeGlob (Ljava/lang/String;)Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/sampling/SamplingRule$SpanSamplingRule : datadog/trace/api/sampling/SamplingRule { + public abstract fun getMaxPerSecond ()I +} + +public abstract interface class datadog/trace/api/sampling/SamplingRule$TraceSamplingRule : datadog/trace/api/sampling/SamplingRule { +} + +public abstract interface class datadog/trace/api/scopemanager/ExtendedScopeListener : datadog/trace/api/scopemanager/ScopeListener { + public abstract fun afterScopeActivated (Ldatadog/trace/api/DDTraceId;JJLdatadog/trace/api/TraceConfig;)V + public abstract fun afterScopeClosed ()V +} + +public abstract interface class datadog/trace/api/scopemanager/ScopeListener { + public abstract fun afterScopeActivated ()V + public abstract fun afterScopeClosed ()V +} + +public class datadog/trace/api/telemetry/CoreMetricCollector : datadog/trace/api/telemetry/MetricCollector { + public fun drain ()Ljava/util/Collection; + public static fun getInstance ()Ldatadog/trace/api/telemetry/CoreMetricCollector; + public fun prepareMetrics ()V +} + +public class datadog/trace/api/telemetry/CoreMetricCollector$CoreMetric : datadog/trace/api/telemetry/MetricCollector$Metric { + public fun (Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/String;)V +} + +public class datadog/trace/api/telemetry/IntegrationsCollector { + public fun drain ()Ljava/util/Map; + public static fun get ()Ldatadog/trace/api/telemetry/IntegrationsCollector; + public fun update (Ljava/lang/Iterable;Z)V +} + +public class datadog/trace/api/telemetry/LogCollector { + public static final field SEND_TELEMETRY Lorg/slf4j/Marker; + public fun addLogMessage (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)V + public fun drain ()Ljava/util/Collection; + public static fun get ()Ldatadog/trace/api/telemetry/LogCollector; +} + +public class datadog/trace/api/telemetry/LogCollector$RawLogMessage { + public field count I + public final field logLevel Ljava/lang/String; + public final field messageOriginal Ljava/lang/String; + public final field throwable Ljava/lang/Throwable; + public final field timestamp J + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;J)V + public fun equals (Ljava/lang/Object;)Z + public fun hashCode ()I + public fun message ()Ljava/lang/String; +} + +public abstract interface class datadog/trace/api/telemetry/MetricCollector { + public static final field RAW_QUEUE_SIZE I + public abstract fun drain ()Ljava/util/Collection; + public abstract fun prepareMetrics ()V +} + +public class datadog/trace/api/telemetry/MetricCollector$Metric { + public final field common Z + public final field metricName Ljava/lang/String; + public final field namespace Ljava/lang/String; + public final field tags Ljava/util/List; + public final field timestamp J + public final field type Ljava/lang/String; + public final field value Ljava/lang/Number; + public fun (Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/String;)V + public fun (Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/Number;Ljava/util/List;)V + public fun (Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/Number;[Ljava/lang/String;)V + public fun equals (Ljava/lang/Object;)Z + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public class datadog/trace/api/telemetry/WafMetricCollector : datadog/trace/api/telemetry/MetricCollector { + public static final field INSTANCE Ldatadog/trace/api/telemetry/WafMetricCollector; + public fun ()V + public fun drain ()Ljava/util/Collection; + public static fun get ()Ldatadog/trace/api/telemetry/WafMetricCollector; + public fun prepareMetrics ()V + public fun wafInit (Ljava/lang/String;Ljava/lang/String;)V + public fun wafRequest ()V + public fun wafRequestBlocked ()V + public fun wafRequestTriggered ()V + public fun wafUpdates (Ljava/lang/String;)V +} + +public class datadog/trace/api/telemetry/WafMetricCollector$AtomicRequestCounter { + public fun ()V + public final fun get ()J + public final fun getAndReset ()J + public final fun increment ()V +} + +public class datadog/trace/api/telemetry/WafMetricCollector$WafInitRawMetric : datadog/trace/api/telemetry/WafMetricCollector$WafMetric { + public fun (JLjava/lang/String;Ljava/lang/String;)V +} + +public abstract class datadog/trace/api/telemetry/WafMetricCollector$WafMetric : datadog/trace/api/telemetry/MetricCollector$Metric { + public fun (Ljava/lang/String;J[Ljava/lang/String;)V +} + +public class datadog/trace/api/telemetry/WafMetricCollector$WafRequestsRawMetric : datadog/trace/api/telemetry/WafMetricCollector$WafMetric { + public fun (JLjava/lang/String;Ljava/lang/String;ZZ)V +} + +public class datadog/trace/api/telemetry/WafMetricCollector$WafUpdatesRawMetric : datadog/trace/api/telemetry/WafMetricCollector$WafMetric { + public fun (JLjava/lang/String;Ljava/lang/String;)V +} + +public class datadog/trace/api/time/ControllableTimeSource : datadog/trace/api/time/TimeSource { + public fun ()V + public fun advance (J)V + public fun getCurrentTimeMicros ()J + public fun getCurrentTimeMillis ()J + public fun getCurrentTimeNanos ()J + public fun getNanoTicks ()J + public fun set (J)V +} + +public class datadog/trace/api/time/SystemTimeSource : datadog/trace/api/time/TimeSource { + public static final field INSTANCE Ldatadog/trace/api/time/TimeSource; + public fun getCurrentTimeMicros ()J + public fun getCurrentTimeMillis ()J + public fun getCurrentTimeNanos ()J + public fun getNanoTicks ()J +} + +public abstract interface class datadog/trace/api/time/TimeSource { + public abstract fun getCurrentTimeMicros ()J + public abstract fun getCurrentTimeMillis ()J + public abstract fun getCurrentTimeNanos ()J + public abstract fun getNanoTicks ()J +} + +public class datadog/trace/bootstrap/ActiveSubsystems { + public static field APPSEC_ACTIVE Z + public fun ()V +} + +public class datadog/trace/bootstrap/config/provider/AgentArgsInjector { + public fun ()V + public static fun injectAgentArgsConfig (Ljava/lang/String;)V + public static fun injectAgentArgsConfig (Ljava/util/Map;)V +} + +public class datadog/trace/bootstrap/config/provider/AgentArgsParser { + public fun ()V + public static fun parseAgentArgs (Ljava/lang/String;)Ljava/util/Map; +} + +public final class datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource : datadog/trace/bootstrap/config/provider/ConfigProvider$Source { + public fun ()V + public fun (Ldatadog/trace/api/env/CapturedEnvironment;)V + public fun origin ()Ldatadog/trace/api/ConfigOrigin; +} + +public final class datadog/trace/bootstrap/config/provider/ConfigProvider { + public static fun createDefault ()Ldatadog/trace/bootstrap/config/provider/ConfigProvider; + public fun getBoolean (Ljava/lang/String;)Ljava/lang/Boolean; + public fun getBoolean (Ljava/lang/String;Z[Ljava/lang/String;)Z + public fun getBoolean (Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Boolean; + public fun getConfigFileStatus ()Ljava/lang/String; + public fun getDouble (Ljava/lang/String;)Ljava/lang/Double; + public fun getDouble (Ljava/lang/String;D)D + public fun getEnum (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Enum;)Ljava/lang/Enum; + public fun getFloat (Ljava/lang/String;F)F + public fun getFloat (Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Float; + public static fun getInstance ()Ldatadog/trace/bootstrap/config/provider/ConfigProvider; + public fun getInteger (Ljava/lang/String;)Ljava/lang/Integer; + public fun getInteger (Ljava/lang/String;I[Ljava/lang/String;)I + public fun getInteger (Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Integer; + public fun getIntegerRange (Ljava/lang/String;Ljava/util/BitSet;)Ljava/util/BitSet; + public fun getList (Ljava/lang/String;)Ljava/util/List; + public fun getList (Ljava/lang/String;Ljava/util/List;)Ljava/util/List; + public fun getLong (Ljava/lang/String;)Ljava/lang/Long; + public fun getLong (Ljava/lang/String;J[Ljava/lang/String;)J + public fun getLong (Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Long; + public fun getMergedMap (Ljava/lang/String;)Ljava/util/Map; + public fun getMergedMapWithOptionalMappings (Ljava/lang/String;Z[Ljava/lang/String;)Ljava/util/Map; + public fun getOrderedMap (Ljava/lang/String;)Ljava/util/Map; + public fun getSet (Ljava/lang/String;Ljava/util/Set;)Ljava/util/Set; + public fun getSpacedList (Ljava/lang/String;)Ljava/util/List; + public fun getString (Ljava/lang/String;)Ljava/lang/String; + public fun getString (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/String; + public fun getStringExcludingSource (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;[Ljava/lang/String;)Ljava/lang/String; + public fun getStringNotEmpty (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/String; + public fun isEnabled (Ljava/lang/Iterable;Ljava/lang/String;Ljava/lang/String;Z)Z + public fun isSet (Ljava/lang/String;)Z + public static fun withPropertiesOverride (Ljava/util/Properties;)Ldatadog/trace/bootstrap/config/provider/ConfigProvider; + public static fun withoutCollector ()Ldatadog/trace/bootstrap/config/provider/ConfigProvider; +} + +public abstract class datadog/trace/bootstrap/config/provider/ConfigProvider$Source { + public fun ()V + protected abstract fun get (Ljava/lang/String;)Ljava/lang/String; + public final fun get (Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/String; + public abstract fun origin ()Ldatadog/trace/api/ConfigOrigin; +} + +public final class datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource : datadog/trace/bootstrap/config/provider/ConfigProvider$Source { + public fun ()V + public fun origin ()Ldatadog/trace/api/ConfigOrigin; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring : datadog/trace/api/experimental/DataStreamsCheckpointer { + public abstract fun add (Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint;)V + public abstract fun newPathwayContext ()Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext; + public abstract fun setCheckpoint (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/util/LinkedHashMap;JJ)V + public abstract fun shouldSampleSchema (Ljava/lang/String;)I + public abstract fun trackBacklog (Ljava/util/LinkedHashMap;J)V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentHistogram { + public abstract fun accept (D)V + public abstract fun accept (DD)V + public abstract fun clear ()V + public abstract fun getCount ()D + public abstract fun getMaxValue ()D + public abstract fun getMinValue ()D + public abstract fun getValueAtQuantile (D)D + public abstract fun isEmpty ()Z + public abstract fun serialize ()Ljava/nio/ByteBuffer; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentPropagation { + public abstract fun extract (Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$ContextVisitor;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context$Extracted; + public abstract fun inject (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;)V + public abstract fun inject (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;)V + public abstract fun inject (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ldatadog/trace/api/TracePropagationStyle;)V + public abstract fun injectPathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;)V + public abstract fun injectPathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;JJ)V + public abstract fun injectPathwayContextWithoutSendingStats (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;)V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentPropagation$BinaryContextVisitor : datadog/trace/bootstrap/instrumentation/api/AgentPropagation$ContextVisitor { + public abstract fun forEachKey (Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$BinaryKeyClassifier;)V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentPropagation$BinaryKeyClassifier { + public abstract fun accept (Ljava/lang/String;[B)Z +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentPropagation$BinarySetter : datadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter { + public abstract fun set (Ljava/lang/Object;Ljava/lang/String;[B)V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentPropagation$ContextVisitor { + public abstract fun forEachKey (Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$KeyClassifier;)V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentPropagation$KeyClassifier { + public abstract fun accept (Ljava/lang/String;Ljava/lang/String;)Z +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter { + public abstract fun set (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentScope : datadog/trace/context/TraceScope, java/io/Closeable { + public abstract fun capture ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation; + public synthetic fun capture ()Ldatadog/trace/context/TraceScope$Continuation; + public abstract fun captureConcurrent ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation; + public synthetic fun captureConcurrent ()Ldatadog/trace/context/TraceScope$Continuation; + public abstract fun close ()V + public abstract fun setAsyncPropagation (Z)V + public abstract fun source ()B + public abstract fun span ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation : datadog/trace/context/TraceScope$Continuation { + public abstract fun activate ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public synthetic fun activate ()Ldatadog/trace/context/TraceScope; + public abstract fun getSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentScopeManager : datadog/trace/bootstrap/instrumentation/api/ScopeStateAware { + public abstract fun activate (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public abstract fun activate (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public abstract fun activateNext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public abstract fun active ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public abstract fun activeSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun captureSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation; + public abstract fun closePrevious (Z)V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentSpan : datadog/trace/api/gateway/IGSpanInfo, datadog/trace/api/interceptor/MutableSpan { + public abstract fun addLink (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink;)V + public abstract fun addThrowable (Ljava/lang/Throwable;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun addThrowable (Ljava/lang/Throwable;B)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun beginEndToEnd ()V + public abstract fun context ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; + public abstract fun eligibleForDropping ()Z + public abstract fun finish ()V + public abstract fun finish (J)V + public abstract fun finishWithDuration (J)V + public abstract fun finishWithEndToEnd ()V + public abstract fun forceSamplingDecision ()Ljava/lang/Integer; + public abstract fun getBaggageItem (Ljava/lang/String;)Ljava/lang/String; + public abstract fun getHttpStatusCode ()S + public synthetic fun getLocalRootSpan ()Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun getLocalRootSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun getRequestContext ()Ldatadog/trace/api/gateway/RequestContext; + public abstract fun getResourceNamePriority ()B + public abstract fun getSpanId ()J + public abstract fun getSpanName ()Ljava/lang/CharSequence; + public abstract fun getTag (Ljava/lang/String;)Ljava/lang/Object; + public abstract fun getTraceId ()Ldatadog/trace/api/DDTraceId; + public abstract fun hasResourceName ()Z + public abstract fun isSameTrace (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Z + public abstract fun phasedFinish ()Z + public abstract fun publish ()V + public abstract fun setBaggageItem (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setError (Z)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setError (Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setError (ZB)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setErrorMessage (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setHttpStatusCode (I)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setMeasured (Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;D)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setMetric (Ljava/lang/CharSequence;D)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;I)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setMetric (Ljava/lang/CharSequence;I)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;J)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setMetric (Ljava/lang/CharSequence;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setResourceName (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setResourceName (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setResourceName (Ljava/lang/CharSequence;B)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setSamplingPriority (II)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setSpanName (Ljava/lang/CharSequence;)V + public synthetic fun setSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setTag (Ljava/lang/String;D)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setTag (Ljava/lang/String;I)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setTag (Ljava/lang/String;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Z)Ldatadog/trace/api/interceptor/MutableSpan; + public abstract fun setTag (Ljava/lang/String;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun traceConfig ()Ldatadog/trace/api/TraceConfig; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context { + public abstract fun baggageItems ()Ljava/lang/Iterable; + public abstract fun getPathwayContext ()Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext; + public abstract fun getSamplingPriority ()I + public abstract fun getSpanId ()J + public abstract fun getTrace ()Ldatadog/trace/bootstrap/instrumentation/api/AgentTrace; + public abstract fun getTraceId ()Ldatadog/trace/api/DDTraceId; + public fun mergePathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext;)V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context$Extracted : datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context { + public abstract fun getCfConnectingIp ()Ljava/lang/String; + public abstract fun getCfConnectingIpv6 ()Ljava/lang/String; + public abstract fun getCustomIpHeader ()Ljava/lang/String; + public abstract fun getFastlyClientIp ()Ljava/lang/String; + public abstract fun getForwarded ()Ljava/lang/String; + public abstract fun getForwardedFor ()Ljava/lang/String; + public abstract fun getTerminatedContextLinks ()Ljava/util/List; + public abstract fun getTrueClientIp ()Ljava/lang/String; + public abstract fun getUserAgent ()Ljava/lang/String; + public abstract fun getXClientIp ()Ljava/lang/String; + public abstract fun getXClusterClientIp ()Ljava/lang/String; + public abstract fun getXForwarded ()Ljava/lang/String; + public abstract fun getXForwardedFor ()Ljava/lang/String; + public abstract fun getXForwardedHost ()Ljava/lang/String; + public abstract fun getXForwardedPort ()Ljava/lang/String; + public abstract fun getXForwardedProto ()Ljava/lang/String; + public abstract fun getXRealIp ()Ljava/lang/String; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentSpanLink { + public static final field DEFAULT_FLAGS B + public static final field SAMPLED_FLAG B + public abstract fun attributes ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink$Attributes; + public abstract fun spanId ()J + public abstract fun traceFlags ()B + public abstract fun traceId ()Ldatadog/trace/api/DDTraceId; + public abstract fun traceState ()Ljava/lang/String; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentSpanLink$Attributes { + public abstract fun asMap ()Ljava/util/Map; + public abstract fun isEmpty ()Z +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentTrace { + public abstract fun cancelContinuation (Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation;)V + public abstract fun registerContinuation (Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation;)V +} + +public class datadog/trace/bootstrap/instrumentation/api/AgentTracer { + public static final field NOOP_TRACER Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$TracerAPI; + public static fun activateNext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public static fun activateSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public static fun activateSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public static fun activeScope ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public static fun activeSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun capture ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation; + public static fun captureSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation; + public static fun closePrevious (Z)V + public static fun forceRegister (Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$TracerAPI;)V + public static fun get ()Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$TracerAPI; + public static fun isRegistered ()Z + public static fun noopSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun propagate ()Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation; + public static fun registerIfAbsent (Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$TracerAPI;)V + public static fun startSpan (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun startSpan (Ljava/lang/CharSequence;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun startSpan (Ljava/lang/CharSequence;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun startSpan (Ljava/lang/CharSequence;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public static fun traceConfig ()Ldatadog/trace/api/TraceConfig; + public static fun traceConfig (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/api/TraceConfig; +} + +public class datadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopAgentDataStreamsMonitoring : datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring { + public static final field INSTANCE Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopAgentDataStreamsMonitoring; + public fun ()V + public fun add (Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint;)V + public fun newPathwayContext ()Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext; + public fun setCheckpoint (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/util/LinkedHashMap;JJ)V + public fun setConsumeCheckpoint (Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/experimental/DataStreamsContextCarrier;)V + public fun setProduceCheckpoint (Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/experimental/DataStreamsContextCarrier;)V + public fun shouldSampleSchema (Ljava/lang/String;)I + public fun trackBacklog (Ljava/util/LinkedHashMap;J)V +} + +public class datadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopAgentHistogram : datadog/trace/bootstrap/instrumentation/api/AgentHistogram { + public static final field INSTANCE Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopAgentHistogram; + public fun ()V + public fun accept (D)V + public fun accept (DD)V + public fun clear ()V + public fun getCount ()D + public fun getMaxValue ()D + public fun getMinValue ()D + public fun getValueAtQuantile (D)D + public fun isEmpty ()Z + public fun serialize ()Ljava/nio/ByteBuffer; +} + +public final class datadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopAgentScope : datadog/trace/bootstrap/instrumentation/api/AgentScope { + public static final field INSTANCE Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopAgentScope; + public fun capture ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation; + public synthetic fun capture ()Ldatadog/trace/context/TraceScope$Continuation; + public fun captureConcurrent ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation; + public synthetic fun captureConcurrent ()Ldatadog/trace/context/TraceScope$Continuation; + public fun close ()V + public fun isAsyncPropagating ()Z + public fun setAsyncPropagation (Z)V + public fun source ()B + public fun span ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; +} + +public final class datadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopAgentSpan : datadog/trace/bootstrap/instrumentation/api/AgentSpan { + public static final field INSTANCE Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopAgentSpan; + public fun addLink (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink;)V + public fun addThrowable (Ljava/lang/Throwable;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun addThrowable (Ljava/lang/Throwable;B)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun beginEndToEnd ()V + public fun context ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; + public fun eligibleForDropping ()Z + public fun finish ()V + public fun finish (J)V + public fun finishWithDuration (J)V + public fun finishWithEndToEnd ()V + public fun forceSamplingDecision ()Ljava/lang/Integer; + public fun getBaggageItem (Ljava/lang/String;)Ljava/lang/String; + public fun getDurationNano ()J + public fun getHttpStatusCode ()S + public synthetic fun getLocalRootSpan ()Ldatadog/trace/api/interceptor/MutableSpan; + public fun getLocalRootSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun getOperationName ()Ljava/lang/CharSequence; + public fun getOperationName ()Ljava/lang/String; + public fun getRequestBlockingAction ()Ldatadog/trace/api/gateway/Flow$Action$RequestBlockingAction; + public fun getRequestContext ()Ldatadog/trace/api/gateway/RequestContext; + public fun getResourceName ()Ljava/lang/CharSequence; + public fun getResourceNamePriority ()B + public synthetic fun getRootSpan ()Ldatadog/trace/api/interceptor/MutableSpan; + public fun getRootSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun getSamplingPriority ()Ljava/lang/Integer; + public fun getServiceName ()Ljava/lang/String; + public fun getSpanId ()J + public synthetic fun getSpanName ()Ljava/lang/CharSequence; + public fun getSpanName ()Ljava/lang/String; + public fun getSpanType ()Ljava/lang/String; + public fun getStartTime ()J + public fun getTag (Ljava/lang/String;)Ljava/lang/Object; + public fun getTags ()Ljava/util/Map; + public fun getTraceId ()Ldatadog/trace/api/DDTraceId; + public fun hasResourceName ()Z + public fun isError ()Z + public fun isSameTrace (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Z + public fun phasedFinish ()Z + public fun publish ()V + public fun setBaggageItem (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setError (Z)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setError (Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setError (ZB)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setErrorMessage (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setHttpStatusCode (I)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setMeasured (Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;D)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setMetric (Ljava/lang/CharSequence;D)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;I)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setMetric (Ljava/lang/CharSequence;I)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;J)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setMetric (Ljava/lang/CharSequence;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setOperationName (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setOperationName (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setRequestBlockingAction (Ldatadog/trace/api/gateway/Flow$Action$RequestBlockingAction;)V + public synthetic fun setResourceName (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setResourceName (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setResourceName (Ljava/lang/CharSequence;B)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setSamplingPriority (I)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setSamplingPriority (I)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setSamplingPriority (II)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setServiceName (Ljava/lang/String;)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setServiceName (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setSpanName (Ljava/lang/CharSequence;)V + public synthetic fun setSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setTag (Ljava/lang/String;D)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setTag (Ljava/lang/String;I)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setTag (Ljava/lang/String;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setTag (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setTag (Ljava/lang/String;Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Z)Ldatadog/trace/api/interceptor/MutableSpan; + public fun setTag (Ljava/lang/String;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun traceConfig ()Ldatadog/trace/api/TraceConfig; +} + +public class datadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopAgentTrace : datadog/trace/bootstrap/instrumentation/api/AgentTrace { + public static final field INSTANCE Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopAgentTrace; + public fun ()V + public fun cancelContinuation (Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation;)V + public fun registerContinuation (Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation;)V +} + +public final class datadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopContext : datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context$Extracted { + public static final field INSTANCE Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopContext; + public fun baggageItems ()Ljava/lang/Iterable; + public fun getCfConnectingIp ()Ljava/lang/String; + public fun getCfConnectingIpv6 ()Ljava/lang/String; + public fun getCustomIpHeader ()Ljava/lang/String; + public fun getFastlyClientIp ()Ljava/lang/String; + public fun getForwarded ()Ljava/lang/String; + public fun getForwardedFor ()Ljava/lang/String; + public fun getPathwayContext ()Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext; + public fun getSamplingPriority ()I + public fun getSpanId ()J + public fun getTerminatedContextLinks ()Ljava/util/List; + public fun getTrace ()Ldatadog/trace/bootstrap/instrumentation/api/AgentTrace; + public fun getTraceId ()Ldatadog/trace/api/DDTraceId; + public fun getTrueClientIp ()Ljava/lang/String; + public fun getUserAgent ()Ljava/lang/String; + public fun getXClientIp ()Ljava/lang/String; + public fun getXClusterClientIp ()Ljava/lang/String; + public fun getXForwarded ()Ljava/lang/String; + public fun getXForwardedFor ()Ljava/lang/String; + public fun getXForwardedHost ()Ljava/lang/String; + public fun getXForwardedPort ()Ljava/lang/String; + public fun getXForwardedProto ()Ljava/lang/String; + public fun getXRealIp ()Ljava/lang/String; +} + +public class datadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopPathwayContext : datadog/trace/bootstrap/instrumentation/api/PathwayContext { + public static final field INSTANCE Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopPathwayContext; + public fun ()V + public fun encode ()[B + public fun getHash ()J + public fun getSavedStats ()Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint; + public fun isStarted ()Z + public fun saveStats (Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint;)V + public fun setCheckpoint (Ljava/util/LinkedHashMap;Ljava/util/function/Consumer;)V + public fun setCheckpoint (Ljava/util/LinkedHashMap;Ljava/util/function/Consumer;J)V + public fun setCheckpoint (Ljava/util/LinkedHashMap;Ljava/util/function/Consumer;JJ)V + public fun strEncode ()Ljava/lang/String; +} + +public final class datadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopTraceConfig : datadog/trace/api/TraceConfig { + public static final field INSTANCE Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$NoopTraceConfig; + public fun ()V + public fun getBaggageMapping ()Ljava/util/Map; + public fun getRequestHeaderTags ()Ljava/util/Map; + public fun getResponseHeaderTags ()Ljava/util/Map; + public fun getServiceMapping ()Ljava/util/Map; + public fun getSpanSamplingRules ()Ljava/util/List; + public fun getTraceSampleRate ()Ljava/lang/Double; + public fun getTraceSamplingRules ()Ljava/util/List; + public fun isDataStreamsEnabled ()Z + public fun isLogsInjectionEnabled ()Z + public fun isRuntimeMetricsEnabled ()Z +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder { + public abstract fun asChildOf (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun ignoreActiveSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun start ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun withErrorFlag ()Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun withLink (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun withRequestContextData (Ldatadog/trace/api/gateway/RequestContextSlot;Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun withResourceName (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun withServiceName (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun withSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun withStartTimestamp (J)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun withTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun withTag (Ljava/lang/String;Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun withTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun withTag (Ljava/lang/String;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AgentTracer$TracerAPI : datadog/trace/api/EndpointCheckpointer, datadog/trace/api/Tracer, datadog/trace/api/internal/InternalTracer, datadog/trace/bootstrap/instrumentation/api/ScopeStateAware { + public abstract fun activateNext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public abstract fun activateSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public abstract fun activateSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public abstract fun activeScope ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public abstract fun activeSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun addScopeListener (Ldatadog/trace/api/scopemanager/ScopeListener;)V + public fun buildSpan (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun buildSpan (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public abstract fun captureSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation; + public abstract fun captureTraceConfig ()Ldatadog/trace/api/TraceConfig; + public abstract fun close ()V + public abstract fun closePrevious (Z)V + public abstract fun getCallbackProvider (Ldatadog/trace/api/gateway/RequestContextSlot;)Ldatadog/trace/api/gateway/CallbackProvider; + public abstract fun getDataStreamsMonitoring ()Ldatadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring; + public synthetic fun getProfilingContext ()Ldatadog/trace/api/profiling/Profiling; + public abstract fun getProfilingContext ()Ldatadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration; + public abstract fun getSpanId (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ljava/lang/String; + public abstract fun getSubscriptionService (Ldatadog/trace/api/gateway/RequestContextSlot;)Ldatadog/trace/api/gateway/SubscriptionService; + public abstract fun getTimer ()Ldatadog/trace/api/profiling/Timer; + public abstract fun getTraceId (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ljava/lang/String; + public abstract fun getUniversalCallbackProvider ()Ldatadog/trace/api/gateway/CallbackProvider; + public abstract fun newHistogram (DI)Ldatadog/trace/bootstrap/instrumentation/api/AgentHistogram; + public abstract fun noopSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun notifyExtensionEnd (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Z)V + public abstract fun notifyExtensionStart (Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; + public abstract fun propagate ()Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation; + public abstract fun registerCheckpointer (Ldatadog/trace/api/EndpointCheckpointer;)V + public abstract fun registerTimer (Ldatadog/trace/api/profiling/Timer;)V + public abstract fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public abstract fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/AttachableWrapper { + public abstract fun attachWrapper (Ljava/lang/Object;)V + public abstract fun getWrapper ()Ljava/lang/Object; +} + +public class datadog/trace/bootstrap/instrumentation/api/Backlog : datadog/trace/bootstrap/instrumentation/api/InboxItem { + public fun (Ljava/util/List;JJ)V + public fun getSortedTags ()Ljava/util/List; + public fun getTimestampNanos ()J + public fun getValue ()J +} + +public class datadog/trace/bootstrap/instrumentation/api/ErrorPriorities { + public static final field DEFAULT B + public static final field HTTP_SERVER_DECORATOR B + public static final field UNSET B + public fun ()V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/InboxItem { +} + +public class datadog/trace/bootstrap/instrumentation/api/InstrumentationTags { + public static final field AMQP_COMMAND Ljava/lang/String; + public static final field AMQP_DELIVERY_MODE Ljava/lang/String; + public static final field AMQP_EXCHANGE Ljava/lang/String; + public static final field AMQP_QUEUE Ljava/lang/String; + public static final field AMQP_ROUTING_KEY Ljava/lang/String; + public static final field AWS_AGENT Ljava/lang/String; + public static final field AWS_BUCKET_NAME Ljava/lang/String; + public static final field AWS_ENDPOINT Ljava/lang/String; + public static final field AWS_OPERATION Ljava/lang/String; + public static final field AWS_QUEUE_NAME Ljava/lang/String; + public static final field AWS_QUEUE_URL Ljava/lang/String; + public static final field AWS_REQUEST_ID Ljava/lang/String; + public static final field AWS_SERVICE Ljava/lang/String; + public static final field AWS_STORAGE_CLASS Ljava/lang/String; + public static final field AWS_STREAM_NAME Ljava/lang/String; + public static final field AWS_TABLE_NAME Ljava/lang/String; + public static final field AWS_TOPIC_NAME Ljava/lang/String; + public static final field BUCKET Ljava/lang/String; + public static final field BUCKET_NAME Ljava/lang/String; + public static final field CASSANDRA_CONTACT_POINTS Ljava/lang/String; + public static final field CONSUMER_GROUP Ljava/lang/String; + public static final field COUCHBASE_OPERATION_ID Ljava/lang/String; + public static final field COUCHBASE_SEED_NODES Ljava/lang/String; + public static final field DBM_TRACE_INJECTED Ljava/lang/String; + public static final field DB_COMMAND_CANCELLED Ljava/lang/String; + public static final field DB_COMMAND_RESULTS_COUNT Ljava/lang/String; + public static final field DB_REDIS_DBINDEX Ljava/lang/String; + public static final field DD_MEASURED Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field DD_PARTIAL_VERSION Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field DD_TOP_LEVEL Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field DD_WAS_LONG_RUNNING Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field ELASTICSEARCH_ID Ljava/lang/String; + public static final field ELASTICSEARCH_NODE_CLUSTER_NAME Ljava/lang/String; + public static final field ELASTICSEARCH_NODE_FAILURES Ljava/lang/String; + public static final field ELASTICSEARCH_REQUEST_INDICES Ljava/lang/String; + public static final field ELASTICSEARCH_REQUEST_SEARCH_TYPES Ljava/lang/String; + public static final field ELASTICSEARCH_REQUEST_WRITE_ROUTING Ljava/lang/String; + public static final field ELASTICSEARCH_REQUEST_WRITE_TYPE Ljava/lang/String; + public static final field ELASTICSEARCH_REQUEST_WRITE_VERSION Ljava/lang/String; + public static final field ELASTICSEARCH_RESPONSE_STATUS Ljava/lang/String; + public static final field ELASTICSEARCH_SHARD_BROADCAST_FAILED Ljava/lang/String; + public static final field ELASTICSEARCH_SHARD_BROADCAST_SUCCESSFUL Ljava/lang/String; + public static final field ELASTICSEARCH_SHARD_BROADCAST_TOTAL Ljava/lang/String; + public static final field ELASTICSEARCH_SHARD_BULK_ID Ljava/lang/String; + public static final field ELASTICSEARCH_SHARD_BULK_INDEX Ljava/lang/String; + public static final field ELASTICSEARCH_SHARD_REPLICATION_FAILED Ljava/lang/String; + public static final field ELASTICSEARCH_SHARD_REPLICATION_TOTAL Ljava/lang/String; + public static final field ELASTICSEARCH_TYPE Ljava/lang/String; + public static final field ELASTICSEARCH_VERSION Ljava/lang/String; + public static final field EVENT Ljava/lang/String; + public static final field HANDLER_TYPE Ljava/lang/String; + public static final field HYSTRIX_CIRCUIT_OPEN Ljava/lang/String; + public static final field HYSTRIX_COMMAND Ljava/lang/String; + public static final field HYSTRIX_GROUP Ljava/lang/String; + public static final field JMS_PRODUCE Ljava/lang/String; + public static final field JSP_CLASSFQCN Ljava/lang/String; + public static final field JSP_COMPILER Ljava/lang/String; + public static final field JSP_FORWARD_ORIGIN Ljava/lang/String; + public static final field KAFKA_BOOTSTRAP_SERVERS Ljava/lang/String; + public static final field MESSAGE Ljava/lang/String; + public static final field MESSAGE_SIZE Ljava/lang/String; + public static final field MESSAGE_TYPE Ljava/lang/String; + public static final field OFFSET Ljava/lang/String; + public static final field PARTITION Ljava/lang/String; + public static final field PROCESSOR_NAME Ljava/lang/String; + public static final field QUARTZ_JOB_GROUP Ljava/lang/String; + public static final field QUARTZ_JOB_NAME Ljava/lang/String; + public static final field QUARTZ_TRIGGER_GROUP Ljava/lang/String; + public static final field QUARTZ_TRIGGER_NAME Ljava/lang/String; + public static final field QUEUE_NAME Ljava/lang/String; + public static final field RECORD_END_TO_END_DURATION_MS Ljava/lang/String; + public static final field RECORD_QUEUE_TIME_MS Ljava/lang/String; + public static final field REQUEST_PREDICATE Ljava/lang/String; + public static final field SERVLET_CONTEXT Ljava/lang/String; + public static final field SERVLET_DISPATCH Ljava/lang/String; + public static final field SERVLET_PATH Ljava/lang/String; + public static final field STATUS_CODE Ljava/lang/String; + public static final field STATUS_DESCRIPTION Ljava/lang/String; + public static final field STREAM_NAME Ljava/lang/String; + public static final field TABLE_NAME Ljava/lang/String; + public static final field TIMEOUT Ljava/lang/String; + public static final field TOMBSTONE Ljava/lang/String; + public static final field TOPIC_NAME Ljava/lang/String; + public static final field TOP_LEVEL_AWS_SERVICE Ljava/lang/String; + public static final field TWILIO_ACCOUNT Ljava/lang/String; + public static final field TWILIO_PARENT_SID Ljava/lang/String; + public static final field TWILIO_SID Ljava/lang/String; + public static final field TWILIO_STATUS Ljava/lang/String; + public static final field TWILIO_TYPE Ljava/lang/String; + public static final field VIEW_NAME Ljava/lang/String; + public static final field VIEW_TYPE Ljava/lang/String; + public fun ()V +} + +public class datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes { + public static final field AEROSPIKE Ljava/lang/CharSequence; + public static final field CACHE Ljava/lang/CharSequence; + public static final field CASSANDRA Ljava/lang/CharSequence; + public static final field COUCHBASE Ljava/lang/CharSequence; + public static final field DATANUCLEUS Ljava/lang/CharSequence; + public static final field ELASTICSEARCH Ljava/lang/CharSequence; + public static final field GRAPHQL Ljava/lang/CharSequence; + public static final field HIBERNATE Ljava/lang/CharSequence; + public static final field HTTP_CLIENT Ljava/lang/CharSequence; + public static final field HTTP_SERVER Ljava/lang/CharSequence; + public static final field MEMCACHED Ljava/lang/CharSequence; + public static final field MESSAGE_BROKER Ljava/lang/CharSequence; + public static final field MESSAGE_CLIENT Ljava/lang/CharSequence; + public static final field MESSAGE_CONSUMER Ljava/lang/CharSequence; + public static final field MESSAGE_PRODUCER Ljava/lang/CharSequence; + public static final field MONGO Ljava/lang/CharSequence; + public static final field OPENSEARCH Ljava/lang/CharSequence; + public static final field REDIS Ljava/lang/CharSequence; + public static final field RPC Ljava/lang/CharSequence; + public static final field SOAP Ljava/lang/CharSequence; + public static final field SQL Ljava/lang/CharSequence; + public static final field TEST Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field TEST_MODULE_END Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field TEST_SESSION_END Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field TEST_SUITE_END Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field VULNERABILITY Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun ()V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/PathwayContext { + public static final field DATADOG_KEY Ljava/lang/String; + public static final field PROPAGATION_KEY Ljava/lang/String; + public static final field PROPAGATION_KEY_BASE64 Ljava/lang/String; + public abstract fun encode ()[B + public abstract fun getHash ()J + public abstract fun getSavedStats ()Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint; + public abstract fun isStarted ()Z + public abstract fun saveStats (Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint;)V + public abstract fun setCheckpoint (Ljava/util/LinkedHashMap;Ljava/util/function/Consumer;)V + public abstract fun setCheckpoint (Ljava/util/LinkedHashMap;Ljava/util/function/Consumer;J)V + public abstract fun setCheckpoint (Ljava/util/LinkedHashMap;Ljava/util/function/Consumer;JJ)V + public abstract fun strEncode ()Ljava/lang/String; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/ProfilerContext { + public abstract fun getEncodedOperationName ()I + public abstract fun getEncodedResourceName ()I + public abstract fun getOperationName ()Ljava/lang/CharSequence; + public abstract fun getResourceName ()Ljava/lang/CharSequence; + public abstract fun getRootSpanId ()J + public abstract fun getSpanId ()J +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration : datadog/trace/api/profiling/Profiling { + public fun encode (Ljava/lang/CharSequence;)I + public fun encodeOperationName (Ljava/lang/CharSequence;)I + public fun encodeResourceName (Ljava/lang/CharSequence;)I + public abstract fun name ()Ljava/lang/String; + public fun newScopeState (Ldatadog/trace/bootstrap/instrumentation/api/ProfilerContext;)Ldatadog/trace/api/Stateful; + public fun onAttach ()V + public fun onDetach ()V + public fun onStart ()V +} + +public final class datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration$NoOp : datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration { + public static final field INSTANCE Ldatadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration; + public fun ()V + public fun createContextAttribute (Ljava/lang/String;)Ldatadog/trace/api/profiling/ProfilingContextAttribute; + public fun name ()Ljava/lang/String; + public fun newScope ()Ldatadog/trace/api/profiling/ProfilingScope; + public fun onAttach ()V + public fun onDetach ()V +} + +public class datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities { + public static final field DEFAULT B + public static final field HTTP_404 B + public static final field HTTP_CLIENT_CONFIG_PATTERN_MATCH B + public static final field HTTP_FRAMEWORK_ROUTE B + public static final field HTTP_PATH_NORMALIZER B + public static final field HTTP_SERVER_CONFIG_PATTERN_MATCH B + public static final field MANUAL_INSTRUMENTATION B + public static final field RPC_COMMAND_NAME B + public static final field TAG_INTERCEPTOR B + public fun ()V +} + +public class datadog/trace/bootstrap/instrumentation/api/SamplerConstants { + public static final field DROP Ljava/lang/String; + public static final field KEEP Ljava/lang/String; +} + +public final class datadog/trace/bootstrap/instrumentation/api/ScopeSource : java/lang/Enum { + public static final field INSTRUMENTATION Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource; + public static final field ITERATION Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource; + public static final field MANUAL Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource; + public fun id ()B + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource; + public static fun values ()[Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/ScopeState { + public abstract fun activate ()V + public abstract fun fetchFromActive ()V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/ScopeStateAware { + public abstract fun newScopeState ()Ldatadog/trace/bootstrap/instrumentation/api/ScopeState; +} + +public class datadog/trace/bootstrap/instrumentation/api/SpanLink : datadog/trace/bootstrap/instrumentation/api/AgentSpanLink { + protected fun (Ldatadog/trace/api/DDTraceId;JBLjava/lang/String;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink$Attributes;)V + public fun attributes ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink$Attributes; + public static fun from (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLink; + public static fun from (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;BLjava/lang/String;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink$Attributes;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLink; + public fun spanId ()J + public fun toString ()Ljava/lang/String; + public fun traceFlags ()B + public fun traceId ()Ldatadog/trace/api/DDTraceId; + public fun traceState ()Ljava/lang/String; +} + +public class datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes : datadog/trace/bootstrap/instrumentation/api/AgentSpanLink$Attributes { + public static final field EMPTY Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink$Attributes; + protected fun (Ljava/util/Map;)V + public fun asMap ()Ljava/util/Map; + public static fun builder ()Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder; + public static fun fromMap (Ljava/util/Map;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes; + public fun isEmpty ()Z + public fun toString ()Ljava/lang/String; +} + +public class datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder { + protected fun ()V + public fun build ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink$Attributes; + public fun put (Ljava/lang/String;D)Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder; + public fun put (Ljava/lang/String;J)Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder; + public fun put (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder; + public fun put (Ljava/lang/String;Z)Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder; + protected fun putArray (Ljava/lang/String;Ljava/util/List;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder; + public fun putBooleanArray (Ljava/lang/String;Ljava/util/List;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder; + public fun putDoubleArray (Ljava/lang/String;Ljava/util/List;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder; + public fun putLongArray (Ljava/lang/String;Ljava/util/List;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder; + public fun putStringArray (Ljava/lang/String;Ljava/util/List;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes$Builder; +} + +public class datadog/trace/bootstrap/instrumentation/api/StatsPoint : datadog/trace/bootstrap/instrumentation/api/InboxItem { + public fun (Ljava/util/List;JJJJJJ)V + public fun getEdgeLatencyNano ()J + public fun getEdgeTags ()Ljava/util/List; + public fun getHash ()J + public fun getParentHash ()J + public fun getPathwayLatencyNano ()J + public fun getPayloadSizeBytes ()J + public fun getTimestampNanos ()J + public fun toString ()Ljava/lang/String; +} + +public class datadog/trace/bootstrap/instrumentation/api/TagContext : datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context$Extracted { + public fun ()V + public fun (Ljava/lang/CharSequence;Ljava/util/Map;Ldatadog/trace/bootstrap/instrumentation/api/TagContext$HttpHeaders;Ljava/util/Map;ILdatadog/trace/api/TraceConfig;Ldatadog/trace/api/TracePropagationStyle;)V + public fun (Ljava/lang/String;Ljava/util/Map;)V + public fun addTerminatedContextLink (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink;)V + public fun baggageItems ()Ljava/lang/Iterable; + public final fun getBaggage ()Ljava/util/Map; + public fun getCfConnectingIp ()Ljava/lang/String; + public fun getCfConnectingIpv6 ()Ljava/lang/String; + public fun getCiVisibilityContextData ()Ljava/lang/Object; + public fun getCustomIpHeader ()Ljava/lang/String; + public fun getFastlyClientIp ()Ljava/lang/String; + public fun getForwarded ()Ljava/lang/String; + public fun getForwardedFor ()Ljava/lang/String; + public final fun getOrigin ()Ljava/lang/CharSequence; + public fun getPathwayContext ()Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext; + public fun getPropagationStyle ()Ldatadog/trace/api/TracePropagationStyle; + public final fun getRequestContextDataAppSec ()Ljava/lang/Object; + public final fun getRequestContextDataIast ()Ljava/lang/Object; + public final fun getSamplingPriority ()I + public fun getSpanId ()J + public final fun getTags ()Ljava/util/Map; + public fun getTerminatedContextLinks ()Ljava/util/List; + public final fun getTrace ()Ldatadog/trace/bootstrap/instrumentation/api/AgentTrace; + public fun getTraceConfig ()Ldatadog/trace/api/TraceConfig; + public fun getTraceId ()Ldatadog/trace/api/DDTraceId; + public fun getTrueClientIp ()Ljava/lang/String; + public fun getUserAgent ()Ljava/lang/String; + public fun getXClientIp ()Ljava/lang/String; + public fun getXClusterClientIp ()Ljava/lang/String; + public fun getXForwarded ()Ljava/lang/String; + public fun getXForwardedFor ()Ljava/lang/String; + public fun getXForwardedHost ()Ljava/lang/String; + public fun getXForwardedPort ()Ljava/lang/String; + public fun getXForwardedProto ()Ljava/lang/String; + public fun getXRealIp ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; + public fun withCiVisibilityContextData (Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/TagContext; + public fun withPathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext;)Ldatadog/trace/bootstrap/instrumentation/api/TagContext; + public final fun withRequestContextDataAppSec (Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/TagContext; + public final fun withRequestContextDataIast (Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/TagContext; +} + +public class datadog/trace/bootstrap/instrumentation/api/TagContext$HttpHeaders { + public field cfConnectingIp Ljava/lang/String; + public field cfConnectingIpv6 Ljava/lang/String; + public field customIpHeader Ljava/lang/String; + public field fastlyClientIp Ljava/lang/String; + public field forwarded Ljava/lang/String; + public field forwardedFor Ljava/lang/String; + public field trueClientIp Ljava/lang/String; + public field userAgent Ljava/lang/String; + public field xClientIp Ljava/lang/String; + public field xClusterClientIp Ljava/lang/String; + public field xForwarded Ljava/lang/String; + public field xForwardedFor Ljava/lang/String; + public field xForwardedHost Ljava/lang/String; + public field xForwardedPort Ljava/lang/String; + public field xForwardedProto Ljava/lang/String; + public field xRealIp Ljava/lang/String; + public fun ()V +} + +public class datadog/trace/bootstrap/instrumentation/api/Tags { + public static final field CI_JOB_NAME Ljava/lang/String; + public static final field CI_JOB_URL Ljava/lang/String; + public static final field CI_NODE_LABELS Ljava/lang/String; + public static final field CI_NODE_NAME Ljava/lang/String; + public static final field CI_PIPELINE_ID Ljava/lang/String; + public static final field CI_PIPELINE_NAME Ljava/lang/String; + public static final field CI_PIPELINE_NUMBER Ljava/lang/String; + public static final field CI_PIPELINE_URL Ljava/lang/String; + public static final field CI_PROVIDER_NAME Ljava/lang/String; + public static final field CI_STAGE_NAME Ljava/lang/String; + public static final field CI_WORKSPACE_PATH Ljava/lang/String; + public static final field COMPONENT Ljava/lang/String; + public static final field DB_INSTANCE Ljava/lang/String; + public static final field DB_OPERATION Ljava/lang/String; + public static final field DB_STATEMENT Ljava/lang/String; + public static final field DB_TYPE Ljava/lang/String; + public static final field DB_USER Ljava/lang/String; + public static final field DD_ENV Ljava/lang/String; + public static final field DD_SERVICE Ljava/lang/String; + public static final field DD_VERSION Ljava/lang/String; + public static final field ENV Ljava/lang/String; + public static final field ERROR Ljava/lang/String; + public static final field GIT_BRANCH Ljava/lang/String; + public static final field GIT_COMMIT_AUTHOR_DATE Ljava/lang/String; + public static final field GIT_COMMIT_AUTHOR_EMAIL Ljava/lang/String; + public static final field GIT_COMMIT_AUTHOR_NAME Ljava/lang/String; + public static final field GIT_COMMIT_COMMITTER_DATE Ljava/lang/String; + public static final field GIT_COMMIT_COMMITTER_EMAIL Ljava/lang/String; + public static final field GIT_COMMIT_COMMITTER_NAME Ljava/lang/String; + public static final field GIT_COMMIT_MESSAGE Ljava/lang/String; + public static final field GIT_COMMIT_SHA Ljava/lang/String; + public static final field GIT_REPOSITORY_URL Ljava/lang/String; + public static final field GIT_TAG Ljava/lang/String; + public static final field HTTP_CLIENT_IP Ljava/lang/String; + public static final field HTTP_FORWARDED Ljava/lang/String; + public static final field HTTP_FORWARDED_HOST Ljava/lang/String; + public static final field HTTP_FORWARDED_IP Ljava/lang/String; + public static final field HTTP_FORWARDED_PORT Ljava/lang/String; + public static final field HTTP_FORWARDED_PROTO Ljava/lang/String; + public static final field HTTP_HOSTNAME Ljava/lang/String; + public static final field HTTP_METHOD Ljava/lang/String; + public static final field HTTP_ROUTE Ljava/lang/String; + public static final field HTTP_STATUS Ljava/lang/String; + public static final field HTTP_URL Ljava/lang/String; + public static final field HTTP_USER_AGENT Ljava/lang/String; + public static final field MESSAGE_BUS_DESTINATION Ljava/lang/String; + public static final field OS_ARCHITECTURE Ljava/lang/String; + public static final field OS_PLATFORM Ljava/lang/String; + public static final field OS_VERSION Ljava/lang/String; + public static final field PEER_HOSTNAME Ljava/lang/String; + public static final field PEER_HOST_IPV4 Ljava/lang/String; + public static final field PEER_HOST_IPV6 Ljava/lang/String; + public static final field PEER_PORT Ljava/lang/String; + public static final field PEER_SERVICE Ljava/lang/String; + public static final field RPC_SERVICE Ljava/lang/String; + public static final field RUNTIME_NAME Ljava/lang/String; + public static final field RUNTIME_VENDOR Ljava/lang/String; + public static final field RUNTIME_VERSION Ljava/lang/String; + public static final field SAMPLING_PRIORITY Ljava/lang/String; + public static final field SPAN_KIND Ljava/lang/String; + public static final field SPAN_KIND_BROKER Ljava/lang/String; + public static final field SPAN_KIND_CLIENT Ljava/lang/String; + public static final field SPAN_KIND_CONSUMER Ljava/lang/String; + public static final field SPAN_KIND_PRODUCER Ljava/lang/String; + public static final field SPAN_KIND_SERVER Ljava/lang/String; + public static final field SPAN_KIND_TEST Ljava/lang/String; + public static final field SPAN_KIND_TEST_MODULE Ljava/lang/String; + public static final field SPAN_KIND_TEST_SESSION Ljava/lang/String; + public static final field SPAN_KIND_TEST_SUITE Ljava/lang/String; + public static final field TEST_CODEOWNERS Ljava/lang/String; + public static final field TEST_CODE_COVERAGE_ENABLED Ljava/lang/String; + public static final field TEST_CODE_COVERAGE_LINES_PERCENTAGE Ljava/lang/String; + public static final field TEST_COMMAND Ljava/lang/String; + public static final field TEST_EXECUTION Ljava/lang/String; + public static final field TEST_FRAMEWORK Ljava/lang/String; + public static final field TEST_FRAMEWORK_VERSION Ljava/lang/String; + public static final field TEST_GRADLE_NESTED_BUILD Ljava/lang/String; + public static final field TEST_ITR_FORCED_RUN Ljava/lang/String; + public static final field TEST_ITR_TESTS_SKIPPING_COUNT Ljava/lang/String; + public static final field TEST_ITR_TESTS_SKIPPING_ENABLED Ljava/lang/String; + public static final field TEST_ITR_TESTS_SKIPPING_TYPE Ljava/lang/String; + public static final field TEST_ITR_UNSKIPPABLE Ljava/lang/String; + public static final field TEST_MODULE Ljava/lang/String; + public static final field TEST_MODULE_ID Ljava/lang/String; + public static final field TEST_NAME Ljava/lang/String; + public static final field TEST_PARAMETERS Ljava/lang/String; + public static final field TEST_SESSION_ID Ljava/lang/String; + public static final field TEST_SKIPPED_BY_ITR Ljava/lang/String; + public static final field TEST_SKIP_REASON Ljava/lang/String; + public static final field TEST_SOURCE_CLASS Ljava/lang/String; + public static final field TEST_SOURCE_END Ljava/lang/String; + public static final field TEST_SOURCE_FILE Ljava/lang/String; + public static final field TEST_SOURCE_METHOD Ljava/lang/String; + public static final field TEST_SOURCE_START Ljava/lang/String; + public static final field TEST_STATUS Ljava/lang/String; + public static final field TEST_SUITE Ljava/lang/String; + public static final field TEST_SUITE_ID Ljava/lang/String; + public static final field TEST_TOOLCHAIN Ljava/lang/String; + public static final field TEST_TRAITS Ljava/lang/String; + public static final field TEST_TYPE Ljava/lang/String; + public fun ()V +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/TaskWrapper { + public abstract fun $$DD$$__unwrap ()Ljava/lang/Object; + public static fun getUnwrappedType (Ljava/lang/Object;)Ljava/lang/Class; +} + +public abstract interface class datadog/trace/bootstrap/instrumentation/api/URIDataAdapter { + public abstract fun fragment ()Ljava/lang/String; + public abstract fun hasPlusEncodedSpaces ()Z + public abstract fun host ()Ljava/lang/String; + public abstract fun isValid ()Z + public abstract fun path ()Ljava/lang/String; + public abstract fun port ()I + public abstract fun query ()Ljava/lang/String; + public abstract fun raw ()Ljava/lang/String; + public abstract fun rawPath ()Ljava/lang/String; + public abstract fun rawQuery ()Ljava/lang/String; + public abstract fun scheme ()Ljava/lang/String; + public abstract fun supportsRaw ()Z +} + +public abstract class datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase : datadog/trace/bootstrap/instrumentation/api/URIDataAdapter { + protected static final field UNINITIALIZED Ljava/lang/String; + public fun ()V + public static fun fromURI (Ljava/lang/String;Ljava/util/function/Function;)Ldatadog/trace/bootstrap/instrumentation/api/URIDataAdapter; + public fun hasPlusEncodedSpaces ()Z + public fun isValid ()Z + public fun raw ()Ljava/lang/String; +} + +public class datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter : datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase { + public fun (Ljava/net/URI;)V + public fun fragment ()Ljava/lang/String; + public fun host ()Ljava/lang/String; + public fun path ()Ljava/lang/String; + public fun port ()I + public fun query ()Ljava/lang/String; + public fun rawPath ()Ljava/lang/String; + public fun rawQuery ()Ljava/lang/String; + public fun scheme ()Ljava/lang/String; + public fun supportsRaw ()Z +} + +public abstract class datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter : datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase { + public fun ()V + protected abstract fun innerRawPath ()Ljava/lang/String; + protected abstract fun innerRawQuery ()Ljava/lang/String; + public final fun path ()Ljava/lang/String; + public final fun query ()Ljava/lang/String; + public final fun rawPath ()Ljava/lang/String; + public final fun rawQuery ()Ljava/lang/String; + public final fun supportsRaw ()Z +} + +public class datadog/trace/bootstrap/instrumentation/api/URIUtils { + public static fun buildURL (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String; + public static fun decode (Ljava/lang/String;)Ljava/lang/String; + public static fun decode (Ljava/lang/String;Z)Ljava/lang/String; + public static fun lazyInvalidUrl (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/URIUtils$LazyUrl; + public static fun lazyValidURL (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/URIUtils$LazyUrl; + public static fun safeConcat (Ljava/lang/String;Ljava/lang/String;)Ljava/net/URI; + public static fun safeParse (Ljava/lang/String;)Ljava/net/URI; + public static fun urlFileName (Ljava/lang/String;)Ljava/lang/String; +} + +public abstract class datadog/trace/bootstrap/instrumentation/api/URIUtils$LazyUrl : java/lang/CharSequence, java/util/function/Supplier { + protected field lazy Ljava/lang/String; + protected fun (Ljava/lang/String;)V + public fun charAt (I)C + public fun hashCode ()I + public fun length ()I + public abstract fun path ()Ljava/lang/String; + public fun subSequence (II)Ljava/lang/CharSequence; + public fun toString ()Ljava/lang/String; +} + +public final class datadog/trace/bootstrap/instrumentation/api/UTF8BytesString : java/lang/CharSequence { + public static final field EMPTY Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun charAt (I)C + public static fun create (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static fun create (Ljava/lang/String;[B)Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static fun create (Ljava/nio/ByteBuffer;)Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static fun create ([B)Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun encodedLength ()I + public fun equals (Ljava/lang/Object;)Z + public fun getUtf8Bytes ()[B + public fun hashCode ()I + public fun length ()I + public fun subSequence (II)Ljava/lang/CharSequence; + public fun toString ()Ljava/lang/String; + public fun transferTo (Ljava/nio/ByteBuffer;)V +} + +public class datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter : datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase { + public fun (Ljava/lang/String;)V + public fun fragment ()Ljava/lang/String; + public fun host ()Ljava/lang/String; + public fun isValid ()Z + public fun path ()Ljava/lang/String; + public fun port ()I + public fun query ()Ljava/lang/String; + public fun raw ()Ljava/lang/String; + public fun rawPath ()Ljava/lang/String; + public fun rawQuery ()Ljava/lang/String; + public fun scheme ()Ljava/lang/String; + public fun supportsRaw ()Z +} + +public final class datadog/trace/bootstrap/instrumentation/api/WriterConstants { + public static final field DD_AGENT_WRITER_TYPE Ljava/lang/String; + public static final field DD_INTAKE_WRITER_TYPE Ljava/lang/String; + public static final field LOGGING_WRITER_TYPE Ljava/lang/String; + public static final field MULTI_WRITER_TYPE Ljava/lang/String; + public static final field PRINTING_WRITER_TYPE Ljava/lang/String; + public static final field TRACE_STRUCTURE_WRITER_TYPE Ljava/lang/String; +} + +public class datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor : datadog/trace/api/interceptor/AbstractTraceInterceptor { + public static final field INSTANCE Ldatadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor; + protected fun (Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority;)V + public fun onTraceComplete (Ljava/util/Collection;)Ljava/util/Collection; +} + +public class datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor : datadog/trace/api/interceptor/AbstractTraceInterceptor { + public static final field INSTANCE Ldatadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor; + protected fun (Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority;)V + public fun onTraceComplete (Ljava/util/Collection;)Ljava/util/Collection; +} + +public class datadog/trace/common/GitMetadataTraceInterceptor : datadog/trace/api/interceptor/AbstractTraceInterceptor { + public static final field INSTANCE Ldatadog/trace/api/interceptor/TraceInterceptor; + protected fun (Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority;)V + public fun onTraceComplete (Ljava/util/Collection;)Ljava/util/Collection; +} + +public final class datadog/trace/common/metrics/AggregateMetric { + public fun ()V + public fun clear ()V + public fun getDuration ()J + public fun getErrorCount ()I + public fun getErrorLatencies ()Ldatadog/trace/core/histogram/Histogram; + public fun getHitCount ()I + public fun getOkLatencies ()Ldatadog/trace/core/histogram/Histogram; + public fun getTopLevelCount ()I + public fun recordDurations (ILjava/util/concurrent/atomic/AtomicLongArray;)Ldatadog/trace/common/metrics/AggregateMetric; +} + +public final class datadog/trace/common/metrics/Batch : datadog/trace/common/metrics/InboxItem { + public fun add (JJ)Z + public fun contributeTo (Ldatadog/trace/common/metrics/AggregateMetric;)V + public fun getKey ()Ldatadog/trace/common/metrics/MetricKey; + public fun isUsed ()Z + public fun reset (Ldatadog/trace/common/metrics/MetricKey;)Ldatadog/trace/common/metrics/Batch; +} + +public abstract interface class datadog/trace/common/metrics/EventListener { + public abstract fun onEvent (Ldatadog/trace/common/metrics/EventListener$EventType;Ljava/lang/String;)V +} + +public final class datadog/trace/common/metrics/EventListener$EventType : java/lang/Enum { + public static final field BAD_PAYLOAD Ldatadog/trace/common/metrics/EventListener$EventType; + public static final field DOWNGRADED Ldatadog/trace/common/metrics/EventListener$EventType; + public static final field ERROR Ldatadog/trace/common/metrics/EventListener$EventType; + public static final field OK Ldatadog/trace/common/metrics/EventListener$EventType; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/common/metrics/EventListener$EventType; + public static fun values ()[Ldatadog/trace/common/metrics/EventListener$EventType; +} + +public final class datadog/trace/common/metrics/MetricKey { + public fun (Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;IZ)V + public fun equals (Ljava/lang/Object;)Z + public fun getHttpStatusCode ()I + public fun getOperationName ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun getResource ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun getService ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun getType ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun hashCode ()I + public fun isSynthetics ()Z +} + +public abstract interface class datadog/trace/common/metrics/MetricWriter { + public abstract fun add (Ldatadog/trace/common/metrics/MetricKey;Ldatadog/trace/common/metrics/AggregateMetric;)V + public abstract fun finishBucket ()V + public abstract fun reset ()V + public abstract fun startBucket (IJJ)V +} + +public abstract interface class datadog/trace/common/metrics/MetricsAggregator : java/lang/AutoCloseable { + public abstract fun close ()V + public abstract fun forceReport ()Ljava/util/concurrent/Future; + public abstract fun publish (Ljava/util/List;)Z + public abstract fun report ()Z + public abstract fun start ()V +} + +public final class datadog/trace/common/metrics/NoOpMetricsAggregator : datadog/trace/common/metrics/MetricsAggregator { + public static final field INSTANCE Ldatadog/trace/common/metrics/NoOpMetricsAggregator; + public fun ()V + public fun close ()V + public fun forceReport ()Ljava/util/concurrent/Future; + public fun publish (Ljava/util/List;)Z + public fun report ()Z + public fun start ()V +} + +public final class datadog/trace/common/metrics/SerializingMetricWriter : datadog/trace/common/metrics/MetricWriter { + public fun (Ldatadog/trace/api/WellKnownTags;Ldatadog/trace/common/metrics/Sink;)V + public fun (Ldatadog/trace/api/WellKnownTags;Ldatadog/trace/common/metrics/Sink;I)V + public fun add (Ldatadog/trace/common/metrics/MetricKey;Ldatadog/trace/common/metrics/AggregateMetric;)V + public fun finishBucket ()V + public fun reset ()V + public fun startBucket (IJJ)V +} + +public abstract interface class datadog/trace/common/metrics/Sink : datadog/trace/serialization/ByteBufferConsumer { + public abstract fun register (Ldatadog/trace/common/metrics/EventListener;)V +} + +public class datadog/trace/common/sampling/AllSampler : datadog/trace/common/sampling/Sampler { + public fun ()V + public fun sample (Ldatadog/trace/core/CoreSpan;)Z + public fun toString ()Ljava/lang/String; +} + +public abstract class datadog/trace/common/sampling/DeterministicSampler : datadog/trace/common/sampling/RateSampler { + public fun (D)V + public static fun cutoff (D)J + public fun getSampleRate ()D + protected abstract fun getSamplingId (Ldatadog/trace/core/CoreSpan;)J + public fun sample (Ldatadog/trace/core/CoreSpan;)Z +} + +public final class datadog/trace/common/sampling/DeterministicSampler$SpanSampler : datadog/trace/common/sampling/DeterministicSampler { + public fun (D)V +} + +public final class datadog/trace/common/sampling/DeterministicSampler$TraceSampler : datadog/trace/common/sampling/DeterministicSampler { + public fun (D)V +} + +public class datadog/trace/common/sampling/ForcePrioritySampler : datadog/trace/common/sampling/PrioritySampler, datadog/trace/common/sampling/Sampler { + public fun (II)V + public fun sample (Ldatadog/trace/core/CoreSpan;)Z + public fun setSamplingPriority (Ldatadog/trace/core/CoreSpan;)V +} + +public abstract interface class datadog/trace/common/sampling/PrioritySampler { + public abstract fun setSamplingPriority (Ldatadog/trace/core/CoreSpan;)V +} + +public class datadog/trace/common/sampling/PrioritySampling { + public static final field SAMPLER_DROP I + public static final field SAMPLER_KEEP I + public static final field UNSET I + public static final field USER_DROP I + public static final field USER_KEEP I +} + +public class datadog/trace/common/sampling/RateByServiceTraceSampler : datadog/trace/common/sampling/PrioritySampler, datadog/trace/common/sampling/Sampler, datadog/trace/common/writer/RemoteResponseListener { + public static final field SAMPLING_AGENT_RATE Ljava/lang/String; + public fun ()V + public fun onResponse (Ljava/lang/String;Ljava/util/Map;)V + public fun sample (Ldatadog/trace/core/CoreSpan;)Z + public fun setSamplingPriority (Ldatadog/trace/core/CoreSpan;)V +} + +public abstract interface class datadog/trace/common/sampling/RateSampler : datadog/trace/common/sampling/Sampler { + public abstract fun getSampleRate ()D +} + +public class datadog/trace/common/sampling/RuleBasedTraceSampler : datadog/trace/common/sampling/PrioritySampler, datadog/trace/common/sampling/Sampler { + public static final field SAMPLING_LIMIT_RATE Ljava/lang/String; + public static final field SAMPLING_RULE_RATE Ljava/lang/String; + public fun (Ljava/util/List;ILdatadog/trace/common/sampling/PrioritySampler;)V + public static fun build (Ldatadog/trace/common/sampling/TraceSamplingRules;Ljava/lang/Double;I)Ldatadog/trace/common/sampling/RuleBasedTraceSampler; + public static fun build (Ljava/util/Map;Ljava/util/Map;Ldatadog/trace/common/sampling/TraceSamplingRules;Ljava/lang/Double;I)Ldatadog/trace/common/sampling/RuleBasedTraceSampler; + public fun sample (Ldatadog/trace/core/CoreSpan;)Z + public fun setSamplingPriority (Ldatadog/trace/core/CoreSpan;)V +} + +public abstract interface class datadog/trace/common/sampling/Sampler { + public abstract fun sample (Ldatadog/trace/core/CoreSpan;)Z +} + +public final class datadog/trace/common/sampling/Sampler$Builder { + public static fun forConfig (Ldatadog/trace/api/Config;Ldatadog/trace/api/TraceConfig;)Ldatadog/trace/common/sampling/Sampler; + public static fun forConfig (Ljava/util/Properties;)Ldatadog/trace/common/sampling/Sampler; +} + +public abstract class datadog/trace/common/sampling/SamplingRule { + public fun (Ldatadog/trace/common/sampling/RateSampler;)V + public fun getSampler ()Ldatadog/trace/common/sampling/RateSampler; + public abstract fun matches (Ldatadog/trace/core/CoreSpan;)Z + public fun sample (Ldatadog/trace/core/CoreSpan;)Z +} + +public class datadog/trace/common/sampling/SamplingRule$AlwaysMatchesSamplingRule : datadog/trace/common/sampling/SamplingRule { + public fun (Ldatadog/trace/common/sampling/RateSampler;)V + public fun matches (Ldatadog/trace/core/CoreSpan;)Z +} + +public class datadog/trace/common/sampling/SamplingRule$OperationSamplingRule : datadog/trace/common/sampling/SamplingRule$PatternMatchSamplingRule { + public fun (Ljava/lang/String;Ldatadog/trace/common/sampling/RateSampler;)V + protected fun getRelevantString (Ldatadog/trace/core/CoreSpan;)Ljava/lang/CharSequence; +} + +public abstract class datadog/trace/common/sampling/SamplingRule$PatternMatchSamplingRule : datadog/trace/common/sampling/SamplingRule { + public fun (Ljava/lang/String;Ldatadog/trace/common/sampling/RateSampler;)V + protected abstract fun getRelevantString (Ldatadog/trace/core/CoreSpan;)Ljava/lang/CharSequence; + public fun matches (Ldatadog/trace/core/CoreSpan;)Z +} + +public class datadog/trace/common/sampling/SamplingRule$ServiceSamplingRule : datadog/trace/common/sampling/SamplingRule$PatternMatchSamplingRule { + public fun (Ljava/lang/String;Ldatadog/trace/common/sampling/RateSampler;)V + protected synthetic fun getRelevantString (Ldatadog/trace/core/CoreSpan;)Ljava/lang/CharSequence; + protected fun getRelevantString (Ldatadog/trace/core/CoreSpan;)Ljava/lang/String; +} + +public final class datadog/trace/common/sampling/SamplingRule$SpanSamplingRule : datadog/trace/common/sampling/SamplingRule { + public fun (Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/common/sampling/RateSampler;Ldatadog/trace/core/util/SimpleRateLimiter;)V + public fun getRateLimiter ()Ldatadog/trace/core/util/SimpleRateLimiter; + public fun matches (Ldatadog/trace/core/CoreSpan;)Z + public fun sample (Ldatadog/trace/core/CoreSpan;)Z +} + +public final class datadog/trace/common/sampling/SamplingRule$TraceSamplingRule : datadog/trace/common/sampling/SamplingRule { + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ldatadog/trace/common/sampling/RateSampler;)V + public fun matches (Ldatadog/trace/core/CoreSpan;)Z +} + +public abstract interface class datadog/trace/common/sampling/SingleSpanSampler { + public abstract fun setSamplingPriority (Ldatadog/trace/core/CoreSpan;)Z +} + +public final class datadog/trace/common/sampling/SingleSpanSampler$Builder { + public static fun forConfig (Ldatadog/trace/api/Config;)Ldatadog/trace/common/sampling/SingleSpanSampler; +} + +public final class datadog/trace/common/sampling/SingleSpanSampler$RuleBasedSingleSpanSampler : datadog/trace/common/sampling/SingleSpanSampler { + public fun (Ldatadog/trace/common/sampling/SpanSamplingRules;)V + public fun setSamplingPriority (Ldatadog/trace/core/CoreSpan;)Z +} + +public class datadog/trace/common/sampling/SpanSamplingRules { + public static final field EMPTY Ldatadog/trace/common/sampling/SpanSamplingRules; + public fun (Ljava/util/List;)V + public static fun deserialize (Ljava/lang/String;)Ldatadog/trace/common/sampling/SpanSamplingRules; + public static fun deserializeFile (Ljava/lang/String;)Ldatadog/trace/common/sampling/SpanSamplingRules; + public fun getRules ()Ljava/util/List; + public fun isEmpty ()Z +} + +public final class datadog/trace/common/sampling/SpanSamplingRules$Rule : datadog/trace/api/sampling/SamplingRule$SpanSamplingRule { + public static fun create (Ldatadog/trace/common/sampling/SpanSamplingRules$JsonRule;)Ldatadog/trace/common/sampling/SpanSamplingRules$Rule; + public fun getMaxPerSecond ()I + public fun getName ()Ljava/lang/String; + public fun getResource ()Ljava/lang/String; + public fun getSampleRate ()D + public fun getService ()Ljava/lang/String; + public fun getTags ()Ljava/util/Map; +} + +public class datadog/trace/common/sampling/TraceSamplingRules { + public static final field EMPTY Ldatadog/trace/common/sampling/TraceSamplingRules; + public fun (Ljava/util/List;)V + public static fun deserialize (Ljava/lang/String;)Ldatadog/trace/common/sampling/TraceSamplingRules; + public fun getRules ()Ljava/util/List; + public fun isEmpty ()Z +} + +public final class datadog/trace/common/sampling/TraceSamplingRules$Rule : datadog/trace/api/sampling/SamplingRule$TraceSamplingRule { + public static fun create (Ldatadog/trace/common/sampling/TraceSamplingRules$JsonRule;)Ldatadog/trace/common/sampling/TraceSamplingRules$Rule; + public fun getName ()Ljava/lang/String; + public fun getResource ()Ljava/lang/String; + public fun getSampleRate ()D + public fun getService ()Ljava/lang/String; + public fun getTags ()Ljava/util/Map; +} + +public class datadog/trace/common/writer/CompositePayloadDispatcher : datadog/trace/common/writer/PayloadDispatcher { + public fun ([Ldatadog/trace/common/writer/PayloadDispatcher;)V + public fun addTrace (Ljava/util/List;)V + public fun flush ()V + public fun getApis ()Ljava/util/Collection; + public fun onDroppedTrace (I)V +} + +public class datadog/trace/common/writer/ListWriter : java/util/concurrent/CopyOnWriteArrayList, datadog/trace/common/writer/Writer { + public static final field ACCEPT_ALL Ldatadog/trace/common/writer/ListWriter$Filter; + public fun ()V + public fun close ()V + public fun firstTrace ()Ljava/util/List; + public fun flush ()Z + public fun incrementDropCounts (I)V + public fun setFilter (Ldatadog/trace/common/writer/ListWriter$Filter;)V + public fun start ()V + public fun toString ()Ljava/lang/String; + public fun waitForTraces (I)V + public fun waitForTracesMax (II)Z + public fun waitUntilReported (Ldatadog/trace/core/DDSpan;)V + public fun waitUntilReported (Ldatadog/trace/core/DDSpan;ILjava/util/concurrent/TimeUnit;)V + public fun write (Ljava/util/List;)V +} + +public abstract interface class datadog/trace/common/writer/ListWriter$Filter { + public abstract fun accept (Ljava/util/List;)Z +} + +public class datadog/trace/common/writer/LoggingWriter : datadog/trace/common/writer/Writer { + public fun ()V + public fun close ()V + public fun flush ()Z + public fun incrementDropCounts (I)V + public fun start ()V + public fun toString ()Ljava/lang/String; + public fun write (Ljava/util/List;)V +} + +public abstract class datadog/trace/common/writer/Payload { + protected field body Ljava/nio/ByteBuffer; + public fun ()V + public fun droppedSpans ()J + public fun droppedTraces ()J + protected fun msgpackArrayHeader (I)Ljava/nio/ByteBuffer; + protected fun msgpackArrayHeaderSize (I)I + protected fun msgpackMapHeader (I)Ljava/nio/ByteBuffer; + protected fun msgpackMapHeaderSize (I)I + public abstract fun sizeInBytes ()I + public abstract fun toRequest ()Lokhttp3/RequestBody; + public fun traceCount ()I + public fun withBody (ILjava/nio/ByteBuffer;)Ldatadog/trace/common/writer/Payload; + public fun withDroppedSpans (J)Ldatadog/trace/common/writer/Payload; + public fun withDroppedTraces (J)Ldatadog/trace/common/writer/Payload; + public abstract fun writeTo (Ljava/nio/channels/WritableByteChannel;)V +} + +public class datadog/trace/common/writer/PayloadDispatcherImpl : datadog/trace/common/writer/PayloadDispatcher, datadog/trace/serialization/ByteBufferConsumer { + public fun (Ldatadog/trace/common/writer/RemoteMapperDiscovery;Ldatadog/trace/common/writer/RemoteApi;Ldatadog/trace/core/monitor/HealthMetrics;Ldatadog/trace/monitor/Monitoring;)V + public fun accept (ILjava/nio/ByteBuffer;)V + public fun addTrace (Ljava/util/List;)V + public fun flush ()V + public fun getApis ()Ljava/util/Collection; + public fun onDroppedTrace (I)V +} + +public class datadog/trace/common/writer/PrintingWriter : datadog/trace/common/writer/Writer { + public fun (Ljava/io/OutputStream;Z)V + public fun close ()V + public fun flush ()Z + public fun incrementDropCounts (I)V + public fun start ()V + public fun write (Ljava/util/List;)V +} + +public abstract class datadog/trace/common/writer/RemoteApi { + protected field failedTraces J + protected final field ioLogger Ldatadog/trace/relocate/api/IOLogger; + protected field receivedTraces J + protected field sentTraces J + protected field totalTraces J + public fun ()V + protected fun countAndLogFailedSend (IILokhttp3/Response;Ljava/io/IOException;)V + protected fun countAndLogSuccessfulSend (II)V + protected fun createSendLogMessage (IILjava/lang/String;)Ljava/lang/String; + protected abstract fun getLogger ()Lorg/slf4j/Logger; + protected static fun getResponseBody (Lokhttp3/Response;)Ljava/lang/String; + protected abstract fun sendSerializedTraces (Ldatadog/trace/common/writer/Payload;)Ldatadog/trace/common/writer/RemoteApi$Response; + protected static fun toLoggerResponse (Lokhttp3/Response;Ljava/lang/String;)Ldatadog/trace/relocate/api/IOLogger$Response; +} + +public final class datadog/trace/common/writer/RemoteApi$Response { + public final fun exception ()Ljava/lang/Throwable; + public static fun failed (I)Ldatadog/trace/common/writer/RemoteApi$Response; + public static fun failed (Ljava/lang/Throwable;)Ldatadog/trace/common/writer/RemoteApi$Response; + public final fun response ()Ljava/lang/String; + public final fun status ()Ljava/lang/Integer; + public final fun success ()Z + public static fun success (I)Ldatadog/trace/common/writer/RemoteApi$Response; + public static fun success (ILjava/lang/String;)Ldatadog/trace/common/writer/RemoteApi$Response; + public static fun success (ILjava/lang/Throwable;)Ldatadog/trace/common/writer/RemoteApi$Response; +} + +public abstract interface class datadog/trace/common/writer/RemoteMapper : datadog/trace/serialization/Mapper { + public static final field DURATION [B + public static final field ERROR [B + public static final field HTTP_STATUS Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field LANGUAGE [B + public static final field META [B + public static final field METRICS [B + public static final field NAME [B + public static final field NO_OP Ldatadog/trace/common/writer/RemoteMapper; + public static final field PARENT_ID [B + public static final field RESOURCE [B + public static final field RUNTIME_ID [B + public static final field SERVICE [B + public static final field SPAN_ID [B + public static final field START [B + public static final field TRACE_ID [B + public static final field TYPE [B + public abstract fun endpoint ()Ljava/lang/String; + public abstract fun messageBufferSize ()I + public abstract fun newPayload ()Ldatadog/trace/common/writer/Payload; + public abstract fun reset ()V +} + +public class datadog/trace/common/writer/RemoteMapper$NoopRemoteMapper : datadog/trace/common/writer/RemoteMapper { + public fun ()V + public fun endpoint ()Ljava/lang/String; + public synthetic fun map (Ljava/lang/Object;Ldatadog/trace/serialization/Writable;)V + public fun map (Ljava/util/List;Ldatadog/trace/serialization/Writable;)V + public fun messageBufferSize ()I + public fun newPayload ()Ldatadog/trace/common/writer/Payload; + public fun reset ()V +} + +public abstract interface class datadog/trace/common/writer/RemoteMapperDiscovery { + public abstract fun discover ()V + public abstract fun getMapper ()Ldatadog/trace/common/writer/RemoteMapper; +} + +public abstract interface class datadog/trace/common/writer/RemoteResponseListener { + public abstract fun onResponse (Ljava/lang/String;Ljava/util/Map;)V +} + +public abstract interface class datadog/trace/common/writer/SpanSamplingWorker : java/lang/AutoCloseable { + public static fun build (ILjava/util/Queue;Ljava/util/Queue;Ldatadog/trace/common/sampling/SingleSpanSampler;Ldatadog/trace/core/monitor/HealthMetrics;Ldatadog/trace/ddagent/DroppingPolicy;)Ldatadog/trace/common/writer/SpanSamplingWorker; + public abstract fun close ()V + public abstract fun getSpanSamplingQueue ()Ljava/util/Queue; + public abstract fun start ()V +} + +public class datadog/trace/common/writer/SpanSamplingWorker$DefaultSpanSamplingWorker : datadog/trace/common/writer/SpanSamplingWorker { + protected fun (ILjava/util/Queue;Ljava/util/Queue;Ldatadog/trace/common/sampling/SingleSpanSampler;Ldatadog/trace/core/monitor/HealthMetrics;Ldatadog/trace/ddagent/DroppingPolicy;)V + protected fun afterOnEvent ()V + public fun close ()V + public fun getSpanSamplingQueue ()Ljava/util/Queue; + public fun start ()V +} + +public class datadog/trace/common/writer/SpanSamplingWorker$NoopSpanSamplingWorker : datadog/trace/common/writer/SpanSamplingWorker { + public fun ()V + public fun close ()V + public fun getSpanSamplingQueue ()Ljava/util/Queue; + public fun start ()V +} + +public class datadog/trace/common/writer/TraceProcessingWorker : java/lang/AutoCloseable { + public fun (ILdatadog/trace/core/monitor/HealthMetrics;Ldatadog/trace/common/writer/PayloadDispatcher;Ldatadog/trace/ddagent/DroppingPolicy;Ldatadog/trace/common/writer/ddagent/Prioritization;JLjava/util/concurrent/TimeUnit;Ldatadog/trace/common/sampling/SingleSpanSampler;)V + public fun close ()V + public fun flush (JLjava/util/concurrent/TimeUnit;)Z + public fun getCapacity ()I + public fun getRemainingCapacity ()J + public fun publish (Ldatadog/trace/core/CoreSpan;ILjava/util/List;)Ldatadog/trace/common/writer/ddagent/PrioritizationStrategy$PublishResult; + public fun start ()V +} + +public abstract class datadog/trace/common/writer/TraceProcessingWorker$TraceSerializingHandler : java/lang/Runnable { + public fun (Lorg/jctools/queues/MpscBlockingConsumerArrayQueue;Lorg/jctools/queues/MpscBlockingConsumerArrayQueue;Ldatadog/trace/core/monitor/HealthMetrics;Ldatadog/trace/common/writer/PayloadDispatcher;JLjava/util/concurrent/TimeUnit;)V + protected fun consumeFromPrimaryQueue ()V + protected fun consumeFromSecondaryQueue ()V + protected fun flushIfNecessary ()V + public fun onEvent (Ljava/lang/Object;)V + protected fun queuesAreEmpty ()Z +} + +public class datadog/trace/common/writer/TraceStructureWriter : datadog/trace/common/writer/Writer { + public fun ()V + public fun (Ljava/lang/String;)V + public fun (Ljava/lang/String;Z)V + public fun (Z)V + public fun close ()V + public fun flush ()Z + public fun incrementDropCounts (I)V + public fun start ()V + public fun write (Ljava/util/List;)V +} + +public abstract interface class datadog/trace/common/writer/Writer : java/io/Closeable { + public abstract fun close ()V + public abstract fun flush ()Z + public abstract fun incrementDropCounts (I)V + public abstract fun start ()V + public abstract fun write (Ljava/util/List;)V +} + +public final class datadog/trace/common/writer/ddagent/FlushEvent { + public fun (Ljava/util/concurrent/CountDownLatch;)V + public fun sync ()V +} + +public abstract class datadog/trace/common/writer/ddagent/Prioritization : java/lang/Enum { + public static final field ENSURE_TRACE Ldatadog/trace/common/writer/ddagent/Prioritization; + public static final field FAST_LANE Ldatadog/trace/common/writer/ddagent/Prioritization; + public abstract fun create (Ljava/util/Queue;Ljava/util/Queue;Ljava/util/Queue;Ldatadog/trace/ddagent/DroppingPolicy;)Ldatadog/trace/common/writer/ddagent/PrioritizationStrategy; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/common/writer/ddagent/Prioritization; + public static fun values ()[Ldatadog/trace/common/writer/ddagent/Prioritization; +} + +public abstract interface class datadog/trace/common/writer/ddagent/PrioritizationStrategy { + public abstract fun flush (JLjava/util/concurrent/TimeUnit;)Z + public abstract fun publish (Ldatadog/trace/core/CoreSpan;ILjava/util/List;)Ldatadog/trace/common/writer/ddagent/PrioritizationStrategy$PublishResult; +} + +public final class datadog/trace/common/writer/ddagent/PrioritizationStrategy$PublishResult : java/lang/Enum { + public static final field DROPPED_BUFFER_OVERFLOW Ldatadog/trace/common/writer/ddagent/PrioritizationStrategy$PublishResult; + public static final field DROPPED_BY_POLICY Ldatadog/trace/common/writer/ddagent/PrioritizationStrategy$PublishResult; + public static final field ENQUEUED_FOR_SERIALIZATION Ldatadog/trace/common/writer/ddagent/PrioritizationStrategy$PublishResult; + public static final field ENQUEUED_FOR_SINGLE_SPAN_SAMPLING Ldatadog/trace/common/writer/ddagent/PrioritizationStrategy$PublishResult; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/common/writer/ddagent/PrioritizationStrategy$PublishResult; + public static fun values ()[Ldatadog/trace/common/writer/ddagent/PrioritizationStrategy$PublishResult; +} + +public abstract interface class datadog/trace/common/writer/ddagent/TraceMapper : datadog/trace/common/writer/RemoteMapper { + public static final field ORIGIN_KEY Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field SAMPLING_PRIORITY_KEY Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field THREAD_ID Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public static final field THREAD_NAME Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; +} + +public abstract interface class datadog/trace/context/TraceScope : java/io/Closeable { + public abstract fun capture ()Ldatadog/trace/context/TraceScope$Continuation; + public abstract fun captureConcurrent ()Ldatadog/trace/context/TraceScope$Continuation; + public abstract fun close ()V + public abstract fun isAsyncPropagating ()Z + public abstract fun setAsyncPropagation (Z)V +} + +public abstract interface class datadog/trace/context/TraceScope$Continuation { + public abstract fun activate ()Ldatadog/trace/context/TraceScope; + public abstract fun cancel ()V +} + +public abstract interface class datadog/trace/core/CoreSpan { + public abstract fun addThrowable (Ljava/lang/Throwable;)Ldatadog/trace/core/CoreSpan; + public abstract fun getDurationNano ()J + public abstract fun getError ()I + public abstract fun getHttpStatusCode ()S + public abstract fun getLocalRootSpan ()Ldatadog/trace/core/CoreSpan; + public abstract fun getOperationName ()Ljava/lang/CharSequence; + public abstract fun getOrigin ()Ljava/lang/CharSequence; + public abstract fun getParentId ()J + public abstract fun getResourceName ()Ljava/lang/CharSequence; + public abstract fun getServiceName ()Ljava/lang/String; + public abstract fun getSpanId ()J + public abstract fun getStartTime ()J + public abstract fun getTag (Ljava/lang/CharSequence;)Ljava/lang/Object; + public abstract fun getTag (Ljava/lang/CharSequence;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun getTraceId ()Ldatadog/trace/api/DDTraceId; + public abstract fun getType ()Ljava/lang/CharSequence; + public abstract fun hasSamplingPriority ()Z + public abstract fun isForceKeep ()Z + public abstract fun isMeasured ()Z + public abstract fun isTopLevel ()Z + public abstract fun processTagsAndBaggage (Ldatadog/trace/core/MetadataConsumer;)V + public abstract fun removeTag (Ljava/lang/String;)Ldatadog/trace/core/CoreSpan; + public abstract fun samplingPriority ()I + public abstract fun setErrorMessage (Ljava/lang/String;)Ldatadog/trace/core/CoreSpan; + public abstract fun setFlag (Ljava/lang/CharSequence;Z)Ldatadog/trace/core/CoreSpan; + public abstract fun setMeasured (Z)Ldatadog/trace/core/CoreSpan; + public abstract fun setMetric (Ljava/lang/CharSequence;D)Ldatadog/trace/core/CoreSpan; + public abstract fun setMetric (Ljava/lang/CharSequence;F)Ldatadog/trace/core/CoreSpan; + public abstract fun setMetric (Ljava/lang/CharSequence;I)Ldatadog/trace/core/CoreSpan; + public abstract fun setMetric (Ljava/lang/CharSequence;J)Ldatadog/trace/core/CoreSpan; + public abstract fun setSamplingPriority (II)Ldatadog/trace/core/CoreSpan; + public abstract fun setSamplingPriority (ILjava/lang/CharSequence;DI)Ldatadog/trace/core/CoreSpan; + public abstract fun setSpanSamplingPriority (DI)Ldatadog/trace/core/CoreSpan; + public abstract fun setTag (Ljava/lang/String;D)Ldatadog/trace/core/CoreSpan; + public abstract fun setTag (Ljava/lang/String;I)Ldatadog/trace/core/CoreSpan; + public abstract fun setTag (Ljava/lang/String;J)Ldatadog/trace/core/CoreSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/core/CoreSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/core/CoreSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/Object;)Ldatadog/trace/core/CoreSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/core/CoreSpan; + public abstract fun setTag (Ljava/lang/String;Z)Ldatadog/trace/core/CoreSpan; +} + +public class datadog/trace/core/CoreTracer : datadog/trace/bootstrap/instrumentation/api/AgentTracer$TracerAPI { + public static final field TRACE_ID_MAX Ljava/math/BigInteger; + public fun activateNext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public fun activateSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public fun activateSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public fun activateSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public fun activeScope ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public fun activeSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun addScopeListener (Ldatadog/trace/api/scopemanager/ScopeListener;)V + public fun addScopeListener (Ljava/lang/Runnable;Ljava/lang/Runnable;)V + public fun addTraceInterceptor (Ldatadog/trace/api/interceptor/TraceInterceptor;)Z + public fun addTracerReportToFlare (Ljava/util/zip/ZipOutputStream;)V + public synthetic fun buildSpan (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun buildSpan (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public static fun builder ()Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun captureSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation; + public synthetic fun captureTraceConfig ()Ldatadog/trace/api/TraceConfig; + public fun captureTraceConfig ()Ldatadog/trace/core/CoreTracer$ConfigSnapshot; + public fun close ()V + public fun closePrevious (Z)V + public fun createTrace (Ldatadog/trace/api/DDTraceId;)Ldatadog/trace/core/PendingTrace; + protected fun finalize ()V + public fun flush ()V + public fun flushMetrics ()V + public fun getCallbackProvider (Ldatadog/trace/api/gateway/RequestContextSlot;)Ldatadog/trace/api/gateway/CallbackProvider; + public fun getDataStreamsCheckpointer ()Ldatadog/trace/api/experimental/DataStreamsCheckpointer; + public fun getDataStreamsMonitoring ()Ldatadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring; + public fun getPartialFlushMinSpans ()I + public synthetic fun getProfilingContext ()Ldatadog/trace/api/profiling/Profiling; + public fun getProfilingContext ()Ldatadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration; + public fun getSpanId ()Ljava/lang/String; + public fun getSpanId (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ljava/lang/String; + public fun getSubscriptionService (Ldatadog/trace/api/gateway/RequestContextSlot;)Ldatadog/trace/api/gateway/SubscriptionService; + public fun getTagInterceptor ()Ldatadog/trace/core/taginterceptor/TagInterceptor; + public fun getTimer ()Ldatadog/trace/api/profiling/Timer; + public fun getTraceId ()Ljava/lang/String; + public fun getTraceId (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ljava/lang/String; + public fun getTraceSegment ()Ldatadog/trace/api/internal/TraceSegment; + public fun getUniversalCallbackProvider ()Ldatadog/trace/api/gateway/CallbackProvider; + public fun newHistogram (DI)Ldatadog/trace/bootstrap/instrumentation/api/AgentHistogram; + public fun newScopeState ()Ldatadog/trace/bootstrap/instrumentation/api/ScopeState; + public fun noopSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun notifyExtensionEnd (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Z)V + public fun notifyExtensionStart (Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; + public fun onRootSpanFinished (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/api/EndpointTracker;)V + public fun onRootSpanStarted (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/api/EndpointTracker; + public fun propagate ()Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation; + public fun rebuildTraceConfig (Ldatadog/trace/api/Config;)V + public fun registerCheckpointer (Ldatadog/trace/api/EndpointCheckpointer;)V + public fun registerTimer (Ldatadog/trace/api/profiling/Timer;)V + public fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun startSpan (Ljava/lang/String;Ljava/lang/CharSequence;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; +} + +protected class datadog/trace/core/CoreTracer$ConfigSnapshot : datadog/trace/api/DynamicConfig$Snapshot { + protected fun (Ldatadog/trace/core/CoreTracer;Ldatadog/trace/api/DynamicConfig$Builder;Ldatadog/trace/core/CoreTracer$ConfigSnapshot;)V +} + +public class datadog/trace/core/CoreTracer$CoreSpanBuilder : datadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder { + public synthetic fun asChildOf (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun asChildOf (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public fun asChildOf (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public synthetic fun ignoreActiveSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun ignoreActiveSpan ()Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public fun start ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun withErrorFlag ()Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun withErrorFlag ()Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public fun withLink (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun withRequestContextData (Ldatadog/trace/api/gateway/RequestContextSlot;Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public synthetic fun withResourceName (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun withResourceName (Ljava/lang/String;)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public synthetic fun withServiceName (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun withServiceName (Ljava/lang/String;)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public synthetic fun withSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun withSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public synthetic fun withStartTimestamp (J)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun withStartTimestamp (J)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public synthetic fun withTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun withTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public synthetic fun withTag (Ljava/lang/String;Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun withTag (Ljava/lang/String;Ljava/lang/Object;)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public synthetic fun withTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun withTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; + public synthetic fun withTag (Ljava/lang/String;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder; + public fun withTag (Ljava/lang/String;Z)Ldatadog/trace/core/CoreTracer$CoreSpanBuilder; +} + +public class datadog/trace/core/CoreTracer$CoreTracerBuilder { + public fun ()V + public fun baggageMapping (Ljava/util/Map;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun build ()Ldatadog/trace/core/CoreTracer; + public fun config (Ldatadog/trace/api/Config;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun defaultSpanTags (Ljava/util/Map;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun extractor (Ldatadog/trace/core/propagation/HttpCodec$Extractor;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun idGenerationStrategy (Ldatadog/trace/api/IdGenerationStrategy;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun injectBaggageAsTags (Z)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun instrumentationGateway (Ldatadog/trace/api/gateway/InstrumentationGateway;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun localRootSpanTags (Ljava/util/Map;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun partialFlushMinSpans (I)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun sampler (Ldatadog/trace/common/sampling/Sampler;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun scopeManager (Ldatadog/trace/bootstrap/instrumentation/api/AgentScopeManager;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun serviceName (Ljava/lang/String;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun serviceNameMappings (Ljava/util/Map;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun statsDClient (Ldatadog/trace/core/taginterceptor/TagInterceptor;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun strictTraceWrites (Z)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun tagInterceptor (Ldatadog/trace/core/taginterceptor/TagInterceptor;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun taggedHeaders (Ljava/util/Map;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun timeSource (Ldatadog/trace/api/time/TimeSource;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun withProperties (Ljava/util/Properties;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; + public fun writer (Ldatadog/trace/common/writer/Writer;)Ldatadog/trace/core/CoreTracer$CoreTracerBuilder; +} + +public class datadog/trace/core/DDSpan : datadog/trace/api/profiling/TransientProfilingContextHolder, datadog/trace/bootstrap/instrumentation/api/AgentSpan, datadog/trace/bootstrap/instrumentation/api/AttachableWrapper, datadog/trace/core/CoreSpan { + public static final field CHECKPOINTED_TAG Ljava/lang/String; + public fun addLink (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink;)V + public synthetic fun addThrowable (Ljava/lang/Throwable;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun addThrowable (Ljava/lang/Throwable;)Ldatadog/trace/core/CoreSpan; + public fun addThrowable (Ljava/lang/Throwable;)Ldatadog/trace/core/DDSpan; + public synthetic fun addThrowable (Ljava/lang/Throwable;B)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun addThrowable (Ljava/lang/Throwable;B)Ldatadog/trace/core/DDSpan; + public fun attachWrapper (Ljava/lang/Object;)V + public fun beginEndToEnd ()V + public synthetic fun context ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; + public final fun context ()Ldatadog/trace/core/DDSpanContext; + public fun eligibleForDropping ()Z + public fun finish ()V + public fun finish (J)V + public final fun finishWithDuration (J)V + public fun finishWithEndToEnd ()V + public fun forceKeep (Z)Ldatadog/trace/core/DDSpan; + public fun forceSamplingDecision ()Ljava/lang/Integer; + public fun getBaggage ()Ljava/util/Map; + public final fun getBaggageItem (Ljava/lang/String;)Ljava/lang/String; + public fun getDurationNano ()J + public fun getEndpointTracker ()Ldatadog/trace/api/EndpointTracker; + public fun getError ()I + public fun getHttpStatusCode ()S + public synthetic fun getLocalRootSpan ()Ldatadog/trace/api/interceptor/MutableSpan; + public synthetic fun getLocalRootSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun getLocalRootSpan ()Ldatadog/trace/core/CoreSpan; + public fun getLocalRootSpan ()Ldatadog/trace/core/DDSpan; + public fun getOperationName ()Ljava/lang/CharSequence; + public fun getOrigin ()Ljava/lang/CharSequence; + public fun getParentId ()J + public fun getRequestBlockingAction ()Ldatadog/trace/api/gateway/Flow$Action$RequestBlockingAction; + public fun getRequestContext ()Ldatadog/trace/api/gateway/RequestContext; + public fun getResourceName ()Ljava/lang/CharSequence; + public fun getResourceNamePriority ()B + public synthetic fun getRootSpan ()Ldatadog/trace/api/interceptor/MutableSpan; + public fun getRootSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun getSamplingPriority ()Ljava/lang/Integer; + public fun getServiceName ()Ljava/lang/String; + public fun getSpanId ()J + public fun getSpanName ()Ljava/lang/CharSequence; + public fun getSpanType ()Ljava/lang/String; + public fun getStartTime ()J + public fun getStartTimeNano ()J + public fun getTag (Ljava/lang/CharSequence;)Ljava/lang/Object; + public fun getTag (Ljava/lang/CharSequence;Ljava/lang/Object;)Ljava/lang/Object; + public fun getTag (Ljava/lang/String;)Ljava/lang/Object; + public fun getTags ()Ljava/util/Map; + public fun getTraceId ()Ldatadog/trace/api/DDTraceId; + public fun getType ()Ljava/lang/CharSequence; + public fun getWrapper ()Ljava/lang/Object; + public fun hasResourceName ()Z + public fun hasSamplingPriority ()Z + public fun isError ()Z + public fun isFinished ()Z + public fun isForceKeep ()Z + public fun isLocalRootSpan ()Z + public fun isMeasured ()Z + public final fun isRootSpan ()Z + public fun isSameTrace (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Z + public fun isTopLevel ()Z + public final fun phasedFinish ()Z + public fun processTagsAndBaggage (Ldatadog/trace/core/MetadataConsumer;)V + public final fun publish ()V + public synthetic fun removeTag (Ljava/lang/String;)Ldatadog/trace/core/CoreSpan; + public fun removeTag (Ljava/lang/String;)Ldatadog/trace/core/DDSpan; + public fun samplingPriority ()I + public synthetic fun setBaggageItem (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public final fun setBaggageItem (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/core/DDSpan; + public fun setEndpointTracker (Ldatadog/trace/api/EndpointTracker;)V + public synthetic fun setError (Z)Ldatadog/trace/api/interceptor/MutableSpan; + public synthetic fun setError (Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setError (Z)Ldatadog/trace/core/DDSpan; + public synthetic fun setError (ZB)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setError (ZB)Ldatadog/trace/core/DDSpan; + public synthetic fun setErrorMessage (Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setErrorMessage (Ljava/lang/String;)Ldatadog/trace/core/CoreSpan; + public fun setErrorMessage (Ljava/lang/String;)Ldatadog/trace/core/DDSpan; + public synthetic fun setFlag (Ljava/lang/CharSequence;Z)Ldatadog/trace/core/CoreSpan; + public fun setFlag (Ljava/lang/CharSequence;Z)Ldatadog/trace/core/DDSpan; + public fun setHttpStatusCode (I)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun setLongRunningVersion (I)V + public synthetic fun setMeasured (Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setMeasured (Z)Ldatadog/trace/core/CoreSpan; + public fun setMeasured (Z)Ldatadog/trace/core/DDSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;D)Ldatadog/trace/api/interceptor/MutableSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;D)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;D)Ldatadog/trace/core/CoreSpan; + public fun setMetric (Ljava/lang/CharSequence;D)Ldatadog/trace/core/DDSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;F)Ldatadog/trace/core/CoreSpan; + public fun setMetric (Ljava/lang/CharSequence;F)Ldatadog/trace/core/DDSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;I)Ldatadog/trace/api/interceptor/MutableSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;I)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;I)Ldatadog/trace/core/CoreSpan; + public fun setMetric (Ljava/lang/CharSequence;I)Ldatadog/trace/core/DDSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;J)Ldatadog/trace/api/interceptor/MutableSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setMetric (Ljava/lang/CharSequence;J)Ldatadog/trace/core/CoreSpan; + public fun setMetric (Ljava/lang/CharSequence;J)Ldatadog/trace/core/DDSpan; + public synthetic fun setOperationName (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public final fun setOperationName (Ljava/lang/CharSequence;)Ldatadog/trace/core/DDSpan; + public fun setRequestBlockingAction (Ldatadog/trace/api/gateway/Flow$Action$RequestBlockingAction;)V + public synthetic fun setResourceName (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public synthetic fun setResourceName (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public final fun setResourceName (Ljava/lang/CharSequence;)Ldatadog/trace/core/DDSpan; + public synthetic fun setResourceName (Ljava/lang/CharSequence;B)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public final fun setResourceName (Ljava/lang/CharSequence;B)Ldatadog/trace/core/DDSpan; + public synthetic fun setSamplingPriority (I)Ldatadog/trace/api/interceptor/MutableSpan; + public final fun setSamplingPriority (I)Ldatadog/trace/core/DDSpan; + public synthetic fun setSamplingPriority (II)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setSamplingPriority (II)Ldatadog/trace/core/CoreSpan; + public final fun setSamplingPriority (II)Ldatadog/trace/core/DDSpan; + public synthetic fun setSamplingPriority (ILjava/lang/CharSequence;DI)Ldatadog/trace/core/CoreSpan; + public fun setSamplingPriority (ILjava/lang/CharSequence;DI)Ldatadog/trace/core/DDSpan; + public synthetic fun setServiceName (Ljava/lang/String;)Ldatadog/trace/api/interceptor/MutableSpan; + public final fun setServiceName (Ljava/lang/String;)Ldatadog/trace/core/DDSpan; + public fun setSpanName (Ljava/lang/CharSequence;)V + public synthetic fun setSpanSamplingPriority (DI)Ldatadog/trace/core/CoreSpan; + public fun setSpanSamplingPriority (DI)Ldatadog/trace/core/DDSpan; + public synthetic fun setSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/api/interceptor/MutableSpan; + public synthetic fun setSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public final fun setSpanType (Ljava/lang/CharSequence;)Ldatadog/trace/core/DDSpan; + public synthetic fun setTag (Ljava/lang/String;D)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;D)Ldatadog/trace/core/CoreSpan; + public fun setTag (Ljava/lang/String;D)Ldatadog/trace/core/DDSpan; + public synthetic fun setTag (Ljava/lang/String;I)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;I)Ldatadog/trace/core/CoreSpan; + public fun setTag (Ljava/lang/String;I)Ldatadog/trace/core/DDSpan; + public synthetic fun setTag (Ljava/lang/String;J)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;J)Ldatadog/trace/core/CoreSpan; + public fun setTag (Ljava/lang/String;J)Ldatadog/trace/core/DDSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/core/CoreSpan; + public fun setTag (Ljava/lang/String;Ljava/lang/CharSequence;)Ldatadog/trace/core/DDSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/api/interceptor/MutableSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/core/CoreSpan; + public fun setTag (Ljava/lang/String;Ljava/lang/Number;)Ldatadog/trace/core/DDSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/Object;)Ldatadog/trace/core/CoreSpan; + public fun setTag (Ljava/lang/String;Ljava/lang/Object;)Ldatadog/trace/core/DDSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/api/interceptor/MutableSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/core/CoreSpan; + public final fun setTag (Ljava/lang/String;Ljava/lang/String;)Ldatadog/trace/core/DDSpan; + public synthetic fun setTag (Ljava/lang/String;Z)Ldatadog/trace/api/interceptor/MutableSpan; + public synthetic fun setTag (Ljava/lang/String;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public synthetic fun setTag (Ljava/lang/String;Z)Ldatadog/trace/core/CoreSpan; + public final fun setTag (Ljava/lang/String;Z)Ldatadog/trace/core/DDSpan; + public fun toString ()Ljava/lang/String; + public fun traceConfig ()Ldatadog/trace/api/TraceConfig; +} + +public class datadog/trace/core/DDSpanContext : datadog/trace/api/gateway/RequestContext, datadog/trace/api/internal/TraceSegment, datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context, datadog/trace/bootstrap/instrumentation/api/ProfilerContext { + public static final field PRIORITY_SAMPLING_KEY Ljava/lang/String; + public static final field SAMPLE_RATE_KEY Ljava/lang/String; + public static final field SPAN_SAMPLING_MAX_PER_SECOND_TAG Ljava/lang/String; + public static final field SPAN_SAMPLING_MECHANISM_TAG Ljava/lang/String; + public static final field SPAN_SAMPLING_RULE_RATE_TAG Ljava/lang/String; + public fun (Ldatadog/trace/api/DDTraceId;JJLjava/lang/CharSequence;Ljava/lang/String;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Ljava/util/Map;ZLjava/lang/CharSequence;ILdatadog/trace/core/PendingTrace;Ljava/lang/Object;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext;ZLdatadog/trace/core/propagation/PropagationTags;)V + public fun (Ldatadog/trace/api/DDTraceId;JJLjava/lang/CharSequence;Ljava/lang/String;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Ljava/util/Map;ZLjava/lang/CharSequence;ILdatadog/trace/core/PendingTrace;Ljava/lang/Object;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext;ZLdatadog/trace/core/propagation/PropagationTags;Ldatadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration;)V + public fun (Ldatadog/trace/api/DDTraceId;JJLjava/lang/CharSequence;Ljava/lang/String;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Ljava/util/Map;ZLjava/lang/CharSequence;ILdatadog/trace/core/PendingTrace;Ljava/lang/Object;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext;ZLdatadog/trace/core/propagation/PropagationTags;Z)V + public fun (Ldatadog/trace/api/DDTraceId;JJLjava/lang/CharSequence;Ljava/lang/String;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Ljava/util/Map;ZLjava/lang/CharSequence;ILdatadog/trace/core/PendingTrace;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext;ZLdatadog/trace/core/propagation/PropagationTags;Ldatadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration;Z)V + public fun baggageItems ()Ljava/lang/Iterable; + public fun beginEndToEnd ()V + public fun close ()V + public fun effectivelyBlocked ()V + public fun forceKeep ()V + public fun getBaggageItem (Ljava/lang/String;)Ljava/lang/String; + public fun getBaggageItems ()Ljava/util/Map; + public fun getBlockResponseFunction ()Ldatadog/trace/api/gateway/BlockResponseFunction; + public fun getData (Ldatadog/trace/api/gateway/RequestContextSlot;)Ljava/lang/Object; + public fun getEncodedOperationName ()I + public fun getEncodedResourceName ()I + public fun getEndToEndStartTime ()J + public fun getErrorFlag ()Z + public fun getHttpStatusCode ()S + public fun getOperationName ()Ljava/lang/CharSequence; + public fun getOrigin ()Ljava/lang/CharSequence; + public fun getParentId ()J + public fun getPathwayContext ()Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext; + public fun getPropagationTags ()Ldatadog/trace/core/propagation/PropagationTags; + public fun getRequestContext ()Ldatadog/trace/api/gateway/RequestContext; + public fun getResourceName ()Ljava/lang/CharSequence; + public fun getResourceNamePriority ()B + public fun getRootSpanId ()J + public fun getSamplingPriority ()I + public fun getServiceName ()Ljava/lang/String; + public fun getSpanId ()J + public fun getSpanType ()Ljava/lang/CharSequence; + public fun getTags ()Ljava/util/Map; + public synthetic fun getTrace ()Ldatadog/trace/bootstrap/instrumentation/api/AgentTrace; + public fun getTrace ()Ldatadog/trace/core/PendingTrace; + public fun getTraceId ()Ldatadog/trace/api/DDTraceId; + public fun getTraceSegment ()Ldatadog/trace/api/internal/TraceSegment; + public fun getTracer ()Ldatadog/trace/core/CoreTracer; + public fun hasResourceName ()Z + public fun isMeasured ()Z + public fun isTopLevel ()Z + public fun lockSamplingPriority ()Z + public fun mergePathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext;)V + public fun processTagsAndBaggage (Ldatadog/trace/core/MetadataConsumer;ILjava/util/List;)V + public fun setBaggageItem (Ljava/lang/String;Ljava/lang/String;)V + public fun setBlockResponseFunction (Ldatadog/trace/api/gateway/BlockResponseFunction;)V + public fun setDataCurrent (Ljava/lang/String;Ljava/lang/Object;)V + public fun setDataTop (Ljava/lang/String;Ljava/lang/Object;)V + public fun setErrorFlag (ZB)V + public fun setHttpStatusCode (S)V + public fun setMeasured (Z)V + public fun setMetric (Ljava/lang/CharSequence;Ljava/lang/Number;)V + public fun setOperationName (Ljava/lang/CharSequence;)V + public fun setOrigin (Ljava/lang/CharSequence;)V + public fun setResourceName (Ljava/lang/CharSequence;B)V + public fun setSamplingPriority (II)Z + public fun setServiceName (Ljava/lang/String;)V + public fun setSpanSamplingPriority (DI)V + public fun setSpanType (Ljava/lang/CharSequence;)V + public fun setTag (Ljava/lang/String;Ljava/lang/Object;)V + public fun setTagCurrent (Ljava/lang/String;Ljava/lang/Object;Z)V + public fun setTagTop (Ljava/lang/String;Ljava/lang/Object;Z)V + public fun toString ()Ljava/lang/String; + public fun unsafeGetTag (Ljava/lang/String;)Ljava/lang/Object; +} + +public class datadog/trace/core/DDSpanLink : datadog/trace/bootstrap/instrumentation/api/SpanLink { + protected fun (Ldatadog/trace/api/DDTraceId;JBLjava/lang/String;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink$Attributes;)V + public static fun from (Ldatadog/trace/core/propagation/ExtractedContext;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLink; + public static fun from (Ldatadog/trace/core/propagation/ExtractedContext;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpanLink$Attributes;)Ldatadog/trace/bootstrap/instrumentation/api/SpanLink; + public static fun toTag (Ljava/util/List;)Ljava/lang/String; +} + +public class datadog/trace/core/DDTraceCoreInfo { + public static final field JAVA_VERSION Ljava/lang/String; + public static final field JAVA_VM_NAME Ljava/lang/String; + public static final field JAVA_VM_VENDOR Ljava/lang/String; + public static final field VERSION Ljava/lang/String; + public fun ()V + public static fun main ([Ljava/lang/String;)V +} + +public class datadog/trace/core/LongRunningTracesTracker { + public static final field EXPIRED I + public static final field NOT_TRACKED I + public static final field TO_TRACK I + public static final field TRACKED I + public static final field UNDEFINED I + public static final field WRITE_RUNNING_SPANS I + public fun (Ldatadog/trace/api/Config;ILdatadog/trace/core/monitor/HealthMetrics;)V + public fun add (Ldatadog/trace/core/PendingTraceBuffer$Element;)Z + public fun flushAndCompact (J)V +} + +public final class datadog/trace/core/Metadata { + public fun (JLdatadog/trace/bootstrap/instrumentation/api/UTF8BytesString;Ljava/util/Map;Ljava/util/Map;IZZLdatadog/trace/bootstrap/instrumentation/api/UTF8BytesString;Ljava/lang/CharSequence;I)V + public fun getBaggage ()Ljava/util/Map; + public fun getHttpStatusCode ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun getOrigin ()Ljava/lang/CharSequence; + public fun getTags ()Ljava/util/Map; + public fun getThreadId ()J + public fun getThreadName ()Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString; + public fun hasSamplingPriority ()Z + public fun longRunningVersion ()I + public fun measured ()Z + public fun samplingPriority ()I + public fun topLevel ()Z +} + +public abstract interface class datadog/trace/core/MetadataConsumer : java/util/function/Consumer { + public static final field NO_OP Ldatadog/trace/core/MetadataConsumer; + public abstract fun accept (Ldatadog/trace/core/Metadata;)V + public synthetic fun accept (Ljava/lang/Object;)V +} + +public class datadog/trace/core/PendingTrace : datadog/trace/bootstrap/instrumentation/api/AgentTrace, datadog/trace/core/PendingTraceBuffer$Element { + public fun beginEndToEnd ()V + public fun cancelContinuation (Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation;)V + public fun compareAndSetLongRunningState (II)Z + public fun enqueueSpansToWrite (Ljava/util/List;Z)I + public fun evaluateSamplingPriority ()Ljava/lang/Integer; + public fun getCurrentTimeNano ()J + public static fun getDurationNano (Ldatadog/trace/core/CoreSpan;)J + public fun getEndToEndStartTime ()J + public fun getLastWriteTime ()J + public fun getRootSpan ()Ldatadog/trace/core/DDSpan; + public fun getRunningTraceStartTime ()J + public fun getTimeSource ()Ldatadog/trace/api/time/TimeSource; + public fun lastReferencedNanosAgo (J)Z + public fun oldestFinishedTime ()J + public fun registerContinuation (Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation;)V + public fun sample (Ldatadog/trace/core/DDSpan;)Z + public fun setEnqueued (Z)Z + public fun setLastWriteTime (J)V + public fun setSamplingPriorityIfNecessary ()V + public fun size ()I + public fun touch ()V + public fun write ()V + public fun writeOnBufferFull ()Z +} + +public abstract class datadog/trace/core/PendingTraceBuffer : java/lang/AutoCloseable { + public fun ()V + public abstract fun close ()V + public static fun delaying (Ldatadog/trace/api/time/TimeSource;Ldatadog/trace/api/Config;Ldatadog/trace/core/monitor/HealthMetrics;)Ldatadog/trace/core/PendingTraceBuffer; + public static fun discarding ()Ldatadog/trace/core/PendingTraceBuffer; + public abstract fun enqueue (Ldatadog/trace/core/PendingTraceBuffer$Element;)V + public abstract fun flush ()V + public fun longRunningSpansEnabled ()Z + public abstract fun start ()V +} + +public abstract interface class datadog/trace/core/PendingTraceBuffer$Element { + public abstract fun getRootSpan ()Ldatadog/trace/core/DDSpan; + public abstract fun lastReferencedNanosAgo (J)Z + public abstract fun oldestFinishedTime ()J + public abstract fun setEnqueued (Z)Z + public abstract fun write ()V + public abstract fun writeOnBufferFull ()Z +} + +public final class datadog/trace/core/StatusLogger : com/squareup/moshi/JsonAdapter, com/squareup/moshi/JsonAdapter$Factory, datadog/trace/util/AgentTaskScheduler$Task { + public fun ()V + public fun create (Ljava/lang/reflect/Type;Ljava/util/Set;Lcom/squareup/moshi/Moshi;)Lcom/squareup/moshi/JsonAdapter; + public fun fromJson (Lcom/squareup/moshi/JsonReader;)Ldatadog/trace/api/Config; + public synthetic fun fromJson (Lcom/squareup/moshi/JsonReader;)Ljava/lang/Object; + public static fun logStatus (Ldatadog/trace/api/Config;)V + public fun run (Ldatadog/trace/api/Config;)V + public synthetic fun run (Ljava/lang/Object;)V + public fun toJson (Lcom/squareup/moshi/JsonWriter;Ldatadog/trace/api/Config;)V + public synthetic fun toJson (Lcom/squareup/moshi/JsonWriter;Ljava/lang/Object;)V +} + +public class datadog/trace/core/datastreams/DataStreamContextExtractor : datadog/trace/core/propagation/HttpCodec$Extractor { + public fun (Ldatadog/trace/core/propagation/HttpCodec$Extractor;Ldatadog/trace/api/time/TimeSource;Ljava/util/function/Supplier;Ldatadog/trace/api/WellKnownTags;)V + public fun extract (Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$ContextVisitor;)Ldatadog/trace/bootstrap/instrumentation/api/TagContext; +} + +public class datadog/trace/core/datastreams/DataStreamContextInjector { + public fun (Ldatadog/trace/core/datastreams/DataStreamsMonitoring;)V + public fun injectPathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;)V + public fun injectPathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;JJ)V + public fun injectPathwayContextWithoutSendingStats (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;)V +} + +public class datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter : datadog/trace/bootstrap/instrumentation/api/AgentPropagation$ContextVisitor, datadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter { + public static final field INSTANCE Ldatadog/trace/core/datastreams/DataStreamsContextCarrierAdapter; + public fun forEachKey (Ldatadog/trace/api/experimental/DataStreamsContextCarrier;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$KeyClassifier;)V + public synthetic fun forEachKey (Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$KeyClassifier;)V + public fun set (Ldatadog/trace/api/experimental/DataStreamsContextCarrier;Ljava/lang/String;Ljava/lang/String;)V + public synthetic fun set (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/core/datastreams/DataStreamsMonitoring : datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring, java/lang/AutoCloseable { + public abstract fun clear ()V + public abstract fun close ()V + public abstract fun extractor (Ldatadog/trace/core/propagation/HttpCodec$Extractor;)Ldatadog/trace/core/propagation/HttpCodec$Extractor; + public abstract fun injector ()Ldatadog/trace/core/datastreams/DataStreamContextInjector; + public abstract fun mergePathwayContextIntoSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/api/experimental/DataStreamsContextCarrier;)V + public abstract fun start ()V +} + +public abstract interface class datadog/trace/core/datastreams/DatastreamsPayloadWriter { + public abstract fun writePayload (Ljava/util/Collection;)V +} + +public class datadog/trace/core/datastreams/DefaultPathwayContext : datadog/trace/bootstrap/instrumentation/api/PathwayContext { + public fun (Ldatadog/trace/api/time/TimeSource;Ldatadog/trace/api/WellKnownTags;)V + public fun encode ()[B + public fun getHash ()J + public fun getSavedStats ()Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint; + public fun isStarted ()Z + public fun saveStats (Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint;)V + public fun setCheckpoint (Ljava/util/LinkedHashMap;Ljava/util/function/Consumer;)V + public fun setCheckpoint (Ljava/util/LinkedHashMap;Ljava/util/function/Consumer;J)V + public fun setCheckpoint (Ljava/util/LinkedHashMap;Ljava/util/function/Consumer;JJ)V + public fun strEncode ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; +} + +public class datadog/trace/core/datastreams/MsgPackDatastreamsPayloadWriter : datadog/trace/core/datastreams/DatastreamsPayloadWriter { + public fun (Ldatadog/trace/common/metrics/Sink;Ldatadog/trace/api/WellKnownTags;Ljava/lang/String;Ljava/lang/String;)V + public fun reset ()V + public fun writePayload (Ljava/util/Collection;)V +} + +public class datadog/trace/core/datastreams/NoOpDataStreamMonitoring : datadog/trace/core/datastreams/DataStreamsMonitoring { + public fun ()V + public fun add (Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint;)V + public fun clear ()V + public fun close ()V + public fun extractor (Ldatadog/trace/core/propagation/HttpCodec$Extractor;)Ldatadog/trace/core/propagation/HttpCodec$Extractor; + public fun injector ()Ldatadog/trace/core/datastreams/DataStreamContextInjector; + public fun mergePathwayContextIntoSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/api/experimental/DataStreamsContextCarrier;)V + public fun newPathwayContext ()Ldatadog/trace/bootstrap/instrumentation/api/PathwayContext; + public fun setCheckpoint (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/util/LinkedHashMap;JJ)V + public fun setConsumeCheckpoint (Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/experimental/DataStreamsContextCarrier;)V + public fun setProduceCheckpoint (Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/experimental/DataStreamsContextCarrier;)V + public fun shouldSampleSchema (Ljava/lang/String;)I + public fun start ()V + public fun trackBacklog (Ljava/util/LinkedHashMap;J)V +} + +public class datadog/trace/core/datastreams/SchemaSampler { + public fun ()V + public fun shouldSample (J)I +} + +public class datadog/trace/core/datastreams/StatsBucket { + public fun (JJ)V + public fun addBacklog (Ldatadog/trace/bootstrap/instrumentation/api/Backlog;)V + public fun addPoint (Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint;)V + public fun getBacklogs ()Ljava/util/Collection; + public fun getBucketDurationNanos ()J + public fun getGroups ()Ljava/util/Collection; + public fun getStartTimeNanos ()J +} + +public class datadog/trace/core/datastreams/StatsGroup { + public fun (Ljava/util/List;JJ)V + public fun add (JJJ)V + public fun getEdgeLatency ()Ldatadog/trace/core/histogram/Histogram; + public fun getEdgeTags ()Ljava/util/List; + public fun getHash ()J + public fun getParentHash ()J + public fun getPathwayLatency ()Ldatadog/trace/core/histogram/Histogram; + public fun getPayloadSize ()Ldatadog/trace/core/histogram/Histogram; + public fun toString ()Ljava/lang/String; +} + +public class datadog/trace/core/datastreams/TagsProcessor { + public static final field CONSUMER_GROUP_TAG Ljava/lang/String; + public static final field DIRECTION_IN Ljava/lang/String; + public static final field DIRECTION_OUT Ljava/lang/String; + public static final field DIRECTION_TAG Ljava/lang/String; + public static final field EXCHANGE_TAG Ljava/lang/String; + public static final field GROUP_TAG Ljava/lang/String; + public static final field HAS_ROUTING_KEY_TAG Ljava/lang/String; + public static final field KAFKA_CLUSTER_ID_TAG Ljava/lang/String; + public static final field PARTITION_TAG Ljava/lang/String; + public static final field SUBSCRIPTION_TAG Ljava/lang/String; + public static final field TOPIC_TAG Ljava/lang/String; + public static final field TYPE_TAG Ljava/lang/String; + public fun ()V + public static fun createTag (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; +} + +public final class datadog/trace/core/datastreams/TagsProcessor$StringPrefix : java/util/function/Function { + public fun (Ljava/lang/String;)V + public synthetic fun apply (Ljava/lang/Object;)Ljava/lang/Object; + public fun apply (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/core/histogram/Histogram : datadog/trace/bootstrap/instrumentation/api/AgentHistogram { + public fun (Lcom/datadoghq/sketch/ddsketch/DDSketch;)V + public fun accept (D)V + public fun accept (DD)V + public fun clear ()V + public fun getCount ()D + public fun getMaxValue ()D + public fun getMinValue ()D + public fun getValueAtQuantile (D)D + public fun isEmpty ()Z + public fun serialize ()Ljava/nio/ByteBuffer; +} + +public final class datadog/trace/core/histogram/Histograms { + public fun ()V + public static fun newHistogram ()Ldatadog/trace/core/histogram/Histogram; + public static fun newHistogram (DI)Ldatadog/trace/core/histogram/Histogram; +} + +public abstract class datadog/trace/core/monitor/HealthMetrics : java/lang/AutoCloseable { + public static field NO_OP Ldatadog/trace/core/monitor/HealthMetrics; + public fun ()V + public fun close ()V + public fun onActivateScope ()V + public fun onCancelContinuation ()V + public fun onCaptureContinuation ()V + public fun onCloseScope ()V + public fun onCreateSpan ()V + public fun onCreateTrace ()V + public fun onFailedPublish (II)V + public fun onFailedSend (IILdatadog/trace/common/writer/RemoteApi$Response;)V + public fun onFailedSerialize (Ljava/util/List;Ljava/lang/Throwable;)V + public fun onFinishContinuation ()V + public fun onFinishSpan ()V + public fun onFlush (Z)V + public fun onLongRunningUpdate (III)V + public fun onPartialFlush (I)V + public fun onPartialPublish (I)V + public fun onPublish (Ljava/util/List;I)V + public fun onScheduleFlush (Z)V + public fun onScopeCloseError (I)V + public fun onScopeStackOverflow ()V + public fun onSend (IILdatadog/trace/common/writer/RemoteApi$Response;)V + public fun onSerialize (I)V + public fun onShutdown (Z)V + public fun onSingleSpanSample ()V + public fun onSingleSpanUnsampled ()V + public fun onStart (I)V + public fun start ()V + public fun summary ()Ljava/lang/String; +} + +public final class datadog/trace/core/monitor/MonitoringImpl : datadog/trace/monitor/Monitoring { + public fun (Ldatadog/trace/api/StatsDClient;JLjava/util/concurrent/TimeUnit;)V + public fun newCounter (Ljava/lang/String;)Ldatadog/trace/monitor/Counter; + public fun newThreadLocalTimer (Ljava/lang/String;)Ldatadog/trace/monitor/Recording; + public fun newTimer (Ljava/lang/String;)Ldatadog/trace/monitor/Recording; + public fun newTimer (Ljava/lang/String;[Ljava/lang/String;)Ldatadog/trace/monitor/Recording; +} + +public final class datadog/trace/core/monitor/StatsDCounter : datadog/trace/monitor/Counter { + public fun increment (I)V + public fun incrementErrorCount (Ljava/lang/String;I)V +} + +public class datadog/trace/core/monitor/ThreadLocalRecording : datadog/trace/monitor/Recording { + public fun (Ljava/lang/ThreadLocal;)V + public fun flush ()V + public fun reset ()V + public fun start ()Ldatadog/trace/monitor/Recording; + public fun stop ()V +} + +public class datadog/trace/core/monitor/Timer : datadog/trace/monitor/Recording { + public fun flush ()V + public fun reset ()V + public fun start ()Ldatadog/trace/monitor/Recording; + public fun stop ()V +} + +public class datadog/trace/core/monitor/Utils { + public fun ()V +} + +public class datadog/trace/core/propagation/B3TraceId : datadog/trace/api/DDTraceId { + protected final field delegate Ldatadog/trace/api/DDTraceId; + protected final field original Ljava/lang/String; + protected fun (Ljava/lang/String;Ldatadog/trace/api/DDTraceId;)V + public fun equals (Ljava/lang/Object;)Z + public static fun fromHex (Ljava/lang/String;)Ldatadog/trace/core/propagation/B3TraceId; + public fun getOriginal ()Ljava/lang/String; + public fun hashCode ()I + public fun toHexString ()Ljava/lang/String; + public fun toHexStringPadded (I)Ljava/lang/String; + public fun toHighOrderLong ()J + public fun toLong ()J + public fun toString ()Ljava/lang/String; +} + +public abstract class datadog/trace/core/propagation/ContextInterpreter : datadog/trace/bootstrap/instrumentation/api/AgentPropagation$KeyClassifier { + protected static final field LOG_EXTRACT_HEADER_NAMES Z + protected field baggage Ljava/util/Map; + protected field baggageMapping Ljava/util/Map; + protected field endToEndStartTime J + protected field fullContext Z + protected field headerTags Ljava/util/Map; + protected field origin Ljava/lang/CharSequence; + protected field propagationTags Ldatadog/trace/core/propagation/PropagationTags; + protected final field propagationTagsFactory Ldatadog/trace/core/propagation/PropagationTags$Factory; + protected field samplingPriority I + protected field spanId J + protected field tags Ljava/util/Map; + protected field traceId Ldatadog/trace/api/DDTraceId; + protected field valid Z + protected fun (Ldatadog/trace/api/Config;)V + protected fun build ()Ldatadog/trace/bootstrap/instrumentation/api/TagContext; + protected fun defaultSamplingPriority ()I + protected final fun handleMappedBaggage (Ljava/lang/String;Ljava/lang/String;)Z + protected final fun handleTags (Ljava/lang/String;Ljava/lang/String;)Z + protected final fun handledForwarding (Ljava/lang/String;Ljava/lang/String;)Z + protected final fun handledIpHeaders (Ljava/lang/String;Ljava/lang/String;)Z + protected final fun handledUserAgent (Ljava/lang/String;Ljava/lang/String;)Z + protected final fun handledXForwarding (Ljava/lang/String;Ljava/lang/String;)Z + protected fun invalidateContext ()V + protected fun onlyTagContext ()V + public fun reset (Ldatadog/trace/api/TraceConfig;)Ldatadog/trace/core/propagation/ContextInterpreter; + public abstract fun style ()Ldatadog/trace/api/TracePropagationStyle; + protected static fun toLowerCase (Ljava/lang/String;)Ljava/lang/String; +} + +public abstract interface class datadog/trace/core/propagation/ContextInterpreter$Factory { + public abstract fun create ()Ldatadog/trace/core/propagation/ContextInterpreter; +} + +public class datadog/trace/core/propagation/CorePropagation : datadog/trace/bootstrap/instrumentation/api/AgentPropagation { + public fun (Ldatadog/trace/core/propagation/HttpCodec$Extractor;Ldatadog/trace/core/propagation/HttpCodec$Injector;Ljava/util/Map;Ldatadog/trace/core/datastreams/DataStreamContextInjector;)V + public fun extract (Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$ContextVisitor;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context$Extracted; + public fun inject (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;)V + public fun inject (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;)V + public fun inject (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ldatadog/trace/api/TracePropagationStyle;)V + public fun injectPathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;)V + public fun injectPathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;JJ)V + public fun injectPathwayContextWithoutSendingStats (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;)V +} + +public class datadog/trace/core/propagation/ExtractedContext : datadog/trace/bootstrap/instrumentation/api/TagContext { + public fun (Ldatadog/trace/api/DDTraceId;JILjava/lang/CharSequence;JLjava/util/Map;Ljava/util/Map;Ldatadog/trace/bootstrap/instrumentation/api/TagContext$HttpHeaders;Ldatadog/trace/core/propagation/PropagationTags;Ldatadog/trace/api/TraceConfig;Ldatadog/trace/api/TracePropagationStyle;)V + public fun (Ldatadog/trace/api/DDTraceId;JILjava/lang/CharSequence;Ldatadog/trace/core/propagation/PropagationTags;Ldatadog/trace/api/TracePropagationStyle;)V + public final fun getEndToEndStartTime ()J + public fun getPropagationTags ()Ldatadog/trace/core/propagation/PropagationTags; + public final fun getSpanId ()J + public final fun getTraceId ()Ldatadog/trace/api/DDTraceId; + public fun toString ()Ljava/lang/String; +} + +public class datadog/trace/core/propagation/HttpCodec { + public fun ()V + public static fun allInjectorsFor (Ldatadog/trace/api/Config;Ljava/util/Map;)Ljava/util/Map; + public static fun createExtractor (Ldatadog/trace/api/Config;Ljava/util/function/Supplier;)Ldatadog/trace/core/propagation/HttpCodec$Extractor; + public static fun createInjector (Ldatadog/trace/api/Config;Ljava/util/Set;Ljava/util/Map;)Ldatadog/trace/core/propagation/HttpCodec$Injector; +} + +public class datadog/trace/core/propagation/HttpCodec$CompoundExtractor : datadog/trace/core/propagation/HttpCodec$Extractor { + public fun (Ljava/util/List;Z)V + public fun extract (Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$ContextVisitor;)Ldatadog/trace/bootstrap/instrumentation/api/TagContext; +} + +public class datadog/trace/core/propagation/HttpCodec$CompoundInjector : datadog/trace/core/propagation/HttpCodec$Injector { + public fun (Ljava/util/List;)V + public fun inject (Ldatadog/trace/core/DDSpanContext;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;)V +} + +public abstract interface class datadog/trace/core/propagation/HttpCodec$Extractor { + public fun cleanup ()V + public abstract fun extract (Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$ContextVisitor;)Ldatadog/trace/bootstrap/instrumentation/api/TagContext; +} + +public abstract interface class datadog/trace/core/propagation/HttpCodec$Injector { + public abstract fun inject (Ldatadog/trace/core/DDSpanContext;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;)V +} + +public class datadog/trace/core/propagation/NoOpCorePropagation : datadog/trace/bootstrap/instrumentation/api/AgentPropagation { + public fun (Ldatadog/trace/core/propagation/HttpCodec$Extractor;)V + public fun extract (Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$ContextVisitor;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context$Extracted; + public fun inject (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;)V + public fun inject (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;)V + public fun inject (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ldatadog/trace/api/TracePropagationStyle;)V + public fun injectPathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;)V + public fun injectPathwayContext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;JJ)V + public fun injectPathwayContextWithoutSendingStats (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$Setter;Ljava/util/LinkedHashMap;)V +} + +public class datadog/trace/core/propagation/NoneCodec { + public static final field EXTRACTOR Ldatadog/trace/core/propagation/HttpCodec$Extractor; + public static final field INJECTOR Ldatadog/trace/core/propagation/HttpCodec$Injector; + public fun ()V +} + +public abstract class datadog/trace/core/propagation/PropagationTags { + public fun ()V + public fun createTagMap ()Ljava/util/HashMap; + public static fun factory ()Ldatadog/trace/core/propagation/PropagationTags$Factory; + public static fun factory (I)Ldatadog/trace/core/propagation/PropagationTags$Factory; + public static fun factory (Ldatadog/trace/api/Config;)Ldatadog/trace/core/propagation/PropagationTags$Factory; + public abstract fun fillTagMap (Ljava/util/Map;)V + public abstract fun getOrigin ()Ljava/lang/CharSequence; + public abstract fun getSamplingPriority ()I + public abstract fun getTraceIdHighOrderBits ()J + public abstract fun getW3CTracestate ()Ljava/lang/String; + public abstract fun headerValue (Ldatadog/trace/core/propagation/PropagationTags$HeaderType;)Ljava/lang/String; + public abstract fun updateTraceIdHighOrderBits (J)V + public abstract fun updateTraceOrigin (Ljava/lang/CharSequence;)V + public abstract fun updateTraceSamplingPriority (II)V + public abstract fun updateW3CTracestate (Ljava/lang/String;)V +} + +public abstract interface class datadog/trace/core/propagation/PropagationTags$Factory { + public abstract fun empty ()Ldatadog/trace/core/propagation/PropagationTags; + public abstract fun fromHeaderValue (Ldatadog/trace/core/propagation/PropagationTags$HeaderType;Ljava/lang/String;)Ldatadog/trace/core/propagation/PropagationTags; +} + +public final class datadog/trace/core/propagation/PropagationTags$HeaderType : java/lang/Enum { + public static final field DATADOG Ldatadog/trace/core/propagation/PropagationTags$HeaderType; + public static final field W3C Ldatadog/trace/core/propagation/PropagationTags$HeaderType; + public static fun getNumValues ()I + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/core/propagation/PropagationTags$HeaderType; + public static fun values ()[Ldatadog/trace/core/propagation/PropagationTags$HeaderType; +} + +public class datadog/trace/core/propagation/TagContextExtractor : datadog/trace/core/propagation/HttpCodec$Extractor { + public fun (Ljava/util/function/Supplier;Ldatadog/trace/core/propagation/ContextInterpreter$Factory;)V + public fun cleanup ()V + public fun extract (Ljava/lang/Object;Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation$ContextVisitor;)Ldatadog/trace/bootstrap/instrumentation/api/TagContext; +} + +public class datadog/trace/core/propagation/ptags/PTagsFactory : datadog/trace/core/propagation/PropagationTags$Factory { + public fun (I)V + public final fun empty ()Ldatadog/trace/core/propagation/PropagationTags; + public final fun fromHeaderValue (Ldatadog/trace/core/propagation/PropagationTags$HeaderType;Ljava/lang/String;)Ldatadog/trace/core/propagation/PropagationTags; +} + +public class datadog/trace/core/propagation/ptags/W3CPTagsCodec { + protected static final field DECISION_MAKER_TAG Ldatadog/trace/core/propagation/ptags/TagKey; + protected static final field PROPAGATION_ERROR_INCONSISTENT_TID Ljava/lang/String; + protected static final field PROPAGATION_ERROR_MALFORMED_TID Ljava/lang/String; + protected static final field TRACE_ID_TAG Ldatadog/trace/core/propagation/ptags/TagKey; + protected static final field UPSTREAM_SERVICES_DEPRECATED_TAG Ldatadog/trace/core/propagation/ptags/TagKey; + public fun ()V + protected fun appendPrefix (Ljava/lang/StringBuilder;Ldatadog/trace/core/propagation/ptags/PTagsFactory$PTags;)I + protected fun appendSuffix (Ljava/lang/StringBuilder;Ldatadog/trace/core/propagation/ptags/PTagsFactory$PTags;I)I + protected fun appendTag (Ljava/lang/StringBuilder;Ldatadog/trace/core/propagation/ptags/TagElement;Ldatadog/trace/core/propagation/ptags/TagElement;I)I + protected fun estimateHeaderSize (Ldatadog/trace/core/propagation/ptags/PTagsFactory$PTags;)I + protected static fun isDigit (C)Z + protected fun isEmpty (Ljava/lang/StringBuilder;I)Z + protected static fun isHexDigit (C)Z + protected fun isTooLarge (Ljava/lang/StringBuilder;I)Z + protected static fun validateTagValue (Ldatadog/trace/core/propagation/ptags/TagKey;Ldatadog/trace/core/propagation/ptags/TagValue;)Z +} + +public final class datadog/trace/core/scopemanager/ContinuableScopeManager : datadog/trace/bootstrap/instrumentation/api/AgentScopeManager { + public fun (IZZ)V + public fun (IZZLdatadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration;Ldatadog/trace/core/monitor/HealthMetrics;)V + public fun activate (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public fun activate (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/bootstrap/instrumentation/api/ScopeSource;Z)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public fun activateNext (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public fun active ()Ldatadog/trace/bootstrap/instrumentation/api/AgentScope; + public fun activeSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; + public fun addScopeListener (Ldatadog/trace/api/scopemanager/ScopeListener;)V + public fun captureSpan (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/bootstrap/instrumentation/api/AgentScope$Continuation; + public fun closePrevious (Z)V + public fun newScopeState ()Ldatadog/trace/bootstrap/instrumentation/api/ScopeState; +} + +public class datadog/trace/core/taginterceptor/RuleFlags { + public fun ()V + public fun (Ldatadog/trace/api/Config;)V + public fun isEnabled (Ldatadog/trace/core/taginterceptor/RuleFlags$Feature;)Z +} + +public final class datadog/trace/core/taginterceptor/RuleFlags$Feature : java/lang/Enum { + public static final field DB_STATEMENT Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static final field FORCE_MANUAL_DROP Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static final field FORCE_MANUAL_KEEP Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static final field PEER_SERVICE Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static final field RESOURCE_NAME Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static final field SERVICE_NAME Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static final field SERVLET_CONTEXT Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static final field STATUS_404 Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static final field STATUS_404_DECORATOR Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static final field URL_AS_RESOURCE_NAME Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; + public static fun values ()[Ldatadog/trace/core/taginterceptor/RuleFlags$Feature; +} + +public class datadog/trace/core/taginterceptor/TagInterceptor { + public fun (Ldatadog/trace/core/taginterceptor/RuleFlags;)V + public fun (ZLjava/lang/String;Ljava/util/Set;Ldatadog/trace/core/taginterceptor/RuleFlags;)V + public fun interceptTag (Ldatadog/trace/core/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z +} + +public class datadog/trace/core/tagprocessor/BaseServiceAdder : datadog/trace/core/tagprocessor/TagsPostProcessor { + public fun (Ljava/lang/String;)V + public fun processTags (Ljava/util/Map;)Ljava/util/Map; + public fun processTagsWithContext (Ljava/util/Map;Ldatadog/trace/core/DDSpanContext;)Ljava/util/Map; +} + +public class datadog/trace/core/tagprocessor/PeerServiceCalculator : datadog/trace/core/tagprocessor/TagsPostProcessor { + public fun ()V + public fun processTags (Ljava/util/Map;)Ljava/util/Map; +} + +public class datadog/trace/core/tagprocessor/PostProcessorChain : datadog/trace/core/tagprocessor/TagsPostProcessor { + public fun ([Ldatadog/trace/core/tagprocessor/TagsPostProcessor;)V + public fun processTags (Ljava/util/Map;)Ljava/util/Map; + public fun processTagsWithContext (Ljava/util/Map;Ldatadog/trace/core/DDSpanContext;)Ljava/util/Map; +} + +public class datadog/trace/core/tagprocessor/QueryObfuscator : datadog/trace/core/tagprocessor/TagsPostProcessor { + public fun (Ljava/lang/String;)V + public fun processTags (Ljava/util/Map;)Ljava/util/Map; +} + +public abstract interface class datadog/trace/core/tagprocessor/TagsPostProcessor { + public abstract fun processTags (Ljava/util/Map;)Ljava/util/Map; + public fun processTagsWithContext (Ljava/util/Map;Ldatadog/trace/core/DDSpanContext;)Ljava/util/Map; +} + +public final class datadog/trace/core/tagprocessor/TagsPostProcessorFactory { + public fun ()V + public static fun instance ()Ldatadog/trace/core/tagprocessor/TagsPostProcessor; + public static fun reset ()V + public static fun withAddBaseService (Z)V +} + +public final class datadog/trace/core/util/GlobPattern { + public static fun globToRegexPattern (Ljava/lang/String;)Ljava/util/regex/Pattern; +} + +public final class datadog/trace/core/util/LRUCache : java/util/LinkedHashMap { + public fun (I)V + public fun (IFI)V + public fun (II)V + public fun (Ldatadog/trace/core/util/LRUCache$ExpiryListener;IFI)V +} + +public abstract interface class datadog/trace/core/util/LRUCache$ExpiryListener { + public abstract fun accept (Ljava/util/Map$Entry;)V +} + +public abstract interface class datadog/trace/core/util/Matcher { + public abstract fun matches (Ljava/lang/CharSequence;)Z + public abstract fun matches (Ljava/lang/String;)Z +} + +public final class datadog/trace/core/util/Matchers { + public static fun compileGlob (Ljava/lang/String;)Ldatadog/trace/core/util/Matcher; + public static fun matches (Ldatadog/trace/core/util/Matcher;Ljava/lang/CharSequence;)Z + public static fun matches (Ldatadog/trace/core/util/Matcher;Ljava/lang/String;)Z +} + +public class datadog/trace/core/util/SimpleRateLimiter { + public fun (I)V + protected fun (ILdatadog/trace/api/time/TimeSource;)V + public fun getCapacity ()I + public fun tryAcquire ()Z +} + +public final class datadog/trace/core/util/SystemAccess { + public fun ()V + public static fun disableJmx ()V + public static fun enableJmx ()V + public static fun getCurrentThreadCpuTime ()J +} + +public abstract interface class datadog/trace/core/util/SystemAccessProvider { + public static final field NONE Ldatadog/trace/core/util/SystemAccessProvider; + public abstract fun getThreadCpuTime ()J +} + +public class datadog/trace/core/util/TagsMatcher { + public fun (Ljava/util/Map;)V + public static fun create (Ljava/util/Map;)Ldatadog/trace/core/util/TagsMatcher; + public fun matches (Ldatadog/trace/core/CoreSpan;)Z +} + +public abstract interface class datadog/trace/ddagent/DroppingPolicy { + public static final field DISABLED Ldatadog/trace/ddagent/DroppingPolicy; + public abstract fun active ()Z +} + +public class datadog/trace/ddagent/DroppingPolicy$DisabledDroppingPolicy : datadog/trace/ddagent/DroppingPolicy { + public fun ()V + public fun active ()Z +} + +public class datadog/trace/lambda/LambdaHandler { + public fun ()V + public static fun notifyEndInvocation (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Z)Z + public static fun notifyStartInvocation (Ljava/lang/Object;Ldatadog/trace/core/propagation/PropagationTags$Factory;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; + public static fun setExtensionBaseUrl (Ljava/lang/String;)V + public static fun writeValueAsString (Ljava/lang/Object;)Ljava/lang/String; +} + +public final class datadog/trace/lambda/ReadFromInputStreamJsonAdapter : com/squareup/moshi/JsonAdapter { + public fun ()V + public fun fromJson (Lcom/squareup/moshi/JsonReader;)Ljava/io/ByteArrayInputStream; + public synthetic fun fromJson (Lcom/squareup/moshi/JsonReader;)Ljava/lang/Object; + public fun toJson (Lcom/squareup/moshi/JsonWriter;Ljava/io/ByteArrayInputStream;)V + public synthetic fun toJson (Lcom/squareup/moshi/JsonWriter;Ljava/lang/Object;)V +} + +public final class datadog/trace/lambda/SkipUnsupportedTypeJsonAdapter : com/squareup/moshi/JsonAdapter { + public fun ()V + public fun fromJson (Lcom/squareup/moshi/JsonReader;)Ljava/lang/Object; + public static fun newFactory ()Lcom/squareup/moshi/JsonAdapter$Factory; + public fun toJson (Lcom/squareup/moshi/JsonWriter;Ljava/lang/Object;)V +} + +public class datadog/trace/logging/GlobalLogLevelSwitcher : datadog/trace/logging/LogLevelSwitcher { + public static fun get ()Ldatadog/trace/logging/LogLevelSwitcher; + public fun reinitialize ()V + public fun restore ()V + public fun switchLevel (Ldatadog/trace/logging/LogLevel;)V +} + +public final class datadog/trace/logging/LogLevel : java/lang/Enum { + public static final field DEBUG Ldatadog/trace/logging/LogLevel; + public static final field ERROR Ldatadog/trace/logging/LogLevel; + public static final field INFO Ldatadog/trace/logging/LogLevel; + public static final field OFF Ldatadog/trace/logging/LogLevel; + public static final field TRACE Ldatadog/trace/logging/LogLevel; + public static final field WARN Ldatadog/trace/logging/LogLevel; + public static fun fromString (Ljava/lang/String;)Ldatadog/trace/logging/LogLevel; + public fun isEnabled (Ldatadog/trace/logging/LogLevel;)Z + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/logging/LogLevel; + public static fun values ()[Ldatadog/trace/logging/LogLevel; +} + +public abstract interface class datadog/trace/logging/LogLevelSwitcher { + public abstract fun reinitialize ()V + public abstract fun restore ()V + public abstract fun switchLevel (Ldatadog/trace/logging/LogLevel;)V +} + +public final class datadog/trace/logging/LoggingSettingsDescription { + public static fun getDescription ()Ljava/util/Map; + public static fun setDescription (Ljava/util/Map;)V +} + +public abstract interface class datadog/trace/monitor/Counter { + public abstract fun increment (I)V + public abstract fun incrementErrorCount (Ljava/lang/String;I)V +} + +public abstract interface class datadog/trace/monitor/Monitoring { + public static final field DISABLED Ldatadog/trace/monitor/Monitoring; + public abstract fun newCounter (Ljava/lang/String;)Ldatadog/trace/monitor/Counter; + public abstract fun newThreadLocalTimer (Ljava/lang/String;)Ldatadog/trace/monitor/Recording; + public abstract fun newTimer (Ljava/lang/String;)Ldatadog/trace/monitor/Recording; + public abstract fun newTimer (Ljava/lang/String;[Ljava/lang/String;)Ldatadog/trace/monitor/Recording; +} + +public class datadog/trace/monitor/Monitoring$DisabledMonitoring : datadog/trace/monitor/Monitoring { + public fun newCounter (Ljava/lang/String;)Ldatadog/trace/monitor/Counter; + public fun newThreadLocalTimer (Ljava/lang/String;)Ldatadog/trace/monitor/Recording; + public fun newTimer (Ljava/lang/String;)Ldatadog/trace/monitor/Recording; + public fun newTimer (Ljava/lang/String;[Ljava/lang/String;)Ldatadog/trace/monitor/Recording; +} + +public final class datadog/trace/monitor/NoOpCounter : datadog/trace/monitor/Counter { + public static final field NO_OP Ldatadog/trace/monitor/Counter; + public fun ()V + public fun increment (I)V + public fun incrementErrorCount (Ljava/lang/String;I)V +} + +public class datadog/trace/monitor/NoOpRecording : datadog/trace/monitor/Recording { + public static final field NO_OP Ldatadog/trace/monitor/Recording; + public fun ()V + public fun flush ()V + public fun reset ()V + public fun start ()Ldatadog/trace/monitor/Recording; + public fun stop ()V +} + +public abstract class datadog/trace/monitor/Recording : java/lang/AutoCloseable { + public fun ()V + public fun close ()V + public abstract fun flush ()V + public abstract fun reset ()V + public abstract fun start ()Ldatadog/trace/monitor/Recording; + public abstract fun stop ()V +} + +public class datadog/trace/relocate/api/IOLogger { + public fun (Lorg/slf4j/Logger;)V + public fun error (Ljava/lang/String;)Z + public fun error (Ljava/lang/String;Ldatadog/trace/relocate/api/IOLogger$Response;)Z + public fun error (Ljava/lang/String;Ldatadog/trace/relocate/api/IOLogger$Response;Ljava/lang/Exception;)Z + public fun error (Ljava/lang/String;Ljava/lang/Exception;)Z + public fun success (Ljava/lang/String;[Ljava/lang/Object;)Z +} + +public final class datadog/trace/relocate/api/IOLogger$Response { + public fun (ILjava/lang/String;Ljava/lang/String;)V + public fun getBody ()Ljava/lang/String; + public fun getMessage ()Ljava/lang/String; + public fun getStatusCode ()I +} + +public class datadog/trace/relocate/api/RatelimitedLogger { + public fun (Lorg/slf4j/Logger;ILjava/util/concurrent/TimeUnit;)V + public fun warn (Ljava/lang/String;[Ljava/lang/Object;)Z +} + +public abstract interface class datadog/trace/serialization/ByteBufferConsumer { + public abstract fun accept (ILjava/nio/ByteBuffer;)V +} + +public final class datadog/trace/serialization/Codec : java/lang/ClassValue { + public static final field INSTANCE Ldatadog/trace/serialization/Codec; + public fun ()V + public fun (Ljava/util/Map;)V +} + +public abstract interface class datadog/trace/serialization/EncodingCache { + public abstract fun encode (Ljava/lang/CharSequence;)[B +} + +public final class datadog/trace/serialization/FlushingBuffer : datadog/trace/serialization/StreamingBuffer { + public fun (ILdatadog/trace/serialization/ByteBufferConsumer;)V + public fun capacity ()I + public fun flush ()Z + public fun isDirty ()Z + public fun mark ()V + public fun put (B)V + public fun put (Ljava/nio/ByteBuffer;)V + public fun put ([B)V + public fun put ([BII)V + public fun putChar (C)V + public fun putDouble (D)V + public fun putFloat (F)V + public fun putInt (I)V + public fun putLong (J)V + public fun putShort (S)V + public fun reset ()V +} + +public final class datadog/trace/serialization/GrowableBuffer : datadog/trace/serialization/StreamingBuffer { + public fun (I)V + public fun capacity ()I + public fun flush ()Z + public fun isDirty ()Z + public fun mark ()V + public fun messageCount ()I + public fun put (B)V + public fun put (Ljava/nio/ByteBuffer;)V + public fun put ([B)V + public fun put ([BII)V + public fun putChar (C)V + public fun putDouble (D)V + public fun putFloat (F)V + public fun putInt (I)V + public fun putLong (J)V + public fun putShort (S)V + public fun reset ()V + public fun slice ()Ljava/nio/ByteBuffer; +} + +public abstract interface class datadog/trace/serialization/Mapper { + public abstract fun map (Ljava/lang/Object;Ldatadog/trace/serialization/Writable;)V +} + +public abstract interface class datadog/trace/serialization/MessageFormatter { + public abstract fun flush ()V + public abstract fun format (Ljava/lang/Object;Ldatadog/trace/serialization/Mapper;)Z +} + +public abstract interface class datadog/trace/serialization/StreamingBuffer { + public abstract fun capacity ()I + public abstract fun flush ()Z + public abstract fun isDirty ()Z + public abstract fun mark ()V + public abstract fun put (B)V + public abstract fun put (Ljava/nio/ByteBuffer;)V + public abstract fun put ([B)V + public abstract fun put ([BII)V + public abstract fun putChar (C)V + public abstract fun putDouble (D)V + public abstract fun putFloat (F)V + public abstract fun putInt (I)V + public abstract fun putLong (J)V + public abstract fun putShort (S)V + public abstract fun reset ()V +} + +public abstract interface class datadog/trace/serialization/ValueWriter { + public abstract fun write (Ljava/lang/Object;Ldatadog/trace/serialization/Writable;Ldatadog/trace/serialization/EncodingCache;)V +} + +public abstract interface class datadog/trace/serialization/Writable { + public abstract fun startArray (I)V + public abstract fun startMap (I)V + public abstract fun startStruct (I)V + public abstract fun writeBinary (Ljava/nio/ByteBuffer;)V + public abstract fun writeBinary ([B)V + public abstract fun writeBinary ([BII)V + public abstract fun writeBoolean (Z)V + public abstract fun writeDouble (D)V + public abstract fun writeFloat (F)V + public abstract fun writeInt (I)V + public abstract fun writeLong (J)V + public abstract fun writeMap (Ljava/util/Map;Ldatadog/trace/serialization/EncodingCache;)V + public abstract fun writeNull ()V + public abstract fun writeObject (Ljava/lang/Object;Ldatadog/trace/serialization/EncodingCache;)V + public abstract fun writeObjectString (Ljava/lang/Object;Ldatadog/trace/serialization/EncodingCache;)V + public abstract fun writeSignedInt (I)V + public abstract fun writeSignedLong (J)V + public abstract fun writeString (Ljava/lang/CharSequence;Ldatadog/trace/serialization/EncodingCache;)V + public abstract fun writeUTF8 (Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString;)V + public abstract fun writeUTF8 ([B)V + public abstract fun writeUTF8 ([BII)V + public abstract fun writeUnsignedLong (J)V +} + +public abstract interface class datadog/trace/serialization/WritableFormatter : datadog/trace/serialization/MessageFormatter, datadog/trace/serialization/Writable { +} + +public class datadog/trace/serialization/msgpack/MsgPackWriter : datadog/trace/serialization/WritableFormatter { + public static final field ARRAY16 B + public static final field ARRAY32 B + public static final field BIN16 B + public static final field BIN32 B + public static final field BIN8 B + public static final field FALSE B + public static final field FIXARRAY I + public static final field FIXMAP I + public static final field FIXSTR I + public static final field FLOAT32 B + public static final field FLOAT64 B + public static final field INT16 B + public static final field INT32 B + public static final field INT64 B + public static final field INT8 B + public static final field MAP16 B + public static final field MAP32 B + public static final field NEGFIXNUM I + public static final field NULL B + public static final field STR16 B + public static final field STR32 B + public static final field STR8 B + public static final field TRUE B + public static final field UINT16 B + public static final field UINT32 B + public static final field UINT64 B + public static final field UINT8 B + public fun (Ldatadog/trace/serialization/Codec;Ldatadog/trace/serialization/StreamingBuffer;)V + public fun (Ldatadog/trace/serialization/StreamingBuffer;)V + public fun flush ()V + public fun format (Ljava/lang/Object;Ldatadog/trace/serialization/Mapper;)Z + public fun startArray (I)V + public fun startMap (I)V + public fun startStruct (I)V + public fun writeBinary (Ljava/nio/ByteBuffer;)V + public fun writeBinary ([B)V + public fun writeBinary ([BII)V + public fun writeBoolean (Z)V + public fun writeDouble (D)V + public fun writeFloat (F)V + public fun writeInt (I)V + public fun writeLong (J)V + public fun writeLongInternal (JZ)V + public fun writeMap (Ljava/util/Map;Ldatadog/trace/serialization/EncodingCache;)V + public fun writeNull ()V + public fun writeObject (Ljava/lang/Object;Ldatadog/trace/serialization/EncodingCache;)V + public fun writeObjectString (Ljava/lang/Object;Ldatadog/trace/serialization/EncodingCache;)V + public fun writeSignedInt (I)V + public fun writeSignedLong (J)V + public fun writeString (Ljava/lang/CharSequence;Ldatadog/trace/serialization/EncodingCache;)V + public fun writeUTF8 (Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString;)V + public fun writeUTF8 ([B)V + public fun writeUTF8 ([BII)V + public fun writeUnsignedLong (J)V +} + +public final class datadog/trace/util/AgentProxySelector : java/net/ProxySelector { + public static final field INSTANCE Ljava/net/ProxySelector; + public fun ()V + public fun connectFailed (Ljava/net/URI;Ljava/net/SocketAddress;Ljava/io/IOException;)V + public fun select (Ljava/net/URI;)Ljava/util/List; +} + +public class datadog/trace/util/AgentTaskScheduler : java/util/concurrent/Executor { + public static final field INSTANCE Ldatadog/trace/util/AgentTaskScheduler; + public fun (Ldatadog/trace/util/AgentThreadFactory$AgentThread;)V + public fun execute (Ljava/lang/Runnable;)V + public static fun initialize ()V + public fun isShutdown ()Z + public fun schedule (Ldatadog/trace/util/AgentTaskScheduler$Task;Ljava/lang/Object;JLjava/util/concurrent/TimeUnit;)Ldatadog/trace/util/AgentTaskScheduler$Scheduled; + public fun schedule (Ljava/lang/Runnable;JLjava/util/concurrent/TimeUnit;)Ldatadog/trace/util/AgentTaskScheduler$Scheduled; + public fun scheduleAtFixedRate (Ldatadog/trace/util/AgentTaskScheduler$Task;Ljava/lang/Object;JJLjava/util/concurrent/TimeUnit;)Ldatadog/trace/util/AgentTaskScheduler$Scheduled; + public fun scheduleAtFixedRate (Ljava/lang/Runnable;JJLjava/util/concurrent/TimeUnit;)Ldatadog/trace/util/AgentTaskScheduler$Scheduled; + public fun scheduleWithJitter (Ldatadog/trace/util/AgentTaskScheduler$Task;Ljava/lang/Object;JLjava/util/concurrent/TimeUnit;)Ldatadog/trace/util/AgentTaskScheduler$Scheduled; + public fun scheduleWithJitter (Ljava/lang/Runnable;JLjava/util/concurrent/TimeUnit;)Ldatadog/trace/util/AgentTaskScheduler$Scheduled; + public fun shutdown (JLjava/util/concurrent/TimeUnit;)V + public fun weakScheduleAtFixedRate (Ldatadog/trace/util/AgentTaskScheduler$Task;Ljava/lang/Object;JJLjava/util/concurrent/TimeUnit;)V + public fun weakScheduleAtFixedRate (Ljava/lang/Runnable;JJLjava/util/concurrent/TimeUnit;)V +} + +public final class datadog/trace/util/AgentTaskScheduler$RunnableTask : datadog/trace/util/AgentTaskScheduler$Task { + public static final field INSTANCE Ldatadog/trace/util/AgentTaskScheduler$RunnableTask; + public fun ()V + public synthetic fun run (Ljava/lang/Object;)V + public fun run (Ljava/lang/Runnable;)V +} + +public class datadog/trace/util/AgentTaskScheduler$Scheduled : datadog/trace/util/AgentTaskScheduler$Target { + public fun cancel ()V + public fun get ()Ljava/lang/Object; +} + +public abstract interface class datadog/trace/util/AgentTaskScheduler$Target { + public abstract fun get ()Ljava/lang/Object; +} + +public abstract interface class datadog/trace/util/AgentTaskScheduler$Task { + public abstract fun run (Ljava/lang/Object;)V +} + +public final class datadog/trace/util/AgentThreadFactory : java/util/concurrent/ThreadFactory { + public static final field AGENT_THREAD_GROUP Ljava/lang/ThreadGroup; + public static final field THREAD_JOIN_TIMOUT_MS J + public fun (Ldatadog/trace/util/AgentThreadFactory$AgentThread;)V + public static fun newAgentThread (Ldatadog/trace/util/AgentThreadFactory$AgentThread;Ljava/lang/Runnable;)Ljava/lang/Thread; + public static fun newAgentThread (Ldatadog/trace/util/AgentThreadFactory$AgentThread;Ljava/lang/Runnable;Z)Ljava/lang/Thread; + public static fun newAgentThread (Ldatadog/trace/util/AgentThreadFactory$AgentThread;Ljava/lang/String;Ljava/lang/Runnable;Z)Ljava/lang/Thread; + public fun newThread (Ljava/lang/Runnable;)Ljava/lang/Thread; +} + +public final class datadog/trace/util/AgentThreadFactory$AgentThread : java/lang/Enum { + public static final field APPSEC_HTTP_DISPATCHER Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field CI_GIT_DATA_SHUTDOWN_HOOK Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field CI_GIT_DATA_UPLOADER Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field CI_PROJECT_CONFIGURATOR Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field CI_SHELL_COMMAND Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field CI_SIGNAL_SERVER Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field CI_TEST_EVENTS_SHUTDOWN_HOOK Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field CWS_TLS Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field DATA_STREAMS_MONITORING Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field DEBUGGER_HTTP_DISPATCHER Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field FLEET_MANAGEMENT_POLLER Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field JMX_COLLECTOR Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field JMX_STARTUP Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field METRICS_AGGREGATOR Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field PROCESS_SUPERVISOR Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field PROFILER_HTTP_DISPATCHER Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field PROFILER_RECORDING_SCHEDULER Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field PROFILER_STARTUP Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field REMOTE_CONFIG Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field SPAN_SAMPLING_PROCESSOR Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field STATSD_CLIENT Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field TASK_SCHEDULER Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field TELEMETRY Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field TRACER_FLARE Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field TRACE_CASSANDRA_ASYNC_SESSION Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field TRACE_MONITOR Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field TRACE_PROCESSOR Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static final field TRACE_STARTUP Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public final field threadName Ljava/lang/String; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/util/AgentThreadFactory$AgentThread; + public static fun values ()[Ldatadog/trace/util/AgentThreadFactory$AgentThread; +} + +public final class datadog/trace/util/ClassNameTrie { + public fun apply (Ljava/lang/String;)I + public static fun apply ([C[ILjava/lang/String;)I + public static fun readFrom (Ljava/io/DataInput;)Ldatadog/trace/util/ClassNameTrie; +} + +public class datadog/trace/util/ClassNameTrie$Builder { + public static final field EMPTY_TRIE Ldatadog/trace/util/ClassNameTrie; + public fun ()V + public fun (Ldatadog/trace/util/ClassNameTrie;)V + public fun apply (Ljava/lang/String;)I + public fun buildTrie ()Ldatadog/trace/util/ClassNameTrie; + public fun isEmpty ()Z + public fun put (Ljava/lang/String;I)V + public fun readClassNameMapping (Ljava/nio/file/Path;)V + public fun writeTo (Ljava/io/DataOutput;)V +} + +public class datadog/trace/util/ClassNameTrie$JavaGenerator { + public fun ()V + public static fun generateJavaTrie (Ljava/util/List;Ljava/lang/String;Ldatadog/trace/util/ClassNameTrie$Builder;)Z + public static fun main ([Ljava/lang/String;)V +} + +public final class datadog/trace/util/CollectionUtils { + public fun ()V + public static fun tryMakeImmutableList (Ljava/util/Collection;)Ljava/util/List; + public static fun tryMakeImmutableMap (Ljava/util/Map;)Ljava/util/Map; + public static fun tryMakeImmutableSet (Ljava/util/Collection;)Ljava/util/Set; +} + +public class datadog/trace/util/FNV64Hash { + public fun ()V + public static fun generateHash (Ljava/lang/String;Ldatadog/trace/util/FNV64Hash$Version;)J + public static fun generateHash ([BIILdatadog/trace/util/FNV64Hash$Version;)J + public static fun generateHash ([BLdatadog/trace/util/FNV64Hash$Version;)J +} + +public final class datadog/trace/util/FNV64Hash$Version : java/lang/Enum { + public static final field v1 Ldatadog/trace/util/FNV64Hash$Version; + public static final field v1A Ldatadog/trace/util/FNV64Hash$Version; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/util/FNV64Hash$Version; + public static fun values ()[Ldatadog/trace/util/FNV64Hash$Version; +} + +public class datadog/trace/util/MethodHandles { + public fun (Ljava/lang/ClassLoader;)V + public fun constructor (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; + public fun constructor (Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; + public fun invoke (Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object; + public fun method (Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; + public fun method (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; + public fun privateFieldGetter (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/invoke/MethodHandle; + public fun privateFieldGetter (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/invoke/MethodHandle; + public fun privateFieldSetter (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/invoke/MethodHandle; + public fun privateFieldSetter (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/invoke/MethodHandle; +} + +public final class datadog/trace/util/PidHelper { + public fun ()V + public static fun getPid ()Ljava/lang/String; + public static fun getPidAsLong ()J +} + +public class datadog/trace/util/ProcessSupervisor : java/io/Closeable { + public static final field ALWAYS_READY Ldatadog/trace/util/ProcessSupervisor$HealthCheck; + public fun (Ljava/lang/String;Ljava/lang/ProcessBuilder;)V + public fun (Ljava/lang/String;Ljava/lang/ProcessBuilder;Ldatadog/trace/util/ProcessSupervisor$HealthCheck;)V + public fun close ()V +} + +public final class datadog/trace/util/ProcessSupervisor$Health : java/lang/Enum { + public static final field FAULTED Ldatadog/trace/util/ProcessSupervisor$Health; + public static final field HEALTHY Ldatadog/trace/util/ProcessSupervisor$Health; + public static final field INTERRUPTED Ldatadog/trace/util/ProcessSupervisor$Health; + public static final field NEVER_CHECKED Ldatadog/trace/util/ProcessSupervisor$Health; + public static final field READY_TO_START Ldatadog/trace/util/ProcessSupervisor$Health; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/util/ProcessSupervisor$Health; + public static fun values ()[Ldatadog/trace/util/ProcessSupervisor$Health; +} + +public abstract interface class datadog/trace/util/ProcessSupervisor$HealthCheck { + public abstract fun run (Ldatadog/trace/util/ProcessSupervisor$Health;)Ldatadog/trace/util/ProcessSupervisor$Health; +} + +public abstract class datadog/trace/util/ProcessUtils { + public static fun getCurrentJvmPath ()Ljava/lang/String; +} + +public final class datadog/trace/util/Strings { + public fun ()V + public static fun escapeToJson (Ljava/lang/String;)Ljava/lang/String; + public static fun getClassName (Ljava/lang/String;)Ljava/lang/String; + public static fun getInternalName (Ljava/lang/String;)Ljava/lang/String; + public static fun getPackageName (Ljava/lang/String;)Ljava/lang/String; + public static fun getResourceName (Ljava/lang/String;)Ljava/lang/String; + public static fun isNotBlank (Ljava/lang/String;)Z + public static fun join (Ljava/lang/CharSequence;Ljava/lang/Iterable;)Ljava/lang/String; + public static fun join (Ljava/lang/CharSequence;[Ljava/lang/CharSequence;)Ljava/lang/String; + public static fun normalizedHeaderTag (Ljava/lang/String;)Ljava/lang/String; + public static fun propertyNameToEnvironmentVariableName (Ljava/lang/String;)Ljava/lang/String; + public static fun propertyNameToSystemPropertyName (Ljava/lang/String;)Ljava/lang/String; + public static fun random (I)Ljava/lang/String; + public static fun replace (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + public static fun replaceFirst (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + public static fun sha256 (Ljava/lang/String;)Ljava/lang/String; + public static fun systemPropertyNameToEnvironmentVariableName (Ljava/lang/String;)Ljava/lang/String; + public static fun toEnvVar (Ljava/lang/String;)Ljava/lang/String; + public static fun toJson (Ljava/lang/Iterable;)Ljava/lang/String; + public static fun toJson (Ljava/util/Map;)Ljava/lang/String; + public static fun toJson (Ljava/util/Map;Z)Ljava/lang/String; + public static fun trim (Ljava/lang/String;)Ljava/lang/String; + public static fun truncate (Ljava/lang/CharSequence;I)Ljava/lang/CharSequence; + public static fun truncate (Ljava/lang/String;I)Ljava/lang/String; +} + +public final class datadog/trace/util/TagsHelper { + public fun ()V + public static fun concatTags ([Ljava/lang/String;)Ljava/lang/String; + public static fun sanitize (Ljava/lang/String;)Ljava/lang/String; +} + +public class datadog/trace/util/TraceUtils { + public fun ()V + public static fun isValidStatusCode (I)Z + public static fun normalizeEnv (Ljava/lang/String;)Ljava/lang/String; + public static fun normalizeOperationName (Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + public static fun normalizeServiceName (Ljava/lang/String;)Ljava/lang/String; + public static fun normalizeSpanType (Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + public static fun normalizeTag (Ljava/lang/String;)Ljava/lang/String; +} + +public abstract class datadog/trace/util/stacktrace/AbstractStackWalker : datadog/trace/util/stacktrace/StackWalker { + public fun ()V + public fun walk (Ljava/util/function/Function;)Ljava/lang/Object; +} + +public class datadog/trace/util/stacktrace/DefaultStackWalker : datadog/trace/util/stacktrace/AbstractStackWalker { + public fun isEnabled ()Z +} + +public abstract class datadog/trace/util/stacktrace/StackUtils { + public fun ()V + public static fun filter (Ljava/lang/Throwable;Ljava/util/function/Predicate;)Ljava/lang/Throwable; + public static fun filterDatadog (Ljava/lang/Throwable;)Ljava/lang/Throwable; + public static fun filterFirst (Ljava/lang/Throwable;Ljava/util/function/Predicate;)Ljava/lang/Throwable; + public static fun filterFirstDatadog (Ljava/lang/Throwable;)Ljava/lang/Throwable; + public static fun filterPackagesIn (Ljava/lang/Throwable;[Ljava/lang/String;)Ljava/lang/Throwable; + public static fun filterUntil (Ljava/lang/Throwable;Ljava/util/function/Predicate;)Ljava/lang/Throwable; + public static fun update (Ljava/lang/Throwable;Ljava/util/function/Function;)Ljava/lang/Throwable; +} + +public abstract interface class datadog/trace/util/stacktrace/StackWalker { + public abstract fun isEnabled ()Z + public abstract fun walk (Ljava/util/function/Function;)Ljava/lang/Object; +} + +public class datadog/trace/util/stacktrace/StackWalkerFactory { + public static final field INSTANCE Ldatadog/trace/util/stacktrace/StackWalker; + public fun ()V +} + +public class datadog/trace/util/throwable/FatalAgentMisconfigurationError : java/lang/Error { + public fun (Ljava/lang/String;)V +} + diff --git a/features/dd-trace-core/build.gradle.kts b/features/dd-trace-core/build.gradle.kts new file mode 100644 index 0000000000..ffb720e938 --- /dev/null +++ b/features/dd-trace-core/build.gradle.kts @@ -0,0 +1,52 @@ +import com.datadog.gradle.config.androidLibraryConfig +import com.datadog.gradle.config.dependencyUpdateConfig +import com.datadog.gradle.config.javadocConfig +import com.datadog.gradle.config.junitConfig + +plugins { + // Build + id("com.android.library") + + // Analysis tools + id("com.github.ben-manes.versions") + + // Tests + id("de.mobilej.unmock") + + // Internal Generation + id("thirdPartyLicences") + id("apiSurface") + id("transitiveDependencies") + id("binary-compatibility-validator") +} + +android { + defaultConfig { + consumerProguardFiles("consumer-rules.pro") + } + compileOptions { + isCoreLibraryDesugaringEnabled = true + } + namespace = "datadog.trace" +} + +dependencies { + coreLibraryDesugaring(libs.desugarJdk) + implementation(libs.slf4j) + implementation(libs.moshi) + implementation(libs.jctools) + implementation(libs.kotlin) + implementation(libs.okHttp) + implementation(libs.kotlin) + implementation(libs.androidXAnnotation) + implementation(libs.datadogSketchesJava) + implementation(libs.re2j) + compileOnly(libs.spotbugs) + + // TODO: RUM-3268 Port and enable the groovy unit tests +} + +androidLibraryConfig() +junitConfig() +javadocConfig() +dependencyUpdateConfig() diff --git a/features/dd-trace-core/consumer-rules.pro b/features/dd-trace-core/consumer-rules.pro new file mode 100644 index 0000000000..8de36b2ecf --- /dev/null +++ b/features/dd-trace-core/consumer-rules.pro @@ -0,0 +1,4 @@ +# Do not warn about missing classes required only at compile time by dependencies +-dontwarn org.slf4j.** +-dontwarn com.google.protobuf.** +-dontwarn edu.umd.cs.findbugs.** diff --git a/features/dd-trace-core/lint.xml b/features/dd-trace-core/lint.xml new file mode 100644 index 0000000000..4fbde87523 --- /dev/null +++ b/features/dd-trace-core/lint.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/features/dd-trace-core/src/main/java/datadog/trace/advice/ActiveRequestContext.java b/features/dd-trace-core/src/main/java/datadog/trace/advice/ActiveRequestContext.java new file mode 100644 index 0000000000..6478e5c4ff --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/advice/ActiveRequestContext.java @@ -0,0 +1,10 @@ +package datadog.trace.advice; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface ActiveRequestContext {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/advice/RequiresRequestContext.java b/features/dd-trace-core/src/main/java/datadog/trace/advice/RequiresRequestContext.java new file mode 100644 index 0000000000..1ac7c06912 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/advice/RequiresRequestContext.java @@ -0,0 +1,19 @@ +package datadog.trace.advice; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import datadog.trace.api.gateway.RequestContext; +import datadog.trace.api.gateway.RequestContextSlot; + +/** + * Transforms the enter and exit advice so that the existence of an active {@link RequestContext} is + * checked before the body of the advice is run. + */ +@Retention(RetentionPolicy.CLASS) +@Target(ElementType.TYPE) +public @interface RequiresRequestContext { + RequestContextSlot value(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Config.java b/features/dd-trace-core/src/main/java/datadog/trace/api/Config.java new file mode 100644 index 0000000000..983f1b3182 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/Config.java @@ -0,0 +1,4165 @@ +package datadog.trace.api; + +import static datadog.trace.api.ConfigDefaults.*; +import static datadog.trace.api.DDTags.HOST_TAG; +import static datadog.trace.api.DDTags.INTERNAL_HOST_NAME; +import static datadog.trace.api.DDTags.LANGUAGE_TAG_KEY; +import static datadog.trace.api.DDTags.LANGUAGE_TAG_VALUE; +import static datadog.trace.api.DDTags.PID_TAG; +import static datadog.trace.api.DDTags.PROFILING_ENABLED; +import static datadog.trace.api.DDTags.RUNTIME_ID_TAG; +import static datadog.trace.api.DDTags.RUNTIME_VERSION_TAG; +import static datadog.trace.api.DDTags.SCHEMA_VERSION_TAG_KEY; +import static datadog.trace.api.DDTags.SERVICE; +import static datadog.trace.api.DDTags.SERVICE_TAG; +import static datadog.trace.api.UserEventTrackingMode.SAFE; +import static datadog.trace.api.config.AppSecConfig.API_SECURITY_ENABLED; +import static datadog.trace.api.config.AppSecConfig.API_SECURITY_REQUEST_SAMPLE_RATE; +import static datadog.trace.api.config.AppSecConfig.APPSEC_AUTOMATED_USER_EVENTS_TRACKING; +import static datadog.trace.api.config.AppSecConfig.APPSEC_HTTP_BLOCKED_TEMPLATE_HTML; +import static datadog.trace.api.config.AppSecConfig.APPSEC_HTTP_BLOCKED_TEMPLATE_JSON; +import static datadog.trace.api.config.AppSecConfig.APPSEC_IP_ADDR_HEADER; +import static datadog.trace.api.config.AppSecConfig.APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP; +import static datadog.trace.api.config.AppSecConfig.APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP; +import static datadog.trace.api.config.AppSecConfig.APPSEC_REPORTING_INBAND; +import static datadog.trace.api.config.AppSecConfig.APPSEC_REPORT_TIMEOUT_SEC; +import static datadog.trace.api.config.AppSecConfig.APPSEC_RULES_FILE; +import static datadog.trace.api.config.AppSecConfig.APPSEC_TRACE_RATE_LIMIT; +import static datadog.trace.api.config.AppSecConfig.APPSEC_WAF_METRICS; +import static datadog.trace.api.config.AppSecConfig.APPSEC_WAF_TIMEOUT; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ADDITIONAL_CHILD_PROCESS_JVM_ARGS; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_URL; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENT_JAR_URI; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AUTO_CONFIGURATION_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CIPROVIDER_INTEGRATION_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_EXCLUDES; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_INCLUDES; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_PERCENTAGE_CALCULATION_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_REPORT_DUMP_DIR; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_ROOT_PACKAGES_LIMIT; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_SEGMENTS_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_COMPILER_PLUGIN_VERSION; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_DEBUG_PORT; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_COUNT; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_REMOTE_NAME; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UNSHALLOW_DEFER; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UNSHALLOW_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UPLOAD_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_INJECTED_TRACER_VERSION; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ITR_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JACOCO_GRADLE_SOURCE_SETS; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JACOCO_PLUGIN_VERSION; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JVM_INFO_CACHE_SIZE; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_EXECUTION_SETTINGS_CACHE_SIZE; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_ID; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_NAME; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_REPO_INDEX_SHARING_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_RESOURCE_FOLDER_NAMES; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SESSION_ID; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_HOST; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_PORT; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SOURCE_DATA_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TRACE_SANITATION_ENABLED; +import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS; +import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS_DEFAULT; +import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_TAGS; +import static datadog.trace.api.config.CwsConfig.CWS_ENABLED; +import static datadog.trace.api.config.CwsConfig.CWS_TLS_REFRESH; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_CAPTURE_TIMEOUT; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_CLASSFILE_DUMP_ENABLED; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_DIAGNOSTICS_INTERVAL; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_ENABLED; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCLUDE_FILES; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_INSTRUMENT_THE_WORLD; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_MAX_PAYLOAD_SIZE; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_METRICS_ENABLED; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_POLL_INTERVAL; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_PROBE_FILE_LOCATION; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTED_IDENTIFIERS; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTED_TYPES; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_ENABLED; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_FLUSH_THRESHOLD; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_FORCE_UPLOAD; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_INCLUDES; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_BATCH_SIZE; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_FLUSH_INTERVAL; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_TIMEOUT; +import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_VERIFY_BYTECODE; +import static datadog.trace.api.config.GeneralConfig.API_KEY; +import static datadog.trace.api.config.GeneralConfig.API_KEY_FILE; +import static datadog.trace.api.config.GeneralConfig.APPLICATION_KEY; +import static datadog.trace.api.config.GeneralConfig.APPLICATION_KEY_FILE; +import static datadog.trace.api.config.GeneralConfig.AZURE_APP_SERVICES; +import static datadog.trace.api.config.GeneralConfig.DATA_STREAMS_BUCKET_DURATION_SECONDS; +import static datadog.trace.api.config.GeneralConfig.DATA_STREAMS_ENABLED; +import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_ARGS; +import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_HOST; +import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_NAMED_PIPE; +import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_PATH; +import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_PORT; +import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_START_DELAY; +import static datadog.trace.api.config.GeneralConfig.ENV; +import static datadog.trace.api.config.GeneralConfig.GLOBAL_TAGS; +import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_ENABLED; +import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_HOST; +import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_PORT; +import static datadog.trace.api.config.GeneralConfig.PERF_METRICS_ENABLED; +import static datadog.trace.api.config.GeneralConfig.PRIMARY_TAG; +import static datadog.trace.api.config.GeneralConfig.RUNTIME_ID_ENABLED; +import static datadog.trace.api.config.GeneralConfig.RUNTIME_METRICS_ENABLED; +import static datadog.trace.api.config.GeneralConfig.SERVICE_NAME; +import static datadog.trace.api.config.GeneralConfig.SITE; +import static datadog.trace.api.config.GeneralConfig.STARTUP_LOGS_ENABLED; +import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_QUEUE_SIZE; +import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_SOCKET_BUFFER; +import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_SOCKET_TIMEOUT; +import static datadog.trace.api.config.GeneralConfig.TAGS; +import static datadog.trace.api.config.GeneralConfig.TELEMETRY_DEPENDENCY_COLLECTION_ENABLED; +import static datadog.trace.api.config.GeneralConfig.TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL; +import static datadog.trace.api.config.GeneralConfig.TELEMETRY_HEARTBEAT_INTERVAL; +import static datadog.trace.api.config.GeneralConfig.TELEMETRY_LOG_COLLECTION_ENABLED; +import static datadog.trace.api.config.GeneralConfig.TELEMETRY_METRICS_INTERVAL; +import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_BUFFERING_ENABLED; +import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_ENABLED; +import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_IGNORED_RESOURCES; +import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_MAX_AGGREGATES; +import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_MAX_PENDING; +import static datadog.trace.api.config.GeneralConfig.TRACE_DEBUG; +import static datadog.trace.api.config.GeneralConfig.TRACE_TRIAGE; +import static datadog.trace.api.config.GeneralConfig.VERSION; +import static datadog.trace.api.config.IastConfig.IAST_DEBUG_ENABLED; +import static datadog.trace.api.config.IastConfig.IAST_DETECTION_MODE; +import static datadog.trace.api.config.IastConfig.IAST_REDACTION_ENABLED; +import static datadog.trace.api.config.IastConfig.IAST_REDACTION_NAME_PATTERN; +import static datadog.trace.api.config.IastConfig.IAST_REDACTION_VALUE_PATTERN; +import static datadog.trace.api.config.IastConfig.IAST_STACKTRACE_LEAK_SUPPRESS; +import static datadog.trace.api.config.IastConfig.IAST_TELEMETRY_VERBOSITY; +import static datadog.trace.api.config.IastConfig.IAST_TRUNCATION_MAX_VALUE_LENGTH; +import static datadog.trace.api.config.IastConfig.IAST_WEAK_CIPHER_ALGORITHMS; +import static datadog.trace.api.config.IastConfig.IAST_WEAK_HASH_ALGORITHMS; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CHECK_PERIOD; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CONFIG; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CONFIG_DIR; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_ENABLED; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_INITIAL_REFRESH_BEANS_PERIOD; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_METRICS_CONFIGS; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_REFRESH_BEANS_PERIOD; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_START_DELAY; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_HOST; +import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_PORT; +import static datadog.trace.api.config.JmxFetchConfig.JMX_TAGS; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_OLD; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_VERY_OLD; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_OLD; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_VERY_OLD; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_RECORD_MESSAGE; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_RECORD_MESSAGE_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_SAMPLE_LIMIT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_SAMPLE_LIMIT_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCLUDE_AGENT_THREADS; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_HOST; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PASSWORD; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PORT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PORT_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_USERNAME; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_DELAY; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_DELAY_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_FORCE_FIRST; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_FORCE_FIRST_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_TAGS; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_TEMPLATE_OVERRIDE_FILE; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_COMPRESSION; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_COMPRESSION_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_PERIOD; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_PERIOD_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_SUMMARY_ON_413; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_SUMMARY_ON_413_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_TIMEOUT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_TIMEOUT_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_URL; +import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_ENABLED; +import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED; +import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_MAX_PAYLOAD_SIZE; +import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_POLL_INTERVAL_SECONDS; +import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_TARGETS_KEY; +import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_TARGETS_KEY_ID; +import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_URL; +import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_HOST; +import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE; +import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX; +import static datadog.trace.api.config.TraceInstrumentationConfig.DB_DBM_PROPAGATION_MODE_MODE; +import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_AND_PARAMS_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_PARAMS_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.GOOGLE_PUBSUB_IGNORED_GRPC_METHODS; +import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_CLIENT_ERROR_STATUSES; +import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_IGNORED_INBOUND_METHODS; +import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_IGNORED_OUTBOUND_METHODS; +import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_SERVER_ERROR_STATUSES; +import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_SERVER_TRIM_PACKAGE_RESOURCE; +import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN; +import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_TAG_HEADERS; +import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_TAG_QUERY_STRING; +import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_DECODED_RESOURCE_PRESERVE_SPACES; +import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_QUERY_STRING; +import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_RESOURCE; +import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_ROUTE_BASED_NAMING; +import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_TAG_QUERY_STRING; +import static datadog.trace.api.config.TraceInstrumentationConfig.HYSTRIX_MEASURED_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.HYSTRIX_TAGS_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.IGNITE_CACHE_INCLUDE_KEYS; +import static datadog.trace.api.config.TraceInstrumentationConfig.INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME; +import static datadog.trace.api.config.TraceInstrumentationConfig.JAX_RS_EXCEPTION_AS_ERROR_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_PROPAGATION_DISABLED_QUEUES; +import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_PROPAGATION_DISABLED_TOPICS; +import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_UNACKNOWLEDGED_MAX_AGE; +import static datadog.trace.api.config.TraceInstrumentationConfig.KAFKA_CLIENT_BASE64_DECODING_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS; +import static datadog.trace.api.config.TraceInstrumentationConfig.LOGS_INJECTION_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.MESSAGE_BROKER_SPLIT_BY_DESTINATION; +import static datadog.trace.api.config.TraceInstrumentationConfig.OBFUSCATION_QUERY_STRING_REGEXP; +import static datadog.trace.api.config.TraceInstrumentationConfig.PLAY_REPORT_HTTP_STATUS; +import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_INCLUDE_ROUTINGKEY_IN_RESOURCE; +import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_PROPAGATION_DISABLED_EXCHANGES; +import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_PROPAGATION_DISABLED_QUEUES; +import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ASYNC_TIMEOUT_ERROR; +import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_PRINCIPAL_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ROOT_CONTEXT_SERVICE_NAME; +import static datadog.trace.api.config.TraceInstrumentationConfig.SPARK_TASK_HISTOGRAM_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME; +import static datadog.trace.api.config.TracerConfig.AGENT_HOST; +import static datadog.trace.api.config.TracerConfig.AGENT_NAMED_PIPE; +import static datadog.trace.api.config.TracerConfig.AGENT_PORT_LEGACY; +import static datadog.trace.api.config.TracerConfig.AGENT_TIMEOUT; +import static datadog.trace.api.config.TracerConfig.AGENT_UNIX_DOMAIN_SOCKET; +import static datadog.trace.api.config.TracerConfig.BAGGAGE_MAPPING; +import static datadog.trace.api.config.TracerConfig.CLIENT_IP_ENABLED; +import static datadog.trace.api.config.TracerConfig.CLOCK_SYNC_PERIOD; +import static datadog.trace.api.config.TracerConfig.ENABLE_TRACE_AGENT_V05; +import static datadog.trace.api.config.TracerConfig.HEADER_TAGS; +import static datadog.trace.api.config.TracerConfig.HTTP_CLIENT_ERROR_STATUSES; +import static datadog.trace.api.config.TracerConfig.HTTP_SERVER_ERROR_STATUSES; +import static datadog.trace.api.config.TracerConfig.ID_GENERATION_STRATEGY; +import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_ENABLED; +import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_MIN_SPANS; +import static datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING; +import static datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING_FORCE; +import static datadog.trace.api.config.TracerConfig.PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED; +import static datadog.trace.api.config.TracerConfig.PROPAGATION_STYLE_EXTRACT; +import static datadog.trace.api.config.TracerConfig.PROPAGATION_STYLE_INJECT; +import static datadog.trace.api.config.TracerConfig.PROXY_NO_PROXY; +import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS; +import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS_COMMA_ALLOWED; +import static datadog.trace.api.config.TracerConfig.RESPONSE_HEADER_TAGS; +import static datadog.trace.api.config.TracerConfig.SCOPE_DEPTH_LIMIT; +import static datadog.trace.api.config.TracerConfig.SCOPE_INHERIT_ASYNC_PROPAGATION; +import static datadog.trace.api.config.TracerConfig.SCOPE_ITERATION_KEEP_ALIVE; +import static datadog.trace.api.config.TracerConfig.SCOPE_STRICT_MODE; +import static datadog.trace.api.config.TracerConfig.SECURE_RANDOM; +import static datadog.trace.api.config.TracerConfig.SERVICE_MAPPING; +import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES; +import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES_FILE; +import static datadog.trace.api.config.TracerConfig.SPAN_TAGS; +import static datadog.trace.api.config.TracerConfig.SPLIT_BY_TAGS; +import static datadog.trace.api.config.TracerConfig.TRACE_128_BIT_TRACEID_GENERATION_ENABLED; +import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_ARGS; +import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_PATH; +import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_PORT; +import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_URL; +import static datadog.trace.api.config.TracerConfig.TRACE_ANALYTICS_ENABLED; +import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_HEADER; +import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_RESOLVER_ENABLED; +import static datadog.trace.api.config.TracerConfig.TRACE_GIT_METADATA_ENABLED; +import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING; +import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH; +import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING; +import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_COMPONENT_OVERRIDES; +import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_DEFAULTS_ENABLED; +import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_MAPPING; +import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_EXTRACT_FIRST; +import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE; +import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE_EXTRACT; +import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE_INJECT; +import static datadog.trace.api.config.TracerConfig.TRACE_RATE_LIMIT; +import static datadog.trace.api.config.TracerConfig.TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED; +import static datadog.trace.api.config.TracerConfig.TRACE_REPORT_HOSTNAME; +import static datadog.trace.api.config.TracerConfig.TRACE_RESOLVER_ENABLED; +import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLE_RATE; +import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_OPERATION_RULES; +import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_RULES; +import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_SERVICE_RULES; +import static datadog.trace.api.config.TracerConfig.TRACE_SPAN_ATTRIBUTE_SCHEMA; +import static datadog.trace.api.config.TracerConfig.TRACE_STRICT_WRITES_ENABLED; +import static datadog.trace.api.config.TracerConfig.TRACE_X_DATADOG_TAGS_MAX_LENGTH; +import static datadog.trace.api.config.TracerConfig.WRITER_BAGGAGE_INJECT; +import static datadog.trace.api.config.TracerConfig.WRITER_TYPE; +import static datadog.trace.api.iast.IastDetectionMode.DEFAULT; +import static datadog.trace.util.CollectionUtils.tryMakeImmutableList; +import static datadog.trace.util.CollectionUtils.tryMakeImmutableSet; +import static datadog.trace.util.Strings.propertyNameToEnvironmentVariableName; + +import androidx.annotation.NonNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.UnknownHostException; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.SortedSet; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import datadog.trace.api.config.GeneralConfig; +import datadog.trace.api.config.ProfilingConfig; +import datadog.trace.api.config.TracerConfig; +import datadog.trace.api.iast.IastDetectionMode; +import datadog.trace.api.iast.telemetry.Verbosity; +import datadog.trace.api.naming.SpanNaming; +import datadog.trace.bootstrap.config.provider.CapturedEnvironmentConfigSource; +import datadog.trace.bootstrap.config.provider.ConfigProvider; +import datadog.trace.bootstrap.config.provider.SystemPropertiesConfigSource; +import datadog.trace.util.PidHelper; +import datadog.trace.util.Strings; +import datadog.trace.util.throwable.FatalAgentMisconfigurationError; + +/** + * Config reads values with the following priority: + * + *

1) system properties + * + *

2) environment variables, + * + *

3) optional configuration file + * + *

4) platform dependant properties. It also includes default values to ensure a valid config. + * + *

System properties are {@link Config#PREFIX}'ed. Environment variables are the same as the + * system property, but uppercased and '.' is replaced with '_'. + * + * @see ConfigProvider for details on how configs are processed + * @see InstrumenterConfig for pre-instrumentation configurations + * @see DynamicConfig for configuration that can be dynamically updated via remote-config + */ +public class Config { + + private static final Logger log = LoggerFactory.getLogger(Config.class); + + private static final Pattern COLON = Pattern.compile(":"); + + private final InstrumenterConfig instrumenterConfig; + + private final long startTimeMillis = System.currentTimeMillis(); + private final boolean timelineEventsEnabled; + + /** + * this is a random UUID that gets generated on JVM start up and is attached to every root span + * and every JMX metric that is sent out. + */ + static class RuntimeIdHolder { + static final String runtimeId = UUID.randomUUID().toString(); + } + + static class HostNameHolder { + static final String hostName = initHostName(); + } + + private final boolean runtimeIdEnabled; + + /** This is the version of the runtime, ex: 1.8.0_332, 11.0.15, 17.0.3 */ + private final String runtimeVersion; + + private final String applicationKey; + /** + * Note: this has effect only on profiling site. Traces are sent to Datadog agent and are not + * affected by this setting. If CI Visibility is used with agentless mode, api key is used when + * sending data (including traces) to backend + */ + private final String apiKey; + /** + * Note: this has effect only on profiling site. Traces are sent to Datadog agent and are not + * affected by this setting. + */ + private final String site; + + private final String serviceName; + private final boolean serviceNameSetByUser; + private final String rootContextServiceName; + private final boolean integrationSynapseLegacyOperationName; + private final String writerType; + private final boolean injectBaggageAsTagsEnabled; + private final boolean agentConfiguredUsingDefault; + private final String agentUrl; + private final String agentHost; + private final int agentPort; + private final String agentUnixDomainSocket; + private final String agentNamedPipe; + private final int agentTimeout; + private final Set noProxyHosts; + private final boolean prioritySamplingEnabled; + private final String prioritySamplingForce; + private final boolean traceResolverEnabled; + private final int spanAttributeSchemaVersion; + private final boolean peerServiceDefaultsEnabled; + private final Map peerServiceComponentOverrides; + private final boolean removeIntegrationServiceNamesEnabled; + private final Map peerServiceMapping; + private final Map serviceMapping; + private final Map tags; + private final Map spanTags; + private final Map jmxTags; + private final Map requestHeaderTags; + private final Map responseHeaderTags; + private final Map baggageMapping; + private final boolean requestHeaderTagsCommaAllowed; + private final BitSet httpServerErrorStatuses; + private final BitSet httpClientErrorStatuses; + private final boolean httpServerTagQueryString; + private final boolean httpServerRawQueryString; + private final boolean httpServerRawResource; + private final boolean httpServerDecodedResourcePreserveSpaces; + private final boolean httpServerRouteBasedNaming; + private final Map httpServerPathResourceNameMapping; + private final Map httpClientPathResourceNameMapping; + private final boolean httpResourceRemoveTrailingSlash; + private final boolean httpClientTagQueryString; + private final boolean httpClientTagHeaders; + private final boolean httpClientSplitByDomain; + private final boolean dbClientSplitByInstance; + private final boolean dbClientSplitByInstanceTypeSuffix; + private final boolean dbClientSplitByHost; + private final Set splitByTags; + private final int scopeDepthLimit; + private final boolean scopeStrictMode; + private final boolean scopeInheritAsyncPropagation; + private final int scopeIterationKeepAlive; + private final int partialFlushMinSpans; + private final boolean traceStrictWritesEnabled; + private final boolean logExtractHeaderNames; + private final Set propagationStylesToExtract; + private final Set propagationStylesToInject; + private final boolean tracePropagationStyleB3PaddingEnabled; + private final Set tracePropagationStylesToExtract; + private final Set tracePropagationStylesToInject; + private final boolean tracePropagationExtractFirst; + private final int clockSyncPeriod; + private final boolean logsInjectionEnabled; + + private final String dogStatsDNamedPipe; + private final int dogStatsDStartDelay; + + private final Integer statsDClientQueueSize; + private final Integer statsDClientSocketBuffer; + private final Integer statsDClientSocketTimeout; + + private final boolean runtimeMetricsEnabled; + private final boolean jmxFetchEnabled; + private final String jmxFetchConfigDir; + private final List jmxFetchConfigs; + @Deprecated private final List jmxFetchMetricsConfigs; + private final Integer jmxFetchCheckPeriod; + private final Integer jmxFetchInitialRefreshBeansPeriod; + private final Integer jmxFetchRefreshBeansPeriod; + private final String jmxFetchStatsdHost; + private final Integer jmxFetchStatsdPort; + private final boolean jmxFetchMultipleRuntimeServicesEnabled; + private final int jmxFetchMultipleRuntimeServicesLimit; + + // These values are default-ed to those of jmx fetch values as needed + private final boolean healthMetricsEnabled; + private final String healthMetricsStatsdHost; + private final Integer healthMetricsStatsdPort; + private final boolean perfMetricsEnabled; + + private final boolean tracerMetricsEnabled; + private final boolean tracerMetricsBufferingEnabled; + private final int tracerMetricsMaxAggregates; + private final int tracerMetricsMaxPending; + + private final boolean reportHostName; + + private final boolean traceAnalyticsEnabled; + private final String traceClientIpHeader; + private final boolean traceClientIpResolverEnabled; + + private final boolean traceGitMetadataEnabled; + + private final Map traceSamplingServiceRules; + private final Map traceSamplingOperationRules; + private final String traceSamplingRules; + private final Double traceSampleRate; + private final int traceRateLimit; + private final String spanSamplingRules; + private final String spanSamplingRulesFile; + + private final boolean profilingEnabled; + private final boolean profilingAgentless; + private final boolean isDatadogProfilerEnabled; + @Deprecated private final String profilingUrl; + private final Map profilingTags; + private final int profilingStartDelay; + private final boolean profilingStartForceFirst; + private final int profilingUploadPeriod; + private final String profilingTemplateOverrideFile; + private final int profilingUploadTimeout; + private final String profilingUploadCompression; + private final String profilingProxyHost; + private final int profilingProxyPort; + private final String profilingProxyUsername; + private final String profilingProxyPassword; + private final int profilingExceptionSampleLimit; + private final int profilingDirectAllocationSampleLimit; + private final int profilingExceptionHistogramTopItems; + private final int profilingExceptionHistogramMaxCollectionSize; + private final boolean profilingExcludeAgentThreads; + private final boolean profilingUploadSummaryOn413Enabled; + private final boolean profilingRecordExceptionMessage; + + private final boolean crashTrackingAgentless; + private final Map crashTrackingTags; + + private final boolean clientIpEnabled; + + private final boolean appSecReportingInband; + private final String appSecRulesFile; + private final int appSecReportMinTimeout; + private final int appSecReportMaxTimeout; + private final int appSecTraceRateLimit; + private final boolean appSecWafMetrics; + private final int appSecWafTimeout; + private final String appSecObfuscationParameterKeyRegexp; + private final String appSecObfuscationParameterValueRegexp; + private final String appSecHttpBlockedTemplateHtml; + private final String appSecHttpBlockedTemplateJson; + private final UserEventTrackingMode appSecUserEventsTracking; + private final boolean apiSecurityEnabled; + private final float apiSecurityRequestSampleRate; + + private final IastDetectionMode iastDetectionMode; + private final int iastMaxConcurrentRequests; + private final int iastVulnerabilitiesPerRequest; + private final float iastRequestSampling; + private final boolean iastDebugEnabled; + private final Verbosity iastTelemetryVerbosity; + private final boolean iastRedactionEnabled; + private final String iastRedactionNamePattern; + private final String iastRedactionValuePattern; + private final int iastMaxRangeCount; + private final int iastTruncationMaxValueLength; + private final boolean iastStacktraceLeakSuppress; + + private final boolean ciVisibilityTraceSanitationEnabled; + private final boolean ciVisibilityAgentlessEnabled; + private final String ciVisibilityAgentlessUrl; + + private final boolean ciVisibilitySourceDataEnabled; + private final boolean ciVisibilitySourceDataRootCheckEnabled; + private final boolean ciVisibilityBuildInstrumentationEnabled; + private final Long ciVisibilitySessionId; + private final Long ciVisibilityModuleId; + private final String ciVisibilityAgentJarUri; + private final boolean ciVisibilityAutoConfigurationEnabled; + private final String ciVisibilityAdditionalChildProcessJvmArgs; + private final boolean ciVisibilityCompilerPluginAutoConfigurationEnabled; + private final boolean ciVisibilityCodeCoverageEnabled; + private final boolean ciVisibilityCodeCoveragePercentageCalculationEnabled; + private final String ciVisibilityCodeCoverageReportDumpDir; + private final String ciVisibilityCompilerPluginVersion; + private final String ciVisibilityJacocoPluginVersion; + private final boolean ciVisibilityJacocoPluginVersionProvided; + private final List ciVisibilityCodeCoverageIncludes; + private final List ciVisibilityCodeCoverageExcludes; + private final String[] ciVisibilityCodeCoverageIncludedPackages; + private final String[] ciVisibilityCodeCoverageExcludedPackages; + private final List ciVisibilityJacocoGradleSourceSets; + private final Integer ciVisibilityDebugPort; + private final boolean ciVisibilityGitUploadEnabled; + private final boolean ciVisibilityGitUnshallowEnabled; + private final boolean ciVisibilityGitUnshallowDefer; + private final long ciVisibilityGitCommandTimeoutMillis; + private final String ciVisibilityGitRemoteName; + private final long ciVisibilityBackendApiTimeoutMillis; + private final long ciVisibilityGitUploadTimeoutMillis; + private final String ciVisibilitySignalServerHost; + private final int ciVisibilitySignalServerPort; + private final boolean ciVisibilityItrEnabled; + private final boolean ciVisibilityCiProviderIntegrationEnabled; + private final boolean ciVisibilityRepoIndexSharingEnabled; + private final int ciVisibilityModuleExecutionSettingsCacheSize; + private final int ciVisibilityJvmInfoCacheSize; + private final boolean ciVisibilityCoverageSegmentsEnabled; + private final int ciVisibilityCoverageRootPackagesLimit; + private final String ciVisibilityInjectedTracerVersion; + private final List ciVisibilityResourceFolderNames; + private final boolean ciVisibilityFlakyRetryEnabled; + private final int ciVisibilityFlakyRetryCount; + private final String ciVisibilityModuleName; + + private final boolean remoteConfigEnabled; + private final boolean remoteConfigIntegrityCheckEnabled; + private final String remoteConfigUrl; + private final float remoteConfigPollIntervalSeconds; + private final long remoteConfigMaxPayloadSize; + private final String remoteConfigTargetsKeyId; + private final String remoteConfigTargetsKey; + + private final String DBMPropagationMode; + + private final boolean debuggerEnabled; + private final int debuggerUploadTimeout; + private final int debuggerUploadFlushInterval; + private final boolean debuggerClassFileDumpEnabled; + private final int debuggerPollInterval; + private final int debuggerDiagnosticsInterval; + private final boolean debuggerMetricEnabled; + private final String debuggerProbeFileLocation; + private final int debuggerUploadBatchSize; + private final long debuggerMaxPayloadSize; + private final boolean debuggerVerifyByteCode; + private final boolean debuggerInstrumentTheWorld; + private final String debuggerExcludeFiles; + private final int debuggerCaptureTimeout; + private final String debuggerRedactedIdentifiers; + private final String debuggerRedactedTypes; + private final boolean debuggerSymbolEnabled; + private final boolean debuggerSymbolForceUpload; + private final String debuggerSymbolIncludes; + private final int debuggerSymbolFlushThreshold; + + private final boolean awsPropagationEnabled; + private final boolean sqsPropagationEnabled; + + private final boolean kafkaClientPropagationEnabled; + private final Set kafkaClientPropagationDisabledTopics; + private final boolean kafkaClientBase64DecodingEnabled; + + private final boolean jmsPropagationEnabled; + private final Set jmsPropagationDisabledTopics; + private final Set jmsPropagationDisabledQueues; + private final int jmsUnacknowledgedMaxAge; + + private final boolean rabbitPropagationEnabled; + private final Set rabbitPropagationDisabledQueues; + private final Set rabbitPropagationDisabledExchanges; + + private final boolean rabbitIncludeRoutingKeyInResource; + + private final boolean messageBrokerSplitByDestination; + + private final boolean hystrixTagsEnabled; + private final boolean hystrixMeasuredEnabled; + + private final boolean igniteCacheIncludeKeys; + + private final String obfuscationQueryRegexp; + + // TODO: remove at a future point. + private final boolean playReportHttpStatus; + + private final boolean servletPrincipalEnabled; + private final boolean servletAsyncTimeoutError; + + private final boolean springDataRepositoryInterfaceResourceName; + + private final int xDatadogTagsMaxLength; + + private final boolean traceAgentV05Enabled; + + private final boolean debugEnabled; + private final boolean triageEnabled; + private final boolean startupLogsEnabled; + private final String configFileStatus; + + private final IdGenerationStrategy idGenerationStrategy; + + private final boolean secureRandom; + + private final boolean trace128bitTraceIdGenerationEnabled; + + private final Set grpcIgnoredInboundMethods; + private final Set grpcIgnoredOutboundMethods; + private final boolean grpcServerTrimPackageResource; + private final BitSet grpcServerErrorStatuses; + private final BitSet grpcClientErrorStatuses; + + private final boolean cwsEnabled; + private final int cwsTlsRefresh; + + private final boolean dataStreamsEnabled; + private final float dataStreamsBucketDurationSeconds; + + private final Set iastWeakHashAlgorithms; + + private final Pattern iastWeakCipherAlgorithms; + + private final boolean iastDeduplicationEnabled; + + private final float telemetryHeartbeatInterval; + private final long telemetryExtendedHeartbeatInterval; + private final float telemetryMetricsInterval; + private final boolean isTelemetryDependencyServiceEnabled; + private final boolean telemetryMetricsEnabled; + private final boolean isTelemetryLogCollectionEnabled; + + private final boolean azureAppServices; + private final String traceAgentPath; + private final List traceAgentArgs; + private final String dogStatsDPath; + private final List dogStatsDArgs; + + private String env; + private String version; + private final String primaryTag; + + private final ConfigProvider configProvider; + + private final boolean longRunningTraceEnabled; + private final long longRunningTraceFlushInterval; + private final boolean elasticsearchBodyEnabled; + private final boolean elasticsearchParamsEnabled; + private final boolean elasticsearchBodyAndParamsEnabled; + private final boolean sparkTaskHistogramEnabled; + private final boolean jaxRsExceptionAsErrorsEnabled; + + private final float traceFlushIntervalSeconds; + + private final boolean telemetryDebugRequestsEnabled; + + // Read order: System Properties -> Env Variables, [-> properties file], [-> default value] + private Config() { + this(ConfigProvider.createDefault()); + } + + private Config(final ConfigProvider configProvider) { + this(configProvider, new InstrumenterConfig(configProvider)); + } + + private Config(final ConfigProvider configProvider, final InstrumenterConfig instrumenterConfig) { + this.configProvider = configProvider; + this.instrumenterConfig = instrumenterConfig; + configFileStatus = configProvider.getConfigFileStatus(); + runtimeIdEnabled = configProvider.getBoolean(RUNTIME_ID_ENABLED, true); + runtimeVersion = System.getProperty("java.version", "unknown"); + + // Note: We do not want APiKey to be loaded from property for security reasons + // Note: we do not use defined default here + // FIXME: We should use better authentication mechanism + final String apiKeyFile = configProvider.getString(API_KEY_FILE); + String tmpApiKey = + configProvider.getStringExcludingSource(API_KEY, null, SystemPropertiesConfigSource.class); + if (apiKeyFile != null) { + try { + tmpApiKey = + new String(Files.readAllBytes(Paths.get(apiKeyFile)), StandardCharsets.UTF_8).trim(); + } catch (final IOException e) { + log.error( + "Cannot read API key from file {}, skipping. Exception {}", apiKeyFile, e.getMessage()); + } + } + site = configProvider.getString(SITE, DEFAULT_SITE); + + String tmpApplicationKey = + configProvider.getStringExcludingSource( + APPLICATION_KEY, null, SystemPropertiesConfigSource.class); + String applicationKeyFile = configProvider.getString(APPLICATION_KEY_FILE); + if (applicationKeyFile != null) { + try { + tmpApplicationKey = + new String(Files.readAllBytes(Paths.get(applicationKeyFile)), StandardCharsets.UTF_8) + .trim(); + } catch (final IOException e) { + log.error("Cannot read API key from file {}, skipping", applicationKeyFile, e); + } + } + applicationKey = tmpApplicationKey; + + String userProvidedServiceName = + configProvider.getStringExcludingSource( + SERVICE, null, CapturedEnvironmentConfigSource.class, SERVICE_NAME); + + if (userProvidedServiceName == null) { + serviceNameSetByUser = false; + serviceName = configProvider.getString(SERVICE, DEFAULT_SERVICE_NAME, SERVICE_NAME); + } else { + serviceNameSetByUser = true; + serviceName = userProvidedServiceName; + } + + rootContextServiceName = + configProvider.getString( + SERVLET_ROOT_CONTEXT_SERVICE_NAME, DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME); + + integrationSynapseLegacyOperationName = + configProvider.getBoolean(INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME, false); + writerType = configProvider.getString(WRITER_TYPE, DEFAULT_AGENT_WRITER_TYPE); + injectBaggageAsTagsEnabled = + configProvider.getBoolean(WRITER_BAGGAGE_INJECT, DEFAULT_WRITER_BAGGAGE_INJECT); + String lambdaInitType = getEnv("AWS_LAMBDA_INITIALIZATION_TYPE"); + if (lambdaInitType != null && lambdaInitType.equals("snap-start")) { + secureRandom = true; + } else { + secureRandom = configProvider.getBoolean(SECURE_RANDOM, DEFAULT_SECURE_RANDOM); + } + elasticsearchBodyEnabled = + configProvider.getBoolean(ELASTICSEARCH_BODY_ENABLED, DEFAULT_ELASTICSEARCH_BODY_ENABLED); + elasticsearchParamsEnabled = + configProvider.getBoolean( + ELASTICSEARCH_PARAMS_ENABLED, DEFAULT_ELASTICSEARCH_PARAMS_ENABLED); + elasticsearchBodyAndParamsEnabled = + configProvider.getBoolean( + ELASTICSEARCH_BODY_AND_PARAMS_ENABLED, DEFAULT_ELASTICSEARCH_BODY_AND_PARAMS_ENABLED); + String strategyName = configProvider.getString(ID_GENERATION_STRATEGY); + trace128bitTraceIdGenerationEnabled = + configProvider.getBoolean( + TRACE_128_BIT_TRACEID_GENERATION_ENABLED, + DEFAULT_TRACE_128_BIT_TRACEID_GENERATION_ENABLED); + if (secureRandom) { + strategyName = "SECURE_RANDOM"; + } + if (strategyName == null) { + strategyName = "RANDOM"; + } + IdGenerationStrategy strategy = + IdGenerationStrategy.fromName(strategyName, trace128bitTraceIdGenerationEnabled); + if (strategy == null) { + log.warn( + "*** you are trying to use an unknown id generation strategy {} - falling back to RANDOM", + strategyName); + strategyName = "RANDOM"; + strategy = IdGenerationStrategy.fromName(strategyName, trace128bitTraceIdGenerationEnabled); + } + if (!strategyName.equals("RANDOM") && !strategyName.equals("SECURE_RANDOM")) { + log.warn( + "*** you are using an unsupported id generation strategy {} - this can impact correctness of traces", + strategyName); + } + idGenerationStrategy = strategy; + + String agentHostFromEnvironment = null; + int agentPortFromEnvironment = -1; + String unixSocketFromEnvironment = null; + boolean rebuildAgentUrl = false; + + final String agentUrlFromEnvironment = configProvider.getString(TRACE_AGENT_URL); + if (agentUrlFromEnvironment != null) { + try { + final URI parsedAgentUrl = new URI(agentUrlFromEnvironment); + agentHostFromEnvironment = parsedAgentUrl.getHost(); + agentPortFromEnvironment = parsedAgentUrl.getPort(); + if ("unix".equals(parsedAgentUrl.getScheme())) { + unixSocketFromEnvironment = parsedAgentUrl.getPath(); + } + } catch (URISyntaxException e) { + log.warn("{} not configured correctly: {}. Ignoring", TRACE_AGENT_URL, e.getMessage()); + } + } + + if (agentHostFromEnvironment == null) { + agentHostFromEnvironment = configProvider.getString(AGENT_HOST); + rebuildAgentUrl = true; + } + + if (agentPortFromEnvironment < 0) { + agentPortFromEnvironment = configProvider.getInteger(TRACE_AGENT_PORT, -1, AGENT_PORT_LEGACY); + rebuildAgentUrl = true; + } + + if (agentHostFromEnvironment == null) { + agentHost = DEFAULT_AGENT_HOST; + } else { + agentHost = agentHostFromEnvironment; + } + + if (agentPortFromEnvironment < 0) { + agentPort = DEFAULT_TRACE_AGENT_PORT; + } else { + agentPort = agentPortFromEnvironment; + } + + if (rebuildAgentUrl) { + agentUrl = "http://" + agentHost + ":" + agentPort; + } else { + agentUrl = agentUrlFromEnvironment; + } + + if (unixSocketFromEnvironment == null) { + unixSocketFromEnvironment = configProvider.getString(AGENT_UNIX_DOMAIN_SOCKET); + String unixPrefix = "unix://"; + // handle situation where someone passes us a unix:// URL instead of a socket path + if (unixSocketFromEnvironment != null && unixSocketFromEnvironment.startsWith(unixPrefix)) { + unixSocketFromEnvironment = unixSocketFromEnvironment.substring(unixPrefix.length()); + } + } + + agentUnixDomainSocket = unixSocketFromEnvironment; + + agentNamedPipe = configProvider.getString(AGENT_NAMED_PIPE); + + agentConfiguredUsingDefault = + agentHostFromEnvironment == null + && agentPortFromEnvironment < 0 + && unixSocketFromEnvironment == null + && agentNamedPipe == null; + + agentTimeout = configProvider.getInteger(AGENT_TIMEOUT, DEFAULT_AGENT_TIMEOUT); + + // DD_PROXY_NO_PROXY is specified as a space-separated list of hosts + noProxyHosts = tryMakeImmutableSet(configProvider.getSpacedList(PROXY_NO_PROXY)); + + prioritySamplingEnabled = + configProvider.getBoolean(PRIORITY_SAMPLING, DEFAULT_PRIORITY_SAMPLING_ENABLED); + prioritySamplingForce = + configProvider.getString(PRIORITY_SAMPLING_FORCE, DEFAULT_PRIORITY_SAMPLING_FORCE); + + traceResolverEnabled = + configProvider.getBoolean(TRACE_RESOLVER_ENABLED, DEFAULT_TRACE_RESOLVER_ENABLED); + serviceMapping = configProvider.getMergedMap(SERVICE_MAPPING); + + { + final Map tags = new HashMap<>(configProvider.getMergedMap(GLOBAL_TAGS)); + tags.putAll(configProvider.getMergedMap(TAGS)); + this.tags = getMapWithPropertiesDefinedByEnvironment(tags, ENV, VERSION); + } + + spanTags = configProvider.getMergedMap(SPAN_TAGS); + jmxTags = configProvider.getMergedMap(JMX_TAGS); + + primaryTag = configProvider.getString(PRIMARY_TAG); + + if (isEnabled(false, HEADER_TAGS, ".legacy.parsing.enabled")) { + requestHeaderTags = configProvider.getMergedMap(HEADER_TAGS); + responseHeaderTags = Collections.emptyMap(); + if (configProvider.isSet(REQUEST_HEADER_TAGS)) { + logIgnoredSettingWarning(REQUEST_HEADER_TAGS, HEADER_TAGS, ".legacy.parsing.enabled"); + } + if (configProvider.isSet(RESPONSE_HEADER_TAGS)) { + logIgnoredSettingWarning(RESPONSE_HEADER_TAGS, HEADER_TAGS, ".legacy.parsing.enabled"); + } + } else { + requestHeaderTags = + configProvider.getMergedMapWithOptionalMappings( + "http.request.headers.", true, HEADER_TAGS, REQUEST_HEADER_TAGS); + responseHeaderTags = + configProvider.getMergedMapWithOptionalMappings( + "http.response.headers.", true, HEADER_TAGS, RESPONSE_HEADER_TAGS); + } + requestHeaderTagsCommaAllowed = + configProvider.getBoolean(REQUEST_HEADER_TAGS_COMMA_ALLOWED, true); + + baggageMapping = configProvider.getMergedMap(BAGGAGE_MAPPING); + + spanAttributeSchemaVersion = schemaVersionFromConfig(); + + // following two only used in v0. + // in v1+ defaults are always calculated regardless this feature flag + peerServiceDefaultsEnabled = + configProvider.getBoolean(TRACE_PEER_SERVICE_DEFAULTS_ENABLED, false); + peerServiceComponentOverrides = + configProvider.getMergedMap(TRACE_PEER_SERVICE_COMPONENT_OVERRIDES); + // feature flag to remove fake services in v0 + removeIntegrationServiceNamesEnabled = + configProvider.getBoolean(TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED, false); + + peerServiceMapping = configProvider.getMergedMap(TRACE_PEER_SERVICE_MAPPING); + + httpServerPathResourceNameMapping = + configProvider.getOrderedMap(TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING); + + httpClientPathResourceNameMapping = + configProvider.getOrderedMap(TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING); + + httpResourceRemoveTrailingSlash = + configProvider.getBoolean( + TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH, + DEFAULT_TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH); + + httpServerErrorStatuses = + configProvider.getIntegerRange( + HTTP_SERVER_ERROR_STATUSES, DEFAULT_HTTP_SERVER_ERROR_STATUSES); + + httpClientErrorStatuses = + configProvider.getIntegerRange( + HTTP_CLIENT_ERROR_STATUSES, DEFAULT_HTTP_CLIENT_ERROR_STATUSES); + + httpServerTagQueryString = + configProvider.getBoolean( + HTTP_SERVER_TAG_QUERY_STRING, DEFAULT_HTTP_SERVER_TAG_QUERY_STRING); + + httpServerRawQueryString = configProvider.getBoolean(HTTP_SERVER_RAW_QUERY_STRING, true); + + httpServerRawResource = configProvider.getBoolean(HTTP_SERVER_RAW_RESOURCE, false); + + httpServerDecodedResourcePreserveSpaces = + configProvider.getBoolean(HTTP_SERVER_DECODED_RESOURCE_PRESERVE_SPACES, true); + + httpServerRouteBasedNaming = + configProvider.getBoolean( + HTTP_SERVER_ROUTE_BASED_NAMING, DEFAULT_HTTP_SERVER_ROUTE_BASED_NAMING); + + httpClientTagQueryString = + configProvider.getBoolean( + HTTP_CLIENT_TAG_QUERY_STRING, DEFAULT_HTTP_CLIENT_TAG_QUERY_STRING); + + httpClientTagHeaders = configProvider.getBoolean(HTTP_CLIENT_TAG_HEADERS, true); + + httpClientSplitByDomain = + configProvider.getBoolean( + HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, DEFAULT_HTTP_CLIENT_SPLIT_BY_DOMAIN); + + dbClientSplitByInstance = + configProvider.getBoolean( + DB_CLIENT_HOST_SPLIT_BY_INSTANCE, DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE); + + dbClientSplitByInstanceTypeSuffix = + configProvider.getBoolean( + DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX, + DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX); + + dbClientSplitByHost = + configProvider.getBoolean( + DB_CLIENT_HOST_SPLIT_BY_HOST, DEFAULT_DB_CLIENT_HOST_SPLIT_BY_HOST); + + DBMPropagationMode = + configProvider.getString( + DB_DBM_PROPAGATION_MODE_MODE, DEFAULT_DB_DBM_PROPAGATION_MODE_MODE); + + splitByTags = tryMakeImmutableSet(configProvider.getList(SPLIT_BY_TAGS)); + + springDataRepositoryInterfaceResourceName = + configProvider.getBoolean(SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME, true); + + scopeDepthLimit = configProvider.getInteger(SCOPE_DEPTH_LIMIT, DEFAULT_SCOPE_DEPTH_LIMIT); + + scopeStrictMode = configProvider.getBoolean(SCOPE_STRICT_MODE, false); + + scopeInheritAsyncPropagation = configProvider.getBoolean(SCOPE_INHERIT_ASYNC_PROPAGATION, true); + + scopeIterationKeepAlive = + configProvider.getInteger(SCOPE_ITERATION_KEEP_ALIVE, DEFAULT_SCOPE_ITERATION_KEEP_ALIVE); + + boolean partialFlushEnabled = configProvider.getBoolean(PARTIAL_FLUSH_ENABLED, true); + partialFlushMinSpans = + !partialFlushEnabled + ? 0 + : configProvider.getInteger(PARTIAL_FLUSH_MIN_SPANS, DEFAULT_PARTIAL_FLUSH_MIN_SPANS); + + traceStrictWritesEnabled = configProvider.getBoolean(TRACE_STRICT_WRITES_ENABLED, false); + + logExtractHeaderNames = + configProvider.getBoolean( + PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED, + DEFAULT_PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED); + + tracePropagationStyleB3PaddingEnabled = + isEnabled(true, TRACE_PROPAGATION_STYLE, ".b3.padding.enabled"); + { + // The dd.propagation.style.(extract|inject) settings have been deprecated in + // favor of dd.trace.propagation.style(|.extract|.inject) settings. + // The different propagation settings when set will be applied in the following order of + // precedence, and warnings will be logged for both deprecation and overrides. + // * dd.trace.propagation.style.(extract|inject) + // * dd.trace.propagation.style + // * dd.propagation.style.(extract|inject) + Set deprecatedExtract = + getSettingsSetFromEnvironment( + PROPAGATION_STYLE_EXTRACT, PropagationStyle::valueOfConfigName, true); + Set deprecatedInject = + getSettingsSetFromEnvironment( + PROPAGATION_STYLE_INJECT, PropagationStyle::valueOfConfigName, true); + Set common = + getSettingsSetFromEnvironment( + TRACE_PROPAGATION_STYLE, TracePropagationStyle::valueOfDisplayName, false); + Set extract = + getSettingsSetFromEnvironment( + TRACE_PROPAGATION_STYLE_EXTRACT, TracePropagationStyle::valueOfDisplayName, false); + Set inject = + getSettingsSetFromEnvironment( + TRACE_PROPAGATION_STYLE_INJECT, TracePropagationStyle::valueOfDisplayName, false); + String extractOrigin = TRACE_PROPAGATION_STYLE_EXTRACT; + String injectOrigin = TRACE_PROPAGATION_STYLE_INJECT; + // Check if we should use the common setting for extraction + if (extract.isEmpty()) { + extract = common; + extractOrigin = TRACE_PROPAGATION_STYLE; + } else if (!common.isEmpty()) { + // The more specific settings will override the common setting, so log a warning + logOverriddenSettingWarning( + TRACE_PROPAGATION_STYLE, TRACE_PROPAGATION_STYLE_EXTRACT, extract); + } + // Check if we should use the common setting for injection + if (inject.isEmpty()) { + inject = common; + injectOrigin = TRACE_PROPAGATION_STYLE; + } else if (!common.isEmpty()) { + // The more specific settings will override the common setting, so log a warning + logOverriddenSettingWarning( + TRACE_PROPAGATION_STYLE, TRACE_PROPAGATION_STYLE_INJECT, inject); + } + // Check if we should use the deprecated setting for extraction + if (extract.isEmpty()) { + // If we don't have a new setting, we convert the deprecated one + extract = convertSettingsSet(deprecatedExtract, PropagationStyle::getNewStyles); + if (!extract.isEmpty()) { + logDeprecatedConvertedSetting( + PROPAGATION_STYLE_EXTRACT, + deprecatedExtract, + TRACE_PROPAGATION_STYLE_EXTRACT, + extract); + } + } else if (!deprecatedExtract.isEmpty()) { + // If we have a new setting, we log a warning + logOverriddenDeprecatedSettingWarning(PROPAGATION_STYLE_EXTRACT, extractOrigin, extract); + } + // Check if we should use the deprecated setting for injection + if (inject.isEmpty()) { + // If we don't have a new setting, we convert the deprecated one + inject = convertSettingsSet(deprecatedInject, PropagationStyle::getNewStyles); + if (!inject.isEmpty()) { + logDeprecatedConvertedSetting( + PROPAGATION_STYLE_INJECT, deprecatedInject, TRACE_PROPAGATION_STYLE_INJECT, inject); + } + } else if (!deprecatedInject.isEmpty()) { + // If we have a new setting, we log a warning + logOverriddenDeprecatedSettingWarning(PROPAGATION_STYLE_INJECT, injectOrigin, inject); + } + // Now we can check if we should pick the default injection/extraction + tracePropagationStylesToExtract = + extract.isEmpty() ? DEFAULT_TRACE_PROPAGATION_STYLE : extract; + tracePropagationStylesToInject = inject.isEmpty() ? DEFAULT_TRACE_PROPAGATION_STYLE : inject; + // These setting are here for backwards compatibility until they can be removed in a major + // release of the tracer + propagationStylesToExtract = + deprecatedExtract.isEmpty() ? DEFAULT_PROPAGATION_STYLE : deprecatedExtract; + propagationStylesToInject = + deprecatedInject.isEmpty() ? DEFAULT_PROPAGATION_STYLE : deprecatedInject; + } + + tracePropagationExtractFirst = + configProvider.getBoolean( + TRACE_PROPAGATION_EXTRACT_FIRST, DEFAULT_TRACE_PROPAGATION_EXTRACT_FIRST); + + clockSyncPeriod = configProvider.getInteger(CLOCK_SYNC_PERIOD, DEFAULT_CLOCK_SYNC_PERIOD); + + logsInjectionEnabled = + configProvider.getBoolean(LOGS_INJECTION_ENABLED, DEFAULT_LOGS_INJECTION_ENABLED); + + dogStatsDNamedPipe = configProvider.getString(DOGSTATSD_NAMED_PIPE); + + dogStatsDStartDelay = + configProvider.getInteger( + DOGSTATSD_START_DELAY, DEFAULT_DOGSTATSD_START_DELAY, JMX_FETCH_START_DELAY); + + statsDClientQueueSize = configProvider.getInteger(STATSD_CLIENT_QUEUE_SIZE); + statsDClientSocketBuffer = configProvider.getInteger(STATSD_CLIENT_SOCKET_BUFFER); + statsDClientSocketTimeout = configProvider.getInteger(STATSD_CLIENT_SOCKET_TIMEOUT); + + runtimeMetricsEnabled = configProvider.getBoolean(RUNTIME_METRICS_ENABLED, true); + + jmxFetchEnabled = + runtimeMetricsEnabled + && configProvider.getBoolean(JMX_FETCH_ENABLED, DEFAULT_JMX_FETCH_ENABLED); + jmxFetchConfigDir = configProvider.getString(JMX_FETCH_CONFIG_DIR); + jmxFetchConfigs = tryMakeImmutableList(configProvider.getList(JMX_FETCH_CONFIG)); + jmxFetchMetricsConfigs = + tryMakeImmutableList(configProvider.getList(JMX_FETCH_METRICS_CONFIGS)); + jmxFetchCheckPeriod = configProvider.getInteger(JMX_FETCH_CHECK_PERIOD); + jmxFetchInitialRefreshBeansPeriod = + configProvider.getInteger(JMX_FETCH_INITIAL_REFRESH_BEANS_PERIOD); + jmxFetchRefreshBeansPeriod = configProvider.getInteger(JMX_FETCH_REFRESH_BEANS_PERIOD); + + jmxFetchStatsdPort = configProvider.getInteger(JMX_FETCH_STATSD_PORT, DOGSTATSD_PORT); + jmxFetchStatsdHost = + configProvider.getString( + JMX_FETCH_STATSD_HOST, + // default to agent host if an explicit port has been set + null != jmxFetchStatsdPort && jmxFetchStatsdPort > 0 ? agentHost : null, + DOGSTATSD_HOST); + + jmxFetchMultipleRuntimeServicesEnabled = + configProvider.getBoolean( + JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED, + DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED); + jmxFetchMultipleRuntimeServicesLimit = + configProvider.getInteger( + JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT, + DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT); + + // Writer.Builder createMonitor will use the values of the JMX fetch & agent to fill-in defaults + healthMetricsEnabled = + runtimeMetricsEnabled + && configProvider.getBoolean(HEALTH_METRICS_ENABLED, DEFAULT_HEALTH_METRICS_ENABLED); + healthMetricsStatsdHost = configProvider.getString(HEALTH_METRICS_STATSD_HOST); + healthMetricsStatsdPort = configProvider.getInteger(HEALTH_METRICS_STATSD_PORT); + perfMetricsEnabled = + runtimeMetricsEnabled + && configProvider.getBoolean(PERF_METRICS_ENABLED, DEFAULT_PERF_METRICS_ENABLED); + + tracerMetricsEnabled = configProvider.getBoolean(TRACER_METRICS_ENABLED, false); + tracerMetricsBufferingEnabled = + configProvider.getBoolean(TRACER_METRICS_BUFFERING_ENABLED, false); + tracerMetricsMaxAggregates = configProvider.getInteger(TRACER_METRICS_MAX_AGGREGATES, 2048); + tracerMetricsMaxPending = configProvider.getInteger(TRACER_METRICS_MAX_PENDING, 2048); + + reportHostName = + configProvider.getBoolean(TRACE_REPORT_HOSTNAME, DEFAULT_TRACE_REPORT_HOSTNAME); + + traceAgentV05Enabled = + configProvider.getBoolean(ENABLE_TRACE_AGENT_V05, DEFAULT_TRACE_AGENT_V05_ENABLED); + + traceAnalyticsEnabled = + configProvider.getBoolean(TRACE_ANALYTICS_ENABLED, DEFAULT_TRACE_ANALYTICS_ENABLED); + + String traceClientIpHeader = configProvider.getString(TRACE_CLIENT_IP_HEADER); + if (traceClientIpHeader == null) { + traceClientIpHeader = configProvider.getString(APPSEC_IP_ADDR_HEADER); + } + if (traceClientIpHeader != null) { + traceClientIpHeader = traceClientIpHeader.toLowerCase(Locale.ROOT); + } + this.traceClientIpHeader = traceClientIpHeader; + + traceClientIpResolverEnabled = + configProvider.getBoolean(TRACE_CLIENT_IP_RESOLVER_ENABLED, true); + + traceGitMetadataEnabled = configProvider.getBoolean(TRACE_GIT_METADATA_ENABLED, true); + + traceSamplingServiceRules = configProvider.getMergedMap(TRACE_SAMPLING_SERVICE_RULES); + traceSamplingOperationRules = configProvider.getMergedMap(TRACE_SAMPLING_OPERATION_RULES); + traceSamplingRules = configProvider.getString(TRACE_SAMPLING_RULES); + traceSampleRate = configProvider.getDouble(TRACE_SAMPLE_RATE); + traceRateLimit = configProvider.getInteger(TRACE_RATE_LIMIT, DEFAULT_TRACE_RATE_LIMIT); + spanSamplingRules = configProvider.getString(SPAN_SAMPLING_RULES); + spanSamplingRulesFile = configProvider.getString(SPAN_SAMPLING_RULES_FILE); + + // For the native image 'instrumenterConfig.isProfilingEnabled()' value will be 'baked-in' based + // on whether + // the profiler was enabled at build time or not. + // Otherwise just do the standard config lookup by key. + profilingEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_ENABLED, instrumenterConfig.isProfilingEnabled()); + profilingAgentless = + configProvider.getBoolean(PROFILING_AGENTLESS, PROFILING_AGENTLESS_DEFAULT); + isDatadogProfilerEnabled = + !isDatadogProfilerEnablementOverridden() + && configProvider.getBoolean( + PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment()); + profilingUrl = configProvider.getString(PROFILING_URL); + + if (tmpApiKey == null) { + final String oldProfilingApiKeyFile = configProvider.getString(PROFILING_API_KEY_FILE_OLD); + tmpApiKey = getEnv(propertyNameToEnvironmentVariableName(PROFILING_API_KEY_OLD)); + if (oldProfilingApiKeyFile != null) { + try { + tmpApiKey = + new String( + Files.readAllBytes(Paths.get(oldProfilingApiKeyFile)), StandardCharsets.UTF_8) + .trim(); + } catch (final IOException e) { + log.error("Cannot read API key from file {}, skipping", oldProfilingApiKeyFile, e); + } + } + } + if (tmpApiKey == null) { + final String veryOldProfilingApiKeyFile = + configProvider.getString(PROFILING_API_KEY_FILE_VERY_OLD); + tmpApiKey = getEnv(propertyNameToEnvironmentVariableName(PROFILING_API_KEY_VERY_OLD)); + if (veryOldProfilingApiKeyFile != null) { + try { + tmpApiKey = + new String( + Files.readAllBytes(Paths.get(veryOldProfilingApiKeyFile)), + StandardCharsets.UTF_8) + .trim(); + } catch (final IOException e) { + log.error("Cannot read API key from file {}, skipping", veryOldProfilingApiKeyFile, e); + } + } + } + + profilingTags = configProvider.getMergedMap(PROFILING_TAGS); + profilingStartDelay = + configProvider.getInteger(PROFILING_START_DELAY, PROFILING_START_DELAY_DEFAULT); + profilingStartForceFirst = + configProvider.getBoolean(PROFILING_START_FORCE_FIRST, PROFILING_START_FORCE_FIRST_DEFAULT); + profilingUploadPeriod = + configProvider.getInteger(PROFILING_UPLOAD_PERIOD, PROFILING_UPLOAD_PERIOD_DEFAULT); + profilingTemplateOverrideFile = configProvider.getString(PROFILING_TEMPLATE_OVERRIDE_FILE); + profilingUploadTimeout = + configProvider.getInteger(PROFILING_UPLOAD_TIMEOUT, PROFILING_UPLOAD_TIMEOUT_DEFAULT); + profilingUploadCompression = + configProvider.getString( + PROFILING_UPLOAD_COMPRESSION, PROFILING_UPLOAD_COMPRESSION_DEFAULT); + profilingProxyHost = configProvider.getString(PROFILING_PROXY_HOST); + profilingProxyPort = + configProvider.getInteger(PROFILING_PROXY_PORT, PROFILING_PROXY_PORT_DEFAULT); + profilingProxyUsername = configProvider.getString(PROFILING_PROXY_USERNAME); + profilingProxyPassword = configProvider.getString(PROFILING_PROXY_PASSWORD); + + profilingExceptionSampleLimit = + configProvider.getInteger( + PROFILING_EXCEPTION_SAMPLE_LIMIT, PROFILING_EXCEPTION_SAMPLE_LIMIT_DEFAULT); + profilingDirectAllocationSampleLimit = + configProvider.getInteger( + PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT, + PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT); + profilingExceptionHistogramTopItems = + configProvider.getInteger( + PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS, + PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS_DEFAULT); + profilingExceptionHistogramMaxCollectionSize = + configProvider.getInteger( + PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE, + PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE_DEFAULT); + + profilingExcludeAgentThreads = configProvider.getBoolean(PROFILING_EXCLUDE_AGENT_THREADS, true); + + profilingRecordExceptionMessage = + configProvider.getBoolean( + PROFILING_EXCEPTION_RECORD_MESSAGE, PROFILING_EXCEPTION_RECORD_MESSAGE_DEFAULT); + + profilingUploadSummaryOn413Enabled = + configProvider.getBoolean( + PROFILING_UPLOAD_SUMMARY_ON_413, PROFILING_UPLOAD_SUMMARY_ON_413_DEFAULT); + + crashTrackingAgentless = + configProvider.getBoolean(CRASH_TRACKING_AGENTLESS, CRASH_TRACKING_AGENTLESS_DEFAULT); + crashTrackingTags = configProvider.getMergedMap(CRASH_TRACKING_TAGS); + + float telemetryInterval = + configProvider.getFloat(TELEMETRY_HEARTBEAT_INTERVAL, DEFAULT_TELEMETRY_HEARTBEAT_INTERVAL); + if (telemetryInterval < 0.1 || telemetryInterval > 3600) { + log.warn( + "Invalid Telemetry heartbeat interval: {}. The value must be in range 0.1-3600", + telemetryInterval); + telemetryInterval = DEFAULT_TELEMETRY_HEARTBEAT_INTERVAL; + } + telemetryHeartbeatInterval = telemetryInterval; + + telemetryExtendedHeartbeatInterval = + configProvider.getLong( + TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL, DEFAULT_TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL); + + telemetryInterval = + configProvider.getFloat(TELEMETRY_METRICS_INTERVAL, DEFAULT_TELEMETRY_METRICS_INTERVAL); + if (telemetryInterval < 0.1 || telemetryInterval > 3600) { + log.warn( + "Invalid Telemetry metrics interval: {}. The value must be in range 0.1-3600", + telemetryInterval); + telemetryInterval = DEFAULT_TELEMETRY_METRICS_INTERVAL; + } + telemetryMetricsInterval = telemetryInterval; + + telemetryMetricsEnabled = + configProvider.getBoolean(GeneralConfig.TELEMETRY_METRICS_ENABLED, true); + + isTelemetryDependencyServiceEnabled = + configProvider.getBoolean( + TELEMETRY_DEPENDENCY_COLLECTION_ENABLED, + DEFAULT_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED); + + isTelemetryLogCollectionEnabled = + configProvider.getBoolean( + TELEMETRY_LOG_COLLECTION_ENABLED, DEFAULT_TELEMETRY_LOG_COLLECTION_ENABLED); + + clientIpEnabled = configProvider.getBoolean(CLIENT_IP_ENABLED, DEFAULT_CLIENT_IP_ENABLED); + + appSecReportingInband = + configProvider.getBoolean(APPSEC_REPORTING_INBAND, DEFAULT_APPSEC_REPORTING_INBAND); + appSecRulesFile = configProvider.getString(APPSEC_RULES_FILE, null); + + // Default AppSec report timeout min=5, max=60 + appSecReportMaxTimeout = configProvider.getInteger(APPSEC_REPORT_TIMEOUT_SEC, 60); + appSecReportMinTimeout = Math.min(appSecReportMaxTimeout, 5); + + appSecTraceRateLimit = + configProvider.getInteger(APPSEC_TRACE_RATE_LIMIT, DEFAULT_APPSEC_TRACE_RATE_LIMIT); + + appSecWafMetrics = configProvider.getBoolean(APPSEC_WAF_METRICS, DEFAULT_APPSEC_WAF_METRICS); + + appSecWafTimeout = configProvider.getInteger(APPSEC_WAF_TIMEOUT, DEFAULT_APPSEC_WAF_TIMEOUT); + + appSecObfuscationParameterKeyRegexp = + configProvider.getString(APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP, null); + appSecObfuscationParameterValueRegexp = + configProvider.getString(APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP, null); + + appSecHttpBlockedTemplateHtml = + configProvider.getString(APPSEC_HTTP_BLOCKED_TEMPLATE_HTML, null); + appSecHttpBlockedTemplateJson = + configProvider.getString(APPSEC_HTTP_BLOCKED_TEMPLATE_JSON, null); + appSecUserEventsTracking = + UserEventTrackingMode.fromString( + configProvider.getStringNotEmpty( + APPSEC_AUTOMATED_USER_EVENTS_TRACKING, SAFE.toString())); + apiSecurityEnabled = + configProvider.getBoolean(API_SECURITY_ENABLED, DEFAULT_API_SECURITY_ENABLED); + apiSecurityRequestSampleRate = + configProvider.getFloat( + API_SECURITY_REQUEST_SAMPLE_RATE, DEFAULT_API_SECURITY_REQUEST_SAMPLE_RATE); + + iastDebugEnabled = configProvider.getBoolean(IAST_DEBUG_ENABLED, DEFAULT_IAST_DEBUG_ENABLED); + + iastDetectionMode = + configProvider.getEnum(IAST_DETECTION_MODE, IastDetectionMode.class, DEFAULT); + iastMaxConcurrentRequests = iastDetectionMode.getIastMaxConcurrentRequests(configProvider); + iastVulnerabilitiesPerRequest = + iastDetectionMode.getIastVulnerabilitiesPerRequest(configProvider); + iastRequestSampling = iastDetectionMode.getIastRequestSampling(configProvider); + iastDeduplicationEnabled = iastDetectionMode.isIastDeduplicationEnabled(configProvider); + iastWeakHashAlgorithms = + tryMakeImmutableSet( + configProvider.getSet(IAST_WEAK_HASH_ALGORITHMS, DEFAULT_IAST_WEAK_HASH_ALGORITHMS)); + iastWeakCipherAlgorithms = + getPattern( + DEFAULT_IAST_WEAK_CIPHER_ALGORITHMS, + configProvider.getString(IAST_WEAK_CIPHER_ALGORITHMS)); + iastTelemetryVerbosity = + configProvider.getEnum(IAST_TELEMETRY_VERBOSITY, Verbosity.class, Verbosity.INFORMATION); + iastRedactionEnabled = + configProvider.getBoolean(IAST_REDACTION_ENABLED, DEFAULT_IAST_REDACTION_ENABLED); + iastRedactionNamePattern = + configProvider.getString(IAST_REDACTION_NAME_PATTERN, DEFAULT_IAST_REDACTION_NAME_PATTERN); + iastRedactionValuePattern = + configProvider.getString( + IAST_REDACTION_VALUE_PATTERN, DEFAULT_IAST_REDACTION_VALUE_PATTERN); + iastTruncationMaxValueLength = + configProvider.getInteger( + IAST_TRUNCATION_MAX_VALUE_LENGTH, DEFAULT_IAST_TRUNCATION_MAX_VALUE_LENGTH); + iastMaxRangeCount = iastDetectionMode.getIastMaxRangeCount(configProvider); + iastStacktraceLeakSuppress = + configProvider.getBoolean( + IAST_STACKTRACE_LEAK_SUPPRESS, DEFAULT_IAST_STACKTRACE_LEAK_SUPPRESS); + + ciVisibilityTraceSanitationEnabled = + configProvider.getBoolean(CIVISIBILITY_TRACE_SANITATION_ENABLED, true); + + ciVisibilityAgentlessEnabled = + configProvider.getBoolean( + CIVISIBILITY_AGENTLESS_ENABLED, DEFAULT_CIVISIBILITY_AGENTLESS_ENABLED); + + ciVisibilitySourceDataEnabled = + configProvider.getBoolean( + CIVISIBILITY_SOURCE_DATA_ENABLED, DEFAULT_CIVISIBILITY_SOURCE_DATA_ENABLED); + + ciVisibilitySourceDataRootCheckEnabled = + configProvider.getBoolean( + CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED, + DEFAULT_CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED); + + ciVisibilityBuildInstrumentationEnabled = + configProvider.getBoolean( + CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED, + DEFAULT_CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED); + + ciVisibilitySessionId = configProvider.getLong(CIVISIBILITY_SESSION_ID); + ciVisibilityModuleId = configProvider.getLong(CIVISIBILITY_MODULE_ID); + + final String ciVisibilityAgentlessUrlStr = configProvider.getString(CIVISIBILITY_AGENTLESS_URL); + URI parsedCiVisibilityUri = null; + if (ciVisibilityAgentlessUrlStr != null && !ciVisibilityAgentlessUrlStr.isEmpty()) { + try { + parsedCiVisibilityUri = new URL(ciVisibilityAgentlessUrlStr).toURI(); + } catch (MalformedURLException | URISyntaxException ex) { + log.error( + "Cannot parse CI Visibility agentless URL '{}', skipping", ciVisibilityAgentlessUrlStr); + } + } + if (parsedCiVisibilityUri != null) { + ciVisibilityAgentlessUrl = ciVisibilityAgentlessUrlStr; + } else { + ciVisibilityAgentlessUrl = null; + } + + ciVisibilityAgentJarUri = configProvider.getString(CIVISIBILITY_AGENT_JAR_URI); + ciVisibilityAutoConfigurationEnabled = + configProvider.getBoolean( + CIVISIBILITY_AUTO_CONFIGURATION_ENABLED, + DEFAULT_CIVISIBILITY_AUTO_CONFIGURATION_ENABLED); + ciVisibilityAdditionalChildProcessJvmArgs = + configProvider.getString(CIVISIBILITY_ADDITIONAL_CHILD_PROCESS_JVM_ARGS); + ciVisibilityCompilerPluginAutoConfigurationEnabled = + configProvider.getBoolean( + CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED, + DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED); + ciVisibilityCodeCoverageEnabled = + configProvider.getBoolean(CIVISIBILITY_CODE_COVERAGE_ENABLED, true); + ciVisibilityCodeCoveragePercentageCalculationEnabled = + configProvider.getBoolean(CIVISIBILITY_CODE_COVERAGE_PERCENTAGE_CALCULATION_ENABLED, true); + ciVisibilityCodeCoverageReportDumpDir = + configProvider.getString(CIVISIBILITY_CODE_COVERAGE_REPORT_DUMP_DIR); + ciVisibilityCompilerPluginVersion = + configProvider.getString( + CIVISIBILITY_COMPILER_PLUGIN_VERSION, DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_VERSION); + ciVisibilityJacocoPluginVersion = + configProvider.getString( + CIVISIBILITY_JACOCO_PLUGIN_VERSION, DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_VERSION); + ciVisibilityJacocoPluginVersionProvided = + configProvider.getString(CIVISIBILITY_JACOCO_PLUGIN_VERSION) != null; + ciVisibilityCodeCoverageIncludes = + Arrays.asList( + COLON.split(configProvider.getString(CIVISIBILITY_CODE_COVERAGE_INCLUDES, ":"))); + ciVisibilityCodeCoverageExcludes = + Arrays.asList( + COLON.split( + configProvider.getString( + CIVISIBILITY_CODE_COVERAGE_EXCLUDES, + DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_EXCLUDES))); + ciVisibilityCodeCoverageIncludedPackages = + convertJacocoExclusionFormatToPackagePrefixes(ciVisibilityCodeCoverageIncludes); + ciVisibilityCodeCoverageExcludedPackages = + convertJacocoExclusionFormatToPackagePrefixes(ciVisibilityCodeCoverageExcludes); + ciVisibilityJacocoGradleSourceSets = + configProvider.getList( + CIVISIBILITY_JACOCO_GRADLE_SOURCE_SETS, Collections.singletonList("main")); + ciVisibilityDebugPort = configProvider.getInteger(CIVISIBILITY_DEBUG_PORT); + ciVisibilityGitUploadEnabled = + configProvider.getBoolean( + CIVISIBILITY_GIT_UPLOAD_ENABLED, DEFAULT_CIVISIBILITY_GIT_UPLOAD_ENABLED); + ciVisibilityGitUnshallowEnabled = + configProvider.getBoolean( + CIVISIBILITY_GIT_UNSHALLOW_ENABLED, DEFAULT_CIVISIBILITY_GIT_UNSHALLOW_ENABLED); + ciVisibilityGitUnshallowDefer = + configProvider.getBoolean(CIVISIBILITY_GIT_UNSHALLOW_DEFER, true); + ciVisibilityGitCommandTimeoutMillis = + configProvider.getLong( + CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS, + DEFAULT_CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS); + ciVisibilityBackendApiTimeoutMillis = + configProvider.getLong( + CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS, + DEFAULT_CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS); + ciVisibilityGitUploadTimeoutMillis = + configProvider.getLong( + CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS, DEFAULT_CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS); + ciVisibilityGitRemoteName = + configProvider.getString( + CIVISIBILITY_GIT_REMOTE_NAME, DEFAULT_CIVISIBILITY_GIT_REMOTE_NAME); + ciVisibilitySignalServerHost = + configProvider.getString( + CIVISIBILITY_SIGNAL_SERVER_HOST, DEFAULT_CIVISIBILITY_SIGNAL_SERVER_HOST); + ciVisibilitySignalServerPort = + configProvider.getInteger( + CIVISIBILITY_SIGNAL_SERVER_PORT, DEFAULT_CIVISIBILITY_SIGNAL_SERVER_PORT); + ciVisibilityItrEnabled = configProvider.getBoolean(CIVISIBILITY_ITR_ENABLED, true); + ciVisibilityCiProviderIntegrationEnabled = + configProvider.getBoolean(CIVISIBILITY_CIPROVIDER_INTEGRATION_ENABLED, true); + ciVisibilityRepoIndexSharingEnabled = + configProvider.getBoolean(CIVISIBILITY_REPO_INDEX_SHARING_ENABLED, true); + ciVisibilityModuleExecutionSettingsCacheSize = + configProvider.getInteger(CIVISIBILITY_MODULE_EXECUTION_SETTINGS_CACHE_SIZE, 16); + ciVisibilityJvmInfoCacheSize = configProvider.getInteger(CIVISIBILITY_JVM_INFO_CACHE_SIZE, 8); + ciVisibilityCoverageSegmentsEnabled = + configProvider.getBoolean(CIVISIBILITY_CODE_COVERAGE_SEGMENTS_ENABLED, false); + ciVisibilityCoverageRootPackagesLimit = + configProvider.getInteger(CIVISIBILITY_CODE_COVERAGE_ROOT_PACKAGES_LIMIT, 50); + ciVisibilityInjectedTracerVersion = + configProvider.getString(CIVISIBILITY_INJECTED_TRACER_VERSION); + ciVisibilityResourceFolderNames = + configProvider.getList( + CIVISIBILITY_RESOURCE_FOLDER_NAMES, DEFAULT_CIVISIBILITY_RESOURCE_FOLDER_NAMES); + ciVisibilityFlakyRetryEnabled = + configProvider.getBoolean(CIVISIBILITY_FLAKY_RETRY_ENABLED, false); + ciVisibilityFlakyRetryCount = configProvider.getInteger(CIVISIBILITY_FLAKY_RETRY_COUNT, 5); + ciVisibilityModuleName = configProvider.getString(CIVISIBILITY_MODULE_NAME); + + remoteConfigEnabled = + configProvider.getBoolean(REMOTE_CONFIG_ENABLED, DEFAULT_REMOTE_CONFIG_ENABLED); + remoteConfigIntegrityCheckEnabled = + configProvider.getBoolean( + REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED, DEFAULT_REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED); + remoteConfigUrl = configProvider.getString(REMOTE_CONFIG_URL); + remoteConfigPollIntervalSeconds = + configProvider.getFloat( + REMOTE_CONFIG_POLL_INTERVAL_SECONDS, DEFAULT_REMOTE_CONFIG_POLL_INTERVAL_SECONDS); + remoteConfigMaxPayloadSize = + configProvider.getInteger( + REMOTE_CONFIG_MAX_PAYLOAD_SIZE, DEFAULT_REMOTE_CONFIG_MAX_PAYLOAD_SIZE) + * 1024; + remoteConfigTargetsKeyId = + configProvider.getString( + REMOTE_CONFIG_TARGETS_KEY_ID, DEFAULT_REMOTE_CONFIG_TARGETS_KEY_ID); + remoteConfigTargetsKey = + configProvider.getString(REMOTE_CONFIG_TARGETS_KEY, DEFAULT_REMOTE_CONFIG_TARGETS_KEY); + + debuggerEnabled = configProvider.getBoolean(DEBUGGER_ENABLED, DEFAULT_DEBUGGER_ENABLED); + debuggerUploadTimeout = + configProvider.getInteger(DEBUGGER_UPLOAD_TIMEOUT, DEFAULT_DEBUGGER_UPLOAD_TIMEOUT); + debuggerUploadFlushInterval = + configProvider.getInteger( + DEBUGGER_UPLOAD_FLUSH_INTERVAL, DEFAULT_DEBUGGER_UPLOAD_FLUSH_INTERVAL); + debuggerClassFileDumpEnabled = + configProvider.getBoolean( + DEBUGGER_CLASSFILE_DUMP_ENABLED, DEFAULT_DEBUGGER_CLASSFILE_DUMP_ENABLED); + debuggerPollInterval = + configProvider.getInteger(DEBUGGER_POLL_INTERVAL, DEFAULT_DEBUGGER_POLL_INTERVAL); + debuggerDiagnosticsInterval = + configProvider.getInteger( + DEBUGGER_DIAGNOSTICS_INTERVAL, DEFAULT_DEBUGGER_DIAGNOSTICS_INTERVAL); + debuggerMetricEnabled = + runtimeMetricsEnabled + && configProvider.getBoolean( + DEBUGGER_METRICS_ENABLED, DEFAULT_DEBUGGER_METRICS_ENABLED); + debuggerProbeFileLocation = configProvider.getString(DEBUGGER_PROBE_FILE_LOCATION); + debuggerUploadBatchSize = + configProvider.getInteger(DEBUGGER_UPLOAD_BATCH_SIZE, DEFAULT_DEBUGGER_UPLOAD_BATCH_SIZE); + debuggerMaxPayloadSize = + configProvider.getInteger(DEBUGGER_MAX_PAYLOAD_SIZE, DEFAULT_DEBUGGER_MAX_PAYLOAD_SIZE) + * 1024; + debuggerVerifyByteCode = + configProvider.getBoolean(DEBUGGER_VERIFY_BYTECODE, DEFAULT_DEBUGGER_VERIFY_BYTECODE); + debuggerInstrumentTheWorld = + configProvider.getBoolean( + DEBUGGER_INSTRUMENT_THE_WORLD, DEFAULT_DEBUGGER_INSTRUMENT_THE_WORLD); + debuggerExcludeFiles = configProvider.getString(DEBUGGER_EXCLUDE_FILES); + debuggerCaptureTimeout = + configProvider.getInteger(DEBUGGER_CAPTURE_TIMEOUT, DEFAULT_DEBUGGER_CAPTURE_TIMEOUT); + debuggerRedactedIdentifiers = configProvider.getString(DEBUGGER_REDACTED_IDENTIFIERS, null); + debuggerRedactedTypes = configProvider.getString(DEBUGGER_REDACTED_TYPES, null); + debuggerSymbolEnabled = + configProvider.getBoolean(DEBUGGER_SYMBOL_ENABLED, DEFAULT_DEBUGGER_SYMBOL_ENABLED); + debuggerSymbolForceUpload = + configProvider.getBoolean( + DEBUGGER_SYMBOL_FORCE_UPLOAD, DEFAULT_DEBUGGER_SYMBOL_FORCE_UPLOAD); + debuggerSymbolIncludes = configProvider.getString(DEBUGGER_SYMBOL_INCLUDES, null); + debuggerSymbolFlushThreshold = + configProvider.getInteger( + DEBUGGER_SYMBOL_FLUSH_THRESHOLD, DEFAULT_DEBUGGER_SYMBOL_FLUSH_THRESHOLD); + + awsPropagationEnabled = isPropagationEnabled(true, "aws", "aws-sdk"); + sqsPropagationEnabled = isPropagationEnabled(true, "sqs"); + + kafkaClientPropagationEnabled = isPropagationEnabled(true, "kafka", "kafka.client"); + kafkaClientPropagationDisabledTopics = + tryMakeImmutableSet(configProvider.getList(KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS)); + kafkaClientBase64DecodingEnabled = + configProvider.getBoolean(KAFKA_CLIENT_BASE64_DECODING_ENABLED, false); + + jmsPropagationEnabled = isPropagationEnabled(true, "jms"); + jmsPropagationDisabledTopics = + tryMakeImmutableSet(configProvider.getList(JMS_PROPAGATION_DISABLED_TOPICS)); + jmsPropagationDisabledQueues = + tryMakeImmutableSet(configProvider.getList(JMS_PROPAGATION_DISABLED_QUEUES)); + jmsUnacknowledgedMaxAge = configProvider.getInteger(JMS_UNACKNOWLEDGED_MAX_AGE, 3600); + + rabbitPropagationEnabled = isPropagationEnabled(true, "rabbit", "rabbitmq"); + rabbitPropagationDisabledQueues = + tryMakeImmutableSet(configProvider.getList(RABBIT_PROPAGATION_DISABLED_QUEUES)); + rabbitPropagationDisabledExchanges = + tryMakeImmutableSet(configProvider.getList(RABBIT_PROPAGATION_DISABLED_EXCHANGES)); + rabbitIncludeRoutingKeyInResource = + configProvider.getBoolean(RABBIT_INCLUDE_ROUTINGKEY_IN_RESOURCE, true); + + messageBrokerSplitByDestination = + configProvider.getBoolean(MESSAGE_BROKER_SPLIT_BY_DESTINATION, false); + + grpcIgnoredInboundMethods = + tryMakeImmutableSet(configProvider.getList(GRPC_IGNORED_INBOUND_METHODS)); + final List tmpGrpcIgnoredOutboundMethods = new ArrayList<>(); + tmpGrpcIgnoredOutboundMethods.addAll(configProvider.getList(GRPC_IGNORED_OUTBOUND_METHODS)); + // When tracing shadowing will be possible we can instrument the stubs to silent tracing + // starting from interception points + if (InstrumenterConfig.get() + .isIntegrationEnabled(Collections.singleton("google-pubsub"), true)) { + tmpGrpcIgnoredOutboundMethods.addAll( + configProvider.getList( + GOOGLE_PUBSUB_IGNORED_GRPC_METHODS, + Arrays.asList( + "google.pubsub.v1.Subscriber/ModifyAckDeadline", + "google.pubsub.v1.Subscriber/Acknowledge", + "google.pubsub.v1.Subscriber/Pull", + "google.pubsub.v1.Subscriber/StreamingPull", + "google.pubsub.v1.Publisher/Publish"))); + } + grpcIgnoredOutboundMethods = tryMakeImmutableSet(tmpGrpcIgnoredOutboundMethods); + grpcServerTrimPackageResource = + configProvider.getBoolean(GRPC_SERVER_TRIM_PACKAGE_RESOURCE, false); + grpcServerErrorStatuses = + configProvider.getIntegerRange( + GRPC_SERVER_ERROR_STATUSES, DEFAULT_GRPC_SERVER_ERROR_STATUSES); + grpcClientErrorStatuses = + configProvider.getIntegerRange( + GRPC_CLIENT_ERROR_STATUSES, DEFAULT_GRPC_CLIENT_ERROR_STATUSES); + + hystrixTagsEnabled = configProvider.getBoolean(HYSTRIX_TAGS_ENABLED, false); + hystrixMeasuredEnabled = configProvider.getBoolean(HYSTRIX_MEASURED_ENABLED, false); + + igniteCacheIncludeKeys = configProvider.getBoolean(IGNITE_CACHE_INCLUDE_KEYS, false); + + obfuscationQueryRegexp = + configProvider.getString( + OBFUSCATION_QUERY_STRING_REGEXP, null, "obfuscation.query.string.regexp"); + + playReportHttpStatus = configProvider.getBoolean(PLAY_REPORT_HTTP_STATUS, false); + + servletPrincipalEnabled = configProvider.getBoolean(SERVLET_PRINCIPAL_ENABLED, false); + + xDatadogTagsMaxLength = + configProvider.getInteger( + TRACE_X_DATADOG_TAGS_MAX_LENGTH, DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH); + + servletAsyncTimeoutError = configProvider.getBoolean(SERVLET_ASYNC_TIMEOUT_ERROR, true); + + debugEnabled = configProvider.getBoolean(TRACE_DEBUG, false); + triageEnabled = configProvider.getBoolean(TRACE_TRIAGE, debugEnabled); // debug implies triage + + startupLogsEnabled = + configProvider.getBoolean(STARTUP_LOGS_ENABLED, DEFAULT_STARTUP_LOGS_ENABLED); + + cwsEnabled = configProvider.getBoolean(CWS_ENABLED, DEFAULT_CWS_ENABLED); + cwsTlsRefresh = configProvider.getInteger(CWS_TLS_REFRESH, DEFAULT_CWS_TLS_REFRESH); + + dataStreamsEnabled = + configProvider.getBoolean(DATA_STREAMS_ENABLED, DEFAULT_DATA_STREAMS_ENABLED); + dataStreamsBucketDurationSeconds = + configProvider.getFloat( + DATA_STREAMS_BUCKET_DURATION_SECONDS, DEFAULT_DATA_STREAMS_BUCKET_DURATION); + + azureAppServices = configProvider.getBoolean(AZURE_APP_SERVICES, false); + traceAgentPath = configProvider.getString(TRACE_AGENT_PATH); + String traceAgentArgsString = configProvider.getString(TRACE_AGENT_ARGS); + if (traceAgentArgsString == null) { + traceAgentArgs = Collections.emptyList(); + } else { + traceAgentArgs = + Collections.unmodifiableList( + new ArrayList<>(parseStringIntoSetOfNonEmptyStrings(traceAgentArgsString))); + } + + dogStatsDPath = configProvider.getString(DOGSTATSD_PATH); + String dogStatsDArgsString = configProvider.getString(DOGSTATSD_ARGS); + if (dogStatsDArgsString == null) { + dogStatsDArgs = Collections.emptyList(); + } else { + dogStatsDArgs = + Collections.unmodifiableList( + new ArrayList<>(parseStringIntoSetOfNonEmptyStrings(dogStatsDArgsString))); + } + + // Setting this last because we have a few places where this can come from + apiKey = tmpApiKey; + + boolean longRunningEnabled = + configProvider.getBoolean( + TracerConfig.TRACE_LONG_RUNNING_ENABLED, + ConfigDefaults.DEFAULT_TRACE_LONG_RUNNING_ENABLED); + long longRunningTraceFlushInterval = + configProvider.getLong( + TracerConfig.TRACE_LONG_RUNNING_FLUSH_INTERVAL, + ConfigDefaults.DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL); + + if (longRunningEnabled + && (longRunningTraceFlushInterval < 20 || longRunningTraceFlushInterval > 450)) { + log.warn( + "Provided long running trace flush interval of {} seconds. It should be between 20 seconds and 7.5 minutes." + + "Setting the flush interval to the default value of {} seconds .", + longRunningTraceFlushInterval, + DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL); + longRunningTraceFlushInterval = DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL; + } + longRunningTraceEnabled = longRunningEnabled; + this.longRunningTraceFlushInterval = longRunningTraceFlushInterval; + + this.sparkTaskHistogramEnabled = + configProvider.getBoolean( + SPARK_TASK_HISTOGRAM_ENABLED, ConfigDefaults.DEFAULT_SPARK_TASK_HISTOGRAM_ENABLED); + + this.jaxRsExceptionAsErrorsEnabled = + configProvider.getBoolean( + JAX_RS_EXCEPTION_AS_ERROR_ENABLED, + ConfigDefaults.DEFAULT_JAX_RS_EXCEPTION_AS_ERROR_ENABLED); + + this.traceFlushIntervalSeconds = + configProvider.getFloat( + TracerConfig.TRACE_FLUSH_INTERVAL, ConfigDefaults.DEFAULT_TRACE_FLUSH_INTERVAL); + if (profilingAgentless && apiKey == null) { + log.warn( + "Agentless profiling activated but no api key provided. Profile uploading will likely fail"); + } + + if (isCiVisibilityEnabled() + && ciVisibilityAgentlessEnabled + && (apiKey == null || apiKey.isEmpty())) { + throw new FatalAgentMisconfigurationError( + "Attempt to start in Agentless mode without API key. " + + "Please ensure that either an API key is configured, or the tracer is set up to work with the Agent"); + } + + this.telemetryDebugRequestsEnabled = + configProvider.getBoolean( + GeneralConfig.TELEMETRY_DEBUG_REQUESTS_ENABLED, + ConfigDefaults.DEFAULT_TELEMETRY_DEBUG_REQUESTS_ENABLED); + + timelineEventsEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_TIMELINE_EVENTS_ENABLED, + ProfilingConfig.PROFILING_TIMELINE_EVENTS_ENABLED_DEFAULT); + + log.debug("New instance: {}", this); + } + + /** + * Converts a list of packages in Jacoco exclusion format ({@code + * my.package.*,my.other.package.*}) to list of package prefixes suitable for use with ASM ({@code + * my/package/,my/other/package/}) + */ + private static String[] convertJacocoExclusionFormatToPackagePrefixes(List packages) { + return packages.stream() + .map(s -> (s.endsWith("*") ? s.substring(0, s.length() - 1) : s).replace('.', '/')) + .toArray(String[]::new); + } + + public ConfigProvider configProvider() { + return configProvider; + } + + public long getStartTimeMillis() { + return startTimeMillis; + } + + public String getRuntimeId() { + return runtimeIdEnabled ? RuntimeIdHolder.runtimeId : ""; + } + + public Long getProcessId() { + return PidHelper.getPidAsLong(); + } + + public String getRuntimeVersion() { + return runtimeVersion; + } + + public String getApiKey() { + return apiKey; + } + + public String getApplicationKey() { + return applicationKey; + } + + public String getSite() { + return site; + } + + public String getHostName() { + return HostNameHolder.hostName; + } + + public String getServiceName() { + return serviceName; + } + + public boolean isServiceNameSetByUser() { + return serviceNameSetByUser; + } + + public String getRootContextServiceName() { + return rootContextServiceName; + } + + public boolean isTraceEnabled() { + return instrumenterConfig.isTraceEnabled(); + } + + public boolean isLongRunningTraceEnabled() { + return longRunningTraceEnabled; + } + + public long getLongRunningTraceFlushInterval() { + return longRunningTraceFlushInterval; + } + + public float getTraceFlushIntervalSeconds() { + return traceFlushIntervalSeconds; + } + + public boolean isIntegrationSynapseLegacyOperationName() { + return integrationSynapseLegacyOperationName; + } + + public String getWriterType() { + return writerType; + } + + public boolean isInjectBaggageAsTagsEnabled() { + return injectBaggageAsTagsEnabled; + } + + public boolean isAgentConfiguredUsingDefault() { + return agentConfiguredUsingDefault; + } + + public String getAgentUrl() { + return agentUrl; + } + + public String getAgentHost() { + return agentHost; + } + + public int getAgentPort() { + return agentPort; + } + + public String getAgentUnixDomainSocket() { + return agentUnixDomainSocket; + } + + public String getAgentNamedPipe() { + return agentNamedPipe; + } + + public int getAgentTimeout() { + return agentTimeout; + } + + public Set getNoProxyHosts() { + return noProxyHosts; + } + + public boolean isPrioritySamplingEnabled() { + return prioritySamplingEnabled; + } + + public String getPrioritySamplingForce() { + return prioritySamplingForce; + } + + public boolean isTraceResolverEnabled() { + return traceResolverEnabled; + } + + public Set getIastWeakHashAlgorithms() { + return iastWeakHashAlgorithms; + } + + public Pattern getIastWeakCipherAlgorithms() { + return iastWeakCipherAlgorithms; + } + + public boolean isIastDeduplicationEnabled() { + return iastDeduplicationEnabled; + } + + public int getSpanAttributeSchemaVersion() { + return spanAttributeSchemaVersion; + } + + public boolean isPeerServiceDefaultsEnabled() { + return peerServiceDefaultsEnabled; + } + + public Map getPeerServiceComponentOverrides() { + return peerServiceComponentOverrides; + } + + public boolean isRemoveIntegrationServiceNamesEnabled() { + return removeIntegrationServiceNamesEnabled; + } + + public Map getPeerServiceMapping() { + return peerServiceMapping; + } + + public Map getServiceMapping() { + return serviceMapping; + } + + public Map getRequestHeaderTags() { + return requestHeaderTags; + } + + public Map getResponseHeaderTags() { + return responseHeaderTags; + } + + public boolean isRequestHeaderTagsCommaAllowed() { + return requestHeaderTagsCommaAllowed; + } + + public Map getBaggageMapping() { + return baggageMapping; + } + + public Map getHttpServerPathResourceNameMapping() { + return httpServerPathResourceNameMapping; + } + + public Map getHttpClientPathResourceNameMapping() { + return httpClientPathResourceNameMapping; + } + + public boolean getHttpResourceRemoveTrailingSlash() { + return httpResourceRemoveTrailingSlash; + } + + public BitSet getHttpServerErrorStatuses() { + return httpServerErrorStatuses; + } + + public BitSet getHttpClientErrorStatuses() { + return httpClientErrorStatuses; + } + + public boolean isHttpServerTagQueryString() { + return httpServerTagQueryString; + } + + public boolean isHttpServerRawQueryString() { + return httpServerRawQueryString; + } + + public boolean isHttpServerRawResource() { + return httpServerRawResource; + } + + public boolean isHttpServerDecodedResourcePreserveSpaces() { + return httpServerDecodedResourcePreserveSpaces; + } + + public boolean isHttpServerRouteBasedNaming() { + return httpServerRouteBasedNaming; + } + + public boolean isHttpClientTagQueryString() { + return httpClientTagQueryString; + } + + public boolean isHttpClientTagHeaders() { + return httpClientTagHeaders; + } + + public boolean isHttpClientSplitByDomain() { + return httpClientSplitByDomain; + } + + public boolean isDbClientSplitByInstance() { + return dbClientSplitByInstance; + } + + public boolean isDbClientSplitByInstanceTypeSuffix() { + return dbClientSplitByInstanceTypeSuffix; + } + + public boolean isDbClientSplitByHost() { + return dbClientSplitByHost; + } + + public Set getSplitByTags() { + return splitByTags; + } + + public int getScopeDepthLimit() { + return scopeDepthLimit; + } + + public boolean isScopeStrictMode() { + return scopeStrictMode; + } + + public boolean isScopeInheritAsyncPropagation() { + return scopeInheritAsyncPropagation; + } + + public int getScopeIterationKeepAlive() { + return scopeIterationKeepAlive; + } + + public int getPartialFlushMinSpans() { + return partialFlushMinSpans; + } + + public boolean isTraceStrictWritesEnabled() { + return traceStrictWritesEnabled; + } + + public boolean isLogExtractHeaderNames() { + return logExtractHeaderNames; + } + + @Deprecated + public Set getPropagationStylesToExtract() { + return propagationStylesToExtract; + } + + @Deprecated + public Set getPropagationStylesToInject() { + return propagationStylesToInject; + } + + public boolean isTracePropagationStyleB3PaddingEnabled() { + return tracePropagationStyleB3PaddingEnabled; + } + + public Set getTracePropagationStylesToExtract() { + return tracePropagationStylesToExtract; + } + + public Set getTracePropagationStylesToInject() { + return tracePropagationStylesToInject; + } + + public boolean isTracePropagationExtractFirst() { + return tracePropagationExtractFirst; + } + + public int getClockSyncPeriod() { + return clockSyncPeriod; + } + + public String getDogStatsDNamedPipe() { + return dogStatsDNamedPipe; + } + + public int getDogStatsDStartDelay() { + return dogStatsDStartDelay; + } + + public Integer getStatsDClientQueueSize() { + return statsDClientQueueSize; + } + + public Integer getStatsDClientSocketBuffer() { + return statsDClientSocketBuffer; + } + + public Integer getStatsDClientSocketTimeout() { + return statsDClientSocketTimeout; + } + + public boolean isRuntimeMetricsEnabled() { + return runtimeMetricsEnabled; + } + + public boolean isJmxFetchEnabled() { + return jmxFetchEnabled; + } + + public String getJmxFetchConfigDir() { + return jmxFetchConfigDir; + } + + public List getJmxFetchConfigs() { + return jmxFetchConfigs; + } + + public List getJmxFetchMetricsConfigs() { + return jmxFetchMetricsConfigs; + } + + public Integer getJmxFetchCheckPeriod() { + return jmxFetchCheckPeriod; + } + + public Integer getJmxFetchRefreshBeansPeriod() { + return jmxFetchRefreshBeansPeriod; + } + + public Integer getJmxFetchInitialRefreshBeansPeriod() { + return jmxFetchInitialRefreshBeansPeriod; + } + + public String getJmxFetchStatsdHost() { + return jmxFetchStatsdHost; + } + + public Integer getJmxFetchStatsdPort() { + return jmxFetchStatsdPort; + } + + public boolean isJmxFetchMultipleRuntimeServicesEnabled() { + return jmxFetchMultipleRuntimeServicesEnabled; + } + + public int getJmxFetchMultipleRuntimeServicesLimit() { + return jmxFetchMultipleRuntimeServicesLimit; + } + + public boolean isHealthMetricsEnabled() { + return healthMetricsEnabled; + } + + public String getHealthMetricsStatsdHost() { + return healthMetricsStatsdHost; + } + + public Integer getHealthMetricsStatsdPort() { + return healthMetricsStatsdPort; + } + + public boolean isPerfMetricsEnabled() { + return perfMetricsEnabled; + } + + public boolean isTracerMetricsEnabled() { + return tracerMetricsEnabled; + } + + public boolean isTracerMetricsBufferingEnabled() { + return tracerMetricsBufferingEnabled; + } + + public int getTracerMetricsMaxAggregates() { + return tracerMetricsMaxAggregates; + } + + public int getTracerMetricsMaxPending() { + return tracerMetricsMaxPending; + } + + public boolean isLogsInjectionEnabled() { + return logsInjectionEnabled; + } + + public boolean isReportHostName() { + return reportHostName; + } + + public boolean isTraceAnalyticsEnabled() { + return traceAnalyticsEnabled; + } + + public String getTraceClientIpHeader() { + return traceClientIpHeader; + } + + // whether to collect headers and run the client ip resolution (also requires appsec to be enabled + // or clientIpEnabled) + public boolean isTraceClientIpResolverEnabled() { + return traceClientIpResolverEnabled; + } + + public boolean isTraceGitMetadataEnabled() { + return traceGitMetadataEnabled; + } + + public Map getTraceSamplingServiceRules() { + return traceSamplingServiceRules; + } + + public Map getTraceSamplingOperationRules() { + return traceSamplingOperationRules; + } + + public String getTraceSamplingRules() { + return traceSamplingRules; + } + + public Double getTraceSampleRate() { + return traceSampleRate; + } + + public int getTraceRateLimit() { + return traceRateLimit; + } + + public String getSpanSamplingRules() { + return spanSamplingRules; + } + + public String getSpanSamplingRulesFile() { + return spanSamplingRulesFile; + } + + public boolean isProfilingEnabled() { + if (Platform.isNativeImage()) { + if (!instrumenterConfig.isProfilingEnabled() && profilingEnabled) { + log.warn( + "Profiling was not enabled during the native image build. " + + "Please set DD_PROFILING_ENABLED=true in your native image build configuration if you want" + + "to use profiling."); + } + } + return profilingEnabled && instrumenterConfig.isProfilingEnabled(); + } + + public boolean isProfilingTimelineEventsEnabled() { + return timelineEventsEnabled; + } + + public boolean isProfilingAgentless() { + return profilingAgentless; + } + + public int getProfilingStartDelay() { + return profilingStartDelay; + } + + public boolean isProfilingStartForceFirst() { + return profilingStartForceFirst; + } + + public int getProfilingUploadPeriod() { + return profilingUploadPeriod; + } + + public String getProfilingTemplateOverrideFile() { + return profilingTemplateOverrideFile; + } + + public int getProfilingUploadTimeout() { + return profilingUploadTimeout; + } + + public String getProfilingUploadCompression() { + return profilingUploadCompression; + } + + public String getProfilingProxyHost() { + return profilingProxyHost; + } + + public int getProfilingProxyPort() { + return profilingProxyPort; + } + + public String getProfilingProxyUsername() { + return profilingProxyUsername; + } + + public String getProfilingProxyPassword() { + return profilingProxyPassword; + } + + public int getProfilingExceptionSampleLimit() { + return profilingExceptionSampleLimit; + } + + public int getProfilingDirectAllocationSampleLimit() { + return profilingDirectAllocationSampleLimit; + } + + public int getProfilingExceptionHistogramTopItems() { + return profilingExceptionHistogramTopItems; + } + + public int getProfilingExceptionHistogramMaxCollectionSize() { + return profilingExceptionHistogramMaxCollectionSize; + } + + public boolean isProfilingExcludeAgentThreads() { + return profilingExcludeAgentThreads; + } + + public boolean isProfilingUploadSummaryOn413Enabled() { + return profilingUploadSummaryOn413Enabled; + } + + public boolean isProfilingRecordExceptionMessage() { + return profilingRecordExceptionMessage; + } + + public boolean isDatadogProfilerEnabled() { + return isDatadogProfilerEnabled; + } + + public static boolean isDatadogProfilerEnablementOverridden() { + // old non-LTS versions without important backports + // also, we have no windows binaries + return Platform.isWindows() + || Platform.isJavaVersion(18) + || Platform.isJavaVersion(16) + || Platform.isJavaVersion(15) + || Platform.isJavaVersion(14) + || Platform.isJavaVersion(13) + || Platform.isJavaVersion(12) + || Platform.isJavaVersion(10) + || Platform.isJavaVersion(9); + } + + public static boolean isDatadogProfilerSafeInCurrentEnvironment() { + // don't want to put this logic (which will evolve) in the public ProfilingConfig, and can't + // access Platform there + if (!Platform.isJ9() && Platform.isJavaVersion(8)) { + String arch = System.getProperty("os.arch"); + if ("aarch64".equalsIgnoreCase(arch) || "arm64".equalsIgnoreCase(arch)) { + return false; + } + } + if (Platform.isGraalVM()) { + // let's be conservative about GraalVM and require opt-in from the users + return false; + } + boolean result = + Platform.isJ9() + || !Platform.isJavaVersion(18) // missing AGCT fixes + || Platform.isJavaVersionAtLeast(17, 0, 5) + || (Platform.isJavaVersion(11) && Platform.isJavaVersionAtLeast(11, 0, 17)) + || (Platform.isJavaVersion(8) && Platform.isJavaVersionAtLeast(8, 0, 352)); + + if (result && Platform.isJ9()) { + // Semeru JDK 11 and JDK 17 have problems with unloaded classes and jmethodids, leading to JVM + // crash + // The ASGCT based profilers are only activated in JDK 11.0.18+ and JDK 17.0.6+ + result &= + !((Platform.isJavaVersion(11) && Platform.isJavaVersionAtLeast(11, 0, 18)) + || ((Platform.isJavaVersion(17) && Platform.isJavaVersionAtLeast(17, 0, 6)))); + } + return result; + } + + public boolean isCrashTrackingAgentless() { + return crashTrackingAgentless; + } + + public boolean isTelemetryEnabled() { + return instrumenterConfig.isTelemetryEnabled(); + } + + public float getTelemetryHeartbeatInterval() { + return telemetryHeartbeatInterval; + } + + public long getTelemetryExtendedHeartbeatInterval() { + return telemetryExtendedHeartbeatInterval; + } + + public float getTelemetryMetricsInterval() { + return telemetryMetricsInterval; + } + + public boolean isTelemetryDependencyServiceEnabled() { + return isTelemetryDependencyServiceEnabled; + } + + public boolean isTelemetryMetricsEnabled() { + return telemetryMetricsEnabled; + } + + public boolean isTelemetryLogCollectionEnabled() { + return isTelemetryLogCollectionEnabled; + } + + public boolean isClientIpEnabled() { + return clientIpEnabled; + } + + public ProductActivation getAppSecActivation() { + return instrumenterConfig.getAppSecActivation(); + } + + public boolean isAppSecReportingInband() { + return appSecReportingInband; + } + + public int getAppSecReportMinTimeout() { + return appSecReportMinTimeout; + } + + public int getAppSecReportMaxTimeout() { + return appSecReportMaxTimeout; + } + + public int getAppSecTraceRateLimit() { + return appSecTraceRateLimit; + } + + public boolean isAppSecWafMetrics() { + return appSecWafMetrics; + } + + // in microseconds + public int getAppSecWafTimeout() { + return appSecWafTimeout; + } + + public String getAppSecObfuscationParameterKeyRegexp() { + return appSecObfuscationParameterKeyRegexp; + } + + public String getAppSecObfuscationParameterValueRegexp() { + return appSecObfuscationParameterValueRegexp; + } + + public String getAppSecHttpBlockedTemplateHtml() { + return appSecHttpBlockedTemplateHtml; + } + + public String getAppSecHttpBlockedTemplateJson() { + return appSecHttpBlockedTemplateJson; + } + + public UserEventTrackingMode getAppSecUserEventsTrackingMode() { + return appSecUserEventsTracking; + } + + public boolean isApiSecurityEnabled() { + return apiSecurityEnabled; + } + + public float getApiSecurityRequestSampleRate() { + return apiSecurityRequestSampleRate; + } + + public ProductActivation getIastActivation() { + return instrumenterConfig.getIastActivation(); + } + + public boolean isIastDebugEnabled() { + return iastDebugEnabled; + } + + public int getIastMaxConcurrentRequests() { + return iastMaxConcurrentRequests; + } + + public int getIastVulnerabilitiesPerRequest() { + return iastVulnerabilitiesPerRequest; + } + + public float getIastRequestSampling() { + return iastRequestSampling; + } + + public Verbosity getIastTelemetryVerbosity() { + return isTelemetryEnabled() ? iastTelemetryVerbosity : Verbosity.OFF; + } + + public boolean isIastRedactionEnabled() { + return iastRedactionEnabled; + } + + public String getIastRedactionNamePattern() { + return iastRedactionNamePattern; + } + + public String getIastRedactionValuePattern() { + return iastRedactionValuePattern; + } + + public int getIastTruncationMaxValueLength() { + return iastTruncationMaxValueLength; + } + + public int getIastMaxRangeCount() { + return iastMaxRangeCount; + } + + public boolean isIastStacktraceLeakSuppress() { + return iastStacktraceLeakSuppress; + } + + public boolean isCiVisibilityEnabled() { + return instrumenterConfig.isCiVisibilityEnabled(); + } + + public boolean isUsmEnabled() { + return instrumenterConfig.isUsmEnabled(); + } + + public boolean isCiVisibilityTraceSanitationEnabled() { + return ciVisibilityTraceSanitationEnabled; + } + + public boolean isCiVisibilityAgentlessEnabled() { + return ciVisibilityAgentlessEnabled; + } + + public String getCiVisibilityAgentlessUrl() { + return ciVisibilityAgentlessUrl; + } + + public boolean isCiVisibilitySourceDataEnabled() { + return ciVisibilitySourceDataEnabled; + } + + public boolean isCiVisibilitySourceDataRootCheckEnabled() { + return ciVisibilitySourceDataRootCheckEnabled; + } + + public boolean isCiVisibilityBuildInstrumentationEnabled() { + return ciVisibilityBuildInstrumentationEnabled; + } + + public Long getCiVisibilitySessionId() { + return ciVisibilitySessionId; + } + + public Long getCiVisibilityModuleId() { + return ciVisibilityModuleId; + } + + public String getCiVisibilityAgentJarUri() { + return ciVisibilityAgentJarUri; + } + + public File getCiVisibilityAgentJarFile() { + if (ciVisibilityAgentJarUri == null || ciVisibilityAgentJarUri.isEmpty()) { + throw new IllegalArgumentException("Agent JAR URI is not set in config"); + } + + try { + URI agentJarUri = new URI(ciVisibilityAgentJarUri); + return new File(agentJarUri); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Malformed agent JAR URI: " + ciVisibilityAgentJarUri, e); + } + } + + public boolean isCiVisibilityAutoConfigurationEnabled() { + return ciVisibilityAutoConfigurationEnabled; + } + + public String getCiVisibilityAdditionalChildProcessJvmArgs() { + return ciVisibilityAdditionalChildProcessJvmArgs; + } + + public boolean isCiVisibilityCompilerPluginAutoConfigurationEnabled() { + return ciVisibilityCompilerPluginAutoConfigurationEnabled; + } + + public boolean isCiVisibilityCodeCoverageEnabled() { + return ciVisibilityCodeCoverageEnabled; + } + + public boolean isCiVisibilityCodeCoveragePercentageCalculationEnabled() { + return ciVisibilityCodeCoveragePercentageCalculationEnabled; + } + + public String getCiVisibilityCodeCoverageReportDumpDir() { + return ciVisibilityCodeCoverageReportDumpDir; + } + + public String getCiVisibilityCompilerPluginVersion() { + return ciVisibilityCompilerPluginVersion; + } + + public String getCiVisibilityJacocoPluginVersion() { + return ciVisibilityJacocoPluginVersion; + } + + public boolean isCiVisibilityJacocoPluginVersionProvided() { + return ciVisibilityJacocoPluginVersionProvided; + } + + public List getCiVisibilityCodeCoverageIncludes() { + return ciVisibilityCodeCoverageIncludes; + } + + public List getCiVisibilityCodeCoverageExcludes() { + return ciVisibilityCodeCoverageExcludes; + } + + public String[] getCiVisibilityCodeCoverageIncludedPackages() { + return ciVisibilityCodeCoverageIncludedPackages; + } + + public String[] getCiVisibilityCodeCoverageExcludedPackages() { + return ciVisibilityCodeCoverageExcludedPackages; + } + + public List getCiVisibilityJacocoGradleSourceSets() { + return ciVisibilityJacocoGradleSourceSets; + } + + public Integer getCiVisibilityDebugPort() { + return ciVisibilityDebugPort; + } + + public boolean isCiVisibilityGitUploadEnabled() { + return ciVisibilityGitUploadEnabled; + } + + public boolean isCiVisibilityGitUnshallowEnabled() { + return ciVisibilityGitUnshallowEnabled; + } + + public boolean isCiVisibilityGitUnshallowDefer() { + return ciVisibilityGitUnshallowDefer; + } + + public long getCiVisibilityGitCommandTimeoutMillis() { + return ciVisibilityGitCommandTimeoutMillis; + } + + public long getCiVisibilityBackendApiTimeoutMillis() { + return ciVisibilityBackendApiTimeoutMillis; + } + + public long getCiVisibilityGitUploadTimeoutMillis() { + return ciVisibilityGitUploadTimeoutMillis; + } + + public String getCiVisibilityGitRemoteName() { + return ciVisibilityGitRemoteName; + } + + public int getCiVisibilitySignalServerPort() { + return ciVisibilitySignalServerPort; + } + + public String getCiVisibilitySignalServerHost() { + return ciVisibilitySignalServerHost; + } + + public boolean isCiVisibilityItrEnabled() { + return ciVisibilityItrEnabled; + } + + public boolean isCiVisibilityCiProviderIntegrationEnabled() { + return ciVisibilityCiProviderIntegrationEnabled; + } + + public boolean isCiVisibilityRepoIndexSharingEnabled() { + return ciVisibilityRepoIndexSharingEnabled; + } + + public int getCiVisibilityModuleExecutionSettingsCacheSize() { + return ciVisibilityModuleExecutionSettingsCacheSize; + } + + public int getCiVisibilityJvmInfoCacheSize() { + return ciVisibilityJvmInfoCacheSize; + } + + public boolean isCiVisibilityCoverageSegmentsEnabled() { + return ciVisibilityCoverageSegmentsEnabled; + } + + public int getCiVisibilityCoverageRootPackagesLimit() { + return ciVisibilityCoverageRootPackagesLimit; + } + + public String getCiVisibilityInjectedTracerVersion() { + return ciVisibilityInjectedTracerVersion; + } + + public List getCiVisibilityResourceFolderNames() { + return ciVisibilityResourceFolderNames; + } + + public boolean isCiVisibilityFlakyRetryEnabled() { + return ciVisibilityFlakyRetryEnabled; + } + + public int getCiVisibilityFlakyRetryCount() { + return ciVisibilityFlakyRetryCount; + } + + public String getCiVisibilityModuleName() { + return ciVisibilityModuleName; + } + + public String getAppSecRulesFile() { + return appSecRulesFile; + } + + public long getRemoteConfigMaxPayloadSizeBytes() { + return remoteConfigMaxPayloadSize; + } + + public boolean isRemoteConfigEnabled() { + return remoteConfigEnabled; + } + + public boolean isRemoteConfigIntegrityCheckEnabled() { + return remoteConfigIntegrityCheckEnabled; + } + + public String getFinalRemoteConfigUrl() { + return remoteConfigUrl; + } + + public float getRemoteConfigPollIntervalSeconds() { + return remoteConfigPollIntervalSeconds; + } + + public String getRemoteConfigTargetsKeyId() { + return remoteConfigTargetsKeyId; + } + + public String getRemoteConfigTargetsKey() { + return remoteConfigTargetsKey; + } + + public boolean isDebuggerEnabled() { + return debuggerEnabled; + } + + public int getDebuggerUploadTimeout() { + return debuggerUploadTimeout; + } + + public int getDebuggerUploadFlushInterval() { + return debuggerUploadFlushInterval; + } + + public boolean isDebuggerClassFileDumpEnabled() { + return debuggerClassFileDumpEnabled; + } + + public int getDebuggerPollInterval() { + return debuggerPollInterval; + } + + public int getDebuggerDiagnosticsInterval() { + return debuggerDiagnosticsInterval; + } + + public boolean isDebuggerMetricsEnabled() { + return debuggerMetricEnabled; + } + + public int getDebuggerUploadBatchSize() { + return debuggerUploadBatchSize; + } + + public long getDebuggerMaxPayloadSize() { + return debuggerMaxPayloadSize; + } + + public boolean isDebuggerVerifyByteCode() { + return debuggerVerifyByteCode; + } + + public boolean isDebuggerInstrumentTheWorld() { + return debuggerInstrumentTheWorld; + } + + public String getDebuggerExcludeFiles() { + return debuggerExcludeFiles; + } + + public int getDebuggerCaptureTimeout() { + return debuggerCaptureTimeout; + } + + public boolean isDebuggerSymbolEnabled() { + return debuggerSymbolEnabled; + } + + public boolean isDebuggerSymbolForceUpload() { + return debuggerSymbolForceUpload; + } + + public String getDebuggerSymbolIncludes() { + return debuggerSymbolIncludes; + } + + public int getDebuggerSymbolFlushThreshold() { + return debuggerSymbolFlushThreshold; + } + + public String getFinalDebuggerProbeUrl() { + // by default poll from datadog agent + return "http://" + agentHost + ":" + agentPort; + } + + public String getFinalDebuggerSnapshotUrl() { + // by default send to datadog agent + return agentUrl + "/debugger/v1/input"; + } + + public String getFinalDebuggerSymDBUrl() { + return agentUrl + "/symdb/v1/input"; + } + + public String getDebuggerProbeFileLocation() { + return debuggerProbeFileLocation; + } + + public String getDebuggerRedactedIdentifiers() { + return debuggerRedactedIdentifiers; + } + + public String getDebuggerRedactedTypes() { + return debuggerRedactedTypes; + } + + public boolean isAwsPropagationEnabled() { + return awsPropagationEnabled; + } + + public boolean isSqsPropagationEnabled() { + return sqsPropagationEnabled; + } + + public boolean isKafkaClientPropagationEnabled() { + return kafkaClientPropagationEnabled; + } + + public boolean isKafkaClientPropagationDisabledForTopic(String topic) { + return null != topic && kafkaClientPropagationDisabledTopics.contains(topic); + } + + public boolean isJmsPropagationEnabled() { + return jmsPropagationEnabled; + } + + public boolean isJmsPropagationDisabledForDestination(final String queueOrTopic) { + return null != queueOrTopic + && (jmsPropagationDisabledQueues.contains(queueOrTopic) + || jmsPropagationDisabledTopics.contains(queueOrTopic)); + } + + public int getJmsUnacknowledgedMaxAge() { + return jmsUnacknowledgedMaxAge; + } + + public boolean isKafkaClientBase64DecodingEnabled() { + return kafkaClientBase64DecodingEnabled; + } + + public boolean isRabbitPropagationEnabled() { + return rabbitPropagationEnabled; + } + + public boolean isRabbitPropagationDisabledForDestination(final String queueOrExchange) { + return null != queueOrExchange + && (rabbitPropagationDisabledQueues.contains(queueOrExchange) + || rabbitPropagationDisabledExchanges.contains(queueOrExchange)); + } + + public boolean isRabbitIncludeRoutingKeyInResource() { + return rabbitIncludeRoutingKeyInResource; + } + + public boolean isMessageBrokerSplitByDestination() { + return messageBrokerSplitByDestination; + } + + public boolean isHystrixTagsEnabled() { + return hystrixTagsEnabled; + } + + public boolean isHystrixMeasuredEnabled() { + return hystrixMeasuredEnabled; + } + + public boolean isIgniteCacheIncludeKeys() { + return igniteCacheIncludeKeys; + } + + public String getObfuscationQueryRegexp() { + return obfuscationQueryRegexp; + } + + public boolean getPlayReportHttpStatus() { + return playReportHttpStatus; + } + + public boolean isServletPrincipalEnabled() { + return servletPrincipalEnabled; + } + + public boolean isSpringDataRepositoryInterfaceResourceName() { + return springDataRepositoryInterfaceResourceName; + } + + public int getxDatadogTagsMaxLength() { + return xDatadogTagsMaxLength; + } + + public boolean isServletAsyncTimeoutError() { + return servletAsyncTimeoutError; + } + + public boolean isTraceAgentV05Enabled() { + return traceAgentV05Enabled; + } + + public boolean isDebugEnabled() { + return debugEnabled; + } + + public boolean isTriageEnabled() { + return triageEnabled; + } + + public boolean isStartupLogsEnabled() { + return startupLogsEnabled; + } + + public boolean isCwsEnabled() { + return cwsEnabled; + } + + public int getCwsTlsRefresh() { + return cwsTlsRefresh; + } + + public boolean isAzureAppServices() { + return azureAppServices; + } + + public boolean isDataStreamsEnabled() { + return dataStreamsEnabled; + } + + public float getDataStreamsBucketDurationSeconds() { + return dataStreamsBucketDurationSeconds; + } + + public long getDataStreamsBucketDurationNanoseconds() { + // Rounds to the nearest millisecond before converting to nanos + int milliseconds = Math.round(dataStreamsBucketDurationSeconds * 1000); + return TimeUnit.MILLISECONDS.toNanos(milliseconds); + } + + public String getTraceAgentPath() { + return traceAgentPath; + } + + public List getTraceAgentArgs() { + return traceAgentArgs; + } + + public String getDogStatsDPath() { + return dogStatsDPath; + } + + public List getDogStatsDArgs() { + return dogStatsDArgs; + } + + public String getConfigFileStatus() { + return configFileStatus; + } + + public IdGenerationStrategy getIdGenerationStrategy() { + return idGenerationStrategy; + } + + public boolean isTrace128bitTraceIdGenerationEnabled() { + return trace128bitTraceIdGenerationEnabled; + } + + public Set getGrpcIgnoredInboundMethods() { + return grpcIgnoredInboundMethods; + } + + public Set getGrpcIgnoredOutboundMethods() { + return grpcIgnoredOutboundMethods; + } + + public boolean isGrpcServerTrimPackageResource() { + return grpcServerTrimPackageResource; + } + + public BitSet getGrpcServerErrorStatuses() { + return grpcServerErrorStatuses; + } + + public BitSet getGrpcClientErrorStatuses() { + return grpcClientErrorStatuses; + } + + public boolean isElasticsearchBodyEnabled() { + return elasticsearchBodyEnabled; + } + + public boolean isElasticsearchParamsEnabled() { + return elasticsearchParamsEnabled; + } + + public boolean isElasticsearchBodyAndParamsEnabled() { + return elasticsearchBodyAndParamsEnabled; + } + + public boolean isSparkTaskHistogramEnabled() { + return sparkTaskHistogramEnabled; + } + + public boolean isJaxRsExceptionAsErrorEnabled() { + return jaxRsExceptionAsErrorsEnabled; + } + + /** @return A map of tags to be applied only to the local application root span. */ + public Map getLocalRootSpanTags() { + final Map runtimeTags = getRuntimeTags(); + final Map result = new HashMap<>(runtimeTags.size() + 2); + result.putAll(runtimeTags); + result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE); + result.put(SCHEMA_VERSION_TAG_KEY, SpanNaming.instance().version()); + result.put(PROFILING_ENABLED, isProfilingEnabled() ? 1 : 0); + + if (reportHostName) { + final String hostName = getHostName(); + if (null != hostName && !hostName.isEmpty()) { + result.put(INTERNAL_HOST_NAME, hostName); + } + } + + if (azureAppServices) { + result.putAll(getAzureAppServicesTags()); + } + + result.putAll(getProcessIdTag()); + + return Collections.unmodifiableMap(result); + } + + public WellKnownTags getWellKnownTags() { + return new WellKnownTags( + getRuntimeId(), + reportHostName ? getHostName() : "", + getEnv(), + serviceName, + getVersion(), + LANGUAGE_TAG_VALUE); + } + + public String getPrimaryTag() { + return primaryTag; + } + + public Set getMetricsIgnoredResources() { + return tryMakeImmutableSet(configProvider.getList(TRACER_METRICS_IGNORED_RESOURCES)); + } + + public String getEnv() { + // intentionally not thread safe + if (env == null) { + env = getMergedSpanTags().get("env"); + if (env == null) { + env = ""; + } + } + + return env; + } + + public String getVersion() { + // intentionally not thread safe + if (version == null) { + version = getMergedSpanTags().get("version"); + if (version == null) { + version = ""; + } + } + + return version; + } + + public Map getMergedSpanTags() { + // Do not include runtimeId into span tags: we only want that added to the root span + final Map result = newHashMap(getGlobalTags().size() + spanTags.size()); + result.putAll(getGlobalTags()); + result.putAll(spanTags); + return Collections.unmodifiableMap(result); + } + + public Map getMergedJmxTags() { + final Map runtimeTags = getRuntimeTags(); + final Map result = + newHashMap( + getGlobalTags().size() + jmxTags.size() + runtimeTags.size() + 1 /* for serviceName */); + result.putAll(getGlobalTags()); + result.putAll(jmxTags); + result.putAll(runtimeTags); + // service name set here instead of getRuntimeTags because apm already manages the service tag + // and may chose to override it. + // Additionally, infra/JMX metrics require `service` rather than APM's `service.name` tag + result.put(SERVICE_TAG, serviceName); + return Collections.unmodifiableMap(result); + } + + public Map getMergedProfilingTags() { + final Map runtimeTags = getRuntimeTags(); + final String host = getHostName(); + final Map result = + newHashMap( + getGlobalTags().size() + + profilingTags.size() + + runtimeTags.size() + + 4 /* for serviceName and host and language and runtime_version */); + result.put(HOST_TAG, host); // Host goes first to allow to override it + result.putAll(getGlobalTags()); + result.putAll(profilingTags); + result.putAll(runtimeTags); + // service name set here instead of getRuntimeTags because apm already manages the service tag + // and may chose to override it. + result.put(SERVICE_TAG, serviceName); + result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE); + result.put(RUNTIME_VERSION_TAG, runtimeVersion); + return Collections.unmodifiableMap(result); + } + + public Map getMergedCrashTrackingTags() { + final Map runtimeTags = getRuntimeTags(); + final String host = getHostName(); + final Map result = + newHashMap( + getGlobalTags().size() + + crashTrackingTags.size() + + runtimeTags.size() + + 3 /* for serviceName and host and language */); + result.put(HOST_TAG, host); // Host goes first to allow to override it + result.putAll(getGlobalTags()); + result.putAll(crashTrackingTags); + result.putAll(runtimeTags); + // service name set here instead of getRuntimeTags because apm already manages the service tag + // and may chose to override it. + result.put(SERVICE_TAG, serviceName); + result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE); + return Collections.unmodifiableMap(result); + } + + /** + * Returns the sample rate for the specified instrumentation or {@link + * ConfigDefaults#DEFAULT_ANALYTICS_SAMPLE_RATE} if none specified. + */ + public float getInstrumentationAnalyticsSampleRate(final String... aliases) { + for (final String alias : aliases) { + final String configKey = alias + ".analytics.sample-rate"; + final Float rate = configProvider.getFloat("trace." + configKey, configKey); + if (null != rate) { + return rate; + } + } + return DEFAULT_ANALYTICS_SAMPLE_RATE; + } + + /** + * Provide 'global' tags, i.e. tags set everywhere. We have to support old (dd.trace.global.tags) + * version of this setting if new (dd.tags) version has not been specified. + */ + public Map getGlobalTags() { + return tags; + } + + /** + * Return a map of tags required by the datadog backend to link runtime metrics (i.e. jmx) and + * traces. + * + *

These tags must be applied to every runtime metrics and placed on the root span of every + * trace. + * + * @return A map of tag-name -> tag-value + */ + private Map getRuntimeTags() { + return Collections.singletonMap(RUNTIME_ID_TAG, getRuntimeId()); + } + + private Map getProcessIdTag() { + return Collections.singletonMap(PID_TAG, getProcessId()); + } + + private Map getAzureAppServicesTags() { + // These variable names and derivations are copied from the dotnet tracer + // See + // https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/src/Datadog.Trace/PlatformHelpers/AzureAppServices.cs + // and + // https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/src/Datadog.Trace/TraceContext.cs#L207 + Map aasTags = new HashMap<>(); + + /// The site name of the site instance in Azure where the traced application is running. + String siteName = getEnv("WEBSITE_SITE_NAME"); + if (siteName != null) { + aasTags.put("aas.site.name", siteName); + } + + // The kind of application instance running in Azure. + // Possible values: app, api, mobileapp, app_linux, app_linux_container, functionapp, + // functionapp_linux, functionapp_linux_container + + // The type of application instance running in Azure. + // Possible values: app, function + if (getEnv("FUNCTIONS_WORKER_RUNTIME") != null + || getEnv("FUNCTIONS_EXTENSIONS_VERSION") != null) { + aasTags.put("aas.site.kind", "functionapp"); + aasTags.put("aas.site.type", "function"); + } else { + aasTags.put("aas.site.kind", "app"); + aasTags.put("aas.site.type", "app"); + } + + // The resource group of the site instance in Azure App Services + String resourceGroup = getEnv("WEBSITE_RESOURCE_GROUP"); + if (resourceGroup != null) { + aasTags.put("aas.resource.group", resourceGroup); + } + + // Example: 8c500027-5f00-400e-8f00-60000000000f+apm-dotnet-EastUSwebspace + // Format: {subscriptionId}+{planResourceGroup}-{hostedInRegion} + String websiteOwner = getEnv("WEBSITE_OWNER_NAME"); + int plusIndex = websiteOwner == null ? -1 : websiteOwner.indexOf("+"); + + // The subscription ID of the site instance in Azure App Services + String subscriptionId = null; + if (plusIndex > 0) { + subscriptionId = websiteOwner.substring(0, plusIndex); + aasTags.put("aas.subscription.id", subscriptionId); + } + + if (subscriptionId != null && siteName != null && resourceGroup != null) { + // The resource ID of the site instance in Azure App Services + String resourceId = + "/subscriptions/" + + subscriptionId + + "/resourcegroups/" + + resourceGroup + + "/providers/microsoft.web/sites/" + + siteName; + resourceId = resourceId.toLowerCase(Locale.ROOT); + aasTags.put("aas.resource.id", resourceId); + } else { + log.warn( + "Unable to generate resource id subscription id: {}, site name: {}, resource group {}", + subscriptionId, + siteName, + resourceGroup); + } + + // The instance ID in Azure + String instanceId = getEnv("WEBSITE_INSTANCE_ID"); + instanceId = instanceId == null ? "unknown" : instanceId; + aasTags.put("aas.environment.instance_id", instanceId); + + // The instance name in Azure + String instanceName = getEnv("COMPUTERNAME"); + instanceName = instanceName == null ? "unknown" : instanceName; + aasTags.put("aas.environment.instance_name", instanceName); + + // The operating system in Azure + String operatingSystem = getEnv("WEBSITE_OS"); + operatingSystem = operatingSystem == null ? "unknown" : operatingSystem; + aasTags.put("aas.environment.os", operatingSystem); + + // The version of the extension installed + String siteExtensionVersion = getEnv("DD_AAS_JAVA_EXTENSION_VERSION"); + siteExtensionVersion = siteExtensionVersion == null ? "unknown" : siteExtensionVersion; + aasTags.put("aas.environment.extension_version", siteExtensionVersion); + + aasTags.put("aas.environment.runtime", getProp("java.vm.name", "unknown")); + + return aasTags; + } + + private int schemaVersionFromConfig() { + String versionStr = + configProvider.getString(TRACE_SPAN_ATTRIBUTE_SCHEMA, "v" + SpanNaming.SCHEMA_MIN_VERSION); + Matcher matcher = Pattern.compile("^v?(0|[1-9]\\d*)$").matcher(versionStr); + int parsedVersion = -1; + if (matcher.matches()) { + parsedVersion = Integer.parseInt(matcher.group(1)); + } + if (parsedVersion < SpanNaming.SCHEMA_MIN_VERSION + || parsedVersion > SpanNaming.SCHEMA_MAX_VERSION) { + log.warn( + "Invalid attribute schema version {} invalid or out of range [v{}, v{}]. Defaulting to v{}", + versionStr, + SpanNaming.SCHEMA_MIN_VERSION, + SpanNaming.SCHEMA_MAX_VERSION, + SpanNaming.SCHEMA_MIN_VERSION); + parsedVersion = SpanNaming.SCHEMA_MIN_VERSION; + } + return parsedVersion; + } + + public String getFinalProfilingUrl() { + if (profilingUrl != null) { + // when profilingUrl is set we use it regardless of apiKey/agentless config + return profilingUrl; + } else if (profilingAgentless) { + // when agentless profiling is turned on we send directly to our intake + return "https://intake.profile." + site + "/api/v2/profile"; + } else { + // when profilingUrl and agentless are not set we send to the dd trace agent running locally + return "http://" + agentHost + ":" + agentPort + "/profiling/v1/input"; + } + } + + public String getFinalCrashTrackingTelemetryUrl() { + if (crashTrackingAgentless) { + // when agentless crashTracking is turned on we send directly to our intake + return "https://all-http-intake.logs." + site + "/api/v2/apmtelemetry"; + } else { + // when agentless are not set we send to the dd trace agent running locally + return "http://" + agentHost + ":" + agentPort + "/telemetry/proxy/api/v2/apmtelemetry"; + } + } + + public boolean isJmxFetchIntegrationEnabled( + final Iterable integrationNames, final boolean defaultEnabled) { + return configProvider.isEnabled(integrationNames, "jmxfetch.", ".enabled", defaultEnabled); + } + + public boolean isRuleEnabled(final String name) { + return isRuleEnabled(name, true); + } + + public boolean isRuleEnabled(final String name, boolean defaultEnabled) { + boolean enabled = configProvider.getBoolean("trace." + name + ".enabled", defaultEnabled); + boolean lowerEnabled = + configProvider.getBoolean( + "trace." + name.toLowerCase(Locale.ROOT) + ".enabled", defaultEnabled); + return defaultEnabled ? enabled && lowerEnabled : enabled || lowerEnabled; + } + + /** + * @param integrationNames + * @param defaultEnabled + * @return + * @deprecated This method should only be used internally. Use the instance getter instead {@link + * #isJmxFetchIntegrationEnabled(Iterable, boolean)}. + */ + public static boolean jmxFetchIntegrationEnabled( + final SortedSet integrationNames, final boolean defaultEnabled) { + return Config.get().isJmxFetchIntegrationEnabled(integrationNames, defaultEnabled); + } + + public boolean isEndToEndDurationEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".e2e.duration.enabled", defaultEnabled); + } + + public boolean isPropagationEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".propagation.enabled", defaultEnabled); + } + + public boolean isLegacyTracingEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return SpanNaming.instance().namingSchema().allowInferredServices() + && configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".legacy.tracing.enabled", defaultEnabled); + } + + public boolean isTimeInQueueEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return SpanNaming.instance().namingSchema().allowInferredServices() + && configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".time-in-queue.enabled", defaultEnabled); + } + + public boolean isEnabled( + final boolean defaultEnabled, final String settingName, String settingSuffix) { + return configProvider.isEnabled( + Collections.singletonList(settingName), "", settingSuffix, defaultEnabled); + } + + public String getDBMPropagationMode() { + return DBMPropagationMode; + } + + private void logIgnoredSettingWarning( + String setting, String overridingSetting, String overridingSuffix) { + log.warn( + "Setting {} ignored since {}{} is enabled.", + propertyNameToSystemPropertyName(setting), + propertyNameToSystemPropertyName(overridingSetting), + overridingSuffix); + } + + private void logOverriddenSettingWarning(String setting, String overridingSetting, Object value) { + log.warn( + "Setting {} is overridden by setting {} with value {}.", + propertyNameToSystemPropertyName(setting), + propertyNameToSystemPropertyName(overridingSetting), + value); + } + + private void logOverriddenDeprecatedSettingWarning( + String setting, String overridingSetting, Object value) { + log.warn( + "Setting {} is deprecated and overridden by setting {} with value {}.", + propertyNameToSystemPropertyName(setting), + propertyNameToSystemPropertyName(overridingSetting), + value); + } + + private void logDeprecatedConvertedSetting( + String deprecatedSetting, Object oldValue, String newSetting, Object newValue) { + log.warn( + "Setting {} is deprecated and the value {} has been converted to {} for setting {}.", + propertyNameToSystemPropertyName(deprecatedSetting), + oldValue, + newValue, + propertyNameToSystemPropertyName(newSetting)); + } + + public boolean isTraceAnalyticsIntegrationEnabled( + final SortedSet integrationNames, final boolean defaultEnabled) { + return configProvider.isEnabled(integrationNames, "", ".analytics.enabled", defaultEnabled); + } + + public boolean isTraceAnalyticsIntegrationEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".analytics.enabled", defaultEnabled); + } + + public boolean isSamplingMechanismValidationDisabled() { + return configProvider.getBoolean(TracerConfig.SAMPLING_MECHANISM_VALIDATION_DISABLED, false); + } + + public > T getEnumValue( + final String name, final Class type, final T defaultValue) { + return configProvider.getEnum(name, type, defaultValue); + } + + /** + * @param integrationNames + * @param defaultEnabled + * @return + * @deprecated This method should only be used internally. Use the instance getter instead {@link + * #isTraceAnalyticsIntegrationEnabled(SortedSet, boolean)}. + */ + public static boolean traceAnalyticsIntegrationEnabled( + final SortedSet integrationNames, final boolean defaultEnabled) { + return Config.get().isTraceAnalyticsIntegrationEnabled(integrationNames, defaultEnabled); + } + + public boolean isTelemetryDebugRequestsEnabled() { + return telemetryDebugRequestsEnabled; + } + + private Set getSettingsSetFromEnvironment( + String name, Function mapper, boolean splitOnWS) { + final String value = configProvider.getString(name, ""); + return convertStringSetToSet( + name, parseStringIntoSetOfNonEmptyStrings(value, splitOnWS), mapper); + } + + private Set convertSettingsSet(Set fromSet, Function> mapper) { + if (fromSet.isEmpty()) { + return Collections.emptySet(); + } + Set result = new LinkedHashSet<>(fromSet.size()); + for (F from : fromSet) { + for (T to : mapper.apply(from)) { + result.add(to); + } + } + return Collections.unmodifiableSet(result); + } + + public static final String PREFIX = "dd."; + + /** + * Converts the property name, e.g. 'service.name' into a public system property name, e.g. + * `dd.service.name`. + * + * @param setting The setting name, e.g. `service.name` + * @return The public facing system property name + */ + @NonNull + private static String propertyNameToSystemPropertyName(final String setting) { + return PREFIX + setting; + } + + @NonNull + private static Map newHashMap(final int size) { + return new HashMap<>(size + 1, 1f); + } + + /** + * @param map + * @param propNames + * @return new unmodifiable copy of {@param map} where properties are overwritten from environment + */ + @NonNull + private Map getMapWithPropertiesDefinedByEnvironment( + @NonNull final Map map, @NonNull final String... propNames) { + final Map res = new HashMap<>(map); + for (final String propName : propNames) { + final String val = configProvider.getString(propName); + if (val != null) { + res.put(propName, val); + } + } + return Collections.unmodifiableMap(res); + } + + @NonNull + private static Set parseStringIntoSetOfNonEmptyStrings(final String str) { + return parseStringIntoSetOfNonEmptyStrings(str, true); + } + + @NonNull + private static Set parseStringIntoSetOfNonEmptyStrings( + final String str, boolean splitOnWS) { + // Using LinkedHashSet to preserve original string order + final Set result = new LinkedHashSet<>(); + // Java returns single value when splitting an empty string. We do not need that value, so + // we need to throw it out. + int start = 0; + int i = 0; + for (; i < str.length(); ++i) { + char c = str.charAt(i); + if (c == ',' || (splitOnWS && Character.isWhitespace(c))) { + if (i - start - 1 > 0) { + result.add(str.substring(start, i)); + } + start = i + 1; + } + } + if (i - start - 1 > 0) { + result.add(str.substring(start)); + } + return Collections.unmodifiableSet(result); + } + + private static Set convertStringSetToSet( + String setting, final Set input, Function mapper) { + if (input.isEmpty()) { + return Collections.emptySet(); + } + // Using LinkedHashSet to preserve original string order + final Set result = new LinkedHashSet<>(); + for (final String value : input) { + try { + result.add(mapper.apply(value)); + } catch (final IllegalArgumentException e) { + log.warn( + "Cannot recognize config string value {} for setting {}", + value, + propertyNameToSystemPropertyName(setting)); + } + } + return Collections.unmodifiableSet(result); + } + + /** Returns the detected hostname. First tries locally, then using DNS */ + static String initHostName() { + String possibleHostname; + + // Try environment variable. This works in almost all environments + if (isWindowsOS()) { + possibleHostname = getEnv("COMPUTERNAME"); + } else { + possibleHostname = getEnv("HOSTNAME"); + } + + if (possibleHostname != null && !possibleHostname.isEmpty()) { + log.debug("Determined hostname from environment variable"); + return possibleHostname.trim(); + } + + // Try hostname files + final String[] hostNameFiles = new String[] {"/proc/sys/kernel/hostname", "/etc/hostname"}; + for (final String hostNameFile : hostNameFiles) { + try { + final Path hostNamePath = FileSystems.getDefault().getPath(hostNameFile); + if (Files.isRegularFile(hostNamePath)) { + byte[] bytes = Files.readAllBytes(hostNamePath); + possibleHostname = new String(bytes, StandardCharsets.ISO_8859_1); + } + } catch (Throwable t) { + // Ignore + } + possibleHostname = Strings.trim(possibleHostname); + if (!possibleHostname.isEmpty()) { + log.debug("Determined hostname from file {}", hostNameFile); + return possibleHostname; + } + } + + // Try hostname command + try (final BufferedReader reader = + new BufferedReader( + new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))) { + possibleHostname = reader.readLine(); + } catch (final Throwable ignore) { + // Ignore. Hostname command is not always available + } + + if (possibleHostname != null && !possibleHostname.isEmpty()) { + log.debug("Determined hostname from hostname command"); + return possibleHostname.trim(); + } + + // From DNS + try { + return InetAddress.getLocalHost().getHostName(); + } catch (final UnknownHostException e) { + // If we are not able to detect the hostname we do not throw an exception. + } + + return null; + } + + private static boolean isWindowsOS() { + return getProp("os.name").startsWith("Windows"); + } + + private static String getEnv(String name) { + String value = System.getenv(name); + if (value != null) { + ConfigCollector.get().put(name, value, ConfigOrigin.ENV); + } + return value; + } + + private static Pattern getPattern(String defaultValue, String userValue) { + try { + if (userValue != null) { + return Pattern.compile(userValue); + } + } catch (Exception e) { + log.debug("Cannot create pattern from user value {}", userValue); + } + return Pattern.compile(defaultValue); + } + + private static String getProp(String name) { + return getProp(name, null); + } + + private static String getProp(String name, String def) { + String value = System.getProperty(name, def); + if (value != null) { + ConfigCollector.get().put(name, value, ConfigOrigin.JVM_PROP); + } + return value; + } + + // This has to be placed after all other static fields to give them a chance to initialize + + private static final Config INSTANCE = + new Config( + Platform.isNativeImageBuilder() + ? ConfigProvider.withoutCollector() + : ConfigProvider.getInstance(), + InstrumenterConfig.get()); + + public static Config get() { + return INSTANCE; + } + + /** + * This method is deprecated since the method of configuration will be changed in the future. The + * properties instance should instead be passed directly into the DDTracer builder: + * + *

+   *   DDTracer.builder().withProperties(new Properties()).build()
+   * 
+ * + *

Config keys for use in Properties instance construction can be found in {@link + * GeneralConfig} and {@link TracerConfig}. + * + * @deprecated + */ + @Deprecated + public static Config get(final Properties properties) { + if (properties == null || properties.isEmpty()) { + return INSTANCE; + } else { + return new Config(ConfigProvider.withPropertiesOverride(properties)); + } + } + + @Override + public String toString() { + return "Config{" + + "instrumenterConfig=" + + instrumenterConfig + + ", runtimeId='" + + getRuntimeId() + + '\'' + + ", runtimeVersion='" + + runtimeVersion + + ", apiKey=" + + (apiKey == null ? "null" : "****") + + ", site='" + + site + + '\'' + + ", hostName='" + + getHostName() + + '\'' + + ", serviceName='" + + serviceName + + '\'' + + ", serviceNameSetByUser=" + + serviceNameSetByUser + + ", rootContextServiceName=" + + rootContextServiceName + + ", integrationSynapseLegacyOperationName=" + + integrationSynapseLegacyOperationName + + ", writerType='" + + writerType + + '\'' + + ", agentConfiguredUsingDefault=" + + agentConfiguredUsingDefault + + ", agentUrl='" + + agentUrl + + '\'' + + ", agentHost='" + + agentHost + + '\'' + + ", agentPort=" + + agentPort + + ", agentUnixDomainSocket='" + + agentUnixDomainSocket + + '\'' + + ", agentTimeout=" + + agentTimeout + + ", noProxyHosts=" + + noProxyHosts + + ", prioritySamplingEnabled=" + + prioritySamplingEnabled + + ", prioritySamplingForce='" + + prioritySamplingForce + + '\'' + + ", traceResolverEnabled=" + + traceResolverEnabled + + ", serviceMapping=" + + serviceMapping + + ", tags=" + + tags + + ", spanTags=" + + spanTags + + ", jmxTags=" + + jmxTags + + ", requestHeaderTags=" + + requestHeaderTags + + ", responseHeaderTags=" + + responseHeaderTags + + ", baggageMapping=" + + baggageMapping + + ", httpServerErrorStatuses=" + + httpServerErrorStatuses + + ", httpClientErrorStatuses=" + + httpClientErrorStatuses + + ", httpServerTagQueryString=" + + httpServerTagQueryString + + ", httpServerRawQueryString=" + + httpServerRawQueryString + + ", httpServerRawResource=" + + httpServerRawResource + + ", httpServerRouteBasedNaming=" + + httpServerRouteBasedNaming + + ", httpServerPathResourceNameMapping=" + + httpServerPathResourceNameMapping + + ", httpClientPathResourceNameMapping=" + + httpClientPathResourceNameMapping + + ", httpClientTagQueryString=" + + httpClientTagQueryString + + ", httpClientSplitByDomain=" + + httpClientSplitByDomain + + ", httpResourceRemoveTrailingSlash" + + httpResourceRemoveTrailingSlash + + ", dbClientSplitByInstance=" + + dbClientSplitByInstance + + ", dbClientSplitByInstanceTypeSuffix=" + + dbClientSplitByInstanceTypeSuffix + + ", dbClientSplitByHost=" + + dbClientSplitByHost + + ", DBMPropagationMode=" + + DBMPropagationMode + + ", splitByTags=" + + splitByTags + + ", scopeDepthLimit=" + + scopeDepthLimit + + ", scopeStrictMode=" + + scopeStrictMode + + ", scopeInheritAsyncPropagation=" + + scopeInheritAsyncPropagation + + ", scopeIterationKeepAlive=" + + scopeIterationKeepAlive + + ", partialFlushMinSpans=" + + partialFlushMinSpans + + ", traceStrictWritesEnabled=" + + traceStrictWritesEnabled + + ", tracePropagationStylesToExtract=" + + tracePropagationStylesToExtract + + ", tracePropagationStylesToInject=" + + tracePropagationStylesToInject + + ", tracePropagationExtractFirst=" + + tracePropagationExtractFirst + + ", clockSyncPeriod=" + + clockSyncPeriod + + ", jmxFetchEnabled=" + + jmxFetchEnabled + + ", dogStatsDStartDelay=" + + dogStatsDStartDelay + + ", jmxFetchConfigDir='" + + jmxFetchConfigDir + + '\'' + + ", jmxFetchConfigs=" + + jmxFetchConfigs + + ", jmxFetchMetricsConfigs=" + + jmxFetchMetricsConfigs + + ", jmxFetchCheckPeriod=" + + jmxFetchCheckPeriod + + ", jmxFetchInitialRefreshBeansPeriod=" + + jmxFetchInitialRefreshBeansPeriod + + ", jmxFetchRefreshBeansPeriod=" + + jmxFetchRefreshBeansPeriod + + ", jmxFetchStatsdHost='" + + jmxFetchStatsdHost + + '\'' + + ", jmxFetchStatsdPort=" + + jmxFetchStatsdPort + + ", jmxFetchMultipleRuntimeServicesEnabled=" + + jmxFetchMultipleRuntimeServicesEnabled + + ", jmxFetchMultipleRuntimeServicesLimit=" + + jmxFetchMultipleRuntimeServicesLimit + + ", healthMetricsEnabled=" + + healthMetricsEnabled + + ", healthMetricsStatsdHost='" + + healthMetricsStatsdHost + + '\'' + + ", healthMetricsStatsdPort=" + + healthMetricsStatsdPort + + ", perfMetricsEnabled=" + + perfMetricsEnabled + + ", tracerMetricsEnabled=" + + tracerMetricsEnabled + + ", tracerMetricsBufferingEnabled=" + + tracerMetricsBufferingEnabled + + ", tracerMetricsMaxAggregates=" + + tracerMetricsMaxAggregates + + ", tracerMetricsMaxPending=" + + tracerMetricsMaxPending + + ", reportHostName=" + + reportHostName + + ", traceAnalyticsEnabled=" + + traceAnalyticsEnabled + + ", traceSamplingServiceRules=" + + traceSamplingServiceRules + + ", traceSamplingOperationRules=" + + traceSamplingOperationRules + + ", traceSamplingJsonRules=" + + traceSamplingRules + + ", traceSampleRate=" + + traceSampleRate + + ", traceRateLimit=" + + traceRateLimit + + ", spanSamplingRules=" + + spanSamplingRules + + ", spanSamplingRulesFile=" + + spanSamplingRulesFile + + ", profilingAgentless=" + + profilingAgentless + + ", profilingUrl='" + + profilingUrl + + '\'' + + ", profilingTags=" + + profilingTags + + ", profilingStartDelay=" + + profilingStartDelay + + ", profilingStartForceFirst=" + + profilingStartForceFirst + + ", profilingUploadPeriod=" + + profilingUploadPeriod + + ", profilingTemplateOverrideFile='" + + profilingTemplateOverrideFile + + '\'' + + ", profilingUploadTimeout=" + + profilingUploadTimeout + + ", profilingUploadCompression='" + + profilingUploadCompression + + '\'' + + ", profilingProxyHost='" + + profilingProxyHost + + '\'' + + ", profilingProxyPort=" + + profilingProxyPort + + ", profilingProxyUsername='" + + profilingProxyUsername + + '\'' + + ", profilingProxyPassword=" + + (profilingProxyPassword == null ? "null" : "****") + + ", profilingExceptionSampleLimit=" + + profilingExceptionSampleLimit + + ", profilingExceptionHistogramTopItems=" + + profilingExceptionHistogramTopItems + + ", profilingExceptionHistogramMaxCollectionSize=" + + profilingExceptionHistogramMaxCollectionSize + + ", profilingExcludeAgentThreads=" + + profilingExcludeAgentThreads + + ", crashTrackingTags=" + + crashTrackingTags + + ", crashTrackingAgentless=" + + crashTrackingAgentless + + ", remoteConfigEnabled=" + + remoteConfigEnabled + + ", remoteConfigUrl=" + + remoteConfigUrl + + ", remoteConfigPollIntervalSeconds=" + + remoteConfigPollIntervalSeconds + + ", remoteConfigMaxPayloadSize=" + + remoteConfigMaxPayloadSize + + ", remoteConfigIntegrityCheckEnabled=" + + remoteConfigIntegrityCheckEnabled + + ", debuggerEnabled=" + + debuggerEnabled + + ", debuggerUploadTimeout=" + + debuggerUploadTimeout + + ", debuggerUploadFlushInterval=" + + debuggerUploadFlushInterval + + ", debuggerClassFileDumpEnabled=" + + debuggerClassFileDumpEnabled + + ", debuggerPollInterval=" + + debuggerPollInterval + + ", debuggerDiagnosticsInterval=" + + debuggerDiagnosticsInterval + + ", debuggerMetricEnabled=" + + debuggerMetricEnabled + + ", debuggerProbeFileLocation=" + + debuggerProbeFileLocation + + ", debuggerUploadBatchSize=" + + debuggerUploadBatchSize + + ", debuggerMaxPayloadSize=" + + debuggerMaxPayloadSize + + ", debuggerVerifyByteCode=" + + debuggerVerifyByteCode + + ", debuggerInstrumentTheWorld=" + + debuggerInstrumentTheWorld + + ", debuggerExcludeFile=" + + debuggerExcludeFiles + + ", awsPropagationEnabled=" + + awsPropagationEnabled + + ", sqsPropagationEnabled=" + + sqsPropagationEnabled + + ", kafkaClientPropagationEnabled=" + + kafkaClientPropagationEnabled + + ", kafkaClientPropagationDisabledTopics=" + + kafkaClientPropagationDisabledTopics + + ", kafkaClientBase64DecodingEnabled=" + + kafkaClientBase64DecodingEnabled + + ", jmsPropagationEnabled=" + + jmsPropagationEnabled + + ", jmsPropagationDisabledTopics=" + + jmsPropagationDisabledTopics + + ", jmsPropagationDisabledQueues=" + + jmsPropagationDisabledQueues + + ", rabbitPropagationEnabled=" + + rabbitPropagationEnabled + + ", rabbitPropagationDisabledQueues=" + + rabbitPropagationDisabledQueues + + ", rabbitPropagationDisabledExchanges=" + + rabbitPropagationDisabledExchanges + + ", messageBrokerSplitByDestination=" + + messageBrokerSplitByDestination + + ", hystrixTagsEnabled=" + + hystrixTagsEnabled + + ", hystrixMeasuredEnabled=" + + hystrixMeasuredEnabled + + ", igniteCacheIncludeKeys=" + + igniteCacheIncludeKeys + + ", servletPrincipalEnabled=" + + servletPrincipalEnabled + + ", servletAsyncTimeoutError=" + + servletAsyncTimeoutError + + ", datadogTagsLimit=" + + xDatadogTagsMaxLength + + ", traceAgentV05Enabled=" + + traceAgentV05Enabled + + ", debugEnabled=" + + debugEnabled + + ", triageEnabled=" + + triageEnabled + + ", startLogsEnabled=" + + startupLogsEnabled + + ", configFile='" + + configFileStatus + + '\'' + + ", idGenerationStrategy=" + + idGenerationStrategy + + ", trace128bitTraceIdGenerationEnabled=" + + trace128bitTraceIdGenerationEnabled + + ", grpcIgnoredInboundMethods=" + + grpcIgnoredInboundMethods + + ", grpcIgnoredOutboundMethods=" + + grpcIgnoredOutboundMethods + + ", grpcServerErrorStatuses=" + + grpcServerErrorStatuses + + ", grpcClientErrorStatuses=" + + grpcClientErrorStatuses + + ", clientIpEnabled=" + + clientIpEnabled + + ", appSecReportingInband=" + + appSecReportingInband + + ", appSecRulesFile='" + + appSecRulesFile + + "'" + + ", appSecHttpBlockedTemplateHtml=" + + appSecHttpBlockedTemplateHtml + + ", appSecWafTimeout=" + + appSecWafTimeout + + " us, appSecHttpBlockedTemplateJson=" + + appSecHttpBlockedTemplateJson + + ", apiSecurityEnabled=" + + apiSecurityEnabled + + ", apiSecurityRequestSampleRate=" + + apiSecurityRequestSampleRate + + ", cwsEnabled=" + + cwsEnabled + + ", cwsTlsRefresh=" + + cwsTlsRefresh + + ", longRunningTraceEnabled=" + + longRunningTraceEnabled + + ", longRunningTraceFlushInterval=" + + longRunningTraceFlushInterval + + ", elasticsearchBodyEnabled=" + + elasticsearchBodyEnabled + + ", elasticsearchParamsEnabled=" + + elasticsearchParamsEnabled + + ", elasticsearchBodyAndParamsEnabled=" + + elasticsearchBodyAndParamsEnabled + + ", traceFlushInterval=" + + traceFlushIntervalSeconds + + ", injectBaggageAsTagsEnabled=" + + injectBaggageAsTagsEnabled + + ", logsInjectionEnabled=" + + logsInjectionEnabled + + ", sparkTaskHistogramEnabled=" + + sparkTaskHistogramEnabled + + ", jaxRsExceptionAsErrorsEnabled=" + + jaxRsExceptionAsErrorsEnabled + + ", peerServiceDefaultsEnabled=" + + peerServiceDefaultsEnabled + + ", peerServiceComponentOverrides=" + + peerServiceComponentOverrides + + ", removeIntegrationServiceNamesEnabled=" + + removeIntegrationServiceNamesEnabled + + ", spanAttributeSchemaVersion=" + + spanAttributeSchemaVersion + + ", telemetryDebugRequestsEnabled=" + + telemetryDebugRequestsEnabled + + ", telemetryMetricsEnabled=" + + telemetryMetricsEnabled + + '}'; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigCollector.java b/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigCollector.java new file mode 100644 index 0000000000..c55f1f309b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigCollector.java @@ -0,0 +1,57 @@ +package datadog.trace.api; + +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +/** + * Collects system properties and environment variables set by the user and used by the tracer. Puts + * to this map will happen in Config and ConfigProvider classes, which can run concurrently with + * consumers. So this is based on a ConcurrentHashMap to deal with it. + */ +public class ConfigCollector { + private static final ConfigCollector INSTANCE = new ConfigCollector(); + + private static final AtomicReferenceFieldUpdater COLLECTED_UPDATER = + AtomicReferenceFieldUpdater.newUpdater(ConfigCollector.class, Map.class, "collected"); + + private volatile Map collected = new ConcurrentHashMap<>(); + + public static ConfigCollector get() { + return INSTANCE; + } + + public void put(String key, Object value, ConfigOrigin origin) { + ConfigSetting setting = new ConfigSetting(key, value, origin); + collected.put(key, setting); + } + + public void putAll(Map keysAndValues, ConfigOrigin origin) { + // attempt merge+replace to avoid collector seeing partial update + Map merged = + new ConcurrentHashMap<>(keysAndValues.size() + collected.size()); + for (Map.Entry entry : keysAndValues.entrySet()) { + ConfigSetting setting = new ConfigSetting(entry.getKey(), entry.getValue(), origin); + merged.put(entry.getKey(), setting); + } + while (true) { + Map current = collected; + current.forEach(merged::putIfAbsent); + if (COLLECTED_UPDATER.compareAndSet(this, current, merged)) { + break; // success + } + // roll back to original update before next attempt + merged.keySet().retainAll(keysAndValues.keySet()); + } + } + + @SuppressWarnings("unchecked") + public Map collect() { + if (!collected.isEmpty()) { + return COLLECTED_UPDATER.getAndSet(this, new ConcurrentHashMap<>()); + } else { + return Collections.emptyMap(); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigDefaults.java b/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigDefaults.java new file mode 100644 index 0000000000..aae9ba7607 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigDefaults.java @@ -0,0 +1,222 @@ +package datadog.trace.api; + +import static java.util.Arrays.asList; +import static datadog.trace.api.TracePropagationStyle.DATADOG; +import static datadog.trace.api.TracePropagationStyle.TRACECONTEXT; + +import java.util.BitSet; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +public final class ConfigDefaults { + + static final BitSet DEFAULT_HTTP_SERVER_ERROR_STATUSES; + static final BitSet DEFAULT_HTTP_CLIENT_ERROR_STATUSES; + static final BitSet DEFAULT_GRPC_SERVER_ERROR_STATUSES; + static final BitSet DEFAULT_GRPC_CLIENT_ERROR_STATUSES; + + static final BitSet DEFAULT_ATTRIBUTE_SCHEMA_VERSIONS; + + static { + DEFAULT_HTTP_SERVER_ERROR_STATUSES = new BitSet(); + DEFAULT_HTTP_SERVER_ERROR_STATUSES.set(500, 600); + DEFAULT_HTTP_CLIENT_ERROR_STATUSES = new BitSet(); + DEFAULT_HTTP_CLIENT_ERROR_STATUSES.set(400, 500); + DEFAULT_GRPC_SERVER_ERROR_STATUSES = new BitSet(); + DEFAULT_GRPC_SERVER_ERROR_STATUSES.set(2, 17); + DEFAULT_GRPC_CLIENT_ERROR_STATUSES = new BitSet(); + DEFAULT_GRPC_CLIENT_ERROR_STATUSES.set(1, 17); + DEFAULT_ATTRIBUTE_SCHEMA_VERSIONS = new BitSet(); + DEFAULT_ATTRIBUTE_SCHEMA_VERSIONS.set(0, 1); + } + + /* These fields are made public because they're referenced elsewhere internally. They're not intended as public API. */ + public static final String DEFAULT_AGENT_HOST = "localhost"; + public static final int DEFAULT_TRACE_AGENT_PORT = 8126; + public static final int DEFAULT_DOGSTATSD_PORT = 8125; + public static final String DEFAULT_TRACE_AGENT_SOCKET_PATH = "/var/run/datadog/apm.socket"; + public static final String DEFAULT_DOGSTATSD_SOCKET_PATH = "/var/run/datadog/dsd.socket"; + public static final int DEFAULT_AGENT_TIMEOUT = 10; // timeout in seconds + public static final String DEFAULT_SERVICE_NAME = "unnamed-java-app"; + public static final String DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME = "root-servlet"; + public static final String DEFAULT_AGENT_WRITER_TYPE = "DDAgentWriter"; + public static final boolean DEFAULT_STARTUP_LOGS_ENABLED = true; + + static final boolean DEFAULT_WRITER_BAGGAGE_INJECT = true; + static final String DEFAULT_SITE = "datadoghq.com"; + + static final boolean DEFAULT_TRACE_ENABLED = true; + static final boolean DEFAULT_TRACE_OTEL_ENABLED = false; + static final boolean DEFAULT_INTEGRATIONS_ENABLED = true; + + static final boolean DEFAULT_RUNTIME_CONTEXT_FIELD_INJECTION = true; + static final boolean DEFAULT_SERIALVERSIONUID_FIELD_INJECTION = true; + + static final boolean DEFAULT_PRIORITY_SAMPLING_ENABLED = true; + static final String DEFAULT_PRIORITY_SAMPLING_FORCE = null; + static final boolean DEFAULT_TRACE_RESOLVER_ENABLED = true; + static final boolean DEFAULT_HTTP_SERVER_TAG_QUERY_STRING = true; + static final boolean DEFAULT_HTTP_SERVER_ROUTE_BASED_NAMING = true; + static final boolean DEFAULT_HTTP_CLIENT_TAG_QUERY_STRING = false; + static final boolean DEFAULT_HTTP_CLIENT_SPLIT_BY_DOMAIN = false; + static final boolean DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE = false; + static final boolean DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX = false; + static final boolean DEFAULT_DB_CLIENT_HOST_SPLIT_BY_HOST = false; + static final String DEFAULT_DB_DBM_PROPAGATION_MODE_MODE = "disabled"; + static final int DEFAULT_SCOPE_DEPTH_LIMIT = 100; + static final int DEFAULT_SCOPE_ITERATION_KEEP_ALIVE = 30; // in seconds + static final int DEFAULT_PARTIAL_FLUSH_MIN_SPANS = 1000; + static final boolean DEFAULT_PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED = false; + static final Set DEFAULT_TRACE_PROPAGATION_STYLE = + new LinkedHashSet<>(asList(DATADOG, TRACECONTEXT)); + static final Set DEFAULT_PROPAGATION_STYLE = + new LinkedHashSet<>(asList(PropagationStyle.DATADOG)); + static final boolean DEFAULT_JMX_FETCH_ENABLED = true; + static final boolean DEFAULT_TRACE_AGENT_V05_ENABLED = false; + + static final boolean DEFAULT_CLIENT_IP_ENABLED = false; + + static final int DEFAULT_CLOCK_SYNC_PERIOD = 30; // seconds + + static final boolean DEFAULT_TRACE_PROPAGATION_EXTRACT_FIRST = false; + + static final boolean DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED = false; + static final int DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT = 10; + + static final int DEFAULT_DOGSTATSD_START_DELAY = 15; // seconds + + static final boolean DEFAULT_HEALTH_METRICS_ENABLED = true; + static final boolean DEFAULT_PERF_METRICS_ENABLED = false; + // No default constants for metrics statsd support -- falls back to jmxfetch values + + static final boolean DEFAULT_LOGS_INJECTION_ENABLED = true; + + static final String DEFAULT_APPSEC_ENABLED = "inactive"; + static final boolean DEFAULT_APPSEC_REPORTING_INBAND = false; + static final int DEFAULT_APPSEC_TRACE_RATE_LIMIT = 100; + static final boolean DEFAULT_APPSEC_WAF_METRICS = true; + static final int DEFAULT_APPSEC_WAF_TIMEOUT = 100000; // 0.1 s + static final boolean DEFAULT_API_SECURITY_ENABLED = false; + static final float DEFAULT_API_SECURITY_REQUEST_SAMPLE_RATE = 0.1f; // 10 % + + static final String DEFAULT_IAST_ENABLED = "false"; + static final boolean DEFAULT_IAST_DEBUG_ENABLED = false; + public static final int DEFAULT_IAST_MAX_CONCURRENT_REQUESTS = 4; + public static final int DEFAULT_IAST_VULNERABILITIES_PER_REQUEST = 2; + public static final int DEFAULT_IAST_REQUEST_SAMPLING = 33; + static final Set DEFAULT_IAST_WEAK_HASH_ALGORITHMS = + new HashSet<>(asList("SHA1", "SHA-1", "MD2", "MD5", "RIPEMD128", "MD4")); + static final String DEFAULT_IAST_WEAK_CIPHER_ALGORITHMS = + "^(?:PBEWITH(?:HMACSHA(?:2(?:24ANDAES_(?:128|256)|56ANDAES_(?:128|256))|384ANDAES_(?:128|256)|512ANDAES_(?:128|256)|1ANDAES_(?:128|256))|SHA1AND(?:RC(?:2_(?:128|40)|4_(?:128|40))|DESEDE)|MD5AND(?:TRIPLEDES|DES))|DES(?:EDE(?:WRAP)?)?|BLOWFISH|ARCFOUR|RC2).*$"; + static final boolean DEFAULT_IAST_REDACTION_ENABLED = true; + static final String DEFAULT_IAST_REDACTION_NAME_PATTERN = + "(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)"; + static final String DEFAULT_IAST_REDACTION_VALUE_PATTERN = + "(?:bearer\\s+[a-z0-9\\._\\-]+|glpat-[\\w\\-]{20}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\\w=\\-]+\\.ey[I-L][\\w=\\-]+(?:\\.[\\w.+/=\\-]+)?|(?:[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY[\\-]{5}|ssh-rsa\\s*[a-z0-9/\\.+]{100,}))"; + public static final int DEFAULT_IAST_MAX_RANGE_COUNT = 10; + static final boolean DEFAULT_IAST_STACKTRACE_LEAK_SUPPRESS = false; + + static final int DEFAULT_IAST_TRUNCATION_MAX_VALUE_LENGTH = 250; + public static final boolean DEFAULT_IAST_DEDUPLICATION_ENABLED = true; + + static final boolean DEFAULT_USM_ENABLED = false; + + static final boolean DEFAULT_CIVISIBILITY_ENABLED = false; + static final boolean DEFAULT_CIVISIBILITY_AGENTLESS_ENABLED = false; + static final boolean DEFAULT_CIVISIBILITY_SOURCE_DATA_ENABLED = true; + static final boolean DEFAULT_CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED = false; + static final boolean DEFAULT_CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED = true; + static final boolean DEFAULT_CIVISIBILITY_AUTO_CONFIGURATION_ENABLED = true; + static final boolean DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED = true; + static final String DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_VERSION = "0.1.8"; + static final String DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_VERSION = "0.8.11"; + static final String DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_EXCLUDES = + "datadog.trace.*:org.apache.commons.*:org.mockito.*"; + static final boolean DEFAULT_CIVISIBILITY_GIT_UPLOAD_ENABLED = true; + static final boolean DEFAULT_CIVISIBILITY_GIT_UNSHALLOW_ENABLED = true; + static final long DEFAULT_CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS = 30_000; + static final long DEFAULT_CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS = 30_000; + static final long DEFAULT_CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS = 60_000; + static final String DEFAULT_CIVISIBILITY_GIT_REMOTE_NAME = "origin"; + static final String DEFAULT_CIVISIBILITY_SIGNAL_SERVER_HOST = "127.0.0.1"; + static final int DEFAULT_CIVISIBILITY_SIGNAL_SERVER_PORT = 0; + static final List DEFAULT_CIVISIBILITY_RESOURCE_FOLDER_NAMES = + asList("/resources/", "/java/", "/groovy/", "/kotlin/", "/scala/"); + + static final boolean DEFAULT_REMOTE_CONFIG_ENABLED = true; + static final boolean DEFAULT_REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED = false; + static final int DEFAULT_REMOTE_CONFIG_MAX_PAYLOAD_SIZE = 5120; // KiB + static final int DEFAULT_REMOTE_CONFIG_POLL_INTERVAL_SECONDS = 5; + static final String DEFAULT_REMOTE_CONFIG_TARGETS_KEY_ID = + "5c4ece41241a1bb513f6e3e5df74ab7d5183dfffbd71bfd43127920d880569fd"; + static final String DEFAULT_REMOTE_CONFIG_TARGETS_KEY = + "e3f1f98c9da02a93bb547f448b472d727e14b22455235796fe49863856252508"; + + static final boolean DEFAULT_DEBUGGER_ENABLED = false; + static final int DEFAULT_DEBUGGER_UPLOAD_TIMEOUT = 30; // seconds + static final int DEFAULT_DEBUGGER_UPLOAD_FLUSH_INTERVAL = 0; // ms, 0 = dynamic + static final boolean DEFAULT_DEBUGGER_CLASSFILE_DUMP_ENABLED = false; + static final int DEFAULT_DEBUGGER_POLL_INTERVAL = 1; // seconds + static final int DEFAULT_DEBUGGER_DIAGNOSTICS_INTERVAL = 60 * 60; // seconds + static final boolean DEFAULT_DEBUGGER_METRICS_ENABLED = true; + static final int DEFAULT_DEBUGGER_UPLOAD_BATCH_SIZE = 100; + static final int DEFAULT_DEBUGGER_MAX_PAYLOAD_SIZE = 1024; // KiB + static final boolean DEFAULT_DEBUGGER_VERIFY_BYTECODE = true; + static final boolean DEFAULT_DEBUGGER_INSTRUMENT_THE_WORLD = false; + static final int DEFAULT_DEBUGGER_CAPTURE_TIMEOUT = 100; // milliseconds + static final boolean DEFAULT_DEBUGGER_SYMBOL_ENABLED = false; + static final boolean DEFAULT_DEBUGGER_SYMBOL_FORCE_UPLOAD = false; + static final int DEFAULT_DEBUGGER_SYMBOL_FLUSH_THRESHOLD = 100; // nb of classes + + static final boolean DEFAULT_TRACE_REPORT_HOSTNAME = false; + static final String DEFAULT_TRACE_ANNOTATIONS = null; + static final boolean DEFAULT_TRACE_ANNOTATION_ASYNC = false; + static final boolean DEFAULT_TRACE_EXECUTORS_ALL = false; + static final String DEFAULT_TRACE_METHODS = null; + static final String DEFAULT_MEASURE_METHODS = ""; + static final boolean DEFAULT_TRACE_ANALYTICS_ENABLED = false; + static final float DEFAULT_ANALYTICS_SAMPLE_RATE = 1.0f; + static final int DEFAULT_TRACE_RATE_LIMIT = 100; + + public static final boolean DEFAULT_ASYNC_PROPAGATING = true; + + static final boolean DEFAULT_CWS_ENABLED = false; + static final int DEFAULT_CWS_TLS_REFRESH = 5000; + + static final boolean DEFAULT_DATA_STREAMS_ENABLED = false; + static final int DEFAULT_DATA_STREAMS_BUCKET_DURATION = 10; // seconds + + static final int DEFAULT_RESOLVER_RESET_INTERVAL = 300; // seconds + + static final boolean DEFAULT_TELEMETRY_ENABLED = true; + static final int DEFAULT_TELEMETRY_HEARTBEAT_INTERVAL = 60; // in seconds + static final int DEFAULT_TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL = + 24 * 60 * 60; // 24 hours in seconds + static final int DEFAULT_TELEMETRY_METRICS_INTERVAL = 10; // in seconds + static final boolean DEFAULT_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED = true; + static final boolean DEFAULT_TELEMETRY_LOG_COLLECTION_ENABLED = false; + + static final boolean DEFAULT_TRACE_128_BIT_TRACEID_GENERATION_ENABLED = true; + static final boolean DEFAULT_TRACE_128_BIT_TRACEID_LOGGING_ENABLED = false; + static final boolean DEFAULT_SECURE_RANDOM = false; + + public static final int DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH = 512; + + static final boolean DEFAULT_TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH = false; + static final boolean DEFAULT_TRACE_LONG_RUNNING_ENABLED = false; + static final long DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL = 300; // seconds -> 5 minutes + + static final float DEFAULT_TRACE_FLUSH_INTERVAL = 1; + + static final boolean DEFAULT_ELASTICSEARCH_BODY_ENABLED = false; + static final boolean DEFAULT_ELASTICSEARCH_PARAMS_ENABLED = true; + static final boolean DEFAULT_ELASTICSEARCH_BODY_AND_PARAMS_ENABLED = false; + + static final boolean DEFAULT_SPARK_TASK_HISTOGRAM_ENABLED = true; + static final boolean DEFAULT_JAX_RS_EXCEPTION_AS_ERROR_ENABLED = true; + static final boolean DEFAULT_TELEMETRY_DEBUG_REQUESTS_ENABLED = false; + + private ConfigDefaults() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigOrigin.java b/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigOrigin.java new file mode 100644 index 0000000000..3f46985758 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigOrigin.java @@ -0,0 +1,18 @@ +package datadog.trace.api; + +public enum ConfigOrigin { + /** configurations that are set through environment variables */ + ENV("env_var"), + /** values that are set using remote config */ + REMOTE("remote_config"), + /** configurations that are set through JVM properties */ + JVM_PROP("jvm_prop"), + /** set when the user has not set any configuration for the key (defaults to a value) */ + DEFAULT("default"); + + public final String value; + + ConfigOrigin(String value) { + this.value = value; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigSetting.java b/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigSetting.java new file mode 100644 index 0000000000..ac4471fbae --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigSetting.java @@ -0,0 +1,52 @@ +package datadog.trace.api; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +public final class ConfigSetting { + public final String key; + public final Object value; + public final ConfigOrigin origin; + + private static final Set CONFIG_FILTER_LIST = + new HashSet<>( + Arrays.asList("DD_API_KEY", "dd.api-key", "dd.profiling.api-key", "dd.profiling.apikey")); + + private static Object filterConfigEntry(String key, Object value) { + return CONFIG_FILTER_LIST.contains(key) ? "" : value; + } + + public ConfigSetting(String key, Object value, ConfigOrigin origin) { + this.key = key; + this.value = filterConfigEntry(key, value); + this.origin = origin; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ConfigSetting that = (ConfigSetting) o; + return key.equals(that.key) && Objects.equals(value, that.value) && origin == that.origin; + } + + @Override + public int hashCode() { + return Objects.hash(key, value, origin); + } + + @Override + public String toString() { + return "ConfigSetting{" + + "key='" + + key + + '\'' + + ", value=" + + value + + ", origin=" + + origin + + '}'; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/CorrelationIdentifier.java b/features/dd-trace-core/src/main/java/datadog/trace/api/CorrelationIdentifier.java new file mode 100644 index 0000000000..2354406d47 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/CorrelationIdentifier.java @@ -0,0 +1,29 @@ +package datadog.trace.api; + +/** + * Utility class to access the active trace and span ids. + * + *

Intended for use with MDC frameworks. + */ +public class CorrelationIdentifier { + private static final String TRACE_ID_KEY = "dd.trace_id"; + private static final String SPAN_ID_KEY = "dd.span_id"; + + /** @return The trace-id key to use with datadog logs integration */ + public static String getTraceIdKey() { + return TRACE_ID_KEY; + } + + /** @return The span-id key to use with datadog logs integration */ + public static String getSpanIdKey() { + return SPAN_ID_KEY; + } + + public static String getTraceId() { + return GlobalTracer.get().getTraceId(); + } + + public static String getSpanId() { + return GlobalTracer.get().getSpanId(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DD128bTraceId.java b/features/dd-trace-core/src/main/java/datadog/trace/api/DD128bTraceId.java new file mode 100644 index 0000000000..5c36731a94 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/DD128bTraceId.java @@ -0,0 +1,178 @@ +package datadog.trace.api; + +import java.util.Locale; + +import datadog.trace.api.internal.util.LongStringUtils; + +/** + * Class encapsulating the unsigned 128-bit id used for TraceIds. + * + *

It contains parsing and formatting to string for both decimal and hexadecimal representations. + * The string representations are either kept from parsing, or generated on demand and cached. + * + *

{@link DD128bTraceId} can represent either a 128-bit TraceId or a 64-bit TraceId. For 128-bit + * TraceId, {@link #highOrderBits} contains a 32-bit timestamp store on the 32 higher bits and + * {@link #lowOrderBits} contains a unique and random 64-bit id. For 64-bit TraceId, {@link + * #highOrderBits} is set to 0 and {@link #lowOrderBits} contains a unique and random + * 63-bit id. + */ +public class DD128bTraceId extends DDTraceId { + public static final DD128bTraceId ZERO = + new DD128bTraceId(0, 0, "00000000000000000000000000000000"); + /** Represents the high-order 64 bits of the 128-bit trace id. */ + private final long highOrderBits; + /** Represents the low-order 64 bits of the 128-bit trace id. */ + private final long lowOrderBits; + /** + * The lower-case, zero-padded, 32 hexadecimal characters {@link String} representation of the + * {@link DDTraceId} instance. + */ + private String hexStr; + /** The 64-bit only decimal {@link String} representation of the {@link DDTraceId} instance. */ + private String str; + + private DD128bTraceId(long highOrderBits, long leastSigBits, String hexStr) { + this.highOrderBits = highOrderBits; + this.lowOrderBits = leastSigBits; + this.hexStr = hexStr; + } + + /** + * Create a new 128-bit {@link DD128bTraceId} from the given {@code long}s interpreted as high + * order and low order bits of the 128-bit id. + * + * @param highOrderBits A {@code long} representing the high-order bits of the {@link + * DD128bTraceId}. + * @param lowOrderBits A {@code long} representing the random id low-order bits. + * @return The created TraceId instance. + */ + public static DD128bTraceId from(long highOrderBits, long lowOrderBits) { + return new DD128bTraceId(highOrderBits, lowOrderBits, null); + } + + /** + * Create a new 128-bit {@link DD128bTraceId} from the given hexadecimal {@link String} + * representation. + * + * @param s The hexadecimal {@link String} representation to parse (a 32 lower-case hexadecimal + * characters maximum). + * @return The created TraceId instance. + * @throws NumberFormatException If the hexadecimal {@link String} representation is not valid. + */ + public static DD128bTraceId fromHex(String s) throws NumberFormatException { + return fromHex(s, 0, s == null ? 0 : s.length(), true); + } + + /** + * Create a new 128-bit {@link DD128bTraceId} from the given hexadecimal {@link String} + * representation. + * + * @param s The string containing the hexadecimal {@link String} representation to parse (32 lower + * or higher-case hexadecimal characters maximum). + * @param start The start index of the hexadecimal {@link String} representation to parse. + * @param length The length of the hexadecimal {@link String} representation to parse. + * @param lowerCaseOnly Whether the hexadecimal characters to parse are lower-case only or not. + * @return The created TraceId instance. + * @throws NumberFormatException If the hexadecimal {@link String} representation is not valid. + */ + public static DD128bTraceId fromHex(String s, int start, int length, boolean lowerCaseOnly) + throws NumberFormatException { + if (s == null) { + throw new NumberFormatException("s can't be null"); + } + int stringLength = s.length(); + if (start < 0 || length <= 0 || length > 32 || start + length > stringLength) { + throw new NumberFormatException("Illegal start or length"); + } + // Parse high and low order bits + long highOrderBits, lowOrderBits; + if (length > 16) { + int highOrderLength = length - 16; + highOrderBits = + LongStringUtils.parseUnsignedLongHex(s, start, highOrderLength, lowerCaseOnly); + lowOrderBits = + LongStringUtils.parseUnsignedLongHex(s, start + highOrderLength, 16, lowerCaseOnly); + } else { + highOrderBits = 0; + lowOrderBits = LongStringUtils.parseUnsignedLongHex(s, start, length, lowerCaseOnly); + } + // Extract hexadecimal string representation to cache + String hexStr = null; + if (length == 32) { + if (start == 0) { + hexStr = s; + } else { + hexStr = s.substring(start, start + 32); + } + if (!lowerCaseOnly) { + hexStr = hexStr.toLowerCase(Locale.ROOT); + } + } + return new DD128bTraceId(highOrderBits, lowOrderBits, hexStr); + } + + /** + * Returns the lower-case zero-padded 32 hexadecimal characters {@link String} representation of + * the {@link DD128bTraceId}. + * + * @return A lower-case zero-padded 32 hexadecimal characters {@link String} representation of the + * {@link DD128bTraceId} instance. + */ + @Override + public String toHexString() { + String hexString = this.hexStr; + // This race condition is intentional and benign. + // The worst that can happen is that an identical value is produced and written into the field. + if (hexString == null) { + this.hexStr = + hexString = LongStringUtils.toHexStringPadded(this.highOrderBits, this.lowOrderBits, 32); + } + return hexString; + } + + @Override + public String toHexStringPadded(int size) { + if (size <= 16) { + return LongStringUtils.toHexStringPadded(this.lowOrderBits, 16); + } + return toHexString(); + } + + @Override + public long toLong() { + return this.lowOrderBits; + } + + @Override + public long toHighOrderLong() { + return this.highOrderBits; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DD128bTraceId)) return false; + DD128bTraceId ddId = (DD128bTraceId) o; + return this.highOrderBits == ddId.highOrderBits && this.lowOrderBits == ddId.lowOrderBits; + } + + @Override + public int hashCode() { + return (int) + (this.highOrderBits + ^ (this.highOrderBits >>> 32) + ^ this.lowOrderBits + ^ (this.lowOrderBits >>> 32)); + } + + @Override + public String toString() { + String s = this.str; + // This race condition is intentional and benign. + // The worst that can happen is that an identical value is produced and written into the field. + if (s == null) { + this.str = s = Long.toUnsignedString(this.lowOrderBits); + } + return s; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DD64bTraceId.java b/features/dd-trace-core/src/main/java/datadog/trace/api/DD64bTraceId.java new file mode 100644 index 0000000000..f40b47a89d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/DD64bTraceId.java @@ -0,0 +1,126 @@ +package datadog.trace.api; + +import datadog.trace.api.internal.util.LongStringUtils; + +/** + * Class encapsulating the unsigned 64 bit id used for Traceids. + * + *

It contains generation of new ids, parsing, and to string for both decimal and hex + * representations. The decimal string representation is either kept from parsing, or generated on + * demand and cached. + */ +public class DD64bTraceId extends DDTraceId { + public static final DD64bTraceId MAX = + new DD64bTraceId(-1, "18446744073709551615"); // All bits set + + private final long id; + private String str; // cache for string representation + private String hexStr; // cache for hex string representation + + DD64bTraceId(long id, String str) { + this.id = id; + this.str = str; + } + + /** + * Create a new {@link DD64bTraceId} from the given {@code long} interpreted as the bits of the + * unsigned 64-bit id. This means that values larger than Long.MAX_VALUE will be represented as + * negative numbers. + * + * @param id The {@code long} representing the bits of the unsigned 64-bit id. + * @return A new {@link DD64bTraceId} instance. + */ + public static DD64bTraceId from(long id) { + return DD64bTraceId.create(id, null); + } + + /** + * Create a new {@code DDTraceId} from the given {@code String} representation of the unsigned 64 + * bit id. + * + * @param s String of unsigned 64 bit id + * @return DDTraceId + * @throws NumberFormatException + */ + public static DD64bTraceId from(String s) throws NumberFormatException { + return DD64bTraceId.create(LongStringUtils.parseUnsignedLong(s), s); + } + + /** + * Create a new {@code DDTraceId} from the given {@code String} hex representation of the unsigned + * 64 bit id. + * + * @param s String in hex of unsigned 64 bit id + * @return DDTraceId + * @throws NumberFormatException + */ + public static DD64bTraceId fromHex(String s) throws NumberFormatException { + return DD64bTraceId.create(LongStringUtils.parseUnsignedLongHex(s), null); + } + + static DD64bTraceId create(long id, String str) { + // ZERO constant is created and stored by the parent class as part of its API contract + // But initialized by this 64-bit child class. Ensures uniqueness of ZERO once created. + if (id == 0 && ZERO != null) { + return (DD64bTraceId) ZERO; + } else if (id == -1) { + return MAX; + } else { + return new DD64bTraceId(id, str); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DD64bTraceId)) return false; + DD64bTraceId ddId = (DD64bTraceId) o; + return this.id == ddId.id; + } + + @Override + public int hashCode() { + long id = this.id; + return (int) (id ^ (id >>> 32)); + } + + @Override + public String toString() { + String s = this.str; + // This race condition is intentional and benign. + // The worst that can happen is that an identical value is produced and written into the field. + if (s == null) { + this.str = s = Long.toUnsignedString(this.id); + } + return s; + } + + @Override + public String toHexString() { + String hexStr = this.hexStr; + // This race condition is intentional and benign. + // The worst that can happen is that an identical value is produced and written into the field. + if (hexStr == null) { + this.hexStr = hexStr = LongStringUtils.toHexStringPadded(this.id, 32); + } + return hexStr; + } + + @Override + public String toHexStringPadded(int size) { + if (size > 16) { + return toHexString(); + } + return LongStringUtils.toHexStringPadded(this.id, size); + } + + @Override + public long toLong() { + return this.id; + } + + @Override + public long toHighOrderLong() { + return 0; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanId.java b/features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanId.java new file mode 100644 index 0000000000..4925370f43 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanId.java @@ -0,0 +1,87 @@ +package datadog.trace.api; + +import datadog.trace.api.internal.util.LongStringUtils; + +/** Class with methods for working with the unsigned 64 bit id used for Span ids. */ +public final class DDSpanId { + + // Don't allow instances + private DDSpanId() {} + + /** The ZERO span id is not allowed and means no span. */ + public static final long ZERO = 0; + + // All bits set, only used from tests + public static final long MAX = -1; + + /** + * Parse the span id from the given {@code String} representation of the unsigned 64 bit id. + * + * @param s String of unsigned 64 bit id + * @return long + * @throws NumberFormatException + */ + public static long from(String s) throws NumberFormatException { + return LongStringUtils.parseUnsignedLong(s); + } + + /** + * Parse the span id from the given {@code String} hex representation of the unsigned 64 bit id. + * + * @param s String in hex of unsigned 64 bit id + * @return long + * @throws NumberFormatException + */ + public static long fromHex(String s) throws NumberFormatException { + return LongStringUtils.parseUnsignedLongHex(s); + } + + /** + * Parse the span id from the given {@code String} hex representation of the unsigned 64 bit id. + * + * @param s String in hex of unsigned 64 bit id + * @param start the start index of the hex value + * @param len the len of the hex value + * @param lowerCaseOnly if the allowed hex characters are lower case only + * @return long + * @throws NumberFormatException + */ + public static long fromHex(String s, int start, int len, boolean lowerCaseOnly) + throws NumberFormatException { + return LongStringUtils.parseUnsignedLongHex(s, start, len, lowerCaseOnly); + } + + /** + * Returns the decimal string representation of the unsigned 64 bit id. The {@code String} will + * NOT be cached. + * + * @param id the long 64 bit id to generate a String for + * @return decimal string + */ + public static String toString(long id) { + // TODO Cache here? https://github.com/DataDog/dd-trace-java/issues/4236 + return Long.toUnsignedString(id); + } + + /** + * Returns the no zero padded hex representation, in lower case, of the unsigned 64 bit id. The + * hex {@code String} will NOT be cached. + * + * @return non zero padded hex String + */ + public static String toHexString(long id) { + // TODO Cache here? https://github.com/DataDog/dd-trace-java/issues/4236 + return Long.toHexString(id); + } + + /** + * Returns the zero padded hex representation, in lower case, of the unsigned 64 bit id. The size + * will be rounded up to 16 characters. The hex {@code String} will NOT be cached. + * + * @return zero padded hex String + */ + public static String toHexStringPadded(long id) { + // TODO Cache here? https://github.com/DataDog/dd-trace-java/issues/4236 + return LongStringUtils.toHexStringPadded(id, 16); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanTypes.java b/features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanTypes.java new file mode 100644 index 0000000000..69366eb146 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanTypes.java @@ -0,0 +1,36 @@ +package datadog.trace.api; + +public class DDSpanTypes { + public static final String HTTP_CLIENT = "http"; + public static final String HTTP_SERVER = "web"; + @Deprecated public static final String WEB_SERVLET = HTTP_SERVER; + public static final String RPC = "rpc"; + public static final String CACHE = "cache"; + public static final String SOAP = "soap"; + + public static final String SQL = "sql"; + public static final String MONGO = "mongodb"; + public static final String CASSANDRA = "cassandra"; + public static final String COUCHBASE = "db"; // Using generic for now. + public static final String REDIS = "redis"; + public static final String MEMCACHED = "memcached"; + public static final String ELASTICSEARCH = "elasticsearch"; + public static final String OPENSEARCH = "opensearch"; + public static final String HIBERNATE = "hibernate"; + public static final String AEROSPIKE = "aerospike"; + public static final String DATANUCLEUS = "datanucleus"; + + public static final String MESSAGE_CLIENT = "queue"; + public static final String MESSAGE_CONSUMER = "queue"; + public static final String MESSAGE_PRODUCER = "queue"; + public static final String MESSAGE_BROKER = "queue"; + + public static final String GRAPHQL = "graphql"; + + public static final String TEST = "test"; + public static final String TEST_SUITE_END = "test_suite_end"; + public static final String TEST_MODULE_END = "test_module_end"; + public static final String TEST_SESSION_END = "test_session_end"; + + public static final String VULNERABILITY = "vulnerability"; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DDTags.java b/features/dd-trace-core/src/main/java/datadog/trace/api/DDTags.java new file mode 100644 index 0000000000..b53cab5ed3 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/DDTags.java @@ -0,0 +1,64 @@ +package datadog.trace.api; + +public class DDTags { + + public static final String SPAN_TYPE = "span.type"; + public static final String SERVICE_NAME = "service.name"; + public static final String RESOURCE_NAME = "resource.name"; + public static final String THREAD_NAME = "thread.name"; + public static final String THREAD_ID = "thread.id"; + public static final String DB_STATEMENT = "sql.query"; + public static final String PATHWAY_HASH = "pathway.hash"; + public static final String SCHEMA_DEFINITION = "schema.definition"; + public static final String SCHEMA_WEIGHT = "schema.weight"; + public static final String SCHEMA_TYPE = "schema.type"; + public static final String SCHEMA_ID = "schema.id"; + public static final String SCHEMA_TOPIC = "schema.topic"; + public static final String SCHEMA_OPERATION = "schema.operation"; + + public static final String HTTP_QUERY = "http.query.string"; + public static final String HTTP_FRAGMENT = "http.fragment.string"; + + public static final String USER_NAME = "user.principal"; + + public static final String ERROR_MSG = "error.message"; // string representing the error message + public static final String ERROR_TYPE = "error.type"; // string representing the type of the error + public static final String ERROR_STACK = "error.stack"; // human-readable version of the stack + + public static final String ANALYTICS_SAMPLE_RATE = "_dd1.sr.eausr"; + @Deprecated public static final String EVENT_SAMPLE_RATE = ANALYTICS_SAMPLE_RATE; + + /** Manually force tracer to keep the trace */ + public static final String MANUAL_KEEP = "manual.keep"; + /** Manually force tracer to drop the trace */ + public static final String MANUAL_DROP = "manual.drop"; + + public static final String TRACE_START_TIME = "t0"; + + /* Tags below are for internal use only. */ + static final String INTERNAL_HOST_NAME = "_dd.hostname"; + public static final String RUNTIME_ID_TAG = "runtime-id"; + public static final String RUNTIME_VERSION_TAG = "runtime_version"; + static final String SERVICE = "service"; + static final String SERVICE_TAG = SERVICE; + static final String HOST_TAG = "host"; + public static final String LANGUAGE_TAG_KEY = "language"; + public static final String LANGUAGE_TAG_VALUE = "jvm"; + public static final String ORIGIN_KEY = "_dd.origin"; + public static final String SPAN_LINKS = "_dd.span_links"; + public static final String LIBRARY_VERSION_TAG_KEY = "library_version"; + public static final String CI_ENV_VARS = "_dd.ci.env_vars"; + public static final String CI_ITR_TESTS_SKIPPED = "_dd.ci.itr.tests_skipped"; + public static final String MEASURED = "_dd.measured"; + public static final String PID_TAG = "process_id"; + public static final String SCHEMA_VERSION_TAG_KEY = "_dd.trace_span_attribute_schema"; + public static final String PEER_SERVICE_SOURCE = "_dd.peer.service.source"; + public static final String PEER_SERVICE_REMAPPED_FROM = "_dd.peer.service.remapped_from"; + public static final String INTERNAL_GIT_REPOSITORY_URL = "_dd.git.repository_url"; + public static final String INTERNAL_GIT_COMMIT_SHA = "_dd.git.commit.sha"; + + public static final String PROFILING_ENABLED = "_dd.profiling.enabled"; + + public static final String PROFILING_CONTEXT_ENGINE = "_dd.profiling.ctx"; + public static final String BASE_SERVICE = "_dd.base_service"; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceApiInfo.java b/features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceApiInfo.java new file mode 100644 index 0000000000..4713a4ecfb --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceApiInfo.java @@ -0,0 +1,27 @@ +package datadog.trace.api; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +public class DDTraceApiInfo { + public static final String VERSION; + + static { + String v; + try (final BufferedReader br = + new BufferedReader( + new InputStreamReader( + DDTraceApiInfo.class.getResourceAsStream("/dd-trace-api.version"), "UTF-8"))) { + final StringBuilder sb = new StringBuilder(); + + for (int c = br.read(); c != -1; c = br.read()) { + sb.append((char) c); + } + + v = sb.toString().trim(); + } catch (final Exception e) { + v = "unknown"; + } + VERSION = v; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceId.java b/features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceId.java new file mode 100644 index 0000000000..cc10e7493e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceId.java @@ -0,0 +1,104 @@ +package datadog.trace.api; + +import datadog.trace.api.internal.util.LongStringUtils; + +/** + * Class encapsulating the id used for TraceIds. + * + *

It contains parsing and formatting to string for both decimal and hexadecimal representations. + * The string representations are either kept from parsing, or generated on demand and cached. + */ +public abstract class DDTraceId { + /** Invalid TraceId value used to denote no TraceId. */ + public static final DDTraceId ZERO = from(0); + /** Convenience constant used from tests */ + public static final DDTraceId ONE = from(1); + + /** + * Creates a new {@link DD64bTraceId 64-bit TraceId} from the given {@code long} interpreted as + * the bits of the unsigned 64-bit id. This means that values larger than {@link Long#MAX_VALUE} + * will be represented as negative numbers. + * + * @param id The {@code long} representing the bits of the unsigned 64-bit id. + * @return A new {@link DDTraceId} instance. + */ + public static DDTraceId from(long id) { + return DD64bTraceId.from(id); + } + + /** + * Creates a new {@link DD64bTraceId 64-bit TraceId} from the given {@link #toString() String + * representation}. + * + * @param s The {@link #toString() String representation} of a {@link DDTraceId}. + * @return A new {@link DDTraceId} instance. + * @throws NumberFormatException If the given {@link String} does not represent a valid number. + */ + public static DDTraceId from(String s) throws NumberFormatException { + return DD64bTraceId.create(LongStringUtils.parseUnsignedLong(s), s); + } + + /** + * Creates a new {@link DDTraceId} from the given {@link #toHexString() hexadecimal + * representation}. + * + * @param s The hexadecimal {@link String} representation of a {@link DD128bTraceId} to parse. + * @return A new {@link DDTraceId} instance. + * @throws NumberFormatException If the given {@link #toHexString() hexadecimal String} does not + * represent a valid number. + */ + public static DDTraceId fromHex(String s) throws NumberFormatException { + if (s == null) { + throw new NumberFormatException("s cannot be null"); + } + return s.length() > 16 ? DD128bTraceId.fromHex(s) : DD64bTraceId.fromHex(s); + } + + /** + * Returns a 64-bit only decimal {@link String} representation of the {@link DDTraceId}. The + * {@link String} will be cached. + * + * @return A cached 64-bit only decimal {@link String} representation of the {@link DDTraceId} + * instance. + */ + @Override + public abstract String toString(); + + /** + * Returns the lower-case zero-padded 32 hexadecimal characters {@link String} representation of + * the {@link DDTraceId}. The * {@link String} will be cached. + * + * @return A cached lower-case zero-padded 32 hexadecimal characters {@link String} representation + * of the {@link DDTraceId} instance. + */ + public abstract String toHexString(); + + /** + * Returns the lower-case zero-padded {@link #toHexString() hexadecimal String} representation of + * the {@link DDTraceId}. The size will be rounded up to 16 or 32 + * characters. This hexadecimal {@link String} will not be cached. + * + * @param size The size in characters of the zero-padded {@link String} (rounded up to 16 + * or 32). + * @return A lower-case zero-padded {@link #toHexString() String representation} representation of + * the {@link DDTraceId} instance. + */ + public abstract String toHexStringPadded(int size); + + /** + * Returns the low-order 64 bits of the {@link DDTraceId} as an unsigned {@code long}. This means + * that values larger than {@link Long#MAX_VALUE} will be represented as negative numbers. + * + * @return The low-order 64 bits of the {@link DDTraceId} as an unsigned {@code long}. + */ + public abstract long toLong(); + + /** + * Returns the high-order 64 bits of 128-bit {@link DDTraceId} as un unsigned {@code long}. This + * means that values larger than {@link Long#MAX_VALUE} will be represented as negative numbers. + * + * @return The high-order 64 bits of the 128-bit {@link DDTraceId} as an unsigned {@code long}, + * 0 for 64-bit {@link DDTraceId} only. + */ + public abstract long toHighOrderLong(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DisableTestTrace.java b/features/dd-trace-core/src/main/java/datadog/trace/api/DisableTestTrace.java new file mode 100644 index 0000000000..6e472573c9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/DisableTestTrace.java @@ -0,0 +1,21 @@ +package datadog.trace.api; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Set this annotation to a test method so the dd-java-agent does not consider it for tracing. This + * annotation must be only used in test framework instrumentation tests to avoid self-tracing of the + * test itself. + */ +@Retention(RUNTIME) +@Target({TYPE, METHOD}) +public @interface DisableTestTrace { + + /** The reason of why test trace has been disable for that test. */ + String reason() default ""; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DynamicConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/DynamicConfig.java new file mode 100644 index 0000000000..35690fc56c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/DynamicConfig.java @@ -0,0 +1,393 @@ +package datadog.trace.api; + +import static datadog.trace.api.config.GeneralConfig.DATA_STREAMS_ENABLED; +import static datadog.trace.api.config.GeneralConfig.RUNTIME_METRICS_ENABLED; +import static datadog.trace.api.config.GeneralConfig.TRACE_DEBUG; +import static datadog.trace.api.config.TraceInstrumentationConfig.LOGS_INJECTION_ENABLED; +import static datadog.trace.api.config.TracerConfig.BAGGAGE_MAPPING; +import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS; +import static datadog.trace.api.config.TracerConfig.RESPONSE_HEADER_TAGS; +import static datadog.trace.api.config.TracerConfig.SERVICE_MAPPING; +import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLE_RATE; +import static datadog.trace.util.CollectionUtils.tryMakeImmutableMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.function.Function; + +import datadog.trace.api.sampling.SamplingRule.SpanSamplingRule; +import datadog.trace.api.sampling.SamplingRule.TraceSamplingRule; +import datadog.trace.util.Strings; + +/** + * Config that can be dynamically updated via remote-config + * + *

Only a small subset of config is currently supported + * + *

Not every config should be dynamic because there are performance implications + * + * @see InstrumenterConfig for pre-instrumentation configurations + * @see Config for other configurations + */ +public final class DynamicConfig { + static final Logger rootLogger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); + + static final Function, String> KEY = DynamicConfig::key; + static final Function, String> VALUE = DynamicConfig::value; + static final Function, String> LOWER_KEY = DynamicConfig::lowerKey; + static final Function, String> REQUEST_TAG = DynamicConfig::requestTag; + static final Function, String> RESPONSE_TAG = + DynamicConfig::responseTag; + + BiFunction snapshotFactory; + + S initialSnapshot; + volatile S currentSnapshot; + + private DynamicConfig(BiFunction snapshotFactory) { + this.snapshotFactory = snapshotFactory; + } + + /** Dynamic configuration that uses the default snapshot type. */ + public static DynamicConfig.Builder create() { + return new DynamicConfig<>(Snapshot::new).new Builder(); + } + + /** Dynamic configuration that wants to add its own state to the snapshot. */ + public static DynamicConfig.Builder create( + BiFunction.Builder, S, S> snapshotFactory) { + return new DynamicConfig(snapshotFactory).new Builder(); + } + + /** Captures a snapshot of the configuration at the start of a trace. */ + public S captureTraceConfig() { + return currentSnapshot; + } + + /** Start building a new configuration based on its initial state. */ + public Builder initial() { + return new Builder(initialSnapshot); + } + + /** Start building a new configuration based on its current state. */ + public Builder current() { + return new Builder(currentSnapshot); + } + + /** Reset the configuration to its initial state. */ + public void resetTraceConfig() { + currentSnapshot = initialSnapshot; + reportConfigChange(initialSnapshot); + } + + @Override + public String toString() { + return currentSnapshot.toString(); + } + + public final class Builder { + + boolean runtimeMetricsEnabled; + boolean logsInjectionEnabled; + boolean dataStreamsEnabled; + + Map serviceMapping; + Map requestHeaderTags; + Map responseHeaderTags; + Map baggageMapping; + + List spanSamplingRules; + List traceSamplingRules; + + Double traceSampleRate; + + Builder() {} + + Builder(Snapshot snapshot) { + + this.runtimeMetricsEnabled = snapshot.runtimeMetricsEnabled; + this.logsInjectionEnabled = snapshot.logsInjectionEnabled; + this.dataStreamsEnabled = snapshot.dataStreamsEnabled; + + this.serviceMapping = snapshot.serviceMapping; + this.requestHeaderTags = snapshot.requestHeaderTags; + this.responseHeaderTags = snapshot.responseHeaderTags; + this.baggageMapping = snapshot.baggageMapping; + + this.traceSampleRate = snapshot.traceSampleRate; + } + + public Builder setRuntimeMetricsEnabled(boolean runtimeMetricsEnabled) { + this.runtimeMetricsEnabled = runtimeMetricsEnabled; + return this; + } + + public Builder setLogsInjectionEnabled(boolean logsInjectionEnabled) { + this.logsInjectionEnabled = logsInjectionEnabled; + return this; + } + + public Builder setDataStreamsEnabled(boolean dataStreamsEnabled) { + this.dataStreamsEnabled = dataStreamsEnabled; + return this; + } + + public Builder setServiceMapping(Map serviceMapping) { + return setServiceMapping(serviceMapping.entrySet()); + } + + @SuppressWarnings("deprecation") + public Builder setHeaderTags(Map headerTags) { + if (Config.get().getRequestHeaderTags().equals(headerTags) + && !Config.get().getResponseHeaderTags().equals(headerTags)) { + // using static config; don't override separate static config for response header tags + this.requestHeaderTags = Config.get().getRequestHeaderTags(); + this.responseHeaderTags = Config.get().getResponseHeaderTags(); + return this; + } else { + return setHeaderTags(headerTags.entrySet()); + } + } + + public Builder setBaggageMapping(Map baggageMapping) { + return setBaggageMapping(baggageMapping.entrySet()); + } + + public Builder setServiceMapping( + Collection> serviceMapping) { + this.serviceMapping = cleanMapping(serviceMapping, KEY, VALUE); + return this; + } + + public Builder setHeaderTags(Collection> headerTags) { + this.requestHeaderTags = cleanMapping(headerTags, LOWER_KEY, REQUEST_TAG); + this.responseHeaderTags = cleanMapping(headerTags, LOWER_KEY, RESPONSE_TAG); + return this; + } + + public Builder setBaggageMapping( + Collection> baggageMapping) { + this.baggageMapping = cleanMapping(baggageMapping, LOWER_KEY, VALUE); + return this; + } + + public Builder setTraceSampleRate(Double traceSampleRate) { + this.traceSampleRate = traceSampleRate; + return this; + } + + public Builder setSpanSamplingRules(List spanSamplingRules) { + this.spanSamplingRules = spanSamplingRules; + return this; + } + + public Builder setTraceSamplingRules(List traceSamplingRules) { + this.traceSamplingRules = traceSamplingRules; + return this; + } + + /** Overwrites the current configuration with a new snapshot. */ + public DynamicConfig apply() { + S oldSnapshot = currentSnapshot; + S newSnapshot = snapshotFactory.apply(this, oldSnapshot); + if (null == oldSnapshot) { + initialSnapshot = newSnapshot; // captured when constructing the dynamic config + currentSnapshot = newSnapshot; + } else { + currentSnapshot = newSnapshot; + reportConfigChange(newSnapshot); + } + return DynamicConfig.this; + } + } + + static Map cleanMapping( + Collection> mapping, + Function, String> keyMapper, + Function, String> valueMapper) { + final Map cleanedMapping = new HashMap<>(mapping.size() * 4 / 3); + for (Map.Entry association : mapping) { + cleanedMapping.put(keyMapper.apply(association), valueMapper.apply(association)); + } + return tryMakeImmutableMap(cleanedMapping); + } + + static String key(Map.Entry association) { + return Strings.trim(association.getKey()); + } + + static String value(Map.Entry association) { + return Strings.trim(association.getValue()); + } + + static String lowerKey(Map.Entry association) { + return key(association).toLowerCase(Locale.ROOT); + } + + static String requestTag(Map.Entry association) { + String requestTag = value(association); + if (requestTag.isEmpty()) { + // normalization is only applied when generating default tag names; see ConfigConverter + requestTag = "http.request.headers." + Strings.normalizedHeaderTag(association.getKey()); + } + return requestTag; + } + + static String responseTag(Map.Entry association) { + String responseTag = value(association); + if (responseTag.isEmpty()) { + // normalization is only applied when generating default tag names; see ConfigConverter + responseTag = "http.response.headers." + Strings.normalizedHeaderTag(association.getKey()); + } + return responseTag; + } + + static void reportConfigChange(Snapshot newSnapshot) { + Map update = new HashMap<>(); + + update.put(TRACE_DEBUG, rootLogger.isDebugEnabled()); + update.put(RUNTIME_METRICS_ENABLED, newSnapshot.runtimeMetricsEnabled); + update.put(LOGS_INJECTION_ENABLED, newSnapshot.logsInjectionEnabled); + update.put(DATA_STREAMS_ENABLED, newSnapshot.dataStreamsEnabled); + + update.put(SERVICE_MAPPING, newSnapshot.serviceMapping); + update.put(REQUEST_HEADER_TAGS, newSnapshot.requestHeaderTags); + update.put(RESPONSE_HEADER_TAGS, newSnapshot.responseHeaderTags); + update.put(BAGGAGE_MAPPING, newSnapshot.baggageMapping); + + maybePut(update, TRACE_SAMPLE_RATE, newSnapshot.traceSampleRate); + + ConfigCollector.get().putAll(update, ConfigOrigin.REMOTE); + } + + @SuppressWarnings("SameParameterValue") + private static void maybePut(Map update, String key, Object value) { + if (null != value) { + update.put(key, value); + } + } + + /** Immutable snapshot of the configuration. */ + public static class Snapshot implements TraceConfig { + final boolean runtimeMetricsEnabled; + final boolean logsInjectionEnabled; + final boolean dataStreamsEnabled; + + final Map serviceMapping; + final Map requestHeaderTags; + final Map responseHeaderTags; + final Map baggageMapping; + + final List spanSamplingRules; + final List traceSamplingRules; + + final Double traceSampleRate; + + protected Snapshot(DynamicConfig.Builder builder, Snapshot oldSnapshot) { + + this.runtimeMetricsEnabled = builder.runtimeMetricsEnabled; + this.logsInjectionEnabled = builder.logsInjectionEnabled; + this.dataStreamsEnabled = builder.dataStreamsEnabled; + + this.serviceMapping = nullToEmpty(builder.serviceMapping); + this.requestHeaderTags = nullToEmpty(builder.requestHeaderTags); + this.responseHeaderTags = nullToEmpty(builder.responseHeaderTags); + this.baggageMapping = nullToEmpty(builder.baggageMapping); + + this.traceSampleRate = builder.traceSampleRate; + + this.spanSamplingRules = builder.spanSamplingRules; + this.traceSamplingRules = builder.traceSamplingRules; + } + + private static Map nullToEmpty(Map mapping) { + return null != mapping ? mapping : Collections.emptyMap(); + } + + @Override + public boolean isRuntimeMetricsEnabled() { + return runtimeMetricsEnabled; + } + + @Override + public boolean isLogsInjectionEnabled() { + return logsInjectionEnabled; + } + + @Override + public boolean isDataStreamsEnabled() { + return dataStreamsEnabled; + } + + @Override + public Map getServiceMapping() { + return serviceMapping; + } + + @Override + public Map getRequestHeaderTags() { + return requestHeaderTags; + } + + @Override + public Map getResponseHeaderTags() { + return responseHeaderTags; + } + + @Override + public Map getBaggageMapping() { + return baggageMapping; + } + + @Override + public Double getTraceSampleRate() { + return traceSampleRate; + } + + @Override + public List getSpanSamplingRules() { + return spanSamplingRules; + } + + @Override + public List getTraceSamplingRules() { + return traceSamplingRules; + } + + @Override + public String toString() { + return "DynamicConfig{" + + "debugEnabled=" + + rootLogger.isDebugEnabled() + + ", runtimeMetricsEnabled=" + + runtimeMetricsEnabled + + ", logsInjectionEnabled=" + + logsInjectionEnabled + + ", dataStreamsEnabled=" + + dataStreamsEnabled + + ", serviceMapping=" + + serviceMapping + + ", requestHeaderTags=" + + requestHeaderTags + + ", responseHeaderTags=" + + responseHeaderTags + + ", baggageMapping=" + + baggageMapping + + ", spanSamplingRules=" + + spanSamplingRules + + ", traceSamplingRules=" + + traceSamplingRules + + ", traceSampleRate=" + + traceSampleRate + + '}'; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointer.java new file mode 100644 index 0000000000..1dd127f398 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointer.java @@ -0,0 +1,21 @@ +package datadog.trace.api; + +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; + +public interface EndpointCheckpointer { + /** + * Callback to be called when a root span is written (together with the trace) + * + * @param rootSpan the local root span of the trace + * @param tracker the endpoint tracker + */ + void onRootSpanFinished(AgentSpan rootSpan, EndpointTracker tracker); + + /** + * Callback to be called when a root span is started + * + * @param rootSpan the local root span of the trace + * @return an endpoint tracker + */ + EndpointTracker onRootSpanStarted(AgentSpan rootSpan); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointerHolder.java b/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointerHolder.java new file mode 100644 index 0000000000..260a04b6c6 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointerHolder.java @@ -0,0 +1,67 @@ +package datadog.trace.api; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; + +public final class EndpointCheckpointerHolder implements EndpointCheckpointer { + + /** + * Creates a new, pre-configured instance bound to {@linkplain NoOpCheckpointer#NO_OP}.
+ * A different {@linkplain EndpointCheckpointer} implementation can be set via {@linkplain + * EndpointCheckpointerHolder#register(EndpointCheckpointer)}. + * + * @return a new, pre-configured instance + */ + public static EndpointCheckpointerHolder create() { + return new EndpointCheckpointerHolder(NoOpCheckpointer.NO_OP); + } + + private static final Logger log = LoggerFactory.getLogger(EndpointCheckpointerHolder.class); + private static final AtomicReferenceFieldUpdater + ROOT_SPAN_CHECKPOINTER = + AtomicReferenceFieldUpdater.newUpdater( + EndpointCheckpointerHolder.class, EndpointCheckpointer.class, "endpointCheckpointer"); + private volatile EndpointCheckpointer endpointCheckpointer; + + public EndpointCheckpointerHolder(EndpointCheckpointer endpointCheckpointer) { + this.endpointCheckpointer = endpointCheckpointer; + } + + public void register(EndpointCheckpointer endpointCheckpointer) { + if (!ROOT_SPAN_CHECKPOINTER.compareAndSet(this, NoOpCheckpointer.NO_OP, endpointCheckpointer)) { + log.debug( + "failed to register root span checkpointer {} - {} already registered", + endpointCheckpointer.getClass(), + this.endpointCheckpointer.getClass()); + } else { + log.debug("Registered root span checkpointer implementation: {}", endpointCheckpointer); + } + } + + @Override + public void onRootSpanFinished(AgentSpan rootSpan, EndpointTracker tracker) { + endpointCheckpointer.onRootSpanFinished(rootSpan, tracker); + } + + @Override + public EndpointTracker onRootSpanStarted(AgentSpan root) { + return endpointCheckpointer.onRootSpanStarted(root); + } + + private static final class NoOpCheckpointer implements EndpointCheckpointer { + + static final NoOpCheckpointer NO_OP = new NoOpCheckpointer(); + + @Override + public void onRootSpanFinished(AgentSpan rootSpan, EndpointTracker tracker) {} + + @Override + public EndpointTracker onRootSpanStarted(AgentSpan rootSpan) { + return null; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointTracker.java b/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointTracker.java new file mode 100644 index 0000000000..1f1eec82e3 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointTracker.java @@ -0,0 +1,16 @@ +package datadog.trace.api; + +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; + +/** A simple listener-like interface for tracking the end-point writes */ +public interface EndpointTracker { + + EndpointTracker NO_OP = span -> {}; + + /** + * Called when a local root span (associated with an end-point) is written + * + * @param span the local root span + */ + void endpointWritten(AgentSpan span); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/EventTracker.java b/features/dd-trace-core/src/main/java/datadog/trace/api/EventTracker.java new file mode 100644 index 0000000000..f053426a1b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/EventTracker.java @@ -0,0 +1,113 @@ +package datadog.trace.api; + +import java.util.Map; + +import datadog.trace.api.internal.InternalTracer; +import datadog.trace.api.internal.TraceSegment; + +public class EventTracker { + + public static final EventTracker NO_EVENT_TRACKER = new EventTracker(null); + private final InternalTracer tracer; + + EventTracker(InternalTracer tracer) { + this.tracer = tracer; + } + + /** + * Method for tracking successful login event. A user login event is made of a user id, and an + * optional key-value map of metadata of string types only. + * + * @param userId user id used for login + * @param metadata custom metadata data represented as key/value map + */ + public void trackLoginSuccessEvent(String userId, Map metadata) { + if (userId == null || userId.isEmpty()) { + throw new IllegalArgumentException("UserId is null or empty"); + } + + TraceSegment segment = getTraceSegment(); + if (segment == null) { + return; + } + + segment.setTagTop("_dd.appsec.events.users.login.success.sdk", true); + segment.setTagTop("appsec.events.users.login.success.track", true); + segment.setTagTop("usr.id", userId); + segment.setTagTop(DDTags.MANUAL_KEEP, true); + + if (metadata != null && !metadata.isEmpty()) { + segment.setTagTop("appsec.events.users.login.success", metadata); + } + } + + /** + * Method for tracking login failure event. A user login event is made of a user id, along user id + * existing flag and an optional key-value map of metadata of string types only. + * + * @param userId user id used for login + * @param exists flag indicates if provided userId exists + * @param metadata custom metadata data represented as key/value map + */ + public void trackLoginFailureEvent(String userId, boolean exists, Map metadata) { + if (userId == null || userId.isEmpty()) { + throw new IllegalArgumentException("UserId is null or empty"); + } + + if (tracer == null) { + return; + } + + TraceSegment segment = getTraceSegment(); + if (segment == null) { + return; + } + + segment.setTagTop("_dd.appsec.events.users.login.failure.sdk", true); + segment.setTagTop("appsec.events.users.login.failure.track", true); + segment.setTagTop("appsec.events.users.login.failure.usr.id", userId); + segment.setTagTop("appsec.events.users.login.failure.usr.exists", exists); + segment.setTagTop(DDTags.MANUAL_KEEP, true); + + if (metadata != null && !metadata.isEmpty()) { + segment.setTagTop("appsec.events.users.login.failure", metadata); + } + } + + /** + * Method for tracking custom events. A custom event is made of an event name along with an + * optional key-value map of metadata of string types only + * + * @param eventName name of the custom event + * @param metadata custom metadata data represented as key/value map + */ + public void trackCustomEvent(String eventName, Map metadata) { + if (eventName == null || eventName.isEmpty()) { + throw new IllegalArgumentException("EventName is null or empty"); + } + + if (tracer == null) { + return; + } + + TraceSegment segment = getTraceSegment(); + if (segment == null) { + return; + } + + segment.setTagTop("_dd.appsec.events." + eventName + ".sdk", true); + segment.setTagTop("appsec.events." + eventName + ".track", true, true); + segment.setTagTop(DDTags.MANUAL_KEEP, true); + + if (metadata != null && !metadata.isEmpty()) { + segment.setTagTop("appsec.events." + eventName, metadata, true); + } + } + + private TraceSegment getTraceSegment() { + if (tracer == null) { + return null; + } + return tracer.getTraceSegment(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Functions.java b/features/dd-trace-core/src/main/java/datadog/trace/api/Functions.java new file mode 100644 index 0000000000..24441c9d7e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/Functions.java @@ -0,0 +1,145 @@ +package datadog.trace.api; + +import static java.util.function.Function.identity; + +import java.util.Locale; +import java.util.function.BiFunction; +import java.util.function.Function; + +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; + +public final class Functions { + + private Functions() {} + + public abstract static class Concatenate { + + public CharSequence concatenate(CharSequence left, CharSequence right) { + return UTF8BytesString.create(String.valueOf(left) + right); + } + } + + public static final class Suffix extends Concatenate + implements Function { + private final CharSequence suffix; + private final Function transformer; + + public Suffix(CharSequence suffix, Function transformer) { + this.suffix = suffix; + this.transformer = transformer; + } + + public Suffix(String suffix) { + this(suffix, identity()); + } + + @Override + public CharSequence apply(CharSequence key) { + return concatenate(transformer.apply(key), suffix); + } + } + + public static final class Prefix extends Concatenate + implements Function { + private final CharSequence prefix; + private final Function transformer; + + public Prefix(CharSequence prefix, Function transformer) { + this.prefix = prefix; + this.transformer = transformer; + } + + public Prefix(CharSequence prefix) { + this(prefix, identity()); + } + + @Override + public CharSequence apply(CharSequence key) { + return concatenate(prefix, transformer.apply(key)); + } + } + + public abstract static class Join + implements BiFunction { + protected final CharSequence joiner; + protected final Function transformer; + + protected Join(CharSequence joiner, Function transformer) { + this.joiner = joiner; + this.transformer = transformer; + } + + @Override + public CharSequence apply(CharSequence left, CharSequence right) { + return UTF8BytesString.create(String.valueOf(left) + joiner + right); + } + + public abstract Function curry(CharSequence specialisation); + } + + public static class PrefixJoin extends Join { + + public PrefixJoin(CharSequence joiner, Function transformer) { + super(joiner, transformer); + } + + @Override + public Function curry(CharSequence specialisation) { + return new Prefix(String.valueOf(specialisation) + joiner, transformer); + } + + public static PrefixJoin of( + CharSequence joiner, Function transformer) { + return new PrefixJoin(joiner, transformer); + } + + public static PrefixJoin of(String joiner) { + return of(joiner, identity()); + } + + public static final PrefixJoin ZERO = of(""); + } + + public static class SuffixJoin extends Join { + + public SuffixJoin(CharSequence joiner, Function transformer) { + super(joiner, transformer); + } + + @Override + public Function curry(CharSequence specialisation) { + return new Suffix(String.valueOf(joiner) + specialisation, transformer); + } + + public static SuffixJoin of( + CharSequence joiner, Function transformer) { + return new SuffixJoin(joiner, transformer); + } + + public static SuffixJoin of(CharSequence joiner) { + return of(joiner, identity()); + } + + public static final SuffixJoin ZERO = of(""); + } + + public static final Function UTF8_ENCODE = UTF8BytesString::create; + + public static final class LowerCase implements Function { + + public static final LowerCase INSTANCE = new LowerCase(); + + @Override + public String apply(String key) { + return key.toLowerCase(Locale.ROOT); + } + } + + public static final class ToString implements Function { + + @Override + public String apply(T key) { + return key.toString(); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/GlobalTracer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/GlobalTracer.java new file mode 100644 index 0000000000..610fa1fef0 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/GlobalTracer.java @@ -0,0 +1,95 @@ +package datadog.trace.api; + +import java.util.ArrayList; +import java.util.Collection; + +import datadog.trace.api.interceptor.TraceInterceptor; +import datadog.trace.api.internal.InternalTracer; + +/** + * A global reference to the registered Datadog tracer. + * + *

OpenTracing's GlobalTracer cannot be cast to its DDTracer implementation, so this class exists + * to provide a global window to datadog-specific features. + */ +public class GlobalTracer { + private static final Tracer NO_OP = + new Tracer() { + @Override + public String getTraceId() { + return "0"; + } + + @Override + public String getSpanId() { + return "0"; + } + + @Override + public boolean addTraceInterceptor(TraceInterceptor traceInterceptor) { + return false; + } + }; + + private static final Collection installationCallbacks = new ArrayList<>(); + private static Tracer provider = NO_OP; + private static EventTracker eventTracker = EventTracker.NO_EVENT_TRACKER; + + public static void registerIfAbsent(Tracer p) { + if (p == null || p == NO_OP) { + throw new IllegalArgumentException(); + } + + synchronized (installationCallbacks) { + if (provider == NO_OP) { + provider = p; + for (Callback callback : installationCallbacks) { + callback.installed(p); + } + } + } + } + + public static void forceRegister(Tracer tracer) { + if (tracer == null || tracer == NO_OP) { + throw new IllegalArgumentException(); + } + + synchronized (installationCallbacks) { + provider = tracer; + for (Callback callback : installationCallbacks) { + callback.installed(tracer); + } + } + } + + public static Tracer get() { + return provider; + } + + public static EventTracker getEventTracker() { + if (eventTracker == EventTracker.NO_EVENT_TRACKER) { + if (provider instanceof InternalTracer) { + eventTracker = new EventTracker((InternalTracer) provider); + } + } + return eventTracker; + } + + // -------------------------------------------------------------------------------- + // All code below is to support the callback registration in WithGlobalTracer + // -------------------------------------------------------------------------------- + static void registerInstallationCallback(Callback callback) { + synchronized (installationCallbacks) { + installationCallbacks.add(callback); + + if (provider != NO_OP) { + callback.installed(provider); + } + } + } + + interface Callback { + void installed(Tracer tracer); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java b/features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java new file mode 100644 index 0000000000..31c1b78a23 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java @@ -0,0 +1,117 @@ +package datadog.trace.api; + +import static java.lang.Long.MAX_VALUE; + +import java.security.SecureRandom; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Strategy for generating trace ids and span ids. + * + *

The reason this is not an ENUM is to allow future changes that are crosscutting and + * configuration based, for example 128 bit trace ids et.c., without changing the public API. + */ +public abstract class IdGenerationStrategy { + protected final boolean traceId128BitGenerationEnabled; + + private IdGenerationStrategy(boolean traceId128BitGenerationEnabled) { + this.traceId128BitGenerationEnabled = traceId128BitGenerationEnabled; + } + + public static IdGenerationStrategy fromName(String name) { + return fromName(name, false); + } + + public static IdGenerationStrategy fromName(String name, boolean traceId128BitGenerationEnabled) { + switch (name.toUpperCase()) { + case "RANDOM": + return new Random(traceId128BitGenerationEnabled); + case "SEQUENTIAL": + return new Sequential(traceId128BitGenerationEnabled); + case "SECURE_RANDOM": + return new SRandom(traceId128BitGenerationEnabled); + default: + return null; + } + } + + public DDTraceId generateTraceId() { + return this.traceId128BitGenerationEnabled + ? DD128bTraceId.from(generateHighOrderBits(), getNonZeroPositiveLong()) + : DD64bTraceId.from(getNonZeroPositiveLong()); + } + + public long generateSpanId() { + return getNonZeroPositiveLong(); + } + + protected abstract long getNonZeroPositiveLong(); + + protected long generateHighOrderBits() { + long timestamp = System.currentTimeMillis() / 1000; + return timestamp << 32; + } + + static final class Random extends IdGenerationStrategy { + private Random(boolean traceId128BitGenerationEnabled) { + super(traceId128BitGenerationEnabled); + } + + @Override + protected long getNonZeroPositiveLong() { + return ThreadLocalRandom.current().nextLong(0, MAX_VALUE) + 1; + } + } + + static final class Sequential extends IdGenerationStrategy { + private final AtomicLong id; + + private Sequential(boolean traceId128BitGenerationEnabled) { + super(traceId128BitGenerationEnabled); + this.id = new AtomicLong(0); + } + + @Override + public DDTraceId generateTraceId() { + // Only use 64-bit TraceId to use incremental values only + return DD64bTraceId.from(getNonZeroPositiveLong()); + } + + @Override + protected long getNonZeroPositiveLong() { + return this.id.incrementAndGet(); + } + } + + @FunctionalInterface + interface ThrowingSupplier { + T get() throws Throwable; + } + + static final class SRandom extends IdGenerationStrategy { + private final SecureRandom secureRandom; + + SRandom(boolean traceId128BitGenerationEnabled) { + this(traceId128BitGenerationEnabled, SecureRandom::getInstanceStrong); + } + + SRandom(boolean traceId128BitGenerationEnabled, ThrowingSupplier supplier) { + super(traceId128BitGenerationEnabled); + try { + secureRandom = supplier.get(); + } catch (Throwable e) { + throw new ExceptionInInitializerError(e); + } + } + + @Override + protected long getNonZeroPositiveLong() { + long value = secureRandom.nextLong() & MAX_VALUE; + while (value == 0) { + value = secureRandom.nextLong() & MAX_VALUE; + } + return value; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/InstrumenterConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/InstrumenterConfig.java new file mode 100644 index 0000000000..7a910cba2e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/InstrumenterConfig.java @@ -0,0 +1,498 @@ +package datadog.trace.api; + +import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_ENABLED; +import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_ENABLED; +import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_ENABLED; +import static datadog.trace.api.ConfigDefaults.DEFAULT_INTEGRATIONS_ENABLED; +import static datadog.trace.api.ConfigDefaults.DEFAULT_MEASURE_METHODS; +import static datadog.trace.api.ConfigDefaults.DEFAULT_RESOLVER_RESET_INTERVAL; +import static datadog.trace.api.ConfigDefaults.DEFAULT_RUNTIME_CONTEXT_FIELD_INJECTION; +import static datadog.trace.api.ConfigDefaults.DEFAULT_SERIALVERSIONUID_FIELD_INJECTION; +import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_ENABLED; +import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_128_BIT_TRACEID_LOGGING_ENABLED; +import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ANNOTATIONS; +import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ANNOTATION_ASYNC; +import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ENABLED; +import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_EXECUTORS_ALL; +import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_METHODS; +import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_OTEL_ENABLED; +import static datadog.trace.api.ConfigDefaults.DEFAULT_USM_ENABLED; +import static datadog.trace.api.config.AppSecConfig.APPSEC_ENABLED; +import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ENABLED; +import static datadog.trace.api.config.GeneralConfig.INTERNAL_EXIT_ON_FAILURE; +import static datadog.trace.api.config.GeneralConfig.TELEMETRY_ENABLED; +import static datadog.trace.api.config.IastConfig.IAST_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_ENABLED_DEFAULT; +import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_URL_CONNECTION_CLASS_NAME; +import static datadog.trace.api.config.TraceInstrumentationConfig.INTEGRATIONS_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.JDBC_CONNECTION_CLASS_NAME; +import static datadog.trace.api.config.TraceInstrumentationConfig.JDBC_PREPARED_STATEMENT_CLASS_NAME; +import static datadog.trace.api.config.TraceInstrumentationConfig.LEGACY_INSTALLER_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.MEASURE_METHODS; +import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_CACHE_CONFIG; +import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_CACHE_DIR; +import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_NAMES_ARE_UNIQUE; +import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_RESET_INTERVAL; +import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_USE_LOADCLASS; +import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_USE_URL_CACHES; +import static datadog.trace.api.config.TraceInstrumentationConfig.RUNTIME_CONTEXT_FIELD_INJECTION; +import static datadog.trace.api.config.TraceInstrumentationConfig.SERIALVERSIONUID_FIELD_INJECTION; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_128_BIT_TRACEID_LOGGING_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ANNOTATIONS; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ANNOTATION_ASYNC; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CLASSES_EXCLUDE; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CLASSES_EXCLUDE_FILE; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CLASSLOADERS_EXCLUDE; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CODESOURCES_EXCLUDE; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_EXECUTORS; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_EXECUTORS_ALL; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_METHODS; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_OTEL_ENABLED; +import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_THREAD_POOL_EXECUTORS_EXCLUDE; +import static datadog.trace.api.config.UsmConfig.USM_ENABLED; +import static datadog.trace.util.CollectionUtils.tryMakeImmutableList; +import static datadog.trace.util.CollectionUtils.tryMakeImmutableSet; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import datadog.trace.bootstrap.config.provider.ConfigProvider; + +/** + * This config is needed before instrumentation is applied + * + *

For example anything that changes what advice is applied, or what classes are instrumented + * + *

This config will be baked into native-images at build time, because instrumentation is also + * baked in at that point + * + *

Config that is accessed from inside advice, for example during application runtime after the + * advice has been applied, shouldn't be in {@link InstrumenterConfig} (it really should just be + * config that must be there ahead of instrumentation) + * + * @see DynamicConfig for configuration that can be dynamically updated via remote-config + * @see Config for other configurations + */ +public class InstrumenterConfig { + private final ConfigProvider configProvider; + + private final boolean integrationsEnabled; + + private final boolean traceEnabled; + private final boolean traceOtelEnabled; + private final boolean logs128bTraceIdEnabled; + private final boolean profilingEnabled; + private final boolean ciVisibilityEnabled; + private final ProductActivation appSecActivation; + private final ProductActivation iastActivation; + private final boolean usmEnabled; + private final boolean telemetryEnabled; + + private final boolean traceExecutorsAll; + private final List traceExecutors; + private final Set traceThreadPoolExecutorsExclude; + + private final String jdbcPreparedStatementClassName; + private final String jdbcConnectionClassName; + + private final String httpURLConnectionClassName; + + private final boolean directAllocationProfilingEnabled; + + private final List excludedClasses; + private final String excludedClassesFile; + private final Set excludedClassLoaders; + private final List excludedCodeSources; + + private final ResolverCacheConfig resolverCacheConfig; + private final String resolverCacheDir; + private final boolean resolverNamesAreUnique; + private final boolean resolverUseLoadClass; + private final Boolean resolverUseUrlCaches; + private final int resolverResetInterval; + + private final boolean runtimeContextFieldInjection; + private final boolean serialVersionUIDFieldInjection; + + private final String traceAnnotations; + private final boolean traceAnnotationAsync; + private final Map> traceMethods; + private final Map> measureMethods; + + private final boolean internalExitOnFailure; + + private final boolean legacyInstallerEnabled; + + private InstrumenterConfig() { + this(ConfigProvider.createDefault()); + } + + InstrumenterConfig(ConfigProvider configProvider) { + this.configProvider = configProvider; + + integrationsEnabled = + configProvider.getBoolean(INTEGRATIONS_ENABLED, DEFAULT_INTEGRATIONS_ENABLED); + + traceEnabled = configProvider.getBoolean(TRACE_ENABLED, DEFAULT_TRACE_ENABLED); + traceOtelEnabled = configProvider.getBoolean(TRACE_OTEL_ENABLED, DEFAULT_TRACE_OTEL_ENABLED); + logs128bTraceIdEnabled = + configProvider.getBoolean( + TRACE_128_BIT_TRACEID_LOGGING_ENABLED, DEFAULT_TRACE_128_BIT_TRACEID_LOGGING_ENABLED); + profilingEnabled = configProvider.getBoolean(PROFILING_ENABLED, PROFILING_ENABLED_DEFAULT); + + if (!Platform.isNativeImageBuilder()) { + ciVisibilityEnabled = + configProvider.getBoolean(CIVISIBILITY_ENABLED, DEFAULT_CIVISIBILITY_ENABLED); + appSecActivation = + ProductActivation.fromString( + configProvider.getStringNotEmpty(APPSEC_ENABLED, DEFAULT_APPSEC_ENABLED)); + iastActivation = + ProductActivation.fromString( + configProvider.getStringNotEmpty(IAST_ENABLED, DEFAULT_IAST_ENABLED)); + usmEnabled = configProvider.getBoolean(USM_ENABLED, DEFAULT_USM_ENABLED); + telemetryEnabled = configProvider.getBoolean(TELEMETRY_ENABLED, DEFAULT_TELEMETRY_ENABLED); + } else { + // disable these features in native-image + ciVisibilityEnabled = false; + appSecActivation = ProductActivation.FULLY_DISABLED; + iastActivation = ProductActivation.FULLY_DISABLED; + telemetryEnabled = false; + usmEnabled = false; + } + + traceExecutorsAll = configProvider.getBoolean(TRACE_EXECUTORS_ALL, DEFAULT_TRACE_EXECUTORS_ALL); + traceExecutors = tryMakeImmutableList(configProvider.getList(TRACE_EXECUTORS)); + traceThreadPoolExecutorsExclude = + tryMakeImmutableSet(configProvider.getList(TRACE_THREAD_POOL_EXECUTORS_EXCLUDE)); + + jdbcPreparedStatementClassName = + configProvider.getString(JDBC_PREPARED_STATEMENT_CLASS_NAME, ""); + jdbcConnectionClassName = configProvider.getString(JDBC_CONNECTION_CLASS_NAME, ""); + + httpURLConnectionClassName = configProvider.getString(HTTP_URL_CONNECTION_CLASS_NAME, ""); + + directAllocationProfilingEnabled = + configProvider.getBoolean( + PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT); + + excludedClasses = tryMakeImmutableList(configProvider.getList(TRACE_CLASSES_EXCLUDE)); + excludedClassesFile = configProvider.getString(TRACE_CLASSES_EXCLUDE_FILE); + excludedClassLoaders = tryMakeImmutableSet(configProvider.getList(TRACE_CLASSLOADERS_EXCLUDE)); + excludedCodeSources = tryMakeImmutableList(configProvider.getList(TRACE_CODESOURCES_EXCLUDE)); + + resolverCacheConfig = + configProvider.getEnum( + RESOLVER_CACHE_CONFIG, ResolverCacheConfig.class, ResolverCacheConfig.MEMOS); + resolverCacheDir = configProvider.getString(RESOLVER_CACHE_DIR); + resolverNamesAreUnique = configProvider.getBoolean(RESOLVER_NAMES_ARE_UNIQUE, false); + resolverUseLoadClass = configProvider.getBoolean(RESOLVER_USE_LOADCLASS, true); + resolverUseUrlCaches = configProvider.getBoolean(RESOLVER_USE_URL_CACHES); + resolverResetInterval = + Platform.isNativeImageBuilder() + ? 0 + : configProvider.getInteger(RESOLVER_RESET_INTERVAL, DEFAULT_RESOLVER_RESET_INTERVAL); + + runtimeContextFieldInjection = + configProvider.getBoolean( + RUNTIME_CONTEXT_FIELD_INJECTION, DEFAULT_RUNTIME_CONTEXT_FIELD_INJECTION); + serialVersionUIDFieldInjection = + configProvider.getBoolean( + SERIALVERSIONUID_FIELD_INJECTION, DEFAULT_SERIALVERSIONUID_FIELD_INJECTION); + + traceAnnotations = configProvider.getString(TRACE_ANNOTATIONS, DEFAULT_TRACE_ANNOTATIONS); + traceAnnotationAsync = + configProvider.getBoolean(TRACE_ANNOTATION_ASYNC, DEFAULT_TRACE_ANNOTATION_ASYNC); + traceMethods = + MethodFilterConfigParser.parse( + configProvider.getString(TRACE_METHODS, DEFAULT_TRACE_METHODS)); + measureMethods = + MethodFilterConfigParser.parse( + configProvider.getString(MEASURE_METHODS, DEFAULT_MEASURE_METHODS)); + internalExitOnFailure = configProvider.getBoolean(INTERNAL_EXIT_ON_FAILURE, false); + + legacyInstallerEnabled = configProvider.getBoolean(LEGACY_INSTALLER_ENABLED, false); + } + + public boolean isIntegrationsEnabled() { + return integrationsEnabled; + } + + public boolean isIntegrationEnabled( + final Iterable integrationNames, final boolean defaultEnabled) { + return configProvider.isEnabled(integrationNames, "integration.", ".enabled", defaultEnabled); + } + + public boolean isIntegrationShortcutMatchingEnabled( + final Iterable integrationNames, final boolean defaultEnabled) { + return configProvider.isEnabled( + integrationNames, "integration.", ".matching.shortcut.enabled", defaultEnabled); + } + + public boolean isTraceEnabled() { + return traceEnabled; + } + + public boolean isTraceOtelEnabled() { + return traceOtelEnabled; + } + + public boolean isLogs128bTraceIdEnabled() { + return logs128bTraceIdEnabled; + } + + public boolean isProfilingEnabled() { + return profilingEnabled; + } + + public boolean isCiVisibilityEnabled() { + return ciVisibilityEnabled; + } + + public ProductActivation getAppSecActivation() { + return appSecActivation; + } + + public ProductActivation getIastActivation() { + return iastActivation; + } + + public boolean isUsmEnabled() { + return usmEnabled; + } + + public boolean isTelemetryEnabled() { + return telemetryEnabled; + } + + public boolean isTraceExecutorsAll() { + return traceExecutorsAll; + } + + public List getTraceExecutors() { + return traceExecutors; + } + + public Set getTraceThreadPoolExecutorsExclude() { + return traceThreadPoolExecutorsExclude; + } + + public String getJdbcPreparedStatementClassName() { + return jdbcPreparedStatementClassName; + } + + public String getJdbcConnectionClassName() { + return jdbcConnectionClassName; + } + + public String getHttpURLConnectionClassName() { + return httpURLConnectionClassName; + } + + public boolean isDirectAllocationProfilingEnabled() { + return directAllocationProfilingEnabled; + } + + public List getExcludedClasses() { + return excludedClasses; + } + + public String getExcludedClassesFile() { + return excludedClassesFile; + } + + public Set getExcludedClassLoaders() { + return excludedClassLoaders; + } + + public List getExcludedCodeSources() { + return excludedCodeSources; + } + + public int getResolverNoMatchesSize() { + return resolverCacheConfig.noMatchesSize(); + } + + public boolean isResolverMemoizingEnabled() { + return resolverCacheConfig.memoPoolSize() > 0; + } + + public int getResolverMemoPoolSize() { + return resolverCacheConfig.memoPoolSize(); + } + + public boolean isResolverOutliningEnabled() { + return resolverCacheConfig.outlinePoolSize() > 0; + } + + public int getResolverOutlinePoolSize() { + return resolverCacheConfig.outlinePoolSize(); + } + + public int getResolverTypePoolSize() { + return resolverCacheConfig.typePoolSize(); + } + + public String getResolverCacheDir() { + return resolverCacheDir; + } + + public boolean isResolverNamesAreUnique() { + return resolverNamesAreUnique; + } + + public boolean isResolverUseLoadClass() { + return resolverUseLoadClass; + } + + public Boolean isResolverUseUrlCaches() { + return resolverUseUrlCaches; + } + + public int getResolverResetInterval() { + return resolverResetInterval; + } + + public boolean isRuntimeContextFieldInjection() { + return runtimeContextFieldInjection; + } + + public boolean isSerialVersionUIDFieldInjection() { + return serialVersionUIDFieldInjection; + } + + public String getTraceAnnotations() { + return traceAnnotations; + } + + /** + * Check whether asynchronous result types are supported with @Trace annotation. + * + * @return {@code true} if supported, {@code false} otherwise. + */ + public boolean isTraceAnnotationAsync() { + return traceAnnotationAsync; + } + + public Map> getTraceMethods() { + return traceMethods; + } + + public boolean isMethodMeasured(Method method) { + if (this.measureMethods.isEmpty()) { + return false; + } + String clazz = method.getDeclaringClass().getName(); + Set methods = this.measureMethods.get(clazz); + return methods != null && (methods.contains(method.getName()) || methods.contains("*")); + } + + public boolean isInternalExitOnFailure() { + return internalExitOnFailure; + } + + public boolean isLegacyInstallerEnabled() { + return legacyInstallerEnabled; + } + + public boolean isLegacyInstrumentationEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".legacy.tracing.enabled", defaultEnabled); + } + + // This has to be placed after all other static fields to give them a chance to initialize + private static final InstrumenterConfig INSTANCE = + new InstrumenterConfig( + Platform.isNativeImageBuilder() + ? ConfigProvider.withoutCollector() + : ConfigProvider.getInstance()); + + public static InstrumenterConfig get() { + return INSTANCE; + } + + @Override + public String toString() { + return "InstrumenterConfig{" + + "integrationsEnabled=" + + integrationsEnabled + + ", traceEnabled=" + + traceEnabled + + ", traceOtelEnabled=" + + traceOtelEnabled + + ", logs128bTraceIdEnabled=" + + logs128bTraceIdEnabled + + ", profilingEnabled=" + + profilingEnabled + + ", ciVisibilityEnabled=" + + ciVisibilityEnabled + + ", appSecActivation=" + + appSecActivation + + ", iastActivation=" + + iastActivation + + ", usmEnabled=" + + usmEnabled + + ", telemetryEnabled=" + + telemetryEnabled + + ", traceExecutorsAll=" + + traceExecutorsAll + + ", traceExecutors=" + + traceExecutors + + ", jdbcPreparedStatementClassName='" + + jdbcPreparedStatementClassName + + '\'' + + ", jdbcConnectionClassName='" + + jdbcConnectionClassName + + '\'' + + ", httpURLConnectionClassName='" + + httpURLConnectionClassName + + '\'' + + ", excludedClasses=" + + excludedClasses + + ", excludedClassesFile=" + + excludedClassesFile + + ", excludedClassLoaders=" + + excludedClassLoaders + + ", excludedCodeSources=" + + excludedCodeSources + + ", resolverCacheConfig=" + + resolverCacheConfig + + ", resolverCacheDir=" + + resolverCacheDir + + ", resolverNamesAreUnique=" + + resolverNamesAreUnique + + ", resolverUseLoadClass=" + + resolverUseLoadClass + + ", resolverUseUrlCaches=" + + resolverUseUrlCaches + + ", resolverResetInterval=" + + resolverResetInterval + + ", runtimeContextFieldInjection=" + + runtimeContextFieldInjection + + ", serialVersionUIDFieldInjection=" + + serialVersionUIDFieldInjection + + ", traceAnnotations='" + + traceAnnotations + + '\'' + + ", traceAnnotationAsync=" + + traceAnnotationAsync + + ", traceMethods='" + + traceMethods + + '\'' + + ", measureMethods= '" + + measureMethods + + '\'' + + ", internalExitOnFailure=" + + internalExitOnFailure + + ", legacyInstallerEnabled=" + + legacyInstallerEnabled + + '}'; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/MethodFilterConfigParser.java b/features/dd-trace-core/src/main/java/datadog/trace/api/MethodFilterConfigParser.java new file mode 100644 index 0000000000..eb9276bbab --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/MethodFilterConfigParser.java @@ -0,0 +1,141 @@ +package datadog.trace.api; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public final class MethodFilterConfigParser { + private static final Logger log = LoggerFactory.getLogger(MethodFilterConfigParser.class); + + private static Map> logWarn( + String message, int start, int end, String configString) { + String part = configString.substring(start, end).trim(); + log.warn( + "Invalid trace method config {} in part '{}'. Must match 'package.Class$Name[method1,method2];?' or 'package.Class$Name[*];?'. Config string: '{}'", + message, + part, + configString); + return Collections.emptyMap(); + } + + private static boolean hasIllegalCharacters(String string) { + for (int i = 0; i < string.length(); i++) { + char c = string.charAt(i); + if (c == '*' || c == '[' || c == ']' || c == ',') { + return true; + } + } + return false; + } + + private static boolean isIllegalClassName(String string) { + return hasIllegalCharacters(string); + } + + private static boolean isIllegalMethodName(String string) { + return !string.equals("*") && hasIllegalCharacters(string); + } + + public static Map> parse(String configString) { + Map> classMethodsToTrace; + if (configString == null || configString.trim().isEmpty()) { + classMethodsToTrace = Collections.emptyMap(); + } else { + Map> toTrace = new HashMap<>(); + int start = 0; + do { + int next = configString.indexOf(';', start + 1); + int end = next == -1 ? configString.length() : next; + if (end > start + 1) { + int methodsStart = configString.indexOf('[', start); + if (methodsStart == -1) { + if (!configString.substring(start).trim().isEmpty()) { + // this had other things than trailing whitespace after the ';' which is illegal + toTrace = logWarn("with incomplete definition", start, end, configString); + } + break; + } else if (methodsStart >= end) { + // this part didn't contain a '[' or ended in a '[' which is illegal + toTrace = logWarn("with incomplete method definition", start, end, configString); + break; + } + int methodsEnd = configString.indexOf(']', methodsStart); + if (methodsEnd == -1 || methodsEnd > end) { + // this part didn't contain a ']' which is illegal + toTrace = logWarn("does not contain a ']'", start, end, configString); + break; + } else if (methodsEnd < end + && !configString.substring(methodsEnd + 1, end).trim().isEmpty()) { + // this had other things than trailing whitespace after the ']' + toTrace = logWarn("with extra characters after ']'", start, end, configString); + break; + } + String className = configString.substring(start, methodsStart).trim(); + if (className.isEmpty() || isIllegalClassName(className)) { + toTrace = logWarn("with illegal class name", start, end, configString); + break; + } + Set methodNames = toTrace.get(className); + if (null == methodNames) { + methodNames = new HashSet<>(); + toTrace.put(className, methodNames); + } + int methods = 0; + int emptyMethods = 0; + boolean hasStar = false; + for (int methodStart = methodsStart + 1; methodStart < methodsEnd; ) { + int nextComma = configString.indexOf(',', methodStart); + int methodEnd = nextComma == -1 || nextComma >= methodsEnd ? methodsEnd : nextComma; + String method = configString.substring(methodStart, methodEnd).trim(); + if (isIllegalMethodName(method)) { + toTrace = logWarn("with illegal method name", start, end, configString); + methods++; // don't log empty method warning at end + next = -1; + break; + } else if (method.isEmpty()) { + emptyMethods++; + if (emptyMethods > 1) { + // we can't have multiple empty methods + toTrace = logWarn("with multiple emtpy method names", start, end, configString); + methods++; // don't log empty method warning at end + next = -1; + break; + } + } else { + methods++; + if (emptyMethods > 0) { + // the empty method name was not the last one, which makes it illegal + toTrace = + logWarn("with method name and emtpy method name", start, end, configString); + next = -1; + break; + } + hasStar |= method.indexOf('*') != -1; + if (hasStar && methods > 1) { + // having both a method and a '*' is illegal + toTrace = logWarn("with both method name and '*'", start, end, configString); + next = -1; + break; + } + methodNames.add(method); + } + methodStart = methodEnd + 1; + } + if (methods == 0) { + // empty method description is illegal + toTrace = logWarn("with empty method definition", start, end, configString); + break; + } + } + start = next + 1; + } while (start != 0); + classMethodsToTrace = Collections.unmodifiableMap(toTrace); + } + return classMethodsToTrace; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/NoOpStatsDClient.java b/features/dd-trace-core/src/main/java/datadog/trace/api/NoOpStatsDClient.java new file mode 100644 index 0000000000..83f1955228 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/NoOpStatsDClient.java @@ -0,0 +1,46 @@ +package datadog.trace.api; + +final class NoOpStatsDClient implements StatsDClient { + + @Override + public void incrementCounter(final String metricName, final String... tags) {} + + @Override + public void count(final String metricName, final long delta, final String... tags) {} + + @Override + public void gauge(final String metricName, final long value, final String... tags) {} + + @Override + public void gauge(final String metricName, final double value, final String... tags) {} + + @Override + public void histogram(final String metricName, final long value, final String... tags) {} + + @Override + public void histogram(final String metricName, final double value, final String... tags) {} + + @Override + public void distribution(String metricName, long value, String... tags) {} + + @Override + public void distribution(String metricName, double value, String... tags) {} + + @Override + public void serviceCheck( + final String serviceCheckName, + final String status, + final String message, + final String... tags) {} + + @Override + public void error(Exception error) {} + + @Override + public int getErrorCount() { + return 0; + } + + @Override + public void close() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Pair.java b/features/dd-trace-core/src/main/java/datadog/trace/api/Pair.java new file mode 100644 index 0000000000..6de16b2f74 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/Pair.java @@ -0,0 +1,53 @@ +package datadog.trace.api; + +import androidx.annotation.Nullable; + +import java.util.Objects; + +public final class Pair { + + public static Pair of(T left, U right) { + return new Pair<>(left, right); + } + + private final T left; + private final U right; + + Pair(@Nullable T left, @Nullable U right) { + this.left = left; + this.right = right; + } + + @Nullable + public T getLeft() { + return left; + } + + @Nullable + public U getRight() { + return right; + } + + public boolean hasLeft() { + return null != left; + } + + public boolean hasRight() { + return null != right; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o instanceof Pair) { + Pair pair = (Pair) o; + return Objects.equals(left, pair.left) && Objects.equals(right, pair.right); + } + return false; + } + + @Override + public int hashCode() { + return 31 * (null == left ? 0 : left.hashCode()) + (null == right ? 0 : right.hashCode()); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java b/features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java new file mode 100644 index 0000000000..dc580a3756 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java @@ -0,0 +1,350 @@ +package datadog.trace.api; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public final class Platform { + // A helper class to capture whether the executable is a native image or not. + // This class needs to be iniatlized at build only during the AOT compilation and build. + private static class Captured { + public static final boolean isNativeImage = checkForNativeImageBuilder(); + } + + public enum GC { + SERIAL("marksweep"), + PARALLEL("ps"), + CMS("concurrentmarksweep"), + G1("g1"), + SHENANDOAH("shenandoah"), + Z("z"), + UNKNOWN(""); + + private final String identifierPrefix; + + GC(String identifierPrefix) { + this.identifierPrefix = identifierPrefix; + } + +// static GC current() { +// if(checkManagementFactory()) { +// for (GarbageCollectorMXBean mxBean : java.lang.management.ManagementFactory.getGarbageCollectorMXBeans()) { +// if (mxBean.isValid()) { +// String name = mxBean.getName().toLowerCase(Locale.ROOT); +// for (GC gc : GC.values()) { +// if (gc != UNKNOWN && name.startsWith(gc.identifierPrefix)) { +// return gc; +// } +// } +// } +// } +// } +// return UNKNOWN; +// } + } + + private static final Version JAVA_VERSION = parseJavaVersion(System.getProperty("java.version")); + private static final JvmRuntime RUNTIME = new JvmRuntime(); + +// private static final GC GARBAGE_COLLECTOR = GC.current(); + + private static final boolean HAS_JFR = checkForJfr(); + private static final boolean IS_NATIVE_IMAGE_BUILDER = checkForNativeImageBuilder(); + private static final boolean IS_NATIVE_IMAGE = Captured.isNativeImage; + +// public static GC activeGarbageCollector() { +// return GARBAGE_COLLECTOR; +// } + + public static boolean hasJfr() { + return HAS_JFR; + } + + public static boolean isNativeImageBuilder() { + return IS_NATIVE_IMAGE_BUILDER; + } + + public static boolean isNativeImage() { + return IS_NATIVE_IMAGE; + } + + private static boolean checkForJfr() { + try { + /* Check only for the open-sources JFR implementation. + * If it is ever needed to support also the closed sourced JDK 8 version the check should be + * enhanced. + * Need this custom check because ClassLoaderMatchers.hasClassNamed() does not support bootstrap class loader yet. + * Note: the downside of this is that we load some JFR classes at startup. + */ + return ClassLoader.getSystemClassLoader().getResource("jdk/jfr/Event.class") != null; + } catch (Throwable e) { + return false; + } + } + private static boolean checkManagementFactory() { + try { + return ClassLoader.getSystemClassLoader().getResource("java/lang/ManagementFactory.class") != null; + } catch (Throwable e) { + return false; + } + } + + private static boolean checkForNativeImageBuilder() { + try { + return "org.graalvm.nativeimage.builder".equals(System.getProperty("jdk.module.main")); + } catch (Throwable e) { + return false; + } + } + + /* The method splits java version string by digits. Delimiters are: dot, underscore and plus */ + private static List splitDigits(String str) { + List results = new ArrayList<>(); + + int len = str.length(); + + int value = 0; + for (int i = 0; i < len; i++) { + char ch = str.charAt(i); + if (ch >= '0' && ch <= '9') { + value = value * 10 + (ch - '0'); + } else if (ch == '.' || ch == '_' || ch == '+') { + results.add(value); + value = 0; + } else { + throw new NumberFormatException(); + } + } + results.add(value); + return results; + } + + private static Version parseJavaVersion(String javaVersion) { + // Remove pre-release part, usually -ea + final int indexOfDash = javaVersion.indexOf('-'); + if (indexOfDash >= 0) { + javaVersion = javaVersion.substring(0, indexOfDash); + } + + int major = 0; + int minor = 0; + int update = 0; + + try { + List nums = splitDigits(javaVersion); + major = nums.get(0); + + // for java 1.6/1.7/1.8 + if (major == 1) { + major = nums.get(1); + minor = nums.get(2); + update = nums.get(3); + } else { + minor = nums.get(1); + update = nums.get(2); + } + } catch (NumberFormatException | IndexOutOfBoundsException e) { + // unable to parse version string - do nothing + } + return new Version(major, minor, update); + } + + static final class Version { + public final int major, minor, update; + + public Version(int major, int minor, int update) { + this.major = major; + this.minor = minor; + this.update = update; + } + + public boolean is(int major) { + return this.major == major; + } + + public boolean is(int major, int minor) { + return this.major == major && this.minor == minor; + } + + public boolean is(int major, int minor, int update) { + return this.major == major && this.minor == minor && this.update == update; + } + + public boolean isAtLeast(int major, int minor, int update) { + return isAtLeast(this.major, this.minor, this.update, major, minor, update); + } + + public boolean isBetween( + int fromMajor, int fromMinor, int fromUpdate, int toMajor, int toMinor, int toUpdate) { + return isAtLeast(toMajor, toMinor, toUpdate, fromMajor, fromMinor, fromUpdate) + && isAtLeast(fromMajor, fromMinor, fromUpdate) + && !isAtLeast(toMajor, toMinor, toUpdate); + } + + private static boolean isAtLeast( + int major, int minor, int update, int atLeastMajor, int atLeastMinor, int atLeastUpdate) { + return (major > atLeastMajor) + || (major == atLeastMajor && minor > atLeastMinor) + || (major == atLeastMajor && minor == atLeastMinor && update >= atLeastUpdate); + } + } + + static final class JvmRuntime { + /* + * Example: + * jvm -> "AdoptOpenJDK 1.8.0_265-b01" + * + * name -> "OpenJDK" + * vendor -> "AdoptOpenJDK" + * version -> "1.8.0_265" + * patches -> "b01" + */ + public final String name; + + public final String vendor; + public final String version; + public final String vendorVersion; + public final String patches; + + public JvmRuntime() { + this( + System.getProperty("java.version"), + System.getProperty("java.runtime.version"), + System.getProperty("java.runtime.name"), + System.getProperty("java.vm.vendor"), + System.getProperty("java.vendor.version")); + } + + // Only visible for testing + JvmRuntime(String javaVer, String rtVer, String name, String vendor, String vendorVersion) { + this.name = name == null ? "" : name; + this.vendor = vendor == null ? "" : vendor; + javaVer = javaVer == null ? "" : javaVer; + this.version = javaVer; + this.vendorVersion = vendorVersion == null ? "" : vendorVersion; + rtVer = javaVer.isEmpty() || rtVer == null ? javaVer : rtVer; + int patchStart = javaVer.length() + 1; + this.patches = (patchStart >= rtVer.length()) ? "" : rtVer.substring(javaVer.length() + 1); + } + } + + public static boolean isJavaVersion(int major) { + return JAVA_VERSION.is(major); + } + + public static boolean isJavaVersion(int major, int minor) { + return JAVA_VERSION.is(major, minor); + } + + public static boolean isJavaVersion(int major, int minor, int update) { + return JAVA_VERSION.is(major, minor, update); + } + + public static boolean isJavaVersionAtLeast(int major) { + return isJavaVersionAtLeast(major, 0, 0); + } + + public static boolean isJavaVersionAtLeast(int major, int minor) { + return isJavaVersionAtLeast(major, minor, 0); + } + + public static boolean isJavaVersionAtLeast(int major, int minor, int update) { + return JAVA_VERSION.isAtLeast(major, minor, update); + } + + /** + * Check if the Java version is between {@code fromMajor} (inclusive) and {@code toMajor} + * (exclusive). + * + * @param fromMajor major from version (inclusive) + * @param toMajor major to version (exclusive) + * @return if the current java version is between the from version (inclusive) and the to version + * exclusive + */ + public static boolean isJavaVersionBetween(int fromMajor, int toMajor) { + return isJavaVersionBetween(fromMajor, 0, toMajor, 0); + } + + /** + * Check if the Java version is between {@code fromMajor.fromMinor} (inclusive) and {@code + * toMajor.toMinor} (exclusive). + * + * @param fromMajor major from version (inclusive) + * @param fromMinor minor from version (inclusive) + * @param toMajor major to version (exclusive) + * @param toMinor minor to version (exclusive) + * @return if the current java version is between the from version (inclusive) and the to version + * exclusive + */ + public static boolean isJavaVersionBetween( + int fromMajor, int fromMinor, int toMajor, int toMinor) { + return isJavaVersionBetween(fromMajor, fromMinor, 0, toMajor, toMinor, 0); + } + + /** + * Check if the Java version is between {@code fromMajor.fromMinor.fromUpdate} (inclusive) and + * {@code toMajor.toMinor.toUpdate} (exclusive). + * + * @param fromMajor major from version (inclusive) + * @param fromMinor minor from version (inclusive) + * @param fromUpdate update from version (inclusive) + * @param toMajor major to version (exclusive) + * @param toMinor minor to version (exclusive) + * @param toUpdate update to version (exclusive) + * @return if the current java version is between the from version (inclusive) and the to version + * exclusive + */ + public static boolean isJavaVersionBetween( + int fromMajor, int fromMinor, int fromUpdate, int toMajor, int toMinor, int toUpdate) { + return JAVA_VERSION.isBetween(fromMajor, fromMinor, fromUpdate, toMajor, toMinor, toUpdate); + } + + public static boolean isLinux() { + return System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("linux"); + } + + public static boolean isWindows() { + // https://mkyong.com/java/how-to-detect-os-in-java-systemgetpropertyosname/ + final String os = System.getProperty("os.name").toLowerCase(Locale.ROOT); + return os.contains("win"); + } + + public static boolean isMac() { + final String os = System.getProperty("os.name").toLowerCase(Locale.ROOT); + return os.contains("mac"); + } + + public static boolean isOracleJDK8() { + return isJavaVersion(8) + && RUNTIME.vendor.contains("Oracle") + && !RUNTIME.name.contains("OpenJDK"); + } + + public static boolean isJ9() { + return System.getProperty("java.vm.name").contains("J9"); + } + + public static boolean isIbm8() { + return isJavaVersion(8) && RUNTIME.vendor.contains("IBM"); + } + + public static boolean isGraalVM() { + return RUNTIME.vendorVersion.toLowerCase().contains("graalvm"); + } + + public static String getLangVersion() { + return String.valueOf(JAVA_VERSION.major); + } + + public static String getRuntimeVendor() { + return RUNTIME.vendor; + } + + public static String getRuntimeVersion() { + return RUNTIME.version; + } + + public static String getRuntimePatches() { + return RUNTIME.patches; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ProductActivation.java b/features/dd-trace-core/src/main/java/datadog/trace/api/ProductActivation.java new file mode 100644 index 0000000000..834afb815c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/ProductActivation.java @@ -0,0 +1,29 @@ +package datadog.trace.api; + +public enum ProductActivation { + /** + * The product is initialized, its instrumentation is applied and the logic in the instrumentation + * advice is applied. It cannot be disabled at runtime. + */ + FULLY_ENABLED, + /** + * Completely disabled. The product is not initialized in any way. It cannot be enabled at + * runtime. + */ + FULLY_DISABLED, + /** + * The product is initialized, its instrumentation applied, but its logic is disabled to the + * greatest extent possible. It can be enabled and disabled at runtime through remote config. + */ + ENABLED_INACTIVE; + + public static ProductActivation fromString(String s) { + if ("true".equalsIgnoreCase(s) || "1".equals(s)) { + return FULLY_ENABLED; + } + if ("inactive".equalsIgnoreCase(s)) { + return ENABLED_INACTIVE; + } + return FULLY_DISABLED; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java b/features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java new file mode 100644 index 0000000000..89bdb67d1e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java @@ -0,0 +1,31 @@ +package datadog.trace.api; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * These are the old propagation styles that have been deprecated in favor of the propagation styles + * in {@code TracePropagationStyle} + */ +@Deprecated +public enum PropagationStyle { + DATADOG(TracePropagationStyle.DATADOG), + B3(TracePropagationStyle.B3SINGLE, TracePropagationStyle.B3MULTI), + HAYSTACK(TracePropagationStyle.HAYSTACK), + XRAY(TracePropagationStyle.XRAY); + + private final List newStyles; + + PropagationStyle(TracePropagationStyle... newStyles) { + this.newStyles = Collections.unmodifiableList(Arrays.asList(newStyles)); + } + + public List getNewStyles() { + return newStyles; + } + + public static PropagationStyle valueOfConfigName(String configName) { + return valueOf(configName.toUpperCase().trim()); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ResolverCacheConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/ResolverCacheConfig.java new file mode 100644 index 0000000000..476b4240f8 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/ResolverCacheConfig.java @@ -0,0 +1,128 @@ +package datadog.trace.api; + +/** Named presets to help configure various caches inside the type resolver/matcher. */ +public enum ResolverCacheConfig { + + /** Memoizing and outlining for large enterprise apps. */ + LARGE { + @Override + public int noMatchesSize() { + return 65536; + } + + @Override + public int memoPoolSize() { + return 4096; + } + + @Override + public int outlinePoolSize() { + return 256; + } + + @Override + public int typePoolSize() { + return 64; + } + }, + + /** Memoizing and outlining for the average sized app. */ + MEMOS { + @Override + public int noMatchesSize() { + return 16384; + } + + @Override + public int memoPoolSize() { + return 2048; + } + + @Override + public int outlinePoolSize() { + return 128; + } + + @Override + public int typePoolSize() { + return 32; + } + }, + + /** Outlining only for the average sized app, no memoizing. */ + NO_MEMOS { + @Override + public int noMatchesSize() { + return 0; + } + + @Override + public int memoPoolSize() { + return 0; + } + + @Override + public int outlinePoolSize() { + return 256; + } + + @Override + public int typePoolSize() { + return 32; + } + }, + + /** Outlining only for small microservice apps. */ + SMALL { + @Override + public int noMatchesSize() { + return 0; + } + + @Override + public int memoPoolSize() { + return 0; + } + + @Override + public int outlinePoolSize() { + return 32; + } + + @Override + public int typePoolSize() { + return 16; + } + }, + + /** No outlining or memoizing. */ + LEGACY { + @Override + public int noMatchesSize() { + return 0; + } + + @Override + public int memoPoolSize() { + return 0; + } + + @Override + public int outlinePoolSize() { + return 0; + } + + @Override + public int typePoolSize() { + return 64; + } + }; + + public abstract int noMatchesSize(); + + public abstract int memoPoolSize(); + + public abstract int outlinePoolSize(); + + public abstract int typePoolSize(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Stateful.java b/features/dd-trace-core/src/main/java/datadog/trace/api/Stateful.java new file mode 100644 index 0000000000..b9532ca6af --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/Stateful.java @@ -0,0 +1,18 @@ +package datadog.trace.api; + +public interface Stateful extends AutoCloseable { + + Stateful DEFAULT = + new Stateful() { + @Override + public void close() {} + + @Override + public void activate(Object context) {} + }; + + @Override + void close(); + + void activate(Object context); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClient.java b/features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClient.java new file mode 100644 index 0000000000..b9cef20ba4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClient.java @@ -0,0 +1,32 @@ +package datadog.trace.api; + +import java.io.Closeable; + +public interface StatsDClient extends Closeable { + StatsDClient NO_OP = new NoOpStatsDClient(); + + void incrementCounter(String metricName, String... tags); + + void count(String metricName, long delta, String... tags); + + void gauge(String metricName, long value, String... tags); + + void gauge(String metricName, double value, String... tags); + + void histogram(String metricName, long value, String... tags); + + void histogram(String metricName, double value, String... tags); + + void distribution(String metricName, long value, String... tags); + + void distribution(String metricName, double value, String... tags); + + void serviceCheck(String serviceCheckName, String status, String message, String... tags); + + void error(Exception error); + + int getErrorCount(); + + @Override + void close(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClientManager.java b/features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClientManager.java new file mode 100644 index 0000000000..a60438da57 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClientManager.java @@ -0,0 +1,16 @@ +package datadog.trace.api; + +public interface StatsDClientManager { + default StatsDClient statsDClient( + String host, Integer port, String namedPipe, String namespace, String[] constantTags) { + return statsDClient(host, port, namedPipe, namespace, constantTags, true); + } + + StatsDClient statsDClient( + String host, + Integer port, + String namedPipe, + String namespace, + String[] constantTags, + boolean useAggregation); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Trace.java b/features/dd-trace-core/src/main/java/datadog/trace/api/Trace.java new file mode 100644 index 0000000000..d558e459e9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/Trace.java @@ -0,0 +1,25 @@ +package datadog.trace.api; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** Set this annotation to a method so the dd-java-agent considers it for tracing. */ +@Retention(RUNTIME) +@Target(METHOD) +public @interface Trace { + + /** The operation name to set. By default it takes the method's name */ + String operationName() default ""; + + /** The resource name. By default it uses the same value as the operation name */ + String resourceName() default ""; + + /** Set whether to measure a trace. By default traces are not measured. */ + boolean measured() default false; + + /** Set whether to start a new trace. By default it continues the current trace. */ + boolean noParent() default false; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/TraceConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/TraceConfig.java new file mode 100644 index 0000000000..52370cf695 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/TraceConfig.java @@ -0,0 +1,41 @@ +package datadog.trace.api; + +import java.util.List; +import java.util.Map; + +import datadog.trace.api.sampling.SamplingRule.SpanSamplingRule; +import datadog.trace.api.sampling.SamplingRule.TraceSamplingRule; + +/** Snapshot of dynamic configuration; valid for the duration of a trace. */ +public interface TraceConfig { + + boolean isRuntimeMetricsEnabled(); + + boolean isLogsInjectionEnabled(); + + boolean isDataStreamsEnabled(); + + Map getServiceMapping(); + + Map getRequestHeaderTags(); + + Map getResponseHeaderTags(); + + Map getBaggageMapping(); + + Double getTraceSampleRate(); + + /** + * Get the tracer sampler Span Sampling Rules. + * + * @return The tracer sampler Span Sampling Rules, or an empty collection if no rule is defined. + */ + List getSpanSamplingRules(); + + /** + * Get the tracer sampler Trace Sampling Rules. + * + * @return The tracer sampler Trace Sampling Rules, or an empty collection if no rule is defined. + */ + List getTraceSamplingRules(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java b/features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java new file mode 100644 index 0000000000..192978cc38 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java @@ -0,0 +1,50 @@ +package datadog.trace.api; + +import java.util.Locale; + +/** Trace propagation styles for injecting and extracting trace propagation headers. */ +public enum TracePropagationStyle { + // Datadog context propagation style + DATADOG, + // B3 single header context propagation style + // https://github.com/openzipkin/b3-propagation/tree/master#single-header + B3SINGLE, + // B3 multi header context propagation style + // https://github.com/openzipkin/b3-propagation/tree/master#multiple-headers + B3MULTI, + // Haystack context propagation style + // https://github.com/ExpediaDotCom/haystack + HAYSTACK, + // Amazon X-Ray context propagation style + // https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader + XRAY, + // W3C trace context propagation style + // https://www.w3.org/TR/trace-context-1/ + TRACECONTEXT, + // None does not extract or inject + NONE; + + public static TracePropagationStyle valueOfDisplayName(String displayName) { + String convertedName = displayName.toUpperCase().replace(' ', '_'); + // Another name for B3 for cross tracer compatibility + switch (convertedName) { + case "B3_SINGLE_HEADER": + return B3SINGLE; + case "B3": + return B3MULTI; + default: + return TracePropagationStyle.valueOf(convertedName); + } + } + + private String displayName; + + @Override + public String toString() { + String string = displayName; + if (displayName == null) { + string = displayName = name().toLowerCase(Locale.ROOT).replace('_', ' '); + } + return string; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Tracer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/Tracer.java new file mode 100644 index 0000000000..d46c89f8cc --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/Tracer.java @@ -0,0 +1,24 @@ +package datadog.trace.api; + +import datadog.trace.api.interceptor.TraceInterceptor; + +/** A class with Datadog tracer features. */ +public interface Tracer { + + /** Get the trace id of the active trace. Returns 0 if there is no active trace. */ + String getTraceId(); + + /** + * Get the span id of the active span of the active trace. Returns 0 if there is no active trace. + */ + String getSpanId(); + + /** + * Add a new interceptor to the tracer. Interceptors with duplicate priority to existing ones are + * ignored. + * + * @param traceInterceptor + * @return false if an interceptor with same priority exists. + */ + boolean addTraceInterceptor(TraceInterceptor traceInterceptor); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/UserEventTrackingMode.java b/features/dd-trace-core/src/main/java/datadog/trace/api/UserEventTrackingMode.java new file mode 100644 index 0000000000..cb21c257e0 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/UserEventTrackingMode.java @@ -0,0 +1,17 @@ +package datadog.trace.api; + +public enum UserEventTrackingMode { + DISABLED, + SAFE, + EXTENDED; + + public static UserEventTrackingMode fromString(String s) { + if ("true".equalsIgnoreCase(s) || "1".equals(s) || "safe".equalsIgnoreCase(s)) { + return SAFE; + } + if ("extended".equalsIgnoreCase(s)) { + return EXTENDED; + } + return DISABLED; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/WellKnownTags.java b/features/dd-trace-core/src/main/java/datadog/trace/api/WellKnownTags.java new file mode 100644 index 0000000000..f01e8d154e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/WellKnownTags.java @@ -0,0 +1,52 @@ +package datadog.trace.api; + +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; + +public class WellKnownTags { + + private final UTF8BytesString runtimeId; + private final UTF8BytesString hostname; + private final UTF8BytesString env; + private final UTF8BytesString service; + private final UTF8BytesString version; + private final UTF8BytesString language; + + public WellKnownTags( + CharSequence runtimeId, + CharSequence hostname, + CharSequence env, + CharSequence service, + CharSequence version, + CharSequence language) { + this.runtimeId = UTF8BytesString.create(runtimeId); + this.hostname = UTF8BytesString.create(hostname); + this.env = UTF8BytesString.create(env); + this.service = UTF8BytesString.create(service); + this.version = UTF8BytesString.create(version); + this.language = UTF8BytesString.create(language); + } + + public UTF8BytesString getRuntimeId() { + return runtimeId; + } + + public UTF8BytesString getHostname() { + return hostname; + } + + public UTF8BytesString getEnv() { + return env; + } + + public UTF8BytesString getService() { + return service; + } + + public UTF8BytesString getVersion() { + return version; + } + + public UTF8BytesString getLanguage() { + return language; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/WithGlobalTracer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/WithGlobalTracer.java new file mode 100644 index 0000000000..ae6354d5ee --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/WithGlobalTracer.java @@ -0,0 +1,42 @@ +package datadog.trace.api; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; + +/** + * Internal API for registering callbacks that will execute as soon as there is a global tracer + * installed, or immediately if the global tracer is already installed. + * + *

The code is separate from {@link GlobalTracer} to not expose this mechanism to end users. It + * is also based on the assumption that registering callbacks is a rare thing, and as of this + * writing the only code doing it is the various MDC log injection instrumentations. + */ +public class WithGlobalTracer { + private static final Logger log = LoggerFactory.getLogger(WithGlobalTracer.class); + + private WithGlobalTracer() {} + + /** + * Register a callback to be run when the global tracer is installed, or execute it right now if + * the tracer is already installed. + */ + public static void registerOrExecute(final Callback callback) { + GlobalTracer.registerInstallationCallback( + new GlobalTracer.Callback() { + @Override + public void installed(Tracer tracer) { + if (tracer instanceof TracerAPI) { + callback.withTracer((TracerAPI) tracer); + } else { + log.warn("Unsupported tracer type {}", tracer.getClass().getName()); + } + } + }); + } + + public interface Callback { + void withTracer(TracerAPI tracer); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/CHMCache.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/CHMCache.java new file mode 100644 index 0000000000..7ac2dd9875 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/CHMCache.java @@ -0,0 +1,43 @@ +package datadog.trace.api.cache; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiConsumer; +import java.util.function.Function; + +final class CHMCache implements DDCache { + + private final ConcurrentHashMap chm; + + public CHMCache(final int initialCapacity) { + this.chm = new ConcurrentHashMap<>(initialCapacity); + } + + @Override + public V computeIfAbsent(K key, Function producer) { + if (null == key) { + return null; + } + V value = chm.get(key); + if (null == value) { + value = producer.apply(key); + V winner = chm.putIfAbsent(key, value); + if (null != winner) { + value = winner; + } + } + return value; + } + + @Override + public void clear() { + chm.clear(); + } + + @Override + public void visit(BiConsumer consumer) { + for (Map.Entry e : chm.entrySet()) { + consumer.accept(e.getKey(), e.getValue()); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCache.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCache.java new file mode 100644 index 0000000000..d1cd802484 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCache.java @@ -0,0 +1,21 @@ +package datadog.trace.api.cache; + +import java.util.function.BiConsumer; +import java.util.function.Function; + +public interface DDCache { + /** + * Look up or create and store a value in the cache. + * + * @param key the key to look up + * @param producer how to create a cached value base on the key if the lookup fails + * @return the cached or created and stored value + */ + V computeIfAbsent(final K key, Function producer); + + /** Clear the cache. */ + void clear(); + + /** Visits elements currently in the cache; for debugging/triage purposes. */ + void visit(BiConsumer consumer); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCaches.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCaches.java new file mode 100644 index 0000000000..65d7b2f697 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCaches.java @@ -0,0 +1,85 @@ +package datadog.trace.api.cache; + +import java.util.function.ToIntFunction; + +public final class DDCaches { + + private DDCaches() {} + + /** + * Creates a cache which cannot grow beyond a fixed capacity. Useful for caching relationships + * between low cardinality but potentially unbounded keys with values, without risking using + * unbounded space. + * + *

When using immutable array keys prefer {@link #newFixedSizeArrayKeyCache(int)}. + * + * @param capacity the cache's fixed capacity + * @param the key type + * @param the value type + */ + public static DDCache newFixedSizeCache(final int capacity) { + return new FixedSizeCache.ObjectHash<>(capacity); + } + + /** + * Specialized fixed-size cache that uses {@link System#identityHashCode} for key hashing and + * equality. + * + * @see #newFixedSizeCache(int) + */ + public static DDCache newFixedSizeIdentityCache(final int capacity) { + return new FixedSizeCache.IdentityHash<>(capacity); + } + + /** + * Specialized fixed-size cache that uses {@link java.util.Arrays} for key hashing and equality. + * + * @see #newFixedSizeCache(int) + */ + public static DDCache newFixedSizeArrayKeyCache(final int capacity) { + return new FixedSizeCache.ArrayHash<>(capacity); + } + + /** + * Specialized fixed-size cache whose keys are weakly referenced. Uses {@link + * System#identityHashCode} for key hashing and equality. + * + * @see #newFixedSizeCache(int) + */ + public static DDCache newFixedSizeWeakKeyCache(final int capacity) { + return new FixedSizeWeakKeyCache<>(capacity); + } + + /** + * Specialized fixed-size cache which also tracks the overall weight of cached elements. + * + * @param capacity the cache's fixed capacity + * @param weigher the weighing function used to weigh elements in the cache + * @param maxWeight the maximum combined weight of all elements in the cache + * @param the key type + * @param the value type + */ + public static DDCache newFixedSizeWeightedCache( + final int capacity, final ToIntFunction weigher, final int maxWeight) { + return new FixedSizeWeightedCache<>(capacity, weigher, maxWeight); + } + + /** + * Creates a memoization of an association. Useful for creating an association between an + * implicitly bounded set of keys and values, where the nature of the keys prevents unbounded + * space usage. + * + * @param initialCapacity the initial capacity. To avoid resizing, should be larger than the total + * number of keys. + * @param the key type + * @param the value type + * @return the value associated with the key + */ + public static DDCache newUnboundedCache(final int initialCapacity) { + return new CHMCache<>(initialCapacity); + } + + public static DDPartialKeyCache newFixedSizePartialKeyCache(final int capacity) { + return new FixedSizePartialKeyCache<>(capacity); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDPartialKeyCache.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDPartialKeyCache.java new file mode 100644 index 0000000000..68eb730bb7 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDPartialKeyCache.java @@ -0,0 +1,49 @@ +package datadog.trace.api.cache; + +/** + * Cache that can work on parts of a key to look up a value. + * + *

An example would be looking up values from a substring of a string instead of first creating a + * string to do the lookup. + * + * @param key type + * @param value type + */ +public interface DDPartialKeyCache { + /** + * Look up or create and store a value in the cache. + * + * @param key the key to look up + * @param m extra parameter that is passed along with the key + * @param n extra parameter that is passed along with the key + * @param hasher how to compute the hash using key, m, and n + * @param comparator how to compare the key, m, n, and value + * @param producer how to create a cached value base on the key, m, and n if the lookup fails + * @return the cached or created and stored value + */ + V computeIfAbsent( + final K key, + int m, + int n, + Hasher hasher, + Comparator comparator, + Producer producer); + + /** Clear the cache. */ + void clear(); + + @FunctionalInterface + interface Hasher { + int apply(T t, int m, int n); + } + + @FunctionalInterface + interface Comparator { + boolean test(T t, int m, int n, U u); + } + + @FunctionalInterface + interface Producer { + R apply(T t, int h, int m, int n); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeCache.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeCache.java new file mode 100644 index 0000000000..98e0822d83 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeCache.java @@ -0,0 +1,175 @@ +package datadog.trace.api.cache; + +import java.util.Arrays; +import java.util.function.BiConsumer; +import java.util.function.Function; + +import datadog.trace.api.Pair; + +/** + * This is a fixed size cache that only has one operation computeIfAbsent, that is used + * to retrieve, or store and compute the cached value. + * + *

If there is a hash collision, the cache uses double hashing two more times to try to find a + * match or an unused slot. + * + *

The cache is thread safe, and assumes that the Producer passed into + * computeIfAbsent is idempotent, or otherwise you might not get back the value you expect + * from a cache lookup. + * + * @param key type + * @param value type + */ +abstract class FixedSizeCache implements DDCache { + + static final int MAXIMUM_CAPACITY = 1 << 30; + + private final int mask; + // This is a cache, so there is no need for volatile, atomics or synchronized. + // All race conditions here are benign since you always read or write a full + // Element that can not be modified, and eventually other threads will see it + // or write the same information at that position, or other information in the + // case of a collision. + private final Pair[] elements; + + /** + * Creates a FixedSizeCache that can hold up to capacity elements, if + * the key hash function has perfect spread. + * + * @param capacity the maximum number of elements that the cache can hold + */ + @SuppressWarnings("unchecked") + FixedSizeCache(int capacity) { + int size = calculateSize(capacity); + this.elements = new Pair[size]; + this.mask = size - 1; + } + + static int calculateSize(int capacity) { + if (capacity <= 0) { + throw new IllegalArgumentException("Cache capacity must be > 0"); + } + if (capacity > MAXIMUM_CAPACITY) { + capacity = MAXIMUM_CAPACITY; + } + // compute a power of two size for the given capacity + int n = -1 >>> Integer.numberOfLeadingZeros(capacity - 1); + return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; + } + + /** + * Look up or create and store a value in the cache. + * + *

If there is a hash collision, the method uses double hashing two more times to try to find a + * match or an unused slot. If there is no match or empty slot, the first slot is overwritten. + * + * @param key the key to look up + * @param producer how to create a cached value base on the key if the lookup fails + * @return the cached or created and stored value + */ + @Override + public final V computeIfAbsent(K key, Function producer) { + if (key == null) { + return null; + } + + int h = hash(key); + int firstPos = h & mask; + V value; + + // try to find a slot or a match 3 times + for (int i = 1; true; i++) { + int pos = h & mask; + Pair current = elements[pos]; + if (current == null) { + // we found an empty slot, so store the value there + value = produceAndStoreValue(key, producer, pos); + break; + } else if (equals(key, current)) { + // we found a cached key, so use that value + value = current.getRight(); + break; + } else if (i == 3) { + // all 3 slots have been taken, so overwrite the first one + value = produceAndStoreValue(key, producer, firstPos); + break; + } + // slot was occupied by someone else, so try another slot + h = rehash(h); + } + return value; + } + + @Override + public void clear() { + Arrays.fill(elements, null); + } + + @Override + public void visit(BiConsumer consumer) { + for (Pair e : elements) { + if (null != e) { + consumer.accept(e.getLeft(), e.getRight()); + } + } + } + + abstract int hash(K key); + + abstract boolean equals(K key, Pair current); + + private V produceAndStoreValue(K key, Function producer, int pos) { + V value = producer.apply(key); + elements[pos] = Pair.of(key, value); + return value; + } + + static int rehash(int v) { + int h = v * 0x9e3775cd; + h = Integer.reverseBytes(h); + return h * 0x9e3775cd; + } + + static final class ObjectHash extends FixedSizeCache { + ObjectHash(int capacity) { + super(capacity); + } + + int hash(K key) { + return key.hashCode(); + } + + boolean equals(K key, Pair current) { + return key.equals(current.getLeft()); + } + } + + static final class IdentityHash extends FixedSizeCache { + IdentityHash(int capacity) { + super(capacity); + } + + int hash(K key) { + int hash = System.identityHashCode(key); + return hash - (hash << 7); // multiply by -127 to improve identityHashCode spread + } + + boolean equals(K key, Pair current) { + return key == current.getLeft(); + } + } + + static final class ArrayHash extends FixedSizeCache { + ArrayHash(int capacity) { + super(capacity); + } + + int hash(K[] key) { + return Arrays.hashCode(key); + } + + boolean equals(K[] key, Pair current) { + return Arrays.equals(key, current.getLeft()); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizePartialKeyCache.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizePartialKeyCache.java new file mode 100644 index 0000000000..d10827d87d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizePartialKeyCache.java @@ -0,0 +1,123 @@ +package datadog.trace.api.cache; + +import static datadog.trace.api.cache.FixedSizeCache.calculateSize; +import static datadog.trace.api.cache.FixedSizeCache.rehash; + +import androidx.annotation.Nullable; + +import java.util.Arrays; + +/** + * This is a fixed size cache that only has one operation computeIfAbsent, that is used + * to retrieve, or store and compute the cached value. + * + *

If there is a hash collision, the cache uses double hashing two more times to try to find a + * match or an unused slot. + * + *

The cache is thread safe, and assumes that the Producer passed into + * computeIfAbsent is idempotent, or otherwise you might not get back the value you expect + * from a cache lookup. + * + * @param key type + * @param value type + */ +final class FixedSizePartialKeyCache implements DDPartialKeyCache { + + private final int mask; + // This is a cache, so there is no need for volatile, atomics or synchronized. + // All race conditions here are benign since you always read or write a full + // Element that can not be modified, and eventually other threads will see it + // or write the same information at that position, or other information in the + // case of a collision. + private final HVElement[] elements; + + /** + * Creates a FixedSizePartialKeyCache that can hold up to capacity + * elements, if the key hash function has perfect spread. + * + * @param capacity the maximum number of elements that the cache can hold + */ + @SuppressWarnings("unchecked") + FixedSizePartialKeyCache(int capacity) { + int size = calculateSize(capacity); + this.elements = new HVElement[size]; + this.mask = size - 1; + } + + /** + * Look up or create and store a value in the cache. + * + *

If there is a hash collision, the method uses double hashing two more times to try to find a + * match or an unused slot. If there is no match or empty slot, the first slot is overwritten. + * + * @param key the key to look up + * @param m extra parameter that is passed along with the key + * @param n extra parameter that is passed along with the key + * @param hasher how to compute the hash using key, m, and n + * @param comparator how to compare the key, m, n, and value + * @param producer how to create a cached value base on the key, m, and n if the lookup fails + * @return the cached or created and stored value + */ + @Override + public V computeIfAbsent( + K key, + int m, + int n, + Hasher hasher, + Comparator comparator, + Producer producer) { + if (key == null) { + return null; + } + + int hash = hasher.apply(key, m, n); + + int h = hash; + int firstPos = h & mask; + V value; + + // try to find a slot or a match 3 times + for (int i = 1; true; i++) { + int pos = h & mask; + HVElement current = elements[pos]; + if (current == null) { + // we found an empty slot, so store the value there + value = produceAndStoreValue(producer, hash, key, m, n, pos); + break; + } else if (hash == current.hash && comparator.test(key, m, n, current.value)) { + // we found a cached key, so use that value + value = current.value; + break; + } else if (i == 3) { + // all 3 slots have been taken, so overwrite the first one + value = produceAndStoreValue(producer, hash, key, m, n, firstPos); + break; + } + // slot was occupied by someone else, so try another slot + h = rehash(h); + } + return value; + } + + @Override + public void clear() { + Arrays.fill(elements, null); + } + + private V produceAndStoreValue( + Producer producer, int hash, K key, int m, int n, int pos) { + V value = producer.apply(key, hash, m, n); + elements[pos] = new HVElement<>(hash, value); + return value; + } + + static final class HVElement { + final int hash; + final U value; + + HVElement(int hash, @Nullable U value) { + this.hash = hash; + this.value = value; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeakKeyCache.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeakKeyCache.java new file mode 100644 index 0000000000..e9b99d204a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeakKeyCache.java @@ -0,0 +1,129 @@ +package datadog.trace.api.cache; + +import static datadog.trace.api.cache.FixedSizeCache.calculateSize; +import static datadog.trace.api.cache.FixedSizeCache.rehash; + +import androidx.annotation.Nullable; + +import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.function.BiConsumer; +import java.util.function.Function; + +/** + * This is a fixed size cache that only has one operation computeIfAbsent, that is used + * to retrieve, or store and compute the cached value. Keys are weakly referenced and the cache uses + * {@link System#identityHashCode} for key hashing and equality. + * + *

If there is a hash collision, the cache uses double hashing two more times to try to find a + * match or an unused slot. Slots whose keys have been garbage collected are considered unused. + * + *

The cache is thread safe, and assumes that the Producer passed into + * computeIfAbsent is idempotent, or otherwise you might not get back the value you expect + * from a cache lookup. + * + * @param key type + * @param value type + */ +final class FixedSizeWeakKeyCache implements DDCache { + + private final int mask; + // This is a cache, so there is no need for volatile, atomics or synchronized. + // All race conditions here are benign since you always read or write a full + // Element that can not be modified, and eventually other threads will see it + // or write the same information at that position, or other information in the + // case of a collision. + private final WeakPair[] elements; + + /** + * Creates a FixedSizeWeakKeyCache that can hold up to capacity + * elements, if the key hash function has perfect spread. + * + * @param capacity the maximum number of elements that the cache can hold + */ + @SuppressWarnings("unchecked") + FixedSizeWeakKeyCache(int capacity) { + int size = calculateSize(capacity); + this.elements = new WeakPair[size]; + this.mask = size - 1; + } + + /** + * Look up or create and store a value in the cache. + * + *

If there is a hash collision, the method uses double hashing two more times to try to find a + * match or an unused slot. If there is no match or empty slot, the first slot is overwritten. + * + * @param key the key to look up + * @param producer how to create a cached value base on the key if the lookup fails + * @return the cached or created and stored value + */ + @Override + public final V computeIfAbsent(K key, Function producer) { + if (key == null) { + return null; + } + + int hash = System.identityHashCode(key); + + int h = hash - (hash << 7); // multiply by -127 to improve identityHashCode spread + int firstPos = h & mask; + V value; + + // try to find a slot or a match 3 times + for (int i = 1; true; i++) { + int pos = h & mask; + WeakPair current = elements[pos]; + if (current == null || null == current.get()) { + // we found an empty slot, so store the value there + value = produceAndStoreValue(producer, hash, key, pos); + break; + } else if (hash == current.hash && key.equals(current.get())) { + // we found a cached key, so use that value + value = current.value; + break; + } else if (i == 3) { + // all 3 slots have been taken, so overwrite the first one + value = produceAndStoreValue(producer, hash, key, firstPos); + break; + } + // slot was occupied by someone else, so try another slot + h = rehash(h); + } + return value; + } + + @Override + public void clear() { + Arrays.fill(elements, null); + } + + @Override + public void visit(BiConsumer consumer) { + for (WeakPair e : elements) { + if (null != e) { + K key = e.get(); + if (null != key) { + consumer.accept(key, e.value); + } + } + } + } + + private V produceAndStoreValue(Function producer, int hash, K key, int pos) { + V value = producer.apply(key); + elements[pos] = new WeakPair<>(key, hash, value); + return value; + } + + static final class WeakPair extends WeakReference { + final int hash; + final V value; + + WeakPair(K key, int hash, @Nullable V value) { + super(key); + this.hash = hash; + this.value = value; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeightedCache.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeightedCache.java new file mode 100644 index 0000000000..85295b39bb --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeightedCache.java @@ -0,0 +1,192 @@ +package datadog.trace.api.cache; + +import static datadog.trace.api.cache.FixedSizeCache.calculateSize; +import static datadog.trace.api.cache.FixedSizeCache.rehash; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.ToIntFunction; + +/** + * This is a fixed size cache that only has one operation computeIfAbsent, that is used + * to retrieve, or store and compute the cached value. + * + *

If there is a hash collision, the cache uses double hashing two more times to try to find a + * match or an unused slot. + * + *

The cache is thread safe, and assumes that the Producer passed into + * computeIfAbsent is idempotent, or otherwise you might not get back the value you expect + * from a cache lookup. + * + *

The cache tracks the total weight of elements inside it, based on the weigher + * function. Elements will be evicted to maintain the total weight below the configured limit. + * + * @param key type + * @param value type + */ +final class FixedSizeWeightedCache implements DDCache { + + private final int mask; + // This is a cache, so there is no need for volatile, atomics or synchronized. + // All race conditions here are benign since you always read or write a full + // Element that can not be modified, and eventually other threads will see it + // or write the same information at that position, or other information in the + // case of a collision. + private final Weighed[] elements; + private final ToIntFunction weigher; + private final int totalWeightLimit; + private final int totalWeightTarget; + + // only used as a hint, so it doesn't need to be 100% accurate + private volatile int totalWeightEstimate; + + private static final AtomicIntegerFieldUpdater + TOTAL_WEIGHT_ESTIMATE_UPDATER = + AtomicIntegerFieldUpdater.newUpdater(FixedSizeWeightedCache.class, "totalWeightEstimate"); + + private static final Weighed EVICTED = new Weighed<>(null, null, 0); + + /** + * Creates a FixedSizeWeightedCache that can hold up to capacity + * elements, if the key hash function has perfect spread. + * + * @param capacity the maximum number of elements that the cache can hold + * @param weigher the function used to weigh elements before they are cached + * @param totalWeightLimit the maximum combined weight of cached elements + */ + @SuppressWarnings("unchecked") + FixedSizeWeightedCache(int capacity, ToIntFunction weigher, int totalWeightLimit) { + int size = calculateSize(capacity); + this.elements = new Weighed[size]; + this.mask = size - 1; + this.weigher = weigher; + this.totalWeightLimit = totalWeightLimit; + this.totalWeightTarget = (int) (0.5 + totalWeightLimit * 0.9); // target 90% of limit + } + + /** + * Look up or create and store a value in the cache. + * + *

If there is a hash collision, the method uses double hashing two more times to try to find a + * match or an unused slot. If there is no match or empty slot, the first slot is overwritten. + * + * @param key the key to look up + * @param producer how to create a cached value base on the key if the lookup fails + * @return the cached or created and stored value + */ + @Override + public V computeIfAbsent(K key, Function producer) { + if (key == null) { + return null; + } + + int h = key.hashCode(); + int oldPos = h & mask; + Weighed old = elements[oldPos]; + V value; + + int pos = oldPos; + Weighed current = old; + + // try to find a slot or a match 3 times + for (int i = 1; true; i++) { + if (current == null) { + // we found an empty slot, so store the value there + value = produceAndStoreValue(key, producer, pos, 0); + break; + } else if (current == EVICTED) { + // use evicted slot instead of first if we can't find a match + if (old != EVICTED) { + oldPos = pos; + old = current; + } + // continue search in case our key appears in a later slot + } else if (key.equals(current.key)) { + // we found a cached key, so use that value + value = current.value; + break; + } + if (i == 3) { + // we've searched all 3 slots, overwrite the first/evicted slot + value = produceAndStoreValue(key, producer, oldPos, old.weight); + break; + } + // try another slot + h = rehash(h); + pos = h & mask; + current = elements[pos]; + } + return value; + } + + @Override + public void clear() { + Arrays.fill(elements, null); + totalWeightEstimate = 0; + } + + @Override + public void visit(BiConsumer consumer) { + for (Weighed e : elements) { + if (null != e) { + consumer.accept(e.key, e.value); + } + } + } + + private V produceAndStoreValue(K key, Function producer, int pos, int oldWeight) { + V value = producer.apply(key); + int weight = weigher.applyAsInt(value); + if (weight > totalWeightLimit) { + return value; // too big to cache + } + int oldEstimate; + while ((oldEstimate = totalWeightEstimate) <= totalWeightLimit) { + int newEstimate = oldEstimate + (weight - oldWeight); // estimate may go up or down + if (TOTAL_WEIGHT_ESTIMATE_UPDATER.compareAndSet(this, oldEstimate, newEstimate)) { + elements[pos] = new Weighed<>(key, value, weight); + if (newEstimate > totalWeightLimit) { + // totalWeightEstimate is now above the limit, making the cache read-only to others. + // As we sweep the cache we evict elements to move the estimate back below the limit. + // When we publish the reduced estimate, the cache becomes writable again. + beginSweep(pos, weight); + } + break; + } + } + return value; + } + + /** + * Sweeps the cache re-calculating the total weight, evicting any elements that would tip it over. + */ + private void beginSweep(int startPos, int startWeight) { + // sweep forward from updated position, wrapping round to cover all other slots in the cache + int totalWeight = startWeight; + for (int i = (startPos + 1) & mask; i != startPos; i = (i + 1) & mask) { + Weighed element = elements[i]; + if (element != null && element != EVICTED) { + totalWeight += element.weight; + if (totalWeight > totalWeightTarget) { + totalWeight -= element.weight; + elements[i] = EVICTED; + } + } + } + totalWeightEstimate = totalWeight; + } + + static final class Weighed { + final K key; + final V value; + final int weight; + + Weighed(K key, V value, int weight) { + this.key = key; + this.value = value; + this.weight = weight; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/QualifiedClassNameCache.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/QualifiedClassNameCache.java new file mode 100644 index 0000000000..715eec5d85 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/QualifiedClassNameCache.java @@ -0,0 +1,61 @@ +package datadog.trace.api.cache; + +import java.util.function.Function; + +import datadog.trace.api.Functions; + +public final class QualifiedClassNameCache extends ClassValue { + + private final Function, CharSequence> formatter; + private final Functions.Join joiner; + private final int leafSize; + + public QualifiedClassNameCache( + Function, CharSequence> formatter, Functions.Join joiner) { + this(formatter, joiner, 16); + } + + public QualifiedClassNameCache( + Function, CharSequence> formatter, Functions.Join joiner, int leafSize) { + this.formatter = formatter; + this.joiner = joiner; + this.leafSize = leafSize; + } + + @Override + protected Leaf computeValue(Class type) { + return new Leaf(formatter.apply(type), joiner, leafSize); + } + + static final class Leaf { + + private final CharSequence name; + + private final DDCache cache; + private final Function joiner; + + private Leaf(CharSequence name, Functions.Join joiner, int leafSize) { + this.name = name; + // the class provides a natural bound on the number of elements + // (e.g. the number of methods) + this.cache = DDCaches.newUnboundedCache(leafSize); + this.joiner = joiner.curry(name); + } + + CharSequence get(CharSequence name) { + return cache.computeIfAbsent(name, joiner); + } + + CharSequence getName() { + return name; + } + } + + public CharSequence getClassName(Class klass) { + return get(klass).getName(); + } + + public CharSequence getQualifiedName(Class klass, String qualifier) { + return get(klass).get(qualifier); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/RadixTreeCache.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/RadixTreeCache.java new file mode 100644 index 0000000000..bb9176b422 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/RadixTreeCache.java @@ -0,0 +1,72 @@ +package datadog.trace.api.cache; + +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.function.IntFunction; + +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; + +/** Sparse cache of values associated with a small integer */ +public final class RadixTreeCache { + private static final IntFunction TO_STRING = + value -> UTF8BytesString.create(Integer.toString(value)); + + public static final int UNSET_STATUS = 0; + // should cover range [0, 512) to cover all standard HTTP statuses + // 16 pages of 32 should keep the tree sparse with typical pages + // covering ranges [192, 224), [288, 320), [384, 416), [480, 512) + public static final RadixTreeCache HTTP_STATUSES = + new RadixTreeCache<>( + 16, 32, TO_STRING, 200, 201, 301, 307, 400, 401, 403, 404, 500, 502, 503); + + public static final int UNSET_PORT = 0; + // should cover range [0, 2^16) + public static final RadixTreeCache PORTS = + new RadixTreeCache<>(256, 256, Integer::valueOf, 80, 443, 8080); + + private final int level1; + private final int level2; + private final int shift; + private final int mask; + + private final AtomicReferenceArray tree; + private final IntFunction mapper; + + public RadixTreeCache(int level1, int level2, IntFunction mapper, int... commonValues) { + this.tree = new AtomicReferenceArray<>(level1); + this.mapper = mapper; + this.level1 = level1; + this.level2 = level2; + this.mask = level2 - 1; + this.shift = Integer.bitCount(mask); + for (int commonValue : commonValues) { + get(commonValue); + } + } + + public T get(int primitive) { + int prefix = primitive >>> shift; + // bounds check both ends with one check + if (prefix >= level1) { + return mapper.apply(primitive); + } + return computeIfAbsent(prefix, primitive); + } + + @SuppressWarnings("unchecked") + private T computeIfAbsent(int prefix, int primitive) { + Object[] page = tree.get(prefix); + if (null == page) { + page = new Object[level2]; + if (!tree.compareAndSet(prefix, null, page)) { + page = tree.get(prefix); + } + } + // it's safe to race here + int suffix = primitive & mask; + Object cached = page[suffix]; + if (cached == null) { + cached = page[suffix] = mapper.apply(primitive); + } + return (T) cached; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIConstants.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIConstants.java new file mode 100644 index 0000000000..76cec93abb --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIConstants.java @@ -0,0 +1,7 @@ +package datadog.trace.api.civisibility; + +public interface CIConstants { + String TEST_PASS = "pass"; + String TEST_FAIL = "fail"; + String TEST_SKIP = "skip"; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIVisibility.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIVisibility.java new file mode 100644 index 0000000000..79dce10d42 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIVisibility.java @@ -0,0 +1,50 @@ +package datadog.trace.api.civisibility; + +import androidx.annotation.Nullable; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import datadog.trace.api.civisibility.noop.NoOpDDTestSession; + +public class CIVisibility { + + private static volatile SessionFactory SESSION_FACTORY = + (projectName, projectRoot, component, startTime) -> NoOpDDTestSession.INSTANCE; + + /** + * This a hook for injecting SessionFactory implementation. It should only be used internally by + * the tracer logic + * + * @param sessionFactory Session factory instance + */ + public static void registerSessionFactory(SessionFactory sessionFactory) { + SESSION_FACTORY = sessionFactory; + } + + /** + * Marks the start of a new test session. + * + * @param projectName The name of the tested project + * @param component The name of the test component (typically corresponds to the name of the + * testing framework used). This will be added as prefix to reported span names + * @param startTime Optional start time in microseconds. If {@code null} is supplied, current time + * will be assumed + * @return Handle to the test session instance + */ + public static DDTestSession startSession( + String projectName, String component, @Nullable Long startTime) { + Path projectRoot = Paths.get("").toAbsolutePath(); + return SESSION_FACTORY.startSession(projectName, projectRoot, component, startTime); + } + + public static DDTestSession startSession( + String projectName, Path projectRoot, String component, @Nullable Long startTime) { + return SESSION_FACTORY.startSession(projectName, projectRoot, component, startTime); + } + + public interface SessionFactory { + DDTestSession startSession( + String projectName, Path projectRoot, String component, Long startTime); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTest.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTest.java new file mode 100644 index 0000000000..978810d237 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTest.java @@ -0,0 +1,53 @@ +package datadog.trace.api.civisibility; + +import androidx.annotation.Nullable; + +/** + * This interface represent an individual test case. Typically, a test case corresponds to a method + * that contains the test logic. + */ +public interface DDTest { + + /** + * Adds an arbitrary tag to the test + * + * @param key The name of the tag + * @param value The value of the tag + */ + void setTag(String key, Object value); + + /** + * Marks the test as failed. + * + *

This does not imply the end of test execution, so {@link #end(Long)} method has to be + * invoked at some point after this one. + * + * @param error Optional exception that caused the test to fail + */ + void setErrorInfo(@Nullable Throwable error); + + /** + * Marks the test as skipped. + * + *

This does not imply the end of test execution, so {@link #end(Long)} method has to be + * invoked at some point after this one. + * + * @param skipReason Optional reason for skipping the test + */ + void setSkipReason(@Nullable String skipReason); + + /** + * Marks the end of test execution. + * + *

Unless either {@link #setErrorInfo(Throwable)} or {@link #setSkipReason(String)} were + * invoked prior to calling this method, the test is assumed to have finished successfully. + * + *

The method must be called once for each test instance. + * + *

The call has to be made in the same thread where the test was started. + * + * @param endTime Optional finish time in microseconds. If {@code null} is supplied, current time + * will be assumed + */ + void end(@Nullable Long endTime); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestModule.java new file mode 100644 index 0000000000..d333924753 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestModule.java @@ -0,0 +1,91 @@ +package datadog.trace.api.civisibility; + +import androidx.annotation.Nullable; + +/** + * This interface represents a test module, i.e. a set of test suites. This typically corresponds to + * a project module (e.g. Maven submodule or Gradle subproject). + */ +public interface DDTestModule { + + /** + * Adds an arbitrary tag to the module + * + * @param key The name of the tag + * @param value The value of the tag + */ + void setTag(String key, Object value); + + /** + * Marks the module as failed. + * + *

This method should be used to signal a failure that is not related to a specific suite or a + * test case, but rather to the module as a whole (e.g. a failure in a setup/teardown logic that + * is executed once per module). If an individual test suite the module fails, there is no need to + * explicitly signal it to the module object: the status of the module will reflect individual + * suite failures automatically. + * + *

This does not imply the end of module execution, so {@link #end(Long)} method has to be + * invoked at some point after this one. + * + * @param error Optional exception that caused the module to fail + */ + void setErrorInfo(Throwable error); + + /** + * Marks the module as skipped. + * + *

This does not imply the end of module execution, so {@link #end(Long)} method has to be + * invoked at some point after this one. + * + * @param skipReason Optional reason for skipping the module + */ + void setSkipReason(String skipReason); + + /** + * Marks the end of module execution. + * + *

Unless either {@link #setErrorInfo(Throwable)} or {@link #setSkipReason(String)} were + * invoked prior to calling this method, the status of the module will be calculated based on the + * statuses of individual test suites that were executed in scope of the module. + * + *

The method must be called once for each module instance. + * + *

The call does not have to be made in the same thread where the module was started. + * + * @param endTime Optional finish time in microseconds. If {@code null} is supplied, current time + * will be assumed + */ + void end(@Nullable Long endTime); + + /** + * Marks the start of a new test suite in the module. + * + * @param testSuiteName The name of the suite + * @param testClass Optional class that corresponds to the test suite. + * @param startTime Optional start time in microseconds. If {@code null} is supplied, current time + * will be assumed + * @return Handle to the test suite instance + */ + default DDTestSuite testSuiteStart( + String testSuiteName, @Nullable Class testClass, @Nullable Long startTime) { + return testSuiteStart(testSuiteName, testClass, startTime, false); + } + + /** + * Marks the start of a new test suite in the module. + * + * @param testSuiteName The name of the suite + * @param testClass Optional class that corresponds to the test suite. + * @param startTime Optional start time in microseconds. If {@code null} is supplied, current time + * will be assumed + * @param parallelized Whether test cases from this suite will be executed concurrently in + * multiple threads + * @return Handle to the test suite instance + */ + DDTestSuite testSuiteStart( + String testSuiteName, + @Nullable Class testClass, + @Nullable Long startTime, + boolean parallelized); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSession.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSession.java new file mode 100644 index 0000000000..f73960e91a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSession.java @@ -0,0 +1,70 @@ +package datadog.trace.api.civisibility; + +import androidx.annotation.Nullable; + +/** + * This interface represents a test session. Test session usually corresponds to execution of a + * single test command issued by a user or by a CI script + */ +public interface DDTestSession { + + /** + * Adds an arbitrary tag to the session + * + * @param key The name of the tag + * @param value The value of the tag + */ + void setTag(String key, Object value); + + /** + * Marks the session as failed. + * + *

This method should be used to signal a failure that is not related to a specific module or a + * test suite, but rather to the tests execution as a whole (e.g. a failure in a setup/teardown + * logic that is executed once for the entire project). If an individual module in the project + * fails, there is no need to explicitly signal it to the session object: the status of the + * session will reflect individual module failures automatically. + * + *

This does not imply the end of tests execution, so {@link #end(Long)} method has to be + * invoked at some point after this one. + * + * @param error Optional exception that caused the execution to fail + */ + void setErrorInfo(Throwable error); + + /** + * Marks the entire execution as skipped. + * + *

This does not imply the end of tests execution, so {@link #end(Long)} method has to be + * invoked at some point after this one. + * + * @param skipReason Optional reason for skipping execution + */ + void setSkipReason(String skipReason); + + /** + * Marks the end of tests execution. + * + *

Unless either {@link #setErrorInfo(Throwable)} or {@link #setSkipReason(String)} were + * invoked prior to calling this method, the status of the execution will be calculated based on + * the statuses of individual modules that were run in scope of the session. + * + *

The method must be called once for each session instance. + * + *

The call does not have to be made in the same thread where the session was started. + * + * @param endTime Optional finish time in microseconds. If {@code null} is supplied, current time + * will be assumed + */ + void end(@Nullable Long endTime); + + /** + * Marks the start of a new module. + * + * @param moduleName The name of the module + * @param startTime Optional start time in microseconds. If {@code null} is supplied, current time + * will be assumed + * @return Handle to the module instance + */ + DDTestModule testModuleStart(String moduleName, @Nullable Long startTime); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSuite.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSuite.java new file mode 100644 index 0000000000..c309c181c6 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSuite.java @@ -0,0 +1,73 @@ +package datadog.trace.api.civisibility; + +import androidx.annotation.Nullable; + +import java.lang.reflect.Method; + +/** + * This interface represents a test suite, i.e. a set of related test cases. Typically, a test suite + * corresponds to a class that contains a number of test method + */ +public interface DDTestSuite { + + /** + * Adds an arbitrary tag to the suite + * + * @param key The name of the tag + * @param value The value of the tag + */ + void setTag(String key, Object value); + + /** + * Marks the suite as failed. + * + *

This method should be used to signal a failure that is not related to a specific test case, + * but rather to the suite as a whole (e.g. a failure in a setup/teardown method whose scope is + * entire suite). If an individual test case in the suite fails, there is no need to explicitly + * signal it to the suite object: the status of the suite will reflect individual test case + * failures automatically. + * + *

This does not imply the end of suite execution, so {@link #end(Long)} method has to be + * invoked at some point after this one. + * + * @param error Optional exception that caused the suite to fail + */ + void setErrorInfo(Throwable error); + + /** + * Marks the suite as skipped. + * + *

This does not imply the end of suite execution, so {@link #end(Long)} method has to be + * invoked at some point after this one. + * + * @param skipReason Optional reason for skipping the suite + */ + void setSkipReason(String skipReason); + + /** + * Marks the end of suite execution. + * + *

Unless either {@link #setErrorInfo(Throwable)} or {@link #setSkipReason(String)} were + * invoked prior to calling this method, the status of the suite will be calculated based on the + * statuses of individual test cases that were executed in scope of the suite. + * + *

The method must be called once for each suite instance. + * + *

The call has to be made in the same thread where the suite was started. + * + * @param endTime Optional finish time in microseconds. If {@code null} is supplied, current time + * will be assumed + */ + void end(@Nullable Long endTime); + + /** + * Marks the start of a new test case in the suite. + * + * @param testName The name of the test case + * @param testMethod Optional method that corresponds to the test case + * @param startTime Optional start time in microseconds. If {@code null} is supplied, current time + * will be assumed + * @return Handle to the test case instance + */ + DDTest testStart(String testName, @Nullable Method testMethod, @Nullable Long startTime); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/InstrumentationBridge.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/InstrumentationBridge.java new file mode 100644 index 0000000000..79fbbdb282 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/InstrumentationBridge.java @@ -0,0 +1,31 @@ +package datadog.trace.api.civisibility; + +import datadog.trace.api.civisibility.events.BuildEventsHandler; +import datadog.trace.api.civisibility.events.TestEventsHandler; + +public abstract class InstrumentationBridge { + + public static final String ITR_SKIP_REASON = "Skipped by Datadog Intelligent Test Runner"; + public static final String ITR_UNSKIPPABLE_TAG = "datadog_itr_unskippable"; + + private static volatile TestEventsHandler.Factory TEST_EVENTS_HANDLER_FACTORY; + private static volatile BuildEventsHandler.Factory BUILD_EVENTS_HANDLER_FACTORY; + + public static void registerTestEventsHandlerFactory( + TestEventsHandler.Factory testEventsHandlerFactory) { + TEST_EVENTS_HANDLER_FACTORY = testEventsHandlerFactory; + } + + public static TestEventsHandler createTestEventsHandler(String component) { + return TEST_EVENTS_HANDLER_FACTORY.create(component); + } + + public static void registerBuildEventsHandlerFactory( + BuildEventsHandler.Factory buildEventsHandlerFactory) { + BUILD_EVENTS_HANDLER_FACTORY = buildEventsHandlerFactory; + } + + public static BuildEventsHandler createBuildEventsHandler() { + return BUILD_EVENTS_HANDLER_FACTORY.create(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/Configurations.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/Configurations.java new file mode 100644 index 0000000000..529598236d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/Configurations.java @@ -0,0 +1,107 @@ +package datadog.trace.api.civisibility.config; + +import java.util.Map; +import java.util.Objects; + +public final class Configurations { + private final String osPlatform; + private final String osArchitecture; + private final String osVersion; + private final String runtimeName; + private final String runtimeVersion; + private final String runtimeVendor; + private final String runtimeArchitecture; + private final String testBundle; + private final Map custom; + + public Configurations( + String osPlatform, + String osArchitecture, + String osVersion, + String runtimeName, + String runtimeVersion, + String runtimeVendor, + String runtimeArchitecture, + String testBundle, + Map custom) { + this.osPlatform = osPlatform; + this.osArchitecture = osArchitecture; + this.osVersion = osVersion; + this.runtimeName = runtimeName; + this.runtimeVersion = runtimeVersion; + this.runtimeVendor = runtimeVendor; + this.runtimeArchitecture = runtimeArchitecture; + this.testBundle = testBundle; + this.custom = custom; + } + + public String getOsPlatform() { + return osPlatform; + } + + public String getOsArchitecture() { + return osArchitecture; + } + + public String getOsVersion() { + return osVersion; + } + + public String getRuntimeName() { + return runtimeName; + } + + public String getRuntimeVersion() { + return runtimeVersion; + } + + public String getRuntimeVendor() { + return runtimeVendor; + } + + public String getRuntimeArchitecture() { + return runtimeArchitecture; + } + + public String getTestBundle() { + return testBundle; + } + + public Map getCustom() { + return custom; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Configurations that = (Configurations) o; + return Objects.equals(osPlatform, that.osPlatform) + && Objects.equals(osArchitecture, that.osArchitecture) + && Objects.equals(osVersion, that.osVersion) + && Objects.equals(runtimeName, that.runtimeName) + && Objects.equals(runtimeVersion, that.runtimeVersion) + && Objects.equals(runtimeVendor, that.runtimeVendor) + && Objects.equals(runtimeArchitecture, that.runtimeArchitecture) + && Objects.equals(testBundle, that.testBundle) + && Objects.equals(custom, that.custom); + } + + @Override + public int hashCode() { + return Objects.hash( + osPlatform, + osArchitecture, + osVersion, + runtimeName, + runtimeVersion, + runtimeVendor, + runtimeArchitecture, + testBundle, + custom); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java new file mode 100644 index 0000000000..31d8a2a095 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java @@ -0,0 +1,98 @@ +package datadog.trace.api.civisibility.config; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public class ModuleExecutionSettings { + + public static final ModuleExecutionSettings EMPTY = + new ModuleExecutionSettings( + false, + false, + Collections.emptyMap(), + Collections.emptyMap(), + Collections.emptyList(), + Collections.emptyList()); + + private final boolean codeCoverageEnabled; + private final boolean itrEnabled; + private final Map systemProperties; + private final Map> skippableTestsByModule; + private final Collection flakyTests; + private final List coverageEnabledPackages; + + public ModuleExecutionSettings( + boolean codeCoverageEnabled, + boolean itrEnabled, + Map systemProperties, + Map> skippableTestsByModule, + Collection flakyTests, + List coverageEnabledPackages) { + this.codeCoverageEnabled = codeCoverageEnabled; + this.itrEnabled = itrEnabled; + this.systemProperties = systemProperties; + this.skippableTestsByModule = skippableTestsByModule; + this.flakyTests = flakyTests; + this.coverageEnabledPackages = coverageEnabledPackages; + } + + public boolean isCodeCoverageEnabled() { + return codeCoverageEnabled; + } + + public boolean isItrEnabled() { + return itrEnabled; + } + + public Map getSystemProperties() { + return systemProperties; + } + + public Map> getSkippableTestsByModule() { + return skippableTestsByModule; + } + + public Collection getFlakyTests() { + return flakyTests; + } + + public Collection getSkippableTests(String moduleName) { + return skippableTestsByModule.getOrDefault(moduleName, Collections.emptyList()); + } + + public Collection getFlakyTests(String moduleName) { + // backend does not store module info for flaky tests + return flakyTests; + } + + public List getCoverageEnabledPackages() { + return coverageEnabledPackages; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ModuleExecutionSettings that = (ModuleExecutionSettings) o; + return codeCoverageEnabled == that.codeCoverageEnabled + && itrEnabled == that.itrEnabled + && Objects.equals(systemProperties, that.systemProperties) + && Objects.equals(skippableTestsByModule, that.skippableTestsByModule) + && Objects.equals(flakyTests, that.flakyTests) + && Objects.equals(coverageEnabledPackages, that.coverageEnabledPackages); + } + + @Override + public int hashCode() { + return Objects.hash( + codeCoverageEnabled, + itrEnabled, + systemProperties, + skippableTestsByModule, + flakyTests, + coverageEnabledPackages); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/TestIdentifier.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/TestIdentifier.java new file mode 100644 index 0000000000..678e13998d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/TestIdentifier.java @@ -0,0 +1,87 @@ +package datadog.trace.api.civisibility.config; + +import androidx.annotation.Nullable; + +import java.util.Objects; + +public class TestIdentifier { + + private final String suite; + private final String name; + private @Nullable final String parameters; + /** + * Configurations field is intentionally excluded from hashCode/equals: the backend does not + * return full configuration for a test case, but rather includes only those parts that were not + * specified in the client request (for instance, when requesting tests without specifying module + * name, each test in the response will have module name present in its config section). Moreover, + * in some edge cases the backend may choose to return empty configuration object instead of null. + * Therefore, reconstructing on the client side a configuration block that fully corresponds to + * the one returned by the backend is non-trivial. + */ + private @Nullable final Configurations configurations; + + public TestIdentifier( + String suite, + String name, + @Nullable String parameters, + @Nullable Configurations configurations) { + this.suite = suite; + this.name = name; + this.parameters = parameters; + this.configurations = configurations; + } + + public String getSuite() { + return suite; + } + + public String getName() { + return name; + } + + @Nullable + public String getParameters() { + return parameters; + } + + @Nullable + public Configurations getConfigurations() { + return configurations; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TestIdentifier that = (TestIdentifier) o; + return Objects.equals(suite, that.suite) + && Objects.equals(name, that.name) + && Objects.equals(parameters, that.parameters); + } + + @Override + public int hashCode() { + return Objects.hash(suite, name, parameters); + } + + @Override + public String toString() { + return "SkippableTest{" + + "suite='" + + suite + + '\'' + + ", name='" + + name + + '\'' + + ", parameters='" + + parameters + + '\'' + + ", configurations=" + + configurations + + '}'; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageBridge.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageBridge.java new file mode 100644 index 0000000000..49b28ab2fc --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageBridge.java @@ -0,0 +1,97 @@ +package datadog.trace.api.civisibility.coverage; + +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan; + +import datadog.trace.api.gateway.RequestContext; +import datadog.trace.api.gateway.RequestContextSlot; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; + +public abstract class CoverageBridge { + /* + * While it is possible to use activeSpan() to get current coverage store, it adds a lot of overhead. + * This thread local is here as a shortcut for hot code paths. + */ + private static final ThreadLocal COVERAGE_PROBE_STORE = new ThreadLocal<>(); + private static volatile CoverageProbeStore.Registry COVERAGE_PROBE_STORE_REGISTRY; + private static volatile CoverageDataSupplier COVERAGE_DATA_SUPPLIER; + + public static void registerCoverageProbeStoreRegistry( + CoverageProbeStore.Registry coverageProbeStoreRegistry) { + COVERAGE_PROBE_STORE_REGISTRY = coverageProbeStoreRegistry; + } + + public static CoverageProbeStore.Registry getCoverageProbeStoreRegistry() { + return COVERAGE_PROBE_STORE_REGISTRY; + } + + public static void registerCoverageDataSupplier(CoverageDataSupplier coverageDataSupplier) { + COVERAGE_DATA_SUPPLIER = coverageDataSupplier; + } + + public static byte[] getCoverageData() { + return COVERAGE_DATA_SUPPLIER != null ? COVERAGE_DATA_SUPPLIER.get() : null; + } + + public static void setThreadLocalCoverageProbeStore(CoverageProbeStore probes) { + COVERAGE_PROBE_STORE.set(probes); + } + + public static void removeThreadLocalCoverageProbeStore() { + COVERAGE_PROBE_STORE.remove(); + } + + /* This method is referenced by name in bytecode added in jacoco instrumentation module */ + public static void currentCoverageProbeStoreRecord(Class clazz, long classId, int probeId) { + CoverageProbeStore probes = COVERAGE_PROBE_STORE.get(); + if (probes != null) { + probes.record(clazz, classId, probeId); + } else { + probes = getCurrentCoverageProbeStore(); + if (probes != null) { + probes.record(clazz, classId, probeId); + } + } + } + + /* This method is referenced by name in bytecode added by coverage probes (see CoverageUtils) */ + public static void currentCoverageProbeStoreRecord(Class clazz) { + CoverageProbeStore probes = COVERAGE_PROBE_STORE.get(); + if (probes != null) { + probes.record(clazz); + } else { + probes = getCurrentCoverageProbeStore(); + if (probes != null) { + probes.record(clazz); + } + } + } + + public static void currentCoverageProbeStoreRecordNonCode(String absolutePath) { + CoverageProbeStore probes = COVERAGE_PROBE_STORE.get(); + if (probes != null) { + probes.recordNonCodeResource(absolutePath); + } else { + probes = getCurrentCoverageProbeStore(); + if (probes != null) { + probes.recordNonCodeResource(absolutePath); + } + } + } + + /** + * Gets coverage probe store associated with the active span. This is a fallback method for cases + * when the probe store could not be retrieved from the thread local. This can happen if the span + * is propagated from the original test thread to another thread. + */ + private static CoverageProbeStore getCurrentCoverageProbeStore() { + AgentSpan span = activeSpan(); + if (span == null) { + return null; + } + RequestContext requestContext = span.getRequestContext(); + if (requestContext == null) { + return null; + } + return requestContext.getData(RequestContextSlot.CI_VISIBILITY); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java new file mode 100644 index 0000000000..a3909674ee --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java @@ -0,0 +1,5 @@ +package datadog.trace.api.civisibility.coverage; + +public interface CoverageDataSupplier { + byte[] get(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java new file mode 100644 index 0000000000..bc181d62a7 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java @@ -0,0 +1,15 @@ +package datadog.trace.api.civisibility.coverage; + +public interface CoverageProbeStore extends TestReportHolder { + void record(Class clazz); + + void record(Class clazz, long classId, int probeId); + + void recordNonCodeResource(String absolutePath); + + void report(Long testSessionId, Long testSuiteId, long spanId); + + interface Registry { + void setTotalProbeCount(String className, int totalProbeCount); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReport.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReport.java new file mode 100644 index 0000000000..cbe187f2bc --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReport.java @@ -0,0 +1,42 @@ +package datadog.trace.api.civisibility.coverage; + +import java.util.Collection; + +public class TestReport { + + private final Long testSessionId; + private final Long testSuiteId; + private final long spanId; + private final Collection testReportFileEntries; + + public TestReport( + Long testSessionId, + Long testSuiteId, + long spanId, + Collection testReportFileEntries) { + this.testSessionId = testSessionId; + this.testSuiteId = testSuiteId; + this.spanId = spanId; + this.testReportFileEntries = testReportFileEntries; + } + + public Long getTestSessionId() { + return testSessionId; + } + + public Long getTestSuiteId() { + return testSuiteId; + } + + public long getSpanId() { + return spanId; + } + + public Collection getTestReportFileEntries() { + return testReportFileEntries; + } + + public boolean isNotEmpty() { + return !testReportFileEntries.isEmpty(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java new file mode 100644 index 0000000000..3f2002d8a4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java @@ -0,0 +1,91 @@ +package datadog.trace.api.civisibility.coverage; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +public class TestReportFileEntry { + private final String sourceFileName; + private final List segments; + + public TestReportFileEntry(String sourceFileName, List segments) { + this.sourceFileName = sourceFileName; + this.segments = segments; + } + + public String getSourceFileName() { + return sourceFileName; + } + + public Collection getSegments() { + return segments; + } + + @Override + public String toString() { + return "TestReportFileEntry{" + + "sourceFileName='" + + sourceFileName + + "', lines=[" + + segments.stream().map(s -> String.valueOf(s.startLine)).collect(Collectors.joining(",")) + + "]}"; + } + + public static class Segment implements Comparable { + private final int startLine; + private final int startColumn; + private final int endLine; + private final int endColumn; + private final int numberOfExecutions; + + public Segment( + int startLine, int startColumn, int endLine, int endColumn, int numberOfExecutions) { + this.startLine = startLine; + this.startColumn = startColumn; + this.endLine = endLine; + this.endColumn = endColumn; + this.numberOfExecutions = numberOfExecutions; + } + + public int getStartLine() { + return startLine; + } + + public int getStartColumn() { + return startColumn; + } + + public int getEndLine() { + return endLine; + } + + public int getEndColumn() { + return endColumn; + } + + public int getNumberOfExecutions() { + return numberOfExecutions; + } + + @Override + public int compareTo(Segment segment) { + return startLine - segment.startLine; + } + + @Override + public String toString() { + return "Segment{" + + "startLine=" + + startLine + + ", startColumn=" + + startColumn + + ", endLine=" + + endLine + + ", endColumn=" + + endColumn + + ", numberOfExecutions=" + + numberOfExecutions + + '}'; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportHolder.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportHolder.java new file mode 100644 index 0000000000..489d594b79 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportHolder.java @@ -0,0 +1,8 @@ +package datadog.trace.api.civisibility.coverage; + +import androidx.annotation.Nullable; + +public interface TestReportHolder { + @Nullable + TestReport getReport(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/BuildEventsHandler.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/BuildEventsHandler.java new file mode 100644 index 0000000000..46a0287f6a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/BuildEventsHandler.java @@ -0,0 +1,60 @@ +package datadog.trace.api.civisibility.events; + +import androidx.annotation.Nullable; + +import java.io.File; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Map; + +import datadog.trace.api.civisibility.config.ModuleExecutionSettings; + +public interface BuildEventsHandler { + void onTestSessionStart( + T sessionKey, + String projectName, + Path projectRoot, + String startCommand, + String buildSystemName, + String buildSystemVersion, + Map additionalTags); + + void onTestSessionFail(T sessionKey, Throwable throwable); + + void onTestSessionFinish(T sessionKey); + + ModuleInfo onTestModuleStart( + T sessionKey, + String moduleName, + Collection outputClassesDirs, + @Nullable Map additionalTags); + + void onTestModuleSkip(T sessionKey, String moduleName, String reason); + + void onTestModuleFail(T sessionKey, String moduleName, Throwable throwable); + + void onTestModuleFinish(T sessionKey, String moduleName); + + ModuleExecutionSettings getModuleExecutionSettings(T sessionKey, Path jvmExecutablePath); + + ModuleInfo getModuleInfo(T sessionKey, String moduleName); + + interface Factory { + BuildEventsHandler create(); + } + + final class ModuleInfo { + public final long moduleId; + public final long sessionId; + public final String signalServerHost; + public final int signalServerPort; + + public ModuleInfo( + long moduleId, long sessionId, String signalServerHost, int signalServerPort) { + this.moduleId = moduleId; + this.sessionId = sessionId; + this.signalServerHost = signalServerHost; + this.signalServerPort = signalServerPort; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/TestEventsHandler.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/TestEventsHandler.java new file mode 100644 index 0000000000..01c62411de --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/TestEventsHandler.java @@ -0,0 +1,88 @@ +package datadog.trace.api.civisibility.events; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.io.Closeable; +import java.lang.reflect.Method; +import java.util.Collection; + +import datadog.trace.api.civisibility.config.TestIdentifier; +import datadog.trace.api.civisibility.retry.TestRetryPolicy; + +public interface TestEventsHandler extends Closeable { + + void onTestSuiteStart( + String testSuiteName, + @Nullable String testFramework, + @Nullable String testFrameworkVersion, + @Nullable Class testClass, + @Nullable Collection categories, + boolean parallelized); + + void onTestSuiteFinish(String testSuiteName, @Nullable Class testClass); + + void onTestSuiteSkip(String testSuiteName, Class testClass, @Nullable String reason); + + void onTestSuiteFailure(String testSuiteName, Class testClass, @Nullable Throwable throwable); + + void onTestStart( + String testSuiteName, + String testName, + @Nullable Object testQualifier, + @Nullable String testFramework, + @Nullable String testFrameworkVersion, + @Nullable String testParameters, + @Nullable Collection categories, + @Nullable Class testClass, + @Nullable String testMethodName, + @Nullable Method testMethod); + + void onTestSkip( + String testSuiteName, + Class testClass, + String testName, + @Nullable Object testQualifier, + @Nullable String testParameters, + @Nullable String reason); + + void onTestFailure( + String testSuiteName, + Class testClass, + String testName, + @Nullable Object testQualifier, + @Nullable String testParameters, + @Nullable Throwable throwable); + + void onTestFinish( + String testSuiteName, + Class testClass, + String testName, + @Nullable Object testQualifier, + @Nullable String testParameters); + + void onTestIgnore( + String testSuiteName, + String testName, + @Nullable Object testQualifier, + @Nullable String testFramework, + @Nullable String testFrameworkVersion, + @Nullable String testParameters, + @Nullable Collection categories, + @Nullable Class testClass, + @Nullable String testMethodName, + @Nullable Method testMethod, + @Nullable String reason); + + boolean skip(TestIdentifier test); + + @NonNull + TestRetryPolicy retryPolicy(TestIdentifier test); + + @Override + void close(); + + interface Factory { + TestEventsHandler create(String component); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTest.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTest.java new file mode 100644 index 0000000000..97bc6ef428 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTest.java @@ -0,0 +1,21 @@ +package datadog.trace.api.civisibility.noop; + +import androidx.annotation.Nullable; + +import datadog.trace.api.civisibility.DDTest; + +public class NoOpDDTest implements DDTest { + static final DDTest INSTANCE = new NoOpDDTest(); + + @Override + public void setTag(String key, Object value) {} + + @Override + public void setErrorInfo(@Nullable Throwable error) {} + + @Override + public void setSkipReason(@Nullable String skipReason) {} + + @Override + public void end(@Nullable Long endTime) {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java new file mode 100644 index 0000000000..f5f98b635b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java @@ -0,0 +1,31 @@ +package datadog.trace.api.civisibility.noop; + +import androidx.annotation.Nullable; + +import datadog.trace.api.civisibility.DDTestModule; +import datadog.trace.api.civisibility.DDTestSuite; + +public class NoOpDDTestModule implements DDTestModule { + static final DDTestModule INSTANCE = new NoOpDDTestModule(); + + @Override + public void setTag(String key, Object value) {} + + @Override + public void setErrorInfo(Throwable error) {} + + @Override + public void setSkipReason(String skipReason) {} + + @Override + public void end(@Nullable Long endTime) {} + + @Override + public DDTestSuite testSuiteStart( + String testSuiteName, + @Nullable Class testClass, + @Nullable Long startTime, + boolean parallelized) { + return NoOpDDTestSuite.INSTANCE; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java new file mode 100644 index 0000000000..b2f85f969f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java @@ -0,0 +1,27 @@ +package datadog.trace.api.civisibility.noop; + +import androidx.annotation.Nullable; + +import datadog.trace.api.civisibility.DDTestModule; +import datadog.trace.api.civisibility.DDTestSession; + +public class NoOpDDTestSession implements DDTestSession { + public static final DDTestSession INSTANCE = new NoOpDDTestSession(); + + @Override + public void setTag(String key, Object value) {} + + @Override + public void setErrorInfo(Throwable error) {} + + @Override + public void setSkipReason(String skipReason) {} + + @Override + public void end(@Nullable Long endTime) {} + + @Override + public DDTestModule testModuleStart(String moduleName, @Nullable Long startTime) { + return NoOpDDTestModule.INSTANCE; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java new file mode 100644 index 0000000000..7d87e5d17c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java @@ -0,0 +1,29 @@ +package datadog.trace.api.civisibility.noop; + +import androidx.annotation.Nullable; + +import java.lang.reflect.Method; + +import datadog.trace.api.civisibility.DDTest; +import datadog.trace.api.civisibility.DDTestSuite; + +public class NoOpDDTestSuite implements DDTestSuite { + static final DDTestSuite INSTANCE = new NoOpDDTestSuite(); + + @Override + public void setTag(String key, Object value) {} + + @Override + public void setErrorInfo(Throwable error) {} + + @Override + public void setSkipReason(String skipReason) {} + + @Override + public void end(@Nullable Long endTime) {} + + @Override + public DDTest testStart(String testName, @Nullable Method testMethod, @Nullable Long startTime) { + return NoOpDDTest.INSTANCE; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/retry/TestRetryPolicy.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/retry/TestRetryPolicy.java new file mode 100644 index 0000000000..465cae3891 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/retry/TestRetryPolicy.java @@ -0,0 +1,7 @@ +package datadog.trace.api.civisibility.retry; + +public interface TestRetryPolicy { + boolean retryPossible(); + + boolean retry(boolean successful); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/AppSecConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/AppSecConfig.java new file mode 100644 index 0000000000..c68380f613 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/AppSecConfig.java @@ -0,0 +1,28 @@ +package datadog.trace.api.config; + +/** Constant with names of configuration options for appsec. */ +public final class AppSecConfig { + + public static final String APPSEC_ENABLED = "appsec.enabled"; + public static final String APPSEC_REPORTING_INBAND = "appsec.reporting.inband"; + public static final String APPSEC_RULES_FILE = "appsec.rules"; + public static final String APPSEC_REPORT_TIMEOUT_SEC = "appsec.report.timeout"; + public static final String APPSEC_IP_ADDR_HEADER = "appsec.ipheader"; + public static final String APPSEC_TRACE_RATE_LIMIT = "appsec.trace.rate.limit"; + public static final String APPSEC_WAF_METRICS = "appsec.waf.metrics"; + public static final String APPSEC_WAF_TIMEOUT = "appsec.waf.timeout"; + public static final String APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP = + "appsec.obfuscation.parameter_key_regexp"; + public static final String APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP = + "appsec.obfuscation.parameter_value_regexp"; + public static final String APPSEC_HTTP_BLOCKED_TEMPLATE_HTML = + "appsec.http.blocked.template.html"; + public static final String APPSEC_HTTP_BLOCKED_TEMPLATE_JSON = + "appsec.http.blocked.template.json"; + public static final String APPSEC_AUTOMATED_USER_EVENTS_TRACKING = + "appsec.automated-user-events-tracking"; + public static final String API_SECURITY_ENABLED = "experimental.api-security.enabled"; + public static final String API_SECURITY_REQUEST_SAMPLE_RATE = "api-security.request.sample.rate"; + + private AppSecConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java new file mode 100644 index 0000000000..3982885359 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java @@ -0,0 +1,78 @@ +package datadog.trace.api.config; + +/** Constant with names of configuration options for CI visibility. */ +public final class CiVisibilityConfig { + + public static final String CIVISIBILITY_ENABLED = "civisibility.enabled"; + public static final String CIVISIBILITY_TRACE_SANITATION_ENABLED = + "civisibility.trace.sanitation.enabled"; + public static final String CIVISIBILITY_AGENTLESS_ENABLED = "civisibility.agentless.enabled"; + public static final String CIVISIBILITY_AGENTLESS_URL = "civisibility.agentless.url"; + public static final String CIVISIBILITY_SOURCE_DATA_ENABLED = "civisibility.source.data.enabled"; + public static final String CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED = + "civisibility.source.data.root.check.enabled"; + public static final String CIVISIBILITY_SESSION_ID = "civisibility.session.id"; + public static final String CIVISIBILITY_MODULE_ID = "civisibility.module.id"; + public static final String CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED = + "civisibility.build.instrumentation.enabled"; + public static final String CIVISIBILITY_AGENT_JAR_URI = "civisibility.agent.jar.uri"; + public static final String CIVISIBILITY_AUTO_CONFIGURATION_ENABLED = + "civisibility.auto.configuration.enabled"; + public static final String CIVISIBILITY_ADDITIONAL_CHILD_PROCESS_JVM_ARGS = + "civisibility.additional.child.process.jvm.args"; + public static final String CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED = + "civisibility.compiler.plugin.auto.configuration.enabled"; + public static final String CIVISIBILITY_COMPILER_PLUGIN_VERSION = + "civisibility.compiler.plugin.version"; + public static final String CIVISIBILITY_DEBUG_PORT = "civisibility.debug.port"; + public static final String CIVISIBILITY_GIT_UPLOAD_ENABLED = "civisibility.git.upload.enabled"; + public static final String CIVISIBILITY_GIT_UNSHALLOW_ENABLED = + "civisibility.git.unshallow.enabled"; + public static final String CIVISIBILITY_GIT_UNSHALLOW_DEFER = "civisibility.git.unshallow.defer"; + public static final String CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS = + "civisibility.git.upload.timeout.millis"; + public static final String CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS = + "civisibility.git.command.timeout.millis"; + public static final String CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS = + "civisibility.backend.api.timeout.millis"; + public static final String CIVISIBILITY_GIT_REMOTE_NAME = "civisibility.git.remote.name"; + public static final String CIVISIBILITY_SIGNAL_SERVER_HOST = "civisibility.signal.server.host"; + public static final String CIVISIBILITY_SIGNAL_SERVER_PORT = "civisibility.signal.server.port"; + public static final String CIVISIBILITY_ITR_ENABLED = "civisibility.itr.enabled"; + public static final String CIVISIBILITY_CIPROVIDER_INTEGRATION_ENABLED = + "civisibility.ciprovider.integration.enabled"; + public static final String CIVISIBILITY_REPO_INDEX_SHARING_ENABLED = + "civisibility.repo.index.sharing.enabled"; + public static final String CIVISIBILITY_MODULE_EXECUTION_SETTINGS_CACHE_SIZE = + "civisibility.module.execution.settings.cache.size"; + public static final String CIVISIBILITY_JVM_INFO_CACHE_SIZE = "civisibility.jvm.info.cache.size"; + public static final String CIVISIBILITY_INJECTED_TRACER_VERSION = + "civisibility.injected.tracer.version"; + public static final String CIVISIBILITY_RESOURCE_FOLDER_NAMES = + "civisibility.resource.folder.names"; + public static final String CIVISIBILITY_FLAKY_RETRY_ENABLED = "civisibility.flaky.retry.enabled"; + public static final String CIVISIBILITY_FLAKY_RETRY_COUNT = "civisibility.flaky.retry.count"; + public static final String CIVISIBILITY_MODULE_NAME = "civisibility.module.name"; + + /* COVERAGE SETTINGS */ + public static final String CIVISIBILITY_CODE_COVERAGE_ENABLED = + "civisibility.code.coverage.enabled"; + public static final String CIVISIBILITY_CODE_COVERAGE_INCLUDES = + "civisibility.code.coverage.includes"; + public static final String CIVISIBILITY_CODE_COVERAGE_EXCLUDES = + "civisibility.code.coverage.excludes"; + public static final String CIVISIBILITY_CODE_COVERAGE_SEGMENTS_ENABLED = + "civisibility.code.coverage.segments.enabled"; + public static final String CIVISIBILITY_CODE_COVERAGE_ROOT_PACKAGES_LIMIT = + "civisibility.code.coverage.root.packages.limit"; + public static final String CIVISIBILITY_CODE_COVERAGE_PERCENTAGE_CALCULATION_ENABLED = + "civisibility.code.coverage.percentage.calculation.enabled"; + public static final String CIVISIBILITY_CODE_COVERAGE_REPORT_DUMP_DIR = + "civisibility.code.coverage.report.dump.dir"; + public static final String CIVISIBILITY_JACOCO_PLUGIN_VERSION = + "civisibility.jacoco.plugin.version"; + public static final String CIVISIBILITY_JACOCO_GRADLE_SOURCE_SETS = + "civisibility.jacoco.gradle.sourcesets"; + + private CiVisibilityConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/CrashTrackingConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/CrashTrackingConfig.java new file mode 100644 index 0000000000..85b593c0c8 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/CrashTrackingConfig.java @@ -0,0 +1,26 @@ +package datadog.trace.api.config; + +/** + * These config options will only work with dd-java-agent, not with dd-trace-ot. + * + *

Configure via system properties, environment variables, or config properties file. See online + * documentation for details. + */ +public final class CrashTrackingConfig { + + public static final String CRASH_TRACKING_TAGS = "crashtracking.tags"; + + public static final String CRASH_TRACKING_UPLOAD_TIMEOUT = "crashtracking.upload.timeout"; + public static final int CRASH_TRACKING_UPLOAD_TIMEOUT_DEFAULT = 30; + + public static final String CRASH_TRACKING_PROXY_HOST = "crashtracking.proxy.host"; + public static final String CRASH_TRACKING_PROXY_PORT = "crashtracking.proxy.port"; + public static final String CRASH_TRACKING_PROXY_USERNAME = "crashtracking.proxy.username"; + public static final String CRASH_TRACKING_PROXY_PASSWORD = "crashtracking.proxy.password"; + + // Not intended for production use + public static final String CRASH_TRACKING_AGENTLESS = "crashtracking.agentless"; + public static final boolean CRASH_TRACKING_AGENTLESS_DEFAULT = false; + + private CrashTrackingConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/CwsConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/CwsConfig.java new file mode 100644 index 0000000000..d65db69252 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/CwsConfig.java @@ -0,0 +1,10 @@ +package datadog.trace.api.config; + +public final class CwsConfig { + + public static final String CWS_ENABLED = "cws.enabled"; + + public static final String CWS_TLS_REFRESH = "cws.tls.refresh"; + + private CwsConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/DebuggerConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/DebuggerConfig.java new file mode 100644 index 0000000000..4d81b8c5f7 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/DebuggerConfig.java @@ -0,0 +1,34 @@ +package datadog.trace.api.config; + +public final class DebuggerConfig { + public static final String DEBUGGER_ENABLED = "dynamic.instrumentation.enabled"; + public static final String DEBUGGER_SNAPSHOT_URL = "dynamic.instrumentation.snapshot.url"; + public static final String DEBUGGER_PROBE_URL = "dynamic.instrumentation.probe.url"; + public static final String DEBUGGER_PROBE_FILE_LOCATION = "dynamic.instrumentation.probe.file"; + public static final String DEBUGGER_UPLOAD_TIMEOUT = "dynamic.instrumentation.upload.timeout"; + public static final String DEBUGGER_UPLOAD_FLUSH_INTERVAL = + "dynamic.instrumentation.upload.flush.interval"; + public static final String DEBUGGER_UPLOAD_BATCH_SIZE = + "dynamic.instrumentation.upload.batch.size"; + public static final String DEBUGGER_MAX_PAYLOAD_SIZE = "dynamic.instrumentation.max.payload.size"; + public static final String DEBUGGER_METRICS_ENABLED = "dynamic.instrumentation.metrics.enabled"; + public static final String DEBUGGER_CLASSFILE_DUMP_ENABLED = + "dynamic.instrumentation.classfile.dump.enabled"; + public static final String DEBUGGER_POLL_INTERVAL = "dynamic.instrumentation.poll.interval"; + public static final String DEBUGGER_DIAGNOSTICS_INTERVAL = + "dynamic.instrumentation.diagnostics.interval"; + public static final String DEBUGGER_VERIFY_BYTECODE = "dynamic.instrumentation.verify.bytecode"; + public static final String DEBUGGER_INSTRUMENT_THE_WORLD = + "dynamic.instrumentation.instrument.the.world"; + public static final String DEBUGGER_EXCLUDE_FILES = "dynamic.instrumentation.exclude.files"; + public static final String DEBUGGER_CAPTURE_TIMEOUT = "dynamic.instrumentation.capture.timeout"; + public static final String DEBUGGER_REDACTED_IDENTIFIERS = + "dynamic.instrumentation.redacted.identifiers"; + public static final String DEBUGGER_REDACTED_TYPES = "dynamic.instrumentation.redacted.types"; + public static final String DEBUGGER_SYMBOL_ENABLED = "symbol.database.upload.enabled"; + public static final String DEBUGGER_SYMBOL_FORCE_UPLOAD = "internal.force.symbol.database.upload"; + public static final String DEBUGGER_SYMBOL_INCLUDES = "symbol.database.includes"; + public static final String DEBUGGER_SYMBOL_FLUSH_THRESHOLD = "symbol.database.flush.threshold"; + + private DebuggerConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/GeneralConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/GeneralConfig.java new file mode 100644 index 0000000000..d53b41fdb1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/GeneralConfig.java @@ -0,0 +1,83 @@ +package datadog.trace.api.config; + +/** + * A list of keys to be used in a Properties instance with dd-trace-ot's DDTracer as follows: + * + *

+ *   DDTracer.builder().withProperties(new Properties()).build()
+ * 
+ * + * If using dd-java-agent, these keys represent settings that should be configured via system + * properties, environment variables, or config properties file. See online documentation for + * details. + */ +public final class GeneralConfig { + + public static final String CONFIGURATION_FILE = "trace.config"; + public static final String API_KEY = "api-key"; + public static final String APPLICATION_KEY = "application-key"; + public static final String API_KEY_FILE = "api-key-file"; + public static final String APPLICATION_KEY_FILE = "application-key-file"; + public static final String SITE = "site"; + + public static final String SERVICE_NAME = "service.name"; + public static final String ENV = "env"; + public static final String VERSION = "version"; + public static final String PRIMARY_TAG = "primary.tag"; + public static final String TAGS = "tags"; + @Deprecated // Use dd.tags instead + public static final String GLOBAL_TAGS = "trace.global.tags"; + + public static final String TRACE_DEBUG = "trace.debug"; + public static final String TRACE_TRIAGE = "trace.triage"; + + public static final String STARTUP_LOGS_ENABLED = "trace.startup.logs"; + + public static final String DOGSTATSD_START_DELAY = "dogstatsd.start-delay"; + public static final String DOGSTATSD_HOST = "dogstatsd.host"; + public static final String DOGSTATSD_PORT = "dogstatsd.port"; + public static final String DOGSTATSD_PATH = "dogstatsd.path"; + public static final String DOGSTATSD_ARGS = "dogstatsd.args"; + public static final String DOGSTATSD_NAMED_PIPE = "dogstatsd.pipe.name"; + + public static final String STATSD_CLIENT_QUEUE_SIZE = "statsd.client.queue.size"; + public static final String STATSD_CLIENT_SOCKET_BUFFER = "statsd.client.socket.buffer"; + public static final String STATSD_CLIENT_SOCKET_TIMEOUT = "statsd.client.socket.timeout"; + + public static final String RUNTIME_METRICS_ENABLED = "runtime.metrics.enabled"; + public static final String RUNTIME_ID_ENABLED = "runtime-id.enabled"; + + public static final String HEALTH_METRICS_ENABLED = "trace.health.metrics.enabled"; + public static final String HEALTH_METRICS_STATSD_HOST = "trace.health.metrics.statsd.host"; + public static final String HEALTH_METRICS_STATSD_PORT = "trace.health.metrics.statsd.port"; + public static final String PERF_METRICS_ENABLED = "trace.perf.metrics.enabled"; + + public static final String TRACER_METRICS_ENABLED = "trace.tracer.metrics.enabled"; + public static final String TRACER_METRICS_BUFFERING_ENABLED = + "trace.tracer.metrics.buffering.enabled"; + public static final String TRACER_METRICS_MAX_AGGREGATES = "trace.tracer.metrics.max.aggregates"; + public static final String TRACER_METRICS_MAX_PENDING = "trace.tracer.metrics.max.pending"; + public static final String TRACER_METRICS_IGNORED_RESOURCES = + "trace.tracer.metrics.ignored.resources"; + + public static final String AZURE_APP_SERVICES = "azure.app.services"; + public static final String INTERNAL_EXIT_ON_FAILURE = "trace.internal.exit.on.failure"; + + public static final String DATA_STREAMS_ENABLED = "data.streams.enabled"; + public static final String DATA_STREAMS_BUCKET_DURATION_SECONDS = + "data.streams.bucket_duration.seconds"; + + public static final String TELEMETRY_ENABLED = "instrumentation.telemetry.enabled"; + public static final String TELEMETRY_HEARTBEAT_INTERVAL = "telemetry.heartbeat.interval"; + public static final String TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL = + "telemetry.extended.heartbeat.interval"; + public static final String TELEMETRY_METRICS_INTERVAL = "telemetry.metrics.interval"; + public static final String TELEMETRY_METRICS_ENABLED = "telemetry.metrics.enabled"; + public static final String TELEMETRY_DEPENDENCY_COLLECTION_ENABLED = + "telemetry.dependency-collection.enabled"; + public static final String TELEMETRY_LOG_COLLECTION_ENABLED = "telemetry.log-collection.enabled"; + + public static final String TELEMETRY_DEBUG_REQUESTS_ENABLED = "telemetry.debug.requests.enabled"; + + private GeneralConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/IastConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/IastConfig.java new file mode 100644 index 0000000000..e70a42becc --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/IastConfig.java @@ -0,0 +1,25 @@ +package datadog.trace.api.config; + +/** Constant with names of configuration options for IAST. */ +public final class IastConfig { + + public static final String IAST_ENABLED = "iast.enabled"; + public static final String IAST_WEAK_HASH_ALGORITHMS = "iast.weak-hash.algorithms"; + public static final String IAST_WEAK_CIPHER_ALGORITHMS = "iast.weak-cipher.algorithms"; + public static final String IAST_DEBUG_ENABLED = "iast.debug.enabled"; + public static final String IAST_MAX_CONCURRENT_REQUESTS = "iast.max-concurrent-requests"; + public static final String IAST_VULNERABILITIES_PER_REQUEST = "iast.vulnerabilities-per-request"; + public static final String IAST_REQUEST_SAMPLING = "iast.request-sampling"; + public static final String IAST_DEDUPLICATION_ENABLED = "iast.deduplication.enabled"; + public static final String IAST_TELEMETRY_VERBOSITY = "iast.telemetry.verbosity"; + public static final String IAST_DETECTION_MODE = "iast.detection.mode"; + public static final String IAST_REDACTION_ENABLED = "iast.redaction.enabled"; + public static final String IAST_REDACTION_NAME_PATTERN = "iast.redaction.name.pattern"; + public static final String IAST_REDACTION_VALUE_PATTERN = "iast.redaction.value.pattern"; + public static final String IAST_STACKTRACE_LEAK_SUPPRESS = "iast.stacktrace-leak.suppress"; + public static final String IAST_MAX_RANGE_COUNT = "iast.max-range-count"; + + public static final String IAST_TRUNCATION_MAX_VALUE_LENGTH = "iast.truncation.max.value.length"; + + private IastConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/JmxFetchConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/JmxFetchConfig.java new file mode 100644 index 0000000000..6d2642f6db --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/JmxFetchConfig.java @@ -0,0 +1,28 @@ +package datadog.trace.api.config; + +/** + * These config options will only work with dd-java-agent, not with dd-trace-ot. + * + *

Configure via system properties, environment variables, or config properties file. See online + * documentation for details. + */ +public final class JmxFetchConfig { + public static final String JMX_TAGS = "trace.jmx.tags"; + public static final String JMX_FETCH_ENABLED = "jmxfetch.enabled"; + public static final String JMX_FETCH_START_DELAY = "jmxfetch.start-delay"; + public static final String JMX_FETCH_CONFIG_DIR = "jmxfetch.config.dir"; + public static final String JMX_FETCH_CONFIG = "jmxfetch.config"; + @Deprecated public static final String JMX_FETCH_METRICS_CONFIGS = "jmxfetch.metrics-configs"; + public static final String JMX_FETCH_CHECK_PERIOD = "jmxfetch.check-period"; + public static final String JMX_FETCH_INITIAL_REFRESH_BEANS_PERIOD = + "jmxfetch.initial-refresh-beans-period"; + public static final String JMX_FETCH_REFRESH_BEANS_PERIOD = "jmxfetch.refresh-beans-period"; + public static final String JMX_FETCH_STATSD_HOST = "jmxfetch.statsd.host"; + public static final String JMX_FETCH_STATSD_PORT = "jmxfetch.statsd.port"; + public static final String JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED = + "jmxfetch.multiple-runtime-services.enabled"; + public static final String JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT = + "jmxfetch.multiple-runtime-services.limit"; + + private JmxFetchConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/ProfilingConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/ProfilingConfig.java new file mode 100644 index 0000000000..ca1dd823d5 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/ProfilingConfig.java @@ -0,0 +1,204 @@ +package datadog.trace.api.config; + +/** + * These config options will only work with dd-java-agent, not with dd-trace-ot. + * + *

Configure via system properties, environment variables, or config properties file. See online + * documentation for details. + */ +public final class ProfilingConfig { + public static final String PROFILING_ENABLED = "profiling.enabled"; + public static final boolean PROFILING_ENABLED_DEFAULT = false; + public static final String PROFILING_ALLOCATION_ENABLED = "profiling.allocation.enabled"; + public static final String PROFILING_HEAP_ENABLED = "profiling.heap.enabled"; + public static final boolean PROFILING_HEAP_ENABLED_DEFAULT = false; + @Deprecated // Use dd.site instead + public static final String PROFILING_URL = "profiling.url"; + @Deprecated // Use dd.api-key instead + public static final String PROFILING_API_KEY_OLD = "profiling.api-key"; + @Deprecated // Use dd.api-key-file instead + public static final String PROFILING_API_KEY_FILE_OLD = "profiling.api-key-file"; + @Deprecated // Use dd.api-key instead + public static final String PROFILING_API_KEY_VERY_OLD = "profiling.apikey"; + @Deprecated // Use dd.api-key-file instead + public static final String PROFILING_API_KEY_FILE_VERY_OLD = "profiling.apikey.file"; + public static final String PROFILING_TAGS = "profiling.tags"; + public static final String PROFILING_START_DELAY = "profiling.start-delay"; + public static final int PROFILING_START_DELAY_DEFAULT = 10; + public static final String PROFILING_START_FORCE_FIRST = "profiling.start-force-first"; + public static final boolean PROFILING_START_FORCE_FIRST_DEFAULT = false; + public static final String PROFILING_UPLOAD_PERIOD = "profiling.upload.period"; + public static final int PROFILING_UPLOAD_PERIOD_DEFAULT = 60; + public static final String PROFILING_TEMPLATE_OVERRIDE_FILE = + "profiling.jfr-template-override-file"; + public static final String PROFILING_UPLOAD_TIMEOUT = "profiling.upload.timeout"; + public static final int PROFILING_UPLOAD_TIMEOUT_DEFAULT = 30; + public static final String PROFILING_UPLOAD_COMPRESSION = "profiling.upload.compression"; + public static final String PROFILING_UPLOAD_COMPRESSION_DEFAULT = "on"; + public static final String PROFILING_PROXY_HOST = "profiling.proxy.host"; + public static final String PROFILING_PROXY_PORT = "profiling.proxy.port"; + public static final int PROFILING_PROXY_PORT_DEFAULT = 8080; + public static final String PROFILING_PROXY_USERNAME = "profiling.proxy.username"; + public static final String PROFILING_PROXY_PASSWORD = "profiling.proxy.password"; + public static final String PROFILING_EXCEPTION_SAMPLE_LIMIT = "profiling.exception.sample.limit"; + public static final int PROFILING_EXCEPTION_SAMPLE_LIMIT_DEFAULT = 10_000; + public static final String PROFILING_EXCEPTION_RECORD_MESSAGE = + "profiling.exception.record.message"; + public static final boolean PROFILING_EXCEPTION_RECORD_MESSAGE_DEFAULT = true; + + public static final String PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT = + "profiling.direct.allocation.sample.limit"; + public static final int PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT = 2_000; + public static final String PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS = + "profiling.exception.histogram.top-items"; + public static final int PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS_DEFAULT = 50; + public static final String PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE = + "profiling.exception.histogram.max-collection-size"; + public static final int PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE_DEFAULT = 10_000; + public static final String PROFILING_EXCLUDE_AGENT_THREADS = "profiling.exclude.agent-threads"; + public static final String PROFILING_HOTSPOTS_ENABLED = "profiling.hotspots.enabled"; + + public static final String PROFILING_AUXILIARY_TYPE = "profiling.auxiliary"; + public static final String PROFILING_AUXILIARY_TYPE_DEFAULT = "none"; + + public static final String PROFILING_DATADOG_PROFILER_ENABLED = "profiling.ddprof.enabled"; + + public static final String PROFILING_DIRECT_ALLOCATION_ENABLED = + "profiling.directallocation.enabled"; + public static final boolean PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT = false; + + public static final String PROFILING_STACKDEPTH = "profiling.stackdepth"; + public static final int PROFILING_STACKDEPTH_DEFAULT = 512; + + // Java profiler lib needs to be extracted from JAR and placed into the scratch location + // By default the scratch is the os temp directory but can be overridden by user + public static final String PROFILING_DATADOG_PROFILER_SCRATCH = "profiling.ddprof.scratch"; + public static final String PROFILING_DATADOG_PROFILER_SCRATCH_DEFAULT = + System.getProperty("java.io.tmpdir"); + public static final String PROFILING_DATADOG_PROFILER_LIBPATH = "profiling.ddprof.debug.lib"; + public static final String PROFILING_DATADOG_PROFILER_ALLOC_ENABLED = + "profiling.ddprof.alloc.enabled"; + public static final boolean PROFILING_DATADOG_PROFILER_ALLOC_ENABLED_DEFAULT = false; + public static final String PROFILING_DATADOG_PROFILER_ALLOC_INTERVAL = + "profiling.ddprof.alloc.interval"; + public static final int PROFILING_DATADOG_PROFILER_ALLOC_INTERVAL_DEFAULT = 256 * 1024; + public static final String PROFILING_DATADOG_PROFILER_CPU_ENABLED = + "profiling.ddprof.cpu.enabled"; + public static final boolean PROFILING_DATADOG_PROFILER_CPU_ENABLED_DEFAULT = true; + public static final String PROFILING_DATADOG_PROFILER_CPU_INTERVAL = + "profiling.ddprof.cpu.interval.ms"; + public static final int PROFILING_DATADOG_PROFILER_CPU_INTERVAL_DEFAULT = 10; + public static final String PROFILING_DATADOG_PROFILER_WALL_ENABLED = + "profiling.ddprof.wall.enabled"; + public static final boolean PROFILING_DATADOG_PROFILER_WALL_ENABLED_DEFAULT = true; + public static final String PROFILING_DATADOG_PROFILER_WALL_INTERVAL = + "profiling.ddprof.wall.interval.ms"; + public static final int PROFILING_DATADOG_PROFILER_WALL_INTERVAL_DEFAULT = 10; + + public static final String PROFILING_DATADOG_PROFILER_WALL_COLLAPSING = + "profiling.ddprof.wall.collapsing"; + public static final boolean PROFILING_DATADOG_PROFILER_WALL_COLLAPSING_DEFAULT = false; + + public static final String PROFILING_DATADOG_PROFILER_WALL_CONTEXT_FILTER = + "profiling.ddprof.wall.context.filter"; + public static final boolean PROFILING_DATADOG_PROFILER_WALL_CONTEXT_FILTER_DEFAULT = true; + + public static final String PROFILING_DATADOG_PROFILER_SCHEDULING_EVENT = + "profiling.experimental.ddprof.scheduling.event"; + + public static final String PROFILING_DATADOG_PROFILER_SCHEDULING_EVENT_INTERVAL = + "profiling.experimental.ddprof.scheduling.event.interval"; + + public static final String PROFILING_DATADOG_PROFILER_LOG_LEVEL = "profiling.ddprof.loglevel"; + + public static final String PROFILING_DATADOG_PROFILER_LOG_LEVEL_DEFAULT = "NONE"; + public static final String PROFILING_DATADOG_PROFILER_STACKDEPTH = "profiling.ddprof.stackdepth"; + public static final String PROFILING_DATADOG_PROFILER_CSTACK = "profiling.ddprof.cstack"; + public static final String PROFILING_DATADOG_PROFILER_CSTACK_DEFAULT = "fp"; + public static final String PROFILING_DATADOG_PROFILER_SAFEMODE = "profiling.ddprof.safemode"; + + private static final int POP_METHOD = 4; + private static final int LAST_JAVA_PC = 16; + public static final int PROFILING_DATADOG_PROFILER_SAFEMODE_DEFAULT = POP_METHOD | LAST_JAVA_PC; + + public static final String PROFILING_DATADOG_PROFILER_LINE_NUMBERS = + "profiling.ddprof.linenumbers"; + + public static final boolean PROFILING_DATADOG_PROFILER_LINE_NUMBERS_DEFAULT = true; + + @Deprecated + public static final String PROFILING_DATADOG_PROFILER_MEMLEAK_ENABLED = + "profiling.ddprof.memleak.enabled"; + + @Deprecated + public static final String PROFILING_DATADOG_PROFILER_MEMLEAK_INTERVAL = + "profiling.ddprof.memleak.interval"; + + @Deprecated + public static final String PROFILING_DATADOG_PROFILER_MEMLEAK_CAPACITY = + "profiling.ddprof.memleak.capacity"; + + public static final String PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED = + "profiling.ddprof.liveheap.enabled"; + public static final boolean PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED_DEFAULT = false; + public static final String PROFILING_DATADOG_PROFILER_LIVEHEAP_INTERVAL = + "profiling.ddprof.liveheap.interval"; + public static final String PROFILING_DATADOG_PROFILER_LIVEHEAP_CAPACITY = + "profiling.ddprof.liveheap.capacity"; + public static final int PROFILING_DATADOG_PROFILER_LIVEHEAP_CAPACITY_DEFAULT = 1024; + public static final String PROFILING_DATADOG_PROFILER_LIVEHEAP_TRACK_HEAPSIZE = + "profiling.ddprof.liveheap.track_size.enabled"; + public static final boolean PROFILING_DATADOG_PROFILER_LIVEHEAP_TRACK_HEAPSIZE_DEFAFULT = true; + public static final String PROFILING_ENDPOINT_COLLECTION_ENABLED = + "profiling.endpoint.collection.enabled"; + public static final boolean PROFILING_ENDPOINT_COLLECTION_ENABLED_DEFAULT = true; + + public static final String PROFILING_JFR_REPOSITORY_MAXSIZE = "profiling.jfr.repository.maxsize"; + public static final int PROFILING_JFR_REPOSITORY_MAXSIZE_DEFAULT = + 64 * 1024 * 1024; // 64MB default + + public static final String PROFILING_UPLOAD_SUMMARY_ON_413 = "profiling.upload.summary-on-413"; + public static final boolean PROFILING_UPLOAD_SUMMARY_ON_413_DEFAULT = false; + + // Not intended for production use + public static final String PROFILING_AGENTLESS = "profiling.agentless"; + public static final boolean PROFILING_AGENTLESS_DEFAULT = false; + + public static final String PROFILING_DISABLED_EVENTS = "profiling.disabled.events"; + public static final String PROFILING_ENABLED_EVENTS = "profiling.enabled.events"; + + public static final String PROFILING_DEBUG_DUMP_PATH = "profiling.debug.dump_path"; + public static final String PROFILING_DEBUG_JFR_DISABLED = "profiling.debug.jfr.disabled"; + + public static final String PROFILING_CONTEXT_ATTRIBUTES = "profiling.context.attributes"; + + public static final String PROFILING_CONTEXT_ATTRIBUTES_SPAN_NAME_ENABLED = + "profiling.context.attributes.span.name.enabled"; + + public static final String PROFILING_CONTEXT_ATTRIBUTES_RESOURCE_NAME_ENABLED = + "profiling.context.attributes.resource.name.enabled"; + + public static final String PROFILING_QUEUEING_TIME_ENABLED = + "profiling.experimental.queueing.time.enabled"; + + public static final boolean PROFILING_QUEUEING_TIME_ENABLED_DEFAULT = false; + + public static final String PROFILING_QUEUEING_TIME_THRESHOLD_MILLIS = + "profiling.experimental.queueing.time.threshold.millis"; + + public static final long PROFILING_QUEUEING_TIME_THRESHOLD_MILLIS_DEFAULT = 50; + + public static final String PROFILING_ULTRA_MINIMAL = "profiling.ultra.minimal"; + + public static final String PROFILING_HEAP_HISTOGRAM_ENABLED = "profiling.heap.histogram.enabled"; + public static final boolean PROFILING_HEAP_HISTOGRAM_ENABLED_DEFAULT = false; + + public static final String PROFILING_HEAP_HISTOGRAM_MODE = "profiling.heap.histogram.mode"; + public static final String PROFILING_HEAP_HISTOGRAM_MODE_DEFAULT = "aftergc"; + + public static final String PROFILING_TIMELINE_EVENTS_ENABLED = + "profiling.timeline.events.enabled"; + public static final boolean PROFILING_TIMELINE_EVENTS_ENABLED_DEFAULT = false; + + private ProfilingConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/RemoteConfigConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/RemoteConfigConfig.java new file mode 100644 index 0000000000..32c9251831 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/RemoteConfigConfig.java @@ -0,0 +1,17 @@ +package datadog.trace.api.config; + +public class RemoteConfigConfig { + public static final String REMOTE_CONFIG_ENABLED = "remote_config.enabled"; + public static final String REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED = + "remote_config.integrity_check.enabled"; + public static final String REMOTE_CONFIG_URL = "remote_config.url"; + public static final String REMOTE_CONFIG_POLL_INTERVAL_SECONDS = + "remote_config.poll_interval.seconds"; + public static final String REMOTE_CONFIG_MAX_PAYLOAD_SIZE = + "remote_config.max.payload.size"; // kb + // these two are specified in RCTE1 + public static final String REMOTE_CONFIG_TARGETS_KEY_ID = "rc.targets.key.id"; + public static final String REMOTE_CONFIG_TARGETS_KEY = "rc.targets.key"; + + private RemoteConfigConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java new file mode 100644 index 0000000000..3833509a78 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java @@ -0,0 +1,139 @@ +package datadog.trace.api.config; + +/** + * These config options will only work with dd-java-agent, not with dd-trace-ot. + * + *

Configure via system properties, environment variables, or config properties file. See online + * documentation for details. + * + * @see TracerConfig for more tracer config options + */ +public final class TraceInstrumentationConfig { + public static final String TRACE_ENABLED = "trace.enabled"; + public static final String TRACE_OTEL_ENABLED = "trace.otel.enabled"; + public static final String INTEGRATIONS_ENABLED = "integrations.enabled"; + public static final String LEGACY_INSTALLER_ENABLED = "legacy.installer.enabled"; + + public static final String INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME = + "integration.synapse.legacy-operation-name"; + public static final String TRACE_ANNOTATIONS = "trace.annotations"; + public static final String TRACE_ANNOTATION_ASYNC = "trace.annotation.async"; + public static final String TRACE_EXECUTORS_ALL = "trace.executors.all"; + public static final String TRACE_EXECUTORS = "trace.executors"; + public static final String TRACE_METHODS = "trace.methods"; + /* + format for measure.methods is the same as for trace.methods: + https://docs.datadoghq.com/tracing/trace_collection/custom_instrumentation/java/ + */ + public static final String MEASURE_METHODS = "measure.methods"; + public static final String TRACE_CLASSES_EXCLUDE = "trace.classes.exclude"; + public static final String TRACE_CLASSES_EXCLUDE_FILE = "trace.classes.exclude.file"; + public static final String TRACE_CLASSLOADERS_EXCLUDE = "trace.classloaders.exclude"; + public static final String TRACE_CODESOURCES_EXCLUDE = "trace.codesources.exclude"; + + @SuppressWarnings("unused") + public static final String TRACE_TESTS_ENABLED = "trace.tests.enabled"; + + public static final String TRACE_THREAD_POOL_EXECUTORS_EXCLUDE = + "trace.thread-pool-executors.exclude"; + + public static final String HTTP_SERVER_TAG_QUERY_STRING = "http.server.tag.query-string"; + public static final String HTTP_SERVER_RAW_QUERY_STRING = "http.server.raw.query-string"; + public static final String HTTP_SERVER_RAW_RESOURCE = "http.server.raw.resource"; + public static final String HTTP_SERVER_DECODED_RESOURCE_PRESERVE_SPACES = + "http.server.decoded.resource.preserve-spaces"; + public static final String HTTP_SERVER_ROUTE_BASED_NAMING = "http.server.route-based-naming"; + public static final String HTTP_CLIENT_TAG_QUERY_STRING = "http.client.tag.query-string"; + public static final String HTTP_CLIENT_TAG_HEADERS = "http.client.tag.headers"; + public static final String HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN = "trace.http.client.split-by-domain"; + public static final String DB_CLIENT_HOST_SPLIT_BY_INSTANCE = "trace.db.client.split-by-instance"; + public static final String DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX = + "trace.db.client.split-by-instance.type.suffix"; + public static final String DB_CLIENT_HOST_SPLIT_BY_HOST = "trace.db.client.split-by-host"; + + public static final String JDBC_PREPARED_STATEMENT_CLASS_NAME = + "trace.jdbc.prepared.statement.class.name"; + + public static final String DB_DBM_PROPAGATION_MODE_MODE = "dbm.propagation.mode"; + + public static final String JDBC_CONNECTION_CLASS_NAME = "trace.jdbc.connection.class.name"; + + public static final String HTTP_URL_CONNECTION_CLASS_NAME = + "trace.http.url.connection.class.name"; + + public static final String RUNTIME_CONTEXT_FIELD_INJECTION = + "trace.runtime.context.field.injection"; + public static final String SERIALVERSIONUID_FIELD_INJECTION = + "trace.serialversionuid.field.injection"; + + public static final String LOGS_INJECTION_ENABLED = "logs.injection"; + public static final String TRACE_128_BIT_TRACEID_LOGGING_ENABLED = + "trace.128.bit.traceid.logging.enabled"; + + public static final String KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS = + "kafka.client.propagation.disabled.topics"; + public static final String KAFKA_CLIENT_BASE64_DECODING_ENABLED = + "kafka.client.base64.decoding.enabled"; + + public static final String JMS_PROPAGATION_DISABLED_TOPICS = "jms.propagation.disabled.topics"; + public static final String JMS_PROPAGATION_DISABLED_QUEUES = "jms.propagation.disabled.queues"; + public static final String JMS_UNACKNOWLEDGED_MAX_AGE = "jms.unacknowledged.max.age"; + + public static final String RABBIT_PROPAGATION_DISABLED_QUEUES = + "rabbit.propagation.disabled.queues"; + public static final String RABBIT_PROPAGATION_DISABLED_EXCHANGES = + "rabbit.propagation.disabled.exchanges"; + + public static final String RABBIT_INCLUDE_ROUTINGKEY_IN_RESOURCE = + "rabbit.include.routingkey.in.resource"; + + public static final String MESSAGE_BROKER_SPLIT_BY_DESTINATION = + "message.broker.split-by-destination"; + + public static final String GRPC_IGNORED_INBOUND_METHODS = "trace.grpc.ignored.inbound.methods"; + public static final String GRPC_IGNORED_OUTBOUND_METHODS = "trace.grpc.ignored.outbound.methods"; + + public static final String GOOGLE_PUBSUB_IGNORED_GRPC_METHODS = + "trace.google-pubsub.ignored.grpc.methods"; + public static final String GRPC_SERVER_TRIM_PACKAGE_RESOURCE = + "trace.grpc.server.trim-package-resource"; + public static final String GRPC_SERVER_ERROR_STATUSES = "grpc.server.error.statuses"; + public static final String GRPC_CLIENT_ERROR_STATUSES = "grpc.client.error.statuses"; + public static final String HYSTRIX_TAGS_ENABLED = "hystrix.tags.enabled"; + public static final String HYSTRIX_MEASURED_ENABLED = "hystrix.measured.enabled"; + + public static final String IGNITE_CACHE_INCLUDE_KEYS = "ignite.cache.include_keys"; + + public static final String OBFUSCATION_QUERY_STRING_REGEXP = + "trace.obfuscation.query.string.regexp"; + + public static final String PLAY_REPORT_HTTP_STATUS = "trace.play.report-http-status"; + + public static final String SERVLET_PRINCIPAL_ENABLED = "trace.servlet.principal.enabled"; + public static final String SERVLET_ASYNC_TIMEOUT_ERROR = "trace.servlet.async-timeout.error"; + + public static final String SERVLET_ROOT_CONTEXT_SERVICE_NAME = + "trace.servlet.root-context.service.name"; + + public static final String SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME = + "spring-data.repository.interface.resource-name"; + + public static final String RESOLVER_CACHE_CONFIG = "resolver.cache.config"; + public static final String RESOLVER_CACHE_DIR = "resolver.cache.dir"; + public static final String RESOLVER_USE_LOADCLASS = "resolver.use.loadclass"; + public static final String RESOLVER_USE_URL_CACHES = "resolver.use.url.caches"; + public static final String RESOLVER_RESET_INTERVAL = "resolver.reset.interval"; + public static final String RESOLVER_NAMES_ARE_UNIQUE = "resolver.names.are.unique"; + + public static final String ELASTICSEARCH_BODY_ENABLED = "trace.elasticsearch.body.enabled"; + public static final String ELASTICSEARCH_PARAMS_ENABLED = "trace.elasticsearch.params.enabled"; + public static final String ELASTICSEARCH_BODY_AND_PARAMS_ENABLED = + "trace.elasticsearch.body-and-params.enabled"; + + public static final String SPARK_TASK_HISTOGRAM_ENABLED = "spark.task-histogram.enabled"; + + public static final String JAX_RS_EXCEPTION_AS_ERROR_ENABLED = + "trace.jax-rs.exception-as-error.enabled"; + + private TraceInstrumentationConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/TracerConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/TracerConfig.java new file mode 100644 index 0000000000..d48178d857 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/TracerConfig.java @@ -0,0 +1,135 @@ +package datadog.trace.api.config; + +/** + * A list of keys to be used in a Properties instance with dd-trace-ot's DDTracer as follows: + * + *

+ *   DDTracer.builder().withProperties(new Properties()).build()
+ * 
+ * + *

If using dd-java-agent, these keys represent settings that should be configured via system + * properties, environment variables, or config properties file. See online documentation for + * details. + * + * @see TraceInstrumentationConfig for instrumentation specific configuration + */ +public final class TracerConfig { + public static final String ID_GENERATION_STRATEGY = "id.generation.strategy"; + public static final String WRITER_TYPE = "writer.type"; + public static final String WRITER_BAGGAGE_INJECT = "writer.baggage.inject"; + + public static final String PRIORITIZATION_TYPE = "prioritization.type"; + public static final String TRACE_AGENT_URL = "trace.agent.url"; + public static final String AGENT_HOST = "agent.host"; + public static final String TRACE_AGENT_PORT = "trace.agent.port"; + public static final String AGENT_PORT_LEGACY = "agent.port"; + public static final String AGENT_UNIX_DOMAIN_SOCKET = "trace.agent.unix.domain.socket"; + public static final String AGENT_NAMED_PIPE = "trace.pipe.name"; + public static final String AGENT_TIMEOUT = "trace.agent.timeout"; + public static final String PROXY_NO_PROXY = "proxy.no_proxy"; + public static final String TRACE_AGENT_PATH = "trace.agent.path"; + public static final String TRACE_AGENT_ARGS = "trace.agent.args"; + public static final String PRIORITY_SAMPLING = "priority.sampling"; + public static final String PRIORITY_SAMPLING_FORCE = "priority.sampling.force"; + @Deprecated public static final String TRACE_RESOLVER_ENABLED = "trace.resolver.enabled"; + public static final String SERVICE_MAPPING = "service.mapping"; + + public static final String SPAN_TAGS = "trace.span.tags"; + public static final String TRACE_ANALYTICS_ENABLED = "trace.analytics.enabled"; + + @Deprecated + public static final String TRACE_SAMPLING_SERVICE_RULES = "trace.sampling.service.rules"; + + @Deprecated + public static final String TRACE_SAMPLING_OPERATION_RULES = "trace.sampling.operation.rules"; + // JSON rules + public static final String TRACE_SAMPLING_RULES = "trace.sampling.rules"; + public static final String SPAN_SAMPLING_RULES = "span.sampling.rules"; + public static final String SPAN_SAMPLING_RULES_FILE = "span.sampling.rules.file"; + // a global rate used for all services (that don’t have a dedicated rule defined). + public static final String TRACE_SAMPLE_RATE = "trace.sample.rate"; + public static final String TRACE_RATE_LIMIT = "trace.rate.limit"; + public static final String TRACE_REPORT_HOSTNAME = "trace.report-hostname"; + public static final String TRACE_CLIENT_IP_HEADER = "trace.client-ip-header"; + public static final String TRACE_CLIENT_IP_RESOLVER_ENABLED = "trace.client-ip.resolver.enabled"; + public static final String TRACE_GIT_METADATA_ENABLED = "trace.git.metadata.enabled"; + public static final String HEADER_TAGS = "trace.header.tags"; + public static final String REQUEST_HEADER_TAGS_COMMA_ALLOWED = + "trace.request_header.tags.comma.allowed"; + public static final String REQUEST_HEADER_TAGS = "trace.request_header.tags"; + public static final String RESPONSE_HEADER_TAGS = "trace.response_header.tags"; + public static final String BAGGAGE_MAPPING = "trace.header.baggage"; + public static final String TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH = + "trace.http.resource.remove-trailing-slash"; + public static final String TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING = + "trace.http.server.path-resource-name-mapping"; + public static final String TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING = + "trace.http.client.path-resource-name-mapping"; + public static final String HTTP_SERVER_ERROR_STATUSES = "http.server.error.statuses"; + public static final String HTTP_CLIENT_ERROR_STATUSES = "http.client.error.statuses"; + + public static final String SPLIT_BY_TAGS = "trace.split-by-tags"; + + public static final String SCOPE_DEPTH_LIMIT = "trace.scope.depth.limit"; + public static final String SCOPE_STRICT_MODE = "trace.scope.strict.mode"; + public static final String SCOPE_INHERIT_ASYNC_PROPAGATION = + "trace.scope.inherit.async.propagation"; + public static final String SCOPE_ITERATION_KEEP_ALIVE = "trace.scope.iteration.keep.alive"; + public static final String PARTIAL_FLUSH_ENABLED = "trace.partial.flush.enabled"; + public static final String PARTIAL_FLUSH_MIN_SPANS = "trace.partial.flush.min.spans"; + public static final String TRACE_STRICT_WRITES_ENABLED = "trace.strict.writes.enabled"; + public static final String PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED = + "propagation.extract.log_header_names.enabled"; + public static final String PROPAGATION_STYLE_EXTRACT = "propagation.style.extract"; + public static final String PROPAGATION_STYLE_INJECT = "propagation.style.inject"; + + public static final String TRACE_PROPAGATION_STYLE = "trace.propagation.style"; + public static final String TRACE_PROPAGATION_STYLE_EXTRACT = "trace.propagation.style.extract"; + public static final String TRACE_PROPAGATION_STYLE_INJECT = "trace.propagation.style.inject"; + public static final String TRACE_PROPAGATION_EXTRACT_FIRST = "trace.propagation.extract.first"; + + public static final String ENABLE_TRACE_AGENT_V05 = "trace.agent.v0.5.enabled"; + + public static final String CLIENT_IP_ENABLED = "trace.client-ip.enabled"; + + public static final String TRACE_128_BIT_TRACEID_GENERATION_ENABLED = + "trace.128.bit.traceid.generation.enabled"; + + public static final String SECURE_RANDOM = "trace.secure-random"; + + /** + * Disables validation that prevents invalid combinations of sampling priority and sampling + * mechanism on the set sampling priority calls. This check is enabled by default. + */ + public static final String SAMPLING_MECHANISM_VALIDATION_DISABLED = + "trace.sampling.mechanism.validation.disabled"; + + /** + * Limit for x-datadog-tags. When exceeded it will stop propagating Datadog tags and will log a + * warning. + */ + public static final String TRACE_X_DATADOG_TAGS_MAX_LENGTH = "trace.x-datadog-tags.max.length"; + + public static final String CLOCK_SYNC_PERIOD = "trace.clock.sync.period"; + + public static final String TRACE_SPAN_ATTRIBUTE_SCHEMA = "trace.span.attribute.schema"; + + public static final String TRACE_LONG_RUNNING_ENABLED = "trace.experimental.long-running.enabled"; + + public static final String TRACE_LONG_RUNNING_FLUSH_INTERVAL = + "trace.experimental.long-running.flush.interval"; + public static final String TRACE_PEER_SERVICE_DEFAULTS_ENABLED = + "trace.peer.service.defaults.enabled"; + + public static final String TRACE_PEER_SERVICE_COMPONENT_OVERRIDES = + "trace.peer.service.component.overrides"; + + public static final String TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED = + "trace.remove.integration-service-names.enabled"; + + public static final String TRACE_PEER_SERVICE_MAPPING = "trace.peer.service.mapping"; + + public static final String TRACE_FLUSH_INTERVAL = "trace.flush.interval"; + + private TracerConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/UsmConfig.java b/features/dd-trace-core/src/main/java/datadog/trace/api/config/UsmConfig.java new file mode 100644 index 0000000000..c84b832a1f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/config/UsmConfig.java @@ -0,0 +1,9 @@ +package datadog.trace.api.config; + +/** Constant with names of configuration options for USM. */ +public final class UsmConfig { + + public static final String USM_ENABLED = "usm.enabled"; + + private UsmConfig() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/env/CapturedEnvironment.java b/features/dd-trace-core/src/main/java/datadog/trace/api/env/CapturedEnvironment.java new file mode 100644 index 0000000000..d1f3fc7694 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/env/CapturedEnvironment.java @@ -0,0 +1,77 @@ +package datadog.trace.api.env; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import datadog.trace.api.config.GeneralConfig; + +/** + * The {@code CapturedEnvironment} instance keeps those {@code Config} values which are platform + * dependant. Notice that this class must be considered internal. You should not depend on it + * directly. + */ +public class CapturedEnvironment { + + private static final CapturedEnvironment INSTANCE = new CapturedEnvironment(); + + private final Map properties; + + CapturedEnvironment() { + properties = new HashMap<>(); + properties.put(GeneralConfig.SERVICE_NAME, autodetectServiceName()); + } + + public Map getProperties() { + return properties; + } + + // Testing purposes + static void useFixedEnv(final Map props) { + INSTANCE.properties.clear(); + + for (final Map.Entry entry : props.entrySet()) { + INSTANCE.properties.put(entry.getKey(), entry.getValue()); + } + } + + /** + * Returns autodetected service name based on the java process command line. Typically, the + * autodetection will return either the JAR filename or the java main class. + */ + private String autodetectServiceName() { + String inAas = System.getenv("DD_AZURE_APP_SERVICES"); + String siteName = System.getenv("WEBSITE_SITE_NAME"); + + if (("true".equalsIgnoreCase(inAas) || "1".equals(inAas)) && siteName != null) { + return siteName; + } + + // Besides "sun.java.command" property is not an standard, all main JDKs has set this property. + // Tested on: + // - OracleJDK, OpenJDK, AdoptOpenJDK, IBM JDK, Azul Zulu JDK, Amazon Coretto JDK + return extractJarOrClass(System.getProperty("sun.java.command")); + } + + private String extractJarOrClass(final String command) { + if (command == null || command.equals("")) { + return null; + } + + final String[] split = command.trim().split(" "); + if (split.length == 0 || split[0].equals("")) { + return null; + } + + final String candidate = split[0]; + if (candidate.endsWith(".jar")) { + return new File(candidate).getName().replace(".jar", ""); + } + + return candidate; + } + + public static CapturedEnvironment get() { + return INSTANCE; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsCheckpointer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsCheckpointer.java new file mode 100644 index 0000000000..574b9fdb2a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsCheckpointer.java @@ -0,0 +1,49 @@ +package datadog.trace.api.experimental; + +import datadog.trace.api.GlobalTracer; +import datadog.trace.api.Tracer; +import datadog.trace.api.internal.InternalTracer; + +/** An interface to Data Streams checkpointer, allowing passing the context manually. */ +public interface DataStreamsCheckpointer { + static DataStreamsCheckpointer get() { + Tracer tracer = GlobalTracer.get(); + if (tracer instanceof InternalTracer) { + return ((InternalTracer) tracer).getDataStreamsCheckpointer(); + } + + return NoOp.INSTANCE; + } + + /** + * @param type The type of the checkpoint, usually the streaming technology being used. Examples: + * kafka, kinesis, sns etc. + * @param source The source of data. For instance: topic, exchange or stream name. + * @param carrier An interface to the context carrier, from which the context will be extracted. + * I.e. wrapper around message headers. + */ + void setConsumeCheckpoint(String type, String source, DataStreamsContextCarrier carrier); + + /** + * @param type The type of the checkpoint, usually the streaming technology being used. Examples: + * kafka, kinesis, sns etc. + * @param target The destination to which the data is being sent. For instance: topic, exchange or + * stream name. + * @param carrier An interface to the context carrier, to which the context will be injected. I.e. + * wrapper around message headers. + */ + void setProduceCheckpoint(String type, String target, DataStreamsContextCarrier carrier); + + final class NoOp implements DataStreamsCheckpointer { + + public static final DataStreamsCheckpointer INSTANCE = new NoOp(); + + @Override + public void setConsumeCheckpoint( + String type, String source, DataStreamsContextCarrier carrier) {} + + @Override + public void setProduceCheckpoint( + String type, String target, DataStreamsContextCarrier carrier) {} + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsContextCarrier.java b/features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsContextCarrier.java new file mode 100644 index 0000000000..2d83b071a5 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsContextCarrier.java @@ -0,0 +1,31 @@ +package datadog.trace.api.experimental; + +import java.util.Collections; +import java.util.Map.Entry; +import java.util.Set; + +/** An interface representing the context carrier. Typically, message headers. */ +public interface DataStreamsContextCarrier { + /** @return A set of key value pairs, such as message headers. */ + Set> entries(); + + /** + * @param key parameter to be set + * @param value to be set + */ + void set(String key, String value); + + final class NoOp implements DataStreamsContextCarrier { + public static final DataStreamsContextCarrier INSTANCE = new NoOp(); + + private NoOp() {} + + @Override + public Set> entries() { + return Collections.emptySet(); + } + + @Override + public void set(String key, String value) {} + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/flare/TracerFlare.java b/features/dd-trace-core/src/main/java/datadog/trace/api/flare/TracerFlare.java new file mode 100644 index 0000000000..f2ba39041a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/flare/TracerFlare.java @@ -0,0 +1,84 @@ +package datadog.trace.api.flare; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public final class TracerFlare { + + public interface Reporter { + default void prepareForFlare() {} + + void addReportToFlare(ZipOutputStream zip) throws IOException; + + default void cleanupAfterFlare() {} + } + + private static final Map, Reporter> reporters = new ConcurrentHashMap<>(); + + public static void prepareForFlare() { + for (Reporter reporter : reporters.values()) { + try { + reporter.prepareForFlare(); + } catch (Throwable ignore) { + } + } + } + + public static void addReportsToFlare(ZipOutputStream zip) throws IOException { + List errors = null; + + for (Reporter reporter : reporters.values()) { + try { + reporter.addReportToFlare(zip); + } catch (Throwable e) { + if (null == errors) { + errors = new ArrayList<>(); + } + errors.add(e); + } + } + + if (null != errors) { + zip.putNextEntry(new ZipEntry("flare_errors.txt")); + for (Throwable e : errors) { + zip.write(e.toString().getBytes(UTF_8)); + zip.write('\n'); + } + } + } + + public static void cleanupAfterFlare() { + for (Reporter reporter : reporters.values()) { + try { + reporter.cleanupAfterFlare(); + } catch (Throwable ignore) { + } + } + } + + public static void addReporter(Reporter reporter) { + reporters.put(reporter.getClass(), reporter); + } + + public static void addText(ZipOutputStream zip, String section, String text) throws IOException { + zip.putNextEntry(new ZipEntry(section)); + if (null != text) { + zip.write(text.getBytes(UTF_8)); + } + } + + public static void addBinary(ZipOutputStream zip, String section, byte[] bytes) + throws IOException { + zip.putNextEntry(new ZipEntry(section)); + if (null != bytes) { + zip.write(bytes); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/function/TriConsumer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/function/TriConsumer.java new file mode 100644 index 0000000000..10abca7b64 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/function/TriConsumer.java @@ -0,0 +1,5 @@ +package datadog.trace.api.function; + +public interface TriConsumer { + void accept(S s, T t, U u); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/function/TriFunction.java b/features/dd-trace-core/src/main/java/datadog/trace/api/function/TriFunction.java new file mode 100644 index 0000000000..438793e712 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/function/TriFunction.java @@ -0,0 +1,5 @@ +package datadog.trace.api.function; + +public interface TriFunction { + R apply(T t, U u, V v); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/BlockResponseFunction.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/BlockResponseFunction.java new file mode 100644 index 0000000000..f3b8f7875c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/BlockResponseFunction.java @@ -0,0 +1,22 @@ +package datadog.trace.api.gateway; + +import java.util.Map; + +import datadog.trace.appsec.api.blocking.BlockingContentType; +import datadog.trace.api.internal.TraceSegment; + +public interface BlockResponseFunction { + /** + * Commits blocking response. + * + *

It's responsible for calling {@link TraceSegment#effectivelyBlocked()} before the span is + * finished. + * + * @return true unless blocking could not be attempted + */ + boolean tryCommitBlockingResponse( + TraceSegment segment, + int statusCode, + BlockingContentType templateType, + Map extraHeaders); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/CallbackProvider.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/CallbackProvider.java new file mode 100644 index 0000000000..e4f07f963d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/CallbackProvider.java @@ -0,0 +1,17 @@ +package datadog.trace.api.gateway; + +/** The API used by the producers to retrieve callbacks. */ +public interface CallbackProvider { + C getCallback(EventType eventType); + + class CallbackProviderNoop implements CallbackProvider { + public static final CallbackProvider INSTANCE = new CallbackProviderNoop(); + + private CallbackProviderNoop() {} + + @Override + public C getCallback(EventType eventType) { + return null; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/EventType.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/EventType.java new file mode 100644 index 0000000000..a14d2b5616 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/EventType.java @@ -0,0 +1,29 @@ +package datadog.trace.api.gateway; + +/** + * The {@code EventType} is a unique identifier for an event. + * + * @param The type of the callback related to the {@code EventType} + */ +public class EventType { + private final String name; + private final int id; + + protected EventType(final String name, final int id) { + this.name = name; + this.id = id; + } + + public String getName() { + return name; + } + + int getId() { + return id; + } + + @Override + public String toString() { + return "EventType{" + "name='" + name + '\'' + '}'; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Events.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Events.java new file mode 100644 index 0000000000..13c32706d1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Events.java @@ -0,0 +1,214 @@ +package datadog.trace.api.gateway; + +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; + +import datadog.trace.api.function.TriConsumer; +import datadog.trace.api.function.TriFunction; +import datadog.trace.api.http.StoredBodySupplier; +import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; + +/** All known {@code EventType} that the {@code InstrumentationGateway} can handle. */ +public final class Events { + private static final AtomicInteger nextId = new AtomicInteger(0); + + // The IDs that we define here need to be compile time constants for Java + // to be able to do a switch statement, hence we can't use nextId in the + // definitions of them :( + // There is a double check in the ET constructor that makes sure that we + // assign the IDs correctly. + + static final int REQUEST_STARTED_ID = 0; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_STARTED = new ET<>("request.started", REQUEST_STARTED_ID); + /** A request started */ + @SuppressWarnings("unchecked") + public EventType>> requestStarted() { + return (EventType>>) REQUEST_STARTED; + } + + static final int REQUEST_ENDED_ID = 1; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_ENDED = new ET<>("request.ended", REQUEST_ENDED_ID); + /** A request ended */ + @SuppressWarnings("unchecked") + public EventType>> requestEnded() { + return (EventType>>) REQUEST_ENDED; + } + + static final int REQUEST_HEADER_ID = 2; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_HEADER = + new ET<>("server.request.header", REQUEST_HEADER_ID); + /** A request header as a key and values separated by , */ + @SuppressWarnings("unchecked") + public EventType> requestHeader() { + return (EventType>) REQUEST_HEADER; + } + + static final int REQUEST_HEADER_DONE_ID = 3; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_HEADER_DONE = + new ET<>("server.request.header.done", REQUEST_HEADER_DONE_ID); + /** All request headers have been provided */ + @SuppressWarnings("unchecked") + public EventType>> requestHeaderDone() { + return (EventType>>) REQUEST_HEADER_DONE; + } + + static final int REQUEST_METHOD_URI_RAW_ID = 4; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_METHOD_URI_RAW = + new ET<>("server.request.method.uri.raw", REQUEST_METHOD_URI_RAW_ID); + /** The method (uppercase) and URIDataAdapter for the request. */ + @SuppressWarnings("unchecked") + public EventType>> + requestMethodUriRaw() { + return (EventType>>) + REQUEST_METHOD_URI_RAW; + } + + static final int REQUEST_PATH_PARAMS_ID = 5; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_PATH_PARAMS = + new ET<>("server.request.method.uri.raw", REQUEST_PATH_PARAMS_ID); + /** The parameters the framework got from the request uri (but not the query string) */ + @SuppressWarnings("unchecked") + public EventType, Flow>> requestPathParams() { + return (EventType, Flow>>) REQUEST_PATH_PARAMS; + } + + static final int REQUEST_CLIENT_SOCKET_ADDRESS_ID = 6; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_CLIENT_SOCKET_ADDRESS = + new ET<>("http.server.client_socket_address", REQUEST_CLIENT_SOCKET_ADDRESS_ID); + /** The method (uppercase) and URIDataAdapter for the request. */ + @SuppressWarnings("unchecked") + public EventType>> + requestClientSocketAddress() { + return (EventType>>) + REQUEST_CLIENT_SOCKET_ADDRESS; + } + + static final int REQUEST_INFERRED_CLIENT_ADDRESS_ID = 7; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_INFERRED_CLIENT_ADDRESS = + new ET<>("http.server.inferred_client_address", REQUEST_INFERRED_CLIENT_ADDRESS_ID); + /** The inferred client IP address. */ + @SuppressWarnings("unchecked") + public EventType>> requestInferredClientAddress() { + return (EventType>>) + REQUEST_INFERRED_CLIENT_ADDRESS; + } + + static final int REQUEST_BODY_START_ID = 8; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_BODY_START = + new ET<>("request.body.started", REQUEST_BODY_START_ID); + /** The request body has started being read */ + @SuppressWarnings("unchecked") + public EventType> requestBodyStart() { + return (EventType>) REQUEST_BODY_START; + } + + static final int REQUEST_BODY_DONE_ID = 9; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_BODY_DONE = + new ET<>("request.body.done", REQUEST_BODY_DONE_ID); + /** The request body is done being read */ + @SuppressWarnings("unchecked") + public EventType>> requestBodyDone() { + return (EventType>>) + REQUEST_BODY_DONE; + } + + static final int REQUEST_BODY_CONVERTED_ID = 10; + + @SuppressWarnings("rawtypes") + private static final EventType REQUEST_BODY_CONVERTED = + new ET<>("request.body.converted", REQUEST_BODY_CONVERTED_ID); + /** The request body has been converted by the framework */ + @SuppressWarnings("unchecked") + public EventType>> requestBodyProcessed() { + return (EventType>>) REQUEST_BODY_CONVERTED; + } + + static final int RESPONSE_STARTED_ID = 11; + + @SuppressWarnings("rawtypes") + private static final EventType RESPONSE_STARTED = + new ET<>("response.started", RESPONSE_STARTED_ID); + /** A response started */ + @SuppressWarnings("unchecked") + public EventType>> responseStarted() { + return (EventType>>) RESPONSE_STARTED; + } + + static final int RESPONSE_HEADER_ID = 12; + + @SuppressWarnings("rawtypes") + private static final EventType RESPONSE_HEADER = + new ET<>("server.response.header", RESPONSE_HEADER_ID); + /** A response header as a key and values separated by , */ + @SuppressWarnings("unchecked") + public EventType> responseHeader() { + return (EventType>) RESPONSE_HEADER; + } + + static final int RESPONSE_HEADER_DONE_ID = 13; + + @SuppressWarnings("rawtypes") + private static final EventType RESPONSE_HEADER_DONE = + new ET<>("server.response.header.done", RESPONSE_HEADER_DONE_ID); + /** All response headers have been provided */ + @SuppressWarnings("unchecked") + public EventType>> responseHeaderDone() { + return (EventType>>) RESPONSE_HEADER_DONE; + } + + static final int GRPC_SERVER_REQUEST_MESSAGE_ID = 14; + + @SuppressWarnings("rawtypes") + private static final EventType GRPC_SERVER_REQUEST_MESSAGE = + new ET<>("grpc.server.request.message", GRPC_SERVER_REQUEST_MESSAGE_ID); + /** All response headers have been provided */ + @SuppressWarnings("unchecked") + public EventType>> grpcServerRequestMessage() { + return (EventType>>) GRPC_SERVER_REQUEST_MESSAGE; + } + + static final int MAX_EVENTS = nextId.get(); + + private static final class ET extends EventType { + public ET(String type, int id) { + super(type, id); + int expectedId = nextId.getAndIncrement(); + if (id != expectedId) { + throw new IllegalArgumentException( + "Event " + type + " has broken id " + id + ", expected " + expectedId + "."); + } + } + } + + private Events() {} + + public static final Events EVENTS = new Events<>(); + + @SuppressWarnings("unchecked") + public static Events get() { + return (Events) EVENTS; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Flow.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Flow.java new file mode 100644 index 0000000000..6286dd6852 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Flow.java @@ -0,0 +1,98 @@ +package datadog.trace.api.gateway; + +import java.util.Collections; +import java.util.Map; + +import datadog.trace.appsec.api.blocking.BlockingContentType; + +/** + * The result of sending an event to a callback. + * + * @param the type of the result + */ +public interface Flow { + Action getAction(); + + T getResult(); + + interface Action { + boolean isBlocking(); + + class Noop implements Action { + public static Action INSTANCE = new Noop(); + + private Noop() {} + + public boolean isBlocking() { + return false; + } + } + + class RequestBlockingAction implements Action { + private final int statusCode; + private final BlockingContentType blockingContentType; + private final Map extraHeaders; + + public RequestBlockingAction( + int statusCode, + BlockingContentType blockingContentType, + Map extraHeaders) { + this.statusCode = statusCode; + this.blockingContentType = blockingContentType; + this.extraHeaders = extraHeaders; + } + + public RequestBlockingAction(int statusCode, BlockingContentType blockingContentType) { + this(statusCode, blockingContentType, Collections.emptyMap()); + } + + public static RequestBlockingAction forRedirect(int statusCode, String location) { + return new RequestBlockingAction( + statusCode, BlockingContentType.NONE, Collections.singletonMap("Location", location)); + } + + @Override + public boolean isBlocking() { + return true; + } + + public int getStatusCode() { + return statusCode; + } + + public BlockingContentType getBlockingContentType() { + return blockingContentType; + } + + public Map getExtraHeaders() { + return extraHeaders; + } + } + } + + class ResultFlow implements Flow { + @SuppressWarnings("rawtypes") + private static final ResultFlow EMPTY = new ResultFlow<>(null); + + @SuppressWarnings("unchecked") + public static ResultFlow empty() { + return (ResultFlow) EMPTY; + } + + private final R result; + + public ResultFlow(R result) { + this.result = result; + } + + @Override + public Action getAction() { + return Action.Noop.INSTANCE; + } + + @Override + public R getResult() { + return result; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/IGSpanInfo.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/IGSpanInfo.java new file mode 100644 index 0000000000..fdfe55d6f8 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/IGSpanInfo.java @@ -0,0 +1,20 @@ +package datadog.trace.api.gateway; + +import java.util.Map; + +import datadog.trace.api.DDTraceId; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; + +public interface IGSpanInfo { + DDTraceId getTraceId(); + + long getSpanId(); + + Map getTags(); + + AgentSpan setTag(String key, boolean value); + + void setRequestBlockingAction(Flow.Action.RequestBlockingAction rba); + + Flow.Action.RequestBlockingAction getRequestBlockingAction(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java new file mode 100644 index 0000000000..6df40dd685 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java @@ -0,0 +1,438 @@ +package datadog.trace.api.gateway; + +import static datadog.trace.api.gateway.Events.GRPC_SERVER_REQUEST_MESSAGE_ID; +import static datadog.trace.api.gateway.Events.MAX_EVENTS; +import static datadog.trace.api.gateway.Events.REQUEST_BODY_CONVERTED_ID; +import static datadog.trace.api.gateway.Events.REQUEST_BODY_DONE_ID; +import static datadog.trace.api.gateway.Events.REQUEST_BODY_START_ID; +import static datadog.trace.api.gateway.Events.REQUEST_CLIENT_SOCKET_ADDRESS_ID; +import static datadog.trace.api.gateway.Events.REQUEST_ENDED_ID; +import static datadog.trace.api.gateway.Events.REQUEST_HEADER_DONE_ID; +import static datadog.trace.api.gateway.Events.REQUEST_HEADER_ID; +import static datadog.trace.api.gateway.Events.REQUEST_INFERRED_CLIENT_ADDRESS_ID; +import static datadog.trace.api.gateway.Events.REQUEST_METHOD_URI_RAW_ID; +import static datadog.trace.api.gateway.Events.REQUEST_PATH_PARAMS_ID; +import static datadog.trace.api.gateway.Events.REQUEST_STARTED_ID; +import static datadog.trace.api.gateway.Events.RESPONSE_HEADER_DONE_ID; +import static datadog.trace.api.gateway.Events.RESPONSE_HEADER_ID; +import static datadog.trace.api.gateway.Events.RESPONSE_STARTED_ID; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; + +import datadog.trace.api.function.TriConsumer; +import datadog.trace.api.function.TriFunction; +import datadog.trace.api.http.StoredBodySupplier; +import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; + +/** The implementation of the {@code CallbackProvider} and {@code SubscriptionService}. */ +public class InstrumentationGateway { + private static final Logger log = LoggerFactory.getLogger(InstrumentationGateway.class); + + private final IGCallbackRegistry callbackRegistryAppSec; + private final IGCallbackRegistry callbackRegistryIast; + private final UniversalCallbackProvider universalCallbackProvider; + + public InstrumentationGateway() { + this.callbackRegistryAppSec = new IGCallbackRegistry(); + this.callbackRegistryIast = new IGCallbackRegistry(); + this.universalCallbackProvider = new UniversalCallbackProvider(); + } + + public SubscriptionService getSubscriptionService(RequestContextSlot slot) { + if (slot == RequestContextSlot.APPSEC) { + return this.callbackRegistryAppSec; + } else if (slot == RequestContextSlot.IAST) { + return this.callbackRegistryIast; + } else { + return SubscriptionService.SubscriptionServiceNoop.INSTANCE; + } + } + + public CallbackProvider getCallbackProvider(RequestContextSlot slot) { + if (slot == RequestContextSlot.APPSEC) { + return this.callbackRegistryAppSec; + } else if (slot == RequestContextSlot.IAST) { + return this.callbackRegistryIast; + } else { + return CallbackProvider.CallbackProviderNoop.INSTANCE; + } + } + + // for tests + void reset() { + this.callbackRegistryAppSec.reset(); + this.callbackRegistryIast.reset(); + this.universalCallbackProvider.reset(); + } + + public CallbackProvider getUniversalCallbackProvider() { + return this.universalCallbackProvider; + } + + private class UniversalCallbackProvider implements CallbackProvider { + final AtomicReferenceArray callbacks = new AtomicReferenceArray<>(MAX_EVENTS); + + @Override + public C getCallback(EventType eventType) { + int id = eventType.getId(); + C cb = (C) callbacks.get(id); + if (cb != null) { + return cb; + } + + cb = universalCallback(eventType); + if (!callbacks.compareAndSet(id, null, cb)) { + return getCallback(eventType); + } + return cb; + } + + void reset() { + for (int i = 0; i < callbacks.length(); i++) { + callbacks.set(i, null); + } + } + } + + private class IGCallbackRegistry implements CallbackProvider, SubscriptionService { + private final AtomicReferenceArray callbacks = new AtomicReferenceArray<>(MAX_EVENTS); + + // for tests + public void reset() { + for (int i = 0; i < callbacks.length(); i++) { + callbacks.set(i, null); + } + } + + void reset(EventType et) { + callbacks.set(et.getId(), null); + } + + @Override + @SuppressWarnings("unchecked") + public C getCallback(EventType eventType) { + return (C) callbacks.get(eventType.getId()); + } + + @Override + @SuppressWarnings("unchecked") + public Subscription registerCallback(final EventType eventType, final C callback) { + final C wrapped = wrap(eventType, callback); + final int id = eventType.getId(); + if (!callbacks.compareAndSet(id, null, wrapped)) { + C existing = (C) callbacks.get(id); + String message = + "Trying to overwrite existing callback " + existing + " for event type " + eventType; + log.warn(message); + throw new IllegalStateException(message); + } + + universalCallbackProvider.callbacks.set(id, null); + + return new Subscription() { + @Override + public void cancel() { + if (!callbacks.compareAndSet(id, wrapped, null)) { + if (log.isDebugEnabled()) { + log.debug("Failed to unregister callback {} for event type {}", callback, eventType); + } + } + } + }; + } + } + + /** Ensure that callbacks don't leak exceptions */ + @SuppressWarnings({"unchecked", "rawtypes", "DuplicateBranchesInSwitch"}) + public static C wrap(final EventType eventType, final C callback) { + switch (eventType.getId()) { + case REQUEST_STARTED_ID: + return (C) + new Supplier>() { + @Override + public Flow get() { + try { + return ((Supplier>) callback).get(); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return Flow.ResultFlow.empty(); + } + } + // Make testing easier by delegating equals + @Override + public boolean equals(Object obj) { + return callback.equals(obj); + } + }; + case REQUEST_ENDED_ID: + return (C) + new BiFunction>() { + @Override + public Flow apply(RequestContext ctx, IGSpanInfo agentSpan) { + try { + return ((BiFunction>) callback) + .apply(ctx, agentSpan); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return Flow.ResultFlow.empty(); + } + } + // Make testing easier by delegating equals + @Override + public boolean equals(Object obj) { + return callback.equals(obj); + } + }; + case REQUEST_HEADER_DONE_ID: + case RESPONSE_HEADER_DONE_ID: + return (C) + new Function>() { + @Override + public Flow apply(RequestContext ctx) { + try { + return ((Function>) callback).apply(ctx); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return Flow.ResultFlow.empty(); + } + } + // Make testing easier by delegating equals + @Override + public boolean equals(Object obj) { + return callback.equals(obj); + } + }; + case REQUEST_HEADER_ID: + case RESPONSE_HEADER_ID: + return (C) + new TriConsumer() { + @Override + public void accept(RequestContext ctx, String key, String value) { + try { + ((TriConsumer) callback).accept(ctx, key, value); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + } + } + // Make testing easier by delegating equals + @Override + public boolean equals(Object obj) { + return callback.equals(obj); + } + }; + case REQUEST_METHOD_URI_RAW_ID: + return (C) + new TriFunction>() { + @Override + public Flow apply(RequestContext ctx, String method, URIDataAdapter adapter) { + try { + return ((TriFunction>) + callback) + .apply(ctx, method, adapter); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return Flow.ResultFlow.empty(); + } + } + // Make testing easier by delegating equals + @Override + public boolean equals(Object obj) { + return callback.equals(obj); + } + }; + case REQUEST_PATH_PARAMS_ID: + return (C) + new BiFunction, Flow>() { + @Override + public Flow apply(RequestContext ctx, Map map) { + try { + return ((BiFunction, Flow>) callback) + .apply(ctx, map); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return Flow.ResultFlow.empty(); + } + } + // Make testing easier by delegating equals + @Override + public boolean equals(Object obj) { + return callback.equals(obj); + } + }; + case REQUEST_CLIENT_SOCKET_ADDRESS_ID: + return (C) + new TriFunction>() { + @Override + public Flow apply(RequestContext ctx, String ip, Integer port) { + try { + return ((TriFunction>) callback) + .apply(ctx, ip, port); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return Flow.ResultFlow.empty(); + } + } + // Make testing easier by delegating equals + @Override + public boolean equals(Object obj) { + return callback.equals(obj); + } + }; + case REQUEST_INFERRED_CLIENT_ADDRESS_ID: + return (C) + new BiFunction>() { + @Override + public Flow apply(RequestContext ctx, String ip) { + try { + return ((BiFunction>) callback).apply(ctx, ip); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return Flow.ResultFlow.empty(); + } + } + // Make testing easier by delegating equals + @Override + public boolean equals(Object obj) { + return callback.equals(obj); + } + }; + case REQUEST_BODY_START_ID: + return (C) + new BiFunction() { + @Override + public Void apply(RequestContext ctx, StoredBodySupplier storedBodySupplier) { + try { + return ((BiFunction) callback) + .apply(ctx, storedBodySupplier); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return null; + } + } + }; + case REQUEST_BODY_DONE_ID: + return (C) + new BiFunction>() { + @Override + public Flow apply(RequestContext ctx, StoredBodySupplier storedBodySupplier) { + try { + return ((BiFunction>) callback) + .apply(ctx, storedBodySupplier); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return Flow.ResultFlow.empty(); + } + } + }; + case GRPC_SERVER_REQUEST_MESSAGE_ID: + case REQUEST_BODY_CONVERTED_ID: + return (C) + new BiFunction>() { + @Override + public Flow apply(RequestContext ctx, Object obj) { + try { + return ((BiFunction>) callback) + .apply(ctx, obj); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return Flow.ResultFlow.empty(); + } + } + }; + case RESPONSE_STARTED_ID: + return (C) + new BiFunction>() { + @Override + public Flow apply(RequestContext ctx, Integer status) { + try { + return ((BiFunction>) callback) + .apply(ctx, status); + } catch (Throwable t) { + log.warn("Callback for {} threw.", eventType, t); + return Flow.ResultFlow.empty(); + } + } + }; + default: + log.warn("Unwrapped callback for {}", eventType); + return callback; + } + } + + private C universalCallback(final EventType eventType) { + final C callbackAppSec = + InstrumentationGateway.this.callbackRegistryAppSec.getCallback(eventType); + final C callbackIast = InstrumentationGateway.this.callbackRegistryIast.getCallback(eventType); + if (callbackAppSec == null && callbackIast == null) { + return null; + } + if (callbackAppSec != null && callbackIast == null) { + return callbackAppSec; + } + if (callbackAppSec == null && callbackIast != null) { + return callbackIast; + } + + switch (eventType.getId()) { + case REQUEST_ENDED_ID: + return (C) + (BiFunction>) + (ctx, agentSpan) -> { + Flow flowAppSec = + ((BiFunction>) callbackAppSec) + .apply(ctx, agentSpan); + Flow flowIast = + ((BiFunction>) callbackIast) + .apply(ctx, agentSpan); + return mergeFlows(flowAppSec, flowIast); + }; + case REQUEST_HEADER_ID: + return (C) + (TriConsumer) + (requestContext, s, s2) -> { + ((TriConsumer) callbackAppSec) + .accept(requestContext, s, s2); + ((TriConsumer) callbackIast) + .accept(requestContext, s, s2); + }; + case REQUEST_HEADER_DONE_ID: + return (C) + (Function>) + requestContext -> { + Flow flowAppSec = + ((Function>) callbackAppSec).apply(requestContext); + Flow flowIast = + ((Function>) callbackIast).apply(requestContext); + return mergeFlows(flowAppSec, flowIast); + }; + } + return null; + } + + public static Flow mergeFlows(final Flow flow1, final Flow flow2) { + if (flow1 == flow2) { + return flow1; + } + return new Flow() { + @Override + public Action getAction() { + return flow1.getAction().isBlocking() ? flow1.getAction() : flow2.getAction(); + } + + @Override + public T getResult() { + if (flow2.getResult() != null) { + return flow2.getResult(); + } + return flow1.getResult(); + } + }; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContext.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContext.java new file mode 100644 index 0000000000..eaa442ed9c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContext.java @@ -0,0 +1,47 @@ +package datadog.trace.api.gateway; + +import java.io.Closeable; +import java.io.IOException; + +import datadog.trace.api.internal.TraceSegment; + +/** + * This is the context that will travel along with the request and be presented to the + * Instrumentation Gateway subscribers. + */ +public interface RequestContext extends Closeable { + T getData(RequestContextSlot slot); + + TraceSegment getTraceSegment(); + + void setBlockResponseFunction(BlockResponseFunction blockResponseFunction); + + BlockResponseFunction getBlockResponseFunction(); + + class Noop implements RequestContext { + public static final RequestContext INSTANCE = new Noop(); + + private Noop() {} + + @Override + public T getData(RequestContextSlot slot) { + return null; + } + + @Override + public TraceSegment getTraceSegment() { + return TraceSegment.NoOp.INSTANCE; + } + + @Override + public void setBlockResponseFunction(BlockResponseFunction blockResponseFunction) {} + + @Override + public BlockResponseFunction getBlockResponseFunction() { + return null; + } + + @Override + public void close() throws IOException {} + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContextSlot.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContextSlot.java new file mode 100644 index 0000000000..9b1ebbf106 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContextSlot.java @@ -0,0 +1,7 @@ +package datadog.trace.api.gateway; + +public enum RequestContextSlot { + APPSEC, + CI_VISIBILITY, + IAST; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Subscription.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Subscription.java new file mode 100644 index 0000000000..dae58bf74d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Subscription.java @@ -0,0 +1,15 @@ +package datadog.trace.api.gateway; + +/** A handle to the started subscription of an event. */ +public interface Subscription { + void cancel(); + + class SubscriptionNoop implements Subscription { + public static final Subscription INSTANCE = new SubscriptionNoop(); + + private SubscriptionNoop() {} + + @Override + public void cancel() {} + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/SubscriptionService.java b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/SubscriptionService.java new file mode 100644 index 0000000000..48448135af --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/SubscriptionService.java @@ -0,0 +1,22 @@ +package datadog.trace.api.gateway; + +/** The API used by the consumers to register callbacks. */ +public interface SubscriptionService { + Subscription registerCallback(EventType eventType, C callback); + + void reset(); + + class SubscriptionServiceNoop implements SubscriptionService { + public static final SubscriptionService INSTANCE = new SubscriptionServiceNoop(); + + private SubscriptionServiceNoop() {} + + @Override + public Subscription registerCallback(EventType eventType, C callback) { + return Subscription.SubscriptionNoop.INSTANCE; + } + + @Override + public void reset() {} + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/CommitInfo.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/CommitInfo.java new file mode 100644 index 0000000000..3cd7182a2d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/git/CommitInfo.java @@ -0,0 +1,93 @@ +package datadog.trace.api.git; + +import java.util.Objects; + +public class CommitInfo { + + public static final CommitInfo NOOP = + new CommitInfo(null, PersonInfo.NOOP, PersonInfo.NOOP, null); + + private final String sha; + private final PersonInfo author; + private final PersonInfo committer; + private final String fullMessage; + + public CommitInfo(final String sha) { + this(sha, PersonInfo.NOOP, PersonInfo.NOOP, null); + } + + public CommitInfo( + final String sha, + final PersonInfo author, + final PersonInfo committer, + final String fullMessage) { + this.sha = sha; + this.author = author; + this.committer = committer; + this.fullMessage = fullMessage; + } + + public String getSha() { + return sha; + } + + public PersonInfo getAuthor() { + return author; + } + + public PersonInfo getCommitter() { + return committer; + } + + public String getFullMessage() { + return fullMessage; + } + + public boolean isEmpty() { + return (sha == null || sha.isEmpty()) + && (author == null || author.isEmpty()) + && (committer == null || committer.isEmpty()) + && (fullMessage == null || fullMessage.isEmpty()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final CommitInfo that = (CommitInfo) o; + return Objects.equals(sha, that.sha) + && Objects.equals(author, that.author) + && Objects.equals(committer, that.committer) + && Objects.equals(fullMessage, that.fullMessage); + } + + @Override + public int hashCode() { + int hash = 1; + hash = 31 * hash + (sha == null ? 0 : sha.hashCode()); + hash = 31 * hash + (author == null ? 0 : author.hashCode()); + hash = 31 * hash + (committer == null ? 0 : committer.hashCode()); + hash = 31 * hash + (fullMessage == null ? 0 : fullMessage.hashCode()); + return hash; + } + + @Override + public String toString() { + return "CommitInfo{" + + "sha='" + + sha + + '\'' + + ", author=" + + author + + ", committer=" + + committer + + ", fullMessage='" + + fullMessage + + '\'' + + '}'; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/EmbeddedGitInfoBuilder.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/EmbeddedGitInfoBuilder.java new file mode 100644 index 0000000000..62f03a49d9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/git/EmbeddedGitInfoBuilder.java @@ -0,0 +1,77 @@ +package datadog.trace.api.git; + +import androidx.annotation.Nullable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class EmbeddedGitInfoBuilder implements GitInfoBuilder { + + private static final Logger log = LoggerFactory.getLogger(EmbeddedGitInfoBuilder.class); + + private static final String EMBEDDED_GIT_PROPERTIES_FILE_NAME = "git.properties"; + + private final String resourceName; + + public EmbeddedGitInfoBuilder() { + this(EMBEDDED_GIT_PROPERTIES_FILE_NAME); + } + + EmbeddedGitInfoBuilder(String resourceName) { + this.resourceName = resourceName; + } + + @Override + public GitInfo build(@Nullable String repositoryPath) { + Properties gitProperties = new Properties(); + try (InputStream is = ClassLoader.getSystemResourceAsStream(resourceName)) { + if (is != null) { + gitProperties.load(is); + } else { + log.debug("Could not find embedded Git properties resource: {}", resourceName); + } + } catch (IOException e) { + log.error("Error reading embedded Git properties from {}", resourceName, e); + } + + String commitSha = gitProperties.getProperty("git.commit.id"); + if (commitSha == null) { + commitSha = gitProperties.getProperty("git.commit.id.full"); + } + + String committerTime = gitProperties.getProperty("git.commit.committer.time"); + if (committerTime == null) { + committerTime = gitProperties.getProperty("git.commit.time"); + } + + String authorTime = gitProperties.getProperty("git.commit.author.time"); + if (authorTime == null) { + authorTime = gitProperties.getProperty("git.commit.time"); + } + + return new GitInfo( + gitProperties.getProperty("git.remote.origin.url"), + gitProperties.getProperty("git.branch"), + gitProperties.getProperty("git.tags"), + new CommitInfo( + commitSha, + new PersonInfo( + gitProperties.getProperty("git.commit.user.name"), + gitProperties.getProperty("git.commit.user.email"), + authorTime), + new PersonInfo( + gitProperties.getProperty("git.commit.user.name"), + gitProperties.getProperty("git.commit.user.email"), + committerTime), + gitProperties.getProperty("git.commit.message.full"))); + } + + @Override + public int order() { + return Integer.MAX_VALUE; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfo.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfo.java new file mode 100644 index 0000000000..4708d3b502 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfo.java @@ -0,0 +1,80 @@ +package datadog.trace.api.git; + +import java.util.Objects; + +public class GitInfo { + + public static final GitInfo NOOP = new GitInfo(null, null, null, CommitInfo.NOOP); + + public static final String DD_GIT_REPOSITORY_URL = "DD_GIT_REPOSITORY_URL"; + public static final String DD_GIT_BRANCH = "DD_GIT_BRANCH"; + public static final String DD_GIT_TAG = "DD_GIT_TAG"; + public static final String DD_GIT_COMMIT_SHA = "DD_GIT_COMMIT_SHA"; + public static final String DD_GIT_COMMIT_MESSAGE = "DD_GIT_COMMIT_MESSAGE"; + public static final String DD_GIT_COMMIT_AUTHOR_NAME = "DD_GIT_COMMIT_AUTHOR_NAME"; + public static final String DD_GIT_COMMIT_AUTHOR_EMAIL = "DD_GIT_COMMIT_AUTHOR_EMAIL"; + public static final String DD_GIT_COMMIT_AUTHOR_DATE = "DD_GIT_COMMIT_AUTHOR_DATE"; + public static final String DD_GIT_COMMIT_COMMITTER_NAME = "DD_GIT_COMMIT_COMMITTER_NAME"; + public static final String DD_GIT_COMMIT_COMMITTER_EMAIL = "DD_GIT_COMMIT_COMMITTER_EMAIL"; + public static final String DD_GIT_COMMIT_COMMITTER_DATE = "DD_GIT_COMMIT_COMMITTER_DATE"; + + private final String repositoryURL; + private final String branch; + private final String tag; + private final CommitInfo commit; + + public GitInfo(String repositoryURL, String branch, String tag, CommitInfo commit) { + this.repositoryURL = repositoryURL; + this.branch = branch; + this.tag = tag; + this.commit = commit; + } + + public String getRepositoryURL() { + return repositoryURL; + } + + public String getBranch() { + return branch; + } + + public String getTag() { + return tag; + } + + public CommitInfo getCommit() { + return commit; + } + + public boolean isEmpty() { + return (repositoryURL == null || repositoryURL.isEmpty()) + && (branch == null || branch.isEmpty()) + && (tag == null || tag.isEmpty()) + && (commit == null || commit.isEmpty()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GitInfo gitInfo = (GitInfo) o; + return Objects.equals(repositoryURL, gitInfo.repositoryURL) + && Objects.equals(branch, gitInfo.branch) + && Objects.equals(tag, gitInfo.tag) + && Objects.equals(commit, gitInfo.commit); + } + + @Override + public int hashCode() { + int hash = 1; + hash = 31 * hash + (repositoryURL == null ? 0 : repositoryURL.hashCode()); + hash = 31 * hash + (branch == null ? 0 : branch.hashCode()); + hash = 31 * hash + (tag == null ? 0 : tag.hashCode()); + hash = 31 * hash + (commit == null ? 0 : commit.hashCode()); + return hash; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoBuilder.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoBuilder.java new file mode 100644 index 0000000000..9951d5df1b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoBuilder.java @@ -0,0 +1,9 @@ +package datadog.trace.api.git; + +import androidx.annotation.Nullable; + +public interface GitInfoBuilder { + GitInfo build(@Nullable String repositoryPath); + + int order(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoProvider.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoProvider.java new file mode 100644 index 0000000000..d1c23f01e4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoProvider.java @@ -0,0 +1,167 @@ +package datadog.trace.api.git; + +import androidx.annotation.Nullable; + +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Predicate; + +import datadog.trace.api.cache.DDCache; +import datadog.trace.api.cache.DDCaches; +import datadog.trace.util.Strings; + +public class GitInfoProvider { + + public static final GitInfoProvider INSTANCE; + + static { + INSTANCE = new GitInfoProvider(); + INSTANCE.registerGitInfoBuilder(new UserSuppliedGitInfoBuilder()); + } + + private volatile Collection builders = Collections.emptyList(); + + // in regular cases git info has to be built only once, + // but there is a rare exception: + // when attaching to a Gradle Daemon, + // it is possible to have builds from multiple repositories + // executed in the same process; + // 4 is chosen somewhat randomly, since we want to make memory footprint small + // and having more than 4 builds from different repos running in parallel + // in the same daemon is unlikely + private final DDCache gitInfoCache = DDCaches.newFixedSizeCache(4); + + public GitInfo getGitInfo() { + return getGitInfo(null); + } + + public GitInfo getGitInfo(@Nullable String repositoryPath) { + if (repositoryPath == null) { + repositoryPath = Paths.get("").toAbsolutePath().toString(); + } + return gitInfoCache.computeIfAbsent(repositoryPath, this::buildGitInfo); + } + + private GitInfo buildGitInfo(String repositoryPath) { + Evaluator evaluator = new Evaluator(repositoryPath, builders); + return new GitInfo( + evaluator.get( + gi -> GitUtils.filterSensitiveInfo(gi.getRepositoryURL()), + GitInfoProvider::validateGitRemoteUrl), + evaluator.get(GitInfo::getBranch, Strings::isNotBlank), + evaluator.get(GitInfo::getTag, Strings::isNotBlank), + new CommitInfo( + evaluator.get(gi1 -> gi1.getCommit().getSha(), Strings::isNotBlank), + new PersonInfo( + evaluator.getIfCommitShaMatches( + gi -> gi.getCommit().getAuthor().getName(), Strings::isNotBlank), + evaluator.getIfCommitShaMatches( + gi -> gi.getCommit().getAuthor().getEmail(), Strings::isNotBlank), + evaluator.getIfCommitShaMatches( + gi -> gi.getCommit().getAuthor().getIso8601Date(), Strings::isNotBlank)), + new PersonInfo( + evaluator.getIfCommitShaMatches( + gi -> gi.getCommit().getCommitter().getName(), Strings::isNotBlank), + evaluator.getIfCommitShaMatches( + gi -> gi.getCommit().getCommitter().getEmail(), Strings::isNotBlank), + evaluator.getIfCommitShaMatches( + gi -> gi.getCommit().getCommitter().getIso8601Date(), Strings::isNotBlank)), + evaluator.getIfCommitShaMatches( + gi -> gi.getCommit().getFullMessage(), Strings::isNotBlank))); + } + + private static boolean validateGitRemoteUrl(String s) { + // we cannot work with URL that uses "file://" protocol + return Strings.isNotBlank(s) && !s.startsWith("file:"); + } + + /** + * Uses provided GitInfoBuilder instances to get GitInfo data. + * + *

Provided builders are sorted according to priority: those builders that are first in the + * list have higher priority. + * + *

GitInfo is evaluated at most once for each builder, and the evaluation is lazy: if all + * required info can be retrieved from a higher-priority builder, those with lower priority will + * not be evaluated. + */ + private static final class Evaluator { + private final String repositoryPath; + private final Map infos; + + private Evaluator(String repositoryPath, Collection builders) { + this.repositoryPath = repositoryPath; + this.infos = new LinkedHashMap<>(); + for (GitInfoBuilder builder : builders) { + infos.put(builder, null); + } + } + + private String get(Function function, Predicate validator) { + return get(function, validator, false); + } + + /** + * If a builder with a higher priority has commit SHA that differs from that of a builder with + * lower priority, lower-priority info will be ignored. + */ + private String getIfCommitShaMatches( + Function function, Predicate validator) { + return get(function, validator, true); + } + + private String get( + Function function, + Predicate validator, + boolean checkShaIntegrity) { + String commitSha = null; + for (Map.Entry e : infos.entrySet()) { + GitInfo info = e.getValue(); + if (info == null) { + GitInfoBuilder builder = e.getKey(); + info = builder.build(repositoryPath); + e.setValue(info); + } + + if (checkShaIntegrity) { + CommitInfo currentCommit = info.getCommit(); + String currentCommitSha = currentCommit != null ? currentCommit.getSha() : null; + if (Strings.isNotBlank(currentCommitSha)) { + if (commitSha == null) { + commitSha = currentCommitSha; + } else if (!commitSha.equals(currentCommitSha)) { + // We already have a commit SHA from source that has higher priority. + // Commit SHA from current source is different, so we have to skip it + continue; + } + } + } + + String result = function.apply(info); + if (validator.test(result)) { + return result; + } + } + return null; + } + } + + public synchronized void registerGitInfoBuilder(GitInfoBuilder builder) { + List updatedBuilders = new ArrayList<>(builders); + updatedBuilders.add(builder); + updatedBuilders.sort(Comparator.comparingInt(GitInfoBuilder::order)); + builders = updatedBuilders; + gitInfoCache.clear(); + } + + public synchronized void invalidateCache() { + gitInfoCache.clear(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitUtils.java new file mode 100644 index 0000000000..036f569880 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitUtils.java @@ -0,0 +1,228 @@ +package datadog.trace.api.git; + +import static datadog.trace.api.git.RawParseUtils.decode; +import static datadog.trace.api.git.RawParseUtils.nextLF; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.regex.Pattern; +import java.util.zip.DataFormatException; +import java.util.zip.Inflater; + +public class GitUtils { + + private static final Pattern ORIGIN_PATTERN = Pattern.compile("origin/", Pattern.LITERAL); + private static final Pattern REFS_HEADS_PATTERN = Pattern.compile("refs/heads/", Pattern.LITERAL); + private static final Pattern REFS_TAGS_PATTERN = Pattern.compile("refs/tags/", Pattern.LITERAL); + private static final Pattern TAGS_PATTERN = Pattern.compile("tags/", Pattern.LITERAL); + + private static final Logger log = LoggerFactory.getLogger(GitUtils.class); + + /** + * Normalizes Git tag references: + * + *

    + *
  • refs/tags/my-tag -> my tag + *
+ * + * @param rawTagRef + * @return git reference normalized. + */ + public static String normalizeTag(final String rawTagRef) { + return normalizeRef(rawTagRef); + } + + /** + * Normalizes Git branch references: + * + *
    + *
  • origin/my-branch -> my-branch + *
  • refs/heads/my-branch -> my-branch + *
+ * + *

If the reference starts with "tags/" or contains "/tags/",null is returned + * + * @param rawBranchRef + * @return git reference normalized. + */ + public static String normalizeBranch(final String rawBranchRef) { + if (isTagReference(rawBranchRef)) { + return null; + } else { + return normalizeRef(rawBranchRef); + } + } + + public static boolean isTagReference(final String ref) { + return ref != null && (ref.startsWith("tags/") || ref.contains("/tags/")); + } + + private static String normalizeRef(final String rawRef) { + if (rawRef == null || rawRef.isEmpty()) { + return null; + } + + String ref = rawRef; + if (ref.startsWith("origin")) { + ref = ORIGIN_PATTERN.matcher(ref).replaceAll(""); + } else if (ref.startsWith("refs/heads")) { + ref = REFS_HEADS_PATTERN.matcher(ref).replaceAll(""); + } + + if (ref.startsWith("refs/tags")) { + return REFS_TAGS_PATTERN.matcher(ref).replaceAll(""); + } else if (ref.startsWith("tags")) { + return TAGS_PATTERN.matcher(ref).replaceAll(""); + } + + return ref; + } + + private static final Pattern SSH_PROTOCOL_AND_USER_INFO = Pattern.compile("^(ssh://).*?@"); + + /** + * Removes the user info of a certain URL. E.g: https://user:password@host.com/path -> + * https://host.com/path + * + * @param urlStr + * @return url without user info. + */ + public static String filterSensitiveInfo(final String urlStr) { + if (urlStr == null || urlStr.isEmpty()) { + return null; + } + try { + if (urlStr.startsWith("http")) { + final URI url = new URI(urlStr); + final String userInfo = url.getRawUserInfo(); + return Pattern.compile(userInfo + "@", Pattern.LITERAL).matcher(urlStr).replaceAll(""); + } else { + return SSH_PROTOCOL_AND_USER_INFO.matcher(urlStr).replaceAll("$1"); + } + } catch (final Exception ex) { + return urlStr; + } + } + + /** + * Splits the git author in the form `John Doe ` in a PersonInfo with name: + * John Doe and email: john.doe@email.com + * + * @param rawAuthor + * @return PersonInfo + */ + public static PersonInfo splitAuthorAndEmail(String rawAuthor) { + if (rawAuthor == null || rawAuthor.isEmpty()) { + return PersonInfo.NOOP; + } + + final byte[] raw = rawAuthor.getBytes(StandardCharsets.UTF_8); + final int nameB = 0; + + // First, we find the index where the email starts and ends: + final int emailB = nextLF(raw, nameB, '<'); + final int emailE = nextLF(raw, emailB, '>'); + if (emailB >= raw.length + || raw[emailB] == '\n' + || (emailE >= raw.length - 1 && raw[emailE - 1] != '>')) { + return PersonInfo.NOOP; + } + + // We need to find which is the index where the name ends, + // using the relative position where the email starts. + final int nameEnd = emailB - 2 >= nameB && raw[emailB - 2] == ' ' ? emailB - 2 : emailB - 1; + + // Once we have the indexes where the name starts and ends + // we can extract the name. + final String name = decode(raw, nameB, nameEnd); + + // Same approach to extract the email, using the indexes + // where the email starts and ends. + final String email = decode(raw, emailB, emailE - 1); + + return new PersonInfo(name, email); + } + + /** + * Decompress the byte array passed as argument using Java Inflater. The git objects are stored + * using ZLib compression. + * + *

If the decompression process requires a preset dictionary or the input is not enough, we + * return null. + * + * @param bytes compress data + * @return decompressed data or null + * @throws DataFormatException + */ + public static byte[] inflate(final byte[] bytes) throws DataFormatException { + try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + + // Git objects are compressed with ZLib. + // We need to decompress it using Inflater. + final Inflater ifr = new Inflater(); + try { + ifr.setInput(bytes); + final byte[] tmp = new byte[4 * 1024]; + while (!ifr.finished()) { + final int size = ifr.inflate(tmp); + if (size != 0) { + baos.write(tmp, 0, size); + } else { + // Inflater can return !finished but 0 bytes inflated. + if (ifr.needsDictionary()) { + logErrorInflating( + "The data was compressed using a preset dictionary. We cannot decompress it."); + return null; + } else if (ifr.needsInput()) { + logErrorInflating("The provided data is not enough. It might be corrupted"); + return null; + } else { + // At this point, neither dictionary nor input is needed. + // We break the loop and we will use the decompressed data that we already have. + break; + } + } + } + + return baos.toByteArray(); + } finally { + ifr.end(); + } + } catch (final IOException e) { + return null; + } + } + + private static void logErrorInflating(final String reason) { + log.warn("Could not decompressed git object: Reason {}", reason); + } + + /** + * Checks if the provided string is a valid commit SHA: + * + *

    + *
  • length >= 40 + *
  • every character is a hexadecimal digit + *
+ */ + public static boolean isValidCommitSha(final String commitSha) { + if (commitSha == null || commitSha.length() < 40) { + return false; + } + for (char c : commitSha.toCharArray()) { + if (!isHex(c)) { + return false; + } + } + return true; + } + + private static boolean isHex(char c) { + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/PersonInfo.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/PersonInfo.java new file mode 100644 index 0000000000..3b1019f894 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/git/PersonInfo.java @@ -0,0 +1,103 @@ +package datadog.trace.api.git; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Objects; +import java.util.TimeZone; + +public class PersonInfo { + + public static final PersonInfo NOOP = new PersonInfo(); + + private static final String DATE_FORMAT_ISO8601 = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; + + private final String name; + private final String email; + private final String iso8601Date; + + public PersonInfo() { + this(null, null, 0, 0); + } + + public PersonInfo(final String name, final String email) { + this(name, email, 0, 0); + } + + public PersonInfo(final String name, final String email, final String iso8601date) { + this.name = name; + this.email = email; + iso8601Date = iso8601date; + } + + public PersonInfo(String name, String email, long when, int tzOffset) { + this.name = name; + this.email = email; + iso8601Date = buildISO8601Date(when); + } + + public String getName() { + return name; + } + + public String getEmail() { + return email; + } + + public String getIso8601Date() { + return iso8601Date; + } + + public boolean isEmpty() { + return (name == null || name.isEmpty()) + && (email == null || email.isEmpty()) + && (iso8601Date == null || iso8601Date.isEmpty()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PersonInfo that = (PersonInfo) o; + return Objects.equals(name, that.name) + && Objects.equals(email, that.email) + && Objects.equals(iso8601Date, that.iso8601Date); + } + + @Override + public int hashCode() { + int hash = 1; + hash = 31 * hash + (name == null ? 0 : name.hashCode()); + hash = 31 * hash + (email == null ? 0 : email.hashCode()); + hash = 31 * hash + (iso8601Date == null ? 0 : iso8601Date.hashCode()); + return hash; + } + + @Override + public String toString() { + return "PersonInfo{" + + "name='" + + name + + '\'' + + ", email='" + + email + + '\'' + + ", ISO8601Date='" + + iso8601Date + + '\'' + + '}'; + } + + private static String buildISO8601Date(final long when) { + if (when <= 0) { + return null; + } + + final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_ISO8601); + sdf.setTimeZone(TimeZone.getTimeZone("UTC")); + return sdf.format(new Date(when)); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/RawParseUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/RawParseUtils.java new file mode 100644 index 0000000000..40d91a2634 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/git/RawParseUtils.java @@ -0,0 +1,392 @@ +package datadog.trace.api.git; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.nio.ByteBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.util.Arrays; + +/** + * Contains utility methods to be used in the byte[] content of a certain Git object. This class is + * based on the RawParseUtils class which is kept in the JGit library. + * https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java + */ +public final class RawParseUtils { + + private RawParseUtils() {} + + public static final byte[] COMMITTER = "committer ".getBytes(); + public static final byte[] AUTHOR = "author ".getBytes(); + + private static final byte[] digits10; + + static { + digits10 = new byte['9' + 1]; + Arrays.fill(digits10, (byte) -1); + for (char i = '0'; i <= '9'; i++) { + digits10[i] = (byte) (i - '0'); + } + } + + /** + * Locate the position of the commit message body. + * + * @param b buffer to scan. + * @param ptr position in buffer to start the scan at. Most callers should pass 0 to ensure the + * scan starts from the beginning of the commit buffer. + * @return position of the user's message buffer. + */ + public static int commitMessage(final byte[] b, int ptr) { + final int sz = b.length; + if (ptr == 0) { + ptr += 46; // skip the "tree ..." line. + } + while (ptr < sz && b[ptr] == 'p') { + ptr += 48; // skip this parent. + } + + // Skip any remaining header lines, ignoring what their actual + // header line type is. This is identical to the logic for a tag. + // + return tagMessage(b, ptr); + } + + /** + * Locate the position of the tag message body. + * + * @param b buffer to scan. + * @param ptr position in buffer to start the scan at. Most callers should pass 0 to ensure the + * scan starts from the beginning of the tag buffer. + * @return position of the user's message buffer. + */ + public static int tagMessage(final byte[] b, int ptr) { + final int sz = b.length; + if (ptr == 0) { + ptr += 48; // skip the "object ..." line. + } + while (ptr < sz && b[ptr] != '\n') { + ptr = nextLF(b, ptr); + } + if (ptr < sz && b[ptr] == '\n') { + return ptr + 1; + } + return -1; + } + + /** + * Locate the "committer " header line data. + * + * @param b buffer to scan. + * @param ptr position in buffer to start the scan at. Most callers should pass 0 to ensure the + * scan starts from the beginning of the commit buffer and does not accidentally look at + * message body. + * @return position just after the space in "committer ", so the first character of the + * committer's name. If no committer header can be located -1 is returned. + */ + public static int committer(final byte[] b, int ptr) { + final int sz = b.length; + if (ptr == 0) { + ptr += 46; // skip the "tree ..." line. + } + while (ptr < sz && b[ptr] == 'p') { + ptr += 48; // skip this parent. + } + if (ptr < sz && b[ptr] == 'a') { + ptr = nextLF(b, ptr); + } + return match(b, ptr, COMMITTER); + } + + /** + * Locate the "author " header line data. + * + * @param b buffer to scan. + * @param ptr position in buffer to start the scan at. Most callers should pass 0 to ensure the + * scan starts from the beginning of the commit buffer and does not accidentally look at + * message body. + * @return position just after the space in "author ", so the first character of the author's + * name. If no author header can be located -1 is returned. + */ + public static final int author(final byte[] b, int ptr) { + final int sz = b.length; + if (ptr == 0) { + ptr += 46; // skip the "tree ..." line. + } + while (ptr < sz && b[ptr] == 'p') { + ptr += 48; // skip this parent. + } + return match(b, ptr, AUTHOR); + } + + /** + * Locate the first position after the next LF. + * + *

This method stops on the first '\n' it finds. + * + * @param b buffer to scan. + * @param ptr position within buffer to start looking for LF at. + * @return new position just after the first LF found. + */ + public static int nextLF(final byte[] b, final int ptr) { + return next(b, ptr, '\n'); + } + + /** + * Locate the first position after either the given character or LF. + * + *

This method stops on the first match it finds from either chrA or '\n'. + * + * @param b buffer to scan. + * @param ptr position within buffer to start looking for chrA or LF at. + * @param chrA character to find. + * @return new position just after the first chrA or LF to be found. + */ + public static int nextLF(final byte[] b, int ptr, final char chrA) { + final int sz = b.length; + while (ptr < sz) { + final byte c = b[ptr++]; + if (c == chrA || c == '\n') { + return ptr; + } + } + return ptr; + } + + /** + * Locate the first position after a given character. + * + * @param b buffer to scan. + * @param ptr position within buffer to start looking for chrA at. + * @param chrA character to find. + * @return new position just after chrA. + */ + public static int next(final byte[] b, int ptr, final char chrA) { + final int sz = b.length; + while (ptr < sz) { + if (b[ptr++] == chrA) { + return ptr; + } + } + return ptr; + } + + /** + * Determine if b[ptr] matches src. + * + * @param b the buffer to scan. + * @param ptr first position within b, this should match src[0]. + * @param src the buffer to test for equality with b. + * @return ptr + src.length if b[ptr..src.length] == src; else -1. + */ + public static int match(final byte[] b, int ptr, final byte[] src) { + if (ptr + src.length > b.length) { + return -1; + } + for (int i = 0; i < src.length; i++, ptr++) { + if (b[ptr] != src[i]) { + return -1; + } + } + return ptr; + } + + /** + * Decode a region of the buffer under the specified character set if possible. + * + *

If the byte stream cannot be decoded that way, the platform default is tried and if that too + * fails, the fail-safe ISO-8859-1 encoding is tried. + * + * @param buffer buffer to pull raw bytes from. + * @param start first position within the buffer to take data from. + * @param end one position past the last location within the buffer to take data from. + * @return a string representation of the range [start,end), after decoding the + * region through the specified character set. + */ + public static String decode(final byte[] buffer, final int start, final int end) { + final ByteBuffer b = ByteBuffer.wrap(buffer, start, end - start); + b.mark(); + + try { + final CharsetDecoder d = UTF_8.newDecoder(); + d.onMalformedInput(CodingErrorAction.REPORT); + d.onUnmappableCharacter(CodingErrorAction.REPORT); + return d.decode(b).toString(); + } catch (final CharacterCodingException e) { + b.reset(); + + // Fall back to an ISO-8859-1 style encoding. At least all of + // the bytes will be present in the output. + // + return extractBinaryString(buffer, start, end); + } + } + + /** + * Decode a region of the buffer under the ISO-8859-1 encoding. + * + *

Each byte is treated as a single character in the 8859-1 character encoding, performing a + * raw binary->char conversion. + * + * @param buffer buffer to pull raw bytes from. + * @param start first position within the buffer to take data from. + * @param end one position past the last location within the buffer to take data from. + * @return a string representation of the range [start,end). + */ + public static String extractBinaryString(final byte[] buffer, final int start, final int end) { + final StringBuilder r = new StringBuilder(end - start); + for (int i = start; i < end; i++) { + r.append((char) (buffer[i] & 0xff)); + } + return r.toString(); + } + + /** + * Get last index of {@code ch} in raw, trimming spaces. + * + * @param raw buffer to scan. + * @param ch character to find. + * @param pos starting position. + * @return last index of {@code ch} in raw, trimming spaces. + * @since 4.1 + */ + public static int lastIndexOfTrim(final byte[] raw, final char ch, int pos) { + while (pos >= 0 && raw[pos] == ' ') { + pos--; + } + + while (pos >= 0 && raw[pos] != ch) { + pos--; + } + + return pos; + } + + /** + * Parse a base 10 numeric from a sequence of ASCII digits into a long. + * + *

Digit sequences can begin with an optional run of spaces before the sequence, and may start + * with a '+' or a '-' to indicate sign position. Any other characters will cause the method to + * stop and return the current result to the caller. + * + * @param b buffer to scan. + * @param ptr position within buffer to start parsing digits at. + * @return the value at this location; 0 if the location is not a valid numeric. + */ + public static long parseLongBase10(final byte[] b, int ptr) { + long r = 0; + int sign = 0; + try { + final int sz = b.length; + while (ptr < sz && b[ptr] == ' ') { + ptr++; + } + if (ptr >= sz) { + return 0; + } + + switch (b[ptr]) { + case '-': + sign = -1; + ptr++; + break; + case '+': + ptr++; + break; + default: + break; + } + + while (ptr < sz) { + final byte v = digits10[b[ptr]]; + if (v < 0) { + break; + } + r = (r * 10) + v; + ptr++; + } + } catch (final ArrayIndexOutOfBoundsException e) { + // Not a valid digit. + } + return sign < 0 ? -r : r; + } + + /** + * Parse a base 10 numeric from a sequence of ASCII digits into an int. + * + *

Digit sequences can begin with an optional run of spaces before the sequence, and may start + * with a '+' or a '-' to indicate sign position. Any other characters will cause the method to + * stop and return the current result to the caller. + * + * @param b buffer to scan. + * @param ptr position within buffer to start parsing digits at. + * @return the value at this location; 0 if the location is not a valid numeric. + */ + public static int parseBase10(final byte[] b, int ptr) { + int r = 0; + int sign = 0; + try { + final int sz = b.length; + while (ptr < sz && b[ptr] == ' ') { + ptr++; + } + if (ptr >= sz) { + return 0; + } + + switch (b[ptr]) { + case '-': + sign = -1; + ptr++; + break; + case '+': + ptr++; + break; + default: + break; + } + + while (ptr < sz) { + final byte v = digits10[b[ptr]]; + if (v < 0) { + break; + } + r = (r * 10) + v; + ptr++; + } + } catch (final ArrayIndexOutOfBoundsException e) { + // Not a valid digit. + } + return sign < 0 ? -r : r; + } + + /** + * Parse a Git style timezone string. + * + *

The sequence "-0315" will be parsed as the numeric value -195, as the lower two positions + * count minutes, not 100ths of an hour. + * + * @param b buffer to scan. + * @param ptr position within buffer to start parsing digits at. + * @return the timezone at this location, expressed in minutes. + * @since 4.1 + */ + public static int parseTimeZoneOffset(final byte[] b, final int ptr) { + final int v = parseBase10(b, ptr); + final int tzMins = v % 100; + final int tzHours = v / 100; + return tzHours * 60 + tzMins; + } + + public static int findByte(final byte[] bytes, final byte b) { + int i = 0; + while (i < bytes.length) { + if (bytes[i] == b) { + return i; + } + i += 1; + } + return -1; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java new file mode 100644 index 0000000000..5df26b5ecd --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java @@ -0,0 +1,108 @@ +package datadog.trace.api.git; + +import static datadog.trace.api.git.GitInfo.DD_GIT_BRANCH; +import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_AUTHOR_DATE; +import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_AUTHOR_EMAIL; +import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_AUTHOR_NAME; +import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_COMMITTER_DATE; +import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_COMMITTER_EMAIL; +import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_COMMITTER_NAME; +import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_MESSAGE; +import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_SHA; +import static datadog.trace.api.git.GitInfo.DD_GIT_REPOSITORY_URL; +import static datadog.trace.api.git.GitInfo.DD_GIT_TAG; + +import androidx.annotation.Nullable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import datadog.trace.api.Config; +import datadog.trace.api.config.GeneralConfig; +import datadog.trace.bootstrap.instrumentation.api.Tags; + +public class UserSuppliedGitInfoBuilder implements GitInfoBuilder { + + private static final Logger log = LoggerFactory.getLogger(UserSuppliedGitInfoBuilder.class); + + @Override + public GitInfo build(@Nullable String repositoryPath) { + String gitRepositoryUrl = System.getenv(DD_GIT_REPOSITORY_URL); + if (gitRepositoryUrl == null) { + gitRepositoryUrl = Config.get().getGlobalTags().get(Tags.GIT_REPOSITORY_URL); + } + + // The user can set the DD_GIT_BRANCH manually but + // using the value returned by the CI Provider, so + // we need to normalize the value. Also, it can contain + // the tag (e.g. origin/tags/0.1.0) + String gitTag = System.getenv(DD_GIT_TAG); + String gitBranch = null; + final String gitBranchOrTag = System.getenv(DD_GIT_BRANCH); + if (gitBranchOrTag != null) { + if (!GitUtils.isTagReference(gitBranchOrTag)) { + gitBranch = GitUtils.normalizeBranch(gitBranchOrTag); + } else if (gitTag == null) { + gitTag = GitUtils.normalizeTag(gitBranchOrTag); + } + } + + String gitCommitSha = System.getenv(DD_GIT_COMMIT_SHA); + if (gitCommitSha == null) { + gitCommitSha = Config.get().getGlobalTags().get(Tags.GIT_COMMIT_SHA); + } + + final String gitCommitMessage = System.getenv(DD_GIT_COMMIT_MESSAGE); + final String gitCommitAuthorName = System.getenv(DD_GIT_COMMIT_AUTHOR_NAME); + final String gitCommitAuthorEmail = System.getenv(DD_GIT_COMMIT_AUTHOR_EMAIL); + final String gitCommitAuthorDate = System.getenv(DD_GIT_COMMIT_AUTHOR_DATE); + final String gitCommitCommitterName = System.getenv(DD_GIT_COMMIT_COMMITTER_NAME); + final String gitCommitCommitterEmail = System.getenv(DD_GIT_COMMIT_COMMITTER_EMAIL); + final String gitCommitCommitterDate = System.getenv(DD_GIT_COMMIT_COMMITTER_DATE); + + GitInfo gitInfo = + new GitInfo( + gitRepositoryUrl, + gitBranch, + gitTag, + new CommitInfo( + gitCommitSha, + new PersonInfo(gitCommitAuthorName, gitCommitAuthorEmail, gitCommitAuthorDate), + new PersonInfo( + gitCommitCommitterName, gitCommitCommitterEmail, gitCommitCommitterDate), + gitCommitMessage)); + + if (!gitInfo.isEmpty()) { + // if there is any git metadata supplied by the user, we want to check that repo URL and + // commit SHA are valid + String repoUrl = gitInfo.getRepositoryURL(); + if (repoUrl == null || repoUrl.isEmpty()) { + log.error( + "Could not resolve git repository URL (can be provided via " + + GitInfo.DD_GIT_REPOSITORY_URL + + " env var, " + + GeneralConfig.TAGS + + " config property or by embedding git metadata at build time)"); + } + + String commitSha = gitInfo.getCommit().getSha(); + if (!GitUtils.isValidCommitSha(commitSha)) { + log.error( + "Git commit SHA could not be resolved or is invalid: " + + commitSha + + " (can be provided via " + + GitInfo.DD_GIT_COMMIT_SHA + + " env var, " + + GeneralConfig.TAGS + + " config property or by embedding git metadata at build time; must be a full-length SHA_"); + } + } + + return gitInfo; + } + + @Override + public int order() { + return 0; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodyFactories.java b/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodyFactories.java new file mode 100644 index 0000000000..5163373b16 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodyFactories.java @@ -0,0 +1,125 @@ +package datadog.trace.api.http; + +import static datadog.trace.api.gateway.Events.EVENTS; + +import java.nio.charset.Charset; +import java.util.function.BiFunction; +import java.util.function.Supplier; + +import datadog.trace.api.gateway.CallbackProvider; +import datadog.trace.api.gateway.Flow; +import datadog.trace.api.gateway.RequestContext; +import datadog.trace.api.gateway.RequestContextSlot; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentTracer; + +public class StoredBodyFactories { + private StoredBodyFactories() {} + + public static StoredByteBody maybeCreateForByte(Charset charset, Object contentLengthHeader) { + AgentSpan agentSpan = AgentTracer.activeSpan(); + if (agentSpan == null) { + return null; + } + return maybeCreateForByte(charset, agentSpan, contentLengthHeader); + } + + @SuppressWarnings("Duplicates") + public static StoredByteBody maybeCreateForByte( + Charset charset, AgentSpan agentSpan, Object contentLengthHeader) { + RequestContext requestContext = agentSpan.getRequestContext(); + if (requestContext == null) { + return null; + } + + CallbackProvider cbp = AgentTracer.get().getCallbackProvider(RequestContextSlot.APPSEC); + BiFunction requestStartCb = + cbp.getCallback(EVENTS.requestBodyStart()); + BiFunction> requestEndedCb = + cbp.getCallback(EVENTS.requestBodyDone()); + if (requestStartCb == null || requestEndedCb == null) { + return null; + } + + int lengthHint = parseLengthHeader(contentLengthHeader); + + return new StoredByteBody(requestContext, requestStartCb, requestEndedCb, charset, lengthHint); + } + + @SuppressWarnings("Duplicates") + public static Flow maybeDeliverBodyInOneGo( + Supplier supplier, RequestContext requestContext) { + CallbackProvider cbp = AgentTracer.get().getCallbackProvider(RequestContextSlot.APPSEC); + BiFunction requestStartCb = + cbp.getCallback(EVENTS.requestBodyStart()); + BiFunction> requestEndedCb = + cbp.getCallback(EVENTS.requestBodyDone()); + if (requestStartCb == null || requestEndedCb == null) { + return Flow.ResultFlow.empty(); + } + + StoredBodySupplier wrappedSupplier = new ConstantBodySupplier(supplier); + requestStartCb.apply(requestContext, wrappedSupplier); + return requestEndedCb.apply(requestContext, wrappedSupplier); + } + + public static Flow maybeDeliverBodyInOneGo(final String str, RequestContext reqCtx) { + return maybeDeliverBodyInOneGo(() -> str, reqCtx); + } + + public static class ConstantBodySupplier implements StoredBodySupplier { + private final CharSequence sequence; + + public ConstantBodySupplier(Supplier original) { + this.sequence = original.get(); + } + + @Override + public CharSequence get() { + return this.sequence; + } + } + + public static StoredCharBody maybeCreateForChar(Object contentLengthHeader) { + AgentSpan agentSpan = AgentTracer.activeSpan(); + if (agentSpan == null) { + return null; + } + return maybeCreateForChar(agentSpan, contentLengthHeader); + } + + @SuppressWarnings("Duplicates") + public static StoredCharBody maybeCreateForChar(AgentSpan agentSpan, Object contentLengthHeader) { + RequestContext requestContext = agentSpan.getRequestContext(); + if (requestContext == null) { + return null; + } + + CallbackProvider cbp = AgentTracer.get().getCallbackProvider(RequestContextSlot.APPSEC); + BiFunction requestStartCb = + cbp.getCallback(EVENTS.requestBodyStart()); + BiFunction> requestEndedCb = + cbp.getCallback(EVENTS.requestBodyDone()); + if (requestStartCb == null || requestEndedCb == null) { + return null; + } + + int lengthHint = parseLengthHeader(contentLengthHeader); + + return new StoredCharBody(requestContext, requestStartCb, requestEndedCb, lengthHint); + } + + private static int parseLengthHeader(Object contentLengthHeader) { + if (contentLengthHeader instanceof Number) { + return ((Number) contentLengthHeader).intValue(); + } + if (contentLengthHeader != null) { + try { + return Integer.parseInt(contentLengthHeader.toString()); + } catch (NumberFormatException nfe) { + // purposefully left blank + } + } + return 0; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodySupplier.java b/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodySupplier.java new file mode 100644 index 0000000000..52d3ee6fbc --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodySupplier.java @@ -0,0 +1,10 @@ +package datadog.trace.api.http; + +import androidx.annotation.NonNull; + +import java.util.function.Supplier; + +public interface StoredBodySupplier extends Supplier { + @NonNull + CharSequence get(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredByteBody.java b/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredByteBody.java new file mode 100644 index 0000000000..7ac0e09ca1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredByteBody.java @@ -0,0 +1,310 @@ +package datadog.trace.api.http; + +import androidx.annotation.Nullable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.UndeclaredThrowableException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; +import java.nio.charset.StandardCharsets; +import java.util.function.BiFunction; + +import datadog.trace.api.gateway.Flow; +import datadog.trace.api.gateway.RequestContext; + +/** @see StoredCharBody */ +public class StoredByteBody implements StoredBodySupplier { + + private static final Logger LOGGER = LoggerFactory.getLogger(StoredByteBody.class); + + static final Charset UTF_8 = StandardCharsets.UTF_8; + static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1; + + private final ByteBuffer undecodedData = ByteBuffer.allocate(64); + // decoded data has double the size to allow for the (unlikely) + // prospect that supplementary characters (2 chars) be encoded in 1 byte + private final CharBuffer decodedData = CharBuffer.allocate(128); + private CharsetDecoder charsetDecoder; + private StoredCharBody storedCharBody; + + public StoredByteBody( + RequestContext requestContext, + BiFunction startCb, + BiFunction> endCb, + @Nullable Charset charset, + int lengthHint) { + if (charset != null) { + this.charsetDecoder = ThreadLocalCoders.decoderFor(charset); + } + this.storedCharBody = new StoredCharBody(requestContext, startCb, endCb, lengthHint, this); + } + + public synchronized void appendData(byte[] bytes, int start, int end) { + try { + if (storedCharBody.isLimitReached()) { + return; + } + for (int i = start; i < end; ) { + if (!undecodedData.hasRemaining()) { + commit(false); + } + int write = Math.min(end - i, undecodedData.remaining()); + undecodedData.put(bytes, i, write); + i += write; + } + } catch (final Throwable e) { + LOGGER.debug("Failed to append byte array chunk", e); + } + storedCharBody.maybeNotifyStart(); + } + + /** + * Writes up to len bytes, in general through several invocations of the callback + * cb. The callback must write exactly undecodedData.remaining() bytes + * on each invocation. The limit of undecodedData passed to the callback will be + * adjusted in the last iteration, if necessary. + * + * @param cb the callback used to write directly into undecodedData + * @param len the amount of data available to write + */ + public synchronized void appendData(ByteBufferWriteCallback cb, int len) { + try { + for (int i = 0; i < len; ) { + if (storedCharBody.isLimitReached()) { + return; + } + if (!undecodedData.hasRemaining()) { + commit(false); + } + int left = len - i; + int remainingInUndecoded = undecodedData.remaining(); + if (remainingInUndecoded > left) { + undecodedData.limit(left); + i += left; + } else { + i += remainingInUndecoded; + } + cb.put(undecodedData); + } + undecodedData.limit(undecodedData.capacity()); + + } catch (final Throwable e) { + LOGGER.debug("Failed to append byte buffer callback", e); + } + storedCharBody.maybeNotifyStart(); + } + + public synchronized void appendData(int byteValue) { + try { + if (storedCharBody.isLimitReached()) { + return; + } + if (byteValue < 0 || byteValue > 255) { + return; + } + + if (!undecodedData.hasRemaining()) { + commit(false); + } + undecodedData.put((byte) byteValue); + } catch (final Throwable e) { + LOGGER.debug("Failed to append byte", e); + } + storedCharBody.maybeNotifyStart(); + } + + public synchronized void setCharset(Charset charset) { + this.charsetDecoder = ThreadLocalCoders.decoderFor(charset); + } + + public Flow maybeNotify() { + try { + commit(true); + } catch (final Throwable e) { + LOGGER.debug("Failed to commit end of input", e); + } + return storedCharBody.maybeNotify(); + } + + // may throw BlockingException. If used directly in advice, make use of @Advice.Throwable to + // propagate + public void maybeNotifyAndBlock() { + try { + commit(true); + } catch (final Throwable e) { + LOGGER.debug("Failed to commit end of input", e); + } + storedCharBody.maybeNotifyAndBlock(); + } + + @Override + public synchronized CharSequence get() { + commit(false); + return storedCharBody.get(); + } + + private void commit(boolean endOfInput) { + if (undecodedData.position() == 0) { + return; + } + if (charsetDecoder == null) { + charsetDecoder = + ThreadLocalCoders.decoderFor(UTF_8).onMalformedInput(CodingErrorAction.REPORT); + } + + this.undecodedData.flip(); + CoderResult decode = charsetDecoder.decode(this.undecodedData, this.decodedData, endOfInput); + if (endOfInput) { + /** + * Ensure the decoder is at a proper state in case the original input stream is reset, + * otherwise we will face: java.lang.IllegalStateException: Current state = CODING_END, new + * state = CODING + */ + charsetDecoder.reset(); + } + + this.decodedData.flip(); + this.storedCharBody.appendData(this.decodedData); + this.decodedData.position(0); + this.decodedData.limit(this.decodedData.capacity()); + + this.undecodedData.compact(); + + if (decode.isError()) { + // should only happen if charset was not explicitly given, + // as o/wise we use repl. chars + reencodeAsLatin1(); + this.charsetDecoder = ThreadLocalCoders.decoderFor(ISO_8859_1); + commit(endOfInput); + } + } + + private void reencodeAsLatin1() { + CharBuffer curData = this.storedCharBody.get(); + // reinterpreting the UTF-8 decoded sequence as latin1 will + // possibly result in a bigger result in terms of code points, + // so we need to make a copy + + CharsetEncoder encoder = ThreadLocalCoders.utf8Encoder(); + ByteBuffer utf8Encoded; + try { + utf8Encoded = encoder.encode(curData); + } catch (CharacterCodingException e) { + throw new UndeclaredThrowableException(e); // can't happen + } + + this.storedCharBody.dropData(); + + int limit = utf8Encoded.limit(); + for (int i = 0; i < limit; i++) { + // & to reverse the sign extension on the int promotion + this.storedCharBody.appendData(utf8Encoded.get(i) & 0xFF); + } + } + + public interface ByteBufferWriteCallback { + /** + * Asks the callback of {@link StoredByteBody#appendData(ByteBufferWriteCallback, int)} to write + * exactly undecodedData.remaining() bytes into the passed ByteBuffer. + * This amount of bytes will never be larger that the amount of data yet to be written; put + * another way, for one invocation of appendData(cb, n), the sum of the values of + * undecodedData.remaining() for the several cb calls will be n + * (or zero, if alternatively, cb is never invoked by appendData). + * + * @param undecodedData the buffer to write into + */ + void put(ByteBuffer undecodedData); + } +} + +// adapted from sun.nio.cs +class ThreadLocalCoders { + private static final int CACHE_SIZE = 3; + + private abstract static class Cache { + + // Thread-local reference to array of cached objects, in LRU order + private final ThreadLocal cache = new ThreadLocal<>(); + private final int size; + + Cache(int size) { + this.size = size; + } + + abstract Object create(Object name); + + private void moveToFront(Object[] oa, int i) { + Object ob = oa[i]; + for (int j = i; j > 0; j--) oa[j] = oa[j - 1]; + oa[0] = ob; + } + + abstract boolean hasName(Object ob, Object name); + + Object forName(Object name) { + Object[] oa = cache.get(); + if (oa == null) { + oa = new Object[size]; + cache.set(oa); + } else { + for (int i = 0; i < oa.length; i++) { + Object ob = oa[i]; + if (ob == null) continue; + if (hasName(ob, name)) { + if (i > 0) moveToFront(oa, i); + return ob; + } + } + } + + // Create a new object + Object ob = create(name); + oa[oa.length - 1] = ob; + moveToFront(oa, oa.length - 1); + return ob; + } + } + + private static final Cache DECODER_CACHE = + new Cache(CACHE_SIZE) { + boolean hasName(Object ob, Object name) { + return ((CharsetDecoder) ob).charset().equals(name); + } + + Object create(Object charset) { + return ((Charset) charset).newDecoder().onUnmappableCharacter(CodingErrorAction.REPLACE); + } + }; + + public static CharsetDecoder decoderFor(Charset charset) { + CharsetDecoder cd = (CharsetDecoder) DECODER_CACHE.forName(charset); + cd.onMalformedInput(CodingErrorAction.REPLACE); + cd.reset(); + return cd; + } + + private static final ThreadLocal UTF8_ENCODER_CACHE = + new ThreadLocal() { + @Override + protected CharsetEncoder initialValue() { + return StoredByteBody.UTF_8 + .newEncoder() + .onUnmappableCharacter(CodingErrorAction.REPLACE) + .onMalformedInput(CodingErrorAction.REPLACE); + } + }; + + public static CharsetEncoder utf8Encoder() { + CharsetEncoder charsetEncoder = UTF8_ENCODER_CACHE.get(); + charsetEncoder.reset(); + return charsetEncoder; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredCharBody.java b/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredCharBody.java new file mode 100644 index 0000000000..c89b0f802e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredCharBody.java @@ -0,0 +1,209 @@ +package datadog.trace.api.http; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.CharBuffer; +import java.util.Arrays; +import java.util.function.BiFunction; + +import datadog.trace.appsec.api.blocking.BlockingException; +import datadog.trace.api.gateway.BlockResponseFunction; +import datadog.trace.api.gateway.Flow; +import datadog.trace.api.gateway.RequestContext; + +/** Analogous to {@link StoredByteBody}, but Java doesn't support generics with scalar types. */ +public class StoredCharBody implements StoredBodySupplier { + + private static final Logger LOGGER = LoggerFactory.getLogger(StoredCharBody.class); + + private static final int MIN_BUFFER_SIZE = 128; // chars + private static final int MAX_BUFFER_SIZE = 128 * 1024; // 256k (char == 2 bytes) + private static final int GROW_FACTOR = 4; + private static final CharBuffer EMPTY_CHAR_BUFFER = CharBuffer.allocate(0); + + private final RequestContext httpContext; + private final BiFunction startCb; + private final BiFunction> endCb; + private final StoredBodySupplier supplierInNotifications; + + private boolean listenerNotified; + + private char[] storedBody; + private int storedBodyLen; + private boolean bodyReadStarted = false; + + public StoredCharBody( + RequestContext httpContext, + BiFunction startCb, + BiFunction> endCb, + int lengthHint) { + this(httpContext, startCb, endCb, lengthHint, null); + } + + StoredCharBody( + RequestContext httpContext, + BiFunction startCb, + BiFunction> endCb, + int lengthHint, + StoredBodySupplier supplierInNotifications) { + this.httpContext = httpContext; + this.startCb = startCb; + this.endCb = endCb; + + if (lengthHint != 0) { + int initialSize = Math.max(MIN_BUFFER_SIZE, Math.min(lengthHint, MAX_BUFFER_SIZE)); + this.storedBody = new char[initialSize]; + } + + this.supplierInNotifications = supplierInNotifications != null ? supplierInNotifications : this; + } + + public synchronized void appendData(char[] chars, int start, int end) { + try { + int newDataLen = end - start; + if (newDataLen <= 0) { + return; + } + if (!maybeExtendStorage(newDataLen)) { + return; + } + + int lenToCopy = Math.min(newDataLen, capacityLeft()); + System.arraycopy(chars, start, this.storedBody, this.storedBodyLen, lenToCopy); + + this.storedBodyLen += lenToCopy; + } catch (final Throwable e) { + LOGGER.debug("Error appending char array chunk", e); + } + maybeNotifyStart(); + } + + public synchronized void appendData(CharBuffer buffer) { + try { + int inputLen = buffer.remaining(); + if (inputLen == 0) { + return; + } + if (!maybeExtendStorage(inputLen)) { + return; + } + int lenToCopy = Math.min(inputLen, capacityLeft()); + + buffer.get(this.storedBody, this.storedBodyLen, lenToCopy); + this.storedBodyLen += lenToCopy; + } catch (final Throwable e) { + LOGGER.debug("Error appending char buffer", e); + } + maybeNotifyStart(); + } + + private boolean maybeExtendStorage(int newDataLen) { + if (this.storedBody == null) { + int initialSize = Math.max(Math.min(newDataLen, MAX_BUFFER_SIZE), MIN_BUFFER_SIZE); + this.storedBody = new char[initialSize]; + } else if (this.storedBodyLen == MAX_BUFFER_SIZE) { + return false; + } else if (capacityLeft() < newDataLen) { + int newSize = + Math.min( + Math.max(this.storedBodyLen + newDataLen, this.storedBodyLen * GROW_FACTOR), + MAX_BUFFER_SIZE); + this.storedBody = Arrays.copyOf(this.storedBody, newSize); + } + return true; + } + + public synchronized void appendData(String s) { + try { + int newDataLen = s.length(); + if (!maybeExtendStorage(newDataLen)) { + return; + } + + int lenToCopy = Math.min(newDataLen, capacityLeft()); + s.getChars(0, lenToCopy, this.storedBody, this.storedBodyLen); + + this.storedBodyLen += lenToCopy; + + } catch (final Throwable e) { + LOGGER.debug("Error appending string", e); + } + maybeNotifyStart(); + } + + private int capacityLeft() { + return this.storedBody.length - this.storedBodyLen; + } + + /** @param utf16CodeUnit an int in the range 0-0xFFFF */ + public synchronized void appendData(int utf16CodeUnit) { + try { + if (utf16CodeUnit < 0) { + return; + } + if (!maybeExtendStorage(1)) { + return; + } + this.storedBody[this.storedBodyLen] = (char) utf16CodeUnit; + this.storedBodyLen += 1; + + } catch (final Throwable e) { + LOGGER.debug("Error appending code unit", e); + } + maybeNotifyStart(); + } + + void maybeNotifyStart() { + if (!bodyReadStarted) { + bodyReadStarted = true; + this.startCb.apply(httpContext, supplierInNotifications); + } + } + + public synchronized Flow maybeNotify() { + if (!listenerNotified) { + listenerNotified = true; + if (!bodyReadStarted) { + this.startCb.apply(httpContext, supplierInNotifications); + } + return this.endCb.apply(httpContext, supplierInNotifications); + } + return Flow.ResultFlow.empty(); + } + + public synchronized void maybeNotifyAndBlock() { + Flow flow = maybeNotify(); + Flow.Action action = flow.getAction(); + if (action instanceof Flow.Action.RequestBlockingAction) { + Flow.Action.RequestBlockingAction rba = (Flow.Action.RequestBlockingAction) action; + + BlockResponseFunction blockResponseFunction = httpContext.getBlockResponseFunction(); + if (blockResponseFunction != null) { + blockResponseFunction.tryCommitBlockingResponse( + httpContext.getTraceSegment(), + rba.getStatusCode(), + rba.getBlockingContentType(), + rba.getExtraHeaders()); + } + throw new BlockingException("Blocked request (for request body stream read)"); + } + } + + @Override + public synchronized CharBuffer get() { + if (this.storedBodyLen == 0) { + return EMPTY_CHAR_BUFFER; + } + return CharBuffer.wrap(this.storedBody, 0, this.storedBodyLen); + } + + synchronized boolean isLimitReached() { + return this.storedBodyLen == MAX_BUFFER_SIZE; + } + + // for StoredByteBody's reencodeAsLatin1 + synchronized void dropData() { + this.storedBodyLen = 0; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastCallSites.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastCallSites.java new file mode 100644 index 0000000000..322e3cfb51 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastCallSites.java @@ -0,0 +1,14 @@ +package datadog.trace.api.iast; + +import datadog.trace.api.iast.telemetry.Verbosity; + +/** + * Interface used to mark advice implementations using @CallSite so they are instrumented by + * IastInstrumentation + */ +public interface IastCallSites { + + interface HasTelemetry { + void setVerbosity(Verbosity verbosity); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastContext.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastContext.java new file mode 100644 index 0000000000..a360a07acb --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastContext.java @@ -0,0 +1,45 @@ +package datadog.trace.api.iast; + +import androidx.annotation.Nullable; + +import datadog.trace.api.gateway.RequestContext; +import datadog.trace.api.gateway.RequestContextSlot; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentTracer; + +/** + * Initial encapsulation of the IAST context to be able to isolate it from the request. Ideally we + * should move away from IastRequestContext and start using this interface as much as possible + */ +public interface IastContext { + + /** + * Some scala instrumentations failed with public static methods inside an interface, that's the + * reason behind an inner class. + */ + abstract class Provider { + + private Provider() {} + + @Nullable + public static IastContext get() { + return get(AgentTracer.activeSpan()); + } + + @Nullable + public static IastContext get(final AgentSpan span) { + if (span == null) { + return null; + } + return get(span.getRequestContext()); + } + + @Nullable + public static IastContext get(final RequestContext reqCtx) { + if (reqCtx == null) { + return null; + } + return reqCtx.getData(RequestContextSlot.IAST); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastDetectionMode.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastDetectionMode.java new file mode 100644 index 0000000000..570f0320dd --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastDetectionMode.java @@ -0,0 +1,85 @@ +package datadog.trace.api.iast; + +import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_DEDUPLICATION_ENABLED; +import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_MAX_CONCURRENT_REQUESTS; +import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_MAX_RANGE_COUNT; +import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_REQUEST_SAMPLING; +import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_VULNERABILITIES_PER_REQUEST; +import static datadog.trace.api.config.IastConfig.IAST_DEDUPLICATION_ENABLED; +import static datadog.trace.api.config.IastConfig.IAST_MAX_CONCURRENT_REQUESTS; +import static datadog.trace.api.config.IastConfig.IAST_MAX_RANGE_COUNT; +import static datadog.trace.api.config.IastConfig.IAST_REQUEST_SAMPLING; +import static datadog.trace.api.config.IastConfig.IAST_VULNERABILITIES_PER_REQUEST; + +import androidx.annotation.NonNull; + +import datadog.trace.bootstrap.config.provider.ConfigProvider; + +public enum IastDetectionMode { + FULL { + @Override + public int getIastMaxConcurrentRequests(@NonNull final ConfigProvider config) { + return UNLIMITED; + } + + @Override + public int getIastVulnerabilitiesPerRequest(@NonNull final ConfigProvider config) { + return UNLIMITED; + } + + @Override + public float getIastRequestSampling(@NonNull final ConfigProvider config) { + return 100; + } + + @Override + public boolean isIastDeduplicationEnabled(@NonNull final ConfigProvider config) { + return false; + } + + @Override + public int getIastMaxRangeCount(@NonNull final ConfigProvider config) { + return Integer.MAX_VALUE; + } + }, + + DEFAULT { + @Override + public int getIastMaxConcurrentRequests(@NonNull final ConfigProvider config) { + return config.getInteger(IAST_MAX_CONCURRENT_REQUESTS, DEFAULT_IAST_MAX_CONCURRENT_REQUESTS); + } + + @Override + public int getIastVulnerabilitiesPerRequest(@NonNull final ConfigProvider config) { + return config.getInteger( + IAST_VULNERABILITIES_PER_REQUEST, DEFAULT_IAST_VULNERABILITIES_PER_REQUEST); + } + + @Override + public float getIastRequestSampling(@NonNull final ConfigProvider config) { + return config.getFloat(IAST_REQUEST_SAMPLING, DEFAULT_IAST_REQUEST_SAMPLING); + } + + @Override + public boolean isIastDeduplicationEnabled(@NonNull final ConfigProvider config) { + return config.getBoolean(IAST_DEDUPLICATION_ENABLED, DEFAULT_IAST_DEDUPLICATION_ENABLED); + } + + @Override + public int getIastMaxRangeCount(@NonNull final ConfigProvider config) { + return config.getInteger(IAST_MAX_RANGE_COUNT, DEFAULT_IAST_MAX_RANGE_COUNT); + } + }; + + public static final int UNLIMITED = Integer.MIN_VALUE; + + public abstract int getIastMaxConcurrentRequests(@NonNull ConfigProvider config); + + public abstract int getIastVulnerabilitiesPerRequest(@NonNull ConfigProvider config); + + public abstract float getIastRequestSampling(@NonNull ConfigProvider config); + + public abstract boolean isIastDeduplicationEnabled(@NonNull ConfigProvider config); + + public abstract int getIastMaxRangeCount(@NonNull ConfigProvider config); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastEnabledChecks.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastEnabledChecks.java new file mode 100644 index 0000000000..5a6daab420 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastEnabledChecks.java @@ -0,0 +1,25 @@ +package datadog.trace.api.iast; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import datadog.trace.api.Platform; + +public abstract class IastEnabledChecks { + + private static final Logger LOGGER = LoggerFactory.getLogger(IastEnabledChecks.class); + + private IastEnabledChecks() {} + + public static boolean isMajorJavaVersionAtLeast(final String version) { + try { + return Platform.isJavaVersionAtLeast(Integer.parseInt(version)); + } catch (final Exception e) { + LOGGER.error( + "Error checking major java version {}, expect some call sites to be disabled", + version, + e); + return false; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastModule.java new file mode 100644 index 0000000000..33d014b963 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastModule.java @@ -0,0 +1,13 @@ +package datadog.trace.api.iast; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public interface IastModule { + + Logger LOG = LoggerFactory.getLogger(IastModule.class); + + default void onUnexpectedException(final String message, final Throwable error) { + LOG.warn(message, error); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/InstrumentationBridge.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/InstrumentationBridge.java new file mode 100644 index 0000000000..78a9bade1e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/InstrumentationBridge.java @@ -0,0 +1,224 @@ +package datadog.trace.api.iast; + +import datadog.trace.api.iast.propagation.CodecModule; +import datadog.trace.api.iast.propagation.PropagationModule; +import datadog.trace.api.iast.propagation.StringModule; +import datadog.trace.api.iast.sink.ApplicationModule; +import datadog.trace.api.iast.sink.CommandInjectionModule; +import datadog.trace.api.iast.sink.HeaderInjectionModule; +import datadog.trace.api.iast.sink.HstsMissingHeaderModule; +import datadog.trace.api.iast.sink.HttpResponseHeaderModule; +import datadog.trace.api.iast.sink.InsecureCookieModule; +import datadog.trace.api.iast.sink.LdapInjectionModule; +import datadog.trace.api.iast.sink.NoHttpOnlyCookieModule; +import datadog.trace.api.iast.sink.NoSameSiteCookieModule; +import datadog.trace.api.iast.sink.PathTraversalModule; +import datadog.trace.api.iast.sink.SqlInjectionModule; +import datadog.trace.api.iast.sink.SsrfModule; +import datadog.trace.api.iast.sink.StacktraceLeakModule; +import datadog.trace.api.iast.sink.TrustBoundaryViolationModule; +import datadog.trace.api.iast.sink.UnvalidatedRedirectModule; +import datadog.trace.api.iast.sink.WeakCipherModule; +import datadog.trace.api.iast.sink.WeakHashModule; +import datadog.trace.api.iast.sink.WeakRandomnessModule; +import datadog.trace.api.iast.sink.XContentTypeModule; +import datadog.trace.api.iast.sink.XPathInjectionModule; +import datadog.trace.api.iast.sink.XssModule; + +/** Bridge between instrumentations and {@link IastModule} instances. */ +public abstract class InstrumentationBridge { + + public static volatile StringModule STRING; + public static volatile CodecModule CODEC; + public static volatile SqlInjectionModule SQL_INJECTION; + public static volatile PathTraversalModule PATH_TRAVERSAL; + public static volatile CommandInjectionModule COMMAND_INJECTION; + public static volatile WeakCipherModule WEAK_CIPHER; + public static volatile WeakHashModule WEAK_HASH; + public static volatile LdapInjectionModule LDAP_INJECTION; + public static volatile PropagationModule PROPAGATION; + public static volatile InsecureCookieModule INSECURE_COOKIE; + public static volatile NoHttpOnlyCookieModule NO_HTTPONLY_COOKIE; + public static volatile NoSameSiteCookieModule NO_SAMESITE_COOKIE; + public static volatile SsrfModule SSRF; + public static volatile UnvalidatedRedirectModule UNVALIDATED_REDIRECT; + public static volatile WeakRandomnessModule WEAK_RANDOMNESS; + public static volatile HttpResponseHeaderModule RESPONSE_HEADER_MODULE; + public static volatile HstsMissingHeaderModule HSTS_MISSING_HEADER_MODULE; + + public static volatile XContentTypeModule X_CONTENT_TYPE_HEADER_MODULE; + + public static volatile TrustBoundaryViolationModule TRUST_BOUNDARY_VIOLATION; + + public static volatile XPathInjectionModule XPATH_INJECTION; + + public static volatile XssModule XSS; + + public static volatile StacktraceLeakModule STACKTRACE_LEAK_MODULE; + + public static volatile ApplicationModule APPLICATION; + + public static volatile HeaderInjectionModule HEADER_INJECTION; + + private InstrumentationBridge() {} + + public static void registerIastModule(final IastModule module) { + if (module instanceof StringModule) { + STRING = (StringModule) module; + } else if (module instanceof CodecModule) { + CODEC = (CodecModule) module; + } else if (module instanceof SqlInjectionModule) { + SQL_INJECTION = (SqlInjectionModule) module; + } else if (module instanceof PathTraversalModule) { + PATH_TRAVERSAL = (PathTraversalModule) module; + } else if (module instanceof CommandInjectionModule) { + COMMAND_INJECTION = (CommandInjectionModule) module; + } else if (module instanceof WeakCipherModule) { + WEAK_CIPHER = (WeakCipherModule) module; + } else if (module instanceof WeakHashModule) { + WEAK_HASH = (WeakHashModule) module; + } else if (module instanceof LdapInjectionModule) { + LDAP_INJECTION = (LdapInjectionModule) module; + } else if (module instanceof PropagationModule) { + PROPAGATION = (PropagationModule) module; + } else if (module instanceof InsecureCookieModule) { + INSECURE_COOKIE = (InsecureCookieModule) module; + } else if (module instanceof NoHttpOnlyCookieModule) { + NO_HTTPONLY_COOKIE = (NoHttpOnlyCookieModule) module; + } else if (module instanceof NoSameSiteCookieModule) { + NO_SAMESITE_COOKIE = (NoSameSiteCookieModule) module; + } else if (module instanceof SsrfModule) { + SSRF = (SsrfModule) module; + } else if (module instanceof UnvalidatedRedirectModule) { + UNVALIDATED_REDIRECT = (UnvalidatedRedirectModule) module; + } else if (module instanceof WeakRandomnessModule) { + WEAK_RANDOMNESS = (WeakRandomnessModule) module; + } else if (module instanceof HttpResponseHeaderModule) { + RESPONSE_HEADER_MODULE = (HttpResponseHeaderModule) module; + } else if (module instanceof HstsMissingHeaderModule) { + HSTS_MISSING_HEADER_MODULE = (HstsMissingHeaderModule) module; + } else if (module instanceof XContentTypeModule) { + X_CONTENT_TYPE_HEADER_MODULE = (XContentTypeModule) module; + } else if (module instanceof XPathInjectionModule) { + XPATH_INJECTION = (XPathInjectionModule) module; + } else if (module instanceof TrustBoundaryViolationModule) { + TRUST_BOUNDARY_VIOLATION = (TrustBoundaryViolationModule) module; + } else if (module instanceof XssModule) { + XSS = (XssModule) module; + } else if (module instanceof StacktraceLeakModule) { + STACKTRACE_LEAK_MODULE = (StacktraceLeakModule) module; + } else if (module instanceof HeaderInjectionModule) { + HEADER_INJECTION = (HeaderInjectionModule) module; + } else if (module instanceof ApplicationModule) { + APPLICATION = (ApplicationModule) module; + } else { + throw new UnsupportedOperationException("Module not yet supported: " + module); + } + } + + /** Mainly used for testing modules */ + @SuppressWarnings("unchecked") + public static E getIastModule(final Class type) { + if (type == StringModule.class) { + return (E) STRING; + } + if (type == CodecModule.class) { + return (E) CODEC; + } + if (type == SqlInjectionModule.class) { + return (E) SQL_INJECTION; + } + if (type == PathTraversalModule.class) { + return (E) PATH_TRAVERSAL; + } + if (type == CommandInjectionModule.class) { + return (E) COMMAND_INJECTION; + } + if (type == WeakCipherModule.class) { + return (E) WEAK_CIPHER; + } + if (type == WeakHashModule.class) { + return (E) WEAK_HASH; + } + if (type == LdapInjectionModule.class) { + return (E) LDAP_INJECTION; + } + if (type == PropagationModule.class) { + return (E) PROPAGATION; + } + if (type == InsecureCookieModule.class) { + return (E) INSECURE_COOKIE; + } + if (type == NoHttpOnlyCookieModule.class) { + return (E) NO_HTTPONLY_COOKIE; + } + if (type == NoSameSiteCookieModule.class) { + return (E) NO_SAMESITE_COOKIE; + } + if (type == SsrfModule.class) { + return (E) SSRF; + } + if (type == UnvalidatedRedirectModule.class) { + return (E) UNVALIDATED_REDIRECT; + } + if (type == WeakRandomnessModule.class) { + return (E) WEAK_RANDOMNESS; + } + if (type == XPathInjectionModule.class) { + return (E) XPATH_INJECTION; + } + if (type == HttpResponseHeaderModule.class) { + return (E) RESPONSE_HEADER_MODULE; + } + if (type == HstsMissingHeaderModule.class) { + return (E) HSTS_MISSING_HEADER_MODULE; + } + if (type == XContentTypeModule.class) { + return (E) X_CONTENT_TYPE_HEADER_MODULE; + } + if (type == TrustBoundaryViolationModule.class) { + return (E) TRUST_BOUNDARY_VIOLATION; + } + if (type == XssModule.class) { + return (E) XSS; + } + if (type == StacktraceLeakModule.class) { + return (E) STACKTRACE_LEAK_MODULE; + } + if (type == ApplicationModule.class) { + return (E) APPLICATION; + } + if (type == HeaderInjectionModule.class) { + return (E) HEADER_INJECTION; + } + throw new UnsupportedOperationException("Module not yet supported: " + type); + } + + /** Mainly used for testing empty modules */ + public static void clearIastModules() { + STRING = null; + CODEC = null; + SQL_INJECTION = null; + PATH_TRAVERSAL = null; + COMMAND_INJECTION = null; + WEAK_CIPHER = null; + WEAK_HASH = null; + LDAP_INJECTION = null; + PROPAGATION = null; + INSECURE_COOKIE = null; + NO_HTTPONLY_COOKIE = null; + NO_SAMESITE_COOKIE = null; + SSRF = null; + UNVALIDATED_REDIRECT = null; + WEAK_RANDOMNESS = null; + RESPONSE_HEADER_MODULE = null; + HSTS_MISSING_HEADER_MODULE = null; + X_CONTENT_TYPE_HEADER_MODULE = null; + XPATH_INJECTION = null; + TRUST_BOUNDARY_VIOLATION = null; + XSS = null; + STACKTRACE_LEAK_MODULE = null; + APPLICATION = null; + HEADER_INJECTION = null; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Propagation.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Propagation.java new file mode 100644 index 0000000000..8ca392f76a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Propagation.java @@ -0,0 +1,10 @@ +package datadog.trace.api.iast; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Propagation {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Sink.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Sink.java new file mode 100644 index 0000000000..c7e53d20e8 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Sink.java @@ -0,0 +1,13 @@ +package datadog.trace.api.iast; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Sink { + /** Vulnerability type */ + byte value(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Source.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Source.java new file mode 100644 index 0000000000..0cf222b59e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Source.java @@ -0,0 +1,13 @@ +package datadog.trace.api.iast; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Source { + /** Source type */ + byte value(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/SourceTypes.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/SourceTypes.java new file mode 100644 index 0000000000..cd6f9a0d05 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/SourceTypes.java @@ -0,0 +1,110 @@ +package datadog.trace.api.iast; + +public abstract class SourceTypes { + + private SourceTypes() {} + + public static final byte NONE = -1; + + public static final byte REQUEST_PARAMETER_NAME = 0; + public static final String REQUEST_PARAMETER_NAME_STRING = "http.request.parameter.name"; + public static final byte REQUEST_PARAMETER_VALUE = 1; + public static final String REQUEST_PARAMETER_VALUE_STRING = "http.request.parameter"; + public static final byte REQUEST_HEADER_NAME = 2; + public static final String REQUEST_HEADER_NAME_STRING = "http.request.header.name"; + public static final byte REQUEST_HEADER_VALUE = 3; + public static final String REQUEST_HEADER_VALUE_STRING = "http.request.header"; + public static final byte REQUEST_COOKIE_NAME = 4; + public static final String REQUEST_COOKIE_NAME_STRING = "http.request.cookie.name"; + public static final byte REQUEST_COOKIE_VALUE = 5; + public static final String REQUEST_COOKIE_VALUE_STRING = "http.request.cookie.value"; + public static final byte REQUEST_BODY = 6; + public static final String REQUEST_BODY_STRING = "http.request.body"; + public static final byte REQUEST_QUERY = 7; + public static final String REQUEST_QUERY_STRING = "http.request.query"; + public static final byte REQUEST_PATH_PARAMETER = 8; + public static final String REQUEST_PATH_PARAMETER_STRING = "http.request.path.parameter"; + public static final byte REQUEST_MATRIX_PARAMETER = 9; + public static final String REQUEST_MATRIX_PARAMETER_STRING = "http.request.matrix.parameter"; + public static final byte REQUEST_MULTIPART_PARAMETER = 10; + public static final String REQUEST_MULTIPART_PARAMETER_STRING = + "http.request.multipart.parameter"; + public static final byte REQUEST_URI = 11; + public static final String REQUEST_URI_STRING = "http.request.uri"; + public static final byte REQUEST_PATH = 12; + public static final String REQUEST_PATH_STRING = "http.request.path"; + public static final byte GRPC_BODY = 13; + public static final String GRPC_BODY_STRING = "grpc.request.body"; + + private static final byte[] VALUES = { + REQUEST_PARAMETER_NAME, + REQUEST_PARAMETER_VALUE, + REQUEST_HEADER_NAME, + REQUEST_HEADER_VALUE, + REQUEST_COOKIE_NAME, + REQUEST_COOKIE_VALUE, + REQUEST_BODY, + REQUEST_QUERY, + REQUEST_PATH_PARAMETER, + REQUEST_MATRIX_PARAMETER, + REQUEST_MULTIPART_PARAMETER, + REQUEST_PATH, + REQUEST_URI, + GRPC_BODY + }; + + public static byte[] values() { + return VALUES; + } + + public static String toString(final byte sourceType) { + switch (sourceType) { + case SourceTypes.REQUEST_PARAMETER_NAME: + return SourceTypes.REQUEST_PARAMETER_NAME_STRING; + case SourceTypes.REQUEST_PARAMETER_VALUE: + return SourceTypes.REQUEST_PARAMETER_VALUE_STRING; + case SourceTypes.REQUEST_HEADER_NAME: + return SourceTypes.REQUEST_HEADER_NAME_STRING; + case SourceTypes.REQUEST_HEADER_VALUE: + return SourceTypes.REQUEST_HEADER_VALUE_STRING; + case SourceTypes.REQUEST_COOKIE_NAME: + return SourceTypes.REQUEST_COOKIE_NAME_STRING; + case SourceTypes.REQUEST_COOKIE_VALUE: + return SourceTypes.REQUEST_COOKIE_VALUE_STRING; + case SourceTypes.REQUEST_BODY: + return SourceTypes.REQUEST_BODY_STRING; + case SourceTypes.REQUEST_QUERY: + return SourceTypes.REQUEST_QUERY_STRING; + case SourceTypes.REQUEST_PATH_PARAMETER: + return SourceTypes.REQUEST_PATH_PARAMETER_STRING; + case SourceTypes.REQUEST_MATRIX_PARAMETER: + return SourceTypes.REQUEST_MATRIX_PARAMETER_STRING; + case SourceTypes.REQUEST_MULTIPART_PARAMETER: + return SourceTypes.REQUEST_MULTIPART_PARAMETER_STRING; + case SourceTypes.REQUEST_PATH: + return SourceTypes.REQUEST_PATH_STRING; + case SourceTypes.REQUEST_URI: + return SourceTypes.REQUEST_URI_STRING; + case SourceTypes.GRPC_BODY: + return SourceTypes.GRPC_BODY_STRING; + default: + return null; + } + } + + public static byte namedSource(final byte sourceType) { + switch (sourceType) { + case SourceTypes.REQUEST_PARAMETER_VALUE: + case SourceTypes.REQUEST_PARAMETER_NAME: + return SourceTypes.REQUEST_PARAMETER_NAME; + case SourceTypes.REQUEST_HEADER_VALUE: + case SourceTypes.REQUEST_HEADER_NAME: + return SourceTypes.REQUEST_HEADER_NAME; + case SourceTypes.REQUEST_COOKIE_VALUE: + case SourceTypes.REQUEST_COOKIE_NAME: + return SourceTypes.REQUEST_COOKIE_NAME; + default: + return sourceType; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Taintable.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Taintable.java new file mode 100644 index 0000000000..c42b8ddd90 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Taintable.java @@ -0,0 +1,61 @@ +package datadog.trace.api.iast; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public interface Taintable { + + Source $$DD$getSource(); + + void $$DD$setSource(final Source source); + + default boolean $DD$isTainted() { + return $$DD$getSource() != null; + } + + /** Interface to isolate customer classloader from our classes */ + interface Source { + byte getOrigin(); + + String getName(); + + String getValue(); + } + + class DebugLogger { + private static final Logger LOGGER; + + static { + try { + LOGGER = LoggerFactory.getLogger("Taintable tainted objects"); + Class levelCls = Class.forName("ch.qos.logback.classic.Level"); + Method setLevel = LOGGER.getClass().getMethod("setLevel", levelCls); + Object debugLevel = levelCls.getField("DEBUG").get(null); + setLevel.invoke(LOGGER, debugLevel); + } catch (IllegalAccessException + | NoSuchFieldException + | ClassNotFoundException + | NoSuchMethodException + | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public static void logTaint(Taintable t) { + String content; + if (t.getClass().getName().startsWith("java.")) { + content = t.toString(); + } else { + content = "(value not shown)"; // toString() may trigger tainting + } + LOGGER.debug( + "taint: {}[{}] {}", + t.getClass().getSimpleName(), + Integer.toHexString(System.identityHashCode(t)), + content); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityMarks.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityMarks.java new file mode 100644 index 0000000000..ab39b1f429 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityMarks.java @@ -0,0 +1,21 @@ +package datadog.trace.api.iast; + +public class VulnerabilityMarks { + + private VulnerabilityMarks() {} + + public static final int NOT_MARKED = 0; + + public static final int XPATH_INJECTION_MARK = 1; + public static final int SQL_INJECTION_MARK = 1 << 1; + public static final int COMMAND_INJECTION_MARK = 1 << 2; + public static final int PATH_TRAVERSAL_MARK = 1 << 3; + public static final int LDAP_INJECTION_MARK = 1 << 4; + public static final int SSRF_MARK = 1 << 5; + public static final int UNVALIDATED_REDIRECT_MARK = 1 << 6; + + public static final int XSS_MARK = 1 << 7; + + public static final int TRUST_BOUNDARY_VIOLATION = 1 << 8; + public static final int HEADER_INJECTION_MARK = 1 << 9; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityTypes.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityTypes.java new file mode 100644 index 0000000000..af2d67d86b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityTypes.java @@ -0,0 +1,175 @@ +package datadog.trace.api.iast; + +public abstract class VulnerabilityTypes { + + private VulnerabilityTypes() {} + + public static final byte WEAK_CIPHER = 0; + public static final String WEAK_CIPHER_STRING = "WEAK_CIPHER"; + public static final byte WEAK_HASH = 1; + public static final String WEAK_HASH_STRING = "WEAK_HASH"; + public static final byte SQL_INJECTION = 2; + public static final String SQL_INJECTION_STRING = "SQL_INJECTION"; + public static final byte COMMAND_INJECTION = 3; + public static final String COMMAND_INJECTION_STRING = "COMMAND_INJECTION"; + public static final byte PATH_TRAVERSAL = 4; + public static final String PATH_TRAVERSAL_STRING = "PATH_TRAVERSAL"; + public static final byte LDAP_INJECTION = 5; + public static final String LDAP_INJECTION_STRING = "LDAP_INJECTION"; + public static final byte SSRF = 6; + public static final String SSRF_STRING = "SSRF"; + public static final byte INSECURE_COOKIE = 7; + public static final String INSECURE_COOKIE_STRING = "INSECURE_COOKIE"; + public static final byte NO_HTTPONLY_COOKIE = 8; + public static final String NO_HTTPONLY_COOKIE_STRING = "NO_HTTPONLY_COOKIE"; + public static final byte HSTS_HEADER_MISSING = 9; + public static final String HSTS_HEADER_MISSING_STRING = "HSTS_HEADER_MISSING"; + public static final byte XCONTENTTYPE_HEADER_MISSING = 10; + public static final String XCONTENTTYPE_HEADER_MISSING_STRING = "XCONTENTTYPE_HEADER_MISSING"; + public static final byte NO_SAMESITE_COOKIE = 11; + public static final String NO_SAMESITE_COOKIE_STRING = "NO_SAMESITE_COOKIE"; + public static final byte UNVALIDATED_REDIRECT = 12; + public static final String UNVALIDATED_REDIRECT_STRING = "UNVALIDATED_REDIRECT"; + public static final byte WEAK_RANDOMNESS = 13; + public static final String WEAK_RANDOMNESS_STRING = "WEAK_RANDOMNESS"; + public static final byte XPATH_INJECTION = 14; + public static final String XPATH_INJECTION_STRING = "XPATH_INJECTION"; + public static final byte TRUST_BOUNDARY_VIOLATION = 15; + public static final String TRUST_BOUNDARY_VIOLATION_STRING = "TRUST_BOUNDARY_VIOLATION"; + public static final byte XSS = 16; + public static final String XSS_STRING = "XSS"; + public static final byte STACKTRACE_LEAK = 17; + public static final String STACKTRACE_LEAK_STRING = "STACKTRACE_LEAK"; + public static final byte HEADER_INJECTION = 18; + public static final String HEADER_INJECTION_STRING = "HEADER_INJECTION"; + + public static final byte VERB_TAMPERING = 19; + public static final String VERB_TAMPERING_STRING = "VERB_TAMPERING"; + + public static final byte DEFAULT_HTML_ESCAPE_INVALID = 20; + public static final String DEFAULT_HTML_ESCAPE_INVALID_STRING = "DEFAULT_HTML_ESCAPE_INVALID"; + + public static final byte SESSION_TIMEOUT = 21; + public static final String SESSION_TIMEOUT_STRING = "SESSION_TIMEOUT"; + + public static final byte DIRECTORY_LISTING_LEAK = 22; + public static final String DIRECTORY_LISTING_LEAK_STRING = "DIRECTORY_LISTING_LEAK"; + + public static final byte INSECURE_JSP_LAYOUT = 23; + public static final String INSECURE_JSP_LAYOUT_STRING = "INSECURE_JSP_LAYOUT"; + + public static final byte ADMIN_CONSOLE_ACTIVE = 24; + public static final String ADMIN_CONSOLE_ACTIVE_STRING = "ADMIN_CONSOLE_ACTIVE"; + + /** + * Use for telemetry only, this is a special vulnerability type that is not reported, reported + * values will be {@link #RESPONSE_HEADER_TYPES} + */ + public static final byte RESPONSE_HEADER = -128; + + public static final byte[] RESPONSE_HEADER_TYPES = { + UNVALIDATED_REDIRECT, + INSECURE_COOKIE, + NO_SAMESITE_COOKIE, + XCONTENTTYPE_HEADER_MISSING, + HSTS_HEADER_MISSING, + HEADER_INJECTION + }; + + /** + * Use for telemetry only, this is a special vulnerability type that is not reported, reported + * values will be {@link #SPRING_RESPONSE_TYPES} + */ + public static final byte SPRING_RESPONSE = -127; + /** Use for spring unvalidated redirect and xss */ + public static final byte[] SPRING_RESPONSE_TYPES = {UNVALIDATED_REDIRECT, XSS}; + + private static final byte[] VALUES = { + WEAK_CIPHER, + WEAK_HASH, + SQL_INJECTION, + COMMAND_INJECTION, + PATH_TRAVERSAL, + LDAP_INJECTION, + SSRF, + INSECURE_COOKIE, + NO_HTTPONLY_COOKIE, + UNVALIDATED_REDIRECT, + WEAK_RANDOMNESS, + XPATH_INJECTION, + TRUST_BOUNDARY_VIOLATION, + HSTS_HEADER_MISSING, + XCONTENTTYPE_HEADER_MISSING, + NO_SAMESITE_COOKIE, + XSS, + STACKTRACE_LEAK, + HEADER_INJECTION, + ADMIN_CONSOLE_ACTIVE, + VERB_TAMPERING, + DEFAULT_HTML_ESCAPE_INVALID, + SESSION_TIMEOUT, + DIRECTORY_LISTING_LEAK, + INSECURE_JSP_LAYOUT + }; + + public static byte[] values() { + return VALUES; + } + + public static String toString(final byte sourceType) { + switch (sourceType) { + case VulnerabilityTypes.WEAK_CIPHER: + return VulnerabilityTypes.WEAK_CIPHER_STRING; + case VulnerabilityTypes.WEAK_HASH: + return VulnerabilityTypes.WEAK_HASH_STRING; + case VulnerabilityTypes.SQL_INJECTION: + return VulnerabilityTypes.SQL_INJECTION_STRING; + case VulnerabilityTypes.COMMAND_INJECTION: + return VulnerabilityTypes.COMMAND_INJECTION_STRING; + case VulnerabilityTypes.PATH_TRAVERSAL: + return VulnerabilityTypes.PATH_TRAVERSAL_STRING; + case VulnerabilityTypes.LDAP_INJECTION: + return VulnerabilityTypes.LDAP_INJECTION_STRING; + case VulnerabilityTypes.SSRF: + return VulnerabilityTypes.SSRF_STRING; + case VulnerabilityTypes.INSECURE_COOKIE: + return VulnerabilityTypes.INSECURE_COOKIE_STRING; + case VulnerabilityTypes.NO_HTTPONLY_COOKIE: + return VulnerabilityTypes.NO_HTTPONLY_COOKIE_STRING; + case VulnerabilityTypes.UNVALIDATED_REDIRECT: + return VulnerabilityTypes.UNVALIDATED_REDIRECT_STRING; + case VulnerabilityTypes.WEAK_RANDOMNESS: + return VulnerabilityTypes.WEAK_RANDOMNESS_STRING; + case VulnerabilityTypes.XPATH_INJECTION: + return VulnerabilityTypes.XPATH_INJECTION_STRING; + case VulnerabilityTypes.TRUST_BOUNDARY_VIOLATION: + return VulnerabilityTypes.TRUST_BOUNDARY_VIOLATION_STRING; + case VulnerabilityTypes.HSTS_HEADER_MISSING: + return VulnerabilityTypes.HSTS_HEADER_MISSING_STRING; + case VulnerabilityTypes.XCONTENTTYPE_HEADER_MISSING: + return VulnerabilityTypes.XCONTENTTYPE_HEADER_MISSING_STRING; + case VulnerabilityTypes.NO_SAMESITE_COOKIE: + return VulnerabilityTypes.NO_SAMESITE_COOKIE_STRING; + case VulnerabilityTypes.XSS: + return VulnerabilityTypes.XSS_STRING; + case VulnerabilityTypes.STACKTRACE_LEAK: + return VulnerabilityTypes.STACKTRACE_LEAK_STRING; + case VulnerabilityTypes.HEADER_INJECTION: + return VulnerabilityTypes.HEADER_INJECTION_STRING; + case VulnerabilityTypes.ADMIN_CONSOLE_ACTIVE: + return VulnerabilityTypes.ADMIN_CONSOLE_ACTIVE_STRING; + case VulnerabilityTypes.VERB_TAMPERING: + return VulnerabilityTypes.VERB_TAMPERING_STRING; + case VulnerabilityTypes.DEFAULT_HTML_ESCAPE_INVALID: + return VulnerabilityTypes.DEFAULT_HTML_ESCAPE_INVALID_STRING; + case VulnerabilityTypes.SESSION_TIMEOUT: + return VulnerabilityTypes.SESSION_TIMEOUT_STRING; + case VulnerabilityTypes.DIRECTORY_LISTING_LEAK: + return VulnerabilityTypes.DIRECTORY_LISTING_LEAK_STRING; + case VulnerabilityTypes.INSECURE_JSP_LAYOUT: + return VulnerabilityTypes.INSECURE_JSP_LAYOUT_STRING; + default: + return null; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/CodecModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/CodecModule.java new file mode 100644 index 0000000000..07c637a5e4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/CodecModule.java @@ -0,0 +1,19 @@ +package datadog.trace.api.iast.propagation; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import datadog.trace.api.iast.IastModule; + +public interface CodecModule extends IastModule { + + void onUrlDecode(@NonNull String value, @Nullable String encoding, @NonNull String result); + + void onStringFromBytes(@NonNull byte[] value, @Nullable String charset, @NonNull String result); + + void onStringGetBytes(@NonNull String value, @Nullable String charset, @NonNull byte[] result); + + void onBase64Encode(@Nullable byte[] value, @Nullable byte[] result); + + void onBase64Decode(@Nullable byte[] value, @Nullable byte[] result); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/PropagationModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/PropagationModule.java new file mode 100644 index 0000000000..7ad06418af --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/PropagationModule.java @@ -0,0 +1,185 @@ +package datadog.trace.api.iast.propagation; + +import androidx.annotation.Nullable; + +import java.util.function.Predicate; + +import datadog.trace.api.iast.IastContext; +import datadog.trace.api.iast.IastModule; +import datadog.trace.api.iast.Taintable.Source; + +/** Main API for propagation of tainted values, */ +@SuppressWarnings("unused") +public interface PropagationModule extends IastModule { + + /** @see #taint(IastContext, Object, byte) */ + void taint(@Nullable Object target, byte origin); + + /** + * Taints the object with a source with the selected origin and no name, if target is a char + * sequence it will be used as value + */ + void taint(@Nullable IastContext ctx, @Nullable Object target, byte origin); + + /** @see #taint(IastContext, Object, byte, CharSequence) */ + void taint(@Nullable Object target, byte origin, @Nullable CharSequence name); + + /** + * Taints the object with a source with the selected origin and name, if target is a char sequence + * it will be used as value + */ + void taint( + @Nullable IastContext ctx, @Nullable Object target, byte origin, @Nullable CharSequence name); + + /** @see #taint(IastContext, Object, byte, CharSequence, CharSequence) */ + void taint( + @Nullable Object target, + byte origin, + @Nullable CharSequence name, + @Nullable CharSequence value); + + /** Taints the object with a source with the selected origin, name and value */ + void taint( + @Nullable IastContext ctx, + @Nullable Object target, + byte origin, + @Nullable CharSequence name, + @Nullable CharSequence value); + + /** @see #taintIfTainted(IastContext, Object, Object) */ + void taintIfTainted(@Nullable Object target, @Nullable Object input); + + /** + * Taints the object only if the input value is tainted. If tainted, it will use the highest + * priority source of the input to taint the object. + */ + void taintIfTainted(@Nullable IastContext ctx, @Nullable Object target, @Nullable Object input); + + /** @see #taintIfTainted(IastContext, Object, Object, boolean, int) */ + void taintIfTainted( + @Nullable Object target, @Nullable Object input, boolean keepRanges, int mark); + + /** + * Taints the object only if the input value is tainted. It will try to reuse sources from the + * input value according to: + * + *

    + *
  • keepRanges=true will reuse the ranges from the input tainted value and mark them + *
  • keepRanges=false will use the highest priority source from the input ranges and mark it + *
+ */ + void taintIfTainted( + @Nullable IastContext ctx, + @Nullable Object target, + @Nullable Object input, + boolean keepRanges, + int mark); + + /** @see #taintIfTainted(IastContext, Object, Object, byte) */ + void taintIfTainted(@Nullable Object target, @Nullable Object input, byte origin); + + /** + * Taints the object only if the input value is tainted, the resulting value will be tainted using + * a source with the specified origin and no name, if target is a char sequence it will be used as + * value + */ + void taintIfTainted( + @Nullable IastContext ctx, @Nullable Object target, @Nullable Object input, byte origin); + + /** @see #taintIfTainted(IastContext, Object, Object, byte, CharSequence) */ + void taintIfTainted( + @Nullable Object target, @Nullable Object input, byte origin, @Nullable CharSequence name); + + /** + * Taints the object only if the input value is tainted, the resulting value will be tainted using + * a source with the specified origin and name, if target is a char sequence it will be used as + * value + */ + void taintIfTainted( + @Nullable IastContext ctx, + @Nullable Object target, + @Nullable Object input, + byte origin, + @Nullable CharSequence name); + + /** @see #taintIfTainted(IastContext, Object, Object, byte, CharSequence, CharSequence) */ + void taintIfTainted( + @Nullable Object target, + @Nullable Object input, + byte origin, + @Nullable CharSequence name, + @Nullable CharSequence value); + + /** + * Taints the object only if the input value is tainted, the resulting value will be tainted using + * a source with the specified origin, name and value. + */ + void taintIfTainted( + @Nullable IastContext ctx, + @Nullable Object target, + @Nullable Object input, + byte origin, + @Nullable CharSequence name, + @Nullable CharSequence value); + + /** @see #taintIfAnyTainted(IastContext, Object, Object[]) */ + void taintIfAnyTainted(@Nullable Object target, @Nullable Object[] inputs); + + /** + * Taints the object if any of the inputs is tainted. When a tainted input is found the logic is + * the same as in {@link #taintIfTainted(IastContext, Object, Object)} + * + * @see #taintIfTainted(IastContext, Object, Object) + */ + void taintIfAnyTainted( + @Nullable IastContext ctx, @Nullable Object target, @Nullable Object[] inputs); + + /** @see #taintIfAnyTainted(IastContext, Object, Object[], boolean, int) */ + void taintIfAnyTainted( + @Nullable Object target, @Nullable Object[] inputs, boolean keepRanges, int mark); + + /** + * Taints the object if any of the inputs is tainted. When a tainted input is found the logic is + * the same as in {@link #taintIfTainted(IastContext, Object, Object, boolean, int)} + * + * @see #taintIfTainted(IastContext, Object, Object, boolean, int) + */ + void taintIfAnyTainted( + @Nullable IastContext ctx, + @Nullable Object target, + @Nullable Object[] inputs, + boolean keepRanges, + int mark); + + /** @see #taintDeeply(IastContext, Object, byte, Predicate) */ + int taintDeeply(@Nullable Object target, byte origin, Predicate> classFilter); + + /** + * Visit the graph of the object and taints all the string properties found using a source with + * the selected origin and no name. + * + * @param classFilter filter for types that should be included in the visiting process + * @return number of tainted elements + */ + int taintDeeply( + @Nullable IastContext ctx, + @Nullable Object target, + byte origin, + Predicate> classFilter); + + /** @see #isTainted(IastContext, Object) */ + boolean isTainted(@Nullable Object target); + + /** Checks if an arbitrary object is tainted */ + boolean isTainted(@Nullable IastContext ctx, @Nullable Object target); + + /** @see #findSource(IastContext, Object) */ + @Nullable + Source findSource(@Nullable Object target); + + /** + * Returns the source with the highest priority if the object is tainted, {@code null} otherwise + */ + @Nullable + Source findSource(@Nullable IastContext ctx, @Nullable Object target); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/StringModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/StringModule.java new file mode 100644 index 0000000000..34b35f7923 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/StringModule.java @@ -0,0 +1,55 @@ +package datadog.trace.api.iast.propagation; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.Locale; + +import datadog.trace.api.iast.IastModule; + +public interface StringModule extends IastModule { + + void onStringConcat(@NonNull String left, @Nullable String right, @NonNull String result); + + void onStringBuilderInit(@NonNull CharSequence builder, @Nullable CharSequence param); + + void onStringBuilderAppend(@NonNull CharSequence builder, @Nullable CharSequence param); + + void onStringBuilderToString(@NonNull CharSequence builder, @NonNull String result); + + void onStringConcatFactory( + @Nullable String result, + @Nullable String[] args, + @Nullable String recipe, + @Nullable Object[] dynamicConstants, + @NonNull int[] recipeOffsets); + + void onStringSubSequence( + @NonNull String self, int beginIndex, int endIndex, @Nullable CharSequence result); + + void onStringJoin( + @Nullable String result, @NonNull CharSequence delimiter, @NonNull CharSequence[] elements); + + void onStringToUpperCase(@NonNull String self, @Nullable String result); + + void onStringToLowerCase(@NonNull String self, @Nullable String result); + + void onStringTrim(@NonNull String self, @Nullable String result); + + void onStringRepeat(@NonNull String self, int count, @NonNull String result); + + void onStringConstructor(@NonNull String self, @NonNull String result); + + void onStringFormat(@NonNull String pattern, @NonNull Object[] params, @NonNull String result); + + void onStringFormat( + @Nullable Locale locale, + @NonNull String pattern, + @NonNull Object[] params, + @NonNull String result); + + void onStringFormat( + @NonNull Iterable literals, @NonNull Object[] params, @NonNull String result); + + void onSplit(final @NonNull String self, final @NonNull String[] result); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/ApplicationModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/ApplicationModule.java new file mode 100644 index 0000000000..f52917cbc1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/ApplicationModule.java @@ -0,0 +1,10 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.Nullable; + +import datadog.trace.api.iast.IastModule; + +public interface ApplicationModule extends IastModule { + + void onRealPath(@Nullable String realPath); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/CommandInjectionModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/CommandInjectionModule.java new file mode 100644 index 0000000000..cd7ca150bc --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/CommandInjectionModule.java @@ -0,0 +1,17 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.List; + +import datadog.trace.api.iast.IastModule; + +public interface CommandInjectionModule extends IastModule { + + void onRuntimeExec(@NonNull String... command); + + void onRuntimeExec(@Nullable String[] env, @NonNull String... command); + + void onProcessBuilderStart(@NonNull List command); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HeaderInjectionModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HeaderInjectionModule.java new file mode 100644 index 0000000000..e4a0bc5372 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HeaderInjectionModule.java @@ -0,0 +1,10 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; + +import datadog.trace.api.iast.IastModule; + +public interface HeaderInjectionModule extends IastModule { + + void onHeader(@NonNull String name, String value); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java new file mode 100644 index 0000000000..bdd1e17bfb --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java @@ -0,0 +1,3 @@ +package datadog.trace.api.iast.sink; + +public interface HstsMissingHeaderModule extends HttpRequestEndModule {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpCookieModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpCookieModule.java new file mode 100644 index 0000000000..6783ae36a1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpCookieModule.java @@ -0,0 +1,13 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; + +import datadog.trace.api.iast.IastModule; +import datadog.trace.api.iast.util.Cookie; + +public interface HttpCookieModule extends IastModule { + + boolean isVulnerable(@NonNull final Cookie cookie); + + T getType(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpRequestEndModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpRequestEndModule.java new file mode 100644 index 0000000000..f6cc6415f2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpRequestEndModule.java @@ -0,0 +1,33 @@ +package datadog.trace.api.iast.sink; + +import java.net.HttpURLConnection; +import java.util.Locale; + +import datadog.trace.api.gateway.IGSpanInfo; +import datadog.trace.api.iast.IastModule; + +public interface HttpRequestEndModule extends IastModule { + + void onRequestEnd(Object ctx, IGSpanInfo span); + + default boolean isHtmlResponse(final String value) { + if (value == null) { + return false; + } + final String contentType = value.toLowerCase(Locale.ROOT); + return contentType.contains("text/html") || contentType.contains("application/xhtml+xml"); + } + + default boolean isIgnorableResponseCode(final Integer httpStatus) { + if (httpStatus == null) { + return false; + } + return httpStatus == HttpURLConnection.HTTP_MOVED_PERM + || httpStatus == HttpURLConnection.HTTP_MOVED_TEMP + || httpStatus == HttpURLConnection.HTTP_NOT_MODIFIED + || httpStatus == HttpURLConnection.HTTP_NOT_FOUND + || httpStatus == HttpURLConnection.HTTP_GONE + || httpStatus == HttpURLConnection.HTTP_INTERNAL_ERROR + || httpStatus == 307; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java new file mode 100644 index 0000000000..0a8a0b46bf --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java @@ -0,0 +1,13 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; + +import datadog.trace.api.iast.IastModule; +import datadog.trace.api.iast.util.Cookie; + +public interface HttpResponseHeaderModule extends IastModule { + + void onHeader(@NonNull String name, String value); + + void onCookie(@NonNull Cookie cookie); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/InsecureCookieModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/InsecureCookieModule.java new file mode 100644 index 0000000000..ed95b38451 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/InsecureCookieModule.java @@ -0,0 +1,3 @@ +package datadog.trace.api.iast.sink; + +public interface InsecureCookieModule extends HttpCookieModule {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/LdapInjectionModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/LdapInjectionModule.java new file mode 100644 index 0000000000..b7b671fc97 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/LdapInjectionModule.java @@ -0,0 +1,12 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import datadog.trace.api.iast.IastModule; + +public interface LdapInjectionModule extends IastModule { + + void onDirContextSearch( + @Nullable String name, @NonNull String filterExpr, @Nullable Object[] filterArgs); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java new file mode 100644 index 0000000000..c05e81c45d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java @@ -0,0 +1,3 @@ +package datadog.trace.api.iast.sink; + +public interface NoHttpOnlyCookieModule extends HttpCookieModule {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java new file mode 100644 index 0000000000..25c2b4d34f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java @@ -0,0 +1,3 @@ +package datadog.trace.api.iast.sink; + +public interface NoSameSiteCookieModule extends HttpCookieModule {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/PathTraversalModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/PathTraversalModule.java new file mode 100644 index 0000000000..211e379f2b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/PathTraversalModule.java @@ -0,0 +1,22 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.io.File; +import java.net.URI; + +import datadog.trace.api.iast.IastModule; + +public interface PathTraversalModule extends IastModule { + + void onPathTraversal(@NonNull String path); + + void onPathTraversal(@Nullable String parent, @NonNull String child); + + void onPathTraversal(@NonNull String first, @NonNull String[] more); + + void onPathTraversal(@NonNull URI uri); + + void onPathTraversal(@Nullable File parent, @NonNull String child); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SqlInjectionModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SqlInjectionModule.java new file mode 100644 index 0000000000..2dd7f9c11d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SqlInjectionModule.java @@ -0,0 +1,14 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.Nullable; + +import datadog.trace.api.iast.IastModule; + +public interface SqlInjectionModule extends IastModule { + + String DATABASE_PARAMETER = "DATABASE"; + + void onJdbcQuery(@Nullable String sql); + + void onJdbcQuery(@Nullable String sql, @Nullable String database); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SsrfModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SsrfModule.java new file mode 100644 index 0000000000..827afad1ff --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SsrfModule.java @@ -0,0 +1,12 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.Nullable; + +import datadog.trace.api.iast.IastModule; + +public interface SsrfModule extends IastModule { + + void onURLConnection(@Nullable Object url); + + void onURLConnection(@Nullable String url, @Nullable Object host, @Nullable Object uri); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/StacktraceLeakModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/StacktraceLeakModule.java new file mode 100644 index 0000000000..65a86225ab --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/StacktraceLeakModule.java @@ -0,0 +1,10 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.Nullable; + +import datadog.trace.api.iast.IastModule; + +public interface StacktraceLeakModule extends IastModule { + void onStacktraceLeak( + @Nullable final Throwable expression, String moduleName, String className, String methodName); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java new file mode 100644 index 0000000000..0a494eeb1d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java @@ -0,0 +1,10 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; + +import datadog.trace.api.iast.IastModule; + +public interface TrustBoundaryViolationModule extends IastModule { + + void onSessionValue(@NonNull String name, Object value); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java new file mode 100644 index 0000000000..acdaec6a40 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java @@ -0,0 +1,19 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.net.URI; + +import datadog.trace.api.iast.IastModule; + +public interface UnvalidatedRedirectModule extends IastModule { + + void onRedirect(@Nullable String value); + + void onRedirect(@NonNull String value, @NonNull String clazz, @NonNull String method); + + void onURIRedirect(@Nullable URI value); + + void onHeader(@NonNull String name, String value); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakCipherModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakCipherModule.java new file mode 100644 index 0000000000..23d629a3c7 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakCipherModule.java @@ -0,0 +1,10 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; + +import datadog.trace.api.iast.IastModule; + +public interface WeakCipherModule extends IastModule { + + void onCipherAlgorithm(@NonNull String algorithm); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakHashModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakHashModule.java new file mode 100644 index 0000000000..de3c1b89a2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakHashModule.java @@ -0,0 +1,10 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; + +import datadog.trace.api.iast.IastModule; + +public interface WeakHashModule extends IastModule { + + void onHashingAlgorithm(@NonNull String algorithm); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakRandomnessModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakRandomnessModule.java new file mode 100644 index 0000000000..383cdc1e9b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakRandomnessModule.java @@ -0,0 +1,10 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; + +import datadog.trace.api.iast.IastModule; + +public interface WeakRandomnessModule extends IastModule { + + void onWeakRandom(@NonNull final Class instance); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XContentTypeModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XContentTypeModule.java new file mode 100644 index 0000000000..525ab7af8b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XContentTypeModule.java @@ -0,0 +1,3 @@ +package datadog.trace.api.iast.sink; + +public interface XContentTypeModule extends HttpRequestEndModule {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XPathInjectionModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XPathInjectionModule.java new file mode 100644 index 0000000000..3a7f321091 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XPathInjectionModule.java @@ -0,0 +1,9 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.Nullable; + +import datadog.trace.api.iast.IastModule; + +public interface XPathInjectionModule extends IastModule { + void onExpression(@Nullable final String expression); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XssModule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XssModule.java new file mode 100644 index 0000000000..81315d4a9f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XssModule.java @@ -0,0 +1,19 @@ +package datadog.trace.api.iast.sink; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import datadog.trace.api.iast.IastModule; + +public interface XssModule extends IastModule { + + void onXss(@NonNull String s); + + void onXss(@NonNull String s, @NonNull String clazz, @NonNull String method); + + void onXss(@NonNull char[] array); + + void onXss(@NonNull String format, @Nullable Object[] args); + + void onXss(@NonNull CharSequence s, @Nullable String file, int line); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetric.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetric.java new file mode 100644 index 0000000000..3faf3b4574 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetric.java @@ -0,0 +1,188 @@ +package datadog.trace.api.iast.telemetry; + +import static datadog.trace.api.iast.VulnerabilityTypes.RESPONSE_HEADER; +import static datadog.trace.api.iast.VulnerabilityTypes.RESPONSE_HEADER_TYPES; +import static datadog.trace.api.iast.VulnerabilityTypes.SPRING_RESPONSE; +import static datadog.trace.api.iast.VulnerabilityTypes.SPRING_RESPONSE_TYPES; + +import androidx.annotation.NonNull; + +import java.util.function.Function; + +import datadog.trace.api.iast.SourceTypes; +import datadog.trace.api.iast.VulnerabilityTypes; + +public enum IastMetric { + INSTRUMENTED_PROPAGATION("instrumented.propagation", true, Scope.GLOBAL, Verbosity.MANDATORY), + INSTRUMENTED_SOURCE( + "instrumented.source", true, Scope.GLOBAL, Tag.SOURCE_TYPE, Verbosity.MANDATORY), + INSTRUMENTED_SINK( + "instrumented.sink", true, Scope.GLOBAL, Tag.VULNERABILITY_TYPE, Verbosity.MANDATORY), + EXECUTED_PROPAGATION("executed.propagation", true, Scope.REQUEST, Verbosity.DEBUG), + EXECUTED_SOURCE("executed.source", true, Scope.REQUEST, Tag.SOURCE_TYPE, Verbosity.INFORMATION), + EXECUTED_SINK( + "executed.sink", true, Scope.REQUEST, Tag.VULNERABILITY_TYPE, Verbosity.INFORMATION), + EXECUTED_TAINTED("executed.tainted", true, Scope.REQUEST, Verbosity.DEBUG), + REQUEST_TAINTED("request.tainted", true, Scope.REQUEST, Verbosity.INFORMATION), + TAINTED_FLAT_MODE("tainted.flat.mode", false, Scope.GLOBAL, Verbosity.INFORMATION); + + private static final int COUNT; + + static { + int count = 0; + for (final IastMetric metric : values()) { + metric.index = count; + if (metric.tag == null) { + count++; + } else { + count += metric.tag.getValues().length; + } + } + COUNT = count; + } + + public static int count() { + return COUNT; + } + + private final String name; + private final boolean common; + private final Scope scope; + private final Tag tag; + private final Verbosity verbosity; + private int index; + + IastMetric( + final String name, final boolean common, final Scope scope, final Verbosity verbosity) { + this(name, common, scope, null, verbosity); + } + + IastMetric( + final String name, + final boolean common, + final Scope scope, + final Tag tag, + final Verbosity verbosity) { + this.name = name; + this.common = common; + this.scope = scope; + this.tag = tag; + this.verbosity = verbosity; + } + + public String getName() { + return name; + } + + public boolean isCommon() { + return common; + } + + public Scope getScope() { + return scope; + } + + public boolean isEnabled(@NonNull final Verbosity verbosity) { + return verbosity.isEnabled(this.verbosity); + } + + public Tag getTag() { + return tag; + } + + /** + * Returns the index for the particular tag to be used in the {@link + * java.util.concurrent.atomic.AtomicLongArray} of {@link IastMetricCollector} + */ + public int getIndex(final byte tagValue) { + if (tag == null) { + return index; + } + if (tagValue < 0) { + return -1; + } + return index + tagValue; + } + + public static class Tag { + + private static final byte[] EMPTY = new byte[0]; + + public static final Tag VULNERABILITY_TYPE = + new Tag("vulnerability_type", VulnerabilityTypes.values(), VulnerabilityTypes::toString) { + + @Override + public boolean isWrapped(byte tagValue) { + switch (tagValue) { + case RESPONSE_HEADER: + case SPRING_RESPONSE: + return true; + default: + return false; + } + } + + public byte[] unwrap(final byte tagValue) { + switch (tagValue) { + case RESPONSE_HEADER: + return RESPONSE_HEADER_TYPES; + case SPRING_RESPONSE: + return SPRING_RESPONSE_TYPES; + default: + return EMPTY; + } + } + }; + + public static final Tag SOURCE_TYPE = + new Tag("source_type", SourceTypes.values(), SourceTypes::toString); + + private final String name; + + private final Function toString; + private final byte[] values; + + private Tag(final String name, final byte[] values, final Function toString) { + this.name = name; + this.toString = toString; + this.values = values; + } + + public String getName() { + return name; + } + + public byte[] getValues() { + return values; + } + + /** Wrapped tags are aggregation of other tags that should be incremented together */ + public boolean isWrapped(final byte tagValue) { + return false; + } + + public byte[] unwrap(final byte tagValue) { + return EMPTY; + } + + public String toString(final byte tagValue) { + return toString.apply(tagValue); + } + } + + public static final class Scope { + + public static final Scope GLOBAL = new Scope("global"); + public static final Scope REQUEST = new Scope("request"); + + private final String name; + + private Scope(final String name) { + this.name = name; + } + + public String getName() { + return name; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java new file mode 100644 index 0000000000..d06027d30c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java @@ -0,0 +1,238 @@ +package datadog.trace.api.iast.telemetry; + +import static datadog.trace.api.iast.telemetry.IastMetric.Scope.REQUEST; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.atomic.AtomicLongArray; + +import datadog.trace.api.Config; +import datadog.trace.api.gateway.RequestContext; +import datadog.trace.api.gateway.RequestContextSlot; +import datadog.trace.api.iast.telemetry.IastMetric.Tag; +import datadog.trace.api.telemetry.MetricCollector; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentTracer; + +@SuppressWarnings("resource") +public class IastMetricCollector implements MetricCollector { + + private static final Logger LOGGER = LoggerFactory.getLogger(IastMetricCollector.class); + + private static final String NAMESPACE = "iast"; + + private static final Verbosity VERBOSITY = Config.get().getIastTelemetryVerbosity(); + + private static final IastMetricCollector INSTANCE = + VERBOSITY != Verbosity.OFF ? new IastMetricCollector() : new NoOpInstance(); + + public static IastMetricCollector get() { + return INSTANCE; + } + + private static IastMetricCollector get(@Nullable Object ctx) { + if (VERBOSITY == Verbosity.OFF) { + return INSTANCE; + } + if (ctx == null) { + ctx = activeRequestContext(); + } + if (ctx instanceof RequestContext) { + ctx = ((RequestContext) ctx).getData(RequestContextSlot.IAST); + } + if (ctx instanceof HasMetricCollector) { + final IastMetricCollector collector = ((HasMetricCollector) ctx).getMetricCollector(); + if (collector != null) { + return collector; + } + } + // if no active request then forward to the global collector + return INSTANCE; + } + + private final BlockingQueue rawMetricsQueue; + + private final AtomicLongArray counters; + + public IastMetricCollector() { + this(new ArrayBlockingQueue<>(RAW_QUEUE_SIZE), new AtomicLongArray(IastMetric.count())); + } + + protected IastMetricCollector( + final BlockingQueue rawMetricsQueue, final AtomicLongArray counters) { + this.rawMetricsQueue = rawMetricsQueue; + this.counters = counters; + } + + /** Prefer using {@link #add(IastMetric, int, Object)} if possible */ + public static void add(@NonNull final IastMetric metric, final int value) { + add(metric, value, null); + } + + public static void add( + @NonNull final IastMetric metric, final int value, @Nullable final Object ctx) { + add(metric, (byte) -1, value, ctx); + } + + /** Prefer using {@link #add(IastMetric, byte, int, Object)} if possible */ + public static void add(@NonNull final IastMetric metric, final byte tagValue, final int value) { + add(metric, tagValue, value, null); + } + + public static void add( + @NonNull final IastMetric metric, + final byte tagValue, + final int value, + @Nullable final Object ctx) { + try { + final IastMetricCollector instance = metric.getScope() == REQUEST ? get(ctx) : INSTANCE; + instance.addMetric(metric, tagValue, value); + } catch (final Throwable e) { + LOGGER.warn("Failed to add metric {} with tag {}", metric, tagValue, e); + } + } + + public void addMetric(final IastMetric metric, final byte tagValue, final int value) { + final Tag tag = metric.getTag(); + if (tag != null && tag.isWrapped(tagValue)) { + // e.g.: VulnerabilityTypes.RESPONSE_HEADER + for (final byte unwrapped : metric.getTag().unwrap(tagValue)) { + increment(metric.getIndex(unwrapped), value); + } + } else { + increment(metric.getIndex(tagValue), value); + } + } + + private void increment(final int index, final int value) { + if (index >= 0) { + counters.getAndAdd(index, value); + } + } + + public void merge(final Collection metrics) { + for (final IastMetricData data : metrics) { + final IastMetric metric = data.metric; + final byte tagValue = data.tagValue; + final long value = data.value.longValue(); + counters.getAndAdd(metric.getIndex(tagValue), value); + } + } + + @Override + public void prepareMetrics() { + for (final IastMetric metric : IastMetric.values()) { + if (metric.getTag() == null) { + prepareMetric(metric, (byte) -1); + } else { + for (final byte tagValue : metric.getTag().getValues()) { + prepareMetric(metric, tagValue); + } + } + } + } + + private void prepareMetric(final IastMetric metric, final byte tagValue) { + final int index = metric.getIndex(tagValue); + final long value = counters.getAndSet(index, 0); + if (value > 0) { + rawMetricsQueue.offer(new IastMetricData(metric, tagValue, value)); + } + } + + @Override + public Collection drain() { + if (!rawMetricsQueue.isEmpty()) { + final List list = new LinkedList<>(); + final int drained = rawMetricsQueue.drainTo(list); + if (drained > 0) { + return list; + } + } + return Collections.emptyList(); + } + + public static class IastMetricData extends Metric { + + private final IastMetric metric; + private final byte tagValue; + + public IastMetricData(final IastMetric metric, final byte tagValue, final long value) { + super( + NAMESPACE, + metric.isCommon(), + metric.getName(), + "count", + value, + computeTag(metric, tagValue)); + this.metric = metric; + this.tagValue = tagValue; + } + + public IastMetric getMetric() { + return metric; + } + + public byte getTagValue() { + return tagValue; + } + + public String getSpanTag() { + if (metric.getTag() == null) { + return metric.getName(); + } + final String tag = metric.getTag().toString(tagValue); + final String spanTag = tag.toLowerCase(Locale.ROOT).replace('.', '_'); + return String.format("%s.%s", metric.getName(), spanTag); + } + + public static String computeTag(final IastMetric metric, final byte tagValue) { + if (metric.getTag() == null) { + return null; + } + return String.format("%s:%s", metric.getTag().getName(), metric.getTag().toString(tagValue)); + } + } + + private static RequestContext activeRequestContext() { + final AgentSpan span = AgentTracer.activeSpan(); + return span == null ? null : span.getRequestContext(); + } + + private static class NoOpInstance extends IastMetricCollector { + + public NoOpInstance() { + super(null, null); + } + + @Override + public void addMetric(final IastMetric metric, final byte tagValue, final int value) {} + + @Override + public void merge(final Collection metrics) {} + + @Override + public void prepareMetrics() {} + + @Override + public Collection drain() { + return Collections.emptyList(); + } + } + + public interface HasMetricCollector { + + IastMetricCollector getMetricCollector(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/Verbosity.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/Verbosity.java new file mode 100644 index 0000000000..c6965aca24 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/Verbosity.java @@ -0,0 +1,24 @@ +package datadog.trace.api.iast.telemetry; + +public enum Verbosity { + OFF, + MANDATORY, + INFORMATION, + DEBUG; + + public boolean isEnabled(final Verbosity value) { + return value.ordinal() <= ordinal(); + } + + public boolean isDebugEnabled() { + return isEnabled(DEBUG); + } + + public boolean isInformationEnabled() { + return isEnabled(INFORMATION); + } + + public boolean isMandatoryEnabled() { + return isEnabled(MANDATORY); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/util/Cookie.java b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/util/Cookie.java new file mode 100644 index 0000000000..c743932add --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/iast/util/Cookie.java @@ -0,0 +1,66 @@ +package datadog.trace.api.iast.util; + +public class Cookie { + + private final String cookieName; + private final boolean secure; + private final String sameSite; + private final boolean httpOnly; + + public Cookie(final String cookieName, boolean secure, boolean httpOnly, String sameSite) { + this.cookieName = cookieName; + this.secure = secure; + this.sameSite = sameSite; + this.httpOnly = httpOnly; + } + + public String getCookieName() { + return cookieName; + } + + public boolean isSecure() { + return secure; + } + + public String getSameSite() { + return sameSite; + } + + public boolean isHttpOnly() { + return httpOnly; + } + + public static Builder named(final String name) { + return new Builder(name); + } + + public static class Builder { + private final String name; + private boolean secure = false; + private boolean httpOnly = false; + private String sameSite = null; + + public Builder(final String name) { + this.name = name; + } + + public Builder secure(final boolean secure) { + this.secure = secure; + return this; + } + + public Builder httpOnly(final boolean httpOnly) { + this.httpOnly = httpOnly; + return this; + } + + public Builder sameSite(final String sameSite) { + this.sameSite = sameSite; + return this; + } + + public Cookie build() { + return new Cookie(name, secure, httpOnly, sameSite); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/intake/TrackType.java b/features/dd-trace-core/src/main/java/datadog/trace/api/intake/TrackType.java new file mode 100644 index 0000000000..6af32af4c2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/intake/TrackType.java @@ -0,0 +1,7 @@ +package datadog.trace.api.intake; + +public enum TrackType { + CITESTCYCLE, + CITESTCOV, + NOOP +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/AbstractTraceInterceptor.java b/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/AbstractTraceInterceptor.java new file mode 100644 index 0000000000..c40bffc83d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/AbstractTraceInterceptor.java @@ -0,0 +1,38 @@ +package datadog.trace.api.interceptor; + +public abstract class AbstractTraceInterceptor implements TraceInterceptor { + + private final Priority priority; + + protected AbstractTraceInterceptor(Priority priority) { + this.priority = priority; + } + + @Override + public int priority() { + return priority.idx; + } + + public enum Priority { + // trace filtering + CI_VISIBILITY_TRACE(0), + CI_VISIBILITY_APM(1), + + // trace data enrichment + DD_INTAKE(2), + GIT_METADATA(3), + + // trace data collection + SERVICE_NAME_COLLECTING(Integer.MAX_VALUE); + + private final int idx; + + Priority(int idx) { + this.idx = idx; + } + + int getIdx() { + return idx; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/MutableSpan.java b/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/MutableSpan.java new file mode 100644 index 0000000000..4856a5ae58 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/MutableSpan.java @@ -0,0 +1,78 @@ +package datadog.trace.api.interceptor; + +import java.util.Map; + +import datadog.trace.api.DDTags; + +public interface MutableSpan { + + /** @return Start time with nanosecond scale, but millisecond resolution. */ + long getStartTime(); + + /** @return Duration with nanosecond scale. */ + long getDurationNano(); + + CharSequence getOperationName(); + + MutableSpan setOperationName(final CharSequence serviceName); + + String getServiceName(); + + MutableSpan setServiceName(final String serviceName); + + CharSequence getResourceName(); + + MutableSpan setResourceName(final CharSequence resourceName); + + Integer getSamplingPriority(); + + /** + * @param newPriority + * @return + * @deprecated Use {@link io.opentracing.Span#setTag(String, boolean)} instead using either tag + * names {@link DDTags#MANUAL_KEEP} or {@link + * DDTags#MANUAL_DROP}. + */ + @Deprecated + MutableSpan setSamplingPriority(final int newPriority); + + String getSpanType(); + + MutableSpan setSpanType(final CharSequence type); + + Map getTags(); + + default Object getTag(String key) { + Map tags = getTags(); + return tags == null ? null : tags.get(key); + } + + MutableSpan setTag(final String tag, final String value); + + MutableSpan setTag(final String tag, final boolean value); + + MutableSpan setTag(final String tag, final Number value); + + MutableSpan setMetric(final CharSequence metric, final int value); + + MutableSpan setMetric(final CharSequence metric, final long value); + + MutableSpan setMetric(final CharSequence metric, final double value); + + boolean isError(); + + MutableSpan setError(boolean value); + + /** @deprecated Use {@link #getLocalRootSpan()} instead. */ + @Deprecated + MutableSpan getRootSpan(); + + /** + * Returns the root span for current the trace fragment. In the context of distributed tracing + * this method returns the root span only for the fragment generated by the currently traced + * application. + * + * @return The root span for the current trace fragment. + */ + MutableSpan getLocalRootSpan(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/TraceInterceptor.java b/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/TraceInterceptor.java new file mode 100644 index 0000000000..822e0b9fd6 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/TraceInterceptor.java @@ -0,0 +1,22 @@ +package datadog.trace.api.interceptor; + +import java.util.Collection; + +public interface TraceInterceptor { + + /** + * After a trace is "complete" but before it is written, it is provided to the interceptors to + * modify. The result following all interceptors is sampled then sent to the trace writer. + * + * @param trace - The collection of spans that represent a trace. Can be modified in place. Order + * of spans should not be relied upon. + * @return A potentially modified or replaced collection of spans. Must not be null. + */ + Collection onTraceComplete(Collection trace); + + /** + * @return A unique priority for sorting relative to other TraceInterceptors. Unique because + * interceptors are stored in a sorted set, so duplicates will not be added. + */ + int priority(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/internal/InternalTracer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/internal/InternalTracer.java new file mode 100644 index 0000000000..73a825ea32 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/internal/InternalTracer.java @@ -0,0 +1,33 @@ +package datadog.trace.api.internal; + +import datadog.trace.api.experimental.DataStreamsCheckpointer; +import datadog.trace.api.profiling.Profiling; + +/** + * Tracer internal features. Those features are not part of public API and can change or be removed + * at any time. + */ +public interface InternalTracer { + /** + * Attach callbacks to the global scope manager. + * + * @param afterScopeActivatedCallback Callback on scope activation. + * @param afterScopeClosedCallback Callback on scope close. + */ + void addScopeListener(Runnable afterScopeActivatedCallback, Runnable afterScopeClosedCallback); + + void flush(); + + void flushMetrics(); + + Profiling getProfilingContext(); + + TraceSegment getTraceSegment(); + + /** + * Return the global instance of the DataStreams checkpointer. + * + * @return DataStreamsCheckpointer instance. + */ + DataStreamsCheckpointer getDataStreamsCheckpointer(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/internal/TraceSegment.java b/features/dd-trace-core/src/main/java/datadog/trace/api/internal/TraceSegment.java new file mode 100644 index 0000000000..0e2adb22ff --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/internal/TraceSegment.java @@ -0,0 +1,90 @@ +package datadog.trace.api.internal; + +/** + * A {@code TraceSegment} represents the local, i.e. in the scope of this {@code Tracer}, part of a + * a {@code Trace}. It can consist of multiple spans, and the {@code TraceSegment} instance can only + * be used in relation to the {@code Span} from which it was acquired. This means that the {@code + * TraceSegment} should not be stored and used at a later time, or passed around to async functions. + */ +public interface TraceSegment { + + /** + * Add a tag to the top of this {@code TraceSegment}. + * + * @param key key of the tag + * @param value value of the tag + */ + default void setTagTop(String key, Object value) { + setTagTop(key, value, false); + } + + /** + * Add a tag to the top of this {@code TraceSegment} with optional key sanitization. + * + * @param key key of the tag + * @param value value of the tag + * @param sanitize indicates is key need to be sanitized + */ + void setTagTop(String key, Object value, boolean sanitize); + + /** + * Add a tag to the current span in this {@code TraceSegment}. + * + * @param key key of the tag + * @param value value of the tag + */ + default void setTagCurrent(String key, Object value) { + setTagCurrent(key, value, false); + } + + /** + * Add a tag to the current span in this {@code TraceSegment}. with optional key sanitization. + * + * @param key key of the tag + * @param value value of the tag + * @param sanitize indicates is key need to be sanitized + */ + void setTagCurrent(String key, Object value, boolean sanitize); + + /** + * Add data to the top of this {@code TraceSegment}. The {@code toString} representation of the + * {@code value} must be valid top level JSON, i.e. an {@code Object} or an {@code Array}. + * + * @param key key of the data + * @param value value of the data + */ + void setDataTop(String key, Object value); + + /** Mark the request as effectively blocked, by setting the tag appsec.blocked */ + void effectivelyBlocked(); + + /** + * Add data to the current span in this {@code TraceSegment}. The {@code toString} representation + * of the {@code value} must be valid top level JSON, i.e. an {@code Object} or an {@code Array}. + * + * @param key key of the data + * @param value value of the data + */ + void setDataCurrent(String key, Object value); + + class NoOp implements TraceSegment { + public static final TraceSegment INSTANCE = new NoOp(); + + private NoOp() {} + + @Override + public void setTagTop(String key, Object value, boolean sanitize) {} + + @Override + public void setTagCurrent(String key, Object value, boolean sanitize) {} + + @Override + public void setDataTop(String key, Object value) {} + + @Override + public void effectivelyBlocked() {} + + @Override + public void setDataCurrent(String key, Object value) {} + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/internal/util/LongStringUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/api/internal/util/LongStringUtils.java new file mode 100644 index 0000000000..aa55b8943f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/internal/util/LongStringUtils.java @@ -0,0 +1,172 @@ +package datadog.trace.api.internal.util; + +import static java.nio.charset.StandardCharsets.US_ASCII; + +import java.util.Arrays; + +/** + * Utility class with common long decimal and hexadecimal parsing, and {@link String} creation + * methods. + */ +public class LongStringUtils { + private static final long MAX_FIRST_PART = 0x1999999999999999L; // Max unsigned 64 bits / 10 + + private LongStringUtils() {} + + /** + * Parse the hex representation of the unsigned 64 bit long from the {@code String}. + * + * @param s String in hexadecimal of unsigned 64-bits long. + * @return long + * @throws NumberFormatException + */ + public static long parseUnsignedLongHex(CharSequence s) throws NumberFormatException { + return LongStringUtils.parseUnsignedLongHex(s, 0, s == null ? 0 : s.length(), false); + } + + /** + * Parse the hex representation of the unsigned 64 bit long from the {@code String}. + * + * @param s String in hex of unsigned 64 bits + * @param start the start index of the hex value + * @param len the len of the hex value + * @param lowerCaseOnly if the allowed hex characters are lower case only + * @return long + * @throws NumberFormatException + */ + public static long parseUnsignedLongHex(CharSequence s, int start, int len, boolean lowerCaseOnly) + throws NumberFormatException { + if (s == null) { + throw new NumberFormatException("null"); + } + + if (len > 0 && start >= 0 && start + len <= s.length()) { + if (len > 16 && (len - firstNonZeroCharacter(s, start)) > 16) { + // Unsigned 64 bits max is 16 digits, so this always overflows + throw numberFormatOutOfLongRange(s); + } + long result = 0; + int ok = 0; + for (int i = 0; i < len && ok >= 0; i++, start++) { + char c = s.charAt(start); + int d = Character.digit(c, 16); + if (lowerCaseOnly && Character.isUpperCase(c)) { + ok = -1; + } + ok |= d; + result = result << 4 | d; + } + if (ok < 0) { + throw new NumberFormatException("Illegal character in " + s.subSequence(start, len)); + } + return result; + } else { + throw new NumberFormatException("Empty input string"); + } + } + + private static int firstNonZeroCharacter(CharSequence s, int start) { + int firstNonZero = start; + for (; firstNonZero < s.length(); firstNonZero++) { + if (s.charAt(firstNonZero) != '0') break; + } + return firstNonZero; + } + + public static long parseUnsignedLong(String s) throws NumberFormatException { + if (s == null) { + throw new NumberFormatException("s can't be null"); + } + + int len = s.length(); + if (len > 0) { + char firstChar = s.charAt(0); + if (firstChar == '-') { + throw new NumberFormatException( + String.format("Illegal leading minus sign on unsigned string %s.", s)); + } else { + if (len <= 18) { // Signed 64 bits max is 19 digits, so this always fits + return Long.parseLong(s); + } else if (len > 20) { // Unsigned 64 bits max is 20 digits, so this always overflows + throw numberFormatOutOfLongRange(s); + } + // Now do the first part and the last character + long first = 0; + int ok = 0; + for (int i = 0; i < len - 1; i++) { + char c = s.charAt(i); + int d = Character.digit(c, 10); + ok |= d; + first = first * 10 + d; + } + int last = Character.digit(s.charAt(len - 1), 10); + ok |= last; + if (ok < 0) { + throw new NumberFormatException("Illegal character in " + s); + } + if (first > MAX_FIRST_PART) { + throw numberFormatOutOfLongRange(s); + } + long guard = first * 10; + long result = guard + last; + if (guard < 0 && result >= 0) { + throw numberFormatOutOfLongRange(s); + } + return result; + } + } else { + throw new NumberFormatException("Empty input string"); + } + } + + /** + * Creates a {@code NumberFormatException} with a consistent error message. + * + * @param s the {@code String} that exceeds the range of a {@code Long} + * @return NumberFormatException + */ + public static NumberFormatException numberFormatOutOfLongRange(CharSequence s) { + return new NumberFormatException( + String.format("String value %s exceeds range of unsigned long.", s)); + } + + private static final byte[] HEX_DIGITS = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + + public static String toHexStringPadded(long id, int size) { + byte[] bytes = allocatePaddedHexStringBytes(size); + fillStringBytesWithPaddedHexId(id, 0, bytes.length, bytes); + return new String(bytes, US_ASCII); + } + + public static String toHexStringPadded(long highOrderBits, long lowOrderBits, int size) { + if (size <= 16) { + // Fallback to only one id formatting + return toHexStringPadded(lowOrderBits, size); + } + byte[] bytes = allocatePaddedHexStringBytes(size); + fillStringBytesWithPaddedHexId(highOrderBits, 0, 16, bytes); + fillStringBytesWithPaddedHexId(lowOrderBits, 16, 16, bytes); + return new String(bytes, US_ASCII); + } + + private static byte[] allocatePaddedHexStringBytes(int size) { + if (size > 16) { + size = 32; + } else if (size < 16) { + size = 16; + } + return new byte[size]; + } + + private static void fillStringBytesWithPaddedHexId(long id, int index, int size, byte[] bytes) { + int nibbleCount = Long.numberOfLeadingZeros(id) >>> 2; + Arrays.fill(bytes, index, index + (size - 16) + nibbleCount, (byte) '0'); + for (int i = 0; i < 16 - nibbleCount; i++) { + int b = (int) (id & 0xF); + bytes[index + size - 1 - i] = HEX_DIGITS[b]; + id >>>= 4; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/CoreCounter.java b/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/CoreCounter.java new file mode 100644 index 0000000000..c5d9abedce --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/CoreCounter.java @@ -0,0 +1,25 @@ +package datadog.trace.api.metrics; + +/** This interface describes a core counter metric. */ +public interface CoreCounter { + /** + * Get the counter name. + * + * @return The counter name. + */ + String getName(); + + /** + * Get the counter value. + * + * @return The counter value. + */ + long getValue(); + + /** + * Get the value and reset the counter. + * + * @return The current counter value. + */ + long getValueAndReset(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistry.java b/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistry.java new file mode 100644 index 0000000000..20c9c26442 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistry.java @@ -0,0 +1,33 @@ +package datadog.trace.api.metrics; + +import datadog.trace.api.InstrumenterConfig; + +/** This class holds the {@link SpanMetrics} instances. */ +@FunctionalInterface +public interface SpanMetricRegistry { + SpanMetricRegistry NOOP = instrumentationName -> SpanMetrics.NOOP; + + /** + * Get the span metrics for an instrumentation. + * + * @param instrumentationName The instrumentation name to get span metrics. + * @return The related span metrics instance. + */ + SpanMetrics get(String instrumentationName); + + /** @return Human-readable summary of the current span metrics. */ + default String summary() { + return ""; + } + + /** + * Get the registry instance according the telemetry status. + * + * @return The registry instance. + */ + static SpanMetricRegistry getInstance() { + return InstrumenterConfig.get().isTelemetryEnabled() + ? SpanMetricRegistryImpl.getInstance() + : SpanMetricRegistry.NOOP; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistryImpl.java b/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistryImpl.java new file mode 100644 index 0000000000..be2123c3ae --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistryImpl.java @@ -0,0 +1,48 @@ +package datadog.trace.api.metrics; + +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** The default {@link SpanMetricRegistry} implementation. */ +public class SpanMetricRegistryImpl implements SpanMetricRegistry { + private static final SpanMetricRegistryImpl INSTANCE = new SpanMetricRegistryImpl(); + private final Map spanMetrics; + + public static SpanMetricRegistryImpl getInstance() { + return INSTANCE; + } + + private SpanMetricRegistryImpl() { + this.spanMetrics = new ConcurrentHashMap<>(); + } + + @Override + public SpanMetrics get(String instrumentationName) { + return this.spanMetrics.computeIfAbsent(instrumentationName, SpanMetricsImpl::new); + } + + @Override + public String summary() { + StringBuilder summary = new StringBuilder(); + for (SpanMetricsImpl metric : spanMetrics.values()) { + summary.append(metric.getInstrumentationName()); + String separator = ": "; + for (CoreCounter counter : metric.getCounters()) { + summary.append(separator).append(counter.getName()).append('=').append(counter.getValue()); + separator = ", "; + } + summary.append('\n'); + } + return summary.toString(); + } + + /** + * Get all span metrics. + * + * @return All span metrics registered instances. + */ + public Collection getSpanMetrics() { + return this.spanMetrics.values(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetrics.java b/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetrics.java new file mode 100644 index 0000000000..fa4462316c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetrics.java @@ -0,0 +1,19 @@ +package datadog.trace.api.metrics; + +/** The core metrics related to a span./ */ +public interface SpanMetrics { + SpanMetrics NOOP = + new SpanMetrics() { + @Override + public void onSpanCreated() {} + + @Override + public void onSpanFinished() {} + }; + + /** Increment span created counter. */ + void onSpanCreated(); + + /** Increment span finished counter. */ + void onSpanFinished(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricsImpl.java b/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricsImpl.java new file mode 100644 index 0000000000..b0781008e2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricsImpl.java @@ -0,0 +1,72 @@ +package datadog.trace.api.metrics; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +/** The default implementation of {@link SpanMetrics} based on atomic counters. */ +public class SpanMetricsImpl implements SpanMetrics { + private final String instrumentationName; + private final AtomicLong spanCreatedCounter; + private final AtomicLong spanFinishedCounter; + private final Collection coreCounters; + + public SpanMetricsImpl(String instrumentationName) { + this.instrumentationName = instrumentationName; + this.spanCreatedCounter = new AtomicLong(0); + this.spanFinishedCounter = new AtomicLong(0); + List coreCounters = new ArrayList<>(2); + coreCounters.add(new SpanCounter("spans_created", this.spanCreatedCounter)); + coreCounters.add(new SpanCounter("spans_finished", this.spanFinishedCounter)); + this.coreCounters = Collections.unmodifiableList(coreCounters); + } + + @Override + public void onSpanCreated() { + this.spanCreatedCounter.incrementAndGet(); + } + + @Override + public void onSpanFinished() { + this.spanFinishedCounter.incrementAndGet(); + } + + public String getInstrumentationName() { + return this.instrumentationName; + } + + public Collection getCounters() { + return this.coreCounters; + } + + private static class SpanCounter implements CoreCounter { + private final String name; + private final AtomicLong counter; + private long previousCount; + + private SpanCounter(String name, AtomicLong counter) { + this.name = name; + this.counter = counter; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public long getValue() { + return counter.get(); + } + + @Override + public long getValueAndReset() { + long count = counter.get(); + long delta = count - previousCount; + previousCount = count; + return delta; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/NamingSchema.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/NamingSchema.java new file mode 100644 index 0000000000..55d8e54ca8 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/NamingSchema.java @@ -0,0 +1,258 @@ +package datadog.trace.api.naming; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.Map; + +public interface NamingSchema { + /** + * Get the naming policy for caches. + * + * @return a {@link ForCache} instance. + */ + ForCache cache(); + + /** + * Get the naming policy for clients (http, soap, ...). + * + * @return a {@link ForClient} instance. + */ + ForClient client(); + + /** + * Get the naming policy for cloud providers (aws, gpc, azure, ...). + * + * @return a {@link ForCloud} instance. + */ + ForCloud cloud(); + + /** + * Get the naming policy for databases. + * + * @return a {@link ForDatabase} instance. + */ + ForDatabase database(); + + /** + * Get the naming policy for messaging. + * + * @return a {@link ForMessaging} instance. + */ + ForMessaging messaging(); + + /** + * Get the naming policy for servers. + * + * @return a {@link ForServer} instance. + */ + ForServer server(); + + /** + * Policy for peer service tags calculation + * + * @return + */ + ForPeerService peerService(); + + /** + * If true, the schema allows having service names != DD_SERVICE + * + * @return + */ + boolean allowInferredServices(); + + interface ForCache { + /** + * Calculate the operation name for a cache span. + * + * @param cacheSystem the caching system (e.g. redis, memcached,..) + * @return the operation name + */ + @NonNull + String operation(@NonNull String cacheSystem); + + /** + * Calculate the service name for a cache span. + * + * @param cacheSystem the caching system (e.g. redis, memcached,..) + * @return the service name + */ + String service(@NonNull String cacheSystem); + } + + interface ForClient { + /** + * Calculate the operation name for a client span. + * + * @param protocol the protocol used (e.g. http, ftp, ..) + * @return the operation name + */ + @NonNull + String operationForProtocol(@NonNull String protocol); + + /** + * Calculate the operation name for a client span. + * + * @param component the name of the instrumentation componen + * @return the operation name + */ + @NonNull + String operationForComponent(@NonNull String component); + } + + interface ForCloud { + + /** + * Calculate the operation name for a generic cloud sdk call. + * + * @param provider the cloud provider + * @param cloudService the cloud service name (e.g. s3) + * @param serviceOperation the qualified service operation (e.g.S3.CreateBucket) + * @return the operation name for this span + */ + @NonNull + String operationForRequest( + @NonNull String provider, @NonNull String cloudService, @NonNull String serviceOperation); + + /** + * Calculate the service name for a generic cloud sdk call. + * + * @param provider the cloud provider + * @param cloudService the cloud service name (e.g. s3). If not provided the method should + * return a default value + * @return the service name for this span + */ + String serviceForRequest(@NonNull String provider, @Nullable String cloudService); + + /** + * Calculate the operation name for a function as a service invocation (e.g. aws lambda) + * + * @param provider the cloud provider + * @return the operation name for this span + */ + @NonNull + String operationForFaas(@NonNull String provider); + } + + interface ForDatabase { + /** + * Normalize the cache name from the raw parsed one. + * + * @param rawName the raw name + * @return the normalized one + */ + String normalizedName(@NonNull String rawName); + + /** + * Calculate the operation name for a database span. + * + * @param databaseType the database type (e.g. postgres, elasticsearch,..) + * @return the operation name + */ + @NonNull + String operation(@NonNull String databaseType); + + /** + * Calculate the service name for a database span. + * + * @param databaseType the database type (e.g. postgres, elasticsearch,..) + * @return the service name + */ + String service(@NonNull String databaseType); + } + + interface ForMessaging { + /** + * Calculate the operation name for a messaging consumer span for process operation. + * + * @param messagingSystem the messaging system (e.g. jms, kafka,..) + * @return the operation name + */ + @NonNull + String inboundOperation(@NonNull String messagingSystem); + + /** + * Calculate the service name for a messaging producer span. + * + * @param messagingSystem the messaging system (e.g. jms, kafka, amqp,..) + * @param useLegacyTracing if true legacy tracing service naming will be applied if compatible + * @return the service name + */ + String inboundService(@NonNull String messagingSystem, boolean useLegacyTracing); + + /** + * Calculate the operation name for a messaging producer span. + * + * @param messagingSystem the messaging system (e.g. jms, kafka, amqp,..) + * @return the operation name + */ + @NonNull + String outboundOperation(@NonNull String messagingSystem); + + /** + * Calculate the service name for a messaging producer span. + * + * @param messagingSystem the messaging system (e.g. jms, kafka, amqp,..) + * @param useLegacyTracing if true legacy tracing service naming will be applied if compatible + * @return the service name + */ + String outboundService(@NonNull String messagingSystem, boolean useLegacyTracing); + + /** + * Calculate the service name for a messaging time in queue synthetic span. + * + * @param messagingSystem the messaging system (e.g. jms, kafka, amqp,..) + * @return the service name + */ + @NonNull + String timeInQueueService(@NonNull String messagingSystem); + + /** + * Calculate the operation name for a messaging time in queue synthetic span. + * + * @param messagingSystem the messaging system (e.g. jms, kafka, amqp,..) + * @return the operation name + */ + @NonNull + String timeInQueueOperation(@NonNull String messagingSystem); + } + + interface ForPeerService { + /** + * Whenever the schema supports peer service calculation + * + * @return + */ + boolean supports(); + + /** + * Calculate the tags to be added to a span to represent the peer service + * + * @param unsafeTags the span tags. Map che be mutated + * @return the input tags + */ + @NonNull + Map tags(@NonNull Map unsafeTags); + } + + interface ForServer { + /** + * Calculate the operation name for a server span. + * + * @param protocol the protocol used (e.g. http, soap, rmi ..) + * @return the operation name + */ + @NonNull + String operationForProtocol(@NonNull String protocol); + + /** + * Calculate the operation name for a server span. + * + * @param component the name of the instrumentation component + * @return the operation name + */ + @NonNull + String operationForComponent(@NonNull String component); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/SpanNaming.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/SpanNaming.java new file mode 100644 index 0000000000..adbc318103 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/SpanNaming.java @@ -0,0 +1,51 @@ +package datadog.trace.api.naming; + +import androidx.annotation.NonNull; + +import datadog.trace.api.Config; +import datadog.trace.api.naming.v0.NamingSchemaV0; +import datadog.trace.api.naming.v1.NamingSchemaV1; + +/** This is the main entry point to drive span naming decisions. */ +public class SpanNaming { + public static final int SCHEMA_MIN_VERSION = 0; + public static final int SCHEMA_MAX_VERSION = 1; + + private static class Singleton { + private static SpanNaming INSTANCE = new SpanNaming(); + } + + public static SpanNaming instance() { + return Singleton.INSTANCE; + } + + private final NamingSchema namingSchema; + private final int version; + + // Choice of version will be driven by a configuration parameter when all the instrumentations' + // naming will be addressed + private SpanNaming() { + this(Config.get().getSpanAttributeSchemaVersion()); + } + + private SpanNaming(final int version) { + this.version = version; + switch (version) { + case 1: + namingSchema = new NamingSchemaV1(); + break; + default: + namingSchema = new NamingSchemaV0(); + break; + } + } + + @NonNull + public NamingSchema namingSchema() { + return namingSchema; + } + + public int version() { + return version; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CacheNamingV0.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CacheNamingV0.java new file mode 100644 index 0000000000..3f858684ca --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CacheNamingV0.java @@ -0,0 +1,43 @@ +package datadog.trace.api.naming.v0; + +import androidx.annotation.NonNull; + +import datadog.trace.api.naming.NamingSchema; + +public class CacheNamingV0 implements NamingSchema.ForCache { + + private final boolean allowInferredServices; + + public CacheNamingV0(boolean allowInferredServices) { + this.allowInferredServices = allowInferredServices; + } + + @NonNull + @Override + public String operation(@NonNull String cacheSystem) { + String postfix; + switch (cacheSystem) { + case "ignite": + postfix = ".cache"; + break; + case "hazelcast": + postfix = ".invoke"; + break; + default: + postfix = ".query"; + break; + } + return cacheSystem + postfix; + } + + @Override + public String service(@NonNull String cacheSystem) { + if (!allowInferredServices) { + return null; + } + if ("hazelcast".equals(cacheSystem)) { + return "hazelcast-sdk"; + } + return cacheSystem; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ClientNamingV0.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ClientNamingV0.java new file mode 100644 index 0000000000..f7b310868d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ClientNamingV0.java @@ -0,0 +1,46 @@ +package datadog.trace.api.naming.v0; + +import androidx.annotation.NonNull; + +import datadog.trace.api.naming.NamingSchema; + +public class ClientNamingV0 implements NamingSchema.ForClient { + + @NonNull + @Override + public String operationForProtocol(@NonNull String protocol) { + final String postfix; + switch (protocol) { + case "grpc": + postfix = ".client"; + break; + case "rmi": + postfix = ".invoke"; + break; + default: + postfix = ".request"; + } + + return protocol + postfix; + } + + @NonNull + @Override + public String operationForComponent(@NonNull String component) { + switch (component) { + case "play-ws": + case "okhttp": + return component + ".request"; + case "netty-client": + return "netty.client.request"; + case "akka-http-client": + return "akka-http.client.request"; + case "pekko-http-client": + return "pekko-http.client.request"; + case "jax-rs.client": + return "jax-rs.client.call"; + default: + return "http.request"; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CloudNamingV0.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CloudNamingV0.java new file mode 100644 index 0000000000..e83c947bca --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CloudNamingV0.java @@ -0,0 +1,51 @@ +package datadog.trace.api.naming.v0; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import datadog.trace.api.naming.NamingSchema; + +public class CloudNamingV0 implements NamingSchema.ForCloud { + private final boolean allowInferredServices; + + public CloudNamingV0(boolean allowInferredServices) { + this.allowInferredServices = allowInferredServices; + } + + @NonNull + @Override + public String operationForRequest( + @NonNull final String provider, + @NonNull final String cloudService, + @NonNull final String qualifiedOperation) { + // only aws sdk is right now implemented + return "aws.http"; + } + + @Override + public String serviceForRequest( + @NonNull final String provider, @Nullable final String cloudService) { + if (!allowInferredServices) { + return null; + } + + // we only manage aws. Future switch for other cloud providers will be needed in the future + if (cloudService == null) { + return "java-aws-sdk"; + } + + switch (cloudService) { + case "sns": + case "sqs": + return cloudService; + default: + return "java-aws-sdk"; + } + } + + @NonNull + @Override + public String operationForFaas(@NonNull final String provider) { + return "dd-tracer-serverless-span"; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/DatabaseNamingV0.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/DatabaseNamingV0.java new file mode 100644 index 0000000000..2eb7f5571b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/DatabaseNamingV0.java @@ -0,0 +1,37 @@ +package datadog.trace.api.naming.v0; + +import androidx.annotation.NonNull; + +import datadog.trace.api.naming.NamingSchema; + +public class DatabaseNamingV0 implements NamingSchema.ForDatabase { + + private final boolean allowInferredServices; + + public DatabaseNamingV0(boolean allowInferredServices) { + this.allowInferredServices = allowInferredServices; + } + + @Override + public String normalizedName(@NonNull String rawName) { + return rawName; + } + + @NonNull + @Override + public String operation(@NonNull String databaseType) { + String postfix = ".query"; + if ("couchbase".equals(databaseType)) { + postfix = ".call"; + } + return databaseType + postfix; + } + + @Override + public String service(@NonNull String databaseType) { + if (allowInferredServices) { + return databaseType; + } + return null; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java new file mode 100644 index 0000000000..666735c7d6 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java @@ -0,0 +1,65 @@ +package datadog.trace.api.naming.v0; + +import androidx.annotation.NonNull; + +import datadog.trace.api.Config; +import datadog.trace.api.naming.NamingSchema; + +public class MessagingNamingV0 implements NamingSchema.ForMessaging { + private final boolean allowInferredServices; + + public MessagingNamingV0(final boolean allowInferredServices) { + this.allowInferredServices = allowInferredServices; + } + + @NonNull + @Override + public String outboundOperation(@NonNull final String messagingSystem) { + if ("amqp".equals(messagingSystem)) { + return "amqp.command"; + } + return messagingSystem + ".produce"; + } + + @Override + public String outboundService(@NonNull final String messagingSystem, boolean useLegacyTracing) { + return inboundService(messagingSystem, useLegacyTracing); + } + + @NonNull + @Override + public String inboundOperation(@NonNull final String messagingSystem) { + switch (messagingSystem) { + case "amqp": + return "amqp.command"; + case "sqs": + return "aws.http"; + default: + return messagingSystem + ".consume"; + } + } + + @Override + public String inboundService(@NonNull final String messagingSystem, boolean useLegacyTracing) { + if (allowInferredServices) { + return useLegacyTracing ? messagingSystem : Config.get().getServiceName(); + } else { + return null; + } + } + + @Override + @NonNull + public String timeInQueueService(@NonNull final String messagingSystem) { + return messagingSystem; + } + + @NonNull + @Override + public String timeInQueueOperation(@NonNull String messagingSystem) { + if ("sqs".equals(messagingSystem)) { + return "aws.http"; + } + return messagingSystem + ".deliver"; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/NamingSchemaV0.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/NamingSchemaV0.java new file mode 100644 index 0000000000..f36966115c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/NamingSchemaV0.java @@ -0,0 +1,63 @@ +package datadog.trace.api.naming.v0; + +import datadog.trace.api.Config; +import datadog.trace.api.naming.NamingSchema; +import datadog.trace.api.naming.v1.PeerServiceNamingV1; + +public class NamingSchemaV0 implements NamingSchema { + + private final boolean allowInferredServices = + !Config.get().isRemoveIntegrationServiceNamesEnabled(); + private final ForCache cacheNaming = new CacheNamingV0(allowInferredServices); + private final ForClient clientNaming = new ClientNamingV0(); + private final ForCloud cloudNaming = new CloudNamingV0(allowInferredServices); + private final ForDatabase databaseNaming = + new DatabaseNamingV0(allowInferredServices); + private final ForMessaging messagingNaming = + new MessagingNamingV0(allowInferredServices); + private final ForPeerService peerServiceNaming = + Config.get().isPeerServiceDefaultsEnabled() + ? new PeerServiceNamingV1(Config.get().getPeerServiceComponentOverrides()) + : new PeerServiceNamingV0(); + private final ForServer serverNaming = new ServerNamingV0(); + + @Override + public ForCache cache() { + return cacheNaming; + } + + @Override + public ForClient client() { + return clientNaming; + } + + @Override + public ForCloud cloud() { + return cloudNaming; + } + + @Override + public ForDatabase database() { + return databaseNaming; + } + + @Override + public ForMessaging messaging() { + return messagingNaming; + } + + @Override + public ForServer server() { + return serverNaming; + } + + @Override + public ForPeerService peerService() { + return peerServiceNaming; + } + + @Override + public boolean allowInferredServices() { + return allowInferredServices; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java new file mode 100644 index 0000000000..6120d713eb --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java @@ -0,0 +1,21 @@ +package datadog.trace.api.naming.v0; + +import androidx.annotation.NonNull; + +import java.util.Collections; +import java.util.Map; + +import datadog.trace.api.naming.NamingSchema; + +public class PeerServiceNamingV0 implements NamingSchema.ForPeerService { + @Override + public boolean supports() { + return false; + } + + @NonNull + @Override + public Map tags(@NonNull final Map unsafeTags) { + return Collections.emptyMap(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ServerNamingV0.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ServerNamingV0.java new file mode 100644 index 0000000000..f5f09b3405 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ServerNamingV0.java @@ -0,0 +1,51 @@ +package datadog.trace.api.naming.v0; + +import androidx.annotation.NonNull; + +import datadog.trace.api.naming.NamingSchema; + +public class ServerNamingV0 implements NamingSchema.ForServer { + @NonNull + @Override + public String operationForProtocol(@NonNull String protocol) { + if ("grpc".equals(protocol)) { + return "grpc.server"; + } + return protocol + ".request"; + } + + @NonNull + @Override + public String operationForComponent(@NonNull String component) { + final String prefix; + switch (component) { + case "undertow-http-server": + prefix = "undertow-http"; + break; + case "akka-http-server": + prefix = "akka-http"; + break; + case "pekko-http-server": + prefix = "pekko-http"; + break; + case "netty": + case "finatra": + case "axway-http": + prefix = component; + break; + case "spray-http-server": + prefix = "spray-http"; + break; + case "restlet-http-server": + prefix = "restlet-http"; + break; + case "synapse-server": + prefix = "synapse"; + break; + default: + prefix = "servlet"; + break; + } + return prefix + ".request"; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CacheNamingV1.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CacheNamingV1.java new file mode 100644 index 0000000000..48286d25d1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CacheNamingV1.java @@ -0,0 +1,18 @@ +package datadog.trace.api.naming.v1; + +import androidx.annotation.NonNull; + +import datadog.trace.api.naming.NamingSchema; + +public class CacheNamingV1 implements NamingSchema.ForCache { + @NonNull + @Override + public String operation(@NonNull String cacheSystem) { + return cacheSystem + ".command"; + } + + @Override + public String service(@NonNull String cacheSystem) { + return null; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ClientNamingV1.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ClientNamingV1.java new file mode 100644 index 0000000000..0617873e63 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ClientNamingV1.java @@ -0,0 +1,34 @@ +package datadog.trace.api.naming.v1; + +import androidx.annotation.NonNull; + +import datadog.trace.api.naming.NamingSchema; + +public class ClientNamingV1 implements NamingSchema.ForClient { + + @NonNull + private String normalizeProtocol(@NonNull final String protocol) { + switch (protocol) { + case "http": + case "https": + return "http"; + case "ftp": + case "ftps": + return "ftp"; + default: + return protocol; + } + } + + @NonNull + @Override + public String operationForProtocol(@NonNull String protocol) { + return normalizeProtocol(protocol) + ".client.request"; + } + + @NonNull + @Override + public String operationForComponent(@NonNull String component) { + return "http.client.request"; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CloudNamingV1.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CloudNamingV1.java new file mode 100644 index 0000000000..179a2c47ec --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CloudNamingV1.java @@ -0,0 +1,55 @@ +package datadog.trace.api.naming.v1; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.Locale; + +import datadog.trace.api.naming.NamingSchema; +import datadog.trace.api.naming.SpanNaming; +import datadog.trace.util.Strings; + +public class CloudNamingV1 implements NamingSchema.ForCloud { + @NonNull + @Override + public String operationForRequest( + @NonNull final String provider, + @NonNull final String cloudService, + @NonNull final String qualifiedOperation) { + // only aws sdk is right now implemented + switch (qualifiedOperation) { + // sdk 1.x format + case "SQS.SendMessage": + case "SQS.SendMessageBatch": + // sdk 2.x format + case "Sqs.SendMessage": + case "Sqs.SendMessageBatch": + return SpanNaming.instance().namingSchema().messaging().outboundOperation("sqs"); + + case "Sqs.ReceiveMessage": + case "SQS.ReceiveMessage": + return SpanNaming.instance().namingSchema().messaging().inboundOperation("sqs"); + case "Sns.Publish": + case "SNS.Publish": + return SpanNaming.instance().namingSchema().messaging().outboundOperation("sns"); + default: + final String lowercaseService = cloudService.toLowerCase(Locale.ROOT); + return Strings.join(".", provider, lowercaseService, "request"); // aws.s3.request + } + } + + @Override + public String serviceForRequest( + @NonNull final String provider, @Nullable final String cloudService) { + return null; + } + + @NonNull + @Override + public String operationForFaas(@NonNull final String provider) { + // for now only aws is implemented. For the future provider might be used to return specific + // function as a service name + // (e.g. azure automation) + return "aws.lambda.invoke"; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/DatabaseNamingV1.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/DatabaseNamingV1.java new file mode 100644 index 0000000000..c4591ffb15 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/DatabaseNamingV1.java @@ -0,0 +1,41 @@ +package datadog.trace.api.naming.v1; + +import androidx.annotation.NonNull; + +import datadog.trace.api.naming.NamingSchema; + +public class DatabaseNamingV1 implements NamingSchema.ForDatabase { + @Override + public String normalizedName(@NonNull String rawName) { + switch (rawName) { + case "mongo": + return "mongodb"; + case "sqlserver": + return "mssql"; + } + return rawName; + } + + @NonNull + @Override + public String operation(@NonNull String databaseType) { + final String prefix; + switch (databaseType) { + case "elasticsearch.rest": + prefix = "elasticsearch"; + break; + case "opensearch.rest": + prefix = "opensearch"; + break; + default: + prefix = databaseType; + } + // already normalized when calling dbType on the decorator. It saves one operation + return prefix + ".query"; + } + + @Override + public String service(@NonNull String databaseType) { + return null; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java new file mode 100644 index 0000000000..ff6ae39b80 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java @@ -0,0 +1,54 @@ +package datadog.trace.api.naming.v1; + +import androidx.annotation.NonNull; + +import datadog.trace.api.naming.NamingSchema; + +public class MessagingNamingV1 implements NamingSchema.ForMessaging { + + private String normalizeForCloud(@NonNull final String messagingSystem) { + switch (messagingSystem) { + case "sns": + case "sqs": + return "aws." + messagingSystem; + case "google-pubsub": + return "gcp.pubsub"; + default: + return messagingSystem; + } + } + + @NonNull + @Override + public String outboundOperation(@NonNull String messagingSystem) { + return normalizeForCloud(messagingSystem) + ".send"; + } + + @Override + public String outboundService(@NonNull String messagingSystem, boolean useLegacyTracing) { + return null; + } + + @NonNull + @Override + public String inboundOperation(@NonNull String messagingSystem) { + return normalizeForCloud(messagingSystem) + ".process"; + } + + @Override + public String inboundService(@NonNull String messagingSystem, boolean useLegacyTracing) { + return null; + } + + @Override + @NonNull + public String timeInQueueService(@NonNull String messagingSystem) { + return messagingSystem + "-queue"; + } + + @NonNull + @Override + public String timeInQueueOperation(@NonNull String messagingSystem) { + return normalizeForCloud(messagingSystem) + ".deliver"; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/NamingSchemaV1.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/NamingSchemaV1.java new file mode 100644 index 0000000000..9c961f60e4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/NamingSchemaV1.java @@ -0,0 +1,55 @@ +package datadog.trace.api.naming.v1; + +import datadog.trace.api.Config; +import datadog.trace.api.naming.NamingSchema; + +public class NamingSchemaV1 implements NamingSchema { + private final ForCache cacheNaming = new CacheNamingV1(); + private final ForClient clientNaming = new ClientNamingV1(); + private final ForCloud cloudNaming = new CloudNamingV1(); + private final ForDatabase databaseNaming = new DatabaseNamingV1(); + private final ForMessaging messagingNaming = new MessagingNamingV1(); + private final ForPeerService peerServiceNaming = + new PeerServiceNamingV1(Config.get().getPeerServiceComponentOverrides()); + private final ForServer serverNaming = new ServerNamingV1(); + + @Override + public ForCache cache() { + return cacheNaming; + } + + @Override + public ForClient client() { + return clientNaming; + } + + @Override + public ForCloud cloud() { + return cloudNaming; + } + + @Override + public ForDatabase database() { + return databaseNaming; + } + + @Override + public ForMessaging messaging() { + return messagingNaming; + } + + @Override + public ForPeerService peerService() { + return peerServiceNaming; + } + + @Override + public boolean allowInferredServices() { + return false; + } + + @Override + public ForServer server() { + return serverNaming; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java new file mode 100644 index 0000000000..5cd70f369c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java @@ -0,0 +1,113 @@ +package datadog.trace.api.naming.v1; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.HashMap; +import java.util.Map; + +import datadog.trace.api.DDTags; +import datadog.trace.api.naming.NamingSchema; +import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags; +import datadog.trace.bootstrap.instrumentation.api.Tags; + +public class PeerServiceNamingV1 implements NamingSchema.ForPeerService { + private static final Map SPECIFIC_PRECURSORS_BY_COMPONENT = + initPrecursorsByComponent(); + private static final String[] DEFAULT_PRECURSORS = {Tags.DB_INSTANCE, Tags.PEER_HOSTNAME}; + + private final Map overridesByComponent; + + private static Map initPrecursorsByComponent() { + final Map ret = new HashMap<>(7); + // messaging + ret.put("java-kafka", new String[] {InstrumentationTags.KAFKA_BOOTSTRAP_SERVERS}); + // database + ret.put("hazelcast-sdk", new String[] {"hazelcast.instance", Tags.PEER_HOSTNAME}); + ret.put( + "couchbase-client", + new String[] { + InstrumentationTags.COUCHBASE_SEED_NODES, "net.peer.name", Tags.PEER_HOSTNAME + }); + + ret.put( + "java-cassandra", + new String[] {InstrumentationTags.CASSANDRA_CONTACT_POINTS, Tags.PEER_HOSTNAME}); + // rpc + final String[] rpcPrecursors = {Tags.RPC_SERVICE, Tags.PEER_HOSTNAME}; + ret.put("grpc-client", rpcPrecursors); + ret.put("armeria-grpc-client", rpcPrecursors); + ret.put("rmi-client", rpcPrecursors); + + // for aws sdk we calculate eagerly to avoid doing too much complex lookups + // this will avoid calculating defaults + ret.put("java-aws-sdk", new String[] {}); + return ret; + } + + public PeerServiceNamingV1(@NonNull final Map overridesByComponent) { + this.overridesByComponent = overridesByComponent; + } + + @Override + public boolean supports() { + return true; + } + + private void resolve(@NonNull final Map unsafeTags) { + final Object component = unsafeTags.get(Tags.COMPONENT); + // avoid issues with UTF8ByteString or others + final String componentString = component == null ? null : component.toString(); + final String override = overridesByComponent.get(componentString); + // check if value can be overridden + if (override != null) { + set(unsafeTags, override, "_component_override"); + return; + } + // otherwise try to lookup by component specific precursor + if (resolveBy(unsafeTags, SPECIFIC_PRECURSORS_BY_COMPONENT.get(componentString))) { + return; + } + // finally fallback to default lookup + resolveBy(unsafeTags, DEFAULT_PRECURSORS); + } + + private boolean resolveBy( + @NonNull final Map unsafeTags, @Nullable final String[] precursors) { + if (precursors == null) { + return false; + } + Object value = null; + String source = null; + for (String precursor : precursors) { + value = unsafeTags.get(precursor); + if (value != null) { + // we have a match. Use the tag name for the source + source = precursor; + break; + } + } + // if something matched now set the value and the source + set(unsafeTags, value, source); + return true; + } + + private void set(@NonNull final Map unsafeTags, Object value, String source) { + if (value != null) { + unsafeTags.put(Tags.PEER_SERVICE, value); + unsafeTags.put(DDTags.PEER_SERVICE_SOURCE, source); + } + } + + @NonNull + @Override + public Map tags(@NonNull final Map unsafeTags) { + // check span.kind eligibility + final Object kind = unsafeTags.get(Tags.SPAN_KIND); + if (Tags.SPAN_KIND_CLIENT.equals(kind) || Tags.SPAN_KIND_PRODUCER.equals(kind)) { + // we can calculate the peer service now + resolve(unsafeTags); + } + return unsafeTags; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ServerNamingV1.java b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ServerNamingV1.java new file mode 100644 index 0000000000..3084be1f6e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ServerNamingV1.java @@ -0,0 +1,20 @@ +package datadog.trace.api.naming.v1; + +import androidx.annotation.NonNull; + +import datadog.trace.api.naming.NamingSchema; + +public class ServerNamingV1 implements NamingSchema.ForServer { + + @NonNull + @Override + public String operationForProtocol(@NonNull String protocol) { + return protocol + ".server.request"; + } + + @NonNull + @Override + public String operationForComponent(@NonNull String component) { + return "http.server.request"; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPathMatcher.java b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPathMatcher.java new file mode 100644 index 0000000000..f50dd62f30 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPathMatcher.java @@ -0,0 +1,351 @@ +package datadog.trace.api.normalize; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.StringTokenizer; + +/** + * PathMatcher implementation for Ant-style path patterns. Examples are provided below. + * + *

Part of this mapping code has been kindly borrowed from Apache Shiro and simplified for our use case. AntPathMatcher.java + * + *

The mapping matches URLs using the following rules:
+ * + *

    + *
  • ? matches one character + *
  • * matches zero or more characters + *
  • ** matches zero or more 'directories' in a path + *
+ * + *

Some examples:
+ * + *

    + *
  • com/t?st.jsp - matches com/test.jsp but also com/tast.jsp + * or com/txst.jsp + *
  • com/*.jsp - matches all .jsp files in the com + * directory + *
  • com/**/test.jsp - matches all test.jsp files underneath + * the com path + *
  • com/datadoghq/dd-trace-java/**/*.jsp - matches all .jsp + * files underneath the com/datadoghq/dd-trace-java path + *
  • com/**/servlet/bla.jsp - matches + * com/datadoghq/dd-trace-java/servlet/bla.jsp but also + * com/datadoghq/dd-trace-java/testing/servlet/bla.jsp and com/servlet/bla.jsp + * + *
+ */ +final class AntPathMatcher { + + AntPathMatcher() {} + + /** + * Checks if {@code path} is a pattern (i.e. contains a '*', or '?'). For example the {@code + * /foo/**} would return {@code true}, while {@code /bar/} would return {@code false}. + * + * @param path the string to check + * @return this method returns {@code true} if {@code path} contains a '*' or '?', otherwise, + * {@code false} + */ + public boolean isPattern(String path) { + return (path.indexOf('*') != -1 || path.indexOf('?') != -1); + } + + /** + * match the given path against the given pattern. + * + * @param pattern the pattern to match against + * @param path the path String to test + * @return true if the supplied path matched, false if it + * didn't + */ + public boolean match(String pattern, String path) { + String pathSeparator = "/"; + if (path == null || path.startsWith(pathSeparator) != pattern.startsWith(pathSeparator)) { + return false; + } + + String[] pattDirs = tokenizeToStringArray(pattern, pathSeparator); + String[] pathDirs = tokenizeToStringArray(path, pathSeparator); + + int pattIdxStart = 0; + int pattIdxEnd = pattDirs.length - 1; + int pathIdxStart = 0; + int pathIdxEnd = pathDirs.length - 1; + + // Match all elements up to the first ** + while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { + String patDir = pattDirs[pattIdxStart]; + if ("**".equals(patDir)) { + break; + } + if (!matchStrings(patDir, pathDirs[pathIdxStart])) { + return false; + } + pattIdxStart++; + pathIdxStart++; + } + + if (pathIdxStart > pathIdxEnd) { + // Path is exhausted, only match if rest of pattern is * or **'s + if (pattIdxStart > pattIdxEnd) { + return (pattern.endsWith(pathSeparator) == path.endsWith(pathSeparator)); + } + if (pattIdxStart == pattIdxEnd + && pattDirs[pattIdxStart].equals("*") + && path.endsWith(pathSeparator)) { + return true; + } + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + return true; + } else if (pattIdxStart > pattIdxEnd) { + // String not exhausted, but pattern is. Failure. + return false; + } + + // up to last '**' + while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { + String patDir = pattDirs[pattIdxEnd]; + if (patDir.equals("**")) { + break; + } + if (!matchStrings(patDir, pathDirs[pathIdxEnd])) { + return false; + } + pattIdxEnd--; + pathIdxEnd--; + } + if (pathIdxStart > pathIdxEnd) { + // String is exhausted + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + return true; + } + + while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) { + int patIdxTmp = -1; + for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) { + if (pattDirs[i].equals("**")) { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == pattIdxStart + 1) { + // '**/**' situation, so skip one + pattIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp - pattIdxStart - 1); + int strLength = (pathIdxEnd - pathIdxStart + 1); + int foundIdx = -1; + + strLoop: + for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + String subPat = pattDirs[pattIdxStart + j + 1]; + String subStr = pathDirs[pathIdxStart + i + j]; + if (!matchStrings(subPat, subStr)) { + continue strLoop; + } + } + foundIdx = pathIdxStart + i; + break; + } + + if (foundIdx == -1) { + return false; + } + + pattIdxStart = patIdxTmp; + pathIdxStart = foundIdx + patLength; + } + + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + + return true; + } + + /** + * Tests whether or not a string matches against a pattern. The pattern may contain two special + * characters:
+ * '*' means zero or more characters
+ * '?' means one and only one character + * + * @param pattern pattern to match against. Must not be null. + * @param str string which must be matched against the pattern. Must not be null. + * @return true if the string matches against the pattern, or false + * otherwise. + */ + private boolean matchStrings(String pattern, String str) { + char[] patArr = pattern.toCharArray(); + char[] strArr = str.toCharArray(); + int patIdxStart = 0; + int patIdxEnd = patArr.length - 1; + int strIdxStart = 0; + int strIdxEnd = strArr.length - 1; + char ch; + + boolean containsStar = false; + for (char aPatArr : patArr) { + if (aPatArr == '*') { + containsStar = true; + break; + } + } + + if (!containsStar) { + // No '*'s, so we make a shortcut + if (patIdxEnd != strIdxEnd) { + return false; // Pattern and string do not have the same size + } + for (int i = 0; i <= patIdxEnd; i++) { + ch = patArr[i]; + if (ch != '?') { + if (ch != strArr[i]) { + return false; // Character mismatch + } + } + } + return true; // String matches against pattern + } + + if (patIdxEnd == 0) { + return true; // Pattern contains only '*', which matches anything + } + + // Process characters before first star + while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) { + if (ch != '?') { + if (ch != strArr[strIdxStart]) { + return false; // Character mismatch + } + } + patIdxStart++; + strIdxStart++; + } + if (strIdxStart > strIdxEnd) { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + return true; + } + + // Process characters after last star + while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) { + if (ch != '?') { + if (ch != strArr[strIdxEnd]) { + return false; // Character mismatch + } + } + patIdxEnd--; + strIdxEnd--; + } + if (strIdxStart > strIdxEnd) { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + return true; + } + + // process pattern between stars. padIdxStart and patIdxEnd point + // always to a '*'. + while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { + int patIdxTmp = -1; + for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { + if (patArr[i] == '*') { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == patIdxStart + 1) { + // Two stars next to each other, skip the first one. + patIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp - patIdxStart - 1); + int strLength = (strIdxEnd - strIdxStart + 1); + int foundIdx = -1; + strLoop: + for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + ch = patArr[patIdxStart + j + 1]; + if (ch != '?') { + if (ch != strArr[strIdxStart + i + j]) { + continue strLoop; + } + } + } + + foundIdx = strIdxStart + i; + break; + } + + if (foundIdx == -1) { + return false; + } + + patIdxStart = patIdxTmp; + strIdxStart = foundIdx + patLength; + } + + // All characters in the string are used. Check if only '*'s are left + // in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + + return true; + } + + private static final String[] EMPTY_STRING_ARRAY = {}; + + private static String[] tokenizeToStringArray(String str, String delimiters) { + + if (str == null) { + return EMPTY_STRING_ARRAY; + } + + StringTokenizer st = new StringTokenizer(str, delimiters); + List tokens = new ArrayList<>(); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if (token.length() > 0) { + tokens.add(token); + } + } + return toStringArray(tokens); + } + + private static String[] toStringArray(Collection collection) { + return ((collection != null && !collection.isEmpty()) + ? collection.toArray(EMPTY_STRING_ARRAY) + : EMPTY_STRING_ARRAY); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java new file mode 100644 index 0000000000..436ce5c4ca --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java @@ -0,0 +1,64 @@ +package datadog.trace.api.normalize; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import datadog.trace.api.cache.DDCache; +import datadog.trace.api.cache.DDCaches; +import datadog.trace.bootstrap.instrumentation.api.URIUtils; + +final class AntPatternHttpPathNormalizer extends HttpPathNormalizer { + private static final Logger log = LoggerFactory.getLogger(AntPatternHttpPathNormalizer.class); + + /** Used to preserve original value as is when it's mapped to this value. */ + private static final String KEEP_AS_IS = "*"; + + private final Map resourceNameMatchers; + private final AntPathMatcher matcher = new AntPathMatcher(); + + private final DDCache cache = DDCaches.newFixedSizeCache(512); + private final Function cacheLoader = + new Function() { + @Override + public String apply(String path) { + for (Map.Entry resourceNameMatcher : resourceNameMatchers.entrySet()) { + if (matcher.match(resourceNameMatcher.getKey(), path)) { + if (KEEP_AS_IS.equals(resourceNameMatcher.getValue())) { + return path; + } + return resourceNameMatcher.getValue(); + } + } + return null; + } + }; + + AntPatternHttpPathNormalizer(Map httpResourceNameMatchers) { + resourceNameMatchers = httpResourceNameMatchers; + + // Clean up invalid patterns + List invalidPatterns = new ArrayList<>(httpResourceNameMatchers.keySet().size()); + for (String pattern : resourceNameMatchers.keySet()) { + if (!matcher.isPattern(pattern)) { + invalidPatterns.add(pattern); + } + } + for (String invalid : invalidPatterns) { + log.warn("Invalid pattern {} removed from matchers", invalid); + resourceNameMatchers.remove(invalid); + } + } + + @Override + public String normalize(String path, boolean encoded) { + if (encoded) { + path = URIUtils.decode(path); + } + return cache.computeIfAbsent(path, cacheLoader); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpPathNormalizer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpPathNormalizer.java new file mode 100644 index 0000000000..4496607d61 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpPathNormalizer.java @@ -0,0 +1,9 @@ +package datadog.trace.api.normalize; + +abstract class HttpPathNormalizer { + public final String normalize(String path) { + return normalize(path, false); + } + + public abstract String normalize(String path, boolean encoded); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpResourceNames.java b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpResourceNames.java new file mode 100644 index 0000000000..597a810a78 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpResourceNames.java @@ -0,0 +1,126 @@ +package datadog.trace.api.normalize; + +import java.util.function.Function; + +import datadog.trace.api.Config; +import datadog.trace.api.Pair; +import datadog.trace.api.cache.DDCache; +import datadog.trace.api.cache.DDCaches; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; + +public class HttpResourceNames { + public static final UTF8BytesString DEFAULT_RESOURCE_NAME = UTF8BytesString.create("/"); + + private static final Function, UTF8BytesString> JOINER = + input -> { + CharSequence path = input.getRight(); + if (path == null) { + return DEFAULT_RESOURCE_NAME; + } + StringBuilder sb; + CharSequence method = input.getLeft(); + if (method == null) { + sb = new StringBuilder(path.length()); + } else { + sb = new StringBuilder(path.length() + method.length() + 1); + sb.append(method); + // uppercase the method part of the resource name + for (int i = 0; i < sb.length(); i++) { + sb.setCharAt(i, Character.toUpperCase(sb.charAt(i))); + } + sb.append(' '); + } + int l = path.length() - 1; + if (instance().removeTrailingSlash && l > 0 && path.charAt(l) == '/') { + // remove trailing slash from the resource name path if needed + sb.append(path, 0, l); + } else { + sb.append(path); + } + return UTF8BytesString.create(sb); + }; + + private static final DDCache, CharSequence> JOINER_CACHE = + DDCaches.newFixedSizeCache(128); + + private static final SimpleHttpPathNormalizer simpleHttpPathNormalizer = + new SimpleHttpPathNormalizer(); + + // Not final for testing + private static HttpResourceNames INSTANCE; + + private final AntPatternHttpPathNormalizer serverAntPatternHttpPathNormalizer; + private final AntPatternHttpPathNormalizer clientAntPatternHttpPathNormalizer; + private final boolean removeTrailingSlash; + + private static HttpResourceNames instance() { + if (null == INSTANCE) { + INSTANCE = new HttpResourceNames(); + } + return INSTANCE; + } + + private HttpResourceNames() { + serverAntPatternHttpPathNormalizer = + new AntPatternHttpPathNormalizer(Config.get().getHttpServerPathResourceNameMapping()); + clientAntPatternHttpPathNormalizer = + new AntPatternHttpPathNormalizer(Config.get().getHttpClientPathResourceNameMapping()); + removeTrailingSlash = Config.get().getHttpResourceRemoveTrailingSlash(); + } + + public static AgentSpan setForServer( + AgentSpan span, CharSequence method, CharSequence path, boolean encoded) { + Pair result = computeForServer(method, path, encoded); + if (result.hasLeft()) { + span.setResourceName(result.getLeft(), result.getRight()); + } + + return span; + } + + public static Pair computeForServer( + CharSequence method, CharSequence path, boolean encoded) { + byte priority; + + String resourcePath = + instance().serverAntPatternHttpPathNormalizer.normalize(path.toString(), encoded); + if (resourcePath != null) { + priority = ResourceNamePriorities.HTTP_SERVER_CONFIG_PATTERN_MATCH; + } else { + resourcePath = simpleHttpPathNormalizer.normalize(path.toString(), encoded); + priority = ResourceNamePriorities.HTTP_PATH_NORMALIZER; + } + + return Pair.of(join(method, resourcePath), priority); + } + + public static Pair computeForClient( + CharSequence method, CharSequence path, boolean encoded) { + byte priority; + + String resourcePath = + instance().clientAntPatternHttpPathNormalizer.normalize(path.toString(), encoded); + if (resourcePath != null) { + priority = ResourceNamePriorities.HTTP_CLIENT_CONFIG_PATTERN_MATCH; + } else { + resourcePath = simpleHttpPathNormalizer.normalize(path.toString(), encoded); + priority = ResourceNamePriorities.HTTP_PATH_NORMALIZER; + } + return Pair.of(join(method, resourcePath), priority); + } + + public static AgentSpan setForClient( + AgentSpan span, CharSequence method, CharSequence path, boolean encoded) { + Pair result = computeForClient(method, path, encoded); + if (result.hasLeft()) { + span.setResourceName(result.getLeft(), result.getRight()); + } + return span; + } + + public static CharSequence join(CharSequence method, CharSequence path) { + return JOINER_CACHE.computeIfAbsent(Pair.of(method, path), JOINER); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SQLNormalizer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SQLNormalizer.java new file mode 100644 index 0000000000..a9e71e8292 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SQLNormalizer.java @@ -0,0 +1,124 @@ +package datadog.trace.api.normalize; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.BitSet; + +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; + +/** + * This class removes numbers and SQL literals from strings on a best-effort basis, producing UTF-8 + * encoded bytes. The aim is to remove as much information as possible, but only when it's cheap to + * do so. It makes no context-sensitive decisions, which works well for ANSI SQL, but, for example, + * will not remove literals in MySQL which are indistinguishable from object names. This is not an + * obfuscator, and the strings produced by this class must be passed through obfuscation in the + * trace agent. + */ +public final class SQLNormalizer { + + private static final Logger log = LoggerFactory.getLogger(SQLNormalizer.class); + + private static final BitSet NUMERIC_LITERAL_PREFIX = new BitSet(); + private static final BitSet SPLITTERS = new BitSet(); + + static { + for (byte symbol : + new byte[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+', '.'}) { + int unsigned = symbol & 0xFF; + NUMERIC_LITERAL_PREFIX.set(unsigned); + } + for (byte symbol : new byte[] {',', '(', ')', '|'}) { + int unsigned = symbol & 0xFF; + SPLITTERS.set(unsigned); + } + for (int i = 0; i < 256; ++i) { + if (Character.isWhitespace((char) i)) { + SPLITTERS.set(i); + } + } + } + + public static UTF8BytesString normalizeCharSequence(CharSequence sql) { + return normalize(sql.toString()); + } + + public static UTF8BytesString normalize(String sql) { + byte[] utf8 = sql.getBytes(UTF_8); + try { + BitSet splitters = findSplitterPositions(utf8); + int outputLength = utf8.length; + int end = outputLength; + int start = end > 0 ? splitters.previousSetBit(end - 1) : -1; + boolean modified = false; + // strip out anything ending with a quote (covers string and hex literals) + // or anything starting with a number, a quote, a decimal point, or a sign + while (end > 0 && start > 0) { + int sequenceStart = start + 1; + int sequenceEnd = end - 1; + if (sequenceEnd == sequenceStart) { + // single digit numbers can can be fixed in place + if (Character.isDigit(utf8[sequenceStart])) { + utf8[sequenceStart] = '?'; + modified = true; + } + } else if (sequenceStart < sequenceEnd) { + if (isQuoted(utf8, sequenceStart, sequenceEnd) + || isNumericLiteralPrefix(utf8, sequenceStart) + || isHexLiteralPrefix(utf8, sequenceStart, sequenceEnd)) { + int length = sequenceEnd - sequenceStart; + System.arraycopy(utf8, end, utf8, sequenceStart + 1, outputLength - end); + utf8[sequenceStart] = '?'; + outputLength -= length; + modified = true; + } + } + end = start; + start = splitters.previousSetBit(start - 1); + } + if (modified) { + return UTF8BytesString.create(Arrays.copyOf(utf8, outputLength)); + } + } catch (Throwable paranoid) { + log.debug("Error normalizing sql {}", sql, paranoid); + } + return UTF8BytesString.create(sql, utf8); + } + + private static boolean isQuoted(byte[] utf8, int start, int end) { + return (utf8[start] == '\'' && utf8[end] == '\''); + } + + private static boolean isHexLiteralPrefix(byte[] utf8, int start, int end) { + return (utf8[start] | ' ') == 'x' && start + 1 < end && utf8[start + 1] == '\''; + } + + private static boolean isNumericLiteralPrefix(byte[] utf8, int start) { + return NUMERIC_LITERAL_PREFIX.get(utf8[start] & 0xFF) + // preserve single line comment (--) prefixes + && !(utf8[start + 1] == '-' && utf8[start] == '-'); + } + + private static boolean isSplitter(byte symbol) { + return SPLITTERS.get(symbol & 0xFF); + } + + private static BitSet findSplitterPositions(byte[] utf8) { + BitSet positions = new BitSet(utf8.length); + boolean quoted = false; + boolean escaped = false; + for (int i = 0; i < utf8.length; ++i) { + byte b = utf8[i]; + if (b == '\'' && !escaped) { + quoted = !quoted; + } else { + escaped = (b == '\\') & !escaped; + positions.set(i, !quoted & isSplitter(b)); + } + } + return positions; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java new file mode 100644 index 0000000000..d4857986eb --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java @@ -0,0 +1,91 @@ +package datadog.trace.api.normalize; + +import datadog.trace.api.Config; + +// public because this is used in the testing module but groovy accesses it through Class.forName +// which is banned +public final class SimpleHttpPathNormalizer extends HttpPathNormalizer { + // package private so things outside groovy for tests can't create an instance + SimpleHttpPathNormalizer() {} + + @Override + public String normalize(String path, boolean encoded) { + if (null == path || path.isEmpty()) { + return "/"; + } + final boolean preserveSpaces = + !encoded && Config.get().isHttpServerDecodedResourcePreserveSpaces(); + StringBuilder sb = null; + int inEncoding = 0; + for (int i = 0; i < path.length(); ) { + int nextSlash = path.indexOf('/', i); + if (nextSlash != i) { + int endOfSegment = nextSlash == -1 ? path.length() : nextSlash; + // detect version identifiers + int segmentLength = (endOfSegment - i); + if ((segmentLength <= 3 && segmentLength > 1 && (path.charAt(i) | ' ') == 'v')) { + boolean numeric = true; + for (int j = i + 1; j < endOfSegment; ++j) { + numeric &= isDigit(path.charAt(j)); + } + if (numeric) { + if (sb != null) { + sb.append(path, i, endOfSegment); + } + } else { + sb = ensureStringBuilder(sb, path, i); + sb.append('?'); + } + } else { + int snapshot = sb != null ? sb.length() : i; + boolean numeric = false; + for (int j = i; j < endOfSegment && !numeric; ++j) { + final char c = path.charAt(j); + if (encoded && c == '%') { + inEncoding = 3; + } + inEncoding--; + numeric = inEncoding < 0 && isDigit(c); + if (!numeric) { + if (Character.isWhitespace(c)) { + sb = ensureStringBuilder(sb, path, j); + if (preserveSpaces && sb.length() > 0) { + sb.append(c); + } + } else if (sb != null) { + sb.append(c); + } + } + } + if (numeric) { + sb = ensureStringBuilder(sb, path, snapshot); + sb.setLength(snapshot); + sb.append('?'); + } + } + i = endOfSegment + 1; + } else { + ++i; + } + if (nextSlash != -1) { + if (sb != null) { + sb.append('/'); + } + } + } + return sb == null ? path : sb.length() == 0 ? "/" : sb.toString(); + } + + private static boolean isDigit(char c) { + return c <= '9' && c >= '0'; + } + + private static StringBuilder ensureStringBuilder(StringBuilder sb, String path, int position) { + if (sb == null) { + sb = new StringBuilder(); + sb.append(path, 0, position); + } + + return sb; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java new file mode 100644 index 0000000000..4d711a3c69 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java @@ -0,0 +1,4 @@ +package datadog.trace.api.profiling; + +/** A generic interface for observable types served by {@linkplain ProfilingListenersRegistry} */ +public interface ObservableType {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Profiling.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Profiling.java new file mode 100644 index 0000000000..f4ee47c4b2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Profiling.java @@ -0,0 +1,41 @@ +package datadog.trace.api.profiling; + +import datadog.trace.api.GlobalTracer; +import datadog.trace.api.Tracer; +import datadog.trace.api.internal.InternalTracer; + +public interface Profiling { + + static Profiling get() { + Tracer tracer = GlobalTracer.get(); + if (tracer instanceof InternalTracer) { + return ((InternalTracer) tracer).getProfilingContext(); + } + return NoOp.INSTANCE; + } + + /** + * Stateful API which restores the previous context when closed. This requires more memory so has + * higher overhead than the stateless API. + * + * @return a profiling scope which can be closed to restore the current state. + */ + default ProfilingScope newScope() { + return ProfilingScope.NO_OP; + } + + /** + * Creates a decorator for the attribute, which can be used to set and clear contexts slightly + * more efficiently than with string attributes. + * + * @param attribute the name of the attribute + * @return a setter which can be used to set and clear profiling context + */ + default ProfilingContextAttribute createContextAttribute(String attribute) { + return ProfilingContextAttribute.NoOp.INSTANCE; + } + + final class NoOp implements Profiling { + public static final NoOp INSTANCE = new NoOp(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContext.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContext.java new file mode 100644 index 0000000000..2d1f72b9a4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContext.java @@ -0,0 +1,38 @@ +package datadog.trace.api.profiling; + +public interface ProfilingContext { + + /** + * Sets a context value to be appended to profiling data + * + * @param attribute the attribute (must have been registered at startup) + * @param value the value + */ + default void setContextValue(String attribute, String value) {} + + /** + * Sets a context value to be appended to profiling data. This overload requires an attribute to + * have been obtained by calling {@link Profiling#createContextAttribute(String) + * createContextAttribute} first, but is more efficient. + * + * @param attribute the attribute (must have been registered at startup) + * @param value the value + */ + default void setContextValue(ProfilingContextAttribute attribute, String value) {} + + /** + * Clears a context value. + * + * @param attribute the attribute (must have been registered at startup) + */ + default void clearContextValue(String attribute) {} + + /** + * Clears a context value. This overload requires an attribute to have been obtained by calling + * {@link Profiling#createContextAttribute(String) createContextAttribute} first, but is more + * efficient. + * + * @param attribute the attribute (must have been registered at startup) + */ + default void clearContextValue(ProfilingContextAttribute attribute) {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContextAttribute.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContextAttribute.java new file mode 100644 index 0000000000..9dcf909e48 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContextAttribute.java @@ -0,0 +1,9 @@ +package datadog.trace.api.profiling; + +public interface ProfilingContextAttribute { + + final class NoOp implements ProfilingContextAttribute { + + public static final NoOp INSTANCE = new NoOp(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListener.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListener.java new file mode 100644 index 0000000000..423479d699 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListener.java @@ -0,0 +1,10 @@ +package datadog.trace.api.profiling; + +/** + * A simple generified listener/observer type + * + * @param the observed data type + */ +public interface ProfilingListener { + void onData(Type observable); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListeners.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListeners.java new file mode 100644 index 0000000000..1e75ead09b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListeners.java @@ -0,0 +1,44 @@ +package datadog.trace.api.profiling; + +import java.util.Collection; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * A listener host. Allows registering listeners and firing 'on-data' events + * + * @param the observable type + */ +public final class ProfilingListeners { + private final Collection> listeners = new ConcurrentLinkedQueue<>(); + + ProfilingListeners() {} + + /** + * Notify all listeners about the data + * + * @param data the observed data + */ + public void fireOnData(Type data) { + for (ProfilingListener listener : listeners) { + listener.onData(data); + } + } + + /** + * Add a listener + * + * @param listener listener instance + */ + public void addListener(ProfilingListener listener) { + listeners.add(listener); + } + + /** + * Remove a listener + * + * @param listener listener instance + */ + public void removeListener(ProfilingListener listener) { + listeners.remove(listener); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListenersRegistry.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListenersRegistry.java new file mode 100644 index 0000000000..b35efde106 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListenersRegistry.java @@ -0,0 +1,28 @@ +package datadog.trace.api.profiling; + +/** + * A {@linkplain ProfilingListeners} registry. Allows retrieving a specific {@linkplain + * ProfilingListeners} instance for the given observable type. + */ +public final class ProfilingListenersRegistry { + private static final ClassValue> listenersPerType = + new ClassValue>() { + @Override + protected ProfilingListeners computeValue(Class type) { + return new ProfilingListeners<>(); + } + }; + + private ProfilingListenersRegistry() {} + + /** + * Retrieve the {@Profiling} + * + * @param type + * @param + * @return + */ + public static ProfilingListeners getHost(Class type) { + return (ProfilingListeners) listenersPerType.get(type); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingScope.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingScope.java new file mode 100644 index 0000000000..182cbe09ec --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingScope.java @@ -0,0 +1,9 @@ +package datadog.trace.api.profiling; + +public interface ProfilingScope extends AutoCloseable, ProfilingContext { + + ProfilingScope NO_OP = () -> {}; + + @Override + void close(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingSnapshot.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingSnapshot.java new file mode 100644 index 0000000000..21eca45267 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingSnapshot.java @@ -0,0 +1,8 @@ +package datadog.trace.api.profiling; + +public interface ProfilingSnapshot extends ObservableType { + enum Kind { + PERIODIC, + ON_SHUTDOWN + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/QueueTiming.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/QueueTiming.java new file mode 100644 index 0000000000..082f5a8be9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/QueueTiming.java @@ -0,0 +1,8 @@ +package datadog.trace.api.profiling; + +public interface QueueTiming extends Timing { + + void setTask(Object task); + + void setScheduler(Class scheduler); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingData.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingData.java new file mode 100644 index 0000000000..cce87e03b9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingData.java @@ -0,0 +1,97 @@ +/* + * Copyright 2019 Datadog + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package datadog.trace.api.profiling; + +import androidx.annotation.NonNull; + +import java.io.IOException; +import java.time.Instant; + +/** Platform-agnostic API for operations required when retrieving data using the ProfilingSystem. */ +public abstract class RecordingData implements ProfilingSnapshot { + protected final Instant start; + protected final Instant end; + protected final Kind kind; + + public RecordingData(final Instant start, final Instant end, Kind kind) { + this.start = start; + this.end = end; + this.kind = kind; + } + + /** + * @return the data stream if it contains any data. + * @throws IOException if the stream to return is empty or another IO-related problem occurred. + */ + @NonNull + public abstract RecordingInputStream getStream() throws IOException; + + /** + * Releases the resources associated with the recording, for example the underlying file. + * + *

Forgetting to releasing this when done streaming, will lead to one or more of the following: + * + *

    + *
  • Memory leak + *
  • File leak + *
+ * + *

Please don't forget to call release when done streaming... + */ + public abstract void release(); + + /** + * Returns the name of the recording from which the data is originating. + * + * @return the name of the recording from which the data is originating. + */ + @NonNull + public abstract String getName(); + + /** + * Returns the requested start time for the recording. + * + *

Note that this doesn't necessarily have to match the time for the actual data recorded. + * + * @return the requested start time. + */ + @NonNull + public final Instant getStart() { + return start; + } + + /** + * Returns the requested end time for the recording. + * + *

Note that this doesn't necessarily have to match the time for the actual data recorded. + * + * @return the requested end time. + */ + @NonNull + public final Instant getEnd() { + return end; + } + + @NonNull + public final Kind getKind() { + return kind; + } + + @Override + public final String toString() { + return "name=" + getName() + ", kind=" + getKind(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingDataListener.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingDataListener.java new file mode 100644 index 0000000000..29a5e4951b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingDataListener.java @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Datadog + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package datadog.trace.api.profiling; + +/** Listener for getting notified when new recording data is becoming available. */ +public interface RecordingDataListener { + /** + * Called when new recording data becomes available. Handle quickly, e.g. typically schedule + * streaming of the new available data in another thread. Do not forget to {@link + * RecordingData#release()} when the data has been uploaded. + * + * @param type type of the recording + * @param data the new data available + * @param handleSynchronously whether to handle the data synchronously + */ + void onNewData(RecordingType type, RecordingData data, boolean handleSynchronously); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingInputStream.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingInputStream.java new file mode 100644 index 0000000000..0549635a02 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingInputStream.java @@ -0,0 +1,34 @@ +package datadog.trace.api.profiling; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class RecordingInputStream extends BufferedInputStream { + public RecordingInputStream(InputStream in) { + super(in); + } + + /** + * Checks whether the recording input stream does not contain any data + * + * @return {@literal true} if the input data stream is empty + * @throws IOException + */ + public boolean isEmpty() throws IOException { + // if 'pos' is non-zero the stream is definitely not empty + if (pos == 0) { + try { + // store the current position (which should be 0) + mark(1); + // and try reading the next byte - if it fails the stream is empty + return read() == -1; + } finally { + // restore the stream back to the stored position so it can be properly processed if not + // empty + reset(); + } + } + return false; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingType.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingType.java new file mode 100644 index 0000000000..639ccc3955 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingType.java @@ -0,0 +1,15 @@ +package datadog.trace.api.profiling; + +public enum RecordingType { + CONTINUOUS("continuous"); + + private final String name; + + RecordingType(final String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timer.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timer.java new file mode 100644 index 0000000000..991fc832e7 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timer.java @@ -0,0 +1,20 @@ +package datadog.trace.api.profiling; + +public interface Timer { + + enum TimerType { + QUEUEING + } + + Timing start(TimerType type); + + final class NoOp implements Timer { + + public static final Timer INSTANCE = new NoOp(); + + @Override + public Timing start(TimerType type) { + return Timing.NoOp.INSTANCE; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timing.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timing.java new file mode 100644 index 0000000000..99aa1913db --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timing.java @@ -0,0 +1,19 @@ +package datadog.trace.api.profiling; + +public interface Timing extends AutoCloseable { + @Override + void close(); + + class NoOp implements Timing, QueueTiming { + public static final Timing INSTANCE = new NoOp(); + + @Override + public void close() {} + + @Override + public void setTask(Object task) {} + + @Override + public void setScheduler(Class scheduler) {} + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/TransientProfilingContextHolder.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/TransientProfilingContextHolder.java new file mode 100644 index 0000000000..ad24b678c0 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/TransientProfilingContextHolder.java @@ -0,0 +1,3 @@ +package datadog.trace.api.profiling; + +public interface TransientProfilingContextHolder {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/package-info.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/package-info.java new file mode 100644 index 0000000000..75028b334f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/package-info.java @@ -0,0 +1,6 @@ +package datadog.trace.api.profiling; + +/** + * This is the communication point between the tracer and profiler. The classes from this package + * are available to both subsystems and can be used when synchronization between them is required. + */ diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/AdaptiveSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/AdaptiveSampler.java new file mode 100644 index 0000000000..09d8f78801 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/AdaptiveSampler.java @@ -0,0 +1,317 @@ +package datadog.trace.api.sampling; + +import androidx.annotation.Nullable; + +import java.time.Duration; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.LongAdder; + +import datadog.trace.util.AgentTaskScheduler; +import datadog.trace.util.AgentTaskScheduler.Task; + +/** + * An adaptive streaming (non-remembering) sampler. + * + *

The sampler attempts to generate at most N samples per fixed time window in randomized + * fashion. For this it divides the timeline into 'sampling windows' of constant duration. Each + * sampling window targets a constant number of samples which are scattered randomly (uniform + * distribution) throughout the window duration and once the window is over the real stats of + * incoming events and the number of gathered samples is used to recompute the target probability to + * use in the following window. + * + *

This will guarantee, if the windows are not excessively large, that the sampler will be able + * to adjust to the changes in the rate of incoming events. + * + *

However, there might so rapid changes in incoming events rate that we will optimistically use + * all allowed samples well before the current window has elapsed or, on the other end of the + * spectrum, there will be to few incoming events and the sampler will not be able to generate the + * target number of samples. + * + *

To smooth out these hiccups the sampler maintains an under-sampling budget which can be used + * to compensate for too rapid changes in the incoming events rate and maintain the target average + * number of samples per window. + */ +public class AdaptiveSampler implements Sampler { + + private static final class Counts { + private final LongAdder testCount = new LongAdder(); + private static final AtomicLongFieldUpdater SAMPLE_COUNT = + AtomicLongFieldUpdater.newUpdater(Counts.class, "sampleCount"); + private volatile long sampleCount = 0L; + + void addTest() { + testCount.increment(); + } + + boolean addSample(final long limit) { + return SAMPLE_COUNT.getAndAccumulate(this, limit, (prev, lim) -> Math.min(prev + 1, lim)) + < limit; + } + + void addSample() { + SAMPLE_COUNT.incrementAndGet(this); + } + + void reset() { + testCount.reset(); + SAMPLE_COUNT.set(this, 0); + } + + long sampleCount() { + return SAMPLE_COUNT.get(this); + } + + long testCount() { + return testCount.sum(); + } + } + + @FunctionalInterface + public interface ConfigListener { + void onWindowRoll( + long totalCount, long sampledCount, long budget, double totalAverage, double probability); + } + + /* + * Exponential Moving Average (EMA) last element weight. + * Check out papers about using EMA for streaming data - eg. + * https://nestedsoftware.com/2018/04/04/exponential-moving-average-on-streaming-data-4hhl.24876.html + * + * Corresponds to 'lookback' of N values: + * With T being the index of the most recent value the lookback of N values means that for all values with index + * T-K, where K > N, the relative weight of that value computed as (1 - alpha)^K is less or equal than the + * weight assigned by a plain arithmetic average (= 1/N). + */ + private final double emaAlpha; + private final int samplesPerWindow; + + private final AtomicReference countsRef; + + // these attributes need to be volatile since they are accessed from user threds as well as the + // maintenance one + private volatile double probability = 1d; + private volatile long samplesBudget; + + // these attributes are accessed solely from the window maintenance thread + private double totalCountRunningAverage = 0d; + private double avgSamples; + + private final int budgetLookback; + private final double budgetAlpha; + + // accessed exclusively from the window maintenance task - does not require any synchronization + private int countsSlotIdx = 0; + private final Counts[] countsSlots = new Counts[] {new Counts(), new Counts()}; + + private final ConfigListener listener; + + private final Duration windowDuration; + private final AgentTaskScheduler taskScheduler; + + /** + * Create a new sampler instance + * + * @param windowDuration the sampling window duration + * @param samplesPerWindow the maximum number of samples in the sampling window + * @param averageLookback the number of windows to consider in averaging the sampling rate + * @param budgetLookback the number of windows to consider when computing the sampling budget + * @param listener an optional listener receiving the sampler config changes + * @param taskScheduler agent task scheduler to use for periodic rolls + */ + protected AdaptiveSampler( + final Duration windowDuration, + final int samplesPerWindow, + final int averageLookback, + final int budgetLookback, + final @Nullable ConfigListener listener, + final AgentTaskScheduler taskScheduler, + boolean startSampler) { + + if (averageLookback < 1) { + throw new IllegalArgumentException("'averageLookback' argument must be at least 1"); + } + if (budgetLookback < 1) { + throw new IllegalArgumentException("'budgetLookback' argument must be at least 1"); + } + this.samplesPerWindow = samplesPerWindow; + this.budgetLookback = budgetLookback; + samplesBudget = samplesPerWindow + (long) budgetLookback * samplesPerWindow; + emaAlpha = computeIntervalAlpha(averageLookback); + budgetAlpha = computeIntervalAlpha(budgetLookback); + countsRef = new AtomicReference<>(countsSlots[0]); + this.listener = listener; + if (listener != null) { + listener.onWindowRoll(0, 0, samplesBudget, totalCountRunningAverage, probability); + } + + this.windowDuration = windowDuration; + this.taskScheduler = taskScheduler; + + if (startSampler) { + start(); + } + } + + /** + * Create a new sampler instance with automatic window roll. + * + * @param windowDuration the sampling window duration + * @param samplesPerWindow the maximum number of samples in the sampling window + * @param averageLookback the number of windows to consider in averaging the sampling rate + * @param budgetLookback the number of windows to consider when computing the sampling budget + */ + public AdaptiveSampler( + final Duration windowDuration, + final int samplesPerWindow, + final int averageLookback, + final int budgetLookback, + boolean startSampler) { + this( + windowDuration, + samplesPerWindow, + averageLookback, + budgetLookback, + null, + AgentTaskScheduler.INSTANCE, + startSampler); + } + + /** + * Create a new sampler instance with automatic window roll. The instance is automatically + * started. + * + * @param windowDuration the sampling window duration + * @param samplesPerWindow the maximum number of samples in the sampling window + * @param averageLookback the number of windows to consider in averaging the sampling rate + * @param budgetLookback the number of windows to consider when computing the sampling budget + * @param listener an optional listener receiving the sampler config changes + */ + public AdaptiveSampler( + final Duration windowDuration, + final int samplesPerWindow, + final int averageLookback, + final int budgetLookback, + final ConfigListener listener) { + this( + windowDuration, + samplesPerWindow, + averageLookback, + budgetLookback, + listener, + AgentTaskScheduler.INSTANCE, + true); + } + + public void start() { + taskScheduler.weakScheduleAtFixedRate( + RollWindowTask.INSTANCE, + this, + windowDuration.toNanos(), + windowDuration.toNanos(), + TimeUnit.NANOSECONDS); + } + + @Override + public boolean sample() { + final Counts counts = countsRef.get(); + counts.addTest(); + if (ThreadLocalRandom.current().nextDouble() < probability) { + return counts.addSample(samplesBudget); + } + + return false; + } + + @Override + public boolean keep() { + final Counts counts = countsRef.get(); + counts.addTest(); + counts.addSample(); + return true; + } + + @Override + public boolean drop() { + final Counts counts = countsRef.get(); + counts.addTest(); + return false; + } + + private void rollWindow() { + + final Counts counts = countsSlots[countsSlotIdx]; + try { + /* + * Semi-atomically replace the Counts instance such that sample requests during window maintenance will be + * using the newly created counts instead of the ones currently processed by the maintenance routine. + * We are ok with slightly racy outcome where totaCount and sampledCount may not be totally in sync + * because it allows to avoid contention in the hot-path and the effect on the overall sample rate is minimal + * and will get compensated in the long run. + * Theoretically, a compensating system might be devised but it will always require introducing a single point + * of contention and add a fair amount of complexity. Considering that we are ok with keeping the target sampling + * rate within certain error margins and this data race is not breaking the margin it is better to keep the + * code simple and reasonably fast. + */ + countsSlotIdx = (countsSlotIdx++) % 2; + countsRef.set(countsSlots[countsSlotIdx]); + final long totalCount = counts.testCount(); + final long sampledCount = counts.sampleCount(); + + samplesBudget = calculateBudgetEma(sampledCount); + + if (totalCountRunningAverage == 0 || emaAlpha <= 0.0d) { + totalCountRunningAverage = totalCount; + } else { + totalCountRunningAverage = + totalCountRunningAverage + emaAlpha * (totalCount - totalCountRunningAverage); + } + + if (totalCountRunningAverage <= 0) { + probability = 1; + } else { + probability = Math.min(samplesBudget / totalCountRunningAverage, 1d); + } + if (listener != null) { + listener.onWindowRoll( + totalCount, sampledCount, samplesBudget, totalCountRunningAverage, probability); + } + } finally { + // Reset the previous counts slot + counts.reset(); + } + } + + private long calculateBudgetEma(final long sampledCount) { + avgSamples = + Double.isNaN(avgSamples) || budgetAlpha <= 0.0d + ? sampledCount + : avgSamples + budgetAlpha * (sampledCount - avgSamples); + return Math.round(Math.max(samplesPerWindow - avgSamples, 0) * budgetLookback); + } + + private static double computeIntervalAlpha(final int lookback) { + return 1 - Math.pow(lookback, -1d / lookback); + } + + private static class RollWindowTask implements Task { + + static final RollWindowTask INSTANCE = new RollWindowTask(); + + @Override + public void run(final AdaptiveSampler target) { + target.rollWindow(); + } + } + + // access for tests + long testCount() { + return countsRef.get().testCount(); + } + + long sampleCount() { + return countsRef.get().sampleCount(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/ConstantSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/ConstantSampler.java new file mode 100644 index 0000000000..e0fb334f63 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/ConstantSampler.java @@ -0,0 +1,25 @@ +package datadog.trace.api.sampling; + +public class ConstantSampler implements Sampler { + + private final boolean constant; + + public ConstantSampler(boolean constant) { + this.constant = constant; + } + + @Override + public boolean sample() { + return constant; + } + + @Override + public boolean keep() { + return true; + } + + @Override + public boolean drop() { + return false; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/PrioritySampling.java b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/PrioritySampling.java new file mode 100644 index 0000000000..4aeda33362 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/PrioritySampling.java @@ -0,0 +1,20 @@ +package datadog.trace.api.sampling; + +public class PrioritySampling { + /** + * Implementation detail of the client. will not be sent to the agent or propagated. + * + *

Internal value used when the priority sampling flag has not been set on the span context. + */ + public static final byte UNSET = (byte) 0x80; + /** The sampler has decided to drop the trace. */ + public static final byte SAMPLER_DROP = 0; + /** The sampler has decided to keep the trace. */ + public static final byte SAMPLER_KEEP = 1; + /** The user has decided to drop the trace. */ + public static final byte USER_DROP = -1; + /** The user has decided to keep the trace. */ + public static final byte USER_KEEP = 2; + + private PrioritySampling() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/Sampler.java b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/Sampler.java new file mode 100644 index 0000000000..032f545402 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/Sampler.java @@ -0,0 +1,25 @@ +package datadog.trace.api.sampling; + +public interface Sampler { + + /** + * Provides binary answer whether the current event is to be sampled + * + * @return {@literal true} if the event should be sampled + */ + boolean sample(); + + /** + * Force the sampling decision to keep this item + * + * @return always {@literal true} + */ + boolean keep(); + + /** + * Force the sampling decision to drop this item + * + * @return always {@literal false} + */ + boolean drop(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingMechanism.java b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingMechanism.java new file mode 100644 index 0000000000..93cb32307d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingMechanism.java @@ -0,0 +1,58 @@ +package datadog.trace.api.sampling; + +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; +import static datadog.trace.api.sampling.PrioritySampling.USER_DROP; +import static datadog.trace.api.sampling.PrioritySampling.USER_KEEP; + +public class SamplingMechanism { + /** Not encouraged to use */ + public static final byte UNKNOWN = -1; + /** Used before the tracer receives any rates from agent and there are no rules configured */ + public static final byte DEFAULT = 0; + /** The sampling rate received in the agent's http response */ + public static final byte AGENT_RATE = 1; + /** Auto; reserved for future use */ + public static final byte REMOTE_AUTO_RATE = 2; + /** Sampling rule or sampling rate based on tracer config */ + public static final byte RULE = 3; + /** User directly sets sampling priority via code using span.SetTag(ManualKeep) or similar API */ + public static final byte MANUAL = 4; + /** AppSec */ + public static final byte APPSEC = 5; + /** User-defined target; reserved for future use */ + public static final byte REMOTE_USER_RATE = 6; + /** Span Sampling Rate (single span sampled on account of a span sampling rule) */ + public static final byte SPAN_SAMPLING_RATE = 8; + /** Data Jobs */ + public static final byte DATA_JOBS = 10; + /** Force override sampling decision from external source, like W3C traceparent. */ + public static final byte EXTERNAL_OVERRIDE = Byte.MIN_VALUE; + + public static boolean validateWithSamplingPriority(int mechanism, int priority) { + switch (mechanism) { + case UNKNOWN: + return true; + + case DEFAULT: + case AGENT_RATE: + case REMOTE_AUTO_RATE: + return priority == SAMPLER_DROP || priority == SAMPLER_KEEP; + + case RULE: + case MANUAL: + case REMOTE_USER_RATE: + return priority == USER_DROP || priority == USER_KEEP; + + case APPSEC: + case DATA_JOBS: + return priority == PrioritySampling.USER_KEEP; + + case EXTERNAL_OVERRIDE: + return false; + } + return true; + } + + private SamplingMechanism() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingRule.java b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingRule.java new file mode 100644 index 0000000000..3bb8ba2d9a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingRule.java @@ -0,0 +1,65 @@ +package datadog.trace.api.sampling; + +import java.util.Map; + +/** This interface describes the criteria for a sampling rule. */ +public interface SamplingRule { + static String normalizeGlob(String name) { + return name == null || MATCH_ALL.equals(name) ? MATCH_ALL : name; + } + + /** The "match all" glob pattern . */ + String MATCH_ALL = "*"; + + /** + * Gets the glob pattern the span service must match to validate the rule. + * + * @return The glob pattern the span service must match. + */ + String getService(); + + /** + * Gets the glob pattern the span name must match to validate the rule. + * + * @return The glob pattern the span name must match. + */ + String getName(); + + /** + * Gets the glob pattern the span resource must match to validate the rule. + * + * @return The glob pattern the span resource must match. + */ + String getResource(); + + /** + * Gets the collection of all (tag name, glob pattern) pairs that span tags must match to validate + * the rules. If the collection is empty, the rule will be validated. If the collection has + * entries, each key must exactly match a span tag name, and its associated glob pattern must + * match the span tag value. + * + * @return The collection of all (tag name, glob pattern) pairs that span tags must match. + */ + Map getTags(); + + /** + * Gets the probability of keeping (sampling) the element matching the rule. + * + * @return The probability of sampling the element matching the rule, between {@code 0.0} and + * {@code 1.0}. + */ + double getSampleRate(); + + /** This interface describes the criteria of a sampling rule that can match against a trace. */ + interface TraceSamplingRule extends SamplingRule {} + + /** This interface describes the criteria of a sampling rule that can match against a span. */ + interface SpanSamplingRule extends SamplingRule { + /** + * Gets the limit applied to the rule, using a token bucket limiter. + * + * @return The limit applied to the rule, {@link Integer#MAX_VALUE} if no limit. + */ + int getMaxPerSecond(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ExtendedScopeListener.java b/features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ExtendedScopeListener.java new file mode 100644 index 0000000000..239fc4eba7 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ExtendedScopeListener.java @@ -0,0 +1,13 @@ +package datadog.trace.api.scopemanager; + +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; + +public interface ExtendedScopeListener extends ScopeListener { + void afterScopeActivated( + DDTraceId traceId, long localRootSpanId, long spanId, TraceConfig traceConfig); + + /** Called just after a scope is closed. */ + @Override + void afterScopeClosed(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ScopeListener.java b/features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ScopeListener.java new file mode 100644 index 0000000000..3c55c67ef3 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ScopeListener.java @@ -0,0 +1,15 @@ +package datadog.trace.api.scopemanager; + +/** Hooks for scope activation */ +public interface ScopeListener { + /** + * Called just after a scope becomes the active scope + * + *

May be called multiple times. When a scope is initially created, or after a child scope is + * deactivated. + */ + void afterScopeActivated(); + + /** Called just after a scope is closed. */ + void afterScopeClosed(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/CoreMetricCollector.java b/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/CoreMetricCollector.java new file mode 100644 index 0000000000..91633d215c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/CoreMetricCollector.java @@ -0,0 +1,72 @@ +package datadog.trace.api.telemetry; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + +import datadog.trace.api.metrics.CoreCounter; +import datadog.trace.api.metrics.SpanMetricRegistryImpl; +import datadog.trace.api.metrics.SpanMetricsImpl; + +/** This class is in charge of draining core metrics for telemetry. */ +public class CoreMetricCollector implements MetricCollector { + private static final String METRIC_NAMESPACE = "tracers"; + private static final String INTEGRATION_NAME_TAG = "integration_name:"; + private static final CoreMetricCollector INSTANCE = new CoreMetricCollector(); + private final SpanMetricRegistryImpl spanMetricRegistry = SpanMetricRegistryImpl.getInstance(); + + private final BlockingQueue metricsQueue; + + public static CoreMetricCollector getInstance() { + return INSTANCE; + } + + private CoreMetricCollector() { + this.metricsQueue = new ArrayBlockingQueue<>(RAW_QUEUE_SIZE); + } + + @Override + public void prepareMetrics() { + for (SpanMetricsImpl spanMetrics : this.spanMetricRegistry.getSpanMetrics()) { + String tag = INTEGRATION_NAME_TAG + spanMetrics.getInstrumentationName(); + for (CoreCounter counter : spanMetrics.getCounters()) { + long value = counter.getValueAndReset(); + if (value == 0) { + // Skip not updated counters + continue; + } + CoreMetric metric = + new CoreMetric(METRIC_NAMESPACE, true, counter.getName(), "count", value, tag); + if (!this.metricsQueue.offer(metric)) { + // Stop adding metrics if the queue is full + break; + } + } + } + } + + @Override + public Collection drain() { + if (this.metricsQueue.isEmpty()) { + return Collections.emptyList(); + } + List drained = new ArrayList<>(this.metricsQueue.size()); + this.metricsQueue.drainTo(drained); + return drained; + } + + public static class CoreMetric extends Metric { + public CoreMetric( + String namespace, + boolean common, + String metricName, + String type, + Number value, + String tag) { + super(namespace, common, metricName, type, value, tag); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/IntegrationsCollector.java b/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/IntegrationsCollector.java new file mode 100644 index 0000000000..2b85a444e6 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/IntegrationsCollector.java @@ -0,0 +1,50 @@ +package datadog.trace.api.telemetry; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; + +public class IntegrationsCollector { + + private static final IntegrationsCollector INSTANCE = new IntegrationsCollector(); + private final Queue integrations = new LinkedBlockingQueue<>(); + + private IntegrationsCollector() {} + + public static IntegrationsCollector get() { + return INSTANCE; + } + + public synchronized void update(Iterable names, boolean enabled) { + Integration i = new Integration(); + i.names = names; + i.enabled = enabled; + + integrations.offer(i); + } + + public synchronized Map drain() { + if (integrations.isEmpty()) { + return Collections.emptyMap(); + } + + Map map = new LinkedHashMap<>(); + + Integration i; + while ((i = integrations.poll()) != null) { + boolean enabled = i.enabled; + for (String name : i.names) { + map.put(name, enabled); + } + } + + return map; + } + + private static class Integration { + public Iterable names; + public boolean enabled; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/LogCollector.java b/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/LogCollector.java new file mode 100644 index 0000000000..0a99d1365f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/LogCollector.java @@ -0,0 +1,107 @@ +package datadog.trace.api.telemetry; + +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +public class LogCollector { + public static final Marker SEND_TELEMETRY = MarkerFactory.getMarker("SEND_TELEMETRY"); + private static final int DEFAULT_MAX_CAPACITY = 1024; + private static final LogCollector INSTANCE = new LogCollector(); + private final Map rawLogMessages; + private final int maxCapacity; + + public static LogCollector get() { + return INSTANCE; + } + + private LogCollector() { + this(DEFAULT_MAX_CAPACITY); + } + + // For testing purpose + LogCollector(int maxCapacity) { + this.maxCapacity = maxCapacity; + this.rawLogMessages = new ConcurrentHashMap<>(maxCapacity); + } + + public void addLogMessage(String logLevel, String message, Throwable throwable) { + RawLogMessage rawLogMessage = + new RawLogMessage(logLevel, message, throwable, System.currentTimeMillis()); + + if (rawLogMessages.size() < maxCapacity) { + AtomicInteger count = rawLogMessages.computeIfAbsent(rawLogMessage, k -> new AtomicInteger()); + count.incrementAndGet(); + } + } + + public Collection drain() { + if (rawLogMessages.isEmpty()) { + return Collections.emptyList(); + } + + List list = new ArrayList<>(); + + Iterator> iterator = + rawLogMessages.entrySet().iterator(); + + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + + RawLogMessage logMessage = entry.getKey(); + logMessage.count = entry.getValue().get(); + + iterator.remove(); + + list.add(logMessage); + } + + return list; + } + + public static class RawLogMessage { + public final String messageOriginal; + public final String logLevel; + public final Throwable throwable; + public final long timestamp; + public int count; + + public RawLogMessage(String logLevel, String message, Throwable throwable, long timestamp) { + this.logLevel = logLevel; + this.messageOriginal = message; + this.throwable = throwable; + this.timestamp = timestamp; + } + + public String message() { + if (count > 1) { + return messageOriginal + ", {" + count + "} additional messages skipped"; + } + return messageOriginal; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RawLogMessage that = (RawLogMessage) o; + return Objects.equals(logLevel, that.logLevel) + && Objects.equals(messageOriginal, that.messageOriginal) + && Objects.equals(throwable, that.throwable); + } + + @Override + public int hashCode() { + return Objects.hash(logLevel, messageOriginal, throwable); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/MetricCollector.java b/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/MetricCollector.java new file mode 100644 index 0000000000..ee8347b61a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/MetricCollector.java @@ -0,0 +1,113 @@ +package datadog.trace.api.telemetry; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static datadog.trace.api.telemetry.MetricCollector.Metric; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +public interface MetricCollector { + + int RAW_QUEUE_SIZE = 1024; + + // TODO All implementations are based on queueing metrics and never care when the queue is full. + // TODO This leads to always resetting counters even if the related metrics could not be enqueued. + // TODO So we may loose metric information during this call. + void prepareMetrics(); + + Collection drain(); + + class Metric { + public final String metricName; + public final boolean common; + public final String namespace; + public final String type; + public final long timestamp; + public final Number value; + public final List tags; + + public Metric( + String namespace, + boolean common, + String metricName, + String type, + Number value, + final String tag) { + this( + namespace, + common, + metricName, + type, + value, + tag == null ? emptyList() : singletonList(tag)); + } + + public Metric( + String namespace, + boolean common, + String metricName, + String type, + Number value, + final String... tags) { + this(namespace, common, metricName, type, value, Arrays.asList(tags)); + } + + public Metric( + String namespace, + boolean common, + String metricName, + String type, + Number value, + final List tags) { + this.namespace = namespace; + this.common = common; + this.metricName = metricName; + this.type = type; + this.timestamp = System.currentTimeMillis() / 1000; + this.value = value; + this.tags = tags; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (!(o instanceof Metric)) return false; + Metric metric = (Metric) o; + return common == metric.common + && Objects.equals(metricName, metric.metricName) + && Objects.equals(namespace, metric.namespace) + && Objects.equals(tags, metric.tags); + } + + @Override + public int hashCode() { + return Objects.hash(metricName, common, namespace, tags); + } + + @Override + public String toString() { + return "Metric{" + + "metricName='" + + metricName + + '\'' + + ", common=" + + common + + ", namespace='" + + namespace + + '\'' + + ", type='" + + type + + '\'' + + ", timestamp=" + + timestamp + + ", value=" + + value + + ", tags=" + + tags + + '}'; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/WafMetricCollector.java b/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/WafMetricCollector.java new file mode 100644 index 0000000000..bec43b3824 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/WafMetricCollector.java @@ -0,0 +1,189 @@ +package datadog.trace.api.telemetry; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +public class WafMetricCollector implements MetricCollector { + + public static final WafMetricCollector INSTANCE = new WafMetricCollector(); + + public static WafMetricCollector get() { + return WafMetricCollector.INSTANCE; + } + + private static final String NAMESPACE = "appsec"; + + private static final BlockingQueue rawMetricsQueue = + new ArrayBlockingQueue<>(RAW_QUEUE_SIZE); + + private static final AtomicInteger wafInitCounter = new AtomicInteger(); + private static final AtomicInteger wafUpdatesCounter = new AtomicInteger(); + + private static final AtomicRequestCounter wafRequestCounter = new AtomicRequestCounter(); + private static final AtomicRequestCounter wafTriggeredRequestCounter = new AtomicRequestCounter(); + private static final AtomicRequestCounter wafBlockedRequestCounter = new AtomicRequestCounter(); + + /** WAF version that will be initialized with wafInit and reused for all metrics. */ + private static String wafVersion = ""; + /** + * Rules version that will be updated on each wafInit and wafUpdates. This is not entirely + * accurate, since wafRequest metrics might be collected for a period where a rules update happens + * and some requests will be incorrectly reported with the old or new rules version. + */ + private static String rulesVersion = ""; + + public void wafInit(final String wafVersion, final String rulesVersion) { + WafMetricCollector.wafVersion = wafVersion; + WafMetricCollector.rulesVersion = rulesVersion; + rawMetricsQueue.offer( + new WafInitRawMetric(wafInitCounter.incrementAndGet(), wafVersion, rulesVersion)); + } + + public void wafUpdates(final String rulesVersion) { + rawMetricsQueue.offer( + new WafUpdatesRawMetric(wafUpdatesCounter.incrementAndGet(), wafVersion, rulesVersion)); + + // Flush request metrics to get the new version. + if (rulesVersion != null + && WafMetricCollector.rulesVersion != null + && !rulesVersion.equals(WafMetricCollector.rulesVersion)) { + WafMetricCollector.get().prepareMetrics(); + } + WafMetricCollector.rulesVersion = rulesVersion; + } + + public void wafRequest() { + wafRequestCounter.increment(); + } + + public void wafRequestTriggered() { + wafTriggeredRequestCounter.increment(); + } + + public void wafRequestBlocked() { + wafBlockedRequestCounter.increment(); + } + + @Override + public Collection drain() { + if (!rawMetricsQueue.isEmpty()) { + List list = new LinkedList<>(); + int drained = rawMetricsQueue.drainTo(list); + if (drained > 0) { + return list; + } + } + return Collections.emptyList(); + } + + @Override + public void prepareMetrics() { + // Requests + if (wafRequestCounter.get() > 0) { + if (!rawMetricsQueue.offer( + new WafRequestsRawMetric( + wafRequestCounter.getAndReset(), + WafMetricCollector.wafVersion, + WafMetricCollector.rulesVersion, + false, + false))) { + return; + } + } + + // Triggered requests + if (wafTriggeredRequestCounter.get() > 0) { + if (!rawMetricsQueue.offer( + new WafRequestsRawMetric( + wafTriggeredRequestCounter.getAndReset(), + WafMetricCollector.wafVersion, + WafMetricCollector.rulesVersion, + true, + false))) { + return; + } + } + + // Blocked requests + if (wafBlockedRequestCounter.get() > 0) { + rawMetricsQueue.offer( + new WafRequestsRawMetric( + wafBlockedRequestCounter.getAndReset(), + WafMetricCollector.wafVersion, + WafMetricCollector.rulesVersion, + true, + true)); + } + } + + public abstract static class WafMetric extends Metric { + + public WafMetric(String metricName, long counter, String... tags) { + super(NAMESPACE, true, metricName, "count", counter, tags); + } + } + + public static class WafInitRawMetric extends WafMetric { + public WafInitRawMetric( + final long counter, final String wafVersion, final String rulesVersion) { + super( + "waf.init", counter, "waf_version:" + wafVersion, "event_rules_version:" + rulesVersion); + } + } + + public static class WafUpdatesRawMetric extends WafMetric { + public WafUpdatesRawMetric( + final long counter, final String wafVersion, final String rulesVersion) { + super( + "waf.updates", + counter, + "waf_version:" + wafVersion, + "event_rules_version:" + rulesVersion); + } + } + + public static class WafRequestsRawMetric extends WafMetric { + public WafRequestsRawMetric( + final long counter, + final String wafVersion, + final String rulesVersion, + final boolean triggered, + final boolean blocked) { + super( + "waf.requests", + counter, + "waf_version:" + wafVersion, + "event_rules_version:" + rulesVersion, + "rule_triggered:" + triggered, + "request_blocked:" + blocked); + } + } + + public static class AtomicRequestCounter { + + private final AtomicLong atomicLong = new AtomicLong(); + private volatile long timestamp; + + public final long get() { + return atomicLong.get(); + } + + public final long getAndReset() { + timestamp = 0; + return atomicLong.getAndSet(0); + } + + public final void increment() { + if (timestamp == 0) { + timestamp = System.currentTimeMillis(); + } + atomicLong.incrementAndGet(); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/time/ControllableTimeSource.java b/features/dd-trace-core/src/main/java/datadog/trace/api/time/ControllableTimeSource.java new file mode 100644 index 0000000000..833314da88 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/time/ControllableTimeSource.java @@ -0,0 +1,35 @@ +package datadog.trace.api.time; + +import java.util.concurrent.TimeUnit; + +public class ControllableTimeSource implements TimeSource { + private long currentTime = 0; + + public void advance(long nanosIncrement) { + currentTime += nanosIncrement; + } + + public void set(long nanos) { + currentTime = nanos; + } + + @Override + public long getNanoTicks() { + return currentTime; + } + + @Override + public long getCurrentTimeMillis() { + return TimeUnit.NANOSECONDS.toMillis(currentTime); + } + + @Override + public long getCurrentTimeMicros() { + return TimeUnit.NANOSECONDS.toMicros(currentTime); + } + + @Override + public long getCurrentTimeNanos() { + return currentTime; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/time/SystemTimeSource.java b/features/dd-trace-core/src/main/java/datadog/trace/api/time/SystemTimeSource.java new file mode 100644 index 0000000000..dfa5139056 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/time/SystemTimeSource.java @@ -0,0 +1,29 @@ +package datadog.trace.api.time; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +public class SystemTimeSource implements TimeSource { + public static final TimeSource INSTANCE = new SystemTimeSource(); + + private SystemTimeSource() {} + + @Override + public long getNanoTicks() { + return System.nanoTime(); + } + + @Override + public long getCurrentTimeMillis() { + return System.currentTimeMillis(); + } + + @Override + public long getCurrentTimeMicros() { + return MILLISECONDS.toMicros(getCurrentTimeMillis()); + } + + @Override + public long getCurrentTimeNanos() { + return MILLISECONDS.toNanos(getCurrentTimeMillis()); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/time/TimeSource.java b/features/dd-trace-core/src/main/java/datadog/trace/api/time/TimeSource.java new file mode 100644 index 0000000000..dc785661fb --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/time/TimeSource.java @@ -0,0 +1,22 @@ +package datadog.trace.api.time; + +/** + * Interface to retrieve various time primitives. Limited by the granularity of the underlying + * platform. + */ +public interface TimeSource { + /** + * Returns monotonically increasing ticks from some arbitrary start point. Should only be used to + * measure durations. Negative numbers and zero are both valid return values + */ + long getNanoTicks(); + + /** Milliseconds since the start of the epoch */ + long getCurrentTimeMillis(); + + /** Microseconds since the start of the epoch */ + long getCurrentTimeMicros(); + + /** Nanoseconds since the start of the epoch. Valid for the time range 1/1/1970 +/- 270 years */ + long getCurrentTimeNanos(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/Blocking.java b/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/Blocking.java new file mode 100644 index 0000000000..0b8d1894d2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/Blocking.java @@ -0,0 +1,137 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.appsec.api.blocking; + +import java.util.Collections; +import java.util.Map; + +/** + * Functionality related to blocking requests. This functionality is available if and only if the + * AppSec subsystem is enabled. + */ +public class Blocking { + private static volatile BlockingService SERVICE = BlockingService.NOOP; + + private Blocking() {} + + /** + * Starts a user-blocking action. + * + * @param userId a non-null unique identifier for the currently identified user + * @return an object through which the action in case of a match can be controlled + */ + public static UserBlockingSpec forUser(String userId) { + if (userId == null) { + throw new NullPointerException("userId cannot be null"); + } + if (SERVICE == null) { + throw new IllegalStateException("Blocking service is not available. Is AppSec disabled?"); + } + return new UserBlockingSpec(userId); + } + + /** + * Tries to commit an HTTP response with the specified status code and content type. No exception + * should escape if this fails. + * + *

This method returns false if blocking cannot be attempted because of the + * following conditions: + * + *

    + *
  • there is no span available, + *
  • blocking is not supported for the server being used, or + *
  • the blocking service is otherwise incapable, in principle, of blocking (e.g. it's a no-op + * implementation). + *
+ * + *

This method does not return false if a blocking response has already been committed, or if + * there is an error when trying to write the response. This is because the writing may happen + * asynchronously, after the caller has returned. + * + * @param statusCode the status code of the response + * @param contentType the content-type of the response. + * @param extraHeaders map of headers to set in the response + * @return whether blocking was/will be attempted + */ + public static boolean tryCommitBlockingResponse( + int statusCode, BlockingContentType contentType, Map extraHeaders) { + try { + return SERVICE.tryCommitBlockingResponse(statusCode, contentType, extraHeaders); + } catch (Exception e) { + return false; + } + } + + /** + * Equivalent to calling {@link #tryCommitBlockingResponse(int, BlockingContentType, Map)} with the last parameter being an empty map. + * + * @param statusCode the status code of the response + * @param contentType the content-type of the response. + * @return whether blocking was/will be attempted + */ + public static boolean tryCommitBlockingResponse(int statusCode, BlockingContentType contentType) { + try { + boolean committedBlockingResponse = + SERVICE.tryCommitBlockingResponse( + statusCode, BlockingContentType.NONE, Collections.emptyMap()); + return committedBlockingResponse; + } catch (Exception e) { + return false; + } + } + + /** + * Controls the implementation for blocking. The AppSec subsystem calls this method on startup. + * This can be called explicitly for e.g. testing purposes. + * + * @param service the implementation for blocking. + */ + public static void setBlockingService(BlockingService service) { + Blocking.SERVICE = service; + } + + public static class UserBlockingSpec { + private final String userId; + + private UserBlockingSpec(String userId) { + this.userId = userId; + } + + /** + * Whether the user in question should be blocked, and, if so, the details of the blocking + * response + * + * @return the details of the blocking response, or null if the user is not to be blocked + */ + public BlockingDetails shouldBlock() { + return SERVICE.shouldBlockUser(userId); + } + + /** + * Convenience method that: + * + *

    + *
  • calls {@link #shouldBlock()}, and, if the result is non-null + *
  • calls {@link #tryCommitBlockingResponse(int, BlockingContentType)}, and + *
  • throws an exception of the type {@link BlockingException} + *
+ */ + public void blockIfMatch() { + BlockingDetails blockingDetails = shouldBlock(); + if (blockingDetails == null) { + return; + } + + SERVICE.tryCommitBlockingResponse( + blockingDetails.statusCode, + blockingDetails.blockingContentType, + blockingDetails.extraHeaders); + throw new BlockingException("Blocking user with id '" + userId + "'"); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingContentType.java b/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingContentType.java new file mode 100644 index 0000000000..c42fef949e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingContentType.java @@ -0,0 +1,21 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.appsec.api.blocking; + +public enum BlockingContentType { + /** + * Automatically choose between HTML and JSON, depending on the value of the Accept + * header. If the preference value is the same, {@link #JSON} will be preferred. + */ + AUTO, + /** An HTTP response. */ + HTML, + /** A JSON response. */ + JSON, + /** No body in the response */ + NONE, +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingDetails.java b/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingDetails.java new file mode 100644 index 0000000000..d452627b03 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingDetails.java @@ -0,0 +1,22 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.appsec.api.blocking; + +import java.util.Map; + +public class BlockingDetails { + public final int statusCode; + public final BlockingContentType blockingContentType; + public final Map extraHeaders; + + public BlockingDetails( + int statusCode, BlockingContentType blockingContentType, Map extraHeaders) { + this.statusCode = statusCode; + this.blockingContentType = blockingContentType; + this.extraHeaders = extraHeaders; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingException.java b/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingException.java new file mode 100644 index 0000000000..3e66084309 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingException.java @@ -0,0 +1,23 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.appsec.api.blocking; + +public class BlockingException extends RuntimeException { + public BlockingException() {} + + public BlockingException(String message) { + super(message); + } + + public BlockingException(String message, Throwable cause) { + super(message, cause); + } + + public BlockingException(Throwable cause) { + super(cause); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingService.java b/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingService.java new file mode 100644 index 0000000000..50bf5dff48 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingService.java @@ -0,0 +1,37 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.appsec.api.blocking; + +import androidx.annotation.NonNull; + +import java.util.Map; + +public interface BlockingService { + BlockingService NOOP = new BlockingServiceNoop(); + + BlockingDetails shouldBlockUser(@NonNull String userId); + + boolean tryCommitBlockingResponse( + int statusCode, @NonNull BlockingContentType type, @NonNull Map extraHeaders); + + class BlockingServiceNoop implements BlockingService { + private BlockingServiceNoop() {} + + @Override + public BlockingDetails shouldBlockUser(@NonNull String userId) { + return null; + } + + @Override + public boolean tryCommitBlockingResponse( + int statusCode, + @NonNull BlockingContentType type, + @NonNull Map extraHeaders) { + return false; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/ActiveSubsystems.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/ActiveSubsystems.java new file mode 100644 index 0000000000..2a43c32c3f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/ActiveSubsystems.java @@ -0,0 +1,5 @@ +package datadog.trace.bootstrap; + +public class ActiveSubsystems { + public static volatile boolean APPSEC_ACTIVE; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java new file mode 100644 index 0000000000..690a82584f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java @@ -0,0 +1,42 @@ +package datadog.trace.bootstrap.config.provider; + +import java.util.Map; + +import datadog.trace.util.Strings; + +public class AgentArgsInjector { + + /** + * Parses agent arguments and sets corresponding system properties. + * + * @param agentArgs Agent arguments to be parsed and set + */ + public static void injectAgentArgsConfig(String agentArgs) { + Map args = ConfigConverter.parseMap(agentArgs, "javaagent arguments", '='); + injectAgentArgsConfig(args); + } + + public static void injectAgentArgsConfig(Map args) { + if (args == null) { + return; + } + for (Map.Entry e : args.entrySet()) { + String propertyName = e.getKey(); + String existingPropertyValue = System.getProperty(propertyName); + if (existingPropertyValue != null) { + // system properties should have higher priority than agent arguments + continue; + } + + String envVarName = Strings.toEnvVar(propertyName); + String envVarValue = System.getenv(envVarName); + if (envVarValue != null) { + // env variables should have higher priority than agent arguments + continue; + } + + String propertyValue = e.getValue(); + System.setProperty(propertyName, propertyValue); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsParser.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsParser.java new file mode 100644 index 0000000000..b8a7480f8d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsParser.java @@ -0,0 +1,44 @@ +package datadog.trace.bootstrap.config.provider; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; + +public class AgentArgsParser { + + private static final Logger log = LoggerFactory.getLogger(AgentArgsParser.class); + + /** + * Parses agent arguments. Key-value pairs should be separated with ',' character. Key and value + * within a pair should be separated with '=' character. For simplicity quoting is not supported + * + * @param agentArgs in form "key1=value1,key2=value2,..." + * @return parsed arguments + */ + public static Map parseAgentArgs(String agentArgs) { + if (agentArgs == null || agentArgs.isEmpty()) { + return null; + } + try { + Map args = new HashMap<>(); + + Scanner scanner = new Scanner(agentArgs); + scanner.useDelimiter(","); + while (scanner.hasNext()) { + String arg = scanner.next(); + int idx = arg.indexOf('='); + String key = arg.substring(0, idx); + String value = arg.substring(idx + 1); + args.put(key, value); + } + return args; + + } catch (Exception ex) { + log.error("Error parsing agent args: {}", agentArgs, ex); + return null; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java new file mode 100644 index 0000000000..56bfb0ad54 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java @@ -0,0 +1,26 @@ +package datadog.trace.bootstrap.config.provider; + +import datadog.trace.api.ConfigOrigin; +import datadog.trace.api.env.CapturedEnvironment; + +public final class CapturedEnvironmentConfigSource extends ConfigProvider.Source { + private final CapturedEnvironment env; + + public CapturedEnvironmentConfigSource() { + this(CapturedEnvironment.get()); + } + + public CapturedEnvironmentConfigSource(CapturedEnvironment env) { + this.env = env; + } + + @Override + protected String get(String key) { + return env.getProperties().get(key); + } + + @Override + public ConfigOrigin origin() { + return ConfigOrigin.ENV; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java new file mode 100644 index 0000000000..99d162e528 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java @@ -0,0 +1,403 @@ +package datadog.trace.bootstrap.config.provider; + +import androidx.annotation.NonNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import datadog.trace.util.Strings; + +final class ConfigConverter { + + private static final Logger log = LoggerFactory.getLogger(ConfigConverter.class); + + /** + * @param value to parse by tClass::valueOf + * @param tClass should contain static parsing method "T valueOf(String)" + * @param + * @return value == null || value.trim().isEmpty() ? defaultValue : tClass.valueOf(value) + * @throws NumberFormatException + */ + @SuppressWarnings("unchecked") + static T valueOf(final String value, @NonNull final Class tClass) { + Objects.requireNonNull(tClass, "tClass is marked non-null but is null"); + if (value == null || value.trim().isEmpty()) { + return null; + } + try { + if(tClass == Boolean.class) { + return (T) Boolean.valueOf(value); + }else if (tClass == Integer.class) { + return (T) Integer.valueOf(value); + }else if (tClass == Long.class) { + return (T) Long.valueOf(value); + }else if (tClass == Double.class) { + return (T) Double.valueOf(value); + }else if (tClass == Float.class) { + return (T) Float.valueOf(value); + } + else { + return null; + } + } catch (final NumberFormatException e) { + throw e; + } catch (final Throwable e) { + log.debug("Can't parse: ", e); + throw new NumberFormatException(e.toString()); + } + } + + @NonNull + static List parseList(final String str) { + return parseList(str, ","); + } + + @NonNull + static List parseList(final String str, final String separator) { + String trimmed = Strings.trim(str); + if (trimmed.isEmpty()) { + return Collections.emptyList(); + } + + final String[] tokens = trimmed.split(separator, -1); + // Remove whitespace from each item. + for (int i = 0; i < tokens.length; i++) { + tokens[i] = tokens[i].trim(); + } + return Collections.unmodifiableList(Arrays.asList(tokens)); + } + + @NonNull + static Map parseMap(final String str, final String settingName) { + return parseMap(str, settingName, ':'); + } + + @NonNull + static Map parseMap( + final String str, final String settingName, final char keyValueSeparator) { + // If we ever want to have default values besides an empty map, this will need to change. + String trimmed = Strings.trim(str); + if (trimmed.isEmpty()) { + return Collections.emptyMap(); + } + Map map = new HashMap<>(); + loadMap(map, trimmed, settingName, keyValueSeparator); + return map; + } + + /** + * This parses a mixed map that can have both key value pairs, and also keys only, that will get + * values on the form "defaultPrefix.key". For keys without a value, the corresponding value will + * be normalized by converting the key to lower case and replacing all non alphanumeric + * characters, except '_', '-', '/' with '_'. + * + *

The allowed format is "(key:value|key)([ ,](key:value|key))*", where you have to choose + * between ',' or ' ' as the separator. + * + * @param str String to parse + * @param settingName Name of the setting being parsed + * @param defaultPrefix Default prefix to add to key ony items + * @param lowercaseKeys Should the keys be converted to lowercase + * @return A map containing the parsed key value pairs + */ + @NonNull + static Map parseMapWithOptionalMappings( + final String str, + final String settingName, + final String defaultPrefix, + boolean lowercaseKeys) { + String trimmed = Strings.trim(str); + if (trimmed.isEmpty()) { + return Collections.emptyMap(); + } + Map map = new HashMap<>(); + loadMapWithOptionalMapping(map, trimmed, settingName, defaultPrefix, lowercaseKeys); + return map; + } + + @NonNull + static Map parseOrderedMap(final String str, final String settingName) { + // If we ever want to have default values besides an empty map, this will need to change. + String trimmed = Strings.trim(str); + if (trimmed.isEmpty()) { + return Collections.emptyMap(); + } + Map map = new LinkedHashMap<>(); + loadMap(map, trimmed, settingName, ':'); + return map; + } + + private static final class BadFormatException extends Exception { + public BadFormatException(String message) { + super(message); + } + } + + private static void loadMap( + Map map, String str, String settingName, char keyValueSeparator) { + // we know that the str is trimmed and rely on that there is no leading/trailing whitespace + try { + int start = 0; + int splitter = str.indexOf(keyValueSeparator, start); + while (splitter != -1) { + int nextSplitter = str.indexOf(keyValueSeparator, splitter + 1); + int nextComma = str.indexOf(',', splitter + 1); + nextComma = nextComma == -1 ? str.length() : nextComma; + int nextSpace = str.indexOf(' ', splitter + 1); + nextSpace = nextSpace == -1 ? str.length() : nextSpace; + // if we have a delimiter after this splitter, then try to move the splitter forward to + // allow for tags with ':' in them + int end = nextComma < str.length() ? nextComma : nextSpace; + while (nextSplitter != -1 && nextSplitter < end) { + nextSplitter = str.indexOf(keyValueSeparator, nextSplitter + 1); + } + if (nextSplitter == -1) { + // this is either the end of the string or the next position where the value should be + // trimmed + end = nextComma; + if (nextComma < str.length() - 1) { + // there are non-space characters after the ',' + throw new BadFormatException("Non white space characters after trailing ','"); + } + } else { + if (nextComma < str.length()) { + end = nextComma; + } else if (nextSpace < str.length()) { + end = nextSpace; + } else { + // this should not happen + throw new BadFormatException("Illegal position of split character ':'"); + } + } + String key = str.substring(start, splitter).trim(); + if (key.indexOf(',') != -1) { + throw new BadFormatException("Illegal ',' character in key '" + key + "'"); + } + String value = str.substring(splitter + 1, end).trim(); + if (value.indexOf(' ') != -1) { + throw new BadFormatException("Illegal ' ' character in value for key '" + key + "'"); + } + if (!key.isEmpty() && !value.isEmpty()) { + map.put(key, value); + } + splitter = nextSplitter; + start = end + 1; + } + } catch (Throwable t) { + if (t instanceof BadFormatException) { + log.warn( + "Invalid config for {}. {}. Must match " + + "'key1{}value1,key2{}value2' or " + + "'key1{}value1 key2{}value2'.", + settingName, + t.getMessage(), + keyValueSeparator, + keyValueSeparator, + keyValueSeparator, + keyValueSeparator); + } else { + log.warn("Unexpected exception during config parsing of {}.", settingName, t); + } + map.clear(); + } + } + + private static void loadMapWithOptionalMapping( + Map map, + String str, + String settingName, + String defaultPrefix, + boolean lowercaseKeys) { + try { + defaultPrefix = null == defaultPrefix ? "" : defaultPrefix; + if (!defaultPrefix.isEmpty() && !defaultPrefix.endsWith(".")) { + defaultPrefix = defaultPrefix + "."; + } + int start = 0; + int len = str.length(); + char listChar = str.indexOf(',') == -1 ? ' ' : ','; + while (start < len) { + int end = len; + int listPos = str.indexOf(listChar, start); + int mapPos = str.indexOf(':', start); + int delimiter = listPos == -1 ? mapPos : mapPos == -1 ? listPos : Math.min(listPos, mapPos); + if (delimiter == -1) { + delimiter = end; + } else if (delimiter == mapPos) { + // we're in a mapping, so let's find the next part + int nextList = str.indexOf(listChar, delimiter + 1); + if (mapPos == start) { + // can't have an empty key + throw new BadFormatException("Illegal empty key at position " + start); + } else if (nextList != -1) { + end = nextList; + } + } else { + // delimiter is at listPos, so set end to delimiter + end = delimiter; + } + + if (start != end) { + String key = trimmedHeader(str, start, delimiter, lowercaseKeys); + if (!key.isEmpty()) { + String value; + if (delimiter == mapPos) { + value = trimmedHeader(str, delimiter + 1, end, false); + // tags must start with a letter + if (!value.isEmpty() && !Character.isLetter(value.charAt(0))) { + throw new BadFormatException( + "Illegal tag starting with non letter for key '" + key + "'"); + } + } else { + if (Character.isLetter(key.charAt(0))) { + value = defaultPrefix + Strings.normalizedHeaderTag(key); + } else { + // tags must start with a letter + throw new BadFormatException( + "Illegal key only tag starting with non letter '" + key + "'"); + } + } + if (!value.isEmpty()) { + map.put(key, value); + } + } + } + start = end + 1; + } + } catch (Throwable t) { + if (t instanceof BadFormatException) { + log.warn( + "Invalid config for {}. {}. Must match '(key:value|key)([ ,](key:value|key))*'.", + settingName, + t.getMessage()); + } else { + log.warn("Unexpected exception during config parsing of {}.", settingName, t); + } + map.clear(); + } + } + + @NonNull + private static String trimmedHeader(String str, int start, int end, boolean lowercase) { + if (start >= end) { + return ""; + } + StringBuilder builder = new StringBuilder(end - start); + int firstNonWhiteSpace = -1; + int lastNonWhitespace = -1; + for (int i = start; i < end; i++) { + char c = lowercase ? Character.toLowerCase(str.charAt(i)) : str.charAt(i); + if (Character.isWhitespace(c)) { + builder.append(' '); + } else { + firstNonWhiteSpace = firstNonWhiteSpace == -1 ? i : firstNonWhiteSpace; + lastNonWhitespace = i; + builder.append(c); + } + } + if (firstNonWhiteSpace == -1) { + return ""; + } else { + str = builder.substring(firstNonWhiteSpace - start, lastNonWhitespace - start + 1); + return str; + } + } + @NonNull + static BitSet parseIntegerRangeSet(@NonNull String str, final String settingName) + throws NumberFormatException { + str = str.replaceAll("\\s", ""); + if (!str.matches("\\d{1,3}(?:-\\d{1,3})?(?:,\\d{1,3}(?:-\\d{1,3})?)*")) { + log.warn( + "Invalid config for {}: '{}'. Must be formatted like '400-403,405,410-499'.", + settingName, + str); + throw new NumberFormatException(); + } + + final int lastSeparator = Math.max(str.lastIndexOf(','), str.lastIndexOf('-')); + final int maxValue = Integer.parseInt(str.substring(lastSeparator + 1)); + final BitSet set = new BitSet(maxValue); + final String[] tokens = str.split(",", -1); + for (final String token : tokens) { + final int separator = token.indexOf('-'); + if (separator == -1) { + set.set(Integer.parseInt(token)); + } else if (separator > 0) { + final int left = Integer.parseInt(token.substring(0, separator)); + final int right = Integer.parseInt(token.substring(separator + 1)); + final int min = Math.min(left, right); + final int max = Math.max(left, right); + set.set(min, max + 1); + } + } + return set; + } + + public static Boolean booleanValueOf(String value) { + if ("1".equals(value)) { + return Boolean.TRUE; + } else { + return Boolean.valueOf(value); + } + } + + private static class ValueOfLookup extends ClassValue { + private static final MethodHandles.Lookup PUBLIC_LOOKUP = MethodHandles.publicLookup(); + + @Override + protected MethodHandle computeValue(Class type) { + try { + if (Boolean.class.equals(type)) { + return MethodHandles.lookup() + .findStatic( + ConfigConverter.class, + "booleanValueOf", + MethodType.methodType(Boolean.class, String.class)); + } + + return PUBLIC_LOOKUP.findStatic(type, "valueOf", MethodType.methodType(type, String.class)); + } catch (final NoSuchMethodException | IllegalAccessException e) { + log.debug("Can't invoke or access 'valueOf': ", e); + throw new RuntimeException(e); + } + } + } + + public static String renderIntegerRange(BitSet bitset) { + StringBuilder sb = new StringBuilder(); + int start = 0; + while (true) { + start = bitset.nextSetBit(start); + if (start < 0) { + break; + } + int end = bitset.nextClearBit(start); + if (sb.length() > 0) { + sb.append(','); + } + if (start < end - 1) { + // interval + sb.append(start); + sb.append('-'); + sb.append(end); + } else { + // single value + sb.append(start); + } + start = end; + } + return sb.toString(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java new file mode 100644 index 0000000000..d9dbaf221a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java @@ -0,0 +1,487 @@ +package datadog.trace.bootstrap.config.provider; + +import static datadog.trace.api.config.GeneralConfig.CONFIGURATION_FILE; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.BitSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import datadog.trace.api.ConfigCollector; +import datadog.trace.api.ConfigOrigin; + +public final class ConfigProvider { + private static final class Singleton { + private static final ConfigProvider INSTANCE = ConfigProvider.createDefault(); + } + + private static final Logger log = LoggerFactory.getLogger(ConfigProvider.class); + + private final boolean collectConfig; + + private final Source[] sources; + + private ConfigProvider(Source... sources) { + this(true, sources); + } + + private ConfigProvider(boolean collectConfig, Source... sources) { + this.collectConfig = collectConfig; + this.sources = sources; + } + + public String getConfigFileStatus() { + for (Source source : sources) { + if (source instanceof PropertiesConfigSource) { + String configFileStatus = ((PropertiesConfigSource) source).getConfigFileStatus(); + if (null != configFileStatus) { + return configFileStatus; + } + } + } + return "no config file present"; + } + + public String getString(String key) { + return getString(key, null); + } + + public > T getEnum(String key, Class enumType, T defaultValue) { + String value = getString(key); + if (null != value) { + try { + return Enum.valueOf(enumType, value); + } catch (Exception ignoreAndUseDefault) { + log.debug("failed to parse {} for {}, defaulting to {}", value, key, defaultValue); + } + } + if (collectConfig) { + ConfigCollector.get().put(key, String.valueOf(defaultValue), ConfigOrigin.DEFAULT); + } + return defaultValue; + } + + public String getString(String key, String defaultValue, String... aliases) { + for (Source source : sources) { + String value = source.get(key, aliases); + if (value != null) { + if (collectConfig) { + ConfigCollector.get().put(key, value, source.origin()); + } + return value; + } + } + if (collectConfig && defaultValue != null) { + ConfigCollector.get().put(key, defaultValue, ConfigOrigin.DEFAULT); + } + return defaultValue; + } + + /** + * Like {@link #getString(String, String, String...)} but falls back to next source if a value is + * an empty or blank string. + */ + public String getStringNotEmpty(String key, String defaultValue, String... aliases) { + for (Source source : sources) { + String value = source.get(key, aliases); + if (value != null && !value.trim().isEmpty()) { + if (collectConfig) { + ConfigCollector.get().put(key, value, source.origin()); + } + return value; + } + } + if (collectConfig && defaultValue != null) { + ConfigCollector.get().put(key, defaultValue, ConfigOrigin.DEFAULT); + } + return defaultValue; + } + + public String getStringExcludingSource( + String key, + String defaultValue, + Class excludedSource, + String... aliases) { + for (Source source : sources) { + if (excludedSource.isAssignableFrom(source.getClass())) { + continue; + } + + String value = source.get(key, aliases); + if (value != null) { + if (collectConfig) { + ConfigCollector.get().put(key, value, source.origin()); + } + return value; + } + } + if (collectConfig && defaultValue != null) { + ConfigCollector.get().put(key, defaultValue, ConfigOrigin.DEFAULT); + } + return defaultValue; + } + + public boolean isSet(String key) { + String value = getString(key); + return value != null && !value.isEmpty(); + } + + public Boolean getBoolean(String key) { + return get(key, null, Boolean.class); + } + + public Boolean getBoolean(String key, String... aliases) { + return get(key, null, Boolean.class, aliases); + } + + public boolean getBoolean(String key, boolean defaultValue, String... aliases) { + return get(key, defaultValue, Boolean.class, aliases); + } + + public Integer getInteger(String key) { + return get(key, null, Integer.class); + } + + public Integer getInteger(String key, String... aliases) { + return get(key, null, Integer.class, aliases); + } + + public int getInteger(String key, int defaultValue, String... aliases) { + return get(key, defaultValue, Integer.class, aliases); + } + + public Long getLong(String key) { + return get(key, null, Long.class); + } + + public Long getLong(String key, String... aliases) { + return get(key, null, Long.class, aliases); + } + + public long getLong(String key, long defaultValue, String... aliases) { + return get(key, defaultValue, Long.class, aliases); + } + + public Float getFloat(String key, String... aliases) { + return get(key, null, Float.class, aliases); + } + + public float getFloat(String key, float defaultValue) { + return get(key, defaultValue, Float.class); + } + + public Double getDouble(String key) { + return get(key, null, Double.class); + } + + public double getDouble(String key, double defaultValue) { + return get(key, defaultValue, Double.class); + } + + private T get(String key, T defaultValue, Class type, String... aliases) { + for (Source source : sources) { + try { + String sourceValue = source.get(key, aliases); + T value = ConfigConverter.valueOf(sourceValue, type); + if (value != null) { + if (collectConfig) { + ConfigCollector.get().put(key, sourceValue, source.origin()); + } + return value; + } + } catch (NumberFormatException ex) { + // continue + } + } + if (collectConfig && defaultValue != null) { + ConfigCollector.get().put(key, defaultValue, ConfigOrigin.DEFAULT); + } + return defaultValue; + } + + public List getList(String key) { + return ConfigConverter.parseList(getString(key)); + } + + public List getList(String key, List defaultValue) { + String list = getString(key); + if (null == list) { + if (collectConfig && defaultValue != null) { + ConfigCollector.get().put(key, String.join(",", defaultValue), ConfigOrigin.DEFAULT); + } + return defaultValue; + } else { + return ConfigConverter.parseList(getString(key)); + } + } + + public Set getSet(String key, Set defaultValue) { + String list = getString(key); + if (null == list) { + if (collectConfig && defaultValue != null) { + String defaultValueStr = String.join(",", defaultValue); + ConfigCollector.get().put(key, defaultValueStr, ConfigOrigin.DEFAULT); + } + return defaultValue; + } else { + return new HashSet(ConfigConverter.parseList(getString(key))); + } + } + + public List getSpacedList(String key) { + return ConfigConverter.parseList(getString(key), " "); + } + + public Map getMergedMap(String key) { + Map merged = new HashMap<>(); + ConfigOrigin origin = ConfigOrigin.DEFAULT; + // System properties take precedence over env + // prior art: + // https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/html/boot-features-external-config.html + // We reverse iterate to allow overrides + for (int i = sources.length - 1; 0 <= i; i--) { + String value = sources[i].get(key); + Map parsedMap = ConfigConverter.parseMap(value, key); + if (!parsedMap.isEmpty()) { + origin = sources[i].origin(); + } + merged.putAll(parsedMap); + } + collectMapSetting(key, merged, origin); + return merged; + } + + public Map getOrderedMap(String key) { + LinkedHashMap merged = new LinkedHashMap<>(); + ConfigOrigin origin = ConfigOrigin.DEFAULT; + // System properties take precedence over env + // prior art: + // https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/html/boot-features-external-config.html + // We reverse iterate to allow overrides + for (int i = sources.length - 1; 0 <= i; i--) { + String value = sources[i].get(key); + Map parsedMap = ConfigConverter.parseOrderedMap(value, key); + if (!parsedMap.isEmpty()) { + origin = sources[i].origin(); + } + merged.putAll(parsedMap); + } + collectMapSetting(key, merged, origin); + return merged; + } + + public Map getMergedMapWithOptionalMappings( + String defaultPrefix, boolean lowercaseKeys, String... keys) { + Map merged = new HashMap<>(); + ConfigOrigin origin = ConfigOrigin.DEFAULT; + // System properties take precedence over env + // prior art: + // https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/html/boot-features-external-config.html + // We reverse iterate to allow overrides + for (String key : keys) { + for (int i = sources.length - 1; 0 <= i; i--) { + String value = sources[i].get(key); + Map parsedMap = + ConfigConverter.parseMapWithOptionalMappings(value, key, defaultPrefix, lowercaseKeys); + if (!parsedMap.isEmpty()) { + origin = sources[i].origin(); + } + merged.putAll(parsedMap); + } + collectMapSetting(key, merged, origin); + } + return merged; + } + + public BitSet getIntegerRange(final String key, final BitSet defaultValue) { + final String value = getString(key); + try { + if (value != null) { + return ConfigConverter.parseIntegerRangeSet(value, key); + } + } catch (final NumberFormatException e) { + log.warn("Invalid configuration for {}", key, e); + } + if (collectConfig) { + String defaultValueStr = ConfigConverter.renderIntegerRange(defaultValue); + ConfigCollector.get().put(key, defaultValueStr, ConfigOrigin.DEFAULT); + } + return defaultValue; + } + + public boolean isEnabled( + final Iterable settingNames, + final String settingPrefix, + final String settingSuffix, + final boolean defaultEnabled) { + // If default is enabled, we want to disable individually. + // If default is disabled, we want to enable individually. + boolean anyEnabled = defaultEnabled; + for (final String name : settingNames) { + final String configKey = settingPrefix + name + settingSuffix; + final String fullKey = configKey.startsWith("trace.") ? configKey : "trace." + configKey; + final boolean configEnabled = getBoolean(fullKey, defaultEnabled, configKey); + if (defaultEnabled) { + anyEnabled &= configEnabled; + } else { + anyEnabled |= configEnabled; + } + } + return anyEnabled; + } + + public static ConfigProvider getInstance() { + return Singleton.INSTANCE; + } + + public static ConfigProvider createDefault() { + Properties configProperties = + loadConfigurationFile( + new ConfigProvider(new SystemPropertiesConfigSource(), new EnvironmentConfigSource())); + if (configProperties.isEmpty()) { + return new ConfigProvider( + new SystemPropertiesConfigSource(), + new EnvironmentConfigSource(), + new CapturedEnvironmentConfigSource()); + } else { + return new ConfigProvider( + new SystemPropertiesConfigSource(), + new EnvironmentConfigSource(), + new PropertiesConfigSource(configProperties, true), + new CapturedEnvironmentConfigSource()); + } + } + + public static ConfigProvider withoutCollector() { + Properties configProperties = + loadConfigurationFile( + new ConfigProvider( + false, new SystemPropertiesConfigSource(), new EnvironmentConfigSource())); + if (configProperties.isEmpty()) { + return new ConfigProvider( + false, + new SystemPropertiesConfigSource(), + new EnvironmentConfigSource(), + new CapturedEnvironmentConfigSource()); + } else { + return new ConfigProvider( + false, + new SystemPropertiesConfigSource(), + new EnvironmentConfigSource(), + new PropertiesConfigSource(configProperties, true), + new CapturedEnvironmentConfigSource()); + } + } + + public static ConfigProvider withPropertiesOverride(Properties properties) { + PropertiesConfigSource providedConfigSource = new PropertiesConfigSource(properties, false); + Properties configProperties = + loadConfigurationFile( + new ConfigProvider( + new SystemPropertiesConfigSource(), + new EnvironmentConfigSource(), + providedConfigSource)); + if (configProperties.isEmpty()) { + return new ConfigProvider( + new SystemPropertiesConfigSource(), + new EnvironmentConfigSource(), + providedConfigSource, + new CapturedEnvironmentConfigSource()); + } else { + return new ConfigProvider( + providedConfigSource, + new SystemPropertiesConfigSource(), + new EnvironmentConfigSource(), + new PropertiesConfigSource(configProperties, true), + new CapturedEnvironmentConfigSource()); + } + } + + private void collectMapSetting(String key, Map merged, ConfigOrigin origin) { + if (!collectConfig || merged.isEmpty()) { + return; + } + StringBuilder mergedValue = new StringBuilder(); + for (Map.Entry entry : merged.entrySet()) { + if (mergedValue.length() > 0) { + mergedValue.append(','); + } + mergedValue.append(entry.getKey()); + mergedValue.append(':'); + mergedValue.append(entry.getValue()); + } + ConfigCollector.get().put(key, mergedValue.toString(), origin); + } + + /** + * Loads the optional configuration properties file into the global {@link Properties} object. + * + * @return The {@link Properties} object. the returned instance might be empty of file does not + * exist or if it is in a wrong format. + * @param configProvider + */ + private static Properties loadConfigurationFile(ConfigProvider configProvider) { + final Properties properties = new Properties(); + + // Reading from system property first and from env after + String configurationFilePath = configProvider.getString(CONFIGURATION_FILE); + if (null == configurationFilePath) { + return properties; + } + + // Normalizing tilde (~) paths for unix systems + configurationFilePath = + configurationFilePath.replaceFirst("^~", System.getProperty("user.home")); + + // Configuration properties file is optional + final File configurationFile = new File(configurationFilePath); + if (!configurationFile.exists()) { + log.error("Configuration file '{}' not found.", configurationFilePath); + return properties; + } + + try (final FileReader fileReader = new FileReader(configurationFile)) { + properties.load(fileReader); + } catch (final FileNotFoundException fnf) { + log.error("Configuration file '{}' not found.", configurationFilePath); + } catch (final IOException ioe) { + log.error( + "Configuration file '{}' cannot be accessed or correctly parsed.", configurationFilePath); + } + + properties.setProperty(PropertiesConfigSource.CONFIG_FILE_STATUS, configurationFilePath); + + return properties; + } + + public abstract static class Source { + public final String get(String key, String... aliases) { + String value = get(key); + if (value != null) { + return value; + } + for (String alias : aliases) { + value = get(alias); + if (value != null) { + return value; + } + } + return null; + } + + protected abstract String get(String key); + + public abstract ConfigOrigin origin(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java new file mode 100644 index 0000000000..6719693fd8 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java @@ -0,0 +1,18 @@ +package datadog.trace.bootstrap.config.provider; + +import static datadog.trace.util.Strings.propertyNameToEnvironmentVariableName; + +import datadog.trace.api.ConfigOrigin; + +final class EnvironmentConfigSource extends ConfigProvider.Source { + + @Override + protected String get(String key) { + return System.getenv(propertyNameToEnvironmentVariableName(key)); + } + + @Override + public ConfigOrigin origin() { + return ConfigOrigin.ENV; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java new file mode 100644 index 0000000000..76ad7c4709 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java @@ -0,0 +1,35 @@ +package datadog.trace.bootstrap.config.provider; + +import static datadog.trace.util.Strings.propertyNameToSystemPropertyName; + +import java.util.Properties; + +import datadog.trace.api.ConfigOrigin; + +final class PropertiesConfigSource extends ConfigProvider.Source { + // start key with underscore, so it isn't visible using the public 'get' method + static final String CONFIG_FILE_STATUS = "_dd.config.file.status"; + + private final Properties props; + private final boolean useSystemPropertyFormat; + + public PropertiesConfigSource(Properties props, boolean useSystemPropertyFormat) { + assert props != null; + this.props = props; + this.useSystemPropertyFormat = useSystemPropertyFormat; + } + + public String getConfigFileStatus() { + return props.getProperty(CONFIG_FILE_STATUS); + } + + @Override + protected String get(String key) { + return props.getProperty(useSystemPropertyFormat ? propertyNameToSystemPropertyName(key) : key); + } + + @Override + public ConfigOrigin origin() { + return ConfigOrigin.JVM_PROP; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java new file mode 100644 index 0000000000..08aaf48702 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java @@ -0,0 +1,18 @@ +package datadog.trace.bootstrap.config.provider; + +import static datadog.trace.util.Strings.propertyNameToSystemPropertyName; + +import datadog.trace.api.ConfigOrigin; + +public final class SystemPropertiesConfigSource extends ConfigProvider.Source { + + @Override + protected String get(String key) { + return System.getProperty(propertyNameToSystemPropertyName(key)); + } + + @Override + public ConfigOrigin origin() { + return ConfigOrigin.JVM_PROP; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java new file mode 100644 index 0000000000..3f04dd292a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java @@ -0,0 +1,40 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.util.LinkedHashMap; + +import datadog.trace.api.experimental.DataStreamsCheckpointer; + +public interface AgentDataStreamsMonitoring extends DataStreamsCheckpointer { + void trackBacklog(LinkedHashMap sortedTags, long value); + + /** + * Sets data streams checkpoint, used for both produce and consume operations. + * + * @param span active span + * @param sortedTags alphabetically sorted tags for the checkpoint (direction, queue type etc) + * @param defaultTimestamp unix timestamp to use as a start of the pathway if this is the first + * checkpoint in the chain. Zero should be passed if we can't extract the timestamp from the + * message / payload itself (for instance: produce operations; http produce / consume etc). + * Value will be ignored for checkpoints happening not at the start of the pipeline. + * @param payloadSizeBytes size of the message (body + headers) in bytes. Zero should be passed if + * the size cannot be evaluated. + */ + void setCheckpoint( + AgentSpan span, + LinkedHashMap sortedTags, + long defaultTimestamp, + long payloadSizeBytes); + + PathwayContext newPathwayContext(); + + void add(StatsPoint statsPoint); + + /** + * shouldSampleSchema is used to determine if we should extract schema from the message or not. + * + * @param topic Kafka topic + * @return the weight of the schema, indicating how many messages have been sent to the topic + * without having been sampled. + */ + int shouldSampleSchema(String topic); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java new file mode 100644 index 0000000000..f36e08ac81 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java @@ -0,0 +1,24 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.nio.ByteBuffer; + +public interface AgentHistogram { + + double getCount(); + + boolean isEmpty(); + + void accept(double value); + + void accept(double value, double count); + + double getValueAtQuantile(double quantile); + + double getMinValue(); + + double getMaxValue(); + + void clear(); + + ByteBuffer serialize(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java new file mode 100644 index 0000000000..e4ba4281e4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java @@ -0,0 +1,55 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.util.LinkedHashMap; + +import datadog.trace.api.TracePropagationStyle; + +public interface AgentPropagation { + void inject(AgentSpan span, C carrier, Setter setter); + + void inject(AgentSpan.Context context, C carrier, Setter setter); + + void inject(AgentSpan span, C carrier, Setter setter, TracePropagationStyle style); + + // The input tags should be sorted. + void injectPathwayContext( + AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags); + + void injectPathwayContext( + AgentSpan span, + C carrier, + Setter setter, + LinkedHashMap sortedTags, + long defaultTimestamp, + long payloadSizeBytes); + + void injectPathwayContextWithoutSendingStats( + AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags); + + interface Setter { + void set(C carrier, String key, String value); + } + + interface BinarySetter extends Setter { + void set(C carrier, String key, byte[] value); + } + + AgentSpan.Context.Extracted extract(C carrier, ContextVisitor getter); + + interface KeyClassifier { + + boolean accept(String key, String value); + } + + interface BinaryKeyClassifier { + boolean accept(String key, byte[] value); + } + + interface ContextVisitor { + void forEachKey(C carrier, KeyClassifier classifier); + } + + interface BinaryContextVisitor extends ContextVisitor { + void forEachKey(C carrier, BinaryKeyClassifier classifier); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java new file mode 100644 index 0000000000..8075c76b26 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java @@ -0,0 +1,32 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.io.Closeable; + +import datadog.trace.context.TraceScope; + +public interface AgentScope extends TraceScope, Closeable { + AgentSpan span(); + + byte source(); + + @Override + Continuation capture(); + + @Override + Continuation captureConcurrent(); + + @Override + void setAsyncPropagation(boolean value); + + @Override + void close(); + + interface Continuation extends TraceScope.Continuation { + + @Override + AgentScope activate(); + + /** Provide access to the captured span */ + AgentSpan getSpan(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java new file mode 100644 index 0000000000..9337c33ab4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java @@ -0,0 +1,21 @@ +package datadog.trace.bootstrap.instrumentation.api; + +/** + * Allows custom scope managers. See OTScopeManager, CustomScopeManager, and ContextualScopeManager + */ +public interface AgentScopeManager extends ScopeStateAware { + + AgentScope activate(AgentSpan span, ScopeSource source); + + AgentScope activate(AgentSpan span, ScopeSource source, boolean isAsyncPropagating); + + AgentScope active(); + + AgentSpan activeSpan(); + + AgentScope.Continuation captureSpan(AgentSpan span); + + void closePrevious(boolean finishSpan); + + AgentScope activateNext(AgentSpan span); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java new file mode 100644 index 0000000000..f534827d5e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java @@ -0,0 +1,225 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.util.List; +import java.util.Map; + +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.gateway.IGSpanInfo; +import datadog.trace.api.gateway.RequestContext; +import datadog.trace.api.interceptor.MutableSpan; +import datadog.trace.api.sampling.PrioritySampling; + +public interface AgentSpan extends MutableSpan, IGSpanInfo { + + DDTraceId getTraceId(); + + long getSpanId(); + + @Override + AgentSpan setTag(String key, boolean value); + + AgentSpan setTag(String key, int value); + + AgentSpan setTag(String key, long value); + + AgentSpan setTag(String key, double value); + + @Override + AgentSpan setTag(String key, String value); + + AgentSpan setTag(String key, CharSequence value); + + AgentSpan setTag(String key, Object value); + + @Override + AgentSpan setTag(String key, Number value); + + @Override + AgentSpan setMetric(CharSequence key, int value); + + @Override + AgentSpan setMetric(CharSequence key, long value); + + @Override + AgentSpan setMetric(CharSequence key, double value); + + @Override + AgentSpan setSpanType(final CharSequence type); + + Object getTag(String key); + + @Override + AgentSpan setError(boolean error); + + AgentSpan setError(boolean error, byte priority); + + AgentSpan setMeasured(boolean measured); + + AgentSpan setErrorMessage(String errorMessage); + + AgentSpan addThrowable(Throwable throwable); + + AgentSpan addThrowable(Throwable throwable, byte errorPriority); + + @Override + AgentSpan getLocalRootSpan(); + + boolean isSameTrace(AgentSpan otherSpan); + + Context context(); + + String getBaggageItem(String key); + + AgentSpan setBaggageItem(String key, String value); + + AgentSpan setHttpStatusCode(int statusCode); + + short getHttpStatusCode(); + + void finish(); + + void finish(long finishMicros); + + void finishWithDuration(long durationNanos); + + /** Marks the start of a message pipeline where we want to track end-to-end processing time. */ + void beginEndToEnd(); + + /** + * Marks the end of a message pipeline where the final end-to-end processing time is recorded. + * + *

Note: this will also finish the span and publish it. + */ + void finishWithEndToEnd(); + + /** + * Finishes the span but does not publish it. The {@link #publish()} method MUST be called once + * otherwise the trace will not be reported. + * + * @return true if the span was successfully finished, false if it was already finished. + */ + boolean phasedFinish(); + + /** + * Publish a span that was previously finished by calling {@link #phasedFinish()}. Must be called + * once and only once per span. + */ + void publish(); + + CharSequence getSpanName(); + + void setSpanName(CharSequence spanName); + + /** + * Deprecated in favor of setResourceName(final CharSequence resourceName, byte priority) or using + * getResourceNamePriority() for comparisons. + */ + @Deprecated + boolean hasResourceName(); + + byte getResourceNamePriority(); + + @Override + AgentSpan setResourceName(final CharSequence resourceName); + + /** + * Implementation note: two calls with the same priority will result in the second resource name + * being used + */ + AgentSpan setResourceName(final CharSequence resourceName, byte priority); + + boolean eligibleForDropping(); + + /** RequestContext for the Instrumentation Gateway */ + RequestContext getRequestContext(); + + Integer forceSamplingDecision(); + + AgentSpan setSamplingPriority(final int newPriority, int samplingMechanism); + + TraceConfig traceConfig(); + + void addLink(AgentSpanLink link); + + interface Context { + /** + * Gets the TraceId of the span's trace. + * + * @return The TraceId of the span's trace, or {@link DDTraceId#ZERO} if not set. + */ + DDTraceId getTraceId(); + + /** + * Gets the SpanId. + * + * @return The span identifier, or {@link datadog.trace.api.DDSpanId#ZERO} if not set. + */ + long getSpanId(); + + /** + * Get the span's trace. + * + * @return The span's trace, or a noop {@link AgentTracer.NoopAgentTrace#INSTANCE} if the trace + * is not valid. + */ + AgentTrace getTrace(); + + /** + * Gets the trace sampling priority of the span's trace. + * + *

Check {@link PrioritySampling} for possible values. + * + * @return The trace sampling priority of the span's trace, or {@link PrioritySampling#UNSET} if + * no priority has been set. + */ + int getSamplingPriority(); + + Iterable> baggageItems(); + + PathwayContext getPathwayContext(); + + default void mergePathwayContext(PathwayContext pathwayContext) {} + + interface Extracted extends Context { + /** + * Gets the span links related to the other terminated context. + * + * @return The span links to other extracted contexts found but terminated. + */ + List getTerminatedContextLinks(); + + String getForwarded(); + + String getFastlyClientIp(); + + String getCfConnectingIp(); + + String getCfConnectingIpv6(); + + String getXForwardedProto(); + + String getXForwardedHost(); + + String getXForwardedPort(); + + String getForwardedFor(); + + String getXForwarded(); + + String getXForwardedFor(); + + String getXClusterClientIp(); + + String getXRealIp(); + + String getXClientIp(); + + String getUserAgent(); + + String getTrueClientIp(); + + String getCustomIpHeader(); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java new file mode 100644 index 0000000000..3e10df0212 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java @@ -0,0 +1,71 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.util.Map; + +import datadog.trace.api.DDTraceId; + +/** + * This interface describes a link to another span. The linked span could be part of the same trace + * or not. + */ +public interface AgentSpanLink { + /** The default trace flags (no flag enabled). */ + byte DEFAULT_FLAGS = 0; + /** The sampled flag denotes that the caller may have recorded trace data. */ + byte SAMPLED_FLAG = 1; + + /** + * Gets the trace identifier of the linked span. + * + * @return The trace identifier of the linked span. + */ + DDTraceId traceId(); + + /** + * Gets the span identifier of the linked span. + * + * @return The span identifier of the linked span as an unsigned 64-bit long. + */ + long spanId(); + + /** + * Gets the 8-bit field that controls tracing flags such as sampling, trace level, etc. + * + * @return The 8-bit field that controls tracing flags such as sampling, trace level, etc. + * @see Trace flag header W3C + * Specification + */ + byte traceFlags(); + + /** + * Gets the vendor-specific trace information as defined per W3C standard. + * + * @return The vendor-specific trace state. + * @see Trace state header W3C + * Specification + */ + String traceState(); + + /** + * Gets the link attributes. + * + * @return The link attributes. + */ + Attributes attributes(); + + interface Attributes { + /** + * Gets the attributes as an immutable map. + * + * @return The attributes as an immutable map. + */ + Map asMap(); + + /** + * Checks whether the attributes are empty. + * + * @return {@code true} if the attributes are empty, {@code false} otherwise. + */ + boolean isEmpty(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java new file mode 100644 index 0000000000..abb4fe9d30 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java @@ -0,0 +1,7 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public interface AgentTrace { + void registerContinuation(AgentScope.Continuation continuation); + + void cancelContinuation(AgentScope.Continuation continuation); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java new file mode 100644 index 0000000000..4ee911f550 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java @@ -0,0 +1,1226 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import static java.util.Collections.emptyList; +import static datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.EndpointCheckpointer; +import datadog.trace.api.EndpointTracker; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.api.experimental.DataStreamsCheckpointer; +import datadog.trace.api.experimental.DataStreamsContextCarrier; +import datadog.trace.api.gateway.CallbackProvider; +import datadog.trace.api.gateway.Flow; +import datadog.trace.api.gateway.RequestContext; +import datadog.trace.api.gateway.RequestContextSlot; +import datadog.trace.api.gateway.SubscriptionService; +import datadog.trace.api.interceptor.TraceInterceptor; +import datadog.trace.api.internal.InternalTracer; +import datadog.trace.api.internal.TraceSegment; +import datadog.trace.api.profiling.Timer; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.api.sampling.SamplingRule; +import datadog.trace.api.scopemanager.ScopeListener; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan.Context; + +public class AgentTracer { + private static final String DEFAULT_INSTRUMENTATION_NAME = "datadog"; + + // Implicit parent + /** Deprecated. Use {@link #startSpan(String, CharSequence)} instead. */ + @Deprecated + public static AgentSpan startSpan(final CharSequence spanName) { + return startSpan(DEFAULT_INSTRUMENTATION_NAME, spanName); + } + + /** @see TracerAPI#startSpan(String, CharSequence) */ + public static AgentSpan startSpan(final String instrumentationName, final CharSequence spanName) { + return get().startSpan(instrumentationName, spanName); + } + + // Implicit parent + /** Deprecated. Use {@link #startSpan(String, CharSequence, long)} instead. */ + @Deprecated + public static AgentSpan startSpan(final CharSequence spanName, final long startTimeMicros) { + return startSpan(DEFAULT_INSTRUMENTATION_NAME, spanName, startTimeMicros); + } + + /** @see TracerAPI#startSpan(String, CharSequence, long) */ + public static AgentSpan startSpan( + final String instrumentationName, final CharSequence spanName, final long startTimeMicros) { + return get().startSpan(instrumentationName, spanName, startTimeMicros); + } + + // Explicit parent + /** Deprecated. Use {@link #startSpan(String, CharSequence, Context)} instead. */ + @Deprecated + public static AgentSpan startSpan(final CharSequence spanName, final Context parent) { + return startSpan(DEFAULT_INSTRUMENTATION_NAME, spanName, parent); + } + + /** @see TracerAPI#startSpan(String, CharSequence, Context) */ + public static AgentSpan startSpan( + final String instrumentationName, + final CharSequence spanName, + final Context parent) { + return get().startSpan(instrumentationName, spanName, parent); + } + + // Explicit parent + /** Deprecated. Use {@link #startSpan(String, CharSequence, Context, long)} instead. */ + @Deprecated + public static AgentSpan startSpan( + final CharSequence spanName, final Context parent, final long startTimeMicros) { + return startSpan(DEFAULT_INSTRUMENTATION_NAME, spanName, parent, startTimeMicros); + } + + /** @see TracerAPI#startSpan(String, CharSequence, Context, long) */ + public static AgentSpan startSpan( + final String instrumentationName, + final CharSequence spanName, + final Context parent, + final long startTimeMicros) { + return get().startSpan(instrumentationName, spanName, parent, startTimeMicros); + } + + public static AgentScope activateSpan(final AgentSpan span) { + return get().activateSpan(span, ScopeSource.INSTRUMENTATION, DEFAULT_ASYNC_PROPAGATING); + } + + public static AgentScope activateSpan(final AgentSpan span, final boolean isAsyncPropagating) { + return get().activateSpan(span, ScopeSource.INSTRUMENTATION, isAsyncPropagating); + } + + public static AgentScope.Continuation captureSpan(final AgentSpan span) { + return get().captureSpan(span); + } + + /** + * Closes the immediately previous iteration scope. Should be called before creating a new span + * for {@link #activateNext(AgentSpan)}. + */ + public static void closePrevious(final boolean finishSpan) { + get().closePrevious(finishSpan); + } + + /** + * Activates a new iteration scope; closes automatically after a fixed period. + * + * @see datadog.trace.api.config.TracerConfig#SCOPE_ITERATION_KEEP_ALIVE + */ + public static AgentScope activateNext(final AgentSpan span) { + return get().activateNext(span); + } + + public static TraceConfig traceConfig(final AgentSpan span) { + return null != span ? span.traceConfig() : traceConfig(); + } + + public static TraceConfig traceConfig() { + return get().captureTraceConfig(); + } + + public static AgentSpan activeSpan() { + return get().activeSpan(); + } + + public static AgentScope activeScope() { + return get().activeScope(); + } + + public static AgentScope.Continuation capture() { + final AgentScope activeScope = activeScope(); + return activeScope == null ? null : activeScope.capture(); + } + + public static AgentPropagation propagate() { + return get().propagate(); + } + + public static AgentSpan noopSpan() { + return get().noopSpan(); + } + + public static final TracerAPI NOOP_TRACER = new NoopTracerAPI(); + + private static volatile TracerAPI provider = NOOP_TRACER; + + public static boolean isRegistered() { + return provider != NOOP_TRACER; + } + + public static synchronized void registerIfAbsent(final TracerAPI tracer) { + if (tracer != null && tracer != NOOP_TRACER) { + provider = tracer; + } + } + + public static synchronized void forceRegister(TracerAPI tracer) { + provider = tracer; + } + + public static TracerAPI get() { + return provider; + } + + // Not intended to be constructed. + private AgentTracer() {} + + public interface TracerAPI + extends datadog.trace.api.Tracer, InternalTracer, EndpointCheckpointer, ScopeStateAware { + + /** + * Create and start a new span. + * + * @param instrumentationName The instrumentation creating the span. + * @param spanName The span operation name. + * @return The new started span. + */ + AgentSpan startSpan(String instrumentationName, CharSequence spanName); + + /** + * Create and start a new span with a given start time. + * + * @param instrumentationName The instrumentation creating the span. + * @param spanName The span operation name. + * @param startTimeMicros The span start time, in microseconds. + * @return The new started span. + */ + AgentSpan startSpan(String instrumentationName, CharSequence spanName, long startTimeMicros); + + /** + * Create and start a new span with an explicit parent. + * + * @param instrumentationName The instrumentation creating the span. + * @param spanName The span operation name. + * @param parent The parent span context. + * @return The new started span. + */ + AgentSpan startSpan( + String instrumentationName, CharSequence spanName, Context parent); + + /** + * Create and start a new span with an explicit parent and a given start time. + * + * @param instrumentationName The instrumentation creating the span. + * @param spanName The span operation name. + * @param parent The parent span context. + * @param startTimeMicros The span start time, in microseconds. + * @return The new started span. + */ + AgentSpan startSpan( + String instrumentationName, + CharSequence spanName, + Context parent, + long startTimeMicros); + + AgentScope activateSpan(AgentSpan span, ScopeSource source); + + AgentScope activateSpan(AgentSpan span, ScopeSource source, boolean isAsyncPropagating); + + AgentScope.Continuation captureSpan(AgentSpan span); + + void closePrevious(boolean finishSpan); + + AgentScope activateNext(AgentSpan span); + + AgentSpan activeSpan(); + + AgentScope activeScope(); + + AgentPropagation propagate(); + + AgentSpan noopSpan(); + + /** Deprecated. Use {@link #buildSpan(String, CharSequence)} instead. */ + @Deprecated + default SpanBuilder buildSpan(CharSequence spanName) { + return buildSpan(DEFAULT_INSTRUMENTATION_NAME, spanName); + } + + SpanBuilder buildSpan(String instrumentationName, CharSequence spanName); + + void close(); + + /** + * Attach a scope listener to the global scope manager + * + * @param listener listener to attach + */ + void addScopeListener(ScopeListener listener); + + /** + * Registers the checkpointer + * + * @param checkpointer + */ + void registerCheckpointer(EndpointCheckpointer checkpointer); + + void registerTimer(Timer timer); + + SubscriptionService getSubscriptionService(RequestContextSlot slot); + + CallbackProvider getCallbackProvider(RequestContextSlot slot); + + CallbackProvider getUniversalCallbackProvider(); + + Context notifyExtensionStart(Object event); + + void notifyExtensionEnd(AgentSpan span, Object result, boolean isError); + + AgentDataStreamsMonitoring getDataStreamsMonitoring(); + + Timer getTimer(); + + String getTraceId(AgentSpan span); + + String getSpanId(AgentSpan span); + + TraceConfig captureTraceConfig(); + + ProfilingContextIntegration getProfilingContext(); + + AgentHistogram newHistogram(double relativeAccuracy, int maxNumBins); + } + + public interface SpanBuilder { + AgentSpan start(); + + SpanBuilder asChildOf(Context toContext); + + SpanBuilder ignoreActiveSpan(); + + SpanBuilder withTag(String key, String value); + + SpanBuilder withTag(String key, boolean value); + + SpanBuilder withTag(String key, Number value); + + SpanBuilder withTag(String tag, Object value); + + SpanBuilder withStartTimestamp(long microseconds); + + SpanBuilder withServiceName(String serviceName); + + SpanBuilder withResourceName(String resourceName); + + SpanBuilder withErrorFlag(); + + SpanBuilder withSpanType(CharSequence spanType); + + SpanBuilder withRequestContextData(RequestContextSlot slot, T data); + + SpanBuilder withLink(AgentSpanLink link); + } + + static class NoopTracerAPI implements TracerAPI { + + protected NoopTracerAPI() {} + + @Override + public AgentSpan startSpan(final String instrumentationName, final CharSequence spanName) { + return NoopAgentSpan.INSTANCE; + } + + @Override + public AgentSpan startSpan( + final String instrumentationName, final CharSequence spanName, final long startTimeMicros) { + return NoopAgentSpan.INSTANCE; + } + + @Override + public AgentSpan startSpan( + final String instrumentationName, final CharSequence spanName, final Context parent) { + return NoopAgentSpan.INSTANCE; + } + + @Override + public AgentSpan startSpan( + final String instrumentationName, + final CharSequence spanName, + final Context parent, + final long startTimeMicros) { + return NoopAgentSpan.INSTANCE; + } + + @Override + public AgentScope activateSpan(final AgentSpan span, final ScopeSource source) { + return NoopAgentScope.INSTANCE; + } + + @Override + public AgentScope activateSpan( + final AgentSpan span, final ScopeSource source, final boolean isAsyncPropagating) { + return NoopAgentScope.INSTANCE; + } + + @Override + public AgentScope.Continuation captureSpan(final AgentSpan span) { + return NoopContinuation.INSTANCE; + } + + @Override + public void closePrevious(final boolean finishSpan) {} + + @Override + public AgentScope activateNext(final AgentSpan span) { + return NoopAgentScope.INSTANCE; + } + + @Override + public AgentSpan activeSpan() { + return NoopAgentSpan.INSTANCE; + } + + @Override + public AgentScope activeScope() { + return null; + } + + @Override + public AgentPropagation propagate() { + return NoopAgentPropagation.INSTANCE; + } + + @Override + public AgentSpan noopSpan() { + return NoopAgentSpan.INSTANCE; + } + + @Override + public SpanBuilder buildSpan(final String instrumentationName, final CharSequence spanName) { + return null; + } + + @Override + public void close() {} + + @Override + public void addScopeListener( + Runnable afterScopeActivatedCallback, Runnable afterScopeClosedCallback) {} + + @Override + public void flush() {} + + @Override + public void flushMetrics() {} + + @Override + public ProfilingContextIntegration getProfilingContext() { + return ProfilingContextIntegration.NoOp.INSTANCE; + } + + @Override + public TraceSegment getTraceSegment() { + return null; + } + + @Override + public String getTraceId() { + return null; + } + + @Override + public String getSpanId() { + return null; + } + + @Override + public String getTraceId(AgentSpan span) { + return null; + } + + @Override + public String getSpanId(AgentSpan span) { + return null; + } + + @Override + public boolean addTraceInterceptor(final TraceInterceptor traceInterceptor) { + return false; + } + + @Override + public DataStreamsCheckpointer getDataStreamsCheckpointer() { + return getDataStreamsMonitoring(); + } + + @Override + public void addScopeListener(final ScopeListener listener) {} + + @Override + public void registerCheckpointer(EndpointCheckpointer checkpointer) {} + + @Override + public void registerTimer(Timer timer) {} + + @Override + public SubscriptionService getSubscriptionService(RequestContextSlot slot) { + return SubscriptionService.SubscriptionServiceNoop.INSTANCE; + } + + @Override + public CallbackProvider getCallbackProvider(RequestContextSlot slot) { + return CallbackProvider.CallbackProviderNoop.INSTANCE; + } + + @Override + public CallbackProvider getUniversalCallbackProvider() { + return CallbackProvider.CallbackProviderNoop.INSTANCE; + } + + @Override + public void onRootSpanFinished(AgentSpan root, EndpointTracker tracker) {} + + @Override + public EndpointTracker onRootSpanStarted(AgentSpan root) { + return EndpointTracker.NO_OP; + } + + @Override + public Context notifyExtensionStart(Object event) { + return null; + } + + @Override + public void notifyExtensionEnd(AgentSpan span, Object result, boolean isError) {} + + @Override + public ScopeState newScopeState() { + return null; + } + + @Override + public AgentDataStreamsMonitoring getDataStreamsMonitoring() { + return NoopAgentDataStreamsMonitoring.INSTANCE; + } + + @Override + public Timer getTimer() { + return Timer.NoOp.INSTANCE; + } + + @Override + public TraceConfig captureTraceConfig() { + return NoopTraceConfig.INSTANCE; + } + + @Override + public AgentHistogram newHistogram(double relativeAccuracy, int maxNumBins) { + return NoopAgentHistogram.INSTANCE; + } + } + + public static final class NoopAgentSpan implements AgentSpan { + public static final NoopAgentSpan INSTANCE = new NoopAgentSpan(); + + private NoopAgentSpan() {} + + @Override + public DDTraceId getTraceId() { + return DDTraceId.ZERO; + } + + @Override + public long getSpanId() { + return DDSpanId.ZERO; + } + + @Override + public AgentSpan setTag(final String key, final boolean value) { + return this; + } + + @Override + public void setRequestBlockingAction(Flow.Action.RequestBlockingAction rba) {} + + @Override + public Flow.Action.RequestBlockingAction getRequestBlockingAction() { + return null; + } + + @Override + public AgentSpan setTag(final String tag, final Number value) { + return this; + } + + @Override + public boolean isError() { + return false; + } + + @Override + public AgentSpan setTag(final String key, final int value) { + return this; + } + + @Override + public AgentSpan setTag(final String key, final long value) { + return this; + } + + @Override + public AgentSpan setTag(final String key, final double value) { + return this; + } + + @Override + public AgentSpan setTag(final String key, final Object value) { + return this; + } + + @Override + public AgentSpan setMetric(final CharSequence key, final int value) { + return this; + } + + @Override + public AgentSpan setMetric(final CharSequence key, final long value) { + return this; + } + + @Override + public AgentSpan setMetric(final CharSequence key, final double value) { + return this; + } + + @Override + public Object getTag(final String key) { + return null; + } + + @Override + public long getStartTime() { + return 0; + } + + @Override + public long getDurationNano() { + return 0; + } + + @Override + public String getOperationName() { + return null; + } + + @Override + public AgentSpan setOperationName(final CharSequence serviceName) { + return this; + } + + @Override + public String getServiceName() { + return null; + } + + @Override + public AgentSpan setServiceName(final String serviceName) { + return this; + } + + @Override + public CharSequence getResourceName() { + return null; + } + + @Override + public AgentSpan setResourceName(final CharSequence resourceName) { + return this; + } + + @Override + public AgentSpan setResourceName(final CharSequence resourceName, byte priority) { + return this; + } + + @Override + public boolean eligibleForDropping() { + return true; + } + + @Override + public RequestContext getRequestContext() { + return RequestContext.Noop.INSTANCE; + } + + @Override + public Integer forceSamplingDecision() { + return null; + } + + @Override + public AgentSpan setSamplingPriority(int newPriority, int samplingMechanism) { + return this; + } + + @Override + public Integer getSamplingPriority() { + return (int) PrioritySampling.UNSET; + } + + @Override + public AgentSpan setSamplingPriority(final int newPriority) { + return this; + } + + @Override + public String getSpanType() { + return null; + } + + @Override + public AgentSpan setSpanType(final CharSequence type) { + return this; + } + + @Override + public Map getTags() { + return Collections.emptyMap(); + } + + @Override + public AgentSpan setTag(final String key, final String value) { + return this; + } + + @Override + public AgentSpan setTag(final String key, final CharSequence value) { + return this; + } + + @Override + public AgentSpan setError(final boolean error) { + return this; + } + + @Override + public AgentSpan setError(boolean error, byte priority) { + return this; + } + + @Override + public AgentSpan setMeasured(boolean measured) { + return this; + } + + @Override + public AgentSpan getRootSpan() { + return this; + } + + @Override + public AgentSpan setErrorMessage(final String errorMessage) { + return this; + } + + @Override + public AgentSpan addThrowable(final Throwable throwable) { + return this; + } + + @Override + public AgentSpan addThrowable(Throwable throwable, byte errorPriority) { + return this; + } + + @Override + public AgentSpan setHttpStatusCode(int statusCode) { + return this; + } + + @Override + public short getHttpStatusCode() { + return 0; + } + + @Override + public AgentSpan getLocalRootSpan() { + return this; + } + + @Override + public boolean isSameTrace(final AgentSpan otherSpan) { + // FIXME [API] AgentSpan or AgentSpan.Context should have a "getTraceId()" type method + // Not sure if this is the best idea... + return otherSpan == INSTANCE; + } + + @Override + public Context context() { + return NoopContext.INSTANCE; + } + + @Override + public String getBaggageItem(final String key) { + return null; + } + + @Override + public AgentSpan setBaggageItem(final String key, final String value) { + return this; + } + + @Override + public void finish() {} + + @Override + public void finish(final long finishMicros) {} + + @Override + public void finishWithDuration(final long durationNanos) {} + + @Override + public void beginEndToEnd() {} + + @Override + public void finishWithEndToEnd() {} + + @Override + public boolean phasedFinish() { + return false; + } + + @Override + public void publish() {} + + @Override + public String getSpanName() { + return ""; + } + + @Override + public void setSpanName(final CharSequence spanName) {} + + @Override + public boolean hasResourceName() { + return false; + } + + @Override + public byte getResourceNamePriority() { + return Byte.MAX_VALUE; + } + + @Override + public TraceConfig traceConfig() { + return NoopTraceConfig.INSTANCE; + } + + @Override + public void addLink(AgentSpanLink link) {} + } + + public static final class NoopAgentScope implements AgentScope { + public static final NoopAgentScope INSTANCE = new NoopAgentScope(); + + private NoopAgentScope() {} + + @Override + public AgentSpan span() { + return NoopAgentSpan.INSTANCE; + } + + @Override + public byte source() { + return 0; + } + + @Override + public void setAsyncPropagation(final boolean value) {} + + @Override + public Continuation capture() { + return NoopContinuation.INSTANCE; + } + + @Override + public Continuation captureConcurrent() { + return NoopContinuation.INSTANCE; + } + + @Override + public void close() {} + + @Override + public boolean isAsyncPropagating() { + return false; + } + } + + static class NoopAgentPropagation implements AgentPropagation { + static final NoopAgentPropagation INSTANCE = new NoopAgentPropagation(); + + @Override + public void inject(final AgentSpan span, final C carrier, final Setter setter) {} + + @Override + public void inject(final Context context, final C carrier, final Setter setter) {} + + @Override + public void inject( + AgentSpan span, C carrier, Setter setter, TracePropagationStyle style) {} + + @Override + public void injectPathwayContext( + AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags) {} + + @Override + public void injectPathwayContext( + AgentSpan span, + C carrier, + Setter setter, + LinkedHashMap sortedTags, + long defaultTimestamp, + long payloadSizeBytes) {} + + @Override + public void injectPathwayContextWithoutSendingStats( + AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags) {} + + @Override + public Context.Extracted extract(final C carrier, final ContextVisitor getter) { + return NoopContext.INSTANCE; + } + } + + static class NoopContinuation implements AgentScope.Continuation { + static final NoopContinuation INSTANCE = new NoopContinuation(); + + @Override + public AgentScope activate() { + return NoopAgentScope.INSTANCE; + } + + @Override + public void cancel() {} + + @Override + public AgentSpan getSpan() { + return NoopAgentSpan.INSTANCE; + } + } + + public static final class NoopContext implements Context.Extracted { + public static final NoopContext INSTANCE = new NoopContext(); + + private NoopContext() {} + + @Override + public DDTraceId getTraceId() { + return DDTraceId.ZERO; + } + + @Override + public long getSpanId() { + return DDSpanId.ZERO; + } + + @Override + public AgentTrace getTrace() { + return NoopAgentTrace.INSTANCE; + } + + @Override + public int getSamplingPriority() { + return PrioritySampling.UNSET; + } + + @Override + public Iterable> baggageItems() { + return emptyList(); + } + + @Override + public PathwayContext getPathwayContext() { + return NoopPathwayContext.INSTANCE; + } + + @Override + public List getTerminatedContextLinks() { + return emptyList(); + } + + @Override + public String getForwarded() { + return null; + } + + @Override + public String getFastlyClientIp() { + return null; + } + + @Override + public String getCfConnectingIp() { + return null; + } + + @Override + public String getCfConnectingIpv6() { + return null; + } + + @Override + public String getXForwardedProto() { + return null; + } + + @Override + public String getXForwardedHost() { + return null; + } + + @Override + public String getXForwardedPort() { + return null; + } + + @Override + public String getForwardedFor() { + return null; + } + + @Override + public String getXForwarded() { + return null; + } + + @Override + public String getXForwardedFor() { + return null; + } + + @Override + public String getXClusterClientIp() { + return null; + } + + @Override + public String getXRealIp() { + return null; + } + + @Override + public String getXClientIp() { + return null; + } + + @Override + public String getUserAgent() { + return null; + } + + @Override + public String getTrueClientIp() { + return null; + } + + @Override + public String getCustomIpHeader() { + return null; + } + } + + public static class NoopAgentTrace implements AgentTrace { + public static final NoopAgentTrace INSTANCE = new NoopAgentTrace(); + + @Override + public void registerContinuation(final AgentScope.Continuation continuation) {} + + @Override + public void cancelContinuation(final AgentScope.Continuation continuation) {} + } + + public static class NoopAgentDataStreamsMonitoring implements AgentDataStreamsMonitoring { + public static final NoopAgentDataStreamsMonitoring INSTANCE = + new NoopAgentDataStreamsMonitoring(); + + @Override + public void trackBacklog(LinkedHashMap sortedTags, long value) {} + + @Override + public void setCheckpoint( + AgentSpan span, + LinkedHashMap sortedTags, + long defaultTimestamp, + long payloadSizeBytes) {} + + @Override + public PathwayContext newPathwayContext() { + return NoopPathwayContext.INSTANCE; + } + + @Override + public void add(StatsPoint statsPoint) {} + + @Override + public int shouldSampleSchema(String topic) { + return 0; + } + + @Override + public void setConsumeCheckpoint( + String type, String source, DataStreamsContextCarrier carrier) {} + + @Override + public void setProduceCheckpoint( + String type, String target, DataStreamsContextCarrier carrier) {} + } + + public static class NoopPathwayContext implements PathwayContext { + public static final NoopPathwayContext INSTANCE = new NoopPathwayContext(); + + @Override + public boolean isStarted() { + return false; + } + + @Override + public long getHash() { + return 0L; + } + + @Override + public void setCheckpoint( + LinkedHashMap sortedTags, + Consumer pointConsumer, + long defaultTimestamp, + long payloadSizeBytes) {} + + @Override + public void setCheckpoint( + LinkedHashMap sortedTags, + Consumer pointConsumer, + long defaultTimestamp) {} + + @Override + public void setCheckpoint( + LinkedHashMap sortedTags, Consumer pointConsumer) {} + + @Override + public void saveStats(StatsPoint point) {} + + @Override + public StatsPoint getSavedStats() { + return null; + } + + @Override + public byte[] encode() { + return null; + } + + @Override + public String strEncode() { + return null; + } + } + + public static class NoopAgentHistogram implements AgentHistogram { + public static final NoopAgentHistogram INSTANCE = new NoopAgentHistogram(); + + @Override + public double getCount() { + return 0; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public void accept(double value) {} + + @Override + public void accept(double value, double count) {} + + @Override + public double getValueAtQuantile(double quantile) { + return 0; + } + + @Override + public double getMinValue() { + return 0; + } + + @Override + public double getMaxValue() { + return 0; + } + + @Override + public void clear() {} + + @Override + public ByteBuffer serialize() { + return null; + } + } + + /** TraceConfig when there is no tracer; this is not the same as a default config. */ + public static final class NoopTraceConfig implements TraceConfig { + public static final NoopTraceConfig INSTANCE = new NoopTraceConfig(); + + @Override + public boolean isRuntimeMetricsEnabled() { + return false; + } + + @Override + public boolean isLogsInjectionEnabled() { + return false; + } + + @Override + public boolean isDataStreamsEnabled() { + return false; + } + + @Override + public Map getServiceMapping() { + return Collections.emptyMap(); + } + + @Override + public Map getRequestHeaderTags() { + return Collections.emptyMap(); + } + + @Override + public Map getResponseHeaderTags() { + return Collections.emptyMap(); + } + + @Override + public Map getBaggageMapping() { + return Collections.emptyMap(); + } + + @Override + public Double getTraceSampleRate() { + return null; + } + + @Override + public List getSpanSamplingRules() { + return Collections.emptyList(); + } + + @Override + public List getTraceSamplingRules() { + return Collections.emptyList(); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java new file mode 100644 index 0000000000..685562807d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java @@ -0,0 +1,15 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** Cache interface for OT/OTel wrappers used by TypeConverters to avoid extra allocations. */ +public interface AttachableWrapper { + + /** Attaches a OT/OTel wrapper to a tracer object. */ + void attachWrapper(@NonNull Object wrapper); + + /** Returns an attached OT/OTel wrapper or null. */ + @Nullable + Object getWrapper(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Backlog.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Backlog.java new file mode 100644 index 0000000000..333a43f6e8 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Backlog.java @@ -0,0 +1,30 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.util.List; + +// Backlog allows us to track the size of a queue in data streams. For example, by monitoring both +// the consumer and the producer, +// we can get the size in bytes of a Kafka queue. +public class Backlog implements InboxItem { + public List getSortedTags() { + return sortedTags; + } + + public long getValue() { + return value; + } + + public long getTimestampNanos() { + return timestampNanos; + } + + private final List sortedTags; + private final long value; + private final long timestampNanos; + + public Backlog(List sortedTags, long value, long timestampNanos) { + this.sortedTags = sortedTags; + this.value = value; + this.timestampNanos = timestampNanos; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java new file mode 100644 index 0000000000..3e48582a1c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java @@ -0,0 +1,8 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public class ErrorPriorities { + public static final byte UNSET = Byte.MIN_VALUE; + public static final byte HTTP_SERVER_DECORATOR = -1; + + public static final byte DEFAULT = 0; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InboxItem.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InboxItem.java new file mode 100644 index 0000000000..1f56183e41 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InboxItem.java @@ -0,0 +1,3 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public interface InboxItem {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java new file mode 100644 index 0000000000..5a2f96fd7c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java @@ -0,0 +1,114 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public class InstrumentationTags { + + // this exists to make it easy to intern UTF-8 encoding + // of tag/metric keys used in instrumentations. It should + // stay reasonably small. TODO when/if this gets large + // start looking at generating constants based on the + // enabled instrumentations. + + public static final String PARTITION = "partition"; + public static final String OFFSET = "offset"; + public static final String CONSUMER_GROUP = "kafka.group"; + public static final String PROCESSOR_NAME = "processor.name"; + public static final String RECORD_QUEUE_TIME_MS = "record.queue_time_ms"; + public static final String RECORD_END_TO_END_DURATION_MS = "record.e2e_duration_ms"; + public static final String TOMBSTONE = "tombstone"; + public static final String AWS_AGENT = "aws.agent"; + public static final String AWS_SERVICE = "aws.service"; + public static final String TOP_LEVEL_AWS_SERVICE = "aws_service"; + public static final String AWS_OPERATION = "aws.operation"; + public static final String AWS_ENDPOINT = "aws.endpoint"; + public static final String AWS_BUCKET_NAME = "aws.bucket.name"; + public static final String BUCKET_NAME = "bucketname"; + public static final String AWS_QUEUE_URL = "aws.queue.url"; + + public static final String AWS_QUEUE_NAME = "aws.queue.name"; + public static final String QUEUE_NAME = "queuename"; + public static final String AWS_TOPIC_NAME = "aws.topic.name"; + public static final String TOPIC_NAME = "topicname"; + public static final String AWS_STREAM_NAME = "aws.stream.name"; + public static final String STREAM_NAME = "streamname"; + public static final String AWS_TABLE_NAME = "aws.table.name"; + public static final String TABLE_NAME = "tablename"; + public static final String AWS_REQUEST_ID = "aws.requestId"; + public static final String AWS_STORAGE_CLASS = "aws.storage.class"; + + public static final String BUCKET = "bucket"; + public static final String CASSANDRA_CONTACT_POINTS = "db.cassandra.contact.points"; + public static final String COUCHBASE_OPERATION_ID = "couchbase.operation_id"; + public static final String COUCHBASE_SEED_NODES = "db.couchbase.seed.nodes"; + public static final String ELASTICSEARCH_REQUEST_INDICES = "elasticsearch.request.indices"; + public static final String ELASTICSEARCH_REQUEST_SEARCH_TYPES = + "elasticsearch.request.search.types"; + public static final String ELASTICSEARCH_REQUEST_WRITE_TYPE = "elasticsearch.request.write.type"; + public static final String ELASTICSEARCH_REQUEST_WRITE_ROUTING = + "elasticsearch.request.write.routing"; + public static final String ELASTICSEARCH_REQUEST_WRITE_VERSION = + "elasticsearch.request.write.version"; + public static final String ELASTICSEARCH_TYPE = "elasticsearch.type"; + public static final String ELASTICSEARCH_ID = "elasticsearch.id"; + public static final String ELASTICSEARCH_VERSION = "elasticsearch.version"; + public static final String ELASTICSEARCH_SHARD_BROADCAST_TOTAL = + "elasticsearch.shard.broadcast.total"; + public static final String ELASTICSEARCH_SHARD_BROADCAST_SUCCESSFUL = + "elasticsearch.shard.broadcast.successful"; + public static final String ELASTICSEARCH_SHARD_BROADCAST_FAILED = + "elasticsearch.shard.broadcast.failed"; + public static final String ELASTICSEARCH_SHARD_BULK_ID = "elasticsearch.shard.bulk.id"; + public static final String ELASTICSEARCH_SHARD_BULK_INDEX = "elasticsearch.shard.bulk.index"; + public static final String ELASTICSEARCH_NODE_FAILURES = "elasticsearch.node.failures"; + public static final String ELASTICSEARCH_NODE_CLUSTER_NAME = "elasticsearch.node.cluster.name"; + public static final String ELASTICSEARCH_SHARD_REPLICATION_TOTAL = + "elasticsearch.shard.replication.total"; + public static final String ELASTICSEARCH_SHARD_REPLICATION_FAILED = + "elasticsearch.shard.replication.failed"; + public static final String ELASTICSEARCH_RESPONSE_STATUS = "elasticsearch.response.status"; + public static final String STATUS_CODE = "status.code"; + public static final String STATUS_DESCRIPTION = "status.description"; + public static final String MESSAGE_TYPE = "message.type"; + public static final String MESSAGE_SIZE = "message.size"; + public static final String HYSTRIX_COMMAND = "hystrix.command"; + public static final String HYSTRIX_CIRCUIT_OPEN = "hystrix.circuit-open"; + public static final String HYSTRIX_GROUP = "hystrix.group"; + public static final String SERVLET_CONTEXT = "servlet.context"; + public static final String SERVLET_PATH = "servlet.path"; + public static final String SERVLET_DISPATCH = "servlet.dispatch"; + public static final String TIMEOUT = "timeout"; + public static final String JMS_PRODUCE = "jms.produce"; + public static final String JSP_COMPILER = "jsp.compiler"; + public static final String JSP_CLASSFQCN = "jsp.classFQCN"; + public static final String JSP_FORWARD_ORIGIN = "jsp.forwardOrigin"; + public static final String DB_REDIS_DBINDEX = "db.redis.dbIndex"; + public static final String DB_COMMAND_CANCELLED = "db.command.cancelled"; + public static final String DB_COMMAND_RESULTS_COUNT = "db.command.results.count"; + public static final String AMQP_DELIVERY_MODE = "amqp.delivery_mode"; + public static final String AMQP_COMMAND = "amqp.command"; + public static final String AMQP_EXCHANGE = "amqp.exchange"; + public static final String AMQP_ROUTING_KEY = "amqp.routing_key"; + public static final String AMQP_QUEUE = "amqp.queue"; + public static final String EVENT = "event"; + public static final String MESSAGE = "message"; + public static final String HANDLER_TYPE = "handler.type"; + public static final String KAFKA_BOOTSTRAP_SERVERS = "messaging.kafka.bootstrap.servers"; + public static final String QUARTZ_JOB_NAME = "quartz.job.name"; + public static final String QUARTZ_JOB_GROUP = "quartz.job.group"; + public static final String QUARTZ_TRIGGER_NAME = "quartz.trigger.name"; + public static final String QUARTZ_TRIGGER_GROUP = "quartz.trigger.group"; + public static final String REQUEST_PREDICATE = "request.predicate"; + public static final String VIEW_NAME = "view.name"; + public static final String VIEW_TYPE = "view.type"; + public static final String TWILIO_TYPE = "twilio.type"; + public static final String TWILIO_ACCOUNT = "twilio.account"; + public static final String TWILIO_SID = "twilio.sid"; + public static final String TWILIO_STATUS = "twilio.status"; + public static final String TWILIO_PARENT_SID = "twilio.parentSid"; + public static final String DBM_TRACE_INJECTED = "_dd.dbm_trace_injected"; + public static final UTF8BytesString DD_MEASURED = UTF8BytesString.create("_dd.measured"); + public static final UTF8BytesString DD_TOP_LEVEL = UTF8BytesString.create("_dd.top_level"); + public static final UTF8BytesString DD_PARTIAL_VERSION = + UTF8BytesString.create("_dd.partial_version"); + public static final UTF8BytesString DD_WAS_LONG_RUNNING = + UTF8BytesString.create("_dd.was_long_running"); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java new file mode 100644 index 0000000000..918f9bd759 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java @@ -0,0 +1,47 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import datadog.trace.api.DDSpanTypes; + +public class InternalSpanTypes { + public static final CharSequence HTTP_CLIENT = UTF8BytesString.create(DDSpanTypes.HTTP_CLIENT); + public static final CharSequence HTTP_SERVER = UTF8BytesString.create(DDSpanTypes.HTTP_SERVER); + public static final CharSequence RPC = UTF8BytesString.create(DDSpanTypes.RPC); + public static final CharSequence CACHE = UTF8BytesString.create(DDSpanTypes.CACHE); + public static final CharSequence SOAP = UTF8BytesString.create(DDSpanTypes.SOAP); + + public static final CharSequence SQL = UTF8BytesString.create(DDSpanTypes.SQL); + public static final CharSequence MONGO = UTF8BytesString.create(DDSpanTypes.MONGO); + public static final CharSequence CASSANDRA = UTF8BytesString.create(DDSpanTypes.CASSANDRA); + public static final CharSequence COUCHBASE = + UTF8BytesString.create(DDSpanTypes.COUCHBASE); // Using generic for now. + public static final CharSequence REDIS = UTF8BytesString.create(DDSpanTypes.REDIS); + public static final CharSequence MEMCACHED = UTF8BytesString.create(DDSpanTypes.MEMCACHED); + public static final CharSequence ELASTICSEARCH = + UTF8BytesString.create(DDSpanTypes.ELASTICSEARCH); + public static final CharSequence OPENSEARCH = UTF8BytesString.create(DDSpanTypes.OPENSEARCH); + public static final CharSequence HIBERNATE = UTF8BytesString.create(DDSpanTypes.HIBERNATE); + public static final CharSequence AEROSPIKE = UTF8BytesString.create(DDSpanTypes.AEROSPIKE); + public static final CharSequence DATANUCLEUS = UTF8BytesString.create(DDSpanTypes.DATANUCLEUS); + + // these are all the same thing but don't want to be taken by surprise by changes in DDSpanTypes + public static final CharSequence MESSAGE_CLIENT = + UTF8BytesString.create(DDSpanTypes.MESSAGE_CLIENT); + public static final CharSequence MESSAGE_CONSUMER = + UTF8BytesString.create(DDSpanTypes.MESSAGE_CONSUMER); + public static final CharSequence MESSAGE_PRODUCER = + UTF8BytesString.create(DDSpanTypes.MESSAGE_PRODUCER); + public static final CharSequence MESSAGE_BROKER = + UTF8BytesString.create(DDSpanTypes.MESSAGE_BROKER); + + public static final CharSequence GRAPHQL = UTF8BytesString.create(DDSpanTypes.GRAPHQL); + + public static final UTF8BytesString TEST = UTF8BytesString.create(DDSpanTypes.TEST); + public static final UTF8BytesString TEST_SUITE_END = + UTF8BytesString.create(DDSpanTypes.TEST_SUITE_END); + public static final UTF8BytesString TEST_MODULE_END = + UTF8BytesString.create(DDSpanTypes.TEST_MODULE_END); + public static final UTF8BytesString TEST_SESSION_END = + UTF8BytesString.create(DDSpanTypes.TEST_SESSION_END); + public static final UTF8BytesString VULNERABILITY = + UTF8BytesString.create(DDSpanTypes.VULNERABILITY); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java new file mode 100644 index 0000000000..b9cd729fc1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java @@ -0,0 +1,37 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.function.Consumer; + +public interface PathwayContext { + String PROPAGATION_KEY = "dd-pathway-ctx"; + String PROPAGATION_KEY_BASE64 = "dd-pathway-ctx-base64"; + String DATADOG_KEY = "_datadog"; + + boolean isStarted(); + + long getHash(); + + void setCheckpoint( + LinkedHashMap sortedTags, + Consumer pointConsumer, + long defaultTimestamp, + long payloadSizeBytes); + + void setCheckpoint( + LinkedHashMap sortedTags, + Consumer pointConsumer, + long defaultTimestamp); + + // The input tags should be sorted. + void setCheckpoint(LinkedHashMap sortedTags, Consumer pointConsumer); + + void saveStats(StatsPoint point); + + StatsPoint getSavedStats(); + + byte[] encode() throws IOException; + + String strEncode() throws IOException; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java new file mode 100644 index 0000000000..1001b1c0a8 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java @@ -0,0 +1,17 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public interface ProfilerContext { + + long getSpanId(); + + /** @return the span id of the local root span, or the span itself */ + long getRootSpanId(); + + int getEncodedOperationName(); + + CharSequence getOperationName(); + + int getEncodedResourceName(); + + CharSequence getResourceName(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java new file mode 100644 index 0000000000..303411289c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java @@ -0,0 +1,64 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import datadog.trace.api.Stateful; +import datadog.trace.api.profiling.Profiling; +import datadog.trace.api.profiling.ProfilingContextAttribute; +import datadog.trace.api.profiling.ProfilingScope; + +public interface ProfilingContextIntegration extends Profiling { + /** + * invoked when the profiler is started, implementations must not initialise JFR before this is + * called. + */ + default void onStart() {} + /** Invoked when a trace first propagates to a thread */ + default void onAttach() {} + + /** Invoked when a thread exits */ + default void onDetach() {} + + default Stateful newScopeState(ProfilerContext profilerContext) { + return Stateful.DEFAULT; + } + + default int encode(CharSequence constant) { + return 0; + } + + default int encodeOperationName(CharSequence constant) { + return 0; + } + + default int encodeResourceName(CharSequence constant) { + return 0; + } + + String name(); + + final class NoOp implements ProfilingContextIntegration { + + public static final ProfilingContextIntegration INSTANCE = + new ProfilingContextIntegration.NoOp(); + + @Override + public ProfilingContextAttribute createContextAttribute(String attribute) { + return ProfilingContextAttribute.NoOp.INSTANCE; + } + + @Override + public ProfilingScope newScope() { + return ProfilingScope.NO_OP; + } + + @Override + public void onAttach() {} + + @Override + public void onDetach() {} + + @Override + public String name() { + return "none"; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java new file mode 100644 index 0000000000..dddeabaf0e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java @@ -0,0 +1,13 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public class ResourceNamePriorities { + public static final byte DEFAULT = 0; + public static final byte HTTP_PATH_NORMALIZER = 1; + public static final byte HTTP_404 = 2; + public static final byte HTTP_FRAMEWORK_ROUTE = 3; + public static final byte RPC_COMMAND_NAME = 3; + public static final byte HTTP_SERVER_CONFIG_PATTERN_MATCH = 4; + public static final byte HTTP_CLIENT_CONFIG_PATTERN_MATCH = 4; + public static final byte TAG_INTERCEPTOR = 5; + public static final byte MANUAL_INSTRUMENTATION = 6; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java new file mode 100644 index 0000000000..eae61cdc31 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java @@ -0,0 +1,9 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public class SamplerConstants { + + public static final String KEEP = "keep"; + public static final String DROP = "drop"; + + private SamplerConstants() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java new file mode 100644 index 0000000000..b801c83273 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java @@ -0,0 +1,17 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public enum ScopeSource { + INSTRUMENTATION((byte) 0), + MANUAL((byte) 1), + ITERATION((byte) 2); + + private final byte id; + + ScopeSource(byte id) { + this.id = id; + } + + public byte id() { + return id; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeState.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeState.java new file mode 100644 index 0000000000..5e715cc354 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeState.java @@ -0,0 +1,7 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public interface ScopeState { + void activate(); + + void fetchFromActive(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java new file mode 100644 index 0000000000..977afc1184 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java @@ -0,0 +1,5 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public interface ScopeStateAware { + ScopeState newScopeState(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLink.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLink.java new file mode 100644 index 0000000000..4a0e28b272 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLink.java @@ -0,0 +1,95 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import static datadog.trace.bootstrap.instrumentation.api.SpanLinkAttributes.EMPTY; + +import datadog.trace.api.DDTraceId; + +/** This class is a base implementation of {@link AgentSpanLink}. */ +public class SpanLink implements AgentSpanLink { + private final DDTraceId traceId; + private final long spanId; + private final byte traceFlags; + private final String traceState; + private final Attributes attributes; + + protected SpanLink( + DDTraceId traceId, long spanId, byte traceFlags, String traceState, Attributes attributes) { + this.traceId = traceId; + this.spanId = spanId; + this.traceFlags = traceFlags; + this.traceState = traceState; + this.attributes = attributes; + } + + /** + * Creates a span link from a span context. Gathers the trace and span identifiers from the given + * instance. + * + * @param context The context of the span to get the link to. + * @return A span link to the given context. + */ + public static SpanLink from(AgentSpan.Context context) { + return from(context, DEFAULT_FLAGS, "", EMPTY); + } + + /** + * Creates a span link from a span context with W3C trace state and custom attributes. Gathers the + * trace and span identifiers from the given instance. + * + * @param context The context of the span to get the link to. + * @param traceFlags The W3C formatted trace flags. + * @param traceState The W3C formatted trace state. + * @param attributes The link attributes. + * @return A span link to the given context. + */ + public static SpanLink from( + AgentSpan.Context context, byte traceFlags, String traceState, Attributes attributes) { + if (context.getSamplingPriority() > 0) { + traceFlags = (byte) (traceFlags | SAMPLED_FLAG); + } + return new SpanLink( + context.getTraceId(), context.getSpanId(), traceFlags, traceState, attributes); + } + + @Override + public DDTraceId traceId() { + return this.traceId; + } + + @Override + public long spanId() { + return this.spanId; + } + + @Override + public byte traceFlags() { + return this.traceFlags; + } + + @Override + public String traceState() { + return this.traceState; + } + + @Override + public Attributes attributes() { + return this.attributes; + } + + @Override + public String toString() { + return "SpanLink{" + + "traceId=" + + this.traceId + + ", spanId=" + + this.spanId + + ", traceFlags=" + + this.traceFlags + + ", traceState='" + + this.traceState + + '\'' + + ", attributes=" + + this.attributes + + '}'; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java new file mode 100644 index 0000000000..87a2ce05f6 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java @@ -0,0 +1,122 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import static java.util.Objects.requireNonNull; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** This class is a base implementation of {@link AgentSpanLink.Attributes}. */ +public class SpanLinkAttributes implements AgentSpanLink.Attributes { + /** An empty span links attributes. */ + public static final AgentSpanLink.Attributes EMPTY = + new SpanLinkAttributes(Collections.emptyMap()); + + private final Map attributes; + + protected SpanLinkAttributes(Map attributes) { + this.attributes = attributes; + } + + /** + * Gets a builder to create span link attributes. + * + * @return A builder to create span link attributes. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Create span link attributes from its map representation. + * + * @param map A map representing the span link attributes. + * @return The related span link attributes. + */ + public static SpanLinkAttributes fromMap(Map map) { + return new SpanLinkAttributes(new HashMap<>(map)); + } + + @Override + public Map asMap() { + return this.attributes; + } + + @Override + public boolean isEmpty() { + return this.attributes.isEmpty(); + } + + @Override + public String toString() { + return "SpanLinkAttributes{" + this.attributes + '}'; + } + + public static class Builder { + private final Map attributes; + + protected Builder() { + this.attributes = new HashMap<>(); + } + + public Builder put(String key, String value) { + requireNonNull(key, "key must not be null"); + if (value != null) { + this.attributes.put(key, value); + } + return this; + } + + public Builder put(String key, boolean value) { + requireNonNull(key, "key must not be null"); + this.attributes.put(key, Boolean.toString(value)); + return this; + } + + public Builder put(String key, long value) { + requireNonNull(key, "key must not be null"); + this.attributes.put(key, Long.toString(value)); + return this; + } + + public Builder put(String key, double value) { + requireNonNull(key, "key must not be null"); + this.attributes.put(key, Double.toString(value)); + return this; + } + + public Builder putStringArray(String key, List array) { + return putArray(key, array); + } + + public Builder putBooleanArray(String key, List array) { + return putArray(key, array); + } + + public Builder putLongArray(String key, List array) { + return putArray(key, array); + } + + public Builder putDoubleArray(String key, List array) { + return putArray(key, array); + } + + protected Builder putArray(String key, List array) { + requireNonNull(key, "key must not be null"); + if (array != null) { + for (int index = 0; index < array.size(); index++) { + Object value = array.get(index); + if (value != null) { + this.attributes.put(key + "." + index, value.toString()); + } + } + } + return this; + } + + public AgentSpanLink.Attributes build() { + return new SpanLinkAttributes(this.attributes); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java new file mode 100644 index 0000000000..caa6540699 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java @@ -0,0 +1,79 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.util.List; + +public class StatsPoint implements InboxItem { + private final List edgeTags; + private final long hash; + private final long parentHash; + private final long timestampNanos; + private final long pathwayLatencyNano; + private final long edgeLatencyNano; + private final long payloadSizeBytes; + + public StatsPoint( + List edgeTags, + long hash, + long parentHash, + long timestampNanos, + long pathwayLatencyNano, + long edgeLatencyNano, + long payloadSizeBytes) { + this.edgeTags = edgeTags; + this.hash = hash; + this.parentHash = parentHash; + this.timestampNanos = timestampNanos; + this.pathwayLatencyNano = pathwayLatencyNano; + this.edgeLatencyNano = edgeLatencyNano; + this.payloadSizeBytes = payloadSizeBytes; + } + + public List getEdgeTags() { + return edgeTags; + } + + public long getHash() { + return hash; + } + + public long getParentHash() { + return parentHash; + } + + public long getTimestampNanos() { + return timestampNanos; + } + + public long getPathwayLatencyNano() { + return pathwayLatencyNano; + } + + public long getEdgeLatencyNano() { + return edgeLatencyNano; + } + + public long getPayloadSizeBytes() { + return payloadSizeBytes; + } + + @Override + public String toString() { + return "StatsPoint{" + + "tags='" + + edgeTags + + '\'' + + ", hash=" + + hash + + ", parentHash=" + + parentHash + + ", timestampNanos=" + + timestampNanos + + ", pathwayLatencyNano=" + + pathwayLatencyNano + + ", edgeLatencyNano=" + + edgeLatencyNano + + ", payloadSizeBytes=" + + payloadSizeBytes + + '}'; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TagContext.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TagContext.java new file mode 100644 index 0000000000..c76475a085 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TagContext.java @@ -0,0 +1,274 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import static java.util.Collections.emptyList; +import static datadog.trace.api.TracePropagationStyle.NONE; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.api.sampling.PrioritySampling; + +/** + * When calling extract, we allow for grabbing other configured headers as tags. Those tags are + * returned here even if the rest of the request would have returned null. + */ +public class TagContext implements AgentSpan.Context.Extracted { + + private static final HttpHeaders EMPTY_HTTP_HEADERS = new HttpHeaders(); + + private final CharSequence origin; + private final Map tags; + private List terminatedContextLinks; + private Object requestContextDataAppSec; + private Object requestContextDataIast; + private Object ciVisibilityContextData; + private PathwayContext pathwayContext; + private final HttpHeaders httpHeaders; + private final Map baggage; + private final int samplingPriority; + private final TraceConfig traceConfig; + private final TracePropagationStyle propagationStyle; + + public TagContext() { + this(null, null); + } + + public TagContext(final String origin, final Map tags) { + this(origin, tags, null, null, PrioritySampling.UNSET, null, NONE); + } + + public TagContext( + final CharSequence origin, + final Map tags, + final HttpHeaders httpHeaders, + final Map baggage, + final int samplingPriority, + final TraceConfig traceConfig, + final TracePropagationStyle propagationStyle) { + this.origin = origin; + this.tags = tags; + this.terminatedContextLinks = null; + this.httpHeaders = httpHeaders == null ? EMPTY_HTTP_HEADERS : httpHeaders; + this.baggage = baggage == null ? Collections.emptyMap() : baggage; + this.samplingPriority = samplingPriority; + this.traceConfig = traceConfig; + this.propagationStyle = propagationStyle; + } + + public TraceConfig getTraceConfig() { + return traceConfig; + } + + public TracePropagationStyle getPropagationStyle() { + return this.propagationStyle; + } + + public final CharSequence getOrigin() { + return origin; + } + + @Override + public List getTerminatedContextLinks() { + return this.terminatedContextLinks == null ? emptyList() : this.terminatedContextLinks; + } + + public void addTerminatedContextLink(AgentSpanLink link) { + if (this.terminatedContextLinks == null) { + this.terminatedContextLinks = new ArrayList<>(); + } + this.terminatedContextLinks.add(link); + } + + @Override + public String getForwarded() { + return httpHeaders.forwarded; + } + + @Override + public String getFastlyClientIp() { + return httpHeaders.fastlyClientIp; + } + + @Override + public String getCfConnectingIp() { + return httpHeaders.cfConnectingIp; + } + + @Override + public String getCfConnectingIpv6() { + return httpHeaders.cfConnectingIpv6; + } + + @Override + public String getXForwardedProto() { + return httpHeaders.xForwardedProto; + } + + @Override + public String getXForwardedHost() { + return httpHeaders.xForwardedHost; + } + + @Override + public String getXForwardedPort() { + return httpHeaders.xForwardedPort; + } + + @Override + public String getForwardedFor() { + return httpHeaders.forwardedFor; + } + + @Override + public String getXForwarded() { + return httpHeaders.xForwarded; + } + + @Override + public String getXForwardedFor() { + return httpHeaders.xForwardedFor; + } + + @Override + public String getXClusterClientIp() { + return httpHeaders.xClusterClientIp; + } + + @Override + public String getXRealIp() { + return httpHeaders.xRealIp; + } + + @Override + public String getXClientIp() { + return httpHeaders.xClientIp; + } + + @Override + public String getUserAgent() { + return httpHeaders.userAgent; + } + + @Override + public String getTrueClientIp() { + return httpHeaders.trueClientIp; + } + + @Override + public String getCustomIpHeader() { + return httpHeaders.customIpHeader; + } + + public final Map getTags() { + return tags; + } + + @Override + public final int getSamplingPriority() { + return samplingPriority; + } + + public final Map getBaggage() { + return baggage; + } + + @Override + public Iterable> baggageItems() { + return baggage.entrySet(); + } + + @Override + public DDTraceId getTraceId() { + return DDTraceId.ZERO; + } + + @Override + public long getSpanId() { + return DDSpanId.ZERO; + } + + @Override + public final AgentTrace getTrace() { + return AgentTracer.NoopAgentTrace.INSTANCE; + } + + public final Object getRequestContextDataAppSec() { + return requestContextDataAppSec; + } + + public final TagContext withRequestContextDataAppSec(Object requestContextData) { + this.requestContextDataAppSec = requestContextData; + return this; + } + + public final Object getRequestContextDataIast() { + return requestContextDataIast; + } + + public final TagContext withRequestContextDataIast(Object requestContextData) { + this.requestContextDataIast = requestContextData; + return this; + } + + public Object getCiVisibilityContextData() { + return ciVisibilityContextData; + } + + public TagContext withCiVisibilityContextData(Object ciVisibilityContextData) { + this.ciVisibilityContextData = ciVisibilityContextData; + return this; + } + + @Override + public PathwayContext getPathwayContext() { + return this.pathwayContext; + } + + public TagContext withPathwayContext(PathwayContext pathwayContext) { + this.pathwayContext = pathwayContext; + return this; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("TagContext{"); + if (origin != null) { + builder.append("origin=").append(origin).append(", "); + } + if (tags != null) { + builder.append("tags=").append(tags).append(", "); + } + if (baggage != null) { + builder.append("baggage=").append(baggage).append(", "); + } + if (samplingPriority != PrioritySampling.UNSET) { + builder.append("samplingPriority=").append(samplingPriority).append(", "); + } + return builder.append('}').toString(); + } + + public static class HttpHeaders { + public String fastlyClientIp; + public String cfConnectingIp; + public String cfConnectingIpv6; + public String xForwarded; + public String forwarded; + public String xForwardedProto; + public String xForwardedHost; + public String xForwardedPort; + public String xForwardedFor; + public String forwardedFor; + public String xClusterClientIp; + public String xRealIp; + public String xClientIp; + public String userAgent; + public String trueClientIp; + public String customIpHeader; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java new file mode 100644 index 0000000000..cfe43ff6df --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java @@ -0,0 +1,114 @@ +package datadog.trace.bootstrap.instrumentation.api; + +// standard tag names (and span kind values) from OpenTracing (see io.opentracing.tag.Tags) +public class Tags { + + public static final String SPAN_KIND_SERVER = "server"; + public static final String SPAN_KIND_CLIENT = "client"; + public static final String SPAN_KIND_PRODUCER = "producer"; + public static final String SPAN_KIND_CONSUMER = "consumer"; + public static final String SPAN_KIND_BROKER = "broker"; + public static final String SPAN_KIND_TEST = "test"; + public static final String SPAN_KIND_TEST_SUITE = "test_suite_end"; + public static final String SPAN_KIND_TEST_MODULE = "test_module_end"; + public static final String SPAN_KIND_TEST_SESSION = "test_session_end"; + + public static final String HTTP_URL = "http.url"; + public static final String HTTP_HOSTNAME = "http.hostname"; + public static final String HTTP_ROUTE = "http.route"; + public static final String HTTP_STATUS = "http.status_code"; + public static final String HTTP_METHOD = "http.method"; + public static final String HTTP_FORWARDED = "http.forwarded"; + public static final String HTTP_FORWARDED_PROTO = "http.forwarded.proto"; + public static final String HTTP_FORWARDED_HOST = "http.forwarded.host"; + public static final String HTTP_FORWARDED_IP = "http.forwarded.ip"; + public static final String HTTP_FORWARDED_PORT = "http.forwarded.port"; + public static final String HTTP_USER_AGENT = "http.useragent"; + public static final String HTTP_CLIENT_IP = "http.client_ip"; + public static final String PEER_HOST_IPV4 = "peer.ipv4"; + public static final String PEER_HOST_IPV6 = "peer.ipv6"; + public static final String PEER_SERVICE = "peer.service"; + public static final String PEER_HOSTNAME = "peer.hostname"; + public static final String PEER_PORT = "peer.port"; + public static final String RPC_SERVICE = "rpc.service"; + public static final String SAMPLING_PRIORITY = "sampling.priority"; + public static final String SPAN_KIND = "span.kind"; + public static final String COMPONENT = "component"; + public static final String ERROR = "error"; + public static final String DB_TYPE = "db.type"; + public static final String DB_INSTANCE = "db.instance"; + public static final String DB_USER = "db.user"; + public static final String DB_OPERATION = "db.operation"; + public static final String DB_STATEMENT = "db.statement"; + public static final String MESSAGE_BUS_DESTINATION = "message_bus.destination"; + + public static final String TEST_MODULE = "test.module"; + public static final String TEST_SUITE = "test.suite"; + public static final String TEST_NAME = "test.name"; + public static final String TEST_STATUS = "test.status"; + public static final String TEST_FRAMEWORK = "test.framework"; + public static final String TEST_FRAMEWORK_VERSION = "test.framework_version"; + public static final String TEST_SKIP_REASON = "test.skip_reason"; + public static final String TEST_SKIPPED_BY_ITR = "test.skipped_by_itr"; + public static final String TEST_TYPE = "test.type"; + public static final String TEST_PARAMETERS = "test.parameters"; + public static final String TEST_CODEOWNERS = "test.codeowners"; + public static final String TEST_SOURCE_FILE = "test.source.file"; + public static final String TEST_SOURCE_CLASS = "test.source.class"; + public static final String TEST_SOURCE_METHOD = "test.source.method"; + public static final String TEST_SOURCE_START = "test.source.start"; + public static final String TEST_SOURCE_END = "test.source.end"; + public static final String TEST_TRAITS = "test.traits"; + public static final String TEST_COMMAND = "test.command"; + public static final String TEST_TOOLCHAIN = "test.toolchain"; + public static final String TEST_EXECUTION = "test.execution"; + public static final String TEST_GRADLE_NESTED_BUILD = "test.gradle.nested_build"; + + public static final String TEST_SESSION_ID = "test_session_id"; + public static final String TEST_MODULE_ID = "test_module_id"; + public static final String TEST_SUITE_ID = "test_suite_id"; + public static final String TEST_CODE_COVERAGE_ENABLED = "test.code_coverage.enabled"; + public static final String TEST_CODE_COVERAGE_LINES_PERCENTAGE = "test.code_coverage.lines_pct"; + public static final String TEST_ITR_TESTS_SKIPPING_ENABLED = "test.itr.tests_skipping.enabled"; + public static final String TEST_ITR_TESTS_SKIPPING_TYPE = "test.itr.tests_skipping.type"; + public static final String TEST_ITR_TESTS_SKIPPING_COUNT = "test.itr.tests_skipping.count"; + public static final String TEST_ITR_UNSKIPPABLE = "test.itr.unskippable"; + public static final String TEST_ITR_FORCED_RUN = "test.itr.forced_run"; + + public static final String CI_PROVIDER_NAME = "ci.provider.name"; + public static final String CI_PIPELINE_ID = "ci.pipeline.id"; + public static final String CI_PIPELINE_NAME = "ci.pipeline.name"; + public static final String CI_PIPELINE_NUMBER = "ci.pipeline.number"; + public static final String CI_PIPELINE_URL = "ci.pipeline.url"; + public static final String CI_STAGE_NAME = "ci.stage.name"; + public static final String CI_JOB_NAME = "ci.job.name"; + public static final String CI_JOB_URL = "ci.job.url"; + public static final String CI_WORKSPACE_PATH = "ci.workspace_path"; + public static final String CI_NODE_NAME = "ci.node.name"; + public static final String CI_NODE_LABELS = "ci.node.labels"; + + public static final String GIT_REPOSITORY_URL = "git.repository_url"; + public static final String GIT_COMMIT_SHA = "git.commit.sha"; + public static final String GIT_COMMIT_AUTHOR_NAME = "git.commit.author.name"; + public static final String GIT_COMMIT_AUTHOR_EMAIL = "git.commit.author.email"; + public static final String GIT_COMMIT_AUTHOR_DATE = "git.commit.author.date"; + public static final String GIT_COMMIT_COMMITTER_NAME = "git.commit.committer.name"; + public static final String GIT_COMMIT_COMMITTER_EMAIL = "git.commit.committer.email"; + public static final String GIT_COMMIT_COMMITTER_DATE = "git.commit.committer.date"; + public static final String GIT_COMMIT_MESSAGE = "git.commit.message"; + public static final String GIT_BRANCH = "git.branch"; + public static final String GIT_TAG = "git.tag"; + + public static final String RUNTIME_NAME = "runtime.name"; + public static final String RUNTIME_VENDOR = "runtime.vendor"; + public static final String RUNTIME_VERSION = "runtime.version"; + public static final String OS_ARCHITECTURE = "os.architecture"; + public static final String OS_PLATFORM = "os.platform"; + public static final String OS_VERSION = "os.version"; + + public static final String DD_SERVICE = "dd.service"; + public static final String DD_VERSION = "dd.version"; + public static final String DD_ENV = "dd.env"; + + public static final String ENV = "env"; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java new file mode 100644 index 0000000000..3315ab3e8b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java @@ -0,0 +1,15 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public interface TaskWrapper { + static Class getUnwrappedType(Object task) { + int depth = 0; + Object inspected = task; + while (depth < 5 && inspected instanceof TaskWrapper) { + inspected = ((TaskWrapper) inspected).$$DD$$__unwrap(); + depth++; + } + return inspected == null ? null : inspected.getClass(); + } + + Object $$DD$$__unwrap(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java new file mode 100644 index 0000000000..6536401f62 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java @@ -0,0 +1,43 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public interface URIDataAdapter { + /** The scheme of this URI. Can never be encoded. */ + String scheme(); + + /** The host of this URI. Can never be encoded. */ + String host(); + + /** The port number of this URI. */ + int port(); + + /** The decoded path of this URI. */ + String path(); + + /** The decoded fragment of this URI. */ + String fragment(); + + /** The decoded query string of this URI. */ + String query(); + + /** Does this adapter support raw encoded access? */ + boolean supportsRaw(); + + /** The raw path of this URI. */ + String rawPath(); + + /** Does the raw query string have '+' encoded spaces? */ + boolean hasPlusEncodedSpaces(); + + /** The raw query string of this URI. */ + String rawQuery(); + + /** The raw path(?query) of this URI. */ + String raw(); + + /** + * The URI is a valid one or not (looks malformed) + * + * @return + */ + boolean isValid(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java new file mode 100644 index 0000000000..87545a9aa6 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java @@ -0,0 +1,48 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.net.URI; +import java.util.function.Function; + +public abstract class URIDataAdapterBase implements URIDataAdapter { + /** Unique instance that signifies an uninitialized field, to allow for == comparison */ + protected static final String UNINITIALIZED = new String("uninitialized"); + + private String raw = supportsRaw() ? UNINITIALIZED : null; + + @Override + public boolean hasPlusEncodedSpaces() { + return false; + } + + @Override + public String raw() { + String raw = this.raw; + if (raw == UNINITIALIZED) { + String p = rawPath(); + String q = rawQuery(); + StringBuilder builder = new StringBuilder(); + if (null != p && !p.isEmpty()) { + builder.append(p); + } + if (null != q && !q.isEmpty()) { + builder.append('?'); + builder.append(q); + } + this.raw = raw = builder.toString(); + } + return raw; + } + + @Override + public boolean isValid() { + return true; + } + + public static URIDataAdapter fromURI(String uri, Function mapper) { + final URI parsed = URIUtils.safeParse(uri); + if (parsed != null) { + return mapper.apply(parsed); + } + return new UnparseableURIDataAdapter(uri); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java new file mode 100644 index 0000000000..6392aad2d4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java @@ -0,0 +1,57 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import java.net.URI; + +public class URIDefaultDataAdapter extends URIDataAdapterBase { + + private final URI uri; + + public URIDefaultDataAdapter(URI uri) { + this.uri = uri; + } + + @Override + public String scheme() { + return uri.getScheme(); + } + + @Override + public String host() { + return uri.getHost(); + } + + @Override + public int port() { + return uri.getPort(); + } + + @Override + public String path() { + return uri.getPath(); + } + + @Override + public String fragment() { + return uri.getFragment(); + } + + @Override + public String query() { + return uri.getQuery(); + } + + @Override + public boolean supportsRaw() { + return true; + } + + @Override + public String rawPath() { + return uri.getRawPath(); + } + + @Override + public String rawQuery() { + return uri.getRawQuery(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java new file mode 100644 index 0000000000..d02af4ead1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java @@ -0,0 +1,55 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public abstract class URIRawDataAdapter extends URIDataAdapterBase { + private String decodedPath = UNINITIALIZED; + private String decodedQuery = UNINITIALIZED; + private String rawPath = UNINITIALIZED; + private String rawQuery = UNINITIALIZED; + + protected abstract String innerRawPath(); + + protected abstract String innerRawQuery(); + + @Override + public final String path() { + String path = decodedPath; + if (path != UNINITIALIZED) { + return path; + } + decodedPath = path = URIUtils.decode(rawPath()); + return path; + } + + @Override + public final String query() { + String query = decodedQuery; + if (query != UNINITIALIZED) { + return query; + } + decodedQuery = query = URIUtils.decode(rawQuery(), hasPlusEncodedSpaces()); + return query; + } + + @Override + public final boolean supportsRaw() { + return true; + } + + @Override + public final String rawPath() { + String path = rawPath; + if (path == UNINITIALIZED) { + rawPath = path = innerRawPath(); + } + return path; + } + + @Override + public final String rawQuery() { + String query = rawQuery; + if (query == UNINITIALIZED) { + rawQuery = query = innerRawQuery(); + } + return query; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIUtils.java new file mode 100644 index 0000000000..b44573f58f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIUtils.java @@ -0,0 +1,302 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.function.Supplier; + +public class URIUtils { + private URIUtils() {} + + // This is the � character, which is also the default replacement for the UTF_8 charset + private static final byte[] REPLACEMENT = {(byte) 0xEF, (byte) 0xBF, (byte) 0xBD}; + + private static final Logger LOGGER = LoggerFactory.getLogger(URIUtils.class); + + /** + * Decodes a %-encoded UTF-8 {@code String} into a regular {@code String}. + * + *

All illegal % sequences and illegal UTF-8 sequences are replaced with one or more � + * characters. + */ + public static String decode(String encoded) { + return decode(encoded, false); + } + + /** + * Decodes a %-encoded UTF-8 {@code String} into a regular {@code String}. Can also be made to + * decode '+' to ' ' to support old query strings. + * + *

All illegal % sequences and illegal UTF-8 sequences are replaced with one or more � + * characters. + */ + public static String decode(String encoded, boolean plusToSpace) { + if (encoded == null) return null; + int len = encoded.length(); + if (len == 0) return encoded; + if (encoded.indexOf('%') < 0 && (!plusToSpace || encoded.indexOf('+') < 0)) return encoded; + + ByteBuffer bb = + ByteBuffer.allocate(len + 2); // The extra 2 is if we have a % last and need to replace it + for (int i = 0; i < len; i++) { + int c = encoded.charAt(i); + if (c == '%') { + if (i + 2 < len) { + int h = Character.digit(encoded.charAt(i + 1), 16); + int l = Character.digit(encoded.charAt(i + 2), 16); + if ((h | l) < 0) { + bb.put(REPLACEMENT[0]); + bb.put(REPLACEMENT[1]); + bb.put(REPLACEMENT[2]); + } else { + bb.put((byte) ((h << 4) + l)); + } + i += 2; + } else { + bb.put(REPLACEMENT[0]); + bb.put(REPLACEMENT[1]); + bb.put(REPLACEMENT[2]); + i = len; + } + } else { + if (plusToSpace && c == '+') { + c = ' '; + } + bb.put((byte) c); + } + } + bb.flip(); + return new String(bb.array(), 0, bb.limit(), StandardCharsets.UTF_8); + } + + /** + * Build a URL based on the scheme, host, port and path. + * + *

Will remove the port if it is <= 0 or if its the default http/https port. + */ + public static String buildURL(String scheme, String host, int port, String path) { + int length = 0; + length += null == scheme ? 0 : scheme.length() + 3; + if (null != host) { + length += host.length(); + if (port > 0 && port != 80 && port != 443) { + length += 6; + } + } + if (null == path || path.isEmpty()) { + ++length; + } else { + if (path.charAt(0) != '/') { + ++length; + } + length += path.length(); + } + final StringBuilder urlNoParams = new StringBuilder(length); + if (scheme != null) { + urlNoParams.append(scheme); + urlNoParams.append("://"); + } + + if (host != null) { + urlNoParams.append(host); + if (port > 0 + && !(port == 80 && "http".equals(scheme) || port == 443 && "https".equals(scheme))) { + urlNoParams.append(':'); + urlNoParams.append(port); + } + } + + if (null == path || path.isEmpty()) { + urlNoParams.append('/'); + } else { + if (path.charAt(0) != '/' && urlNoParams.length() > 0) { + urlNoParams.append('/'); + } + urlNoParams.append(path); + } + return urlNoParams.toString(); + } + + public static URI safeParse(final String unparsed) { + if (unparsed == null) { + return null; + } + try { + return URI.create(unparsed); + } catch (final IllegalArgumentException exception) { + LOGGER.debug("Unable to parse request uri {}", unparsed, exception); + return null; + } + } + + /** + * Builds a lazily evaluated valid URL based on the scheme, host, port and path. + * + *

Will remove the port if it is <= 0 or if its the default http/https port. + * + * @param scheme The scheme + * @param host The host + * @param port The port + * @param path The path + * @return The {@code LazyUrl} + */ + public static LazyUrl lazyValidURL(String scheme, String host, int port, String path) { + return new ValidUrl(scheme, host, port, path); + } + + /** + * Builds an invalid URL from a raw string representation. + * + * @param raw The raw {@code String} representation of the invalid URL + * @return The {@code LazyUrl} + */ + public static LazyUrl lazyInvalidUrl(String raw) { + return new InvalidUrl(raw); + } + + public static String urlFileName(String raw) { + try { + URL url = new URL(raw); + String path = url.getPath(); + int nameEnd = path.length() - 1; + while (nameEnd >= 0 && path.charAt(nameEnd) == '/') { + nameEnd--; + } + if (nameEnd < 0) { + return ""; + } + String name = path.substring(path.lastIndexOf('/', nameEnd) + 1, nameEnd + 1); + return name; + } catch (MalformedURLException e) { + return ""; + } + } + + /** + * A lazily evaluated URL that can also return its path. If the URL is invalid the path will be + * {@code null}. + */ + public abstract static class LazyUrl implements CharSequence, Supplier { + protected String lazy; + + protected LazyUrl(String lazy) { + this.lazy = lazy; + } + + /** + * The path component of this URL. + * + * @return The path if valid or {@code null} if invalid + */ + public abstract String path(); + + @Override + public String toString() { + String str = lazy; + if (str == null) { + str = lazy = get(); + } + return str; + } + + @Override + public int length() { + return toString().length(); + } + + @Override + public char charAt(int index) { + return toString().charAt(index); + } + + @Override + public CharSequence subSequence(int start, int end) { + return toString().subSequence(start, end); + } + + @Override + public int hashCode() { + return toString().hashCode(); + } + } + + private static class ValidUrl extends LazyUrl { + private final String scheme; + private final String host; + private final int port; + private final String path; + + private ValidUrl(String scheme, String host, int port, String path) { + super(null); + this.scheme = scheme; + this.host = host; + this.port = port; + if (null == path || path.isEmpty()) { + this.path = ""; + } else { + this.path = path; + } + } + + @Override + public String path() { + return path; + } + + @Override + public String get() { + String res = lazy; + return res != null ? res : buildURL(scheme, host, port, path); + } + } + + private static class InvalidUrl extends LazyUrl { + public InvalidUrl(String raw) { + super(String.valueOf(raw)); + } + + @Override + public String path() { + return null; + } + + @Override + public String get() { + return lazy; + } + } + + /** + * Concatenate two URI parts to form the complete one. Mostly used for apache http client + * instrumentations + * + * @param schemeHostPort the first part (usually http://host:port) + * @param theRest the rest of the uri (e.g. /path?query#fragment + * @return the full URI or null if fails to parse + */ + public static URI safeConcat(final String schemeHostPort, final String theRest) { + if (schemeHostPort == null && theRest == null) { + return null; + } + final String part1 = schemeHostPort != null ? schemeHostPort : ""; + final String part2 = theRest != null ? theRest : ""; + if (part2.startsWith(part1)) { + return safeParse(part2); + } + final boolean addSlash = !(part2.startsWith("/") || part1.endsWith("/")); + final StringBuilder sb = + new StringBuilder(part1.length() + part2.length() + (addSlash ? 1 : 0)); + sb.append(part1); + if (addSlash) { + // it happens for http async client 4 with relative URI + sb.append("/"); + } + sb.append(part2); + return safeParse(sb.toString()); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java new file mode 100644 index 0000000000..ce60056fd9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java @@ -0,0 +1,134 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.nio.ByteBuffer; + +/** + * Class that wraps a {@code String} and caches the UTF8 byte representation. Implements {@code + * CharSequence} so that it can be mixed with normal{@code String} instances. + */ +public final class UTF8BytesString implements CharSequence { + + public static final UTF8BytesString EMPTY = UTF8BytesString.create(""); + + public static UTF8BytesString create(CharSequence sequence) { + if (null == sequence) { + return null; + } else if (sequence instanceof UTF8BytesString) { + return (UTF8BytesString) sequence; + } else { + return new UTF8BytesString(String.valueOf(sequence)); + } + } + + public static UTF8BytesString create(byte[] utf8Bytes) { + if (null == utf8Bytes) { + return null; + } else { + return new UTF8BytesString(utf8Bytes); + } + } + + public static UTF8BytesString create(String string, byte[] utf8Bytes) { + if (null == utf8Bytes) { + return null; + } else { + return new UTF8BytesString(string, utf8Bytes); + } + } + + /** + * Creates a new {@linkplain UTF8BytesString} instance using the provided {@linkplain ByteBuffer} + *
+ * All available data from the current position are read and used as the backing array. + * + * @param utf8BytesBuffer the byte buffer containing UTF8 data + * @return a new {@linkplain UTF8BytesString} instance or {@literal null} + */ + public static UTF8BytesString create(ByteBuffer utf8BytesBuffer) { + if (null == utf8BytesBuffer) { + return null; + } else { + byte[] utf8Bytes = new byte[utf8BytesBuffer.remaining()]; + utf8BytesBuffer.get(utf8Bytes); + return new UTF8BytesString(utf8Bytes); + } + } + + private final String string; + private byte[] utf8Bytes; + + private UTF8BytesString(String string) { + this.string = string; + } + + private UTF8BytesString(byte[] utf8Bytes) { + this(new String(utf8Bytes, UTF_8), utf8Bytes); + } + + private UTF8BytesString(String string, byte[] utf8Bytes) { + this.string = string; + this.utf8Bytes = utf8Bytes; + } + + /** Writes the UTF8 encoding of the wrapped {@code String}. */ + public void transferTo(ByteBuffer buffer) { + encodeIfNecessary(); + buffer.put(utf8Bytes); + } + + /** Writes the UTF8 encoding of the wrapped {@code String}. */ + public byte[] getUtf8Bytes() { + encodeIfNecessary(); + return utf8Bytes; + } + + public int encodedLength() { + encodeIfNecessary(); + return utf8Bytes.length; + } + + @Override + public String toString() { + return string; + } + + private void encodeIfNecessary() { + // benign and intentional race condition + if (null == utf8Bytes) { + utf8Bytes = string.getBytes(UTF_8); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null) return false; + String that = null; + if (o instanceof UTF8BytesString) { + that = ((UTF8BytesString) o).string; + } + return this.string.equals(that); + } + + @Override + public int hashCode() { + return this.string.hashCode(); + } + + @Override + public int length() { + return this.string.length(); + } + + @Override + public char charAt(int index) { + return this.string.charAt(index); + } + + @Override + public CharSequence subSequence(int start, int end) { + return this.string.subSequence(start, end); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java new file mode 100644 index 0000000000..7a3b4f1daa --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java @@ -0,0 +1,66 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import androidx.annotation.NonNull; + +public class UnparseableURIDataAdapter extends URIDataAdapterBase { + private final String rawUri; + + public UnparseableURIDataAdapter(@NonNull String rawUri) { + this.rawUri = rawUri; + } + + @Override + public boolean isValid() { + return false; + } + + @Override + public String scheme() { + return null; + } + + @Override + public String host() { + return null; + } + + @Override + public int port() { + return 0; + } + + @Override + public String path() { + return null; + } + + @Override + public String fragment() { + return null; + } + + @Override + public String query() { + return null; + } + + @Override + public boolean supportsRaw() { + return true; + } + + @Override + public String rawPath() { + return null; + } + + @Override + public String rawQuery() { + return null; + } + + @Override + public String raw() { + return rawUri; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java new file mode 100644 index 0000000000..0c283d129f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java @@ -0,0 +1,12 @@ +package datadog.trace.bootstrap.instrumentation.api; + +public final class WriterConstants { + public static final String DD_AGENT_WRITER_TYPE = "DDAgentWriter"; + public static final String DD_INTAKE_WRITER_TYPE = "DDIntakeWriter"; + public static final String LOGGING_WRITER_TYPE = "LoggingWriter"; + public static final String PRINTING_WRITER_TYPE = "PrintingWriter"; + public static final String TRACE_STRUCTURE_WRITER_TYPE = "TraceStructureWriter"; + public static final String MULTI_WRITER_TYPE = "MultiWriter"; + + private WriterConstants() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java b/features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java new file mode 100644 index 0000000000..589fba522d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java @@ -0,0 +1,45 @@ +package datadog.trace.civisibility.interceptor; + +import datadog.trace.api.DDSpanTypes; +import datadog.trace.api.interceptor.AbstractTraceInterceptor; +import datadog.trace.api.interceptor.MutableSpan; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +/** + * An interceptor that removes spans and tags that are not supported in the APM protocol (some spans + * and tags related to certain CI Visibility features, e.g. Test Suite Level Visibility, can only be + * written with CI Test Cycle protocol) + */ +public class CiVisibilityApmProtocolInterceptor extends AbstractTraceInterceptor { + + public static final CiVisibilityApmProtocolInterceptor INSTANCE = + new CiVisibilityApmProtocolInterceptor(Priority.CI_VISIBILITY_APM); + + protected CiVisibilityApmProtocolInterceptor(Priority priority) { + super(priority); + } + + @Override + public Collection onTraceComplete( + Collection trace) { + + List filteredTrace = + trace.stream().filter(this::isSupportedByApmProtocol).collect(Collectors.toList()); + for (MutableSpan span : filteredTrace) { + span.setTag(Tags.TEST_SESSION_ID, (Number) null); + span.setTag(Tags.TEST_MODULE_ID, (Number) null); + span.setTag(Tags.TEST_SUITE_ID, (Number) null); + } + return filteredTrace; + } + + private boolean isSupportedByApmProtocol(MutableSpan span) { + String spanType = span.getSpanType(); + return !DDSpanTypes.TEST_SESSION_END.equals(spanType) + && !DDSpanTypes.TEST_MODULE_END.equals(spanType) + && !DDSpanTypes.TEST_SUITE_END.equals(spanType); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java b/features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java new file mode 100644 index 0000000000..bec1bdcd64 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java @@ -0,0 +1,56 @@ +package datadog.trace.civisibility.interceptor; + +import datadog.trace.api.DDSpanTypes; +import datadog.trace.api.DDTags; +import datadog.trace.api.interceptor.AbstractTraceInterceptor; +import datadog.trace.api.interceptor.MutableSpan; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.core.DDSpan; +import datadog.trace.core.DDTraceCoreInfo; +import java.util.Collection; +import java.util.Collections; + +public class CiVisibilityTraceInterceptor extends AbstractTraceInterceptor { + + public static final CiVisibilityTraceInterceptor INSTANCE = + new CiVisibilityTraceInterceptor(Priority.CI_VISIBILITY_TRACE); + + static final UTF8BytesString CIAPP_TEST_ORIGIN = UTF8BytesString.create("ciapp-test"); + + protected CiVisibilityTraceInterceptor(Priority priority) { + super(priority); + } + + @Override + public Collection onTraceComplete( + Collection trace) { + if (trace.isEmpty()) { + return trace; + } + + final DDSpan firstSpan = (DDSpan) trace.iterator().next(); + final DDSpan localRootSpan = firstSpan.getLocalRootSpan(); + + final DDSpan spanToCheck = null == localRootSpan ? firstSpan : localRootSpan; + + // If root span is not a CI visibility span, we drop the full trace. + CharSequence type = spanToCheck.getType(); // Don't null pointer if there is no type + if (type == null + || (!DDSpanTypes.TEST.contentEquals(type) + && !DDSpanTypes.TEST_SUITE_END.contentEquals(type) + && !DDSpanTypes.TEST_MODULE_END.contentEquals(type) + && !DDSpanTypes.TEST_SESSION_END.contentEquals(type))) { + return Collections.emptyList(); + } + + // If the trace belongs to a "test", we need to set the origin to `ciapp-test` and the + // `library_version` tag for all spans. + firstSpan.context().setOrigin(CIAPP_TEST_ORIGIN); + firstSpan.setTag(DDTags.LIBRARY_VERSION_TAG_KEY, DDTraceCoreInfo.VERSION); + for (MutableSpan span : trace) { + span.setTag(DDTags.LIBRARY_VERSION_TAG_KEY, DDTraceCoreInfo.VERSION); + } + + return trace; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/GitMetadataTraceInterceptor.java b/features/dd-trace-core/src/main/java/datadog/trace/common/GitMetadataTraceInterceptor.java new file mode 100644 index 0000000000..584d79f8ff --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/GitMetadataTraceInterceptor.java @@ -0,0 +1,38 @@ +package datadog.trace.common; + +import datadog.trace.api.DDTags; +import datadog.trace.api.git.GitInfo; +import datadog.trace.api.git.GitInfoProvider; +import datadog.trace.api.interceptor.AbstractTraceInterceptor; +import datadog.trace.api.interceptor.MutableSpan; +import datadog.trace.api.interceptor.TraceInterceptor; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.core.DDSpan; +import java.util.Collection; + +public class GitMetadataTraceInterceptor extends AbstractTraceInterceptor { + + public static final TraceInterceptor INSTANCE = + new GitMetadataTraceInterceptor(Priority.GIT_METADATA); + + protected GitMetadataTraceInterceptor(Priority priority) { + super(priority); + } + + @Override + public Collection onTraceComplete( + Collection trace) { + if (trace.isEmpty()) { + return trace; + } + + final DDSpan firstSpan = (DDSpan) trace.iterator().next(); + String ciWorkspacePath = (String) firstSpan.getTag(Tags.CI_WORKSPACE_PATH); + + GitInfo gitInfo = GitInfoProvider.INSTANCE.getGitInfo(ciWorkspacePath); + firstSpan.setTag(DDTags.INTERNAL_GIT_REPOSITORY_URL, gitInfo.getRepositoryURL()); + firstSpan.setTag(DDTags.INTERNAL_GIT_COMMIT_SHA, gitInfo.getCommit().getSha()); + + return trace; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/AggregateMetric.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/AggregateMetric.java new file mode 100644 index 0000000000..c81015b52f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/AggregateMetric.java @@ -0,0 +1,78 @@ +package datadog.trace.common.metrics; + +import datadog.trace.core.histogram.Histogram; +import datadog.trace.core.histogram.Histograms; +import java.util.concurrent.atomic.AtomicLongArray; + +/** Not thread-safe. Accumulates counts and durations. */ +public final class AggregateMetric { + + static final long ERROR_TAG = 0x8000000000000000L; + static final long TOP_LEVEL_TAG = 0x4000000000000000L; + + private final Histogram okLatencies; + private final Histogram errorLatencies; + private int errorCount; + private int hitCount; + private int topLevelCount; + private long duration; + + public AggregateMetric() { + okLatencies = Histograms.newHistogram(); + errorLatencies = Histograms.newHistogram(); + } + + public AggregateMetric recordDurations(int count, AtomicLongArray durations) { + this.hitCount += count; + for (int i = 0; i < count && i < durations.length(); ++i) { + long duration = durations.getAndSet(i, 0); + if ((duration & TOP_LEVEL_TAG) == TOP_LEVEL_TAG) { + duration ^= TOP_LEVEL_TAG; + ++topLevelCount; + } + if ((duration & ERROR_TAG) == ERROR_TAG) { + // then it's an error + duration ^= ERROR_TAG; + errorLatencies.accept(duration); + ++errorCount; + } else { + okLatencies.accept(duration); + } + this.duration += duration; + } + return this; + } + + public int getErrorCount() { + return errorCount; + } + + public int getHitCount() { + return hitCount; + } + + public int getTopLevelCount() { + return topLevelCount; + } + + public long getDuration() { + return duration; + } + + public Histogram getOkLatencies() { + return okLatencies; + } + + public Histogram getErrorLatencies() { + return errorLatencies; + } + + public void clear() { + this.errorCount = 0; + this.hitCount = 0; + this.topLevelCount = 0; + this.duration = 0; + this.okLatencies.clear(); + this.errorLatencies.clear(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Aggregator.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Aggregator.java new file mode 100644 index 0000000000..b2b8b1820f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Aggregator.java @@ -0,0 +1,194 @@ +package datadog.trace.common.metrics; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import datadog.trace.common.metrics.SignalItem.StopSignal; +import datadog.trace.core.util.LRUCache; +import java.util.Iterator; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import org.jctools.maps.NonBlockingHashMap; +import org.jctools.queues.MessagePassingQueue; +import org.jctools.queues.MpscCompoundQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class Aggregator implements Runnable { + + private static final long DEFAULT_SLEEP_MILLIS = 10; + + private static final Logger log = LoggerFactory.getLogger(Aggregator.class); + + private final Queue batchPool; + private final MpscCompoundQueue inbox; + private final LRUCache aggregates; + private final NonBlockingHashMap pending; + private final Set commonKeys; + private final MetricWriter writer; + // the reporting interval controls how much history will be buffered + // when the agent is unresponsive (only 10 pending requests will be + // buffered by OkHttpSink) + private final long reportingIntervalNanos; + + private final long sleepMillis; + + private boolean dirty; + + Aggregator( + MetricWriter writer, + Queue batchPool, + MpscCompoundQueue inbox, + NonBlockingHashMap pending, + final Set commonKeys, + int maxAggregates, + long reportingInterval, + TimeUnit reportingIntervalTimeUnit) { + this( + writer, + batchPool, + inbox, + pending, + commonKeys, + maxAggregates, + reportingInterval, + reportingIntervalTimeUnit, + DEFAULT_SLEEP_MILLIS); + } + + Aggregator( + MetricWriter writer, + Queue batchPool, + MpscCompoundQueue inbox, + NonBlockingHashMap pending, + final Set commonKeys, + int maxAggregates, + long reportingInterval, + TimeUnit reportingIntervalTimeUnit, + long sleepMillis) { + this.writer = writer; + this.batchPool = batchPool; + this.inbox = inbox; + this.commonKeys = commonKeys; + this.aggregates = + new LRUCache<>( + new CommonKeyCleaner(commonKeys), maxAggregates * 4 / 3, 0.75f, maxAggregates); + this.pending = pending; + this.reportingIntervalNanos = reportingIntervalTimeUnit.toNanos(reportingInterval); + this.sleepMillis = sleepMillis; + } + + public void clearAggregates() { + this.aggregates.clear(); + } + + @Override + public void run() { + Thread currentThread = Thread.currentThread(); + Drainer drainer = new Drainer(); + while (!currentThread.isInterrupted() && !drainer.stopped) { + try { + if (!inbox.isEmpty()) { + inbox.drain(drainer); + } else { + Thread.sleep(sleepMillis); + } + } catch (InterruptedException e) { + currentThread.interrupt(); + } catch (Throwable error) { + log.debug("error aggregating metrics", error); + } + } + log.debug("metrics aggregator exited"); + } + + private final class Drainer implements MessagePassingQueue.Consumer { + + boolean stopped = false; + + @Override + public void accept(InboxItem item) { + if (item instanceof SignalItem) { + SignalItem signal = (SignalItem) item; + if (!stopped) { + report(wallClockTime(), signal); + stopped = item instanceof StopSignal; + if (stopped) { + signal.complete(); + } + } else { + signal.ignore(); + } + } else if (item instanceof Batch && !stopped) { + Batch batch = (Batch) item; + MetricKey key = batch.getKey(); + // important that it is still *this* batch pending, must not remove otherwise + pending.remove(key, batch); + AggregateMetric aggregate = aggregates.computeIfAbsent(key, k -> new AggregateMetric()); + batch.contributeTo(aggregate); + dirty = true; + // return the batch for reuse + batchPool.offer(batch); + } + } + } + + private void report(long when, SignalItem signal) { + boolean skipped = true; + if (dirty) { + try { + expungeStaleAggregates(); + if (!aggregates.isEmpty()) { + skipped = false; + writer.startBucket(aggregates.size(), when, reportingIntervalNanos); + for (Map.Entry aggregate : aggregates.entrySet()) { + writer.add(aggregate.getKey(), aggregate.getValue()); + aggregate.getValue().clear(); + } + // note that this may do IO and block + writer.finishBucket(); + } + } catch (Throwable error) { + writer.reset(); + log.debug("Error publishing metrics. Dropping payload", error); + } + dirty = false; + } + signal.complete(); + if (skipped) { + log.debug("skipped metrics reporting because no points have changed"); + } + } + + private void expungeStaleAggregates() { + Iterator> it = aggregates.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pair = it.next(); + AggregateMetric metric = pair.getValue(); + if (metric.getHitCount() == 0) { + it.remove(); + commonKeys.remove(pair.getKey()); + } + } + } + + private long wallClockTime() { + return MILLISECONDS.toNanos(System.currentTimeMillis()); + } + + private static final class CommonKeyCleaner + implements LRUCache.ExpiryListener { + + private final Set commonKeys; + + private CommonKeyCleaner(Set commonKeys) { + this.commonKeys = commonKeys; + } + + @Override + public void accept(Map.Entry expired) { + commonKeys.remove(expired.getKey()); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Batch.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Batch.java new file mode 100644 index 0000000000..f3c7ea4d46 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Batch.java @@ -0,0 +1,89 @@ +package datadog.trace.common.metrics; + +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import java.util.concurrent.atomic.AtomicLongArray; + +/** + * This is a thread-safe container for partial conflating and accumulating partial aggregates on the + * same key. + * + *

Updates to an already consumed batch are rejected. + * + *

A batch can currently take at most 64 values. Attempts to add the 65th update will be + * rejected. + */ +public final class Batch implements InboxItem { + + private static final int MAX_BATCH_SIZE = 64; + private static final AtomicIntegerFieldUpdater COUNT = + AtomicIntegerFieldUpdater.newUpdater(Batch.class, "count"); + private static final AtomicIntegerFieldUpdater COMMITTED = + AtomicIntegerFieldUpdater.newUpdater(Batch.class, "committed"); + + /** + * This counter has two states: + * + *

    + *
  1. negative: the batch has been used, must not add values + *
  2. otherwise: the number of values added to the batch + *
+ */ + private volatile int count = 0; + /** incremented when a duration has been added. */ + private volatile int committed = 0; + + private MetricKey key; + private final AtomicLongArray durations; + + Batch(MetricKey key) { + this(new AtomicLongArray(MAX_BATCH_SIZE)); + this.key = key; + } + + Batch() { + this(new AtomicLongArray(MAX_BATCH_SIZE)); + } + + private Batch(AtomicLongArray durations) { + this.durations = durations; + } + + public MetricKey getKey() { + return key; + } + + public Batch reset(MetricKey key) { + this.key = key; + COUNT.lazySet(this, 0); + return this; + } + + public boolean isUsed() { + return count < 0; + } + + public boolean add(long tag, long durationNanos) { + // technically this would be wrong if there were 2^31 unsuccessful + // attempts to add a value, but this an acceptable risk + int position = COUNT.getAndIncrement(this); + if (position >= 0 && position < durations.length()) { + durations.set(position, tag | durationNanos); + COMMITTED.getAndIncrement(this); + return true; + } + return false; + } + + public void contributeTo(AggregateMetric aggregate) { + int count = Math.min(COUNT.getAndSet(this, Integer.MIN_VALUE), MAX_BATCH_SIZE); + if (count >= 0) { + // wait for the duration to have been set. + // note this mechanism only supports a single reader + while (committed != count) { + Thread.yield(); + } + COMMITTED.lazySet(this, 0); + aggregate.recordDurations(count, durations); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/EventListener.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/EventListener.java new file mode 100644 index 0000000000..ae5f910b0a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/EventListener.java @@ -0,0 +1,12 @@ +package datadog.trace.common.metrics; + +public interface EventListener { + enum EventType { + BAD_PAYLOAD, + DOWNGRADED, + OK, + ERROR + } + + void onEvent(EventType eventType, String message); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java new file mode 100644 index 0000000000..7d66cad6a1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java @@ -0,0 +1,31 @@ +package datadog.trace.common.metrics; + +import java.util.concurrent.CompletableFuture; + +interface InboxItem {} + +abstract class SignalItem implements InboxItem { + final CompletableFuture future; + + public SignalItem() { + this.future = new CompletableFuture<>(); + } + + void complete() { + this.future.complete(true); + } + + void ignore() { + this.future.complete(false); + } + + static final class StopSignal extends SignalItem { + static final StopSignal STOP = new StopSignal(); + + private StopSignal() {} + } + + static final class ReportSignal extends SignalItem { + static final ReportSignal REPORT = new ReportSignal(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricKey.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricKey.java new file mode 100644 index 0000000000..4ba23db6d5 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricKey.java @@ -0,0 +1,87 @@ +package datadog.trace.common.metrics; + +import static datadog.trace.bootstrap.instrumentation.api.UTF8BytesString.EMPTY; + +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; + +/** The aggregation key for tracked metrics. */ +public final class MetricKey { + private final UTF8BytesString resource; + private final UTF8BytesString service; + private final UTF8BytesString operationName; + private final UTF8BytesString type; + private final int httpStatusCode; + private final boolean synthetics; + private final int hash; + + public MetricKey( + CharSequence resource, + CharSequence service, + CharSequence operationName, + CharSequence type, + int httpStatusCode, + boolean synthetics) { + this.resource = null == resource ? EMPTY : UTF8BytesString.create(resource); + this.service = null == service ? EMPTY : UTF8BytesString.create(service); + this.operationName = null == operationName ? EMPTY : UTF8BytesString.create(operationName); + this.type = null == type ? EMPTY : UTF8BytesString.create(type); + this.httpStatusCode = httpStatusCode; + this.synthetics = synthetics; + // unrolled polynomial hashcode which avoids allocating varargs + // the constants are 31^5, 31^4, 31^3, 31^2, 31^1, 31^0 + this.hash = + 28629151 * this.resource.hashCode() + + 923521 * this.service.hashCode() + + 29791 * this.operationName.hashCode() + + 961 * this.type.hashCode() + + 31 * httpStatusCode + + (this.synthetics ? 1 : 0); + } + + public UTF8BytesString getResource() { + return resource; + } + + public UTF8BytesString getService() { + return service; + } + + public UTF8BytesString getOperationName() { + return operationName; + } + + public UTF8BytesString getType() { + return type; + } + + public int getHttpStatusCode() { + return httpStatusCode; + } + + public boolean isSynthetics() { + return synthetics; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if ((o instanceof MetricKey)) { + MetricKey metricKey = (MetricKey) o; + return hash == metricKey.hash + && synthetics == metricKey.synthetics + && httpStatusCode == metricKey.httpStatusCode + && resource.equals(metricKey.resource) + && service.equals(metricKey.service) + && operationName.equals(metricKey.operationName) + && type.equals(metricKey.type); + } + return false; + } + + @Override + public int hashCode() { + return hash; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricWriter.java new file mode 100644 index 0000000000..fa26ed2e5d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricWriter.java @@ -0,0 +1,11 @@ +package datadog.trace.common.metrics; + +public interface MetricWriter { + void startBucket(int metricCount, long start, long duration); + + void add(MetricKey key, AggregateMetric aggregate); + + void finishBucket(); + + void reset(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricsAggregator.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricsAggregator.java new file mode 100644 index 0000000000..3ea6df9c58 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricsAggregator.java @@ -0,0 +1,18 @@ +package datadog.trace.common.metrics; + +import datadog.trace.core.CoreSpan; +import java.util.List; +import java.util.concurrent.Future; + +public interface MetricsAggregator extends AutoCloseable { + void start(); + + boolean report(); + + Future forceReport(); + + boolean publish(List> trace); + + @Override + void close(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java new file mode 100644 index 0000000000..a15c008e10 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java @@ -0,0 +1,34 @@ +package datadog.trace.common.metrics; + +import static java.lang.Boolean.FALSE; + +import datadog.trace.core.CoreSpan; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; + +public final class NoOpMetricsAggregator implements MetricsAggregator { + + public static final NoOpMetricsAggregator INSTANCE = new NoOpMetricsAggregator(); + + @Override + public void start() {} + + @Override + public boolean report() { + return false; + } + + @Override + public Future forceReport() { + return CompletableFuture.completedFuture(FALSE); + } + + @Override + public boolean publish(List> trace) { + return false; + } + + @Override + public void close() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/SerializingMetricWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/SerializingMetricWriter.java new file mode 100644 index 0000000000..37287c3fbf --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/SerializingMetricWriter.java @@ -0,0 +1,136 @@ +package datadog.trace.common.metrics; + +import static java.nio.charset.StandardCharsets.ISO_8859_1; + +import datadog.trace.serialization.GrowableBuffer; +import datadog.trace.serialization.WritableFormatter; +import datadog.trace.serialization.msgpack.MsgPackWriter; +import datadog.trace.api.WellKnownTags; + +public final class SerializingMetricWriter implements MetricWriter { + + private static final byte[] SEQUENCE = "Seq".getBytes(ISO_8859_1); + private static final byte[] RUNTIME_ID = "RuntimeId".getBytes(ISO_8859_1); + private static final byte[] HOSTNAME = "Hostname".getBytes(ISO_8859_1); + private static final byte[] NAME = "Name".getBytes(ISO_8859_1); + private static final byte[] ENV = "Env".getBytes(ISO_8859_1); + private static final byte[] SERVICE = "Service".getBytes(ISO_8859_1); + private static final byte[] RESOURCE = "Resource".getBytes(ISO_8859_1); + private static final byte[] VERSION = "Version".getBytes(ISO_8859_1); + private static final byte[] HITS = "Hits".getBytes(ISO_8859_1); + private static final byte[] ERRORS = "Errors".getBytes(ISO_8859_1); + private static final byte[] TOP_LEVEL_HITS = "TopLevelHits".getBytes(ISO_8859_1); + private static final byte[] DURATION = "Duration".getBytes(ISO_8859_1); + private static final byte[] TYPE = "Type".getBytes(ISO_8859_1); + private static final byte[] HTTP_STATUS_CODE = "HTTPStatusCode".getBytes(ISO_8859_1); + private static final byte[] SYNTHETICS = "Synthetics".getBytes(ISO_8859_1); + private static final byte[] START = "Start".getBytes(ISO_8859_1); + private static final byte[] STATS = "Stats".getBytes(ISO_8859_1); + private static final byte[] OK_SUMMARY = "OkSummary".getBytes(ISO_8859_1); + private static final byte[] ERROR_SUMMARY = "ErrorSummary".getBytes(ISO_8859_1); + + private final WellKnownTags wellKnownTags; + private final WritableFormatter writer; + private final Sink sink; + private final GrowableBuffer buffer; + private long sequence = 0; + + public SerializingMetricWriter(WellKnownTags wellKnownTags, Sink sink) { + this(wellKnownTags, sink, 512 * 1024); + } + + public SerializingMetricWriter(WellKnownTags wellKnownTags, Sink sink, int initialCapacity) { + this.wellKnownTags = wellKnownTags; + this.buffer = new GrowableBuffer(initialCapacity); + this.writer = new MsgPackWriter(buffer); + this.sink = sink; + } + + @Override + public void startBucket(int metricCount, long start, long duration) { + writer.startMap(6); + + writer.writeUTF8(RUNTIME_ID); + writer.writeUTF8(wellKnownTags.getRuntimeId()); + + writer.writeUTF8(SEQUENCE); + writer.writeLong(sequence++); + + writer.writeUTF8(HOSTNAME); + writer.writeUTF8(wellKnownTags.getHostname()); + + writer.writeUTF8(ENV); + writer.writeUTF8(wellKnownTags.getEnv()); + + writer.writeUTF8(VERSION); + writer.writeUTF8(wellKnownTags.getVersion()); + + writer.writeUTF8(STATS); + writer.startArray(1); + + writer.startMap(3); + + writer.writeUTF8(START); + writer.writeLong(start); + + writer.writeUTF8(DURATION); + writer.writeLong(duration); + + writer.writeUTF8(STATS); + writer.startArray(metricCount); + } + + @Override + public void add(MetricKey key, AggregateMetric aggregate) { + + writer.startMap(12); + + writer.writeUTF8(NAME); + writer.writeUTF8(key.getOperationName()); + + writer.writeUTF8(SERVICE); + writer.writeUTF8(key.getService()); + + writer.writeUTF8(RESOURCE); + writer.writeUTF8(key.getResource()); + + writer.writeUTF8(TYPE); + writer.writeUTF8(key.getType()); + + writer.writeUTF8(HTTP_STATUS_CODE); + writer.writeInt(key.getHttpStatusCode()); + + writer.writeUTF8(SYNTHETICS); + writer.writeBoolean(key.isSynthetics()); + + writer.writeUTF8(HITS); + writer.writeInt(aggregate.getHitCount()); + + writer.writeUTF8(ERRORS); + writer.writeInt(aggregate.getErrorCount()); + + writer.writeUTF8(TOP_LEVEL_HITS); + writer.writeInt(aggregate.getTopLevelCount()); + + writer.writeUTF8(DURATION); + writer.writeLong(aggregate.getDuration()); + + writer.writeUTF8(OK_SUMMARY); + writer.writeBinary(aggregate.getOkLatencies().serialize()); + + writer.writeUTF8(ERROR_SUMMARY); + writer.writeBinary(aggregate.getErrorLatencies().serialize()); + } + + @Override + public void finishBucket() { + buffer.mark(); + sink.accept(buffer.messageCount(), buffer.slice()); + buffer.reset(); + } + + @Override + public void reset() { + buffer.reset(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Sink.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Sink.java new file mode 100644 index 0000000000..7328caaedd --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Sink.java @@ -0,0 +1,8 @@ +package datadog.trace.common.metrics; + +import datadog.trace.serialization.ByteBufferConsumer; + +public interface Sink extends ByteBufferConsumer { + + void register(EventListener listener); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/AllSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/AllSampler.java new file mode 100644 index 0000000000..1e381a9d94 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/AllSampler.java @@ -0,0 +1,17 @@ +package datadog.trace.common.sampling; + +import datadog.trace.core.CoreSpan; + +/** Sampler that always says yes... */ +public class AllSampler implements Sampler { + + @Override + public String toString() { + return "AllSampler { sample=true }"; + } + + @Override + public > boolean sample(T span) { + return true; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/DeterministicSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/DeterministicSampler.java new file mode 100644 index 0000000000..350e27a5ee --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/DeterministicSampler.java @@ -0,0 +1,69 @@ +package datadog.trace.common.sampling; + +import datadog.trace.core.CoreSpan; + +/** + * This implements the deterministic sampling algorithm used by the Datadog Agent as well as the + * tracers for other languages + */ +public abstract class DeterministicSampler implements RateSampler { + + /** Uses trace-id as a sampling id */ + public static final class TraceSampler extends DeterministicSampler { + + public TraceSampler(double rate) { + super(rate); + } + + @Override + protected > long getSamplingId(T span) { + return span.getTraceId().toLong(); + } + } + + /** Uses span-id as a sampling id */ + public static final class SpanSampler extends DeterministicSampler { + + public SpanSampler(double rate) { + super(rate); + } + + @Override + protected > long getSamplingId(T span) { + return span.getSpanId(); + } + } + + private static final long KNUTH_FACTOR = 1111111111111111111L; + + private static final double MAX = Math.pow(2, 64) - 1; + + private final float rate; + + public DeterministicSampler(final double rate) { + this.rate = (float) rate; + } + + @Override + public > boolean sample(final T span) { + // unsigned 64 bit comparison with cutoff + return getSamplingId(span) * KNUTH_FACTOR + Long.MIN_VALUE < cutoff(rate); + } + + protected abstract > long getSamplingId(T span); + + @Override + public double getSampleRate() { + return rate; + } + + public static long cutoff(double rate) { + if (rate < 0.5) { + return (long) (rate * MAX) + Long.MIN_VALUE; + } + if (rate < 1.0) { + return (long) ((rate * MAX) + Long.MIN_VALUE); + } + return Long.MAX_VALUE; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/ForcePrioritySampler.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/ForcePrioritySampler.java new file mode 100644 index 0000000000..69aa8bf36d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/ForcePrioritySampler.java @@ -0,0 +1,25 @@ +package datadog.trace.common.sampling; + +import datadog.trace.core.CoreSpan; + +/** A sampler which forces the sampling priority */ +public class ForcePrioritySampler implements Sampler, PrioritySampler { + + private final int prioritySampling; + private final int samplingMechanism; + + public ForcePrioritySampler(final int prioritySampling, final int samplingMechanism) { + this.prioritySampling = prioritySampling; + this.samplingMechanism = samplingMechanism; + } + + @Override + public > boolean sample(final T span) { + return true; + } + + @Override + public > void setSamplingPriority(final T span) { + span.setSamplingPriority(prioritySampling, samplingMechanism); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampler.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampler.java new file mode 100644 index 0000000000..474617de1b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampler.java @@ -0,0 +1,7 @@ +package datadog.trace.common.sampling; + +import datadog.trace.core.CoreSpan; + +public interface PrioritySampler { + > void setSamplingPriority(T span); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampling.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampling.java new file mode 100644 index 0000000000..18446bcdfe --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampling.java @@ -0,0 +1,22 @@ +package datadog.trace.common.sampling; + +/** @deprecated Replaced by {@link datadog.trace.api.sampling.PrioritySampling} . */ +@Deprecated +public class PrioritySampling { + /** + * Implementation detail of the client. will not be sent to the agent or propagated. + * + *

Internal value used when the priority sampling flag has not been set on the span context. + */ + public static final int UNSET = Integer.MIN_VALUE; + /** The sampler has decided to drop the trace. */ + public static final int SAMPLER_DROP = 0; + /** The sampler has decided to keep the trace. */ + public static final int SAMPLER_KEEP = 1; + /** The user has decided to drop the trace. */ + public static final int USER_DROP = -1; + /** The user has decided to keep the trace. */ + public static final int USER_KEEP = 2; + + private PrioritySampling() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateByServiceTraceSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateByServiceTraceSampler.java new file mode 100644 index 0000000000..3434b0681c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateByServiceTraceSampler.java @@ -0,0 +1,168 @@ +package datadog.trace.common.sampling; + +import datadog.trace.api.cache.DDCache; +import datadog.trace.api.cache.DDCaches; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.api.sampling.SamplingMechanism; +import datadog.trace.common.writer.RemoteResponseListener; +import datadog.trace.core.CoreSpan; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A rate sampler which maintains different sample rates per service+env name. + * + *

The configuration of (serviceName,env)->rate is configured by the core agent. + */ +public class RateByServiceTraceSampler implements Sampler, PrioritySampler, RemoteResponseListener { + + private static final Logger log = LoggerFactory.getLogger(RateByServiceTraceSampler.class); + public static final String SAMPLING_AGENT_RATE = "_dd.agent_psr"; + + private static final double DEFAULT_RATE = 1.0; + + private volatile RateSamplersByEnvAndService serviceRates = new RateSamplersByEnvAndService(); + + @Override + public > boolean sample(final T span) { + // Priority sampling sends all traces to the core agent, including traces marked dropped. + // This allows the core agent to collect stats on all traces. + return true; + } + + /** If span is a root span, set the span context samplingPriority to keep or drop */ + @Override + public > void setSamplingPriority(final T span) { + final String serviceName = span.getServiceName(); + final String env = getSpanEnv(span); + + final RateSamplersByEnvAndService rates = serviceRates; + RateSampler sampler = rates.getSampler(env, serviceName); + + if (sampler.sample(span)) { + span.setSamplingPriority( + PrioritySampling.SAMPLER_KEEP, + SAMPLING_AGENT_RATE, + sampler.getSampleRate(), + SamplingMechanism.AGENT_RATE); + } else { + span.setSamplingPriority( + PrioritySampling.SAMPLER_DROP, + SAMPLING_AGENT_RATE, + sampler.getSampleRate(), + SamplingMechanism.AGENT_RATE); + } + } + + private > String getSpanEnv(final T span) { + return span.getTag("env", ""); + } + + @Override + public void onResponse( + final String endpoint, final Map> responseJson) { + final Map newServiceRates = responseJson.get("rate_by_service"); + if (null != newServiceRates) { + log.debug("Update service sampler rates: {} -> {}", endpoint, responseJson); + final Map> updatedEnvServiceRates = + new HashMap<>(newServiceRates.size() * 2); + for (final Map.Entry entry : newServiceRates.entrySet()) { + if (entry.getValue() != null) { + EnvAndService envAndService = EnvAndService.fromString(entry.getKey()); + Map serviceRates = + updatedEnvServiceRates.computeIfAbsent( + envAndService.env, env -> new HashMap<>(newServiceRates.size() * 2)); + serviceRates.computeIfAbsent( + envAndService.service, + service -> + RateByServiceTraceSampler.createRateSampler(entry.getValue().doubleValue())); + } + } + serviceRates = new RateSamplersByEnvAndService(updatedEnvServiceRates); + } + } + + private static RateSampler createRateSampler(final double sampleRate) { + final double sanitizedRate; + if (sampleRate < 0) { + log.error("SampleRate is negative or null, disabling the sampler"); + sanitizedRate = 1; + } else if (sampleRate > 1) { + sanitizedRate = 1; + } else { + sanitizedRate = sampleRate; + } + + return new DeterministicSampler.TraceSampler(sanitizedRate); + } + + private static final class RateSamplersByEnvAndService { + private static final RateSampler DEFAULT = createRateSampler(DEFAULT_RATE); + + private final Map> envServiceRates; + + RateSamplersByEnvAndService() { + this(new HashMap<>(0)); + } + + RateSamplersByEnvAndService(Map> envServiceRates) { + this.envServiceRates = envServiceRates; + } + + // used in tests only + RateSampler getSampler(EnvAndService envAndService) { + return getSampler(envAndService.env, envAndService.service); + } + + public RateSampler getSampler(String env, String service) { + Map serviceRates = envServiceRates.get(env); + if (serviceRates == null) { + return DEFAULT; + } + RateSampler sampler = serviceRates.get(service); + return null == sampler ? DEFAULT : sampler; + } + } + + private static final class EnvAndService { + + private static final DDCache CACHE = DDCaches.newFixedSizeCache(32); + + private static final Function PARSE = + new Function() { + + @Override + public EnvAndService apply(String key) { + // "service:,env:" + int serviceStart = key.indexOf(':') + 1; + int serviceEnd = key.indexOf(',', serviceStart); + int envStart = key.indexOf(':', serviceEnd) + 1; + // both empty or at least one invalid + if ((serviceStart == serviceEnd && envStart == key.length()) + || (serviceStart | serviceEnd | envStart) < 0) { + return DEFAULT; + } + String service = key.substring(serviceStart, serviceEnd); + String env = key.substring(envStart); + return new EnvAndService(env, service); + } + }; + + static final EnvAndService DEFAULT = new EnvAndService("", ""); + + public static EnvAndService fromString(String key) { + return CACHE.computeIfAbsent(key, PARSE); + } + + private final String env; + private final String service; + + private EnvAndService(String env, String service) { + this.env = env; + this.service = service; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateSampler.java new file mode 100644 index 0000000000..d8691a6642 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateSampler.java @@ -0,0 +1,5 @@ +package datadog.trace.common.sampling; + +public interface RateSampler extends Sampler { + double getSampleRate(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RuleBasedTraceSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RuleBasedTraceSampler.java new file mode 100644 index 0000000000..c02a5daaab --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RuleBasedTraceSampler.java @@ -0,0 +1,158 @@ +package datadog.trace.common.sampling; + +import datadog.trace.api.config.TracerConfig; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.api.sampling.SamplingMechanism; +import datadog.trace.common.sampling.SamplingRule.AlwaysMatchesSamplingRule; +import datadog.trace.common.sampling.SamplingRule.OperationSamplingRule; +import datadog.trace.common.sampling.SamplingRule.ServiceSamplingRule; +import datadog.trace.common.sampling.SamplingRule.TraceSamplingRule; +import datadog.trace.core.CoreSpan; +import datadog.trace.core.util.SimpleRateLimiter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RuleBasedTraceSampler> implements Sampler, PrioritySampler { + + private static final Logger log = LoggerFactory.getLogger(RuleBasedTraceSampler.class); + private final List samplingRules; + private final PrioritySampler fallbackSampler; + private final SimpleRateLimiter rateLimiter; + private final long rateLimit; + + public static final String SAMPLING_RULE_RATE = "_dd.rule_psr"; + public static final String SAMPLING_LIMIT_RATE = "_dd.limit_psr"; + + public RuleBasedTraceSampler( + final List samplingRules, + final int rateLimit, + final PrioritySampler fallbackSampler) { + this.samplingRules = samplingRules; + this.fallbackSampler = fallbackSampler; + rateLimiter = new SimpleRateLimiter(rateLimit); + + this.rateLimit = rateLimit; + } + + public static RuleBasedTraceSampler build( + final TraceSamplingRules traceSamplingRules, final Double defaultRate, final int rateLimit) { + return build(null, null, traceSamplingRules, defaultRate, rateLimit); + } + + public static RuleBasedTraceSampler build( + @Deprecated final Map serviceRules, + @Deprecated final Map operationRules, + final TraceSamplingRules traceSamplingRules, + final Double defaultRate, + final int rateLimit) { + + final List samplingRules = new ArrayList<>(); + + if (traceSamplingRules != null && !traceSamplingRules.isEmpty()) { + if ((!serviceRules.isEmpty() || !operationRules.isEmpty())) { + log.warn( + "Both {} and/or {} as well as {} are defined. Only {} will be used for rule-based sampling", + TracerConfig.TRACE_SAMPLING_SERVICE_RULES, + TracerConfig.TRACE_SAMPLING_OPERATION_RULES, + TracerConfig.TRACE_SAMPLING_RULES, + TracerConfig.TRACE_SAMPLING_RULES); + } + // Ignore serviceRules & operationRules if traceSamplingRules are defined + for (TraceSamplingRules.Rule rule : traceSamplingRules.getRules()) { + TraceSamplingRule samplingRule = + new TraceSamplingRule( + rule.getService(), + rule.getName(), + rule.getResource(), + rule.getTags(), + new DeterministicSampler.TraceSampler(rule.getSampleRate())); + samplingRules.add(samplingRule); + } + } else { + // Take into account serviceRules & operationRules only if traceSamplingRules are NOT defined + if (serviceRules != null) { + for (final Entry entry : serviceRules.entrySet()) { + try { + final double rateForEntry = Double.parseDouble(entry.getValue()); + final SamplingRule samplingRule = + new ServiceSamplingRule( + entry.getKey(), new DeterministicSampler.TraceSampler(rateForEntry)); + samplingRules.add(samplingRule); + } catch (final NumberFormatException e) { + log.error("Unable to parse rate for service: {}", entry, e); + } + } + } + + if (operationRules != null) { + for (final Entry entry : operationRules.entrySet()) { + try { + final double rateForEntry = Double.parseDouble(entry.getValue()); + final SamplingRule samplingRule = + new OperationSamplingRule( + entry.getKey(), new DeterministicSampler.TraceSampler(rateForEntry)); + samplingRules.add(samplingRule); + } catch (final NumberFormatException e) { + log.error("Unable to parse rate for operation: {}", entry, e); + } + } + } + } + + if (defaultRate != null) { + final SamplingRule samplingRule = + new AlwaysMatchesSamplingRule(new DeterministicSampler.TraceSampler(defaultRate)); + samplingRules.add(samplingRule); + } + + return new RuleBasedTraceSampler(samplingRules, rateLimit, new RateByServiceTraceSampler()); + } + + @Override + public > boolean sample(final T span) { + return true; + } + + @Override + public > void setSamplingPriority(final T span) { + SamplingRule matchedRule = null; + + for (final SamplingRule samplingRule : samplingRules) { + if (samplingRule.matches(span)) { + matchedRule = samplingRule; + break; + } + } + + if (matchedRule == null) { + fallbackSampler.setSamplingPriority(span); + } else { + if (matchedRule.sample(span)) { + if (rateLimiter.tryAcquire()) { + span.setSamplingPriority( + PrioritySampling.USER_KEEP, + SAMPLING_RULE_RATE, + matchedRule.getSampler().getSampleRate(), + SamplingMechanism.RULE); + } else { + span.setSamplingPriority( + PrioritySampling.USER_DROP, + SAMPLING_RULE_RATE, + matchedRule.getSampler().getSampleRate(), + SamplingMechanism.RULE); + } + span.setMetric(SAMPLING_LIMIT_RATE, rateLimit); + } else { + span.setSamplingPriority( + PrioritySampling.USER_DROP, + SAMPLING_RULE_RATE, + matchedRule.getSampler().getSampleRate(), + SamplingMechanism.RULE); + } + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/Sampler.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/Sampler.java new file mode 100644 index 0000000000..63309af2b9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/Sampler.java @@ -0,0 +1,97 @@ +package datadog.trace.common.sampling; + +import static datadog.trace.bootstrap.instrumentation.api.SamplerConstants.DROP; +import static datadog.trace.bootstrap.instrumentation.api.SamplerConstants.KEEP; + +import datadog.trace.api.Config; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.config.TracerConfig; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.api.sampling.SamplingMechanism; +import datadog.trace.core.CoreSpan; +import java.util.Map; +import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Main interface to sample a collection of traces. */ +public interface Sampler { + + /** + * Sample a collection of traces based on the parent span + * + * @param span the parent span with its context + * @return true when the trace/spans has to be reported/written + */ + > boolean sample(T span); + + final class Builder { + private static final Logger log = LoggerFactory.getLogger(Builder.class); + + public static Sampler forConfig(final Config config, final TraceConfig traceConfig) { + Sampler sampler; + if (config != null) { + final Map serviceRules = config.getTraceSamplingServiceRules(); + final Map operationRules = config.getTraceSamplingOperationRules(); + String traceSamplingRulesJson = config.getTraceSamplingRules(); + TraceSamplingRules traceSamplingRules = TraceSamplingRules.EMPTY; + if (traceSamplingRulesJson != null) { + traceSamplingRules = TraceSamplingRules.deserialize(traceSamplingRulesJson); + } + boolean serviceRulesDefined = serviceRules != null && !serviceRules.isEmpty(); + boolean operationRulesDefined = operationRules != null && !operationRules.isEmpty(); + boolean jsonTraceSamplingRulesDefined = !traceSamplingRules.isEmpty(); + if ((serviceRulesDefined || operationRulesDefined) && jsonTraceSamplingRulesDefined) { + log.warn( + "Both {} and/or {} as well as {} are defined. Only {} will be used for rule-based sampling", + TracerConfig.TRACE_SAMPLING_SERVICE_RULES, + TracerConfig.TRACE_SAMPLING_OPERATION_RULES, + TracerConfig.TRACE_SAMPLING_RULES, + TracerConfig.TRACE_SAMPLING_RULES); + } + Double traceSampleRate = + null != traceConfig ? traceConfig.getTraceSampleRate() : config.getTraceSampleRate(); + if (serviceRulesDefined + || operationRulesDefined + || jsonTraceSamplingRulesDefined + || traceSampleRate != null) { + try { + sampler = + RuleBasedTraceSampler.build( + serviceRules, + operationRules, + traceSamplingRules, + traceSampleRate, + config.getTraceRateLimit()); + } catch (final IllegalArgumentException e) { + log.error("Invalid sampler configuration. Using AllSampler", e); + sampler = new AllSampler(); + } + } else if (config.isPrioritySamplingEnabled()) { + if (KEEP.equalsIgnoreCase(config.getPrioritySamplingForce())) { + log.debug("Force Sampling Priority to: SAMPLER_KEEP."); + sampler = + new ForcePrioritySampler(PrioritySampling.SAMPLER_KEEP, SamplingMechanism.DEFAULT); + } else if (DROP.equalsIgnoreCase(config.getPrioritySamplingForce())) { + log.debug("Force Sampling Priority to: SAMPLER_DROP."); + sampler = + new ForcePrioritySampler(PrioritySampling.SAMPLER_DROP, SamplingMechanism.DEFAULT); + } else { + sampler = new RateByServiceTraceSampler(); + } + } else { + sampler = new AllSampler(); + } + } else { + sampler = new AllSampler(); + } + return sampler; + } + + public static Sampler forConfig(final Properties config) { + return forConfig(Config.get(config), null); + } + + private Builder() {} + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SamplingRule.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SamplingRule.java new file mode 100644 index 0000000000..c2aded26b4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SamplingRule.java @@ -0,0 +1,140 @@ +package datadog.trace.common.sampling; + +import datadog.trace.core.CoreSpan; +import datadog.trace.core.util.Matcher; +import datadog.trace.core.util.Matchers; +import datadog.trace.core.util.SimpleRateLimiter; +import datadog.trace.core.util.TagsMatcher; +import java.util.Map; +import java.util.regex.Pattern; + +public abstract class SamplingRule { + private final RateSampler sampler; + + public SamplingRule(final RateSampler sampler) { + this.sampler = sampler; + } + + public abstract > boolean matches(T span); + + public > boolean sample(final T span) { + return sampler.sample(span); + } + + public RateSampler getSampler() { + return sampler; + } + + public static class AlwaysMatchesSamplingRule extends SamplingRule { + + public AlwaysMatchesSamplingRule(final RateSampler sampler) { + super(sampler); + } + + @Override + public > boolean matches(final T span) { + return true; + } + } + + public abstract static class PatternMatchSamplingRule extends SamplingRule { + private final Pattern pattern; + + public PatternMatchSamplingRule(final String regex, final RateSampler sampler) { + super(sampler); + this.pattern = Pattern.compile(regex); + } + + @Override + public > boolean matches(final T span) { + final CharSequence relevantString = getRelevantString(span); + return relevantString != null && pattern.matcher(relevantString).matches(); + } + + protected abstract > CharSequence getRelevantString(T span); + } + + public static class ServiceSamplingRule extends PatternMatchSamplingRule { + public ServiceSamplingRule(final String regex, final RateSampler sampler) { + super(regex, sampler); + } + + @Override + protected > String getRelevantString(final T span) { + return span.getServiceName(); + } + } + + public static class OperationSamplingRule extends PatternMatchSamplingRule { + public OperationSamplingRule(final String regex, final RateSampler sampler) { + super(regex, sampler); + } + + @Override + protected > CharSequence getRelevantString(final T span) { + return span.getOperationName(); + } + } + + public static final class TraceSamplingRule extends SamplingRule { + private final Matcher serviceMatcher; + private final Matcher operationMatcher; + private final Matcher resourceMatcher; + private final TagsMatcher tagsMatcher; + + public TraceSamplingRule( + final String serviceGlob, + final String operationGlob, + final String resourceGlob, + final Map tags, + final RateSampler sampler) { + super(sampler); + serviceMatcher = Matchers.compileGlob(serviceGlob); + operationMatcher = Matchers.compileGlob(operationGlob); + resourceMatcher = Matchers.compileGlob(resourceGlob); + tagsMatcher = TagsMatcher.create(tags); + } + + @Override + public > boolean matches(T span) { + return Matchers.matches(serviceMatcher, span.getServiceName()) + && Matchers.matches(operationMatcher, span.getOperationName()) + && Matchers.matches(resourceMatcher, span.getResourceName()) + && tagsMatcher.matches(span); + } + } + + public static final class SpanSamplingRule extends SamplingRule { + private final Matcher serviceMatcher; + private final Matcher operationMatcher; + private final SimpleRateLimiter rateLimiter; + + public SpanSamplingRule( + final String serviceName, + final String operationName, + final RateSampler sampler, + final SimpleRateLimiter rateLimiter) { + super(sampler); + + serviceMatcher = Matchers.compileGlob(serviceName); + operationMatcher = Matchers.compileGlob(operationName); + + this.rateLimiter = rateLimiter; + } + + @Override + public > boolean matches(T span) { + return Matchers.matches(serviceMatcher, span.getServiceName()) + && Matchers.matches(operationMatcher, span.getOperationName()); + } + + @Override + public > boolean sample(T span) { + return super.sample(span) && (rateLimiter == null || rateLimiter.tryAcquire()); + } + + public SimpleRateLimiter getRateLimiter() { + return rateLimiter; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SingleSpanSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SingleSpanSampler.java new file mode 100644 index 0000000000..2d01192465 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SingleSpanSampler.java @@ -0,0 +1,93 @@ +package datadog.trace.common.sampling; + +import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES; +import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES_FILE; + +import datadog.trace.api.Config; +import datadog.trace.core.CoreSpan; +import datadog.trace.core.util.SimpleRateLimiter; +import java.util.ArrayList; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public interface SingleSpanSampler { + + > boolean setSamplingPriority(T span); + + final class Builder { + private static final Logger log = LoggerFactory.getLogger(Builder.class); + + public static SingleSpanSampler forConfig(Config config) { + String spanSamplingRules = config.getSpanSamplingRules(); + String spanSamplingRulesFile = config.getSpanSamplingRulesFile(); + + boolean spanSamplingRulesDefined = spanSamplingRules != null && !spanSamplingRules.isEmpty(); + boolean spanSamplingRulesFileDefined = + spanSamplingRulesFile != null && !spanSamplingRulesFile.isEmpty(); + + if (spanSamplingRulesDefined && spanSamplingRulesFileDefined) { + log.warn( + "Both {} and {} defined. {} will be ignored.", + SPAN_SAMPLING_RULES, + SPAN_SAMPLING_RULES_FILE, + SPAN_SAMPLING_RULES_FILE); + } + + if (spanSamplingRulesDefined) { + SpanSamplingRules rules = SpanSamplingRules.deserialize(spanSamplingRules); + if (!rules.isEmpty()) { + return new RuleBasedSingleSpanSampler(rules); + } + } else if (spanSamplingRulesFileDefined) { + SpanSamplingRules rules = SpanSamplingRules.deserializeFile(spanSamplingRulesFile); + if (!rules.isEmpty()) { + return new RuleBasedSingleSpanSampler(rules); + } + } + + return null; + } + + private Builder() {} + } + + final class RuleBasedSingleSpanSampler implements SingleSpanSampler { + private final List spanSamplingRules; + + public RuleBasedSingleSpanSampler(SpanSamplingRules rules) { + if (rules == null) { + throw new NullPointerException("SpanSamplingRules can't be null."); + } + this.spanSamplingRules = new ArrayList<>(); + for (SpanSamplingRules.Rule rule : rules.getRules()) { + RateSampler sampler = new DeterministicSampler.SpanSampler(rule.getSampleRate()); + SimpleRateLimiter simpleRateLimiter = + rule.getMaxPerSecond() == Integer.MAX_VALUE + ? null + : new SimpleRateLimiter(rule.getMaxPerSecond()); + SamplingRule.SpanSamplingRule spanSamplingRule = + new SamplingRule.SpanSamplingRule( + rule.getService(), rule.getName(), sampler, simpleRateLimiter); + spanSamplingRules.add(spanSamplingRule); + } + } + + @Override + public > boolean setSamplingPriority(T span) { + for (SamplingRule.SpanSamplingRule rule : spanSamplingRules) { + if (rule.matches(span)) { + if (rule.sample(span)) { + double rate = rule.getSampler().getSampleRate(); + SimpleRateLimiter rateLimiter = rule.getRateLimiter(); + int limit = rateLimiter == null ? Integer.MAX_VALUE : rateLimiter.getCapacity(); + span.setSpanSamplingPriority(rate, limit); + return true; + } + break; + } + } + return false; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SpanSamplingRules.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SpanSamplingRules.java new file mode 100644 index 0000000000..954ded5480 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SpanSamplingRules.java @@ -0,0 +1,207 @@ +package datadog.trace.common.sampling; + +import com.squareup.moshi.FromJson; +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.JsonReader; +import com.squareup.moshi.Moshi; +import com.squareup.moshi.Types; +import datadog.trace.api.sampling.SamplingRule; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import okio.Okio; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Represents list of Span Sampling Rules read from JSON. See SPAN_SAMPLING_RULES */ +public class SpanSamplingRules { + public static final SpanSamplingRules EMPTY = new SpanSamplingRules(Collections.emptyList()); + private static final Logger log = LoggerFactory.getLogger(SpanSamplingRules.class); + private static final Moshi MOSHI = new Moshi.Builder().add(new RuleAdapter()).build(); + private static final ParameterizedType LIST_OF_RULES = + Types.newParameterizedType(List.class, Rule.class); + private static final JsonAdapter> LIST_OF_RULES_ADAPTER = MOSHI.adapter(LIST_OF_RULES); + private final List rules; + + public SpanSamplingRules(List rules) { + this.rules = Collections.unmodifiableList(rules); + } + + public static SpanSamplingRules deserialize(String json) { + SpanSamplingRules result = EMPTY; + try { + result = filterOutNullRules(LIST_OF_RULES_ADAPTER.fromJson(json)); + } catch (Throwable ex) { + log.error("Couldn't parse Span Sampling Rules from JSON: {}", json, ex); + } + return result; + } + + public static SpanSamplingRules deserializeFile(String jsonFile) { + SpanSamplingRules result = EMPTY; + try (JsonReader reader = JsonReader.of(Okio.buffer(Okio.source(new File(jsonFile))))) { + result = filterOutNullRules(LIST_OF_RULES_ADAPTER.fromJson(reader)); + } catch (FileNotFoundException e) { + log.warn("Span Sampling Rules file {} doesn't exist", jsonFile); + } catch (IOException e) { + log.error("Couldn't read Span Sampling Rules file {}.", jsonFile, e); + } catch (Throwable ex) { + log.error("Couldn't parse Span Sampling Rules from JSON file {}.", jsonFile, ex); + } + return result; + } + + private static SpanSamplingRules filterOutNullRules(List rules) { + if (rules == null || rules.isEmpty()) { + return EMPTY; + } + List notNullRules = new ArrayList<>(rules.size()); + for (Rule rule : rules) { + if (rule != null) { + notNullRules.add(rule); + } + } + if (notNullRules.isEmpty()) { + return EMPTY; + } + return new SpanSamplingRules(notNullRules); + } + + public List getRules() { + return rules; + } + + public boolean isEmpty() { + return rules.isEmpty(); + } + + public static final class Rule implements SamplingRule.SpanSamplingRule { + private final String service; + private final String name; + private final String resource; + private final Map tags; + private final double sampleRate; + private final int maxPerSecond; + + private Rule( + String service, + String name, + String resource, + Map tags, + double sampleRate, + int maxPerSecond) { + this.service = service; + this.name = name; + this.resource = resource; + this.tags = tags; + this.sampleRate = sampleRate; + this.maxPerSecond = maxPerSecond; + } + + /** + * Validate and create a {@link Rule} from its {@link JsonRule} representation. + * + * @param jsonRule The {@link JsonRule} to validate. + * @return A {@link Rule} if the {@link JsonRule} is valid, {@code null} otherwise. + */ + public static Rule create(JsonRule jsonRule) { + String service = SamplingRule.normalizeGlob(jsonRule.service); + String name = SamplingRule.normalizeGlob(jsonRule.name); + String resource = SamplingRule.normalizeGlob(jsonRule.resource); + Map tags = jsonRule.tags; + if (tags == null) { + tags = Collections.emptyMap(); + } + double sampleRate = 1D; + if (jsonRule.sample_rate != null) { + try { + sampleRate = Double.parseDouble(jsonRule.sample_rate); + } catch (NumberFormatException ex) { + logRuleError(jsonRule, "sample_rate must be a number between 0.0 and 1.0"); + return null; + } + if (sampleRate < 0D || sampleRate > 1D) { + logRuleError(jsonRule, "sample_rate must be between 0.0 and 1.0"); + return null; + } + } + int maxPerSecond = Integer.MAX_VALUE; + if (jsonRule.max_per_second != null) { + try { + double parsedMaxPerSeconds = Double.parseDouble(jsonRule.max_per_second); + if (parsedMaxPerSeconds <= 0) { + logRuleError(jsonRule, "max_per_second must be greater than 0.0"); + return null; + } + maxPerSecond = Math.max((int) parsedMaxPerSeconds, 1); + } catch (NumberFormatException ex) { + logRuleError(jsonRule, "max_per_second must be a number greater than 0.0"); + return null; + } + } + return new Rule(service, name, resource, tags, sampleRate, maxPerSecond); + } + + private static void logRuleError(JsonRule rule, String error) { + log.error("Skipping invalid Span Sampling Rule: {} - {}", rule, error); + } + + @Override + public String getService() { + return service; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getResource() { + return resource; + } + + @Override + public Map getTags() { + return tags; + } + + @Override + public double getSampleRate() { + return sampleRate; + } + + @Override + public int getMaxPerSecond() { + return maxPerSecond; + } + } + + private static final class JsonRule { + private static final JsonAdapter jsonAdapter = MOSHI.adapter(JsonRule.class); + + String service; + String name; + String resource; + Map tags; + String sample_rate; // Use String to be able to map int as double + String max_per_second; // Use String to be able to map int as double + + @Override + public String toString() { + return jsonAdapter.toJson(this); + } + } + + private static final class RuleAdapter { + @FromJson + Rule fromJson(JsonRule jsonRule) { + return Rule.create(jsonRule); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/TraceSamplingRules.java b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/TraceSamplingRules.java new file mode 100644 index 0000000000..d97e1a4081 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/TraceSamplingRules.java @@ -0,0 +1,163 @@ +package datadog.trace.common.sampling; + +import com.squareup.moshi.FromJson; +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.Moshi; +import com.squareup.moshi.Types; +import datadog.trace.api.sampling.SamplingRule; +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Represents list of Trace Sampling Rules read from JSON. See TRACE_SAMPLING_RULES */ +public class TraceSamplingRules { + + public static final TraceSamplingRules EMPTY = new TraceSamplingRules(Collections.emptyList()); + private static final Logger log = LoggerFactory.getLogger(TraceSamplingRules.class); + private static final Moshi MOSHI = new Moshi.Builder().add(new RuleAdapter()).build(); + private static final ParameterizedType LIST_OF_RULES = + Types.newParameterizedType(List.class, Rule.class); + private static final JsonAdapter> LIST_OF_RULES_ADAPTER = MOSHI.adapter(LIST_OF_RULES); + private final List rules; + + public TraceSamplingRules(List rules) { + this.rules = Collections.unmodifiableList(rules); + } + + public static TraceSamplingRules deserialize(String json) { + TraceSamplingRules result = EMPTY; + try { + result = filterOutNullRules(LIST_OF_RULES_ADAPTER.fromJson(json)); + } catch (Throwable ex) { + log.error("Couldn't parse Trace Sampling Rules from JSON: {}", json, ex); + } + return result; + } + + private static TraceSamplingRules filterOutNullRules(List rules) { + if (rules == null || rules.isEmpty()) { + return EMPTY; + } + List notNullRules = new ArrayList<>(rules.size()); + for (Rule rule : rules) { + if (rule != null) { + notNullRules.add(rule); + } + } + if (notNullRules.isEmpty()) { + return EMPTY; + } + return new TraceSamplingRules(notNullRules); + } + + public List getRules() { + return rules; + } + + public boolean isEmpty() { + return this.rules.isEmpty(); + } + + public static final class Rule implements SamplingRule.TraceSamplingRule { + private final String service; + private final String name; + private final String resource; + private final Map tags; + private final double sampleRate; + + private Rule( + String service, String name, String resource, Map tags, double sampleRate) { + this.service = service; + this.name = name; + this.resource = resource; + this.tags = tags; + this.sampleRate = sampleRate; + } + + /** + * Validate and create a {@link Rule} from its {@link JsonRule} representation. + * + * @param jsonRule The {@link JsonRule} to validate. + * @return A {@link Rule} if the {@link JsonRule} is valid, {@code null} otherwise. + */ + public static Rule create(JsonRule jsonRule) { + String service = SamplingRule.normalizeGlob(jsonRule.service); + String name = SamplingRule.normalizeGlob(jsonRule.name); + String resource = SamplingRule.normalizeGlob(jsonRule.resource); + Map tags = jsonRule.tags; + if (tags == null) { + tags = Collections.emptyMap(); + } + double sampleRate = 1D; + if (jsonRule.sample_rate != null) { + try { + sampleRate = Double.parseDouble(jsonRule.sample_rate); + } catch (NumberFormatException ex) { + logRuleError(jsonRule, "sample_rate must be a number between 0.0 and 1.0"); + return null; + } + if (sampleRate < 0D || sampleRate > 1D) { + logRuleError(jsonRule, "sample_rate must be between 0.0 and 1.0"); + return null; + } + } + return new Rule(service, name, resource, tags, sampleRate); + } + + private static void logRuleError(JsonRule rule, String error) { + log.error("Skipping invalid Trace Sampling Rule: {} - {}", rule, error); + } + + @Override + public String getService() { + return service; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getResource() { + return resource; + } + + @Override + public Map getTags() { + return tags; + } + + @Override + public double getSampleRate() { + return sampleRate; + } + } + + private static final class JsonRule { + private static final JsonAdapter jsonAdapter = MOSHI.adapter(JsonRule.class); + + String service; + String name; + String resource; + Map tags; + String target_span; + String sample_rate; + + @Override + public String toString() { + return jsonAdapter.toJson(this); + } + } + + private static final class RuleAdapter { + @FromJson + Rule fromJson(JsonRule jsonRule) { + return Rule.create(jsonRule); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/CompositePayloadDispatcher.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/CompositePayloadDispatcher.java new file mode 100644 index 0000000000..3822d62160 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/CompositePayloadDispatcher.java @@ -0,0 +1,45 @@ +package datadog.trace.common.writer; + +import datadog.trace.core.CoreSpan; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class CompositePayloadDispatcher implements PayloadDispatcher { + + private final PayloadDispatcher[] delegates; + + public CompositePayloadDispatcher(PayloadDispatcher... delegates) { + this.delegates = delegates; + } + + @Override + public void onDroppedTrace(int spanCount) { + for (PayloadDispatcher delegate : delegates) { + delegate.onDroppedTrace(spanCount); + } + } + + @Override + public void addTrace(List> trace) { + for (PayloadDispatcher delegate : delegates) { + delegate.addTrace(trace); + } + } + + @Override + public void flush() { + for (PayloadDispatcher delegate : delegates) { + delegate.flush(); + } + } + + @Override + public Collection> getApis() { + Collection> apis = new ArrayList<>(delegates.length); + for (PayloadDispatcher delegate : delegates) { + apis.addAll(delegate.getApis()); + } + return apis; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/DDSpanJsonAdapter.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/DDSpanJsonAdapter.java new file mode 100644 index 0000000000..93c6995d4e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/DDSpanJsonAdapter.java @@ -0,0 +1,111 @@ +package datadog.trace.common.writer; + +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.JsonReader; +import com.squareup.moshi.Moshi; +import com.squareup.moshi.Types; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTraceId; +import datadog.trace.core.DDSpan; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Map; +import java.util.Set; + +class DDSpanJsonAdapter extends JsonAdapter { + private final boolean hexIds; + + DDSpanJsonAdapter(final boolean hexIds) { + this.hexIds = hexIds; + } + + public static Factory buildFactory(final boolean hexIds) { + return new Factory() { + @Override + public JsonAdapter create( + final Type type, final Set annotations, final Moshi moshi) { + final Class rawType = Types.getRawType(type); + if (rawType.isAssignableFrom(DDSpan.class)) { + return new DDSpanJsonAdapter(hexIds); + } + return null; + } + }; + } + + @Override + public DDSpan fromJson(final JsonReader reader) { + throw new UnsupportedOperationException(); + } + + @Override + public void toJson(final com.squareup.moshi.JsonWriter writer, final DDSpan span) + throws IOException { + writer.beginObject(); + writer.name("service"); + writer.value(span.getServiceName()); + writer.name("name"); + writer.value(span.getOperationName().toString()); + writer.name("resource"); + writer.value(span.getResourceName().toString()); + writer.name("trace_id"); + writeTraceId(writer, span.getTraceId()); + writer.name("span_id"); + writeSpanId(writer, span.getSpanId()); + writer.name("parent_id"); + writeSpanId(writer, span.getParentId()); + writer.name("start"); + writer.value(span.getStartTime()); + writer.name("duration"); + writer.value(span.getDurationNano()); + writer.name("type"); + writer.value(span.getSpanType()); + writer.name("error"); + writer.value(span.getError()); + writer.name("metrics"); + writer.beginObject(); + for (final Map.Entry entry : span.getTags().entrySet()) { + if (entry.getValue() instanceof Number) { + writer.name(entry.getKey()); + writer.value((Number) entry.getValue()); + } + } + writer.endObject(); + writer.name("meta"); + writer.beginObject(); + final Map tags = span.getTags(); + for (final Map.Entry entry : span.context().getBaggageItems().entrySet()) { + if (!tags.containsKey(entry.getKey())) { + writer.name(entry.getKey()); + writer.value(entry.getValue()); + } + } + for (final Map.Entry entry : tags.entrySet()) { + if (!(entry.getValue() instanceof Number)) { + writer.name(entry.getKey()); + writer.value(String.valueOf(entry.getValue())); + } + } + writer.endObject(); + writer.endObject(); + } + + private void writeTraceId(final com.squareup.moshi.JsonWriter writer, final DDTraceId id) + throws IOException { + if (hexIds) { + writer.value(id.toHexString()); + } else { + writer.value(id.toLong()); + } + } + + private void writeSpanId(final com.squareup.moshi.JsonWriter writer, final long id) + throws IOException { + if (hexIds) { + writer.value(DDSpanId.toHexString(id)); + } else { + writer.value(id); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ListWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ListWriter.java new file mode 100644 index 0000000000..6393547c6e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ListWriter.java @@ -0,0 +1,167 @@ +package datadog.trace.common.writer; + +import datadog.trace.core.DDSpan; +import datadog.trace.core.MetadataConsumer; +import datadog.trace.core.tagprocessor.PeerServiceCalculator; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** List writer used by tests mostly */ +public class ListWriter extends CopyOnWriteArrayList> implements Writer { + + private static final Logger log = LoggerFactory.getLogger(ListWriter.class); + + public static final Filter ACCEPT_ALL = + new Filter() { + @Override + public boolean accept(List trace) { + return true; + } + }; + + private final List latches = new ArrayList<>(); + private final AtomicInteger traceCount = new AtomicInteger(); + private final TraceStructureWriter structureWriter = new TraceStructureWriter(true); + + private final PeerServiceCalculator peerServiceCalculator = new PeerServiceCalculator(); + private Filter filter = ACCEPT_ALL; + + public List firstTrace() { + return get(0); + } + + @Override + public void write(List trace) { + if (!filter.accept(trace)) { + return; + } + for (DDSpan span : trace) { + // This is needed to properly do all delayed processing to make this writer even + // remotely realistic so the test actually test something + span.processTagsAndBaggage(MetadataConsumer.NO_OP); + } + traceCount.incrementAndGet(); + synchronized (latches) { + add(trace); + for (final CountDownLatch latch : latches) { + if (size() >= latch.getCount()) { + while (latch.getCount() > 0) { + latch.countDown(); + } + } + } + } + structureWriter.write(trace); + } + + public boolean waitForTracesMax(final int number, int seconds) + throws InterruptedException, TimeoutException { + final CountDownLatch latch = new CountDownLatch(number); + synchronized (latches) { + if (size() >= number) { + return true; + } + latches.add(latch); + } + return latch.await(seconds, TimeUnit.SECONDS); + } + + public void waitForTraces(final int number) throws InterruptedException, TimeoutException { + if (!waitForTracesMax(number, 20)) { + String msg = + "Timeout waiting for " + + number + + " trace(s). ListWriter.size() == " + + size() + + " : " + + super.toString(); + log.warn(msg); + throw new TimeoutException(msg); + } + } + + public void waitUntilReported(final DDSpan span) throws InterruptedException, TimeoutException { + waitUntilReported(span, 20, TimeUnit.SECONDS); + } + + public void waitUntilReported(final DDSpan span, int timeout, TimeUnit unit) + throws InterruptedException, TimeoutException { + while (true) { + final CountDownLatch latch = new CountDownLatch(size() + 1); + synchronized (latches) { + latches.add(latch); + } + if (isReported(span)) { + return; + } + if (!latch.await(timeout, unit)) { + String msg = "Timeout waiting for span to be reported: " + span; + log.warn(msg); + throw new TimeoutException(msg); + } + } + } + + /** + * Set a filter to be applied to all incoming traces to determine whether they should be written + * or not. + */ + public void setFilter(Filter filter) { + this.filter = filter; + } + + private boolean isReported(DDSpan span) { + for (List trace : this) { + for (DDSpan aSpan : trace) { + if (aSpan == span) { + return true; + } + } + } + return false; + } + + @Override + public void incrementDropCounts(int spanCount) {} + + @Override + public void start() { + close(); + } + + @Override + public boolean flush() { + filter = ACCEPT_ALL; + return true; + } + + @Override + public void close() { + clear(); + synchronized (latches) { + for (final CountDownLatch latch : latches) { + while (latch.getCount() > 0) { + latch.countDown(); + } + } + latches.clear(); + } + } + + @Override + public String toString() { + return "ListWriter { size=" + size() + " }"; + } + + /** Interface for filtering out select traces from being written. */ + public interface Filter { + boolean accept(List trace); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/LoggingWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/LoggingWriter.java new file mode 100644 index 0000000000..24a6361db3 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/LoggingWriter.java @@ -0,0 +1,52 @@ +package datadog.trace.common.writer; + +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.Moshi; +import com.squareup.moshi.Types; +import datadog.trace.core.DDSpan; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LoggingWriter implements Writer { + + private static final Logger log = LoggerFactory.getLogger(LoggingWriter.class); + private static final JsonAdapter> TRACE_ADAPTER = + new Moshi.Builder() + .add(DDSpanJsonAdapter.buildFactory(false)) + .build() + .adapter(Types.newParameterizedType(List.class, DDSpan.class)); + + @Override + public void write(final List trace) { + try { + log.info("write(trace): {}", TRACE_ADAPTER.toJson(trace)); + } catch (final Exception e) { + log.error("error writing(trace): {}", trace, e); + } + } + + @Override + public void start() { + log.info("start()"); + } + + @Override + public boolean flush() { + log.info("flush()"); + return true; + } + + @Override + public void close() { + log.info("close()"); + } + + @Override + public void incrementDropCounts(int spanCount) {} + + @Override + public String toString() { + return "LoggingWriter { }"; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java new file mode 100644 index 0000000000..a523d44de9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java @@ -0,0 +1,99 @@ +package datadog.trace.common.writer; + +import static datadog.trace.serialization.msgpack.MsgPackWriter.ARRAY16; +import static datadog.trace.serialization.msgpack.MsgPackWriter.ARRAY32; +import static datadog.trace.serialization.msgpack.MsgPackWriter.FIXARRAY; +import static datadog.trace.serialization.msgpack.MsgPackWriter.FIXMAP; +import static datadog.trace.serialization.msgpack.MsgPackWriter.MAP16; +import static datadog.trace.serialization.msgpack.MsgPackWriter.MAP32; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.WritableByteChannel; +import okhttp3.RequestBody; + +public abstract class Payload { + + private static final ByteBuffer EMPTY_ARRAY = ByteBuffer.allocate(1).put(0, (byte) 0x90); + + private int traceCount = 0; + private long droppedTraces = 0; + private long droppedSpans = 0; + protected ByteBuffer body = EMPTY_ARRAY.duplicate(); + + public Payload withBody(int traceCount, ByteBuffer body) { + this.traceCount = traceCount; + if (null != body) { + this.body = body; + } + return this; + } + + public Payload withDroppedTraces(long droppedTraceCount) { + this.droppedTraces += droppedTraceCount; + return this; + } + + public Payload withDroppedSpans(long droppedSpanCount) { + this.droppedSpans += droppedSpanCount; + return this; + } + + public int traceCount() { + return traceCount; + } + + public long droppedTraces() { + return droppedTraces; + } + + public long droppedSpans() { + return droppedSpans; + } + + public abstract int sizeInBytes(); + + public abstract void writeTo(WritableByteChannel channel) throws IOException; + + public abstract RequestBody toRequest(); + + protected int msgpackArrayHeaderSize(int count) { + if (count < 0x10) { + return 1; + } else if (count < 0x10000) { + return 3; + } else { + return 5; + } + } + + protected int msgpackMapHeaderSize(int count) { + if (count < 0x10) { + return 1; + } else if (count < 0x10000) { + return 3; + } else { + return 5; + } + } + + protected ByteBuffer msgpackArrayHeader(int count) { + if (count < 0x10) { + return ByteBuffer.allocate(1).put(0, (byte) (FIXARRAY | count)); + } else if (count < 0x10000) { + return ByteBuffer.allocate(3).put(0, ARRAY16).putShort(1, (short) count); + } else { + return ByteBuffer.allocate(5).put(0, ARRAY32).putInt(1, count); + } + } + + protected ByteBuffer msgpackMapHeader(int count) { + if (count < 0x10) { + return ByteBuffer.allocate(1).put(0, (byte) (FIXMAP | count)); + } else if (count < 0x10000) { + return ByteBuffer.allocate(3).put(0, MAP16).putShort((short) count); + } else { + return ByteBuffer.allocate(5).put(0, MAP32).putInt(1, count); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcher.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcher.java new file mode 100644 index 0000000000..ee39606822 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcher.java @@ -0,0 +1,16 @@ +package datadog.trace.common.writer; + +import datadog.trace.core.CoreSpan; +import java.util.Collection; +import java.util.List; + +interface PayloadDispatcher { + void onDroppedTrace(int spanCount); + + void addTrace(List> trace); + + void flush(); + + // used by tests + Collection> getApis(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcherImpl.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcherImpl.java new file mode 100644 index 0000000000..c410785fa9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcherImpl.java @@ -0,0 +1,129 @@ +package datadog.trace.common.writer; + +import datadog.trace.monitor.Monitoring; +import datadog.trace.monitor.Recording; +import datadog.trace.serialization.ByteBufferConsumer; +import datadog.trace.serialization.FlushingBuffer; +import datadog.trace.serialization.WritableFormatter; +import datadog.trace.serialization.msgpack.MsgPackWriter; +import datadog.trace.core.CoreSpan; +import datadog.trace.core.monitor.HealthMetrics; +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.jctools.counters.CountersFactory; +import org.jctools.counters.FixedSizeStripedLongCounter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PayloadDispatcherImpl implements ByteBufferConsumer, PayloadDispatcher { + + private static final Logger log = LoggerFactory.getLogger(PayloadDispatcherImpl.class); + + private final RemoteApi api; + private final RemoteMapperDiscovery mapperDiscovery; + private final HealthMetrics healthMetrics; + private final Monitoring monitoring; + + private Recording batchTimer; + private RemoteMapper mapper; + private WritableFormatter packer; + + private final FixedSizeStripedLongCounter droppedSpanCount = + CountersFactory.createFixedSizeStripedCounter(8); + private final FixedSizeStripedLongCounter droppedTraceCount = + CountersFactory.createFixedSizeStripedCounter(8); + + public PayloadDispatcherImpl( + RemoteMapperDiscovery mapperDiscovery, + RemoteApi api, + HealthMetrics healthMetrics, + Monitoring monitoring) { + this.mapperDiscovery = mapperDiscovery; + this.api = api; + this.healthMetrics = healthMetrics; + this.monitoring = monitoring; + } + + @Override + public void flush() { + if (null != packer) { + packer.flush(); + } + } + + @Override + public Collection> getApis() { + return Collections.singleton(api.getClass()); + } + + @Override + public void onDroppedTrace(int spanCount) { + droppedSpanCount.inc(spanCount); + droppedTraceCount.inc(); + } + + @Override + public void addTrace(List> trace) { + selectMapper(); + // the call below is blocking and will trigger IO if a flush is necessary + // there are alternative approaches to avoid blocking here, such as + // introducing an unbound queue and another thread to do the IO + // however, we can't block the application threads from here. + if (null == mapper || !packer.format(trace, mapper)) { + healthMetrics.onFailedPublish( + trace.isEmpty() ? 0 : trace.get(0).samplingPriority(), trace.size()); + } + } + + private void selectMapper() { + if (null == mapper) { + if (mapperDiscovery.getMapper() == null) { + mapperDiscovery.discover(); + } + + mapper = mapperDiscovery.getMapper(); + if (null != mapper && null == packer) { + batchTimer = + monitoring.newTimer("tracer.trace.buffer.fill.time", "endpoint:" + mapper.endpoint()); + packer = new MsgPackWriter(new FlushingBuffer(mapper.messageBufferSize(), this)); + batchTimer.start(); + } + } + } + + Payload newPayload(int messageCount, ByteBuffer buffer) { + return mapper + .newPayload() + .withBody(messageCount, buffer) + .withDroppedSpans(droppedSpanCount.getAndReset()) + .withDroppedTraces(droppedTraceCount.getAndReset()); + } + + @Override + public void accept(int messageCount, ByteBuffer buffer) { + // the packer calls this when the buffer is full, + // or when the packer is flushed at a heartbeat + if (messageCount > 0) { + batchTimer.reset(); + Payload payload = newPayload(messageCount, buffer); + final int sizeInBytes = payload.sizeInBytes(); + healthMetrics.onSerialize(sizeInBytes); + RemoteApi.Response response = api.sendSerializedTraces(payload); + mapper.reset(); + if (response.success()) { + if (log.isDebugEnabled()) { + log.debug("Successfully sent {} traces to the API", messageCount); + } + healthMetrics.onSend(messageCount, sizeInBytes, response); + } else { + if (log.isDebugEnabled()) { + log.debug( + "Failed to send {} traces of size {} bytes to the API", messageCount, sizeInBytes); + } + healthMetrics.onFailedSend(messageCount, sizeInBytes, response); + } + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PrintingWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PrintingWriter.java new file mode 100644 index 0000000000..e882abcd5e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PrintingWriter.java @@ -0,0 +1,66 @@ +package datadog.trace.common.writer; + +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.Moshi; +import com.squareup.moshi.Types; +import datadog.trace.core.DDSpan; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import okio.BufferedSink; +import okio.Okio; + +public class PrintingWriter implements Writer { + private final BufferedSink sink; + private final JsonAdapter>>> jsonAdapter; + + public PrintingWriter(final OutputStream outputStream, final boolean hexIds) { + sink = Okio.buffer(Okio.sink(outputStream)); + + this.jsonAdapter = + new Moshi.Builder() + .add(DDSpanJsonAdapter.buildFactory(hexIds)) + .build() + .adapter( + Types.newParameterizedType( + Map.class, + String.class, + Types.newParameterizedType( + List.class, Types.newParameterizedType(List.class, DDSpan.class)))); + } + + @Override + public void write(final List trace) { + final List> tracesList = Collections.singletonList(trace); + try { + synchronized (sink) { + jsonAdapter.toJson(sink, Collections.singletonMap("traces", tracesList)); + sink.writeString("\n", StandardCharsets.UTF_8); + sink.flush(); + } + } catch (final IOException e) { + // do nothing + } + } + + @Override + public void start() { + // do nothing + } + + @Override + public boolean flush() { + return true; + } + + @Override + public void close() { + // do nothing + } + + @Override + public void incrementDropCounts(int spanCount) {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteApi.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteApi.java new file mode 100644 index 0000000000..232f5a8d2f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteApi.java @@ -0,0 +1,152 @@ +package datadog.trace.common.writer; + +import datadog.trace.relocate.api.IOLogger; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.io.IOException; +import org.slf4j.Logger; + +public abstract class RemoteApi { + + protected final IOLogger ioLogger = new IOLogger(getLogger()); + + protected long totalTraces = 0; + protected long receivedTraces = 0; + protected long sentTraces = 0; + protected long failedTraces = 0; + + protected void countAndLogSuccessfulSend(final int traceCount, final int sizeInBytes) { + // count the successful traces + sentTraces += traceCount; + + ioLogger.success(createSendLogMessage(traceCount, sizeInBytes, "Success")); + } + + protected void countAndLogFailedSend( + final int traceCount, + final int sizeInBytes, + final okhttp3.Response response, + final IOException outer) { + // count the failed traces + failedTraces += traceCount; + // these are used to catch and log if there is a failure in debug logging the response body + String responseBody = getResponseBody(response); + String sendErrorString = + createSendLogMessage( + traceCount, sizeInBytes, responseBody.isEmpty() ? "Error" : responseBody); + + ioLogger.error(sendErrorString, toLoggerResponse(response, responseBody), outer); + } + + protected static IOLogger.Response toLoggerResponse(okhttp3.Response response, String body) { + if (response == null) { + return null; + } + return new IOLogger.Response(response.code(), response.message(), body); + } + + protected String createSendLogMessage( + final int traceCount, final int sizeInBytes, final String prefix) { + String sizeString = sizeInBytes > 1024 ? (sizeInBytes / 1024) + "KB" : sizeInBytes + "B"; + return prefix + + " while sending " + + traceCount + + " (size=" + + sizeString + + ")" + + " traces." + + " Total: " + + totalTraces + + ", Received: " + + receivedTraces + + ", Sent: " + + sentTraces + + ", Failed: " + + failedTraces + + "."; + } + + @SuppressFBWarnings("DCN_NULLPOINTER_EXCEPTION") + protected static String getResponseBody(okhttp3.Response response) { + if (response != null) { + try { + return response.body().string().trim(); + } catch (NullPointerException | IOException ignored) { + } + } + return ""; + } + + protected abstract Response sendSerializedTraces(final Payload payload); + + protected abstract Logger getLogger(); + + /** + * Encapsulates an attempted response from the remote location. + * + *

If communication fails or times out, the Response will NOT be successful and will lack + * status code, but will have an exception. + * + *

If an communication occurs, the Response will have a status code and will be marked as + * success or fail in accordance with the code. + * + *

NOTE: A successful communication may still contain an exception if there was a problem + * parsing the response from the Datadog agent. + */ + public static final class Response { + /** Factory method for a successful request with a trivial response body */ + public static Response success(final int status) { + return new Response(true, status, null, null); + } + + /** Factory method for a successful request with a trivial response body */ + public static Response success(final int status, String response) { + return new Response(true, status, null, response); + } + + /** Factory method for a successful request will a malformed response body */ + public static Response success(final int status, final Throwable exception) { + return new Response(true, status, exception, null); + } + + /** Factory method for a request that receive an error status in response */ + public static Response failed(final int status) { + return new Response(false, status, null, null); + } + + /** Factory method for a failed communication attempt */ + public static Response failed(final Throwable exception) { + return new Response(false, null, exception, null); + } + + private final boolean success; + private final Integer status; + private final Throwable exception; + private final String response; + + private Response( + final boolean success, final Integer status, final Throwable exception, String response) { + this.success = success; + this.status = status; + this.exception = exception; + this.response = response; + } + + public final boolean success() { + return success; + } + + // TODO: DQH - In Java 8, switch to OptionalInteger + public final Integer status() { + return status; + } + + // TODO: DQH - In Java 8, switch to Optional? + public final Throwable exception() { + return exception; + } + + public final String response() { + return response; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapper.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapper.java new file mode 100644 index 0000000000..48b64de1be --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapper.java @@ -0,0 +1,66 @@ +package datadog.trace.common.writer; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import datadog.trace.serialization.Mapper; +import datadog.trace.serialization.Writable; +import datadog.trace.api.DDTags; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.core.CoreSpan; +import java.util.List; + +public interface RemoteMapper extends Mapper>> { + + RemoteMapper NO_OP = new NoopRemoteMapper(); + + byte[] RUNTIME_ID = DDTags.RUNTIME_ID_TAG.getBytes(UTF_8); + byte[] LANGUAGE = DDTags.LANGUAGE_TAG_KEY.getBytes(UTF_8); + + byte[] SERVICE = "service".getBytes(UTF_8); + byte[] NAME = "name".getBytes(UTF_8); + byte[] RESOURCE = "resource".getBytes(UTF_8); + byte[] TRACE_ID = "trace_id".getBytes(UTF_8); + byte[] SPAN_ID = "span_id".getBytes(UTF_8); + byte[] PARENT_ID = "parent_id".getBytes(UTF_8); + byte[] START = "start".getBytes(UTF_8); + byte[] DURATION = "duration".getBytes(UTF_8); + byte[] TYPE = "type".getBytes(UTF_8); + byte[] ERROR = "error".getBytes(UTF_8); + byte[] METRICS = "metrics".getBytes(UTF_8); + byte[] META = "meta".getBytes(UTF_8); + + UTF8BytesString HTTP_STATUS = UTF8BytesString.create(Tags.HTTP_STATUS); + + Payload newPayload(); + + int messageBufferSize(); + + void reset(); + + String endpoint(); + + class NoopRemoteMapper implements RemoteMapper { + + @Override + public void map(List> data, Writable packer) {} + + @Override + public Payload newPayload() { + return null; + } + + @Override + public int messageBufferSize() { + return 0; + } + + @Override + public void reset() {} + + @Override + public String endpoint() { + return null; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapperDiscovery.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapperDiscovery.java new file mode 100644 index 0000000000..a09674282f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapperDiscovery.java @@ -0,0 +1,7 @@ +package datadog.trace.common.writer; + +public interface RemoteMapperDiscovery { + void discover(); + + RemoteMapper getMapper(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteResponseListener.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteResponseListener.java new file mode 100644 index 0000000000..d51440a087 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteResponseListener.java @@ -0,0 +1,8 @@ +package datadog.trace.common.writer; + +import java.util.Map; + +public interface RemoteResponseListener { + /** Invoked after the api receives a response from the remote service. */ + void onResponse(String endpoint, Map> responseJson); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/SpanSamplingWorker.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/SpanSamplingWorker.java new file mode 100644 index 0000000000..fb1b4ec9e2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/SpanSamplingWorker.java @@ -0,0 +1,193 @@ +package datadog.trace.common.writer; + +import static datadog.trace.util.AgentThreadFactory.AgentThread.SPAN_SAMPLING_PROCESSOR; +import static datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; +import static datadog.trace.util.AgentThreadFactory.newAgentThread; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import datadog.trace.ddagent.DroppingPolicy; +import datadog.trace.common.sampling.SingleSpanSampler; +import datadog.trace.core.DDSpan; +import datadog.trace.core.monitor.HealthMetrics; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import org.jctools.queues.MessagePassingQueue; +import org.jctools.queues.MpscBlockingConsumerArrayQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public interface SpanSamplingWorker extends AutoCloseable { + static SpanSamplingWorker build( + int capacity, + Queue primaryQueue, + Queue secondaryQueue, + SingleSpanSampler singleSpanSampler, + HealthMetrics healthMetrics, + DroppingPolicy droppingPolicy) { + if (singleSpanSampler == null) { + return new NoopSpanSamplingWorker(); + } + return new DefaultSpanSamplingWorker( + capacity, primaryQueue, secondaryQueue, singleSpanSampler, healthMetrics, droppingPolicy); + } + + void start(); + + Queue getSpanSamplingQueue(); + + @Override + void close(); + + class DefaultSpanSamplingWorker implements SpanSamplingWorker { + + private static final Logger log = LoggerFactory.getLogger(SpanSamplingWorker.class); + + private final Thread spanSamplingThread; + private final SamplingHandler samplingHandler; + private final MpscBlockingConsumerArrayQueue spanSamplingQueue; + private final Queue primaryQueue; + private final Queue secondaryQueue; + private final SingleSpanSampler singleSpanSampler; + private final HealthMetrics healthMetrics; + + private final DroppingPolicy droppingPolicy; + + protected DefaultSpanSamplingWorker( + int capacity, + Queue primaryQueue, + Queue secondaryQueue, + SingleSpanSampler singleSpanSampler, + HealthMetrics healthMetrics, + DroppingPolicy droppingPolicy) { + this.samplingHandler = new SamplingHandler(); + this.spanSamplingThread = newAgentThread(SPAN_SAMPLING_PROCESSOR, samplingHandler); + this.spanSamplingQueue = new MpscBlockingConsumerArrayQueue<>(capacity); + this.primaryQueue = primaryQueue; + this.secondaryQueue = secondaryQueue; + this.singleSpanSampler = singleSpanSampler; + this.healthMetrics = healthMetrics; + this.droppingPolicy = droppingPolicy; + } + + @Override + public void start() { + this.spanSamplingThread.start(); + } + + @Override + public void close() { + spanSamplingThread.interrupt(); + try { + spanSamplingThread.join(THREAD_JOIN_TIMOUT_MS); + } catch (InterruptedException ignored) { + } + } + + @Override + public Queue getSpanSamplingQueue() { + return spanSamplingQueue; + } + + protected void afterOnEvent() { + // this method is used in tests only + } + + private final class SamplingHandler implements Runnable { + + @Override + public void run() { + try { + runDutyCycle(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + private void runDutyCycle() throws InterruptedException { + Thread thread = Thread.currentThread(); + while (!thread.isInterrupted()) { + consumeFromInputQueue(); + } + } + + private void consumeFromInputQueue() throws InterruptedException { + Object event = spanSamplingQueue.poll(100, MILLISECONDS); + if (null != event) { + onEvent(event); + consumeBatch(spanSamplingQueue); + } + } + + @SuppressWarnings("unchecked") + public void onEvent(Object event) { + if (event instanceof List) { + List trace = (List) event; + + if (trace.isEmpty()) { + // protect against empty traces + log.warn("SingleSamplingWorker has received an empty trace."); + return; + } + + ArrayList sampledSpans = new ArrayList<>(trace.size()); + ArrayList unsampledSpans = new ArrayList<>(trace.size()); + for (DDSpan span : trace) { + if (singleSpanSampler.setSamplingPriority(span)) { + sampledSpans.add(span); + healthMetrics.onSingleSpanSample(); + } else { + unsampledSpans.add(span); + healthMetrics.onSingleSpanUnsampled(); + } + } + + int samplingPriority = trace.get(0).samplingPriority(); + if (sampledSpans.size() > 0 && !primaryQueue.offer(sampledSpans)) { + // couldn't send sampled spans because the queue is full, count entire trace as dropped + healthMetrics.onFailedPublish(samplingPriority, trace.size()); + log.debug( + "Sampled spans written to overfilled buffer after single span sampling. Counted but dropping trace: {}", + trace); + } else if (unsampledSpans.size() > 0 + && (droppingPolicy.active() || !secondaryQueue.offer(unsampledSpans))) { + if (sampledSpans.isEmpty()) { + // dropped all spans because none of the spans sampled + healthMetrics.onFailedPublish(samplingPriority, unsampledSpans.size()); + log.debug( + "Trace is empty. None of the spans have been sampled by single span sampling. Counted but dropping trace: {}", + trace); + } else { + healthMetrics.onPartialPublish(unsampledSpans.size()); + log.debug( + "Unsampled spans dropped after single span sampling because Dropping Policy is active (droppingPolicy.active()={}) or the queue is full. Counted partial trace: {}", + droppingPolicy.active(), + sampledSpans); + } + } else { + log.debug("Entire trace has been published: {}", trace); + healthMetrics.onPublish(trace, samplingPriority); + } + afterOnEvent(); + } + } + + private void consumeBatch(MessagePassingQueue queue) { + queue.drain(this::onEvent, queue.size()); + } + } + } + + class NoopSpanSamplingWorker implements SpanSamplingWorker { + @Override + public void start() {} + + @Override + public Queue getSpanSamplingQueue() { + return null; + } + + @Override + public void close() {} + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceProcessingWorker.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceProcessingWorker.java new file mode 100644 index 0000000000..227c53f42b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceProcessingWorker.java @@ -0,0 +1,299 @@ +package datadog.trace.common.writer; + +import static datadog.trace.util.AgentThreadFactory.AgentThread.TRACE_PROCESSOR; +import static datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; +import static datadog.trace.util.AgentThreadFactory.newAgentThread; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import datadog.trace.ddagent.DroppingPolicy; +import datadog.trace.api.Config; +import datadog.trace.common.sampling.SingleSpanSampler; +import datadog.trace.common.writer.ddagent.FlushEvent; +import datadog.trace.common.writer.ddagent.Prioritization; +import datadog.trace.common.writer.ddagent.PrioritizationStrategy; +import datadog.trace.core.CoreSpan; +import datadog.trace.core.DDSpan; +import datadog.trace.core.monitor.HealthMetrics; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import org.jctools.queues.MessagePassingQueue; +import org.jctools.queues.MpscBlockingConsumerArrayQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Worker which applies rules to traces and serializes the results. Upon completion, the serialized + * traces are published in batches to the Datadog Agent}. + * + *

publishing to the buffer will not block the calling thread, but instead will return false if + * the buffer is full. This is to avoid impacting an application thread. + */ +public class TraceProcessingWorker implements AutoCloseable { + + private static final Logger log = LoggerFactory.getLogger(TraceProcessingWorker.class); + + private final PrioritizationStrategy prioritizationStrategy; + private final MpscBlockingConsumerArrayQueue primaryQueue; + private final MpscBlockingConsumerArrayQueue secondaryQueue; + private final TraceSerializingHandler serializingHandler; + private final Thread serializerThread; + private final int capacity; + + private final SpanSamplingWorker spanSamplingWorker; + + public TraceProcessingWorker( + final int capacity, + final HealthMetrics healthMetrics, + final PayloadDispatcher dispatcher, + final DroppingPolicy droppingPolicy, + final Prioritization prioritization, + final long flushInterval, + final TimeUnit timeUnit, + final SingleSpanSampler singleSpanSampler) { + this.capacity = capacity; + this.primaryQueue = createQueue(capacity); + this.secondaryQueue = createQueue(capacity); + this.spanSamplingWorker = + SpanSamplingWorker.build( + capacity, + primaryQueue, + secondaryQueue, + singleSpanSampler, + healthMetrics, + droppingPolicy); + this.prioritizationStrategy = + prioritization.create( + primaryQueue, + secondaryQueue, + spanSamplingWorker.getSpanSamplingQueue(), + droppingPolicy); + + boolean runAsDaemon = !Config.get().isCiVisibilityEnabled(); + this.serializingHandler = + runAsDaemon + ? new DaemonTraceSerializingHandler( + primaryQueue, secondaryQueue, healthMetrics, dispatcher, flushInterval, timeUnit) + : new NonDaemonTraceSerializingHandler( + primaryQueue, secondaryQueue, healthMetrics, dispatcher, flushInterval, timeUnit); + this.serializerThread = newAgentThread(TRACE_PROCESSOR, serializingHandler, runAsDaemon); + } + + public void start() { + this.serializerThread.start(); + this.spanSamplingWorker.start(); + } + + public boolean flush(long timeout, TimeUnit timeUnit) { + CountDownLatch latch = new CountDownLatch(1); + FlushEvent flush = new FlushEvent(latch); + boolean offered; + do { + offered = primaryQueue.offer(flush); + } while (!offered && serializerThread.isAlive()); + try { + return latch.await(timeout, timeUnit); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return false; + } + } + + @Override + public void close() { + spanSamplingWorker.close(); + serializerThread.interrupt(); + try { + serializerThread.join(THREAD_JOIN_TIMOUT_MS); + } catch (InterruptedException ignored) { + } + } + + public > PrioritizationStrategy.PublishResult publish( + T root, int samplingPriority, final List trace) { + return prioritizationStrategy.publish(root, samplingPriority, trace); + } + + public int getCapacity() { + return capacity; + } + + public long getRemainingCapacity() { + // only advertise primary capacity (partly to keep test which aims to saturate the queue happy) + return primaryQueue.remainingCapacity(); + } + + private static MpscBlockingConsumerArrayQueue createQueue(int capacity) { + return new MpscBlockingConsumerArrayQueue<>(capacity); + } + + private static class DaemonTraceSerializingHandler extends TraceSerializingHandler { + public DaemonTraceSerializingHandler( + MpscBlockingConsumerArrayQueue primaryQueue, + MpscBlockingConsumerArrayQueue secondaryQueue, + HealthMetrics healthMetrics, + PayloadDispatcher payloadDispatcher, + long flushInterval, + TimeUnit timeUnit) { + super( + primaryQueue, secondaryQueue, healthMetrics, payloadDispatcher, flushInterval, timeUnit); + } + + @Override + public void run() { + try { + runDutyCycle(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + log.debug("Datadog trace processor exited. Publishing traces stopped"); + } + + private void runDutyCycle() throws InterruptedException { + Thread thread = Thread.currentThread(); + while (!thread.isInterrupted()) { + consumeFromPrimaryQueue(); + consumeFromSecondaryQueue(); + flushIfNecessary(); + } + } + } + + private static class NonDaemonTraceSerializingHandler extends TraceSerializingHandler { + private static final double SHUTDOWN_TIMEOUT_MILLIS = 5_000; + private Long shutdownSignalTimestamp; + + public NonDaemonTraceSerializingHandler( + MpscBlockingConsumerArrayQueue primaryQueue, + MpscBlockingConsumerArrayQueue secondaryQueue, + HealthMetrics healthMetrics, + PayloadDispatcher payloadDispatcher, + long flushInterval, + TimeUnit timeUnit) { + super( + primaryQueue, secondaryQueue, healthMetrics, payloadDispatcher, flushInterval, timeUnit); + } + + @Override + public void run() { + while (!shouldShutdown()) { + try { + consumeFromPrimaryQueue(); + consumeFromSecondaryQueue(); + flushIfNecessary(); + } catch (InterruptedException e) { + if (shutdownSignalTimestamp == null) { + shutdownSignalTimestamp = System.currentTimeMillis(); + } + } + } + log.debug("Datadog trace processor exited. Unpublished traces left: " + !queuesAreEmpty()); + } + + private boolean shouldShutdown() { + return shutdownSignalTimestamp != null + && (shutdownSignalTimestamp + SHUTDOWN_TIMEOUT_MILLIS <= System.currentTimeMillis() + || queuesAreEmpty()); + } + } + + public abstract static class TraceSerializingHandler implements Runnable { + + private final MpscBlockingConsumerArrayQueue primaryQueue; + private final MpscBlockingConsumerArrayQueue secondaryQueue; + private final HealthMetrics healthMetrics; + private final long ticksRequiredToFlush; + private final boolean doTimeFlush; + private final PayloadDispatcher payloadDispatcher; + private long lastTicks; + + public TraceSerializingHandler( + final MpscBlockingConsumerArrayQueue primaryQueue, + final MpscBlockingConsumerArrayQueue secondaryQueue, + final HealthMetrics healthMetrics, + final PayloadDispatcher payloadDispatcher, + final long flushInterval, + final TimeUnit timeUnit) { + this.primaryQueue = primaryQueue; + this.secondaryQueue = secondaryQueue; + this.healthMetrics = healthMetrics; + this.doTimeFlush = flushInterval > 0; + this.payloadDispatcher = payloadDispatcher; + if (doTimeFlush) { + this.lastTicks = System.nanoTime(); + this.ticksRequiredToFlush = timeUnit.toNanos(flushInterval); + } else { + this.ticksRequiredToFlush = Long.MAX_VALUE; + } + } + + @SuppressWarnings("unchecked") + public void onEvent(Object event) { + // publish an incomplete batch if + // 1. we get a heartbeat, and it's time to send (early heartbeats will be ignored) + // 2. a synchronous flush command is received (at shutdown) + try { + if (event instanceof List) { + List trace = (List) event; + // TODO populate `_sample_rate` metric in a way that accounts for lost/dropped traces + payloadDispatcher.addTrace(trace); + } else if (event instanceof FlushEvent) { + payloadDispatcher.flush(); + ((FlushEvent) event).sync(); + } + } catch (final Throwable e) { + if (log.isDebugEnabled()) { + log.debug("Error while serializing trace", e); + } + List data = event instanceof List ? (List) event : null; + healthMetrics.onFailedSerialize(data, e); + } + } + + protected void consumeFromPrimaryQueue() throws InterruptedException { + Object event = primaryQueue.poll(100, MILLISECONDS); + if (null != event) { + // there's a high priority trace, consume it, + // and then drain whatever's in the queue + onEvent(event); + consumeBatch(primaryQueue); + } + } + + protected void consumeFromSecondaryQueue() { + // if there's something there now, take it and try to fill a batch, + // if not, it's the secondary queue so get back to polling the primary ASAP + Object event = secondaryQueue.poll(); + if (null != event) { + onEvent(event); + consumeBatch(secondaryQueue); + } + } + + protected void flushIfNecessary() { + if (shouldFlush()) { + payloadDispatcher.flush(); + } + } + + private boolean shouldFlush() { + if (doTimeFlush) { + long nanoTime = System.nanoTime(); + long ticks = nanoTime - lastTicks; + if (ticks > ticksRequiredToFlush) { + lastTicks = nanoTime; + return true; + } + } + return false; + } + + private void consumeBatch(MessagePassingQueue queue) { + queue.drain(this::onEvent, queue.size()); + } + + protected boolean queuesAreEmpty() { + return primaryQueue.isEmpty() && secondaryQueue.isEmpty(); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceStructureWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceStructureWriter.java new file mode 100644 index 0000000000..9c2cefd23d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceStructureWriter.java @@ -0,0 +1,227 @@ +package datadog.trace.common.writer; + +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.Platform; +import datadog.trace.core.DDSpan; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Pattern; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TraceStructureWriter implements Writer { + + private static final Logger log = LoggerFactory.getLogger(TraceStructureWriter.class); + private static final Pattern ARGS_DELIMITER = Pattern.compile(":", Pattern.LITERAL); + + private final PrintStream out; + private final boolean debugLog; + private final boolean includeResource; + private final boolean includeService; + + public TraceStructureWriter() { + this("", false); + } + + public TraceStructureWriter(boolean debugLog) { + this("", debugLog); + } + + public TraceStructureWriter(String outputFile) { + this(outputFile, false); + } + + public TraceStructureWriter(String outputFile, boolean debugLog) { + boolean argsDebugLog = debugLog; + boolean argsIncludeResource = false; + boolean argsIncludeService = false; + if (null == outputFile) { + outputFile = ""; + } + if (!outputFile.isEmpty() && outputFile.charAt(0) == ':') { + outputFile = outputFile.substring(1); + } + try { + String[] args = parseArgs(outputFile); + String fileName = args[0]; + this.out = fileName.isEmpty() ? System.err : new PrintStream(new FileOutputStream(fileName)); + for (int i = 1; i < args.length; i++) { + switch (args[i].toLowerCase(Locale.ROOT)) { + case "includeresource": + argsIncludeResource = true; + break; + case "includeservice": + argsIncludeService = true; + break; + case "debuglog": + argsDebugLog = true; + break; + default: + log.warn("Illegal TraceStructureWriter argument '{}'", args[i]); + break; + } + } + } catch (IOException e) { + throw new RuntimeException("Failed to create trace structure writer from " + outputFile, e); + } + this.debugLog = argsDebugLog; + this.includeResource = argsIncludeResource; + this.includeService = argsIncludeService; + } + + private static String[] parseArgs(String outputFile) { + String[] args = ARGS_DELIMITER.split(outputFile); + // Check Windows absolute paths (:) as column is used as arg delimiter + if (Platform.isWindows() + && args.length > 1 + && args[0].length() == 1 + && (args[1].startsWith("\\") || args[1].startsWith("/"))) { + String[] windowsArgs = new String[args.length - 1]; + windowsArgs[0] = args[0] + ":" + args[1]; + System.arraycopy(args, 2, windowsArgs, 1, args.length - 2); + args = windowsArgs; + } + return args; + } + + @Override + public void write(List trace) { + if (trace.isEmpty()) { + output("[]", null, DDSpanId.ZERO); + } else { + DDTraceId traceId = trace.get(0).getTraceId(); + long rootSpanId = trace.get(0).getSpanId(); + Map nodesById = new HashMap<>(); + // index the tree + for (DDSpan span : trace) { + if (span.getLocalRootSpan() == span) { + rootSpanId = span.getSpanId(); + } + nodesById.put(span.getSpanId(), new Node(span, includeService, includeResource)); + } + // build the tree + for (DDSpan span : trace) { + if (!traceId.equals(span.getTraceId())) { + String message = + "Trace " + + traceId + + " has broken trace link at " + + span.getSpanId() + + "(" + + span.getOperationName() + + ")" + + "->" + + span.getTraceId(); + out.println("ERROR: " + message); + if (debugLog) { + log.error(message); + } + return; + } + if (rootSpanId != span.getSpanId()) { + Node parent = nodesById.get(span.getParentId()); + if (null == parent) { + String message = + "Trace " + + traceId + + " has broken parent link at " + + span.getSpanId() + + "(" + + span.getOperationName() + + ")" + + "->" + + span.getParentId(); + out.println("ERROR: " + message); + if (debugLog) { + log.error(message); + } + // Add this to the rootSpanId and continue so we can see the broken trace + parent = nodesById.get(rootSpanId); + } + parent.addChild(nodesById.get(span.getSpanId())); + } + } + output(String.valueOf(nodesById.get(rootSpanId)), traceId, rootSpanId); + } + } + + private void output(String trace, DDTraceId traceId, long rootSpanId) { + out.println(trace); + if (debugLog && log.isDebugEnabled()) { + StringBuilder start = new StringBuilder(); + if (traceId != null) { + start.append("t_id=").append(traceId); + } + if (rootSpanId != DDSpanId.ZERO) { + if (start.length() > 0) { + start.append(", "); + } + start.append("s_id=").append(DDSpanId.toString(rootSpanId)); + } + if (start.length() > 0) { + start.append(" -> "); + } + log.debug("{}wrote {}", start, trace); + } + } + + @Override + public void start() {} + + @Override + public boolean flush() { + out.flush(); + return true; + } + + @Override + public void close() { + if (out != System.err) { + out.close(); + } + } + + @Override + public void incrementDropCounts(int spanCount) {} + + private static final class Node { + private final CharSequence operationName; + private final CharSequence resourceName; + private final CharSequence serviceName; + private final List children = new ArrayList<>(); + + private Node(DDSpan span, boolean includeService, boolean includeResource) { + this.operationName = span.getOperationName(); + this.resourceName = includeResource ? span.getResourceName() : null; + this.serviceName = includeService ? span.getServiceName() : null; + } + + public void addChild(Node child) { + children.add(child); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append('['); + if (null != serviceName) { + sb.append(serviceName).append(':'); + } + sb.append(operationName); + if (null != resourceName) { + sb.append(':').append(resourceName); + } + for (Node node : children) { + sb.append(node); + } + return sb.append(']').toString(); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Writer.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Writer.java new file mode 100644 index 0000000000..cd4ccf70bf --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Writer.java @@ -0,0 +1,36 @@ +package datadog.trace.common.writer; + +import datadog.trace.core.DDSpan; +import java.io.Closeable; +import java.util.List; + +/** A writer is responsible to send collected spans to some place */ +public interface Writer extends Closeable { + + /** + * Write a trace represented by the entire list of all the finished spans + * + * @param trace the list of spans to write + */ + void write(List trace); + + /** Start the writer */ + void start(); + + /** + * Requests the writer to send all finished traces and block until complete. + * + * @return true if completed normally + */ + boolean flush(); + + /** + * Indicates to the writer that no future writing will come and it should terminates all + * connections and tasks + */ + @Override + void close(); + + /** Count that a trace was captured for stats, but without reporting it. */ + void incrementDropCounts(int spanCount); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/FlushEvent.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/FlushEvent.java new file mode 100644 index 0000000000..edb2aa1528 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/FlushEvent.java @@ -0,0 +1,15 @@ +package datadog.trace.common.writer.ddagent; + +import java.util.concurrent.CountDownLatch; + +public final class FlushEvent { + private final CountDownLatch latch; + + public FlushEvent(CountDownLatch latch) { + this.latch = latch; + } + + public void sync() { + latch.countDown(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/Prioritization.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/Prioritization.java new file mode 100644 index 0000000000..ab78164a94 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/Prioritization.java @@ -0,0 +1,153 @@ +package datadog.trace.common.writer.ddagent; + +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static datadog.trace.api.sampling.PrioritySampling.USER_DROP; + +import datadog.trace.ddagent.DroppingPolicy; +import datadog.trace.core.CoreSpan; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public enum Prioritization { + ENSURE_TRACE { + @Override + public PrioritizationStrategy create( + final Queue primary, + final Queue secondary, + final Queue spanSampling, + DroppingPolicy neverUsed) { + return new EnsureTraceStrategy(primary, secondary, spanSampling); + } + }, + FAST_LANE { + @Override + public PrioritizationStrategy create( + final Queue primary, + final Queue secondary, + final Queue spanSampling, + DroppingPolicy droppingPolicy) { + return new FastLaneStrategy(primary, secondary, spanSampling, droppingPolicy); + } + }; + + public abstract PrioritizationStrategy create( + Queue primary, + Queue secondary, + Queue spanSampling, + DroppingPolicy droppingPolicy); + + private abstract static class PrioritizationStrategyWithFlush implements PrioritizationStrategy { + + protected final Queue primary; + + protected PrioritizationStrategyWithFlush(Queue primary) { + this.primary = primary; + } + + @Override + public boolean flush(final long timeout, final TimeUnit timeUnit) { + // ok not to flush the secondary + final CountDownLatch latch = new CountDownLatch(1); + final FlushEvent event = new FlushEvent(latch); + blockingOffer(primary, event); + try { + return latch.await(timeout, timeUnit); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + return false; + } + } + + protected void blockingOffer(final Queue queue, final Object event) { + boolean offered; + do { + offered = queue.offer(event); + } while (!offered); + } + } + + private static final class EnsureTraceStrategy extends PrioritizationStrategyWithFlush { + + private final Queue secondary; + private final Queue spanSampling; + + private EnsureTraceStrategy( + final Queue primary, + final Queue secondary, + final Queue spanSampling) { + super(primary); + this.secondary = secondary; + this.spanSampling = spanSampling; + } + + @Override + public > PublishResult publish( + T root, int priority, final List trace) { + switch (priority) { + case SAMPLER_DROP: + case USER_DROP: + if (spanSampling != null) { + // send dropped traces for single span sampling + return spanSampling.offer(trace) + ? PublishResult.ENQUEUED_FOR_SINGLE_SPAN_SAMPLING + : PublishResult.DROPPED_BUFFER_OVERFLOW; + } + return secondary.offer(trace) + ? PublishResult.ENQUEUED_FOR_SERIALIZATION + : PublishResult.DROPPED_BUFFER_OVERFLOW; + default: + blockingOffer(primary, trace); + return PublishResult.ENQUEUED_FOR_SERIALIZATION; + } + } + } + + private static final class FastLaneStrategy extends PrioritizationStrategyWithFlush { + + private final Queue secondary; + private final Queue spanSampling; + private final DroppingPolicy droppingPolicy; + + private FastLaneStrategy( + final Queue primary, + final Queue secondary, + final Queue spanSampling, + DroppingPolicy droppingPolicy) { + super(primary); + this.secondary = secondary; + this.spanSampling = spanSampling; + this.droppingPolicy = droppingPolicy; + } + + @Override + public > PublishResult publish(T root, int priority, List trace) { + if (root.isForceKeep()) { + return primary.offer(trace) + ? PublishResult.ENQUEUED_FOR_SERIALIZATION + : PublishResult.DROPPED_BUFFER_OVERFLOW; + } + switch (priority) { + case SAMPLER_DROP: + case USER_DROP: + if (spanSampling != null) { + // send dropped traces for single span sampling + return spanSampling.offer(trace) + ? PublishResult.ENQUEUED_FOR_SINGLE_SPAN_SAMPLING + : PublishResult.DROPPED_BUFFER_OVERFLOW; + } + if (droppingPolicy.active()) { + return PublishResult.DROPPED_BY_POLICY; + } + return secondary.offer(trace) + ? PublishResult.ENQUEUED_FOR_SERIALIZATION + : PublishResult.DROPPED_BUFFER_OVERFLOW; + default: + return primary.offer(trace) + ? PublishResult.ENQUEUED_FOR_SERIALIZATION + : PublishResult.DROPPED_BUFFER_OVERFLOW; + } + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java new file mode 100644 index 0000000000..5918015e3a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java @@ -0,0 +1,19 @@ +package datadog.trace.common.writer.ddagent; + +import datadog.trace.core.CoreSpan; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public interface PrioritizationStrategy { + + enum PublishResult { + ENQUEUED_FOR_SERIALIZATION, + ENQUEUED_FOR_SINGLE_SPAN_SAMPLING, + DROPPED_BY_POLICY, + DROPPED_BUFFER_OVERFLOW + }; + + > PublishResult publish(T root, int priority, List trace); + + boolean flush(long timeout, TimeUnit timeUnit); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapper.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapper.java new file mode 100644 index 0000000000..3866a056b5 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapper.java @@ -0,0 +1,15 @@ +package datadog.trace.common.writer.ddagent; + +import datadog.trace.api.DDTags; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.common.writer.RemoteMapper; +import datadog.trace.core.DDSpanContext; + +public interface TraceMapper extends RemoteMapper { + + UTF8BytesString THREAD_NAME = UTF8BytesString.create(DDTags.THREAD_NAME); + UTF8BytesString THREAD_ID = UTF8BytesString.create(DDTags.THREAD_ID); + UTF8BytesString SAMPLING_PRIORITY_KEY = + UTF8BytesString.create(DDSpanContext.PRIORITY_SAMPLING_KEY); + UTF8BytesString ORIGIN_KEY = UTF8BytesString.create(DDTags.ORIGIN_KEY); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/context/TraceScope.java b/features/dd-trace-core/src/main/java/datadog/trace/context/TraceScope.java new file mode 100644 index 0000000000..effa5a5758 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/context/TraceScope.java @@ -0,0 +1,62 @@ +package datadog.trace.context; + +import java.io.Closeable; + +/** An object which can propagate a datadog trace across multiple threads. */ +public interface TraceScope extends Closeable { + /** + * Prevent the trace attached to this TraceScope from reporting until the returned Continuation is + * either activated (and the returned scope is closed), or canceled. + * + *

Should be called on the parent thread. + */ + Continuation capture(); + + /** + * Prevent the trace attached to this TraceScope from reporting until the returned Continuation is + * either activated (and the returned scope is closed), or canceled. + * + *

Should be called on the parent thread. + * + *

If the returned {@link Continuation} is activated, it needs to be canceled in addition to + * the returned {@link TraceScope} being closed. This is to allow multiple concurrent threads that + * activate the continuation to race in a safe way, and close the scopes without fear of closing + * the related {@code Span} prematurely. + */ + Continuation captureConcurrent(); + + /** Close the activated context and allow any underlying spans to finish. */ + @Override + void close(); + + /** If true, this context will propagate across async boundaries. */ + boolean isAsyncPropagating(); + + /** + * Enable or disable async propagation. Async propagation is initially set to false. + * + * @param value The new propagation value. True == propagate. False == don't propagate. + */ + void setAsyncPropagation(boolean value); + + /** + * Used to pass async context between workers. A trace will not be reported until all spans and + * continuations are resolved. You must call activate (and close on the returned scope) or cancel + * on each continuation to avoid discarding traces. + */ + interface Continuation { + + /** + * Activate the continuation. + * + *

Should be called on the child thread. + * + *

Consider calling this in a try-with-resources initialization block to ensure the returned + * scope is closed properly. + */ + TraceScope activate(); + + /** Allow trace to stop waiting on this continuation for reporting. */ + void cancel(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java b/features/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java new file mode 100644 index 0000000000..ca2bbd44ab --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java @@ -0,0 +1,90 @@ +package datadog.trace.core; + +import datadog.trace.api.DDTraceId; + +public interface CoreSpan> { + + T getLocalRootSpan(); + + String getServiceName(); + + CharSequence getOperationName(); + + CharSequence getResourceName(); + + DDTraceId getTraceId(); + + long getSpanId(); + + long getParentId(); + + long getStartTime(); + + long getDurationNano(); + + int getError(); + + short getHttpStatusCode(); + + CharSequence getOrigin(); + + T setMeasured(boolean measured); + + T setErrorMessage(final String errorMessage); + + T addThrowable(final Throwable error); + + T setTag(final String tag, final String value); + + T setTag(final String tag, final boolean value); + + T setTag(final String tag, final int value); + + T setTag(final String tag, final long value); + + T setTag(final String tag, final double value); + + T setTag(final String tag, final Number value); + + T setTag(final String tag, final CharSequence value); + + T setTag(final String tag, final Object value); + + T removeTag(final String tag); + + U getTag(CharSequence name, U defaultValue); + + U getTag(CharSequence name); + + boolean hasSamplingPriority(); + + boolean isMeasured(); + + /** @return whether this span has a different service name from its parent, or is a local root. */ + boolean isTopLevel(); + + boolean isForceKeep(); + + CharSequence getType(); + + void processTagsAndBaggage(MetadataConsumer consumer); + + T setSamplingPriority(int samplingPriority, int samplingMechanism); + + T setSamplingPriority( + int samplingPriority, CharSequence rate, double sampleRate, int samplingMechanism); + + T setSpanSamplingPriority(double rate, int limit); + + T setMetric(CharSequence name, int value); + + T setMetric(CharSequence name, long value); + + T setMetric(CharSequence name, float value); + + T setMetric(CharSequence name, double value); + + T setFlag(CharSequence name, boolean value); + + int samplingPriority(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java new file mode 100644 index 0000000000..8be144843c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -0,0 +1,1456 @@ +package datadog.trace.core; + +import static datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; +import static datadog.trace.api.DDTags.PROFILING_CONTEXT_ENGINE; +import static datadog.trace.util.AgentThreadFactory.AGENT_THREAD_GROUP; +import static datadog.trace.util.CollectionUtils.tryMakeImmutableMap; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; +import datadog.trace.monitor.Monitoring; +import datadog.trace.monitor.Recording; +import datadog.trace.monitor.NoOpRecording; +import datadog.trace.api.Config; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.DynamicConfig; +import datadog.trace.api.EndpointCheckpointer; +import datadog.trace.api.EndpointCheckpointerHolder; +import datadog.trace.api.EndpointTracker; +import datadog.trace.api.IdGenerationStrategy; +import datadog.trace.api.InstrumenterConfig; +import datadog.trace.api.StatsDClient; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.api.config.GeneralConfig; +import datadog.trace.api.experimental.DataStreamsCheckpointer; +import datadog.trace.api.flare.TracerFlare; +import datadog.trace.api.gateway.CallbackProvider; +import datadog.trace.api.gateway.InstrumentationGateway; +import datadog.trace.api.gateway.RequestContext; +import datadog.trace.api.gateway.RequestContextSlot; +import datadog.trace.api.gateway.SubscriptionService; +import datadog.trace.api.interceptor.MutableSpan; +import datadog.trace.api.interceptor.TraceInterceptor; +import datadog.trace.api.internal.TraceSegment; +import datadog.trace.api.metrics.SpanMetricRegistry; +import datadog.trace.api.naming.SpanNaming; +import datadog.trace.api.profiling.Timer; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.api.scopemanager.ScopeListener; +import datadog.trace.api.time.SystemTimeSource; +import datadog.trace.api.time.TimeSource; +import datadog.trace.bootstrap.instrumentation.api.AgentDataStreamsMonitoring; +import datadog.trace.bootstrap.instrumentation.api.AgentHistogram; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentScopeManager; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; +import datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; +import datadog.trace.bootstrap.instrumentation.api.ScopeSource; +import datadog.trace.bootstrap.instrumentation.api.ScopeState; +import datadog.trace.bootstrap.instrumentation.api.TagContext; +import datadog.trace.civisibility.interceptor.CiVisibilityTraceInterceptor; +import datadog.trace.common.GitMetadataTraceInterceptor; +import datadog.trace.common.metrics.MetricsAggregator; +import datadog.trace.common.metrics.NoOpMetricsAggregator; +import datadog.trace.common.sampling.Sampler; +import datadog.trace.common.sampling.SpanSamplingRules; +import datadog.trace.common.sampling.TraceSamplingRules; +import datadog.trace.common.writer.Writer; +import datadog.trace.core.datastreams.DataStreamsMonitoring; +import datadog.trace.core.datastreams.NoOpDataStreamMonitoring; +import datadog.trace.core.histogram.Histograms; +import datadog.trace.core.monitor.HealthMetrics; +import datadog.trace.core.propagation.*; +import datadog.trace.core.scopemanager.ContinuableScopeManager; +import datadog.trace.core.taginterceptor.RuleFlags; +import datadog.trace.core.taginterceptor.TagInterceptor; +import datadog.trace.lambda.LambdaHandler; +import datadog.trace.relocate.api.RatelimitedLogger; +import datadog.trace.util.AgentTaskScheduler; + +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.zip.ZipOutputStream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Main entrypoint into the tracer implementation. In addition to implementing + * datadog.trace.api.Tracer and TracerAPI, it coordinates many functions necessary creating, + * reporting, and propagating traces + */ +public class CoreTracer implements AgentTracer.TracerAPI { + private static final Logger log = LoggerFactory.getLogger(CoreTracer.class); + // UINT64 max value + public static final BigInteger TRACE_ID_MAX = + BigInteger.valueOf(2).pow(64).subtract(BigInteger.ONE); + + public static CoreTracerBuilder builder() { + return new CoreTracerBuilder(); + } + + private static final String LANG_STATSD_TAG = "lang"; + private static final String LANG_VERSION_STATSD_TAG = "lang_version"; + private static final String LANG_INTERPRETER_STATSD_TAG = "lang_interpreter"; + private static final String LANG_INTERPRETER_VENDOR_STATSD_TAG = "lang_interpreter_vendor"; + private static final String TRACER_VERSION_STATSD_TAG = "tracer_version"; + + /** + * Tracer start time in nanoseconds measured up to a millisecond accuracy + */ + private final long startTimeNano; + /** + * Nanosecond ticks value at tracer start + */ + private final long startNanoTicks; + /** + * How often should traced threads check clock ticks against the wall clock + */ + private final long clockSyncPeriod; + + /** + * If the tracer can create inferred services + */ + private final boolean allowInferredServices; + + /** + * Last time (in nanosecond ticks) the clock was checked for drift + */ + private volatile long lastSyncTicks; + /** + * Nanosecond offset to counter clock drift + */ + private volatile long counterDrift; + + private final PendingTraceBuffer pendingTraceBuffer; + + /** + * Default service name if none provided on the trace or span + */ + final String serviceName; + /** + * Writer is an charge of reporting traces and spans to the desired endpoint + */ + final Writer writer; + /** + * Sampler defines the sampling policy in order to reduce the number of traces for instance + */ + final Sampler initialSampler; + /** + * Scope manager is in charge of managing the scopes from which spans are created + */ + final AgentScopeManager scopeManager; + + final MetricsAggregator metricsAggregator; + + /** + * Initial static configuration associated with the tracer. + */ + final Config initialConfig; + /** + * Maintains dynamic configuration associated with the tracer + */ + private final DynamicConfig dynamicConfig; + /** + * A set of tags that are added only to the application's root span + */ + private final Map localRootSpanTags; + /** + * A set of tags that are added to every span + */ + private final Map defaultSpanTags; + + /** + * number of spans in a pending trace before they get flushed + */ + private final int partialFlushMinSpans; + + private final StatsDClient statsDClient; + private final Monitoring monitoring; + private final Monitoring performanceMonitoring; + + private final HealthMetrics healthMetrics; + private final Recording traceWriteTimer; + private final IdGenerationStrategy idGenerationStrategy; + private final PendingTrace.Factory pendingTraceFactory; + private final EndpointCheckpointerHolder endpointCheckpointer; + private final DataStreamsMonitoring dataStreamsMonitoring; + + private final boolean disableSamplingMechanismValidation; + private final TimeSource timeSource; + private final ProfilingContextIntegration profilingContextIntegration; + private boolean injectBaggageAsTags; + + private Timer timer = Timer.NoOp.INSTANCE; + + /** + * JVM shutdown callback, keeping a reference to it to remove this if DDTracer gets destroyed + * earlier + */ + private final Thread shutdownCallback; + + /** + * Span tag interceptors. This Map is only ever added to during initialization, so it doesn't need + * to be concurrent. + */ + private final TagInterceptor tagInterceptor; + + private final SortedSet interceptors = + new ConcurrentSkipListSet<>(Comparator.comparingInt(TraceInterceptor::priority)); + + private final AgentPropagation propagation; + private final boolean logs128bTraceIdEnabled; + + private final InstrumentationGateway instrumentationGateway; + private final CallbackProvider callbackProviderAppSec; + private final CallbackProvider callbackProviderIast; + private final CallbackProvider universalCallbackProvider; + + private final PropagationTags.Factory propagationTagsFactory; + + @Override + public ConfigSnapshot captureTraceConfig() { + return dynamicConfig.captureTraceConfig(); + } + + @Override + public AgentHistogram newHistogram(double relativeAccuracy, int maxNumBins) { + return Histograms.newHistogram(relativeAccuracy, maxNumBins); + } + + PropagationTags.Factory getPropagationTagsFactory() { + return propagationTagsFactory; + } + + @Override + public void onRootSpanFinished(AgentSpan root, EndpointTracker tracker) { + endpointCheckpointer.onRootSpanFinished(root, tracker); + } + + @Override + public EndpointTracker onRootSpanStarted(AgentSpan root) { + return endpointCheckpointer.onRootSpanStarted(root); + } + + @Override + public ScopeState newScopeState() { + return scopeManager.newScopeState(); + } + + public static class CoreTracerBuilder { + + private Config config; + private String serviceName; + private Writer writer; + private IdGenerationStrategy idGenerationStrategy; + private Sampler sampler; + private HttpCodec.Extractor extractor; + private AgentScopeManager scopeManager; + private Map localRootSpanTags; + private Map defaultSpanTags; + private Map serviceNameMappings; + private Map taggedHeaders; + private Map baggageMapping; + private int partialFlushMinSpans; + private TagInterceptor tagInterceptor; + private boolean strictTraceWrites; + private InstrumentationGateway instrumentationGateway; + private TimeSource timeSource; + private ProfilingContextIntegration profilingContextIntegration = + ProfilingContextIntegration.NoOp.INSTANCE; + private boolean injectBaggageAsTags; + + public CoreTracerBuilder serviceName(String serviceName) { + this.serviceName = serviceName; + return this; + } + + public CoreTracerBuilder writer(Writer writer) { + this.writer = writer; + return this; + } + + public CoreTracerBuilder idGenerationStrategy(IdGenerationStrategy idGenerationStrategy) { + this.idGenerationStrategy = idGenerationStrategy; + return this; + } + + public CoreTracerBuilder sampler(Sampler sampler) { + this.sampler = sampler; + return this; + } + + public CoreTracerBuilder extractor(HttpCodec.Extractor extractor) { + this.extractor = extractor; + return this; + } + + public CoreTracerBuilder scopeManager(AgentScopeManager scopeManager) { + this.scopeManager = scopeManager; + return this; + } + + public CoreTracerBuilder localRootSpanTags(Map localRootSpanTags) { + this.localRootSpanTags = tryMakeImmutableMap(localRootSpanTags); + return this; + } + + public CoreTracerBuilder defaultSpanTags(Map defaultSpanTags) { + this.defaultSpanTags = tryMakeImmutableMap(defaultSpanTags); + return this; + } + + public CoreTracerBuilder serviceNameMappings(Map serviceNameMappings) { + this.serviceNameMappings = tryMakeImmutableMap(serviceNameMappings); + return this; + } + + public CoreTracerBuilder taggedHeaders(Map taggedHeaders) { + this.taggedHeaders = tryMakeImmutableMap(taggedHeaders); + return this; + } + + public CoreTracerBuilder baggageMapping(Map baggageMapping) { + this.baggageMapping = tryMakeImmutableMap(baggageMapping); + return this; + } + + public CoreTracerBuilder partialFlushMinSpans(int partialFlushMinSpans) { + this.partialFlushMinSpans = partialFlushMinSpans; + return this; + } + + public CoreTracerBuilder tagInterceptor(TagInterceptor tagInterceptor) { + this.tagInterceptor = tagInterceptor; + return this; + } + + public CoreTracerBuilder statsDClient(TagInterceptor tagInterceptor) { + this.tagInterceptor = tagInterceptor; + return this; + } + + public CoreTracerBuilder strictTraceWrites(boolean strictTraceWrites) { + this.strictTraceWrites = strictTraceWrites; + return this; + } + + public CoreTracerBuilder instrumentationGateway(InstrumentationGateway instrumentationGateway) { + this.instrumentationGateway = instrumentationGateway; + return this; + } + + public CoreTracerBuilder timeSource(TimeSource timeSource) { + this.timeSource = timeSource; + return this; + } + + + public CoreTracerBuilder injectBaggageAsTags(boolean injectBaggageAsTags) { + this.injectBaggageAsTags = injectBaggageAsTags; + return this; + } + + public CoreTracerBuilder() { + // Apply the default values from config. + config(Config.get()); + } + + public CoreTracerBuilder withProperties(final Properties properties) { + return config(Config.get(properties)); + } + + public CoreTracerBuilder config(final Config config) { + this.config = config; + serviceName(config.getServiceName()); + // Explicitly skip setting writer to avoid allocating resources prematurely. + sampler(Sampler.Builder.forConfig(config, null)); + instrumentationGateway(new InstrumentationGateway()); + // Explicitly skip setting scope manager because it depends on statsDClient + localRootSpanTags(config.getLocalRootSpanTags()); + defaultSpanTags(config.getMergedSpanTags()); + serviceNameMappings(config.getServiceMapping()); + taggedHeaders(config.getRequestHeaderTags()); + baggageMapping(config.getBaggageMapping()); + partialFlushMinSpans(config.getPartialFlushMinSpans()); + strictTraceWrites(config.isTraceStrictWritesEnabled()); + injectBaggageAsTags(config.isInjectBaggageAsTagsEnabled()); + return this; + } + + public CoreTracer build() { + return new CoreTracer( + config, + serviceName, + writer, + idGenerationStrategy, + sampler, + extractor, + scopeManager, + localRootSpanTags, + defaultSpanTags, + serviceNameMappings, + taggedHeaders, + baggageMapping, + partialFlushMinSpans, + tagInterceptor, + strictTraceWrites, + instrumentationGateway, + timeSource, + profilingContextIntegration, + injectBaggageAsTags); + } + } + + // These field names must be stable to ensure the builder api is stable. + private CoreTracer( + final Config config, + final String serviceName, + final Writer writer, + final IdGenerationStrategy idGenerationStrategy, + final Sampler sampler, + final HttpCodec.Extractor extractor, + final AgentScopeManager scopeManager, + final Map localRootSpanTags, + final Map defaultSpanTags, + final Map serviceNameMappings, + final Map taggedHeaders, + final Map baggageMapping, + final int partialFlushMinSpans, + final TagInterceptor tagInterceptor, + final boolean strictTraceWrites, + final InstrumentationGateway instrumentationGateway, + final TimeSource timeSource, + final ProfilingContextIntegration profilingContextIntegration, + final boolean injectBaggageAsTags) { + + assert localRootSpanTags != null; + assert defaultSpanTags != null; + assert serviceNameMappings != null; + assert taggedHeaders != null; + assert baggageMapping != null; + + this.timeSource = timeSource == null ? SystemTimeSource.INSTANCE : timeSource; + startTimeNano = this.timeSource.getCurrentTimeNanos(); + startNanoTicks = this.timeSource.getNanoTicks(); + clockSyncPeriod = Math.max(1_000_000L, SECONDS.toNanos(config.getClockSyncPeriod())); + lastSyncTicks = startNanoTicks; + + endpointCheckpointer = EndpointCheckpointerHolder.create(); + this.serviceName = serviceName; + + this.initialConfig = config; + this.initialSampler = sampler; + + // Get initial Trace Sampling Rules from config + TraceSamplingRules traceSamplingRules = + config.getTraceSamplingRules() == null + ? TraceSamplingRules.EMPTY + : TraceSamplingRules.deserialize(config.getTraceSamplingRules()); + // Get initial Span Sampling Rules from config + String spanSamplingRulesJson = config.getSpanSamplingRules(); + String spanSamplingRulesFile = config.getSpanSamplingRulesFile(); + SpanSamplingRules spanSamplingRules = SpanSamplingRules.EMPTY; + if (spanSamplingRulesJson != null) { + spanSamplingRules = SpanSamplingRules.deserialize(spanSamplingRulesJson); + } else if (spanSamplingRulesFile != null) { + spanSamplingRules = SpanSamplingRules.deserializeFile(spanSamplingRulesFile); + } + + this.dynamicConfig = + DynamicConfig.create(ConfigSnapshot::new) + .setRuntimeMetricsEnabled(config.isRuntimeMetricsEnabled()) + .setLogsInjectionEnabled(config.isLogsInjectionEnabled()) + .setDataStreamsEnabled(config.isDataStreamsEnabled()) + .setServiceMapping(serviceNameMappings) + .setHeaderTags(taggedHeaders) + .setBaggageMapping(baggageMapping) + .setTraceSampleRate(config.getTraceSampleRate()) + .setSpanSamplingRules(spanSamplingRules.getRules()) + .setTraceSamplingRules(traceSamplingRules.getRules()) + .apply(); + + this.logs128bTraceIdEnabled = InstrumenterConfig.get().isLogs128bTraceIdEnabled(); + this.defaultSpanTags = defaultSpanTags; + this.partialFlushMinSpans = partialFlushMinSpans; + this.idGenerationStrategy = + null == idGenerationStrategy + ? Config.get().getIdGenerationStrategy() + : idGenerationStrategy; + + this.statsDClient = StatsDClient.NO_OP; + + this.traceWriteTimer = NoOpRecording.NO_OP; + this.healthMetrics = HealthMetrics.NO_OP; + this.monitoring = Monitoring.DISABLED; + this.performanceMonitoring = Monitoring.DISABLED; + if (scopeManager == null) { + this.scopeManager = + new ContinuableScopeManager( + config.getScopeDepthLimit(), + config.isScopeStrictMode(), + config.isScopeInheritAsyncPropagation(), + profilingContextIntegration, + healthMetrics); + } else { + this.scopeManager = scopeManager; + } + + disableSamplingMechanismValidation = config.isSamplingMechanismValidationDisabled(); + + this.writer = writer; + pendingTraceBuffer = + strictTraceWrites + ? PendingTraceBuffer.discarding() + : PendingTraceBuffer.delaying( + this.timeSource, config, healthMetrics); + pendingTraceFactory = + new PendingTrace.Factory( + this, pendingTraceBuffer, this.timeSource, strictTraceWrites, healthMetrics); + pendingTraceBuffer.start(); + + this.writer.start(); + metricsAggregator = NoOpMetricsAggregator.INSTANCE; + // Schedule the metrics aggregator to begin reporting after a random delay of 1 to 10 seconds + // (using milliseconds granularity.) This avoids a fleet of traced applications starting at the + // same time from sending metrics in sync. + AgentTaskScheduler.INSTANCE.scheduleWithJitter( + MetricsAggregator::start, metricsAggregator, 1, SECONDS); + + this.dataStreamsMonitoring = new NoOpDataStreamMonitoring(); + // Create default extractor from config if not provided and decorate it with DSM extractor + HttpCodec.Extractor builtExtractor = + extractor == null ? HttpCodec.createExtractor(config, this::captureTraceConfig) : extractor; + // Create all HTTP injectors plus the DSM one + Map injectors = + HttpCodec.allInjectorsFor(config, invertMap(baggageMapping)); + // Store all propagators to propagation + this.propagation = new NoOpCorePropagation(builtExtractor); + this.tagInterceptor = + null == tagInterceptor ? new TagInterceptor(new RuleFlags(config)) : tagInterceptor; + if (config.isCiVisibilityEnabled()) { + if (config.isCiVisibilityTraceSanitationEnabled()) { + addTraceInterceptor(CiVisibilityTraceInterceptor.INSTANCE); + } + } + if (config.isTraceGitMetadataEnabled()) { + addTraceInterceptor(GitMetadataTraceInterceptor.INSTANCE); + } + + this.instrumentationGateway = instrumentationGateway; + callbackProviderAppSec = instrumentationGateway.getCallbackProvider(RequestContextSlot.APPSEC); + callbackProviderIast = instrumentationGateway.getCallbackProvider(RequestContextSlot.IAST); + universalCallbackProvider = instrumentationGateway.getUniversalCallbackProvider(); + + shutdownCallback = new ShutdownHook(this); + try { + Runtime.getRuntime().addShutdownHook(shutdownCallback); + } catch (final IllegalStateException ex) { + // The JVM is already shutting down. + } + + registerClassLoader(ClassLoader.getSystemClassLoader()); + + StatusLogger.logStatus(config); + + propagationTagsFactory = PropagationTags.factory(config); + this.profilingContextIntegration = profilingContextIntegration; + this.injectBaggageAsTags = injectBaggageAsTags; + this.allowInferredServices = SpanNaming.instance().namingSchema().allowInferredServices(); + if (profilingContextIntegration != ProfilingContextIntegration.NoOp.INSTANCE) { + Map tmp = new HashMap<>(localRootSpanTags); + tmp.put(PROFILING_CONTEXT_ENGINE, profilingContextIntegration.name()); + this.localRootSpanTags = tryMakeImmutableMap(tmp); + } else { + this.localRootSpanTags = localRootSpanTags; + } + } + + /** + * Used by AgentTestRunner to inject configuration into the test tracer. + */ + public void rebuildTraceConfig(Config config) { + dynamicConfig + .initial() + .setRuntimeMetricsEnabled(config.isRuntimeMetricsEnabled()) + .setLogsInjectionEnabled(config.isLogsInjectionEnabled()) + .setDataStreamsEnabled(config.isDataStreamsEnabled()) + .setServiceMapping(config.getServiceMapping()) + .setHeaderTags(config.getRequestHeaderTags()) + .setBaggageMapping(config.getBaggageMapping()) + .setTraceSampleRate(config.getTraceSampleRate()) + .apply(); + } + + @Override + protected void finalize() { + if (null != shutdownCallback) { + try { + shutdownCallback.run(); + Runtime.getRuntime().removeShutdownHook(shutdownCallback); + } catch (final IllegalStateException e) { + // Do nothing. Already shutting down + } catch (final Exception e) { + log.error("Error while finalizing DDTracer.", e); + } + } + } + + /** + * Only visible for benchmarking purposes + * + * @return a PendingTrace + */ + public PendingTrace createTrace(DDTraceId id) { + return pendingTraceFactory.create(id); + } + + PendingTrace createTrace(DDTraceId id, ConfigSnapshot traceConfig) { + return pendingTraceFactory.create(id, traceConfig); + } + + /** + * If an application is using a non-system classloader, that classloader should be registered + * here. Due to the way Spring Boot structures its' executable jar, this might log some warnings. + * + * @param classLoader to register. + */ + private void registerClassLoader(final ClassLoader classLoader) { + try { + for (final TraceInterceptor interceptor : + ServiceLoader.load(TraceInterceptor.class, classLoader)) { + addTraceInterceptor(interceptor); + } + } catch (final ServiceConfigurationError e) { + log.warn("Problem loading TraceInterceptor for classLoader: {}", classLoader, e); + } + } + + /** + * Timestamp in nanoseconds for the current {@code nanoTicks}. + * + *

Note: it is not possible to get 'real' nanosecond time. This method uses tracer start time + * (with millisecond precision) as a reference and applies relative time with nanosecond precision + * after that. This means time measured with same Tracer in different Spans is relatively correct + * with nanosecond precision. + * + * @param nanoTicks as returned by {@link TimeSource#getNanoTicks()} + * @return timestamp in nanoseconds + */ + long getTimeWithNanoTicks(long nanoTicks) { + long computedNanoTime = startTimeNano + Math.max(0, nanoTicks - startNanoTicks); + if (nanoTicks - lastSyncTicks >= clockSyncPeriod) { + long drift = computedNanoTime - timeSource.getCurrentTimeNanos(); + if (Math.abs(drift + counterDrift) >= 1_000_000L) { // allow up to 1ms of drift + counterDrift = -MILLISECONDS.toNanos(NANOSECONDS.toMillis(drift)); + } + lastSyncTicks = nanoTicks; + } + return computedNanoTime + counterDrift; + } + + @Override + public CoreSpanBuilder buildSpan( + final String instrumentationName, final CharSequence operationName) { + return new CoreSpanBuilder(instrumentationName, operationName, this); + } + + @Override + public AgentSpan startSpan(final String instrumentationName, final CharSequence spanName) { + return buildSpan(instrumentationName, spanName).start(); + } + + @Override + public AgentSpan startSpan( + final String instrumentationName, final CharSequence spanName, final long startTimeMicros) { + return buildSpan(instrumentationName, spanName).withStartTimestamp(startTimeMicros).start(); + } + + @Override + public AgentSpan startSpan( + String instrumentationName, final CharSequence spanName, final AgentSpan.Context parent) { + return buildSpan(instrumentationName, spanName).ignoreActiveSpan().asChildOf(parent).start(); + } + + @Override + public AgentSpan startSpan( + final String instrumentationName, + final CharSequence spanName, + final AgentSpan.Context parent, + final long startTimeMicros) { + return buildSpan(instrumentationName, spanName) + .ignoreActiveSpan() + .asChildOf(parent) + .withStartTimestamp(startTimeMicros) + .start(); + } + + public AgentScope activateSpan(final AgentSpan span) { + return scopeManager.activate(span, ScopeSource.INSTRUMENTATION, DEFAULT_ASYNC_PROPAGATING); + } + + @Override + public AgentScope activateSpan(final AgentSpan span, final ScopeSource source) { + return scopeManager.activate(span, source); + } + + @Override + public AgentScope activateSpan(AgentSpan span, ScopeSource source, boolean isAsyncPropagating) { + return scopeManager.activate(span, source, isAsyncPropagating); + } + + @Override + public AgentScope.Continuation captureSpan(final AgentSpan span) { + return scopeManager.captureSpan(span); + } + + @Override + public void closePrevious(boolean finishSpan) { + scopeManager.closePrevious(finishSpan); + } + + @Override + public AgentScope activateNext(AgentSpan span) { + return scopeManager.activateNext(span); + } + + public TagInterceptor getTagInterceptor() { + return tagInterceptor; + } + + public int getPartialFlushMinSpans() { + return partialFlushMinSpans; + } + + @Override + public AgentSpan activeSpan() { + return scopeManager.activeSpan(); + } + + @Override + public AgentScope activeScope() { + return scopeManager.active(); + } + + @Override + public AgentPropagation propagate() { + return this.propagation; + } + + @Override + public AgentSpan noopSpan() { + return AgentTracer.NoopAgentSpan.INSTANCE; + } + + @Override + public AgentSpan.Context notifyExtensionStart(Object event) { + return LambdaHandler.notifyStartInvocation(event, propagationTagsFactory); + } + + @Override + public void notifyExtensionEnd(AgentSpan span, Object result, boolean isError) { + LambdaHandler.notifyEndInvocation(span, result, isError); + } + + @Override + public AgentDataStreamsMonitoring getDataStreamsMonitoring() { + return dataStreamsMonitoring; + } + + @Override + public Timer getTimer() { + return timer; + } + + private final RatelimitedLogger rlLog = new RatelimitedLogger(log, 1, MINUTES); + + /** + * We use the sampler to know if the trace has to be reported/written. The sampler is called on + * the first span (root span) of the trace. If the trace is marked as a sample, we report it. + * + * @param trace a list of the spans related to the same trace + */ + void write(final List trace) { + List writtenTrace = interceptCompleteTrace(trace); + if (writtenTrace.isEmpty()) { + return; + } + boolean forceKeep = metricsAggregator.publish(writtenTrace); + + PendingTrace pendingTrace = writtenTrace.get(0).context().getTrace(); + pendingTrace.setSamplingPriorityIfNecessary(); + + DDSpan rootSpan = pendingTrace.getRootSpan(); + DDSpan spanToSample = rootSpan == null ? writtenTrace.get(0) : rootSpan; + spanToSample.forceKeep(forceKeep); + boolean published = forceKeep || pendingTrace.sample(spanToSample); + if (published) { + writer.write(writtenTrace); + } else { + // with span streaming this won't work - it needs to be changed + // to track an effective sampling rate instead, however, tests + // checking that a hard reference on a continuation prevents + // reporting fail without this, so will need to be fixed first. + writer.incrementDropCounts(writtenTrace.size()); + } + if (null != rootSpan) { + onRootSpanFinished(rootSpan, rootSpan.getEndpointTracker()); + + // request context is propagated to contexts in child spans + // Assume here that if present it will be so starting in the top span + RequestContext requestContext = rootSpan.getRequestContext(); + if (requestContext != null) { + try { + requestContext.close(); + } catch (IOException e) { + log.warn("Error closing request context data", e); + } + } + } + } + + private List interceptCompleteTrace(List trace) { + if (!interceptors.isEmpty() && !trace.isEmpty()) { + Collection interceptedTrace = new ArrayList<>(trace); + for (final TraceInterceptor interceptor : interceptors) { + try { + // If one TraceInterceptor throws an exception, then continue with the next one + interceptedTrace = interceptor.onTraceComplete(interceptedTrace); + } catch (Exception e) { + String interceptorName = interceptor.getClass().getName(); + rlLog.warn("Exception in TraceInterceptor {}", interceptorName, e); + } + } + trace = new ArrayList<>(interceptedTrace.size()); + for (final MutableSpan span : interceptedTrace) { + if (span instanceof DDSpan) { + trace.add((DDSpan) span); + } + } + } + return trace; + } + + @Override + public String getTraceId() { + return getTraceId(activeSpan()); + } + + @Override + public String getSpanId() { + return getSpanId(activeSpan()); + } + + @Override + public String getTraceId(AgentSpan span) { + if (span != null && span.getTraceId() != null) { + DDTraceId traceId = span.getTraceId(); + // Return padded hexadecimal string representation if 128-bit TraceId logging is enabled and + // TraceId is a 128-bit ID, otherwise use the default numerical string representation. + if (this.logs128bTraceIdEnabled && traceId.toHighOrderLong() != 0) { + return traceId.toHexString(); + } else { + return traceId.toString(); + } + } + return "0"; + } + + @Override + public String getSpanId(AgentSpan span) { + if (span != null) { + return DDSpanId.toString(span.getSpanId()); + } + return "0"; + } + + @Override + public boolean addTraceInterceptor(final TraceInterceptor interceptor) { + if (interceptors.add(interceptor)) { + return true; + } else { + Comparator interceptorComparator = interceptors.comparator(); + if (interceptorComparator != null) { + TraceInterceptor anotherInterceptor = + interceptors.stream() + .filter(i -> interceptorComparator.compare(i, interceptor) == 0) + .findFirst() + .orElse(null); + log.warn( + "Interceptor {} will NOT be registered with the tracer, " + + "as already registered interceptor {} is considered its duplicate", + interceptor, + anotherInterceptor); + } + return false; + } + } + + @Override + public DataStreamsCheckpointer getDataStreamsCheckpointer() { + return this.dataStreamsMonitoring; + } + + @Override + public void addScopeListener(final ScopeListener listener) { + if (scopeManager instanceof ContinuableScopeManager) { + ((ContinuableScopeManager) scopeManager).addScopeListener(listener); + } + } + + @Override + public void registerCheckpointer(EndpointCheckpointer implementation) { + endpointCheckpointer.register(implementation); + } + + @Override + public void registerTimer(Timer timer) { + this.timer = timer; + } + + @Override + public SubscriptionService getSubscriptionService(RequestContextSlot slot) { + return (SubscriptionService) instrumentationGateway.getCallbackProvider(slot); + } + + @Override + public CallbackProvider getCallbackProvider(RequestContextSlot slot) { + if (slot == RequestContextSlot.APPSEC) { + return callbackProviderAppSec; + } else if (slot == RequestContextSlot.IAST) { + return callbackProviderIast; + } else { + return CallbackProvider.CallbackProviderNoop.INSTANCE; + } + } + + @Override + public CallbackProvider getUniversalCallbackProvider() { + return universalCallbackProvider; + } + + @Override + public void close() { + pendingTraceBuffer.close(); + writer.close(); + statsDClient.close(); + metricsAggregator.close(); + dataStreamsMonitoring.close(); + } + + @Override + public void addScopeListener( + Runnable afterScopeActivatedCallback, Runnable afterScopeClosedCallback) { + addScopeListener( + new ScopeListener() { + @Override + public void afterScopeActivated() { + afterScopeActivatedCallback.run(); + } + + @Override + public void afterScopeClosed() { + afterScopeClosedCallback.run(); + } + }); + } + + @Override + public void flush() { + pendingTraceBuffer.flush(); + writer.flush(); + } + + @Override + public void flushMetrics() { + try { + metricsAggregator.forceReport().get(2_500, MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + log.debug("Failed to wait for metrics flush.", e); + } + } + + @Override + public ProfilingContextIntegration getProfilingContext() { + return profilingContextIntegration; + } + + @Override + public TraceSegment getTraceSegment() { + AgentSpan activeSpan = activeSpan(); + if (activeSpan == null) { + return null; + } + AgentSpan.Context ctx = activeSpan.context(); + if (ctx instanceof DDSpanContext) { + return ((DDSpanContext) ctx).getTraceSegment(); + } + return null; + } + + public void addTracerReportToFlare(ZipOutputStream zip) throws IOException { + TracerFlare.addText(zip, "tracer_health.txt", healthMetrics.summary()); + TracerFlare.addText(zip, "span_metrics.txt", SpanMetricRegistry.getInstance().summary()); + } + + private static String[] generateConstantTags(final Config config) { + final List constantTags = new ArrayList<>(); + + constantTags.add(statsdTag(LANG_STATSD_TAG, "java")); + constantTags.add(statsdTag(LANG_VERSION_STATSD_TAG, DDTraceCoreInfo.JAVA_VERSION)); + constantTags.add(statsdTag(LANG_INTERPRETER_STATSD_TAG, DDTraceCoreInfo.JAVA_VM_NAME)); + constantTags.add(statsdTag(LANG_INTERPRETER_VENDOR_STATSD_TAG, DDTraceCoreInfo.JAVA_VM_VENDOR)); + constantTags.add(statsdTag(TRACER_VERSION_STATSD_TAG, DDTraceCoreInfo.VERSION)); + constantTags.add(statsdTag("service", config.getServiceName())); + + final Map mergedSpanTags = config.getMergedSpanTags(); + final String version = mergedSpanTags.get(GeneralConfig.VERSION); + if (version != null && !version.isEmpty()) { + constantTags.add(statsdTag("version", version)); + } + + final String env = mergedSpanTags.get(GeneralConfig.ENV); + if (env != null && !env.isEmpty()) { + constantTags.add(statsdTag("env", env)); + } + + return constantTags.toArray(new String[0]); + } + + Recording writeTimer() { + return traceWriteTimer.start(); + } + + private static String statsdTag(final String tagPrefix, final String tagValue) { + return tagPrefix + ":" + tagValue; + } + + private static Map invertMap(Map map) { + Map inverted = new HashMap<>(map.size()); + for (Map.Entry entry : map.entrySet()) { + inverted.put(entry.getValue(), entry.getKey()); + } + return Collections.unmodifiableMap(inverted); + } + + /** + * Spans are built using this builder + */ + public class CoreSpanBuilder implements AgentTracer.SpanBuilder { + private final String instrumentationName; + private final CharSequence operationName; + private final CoreTracer tracer; + + // Builder attributes + private Map tags; + private long timestampMicro; + private AgentSpan.Context parent; + private String serviceName; + private String resourceName; + private boolean errorFlag; + private CharSequence spanType; + private boolean ignoreScope = false; + private Object builderRequestContextDataAppSec; + private Object builderRequestContextDataIast; + private Object builderCiVisibilityContextData; + private List links; + + CoreSpanBuilder( + final String instrumentationName, final CharSequence operationName, CoreTracer tracer) { + this.instrumentationName = instrumentationName; + this.operationName = operationName; + this.tracer = tracer; + } + + @Override + public CoreSpanBuilder ignoreActiveSpan() { + ignoreScope = true; + return this; + } + + private DDSpan buildSpan() { + addTerminatedContextAsLinks(); + DDSpan span = DDSpan.create(instrumentationName, timestampMicro, buildSpanContext(), links); + if (span.isLocalRootSpan()) { + EndpointTracker tracker = tracer.onRootSpanStarted(span); + span.setEndpointTracker(tracker); + } + return span; + } + + private void addTerminatedContextAsLinks() { + if (this.parent instanceof TagContext) { + List terminatedContextLinks = + ((TagContext) this.parent).getTerminatedContextLinks(); + if (!terminatedContextLinks.isEmpty()) { + if (this.links == null) { + this.links = new ArrayList<>(); + } + this.links.addAll(terminatedContextLinks); + } + } + } + + @Override + public AgentSpan start() { + return buildSpan(); + } + + @Override + public CoreSpanBuilder withTag(final String tag, final Number number) { + return withTag(tag, (Object) number); + } + + @Override + public CoreSpanBuilder withTag(final String tag, final String string) { + return withTag(tag, (Object) (string == null || string.isEmpty() ? null : string)); + } + + @Override + public CoreSpanBuilder withTag(final String tag, final boolean bool) { + return withTag(tag, (Object) bool); + } + + @Override + public CoreSpanBuilder withStartTimestamp(final long timestampMicroseconds) { + timestampMicro = timestampMicroseconds; + return this; + } + + @Override + public CoreSpanBuilder withServiceName(final String serviceName) { + this.serviceName = serviceName; + return this; + } + + @Override + public CoreSpanBuilder withResourceName(final String resourceName) { + this.resourceName = resourceName; + return this; + } + + @Override + public CoreSpanBuilder withErrorFlag() { + errorFlag = true; + return this; + } + + @Override + public CoreSpanBuilder withSpanType(final CharSequence spanType) { + this.spanType = spanType; + return this; + } + + @Override + public CoreSpanBuilder asChildOf(final AgentSpan.Context spanContext) { + // TODO we will start propagating stack trace hash and it will need to + // be extracted here if available + parent = spanContext; + return this; + } + + public CoreSpanBuilder asChildOf(final AgentSpan agentSpan) { + parent = agentSpan.context(); + return this; + } + + @Override + public CoreSpanBuilder withTag(final String tag, final Object value) { + if (tag == null) { + return this; + } + Map tagMap = tags; + if (tagMap == null) { + tags = tagMap = new LinkedHashMap<>(); // Insertion order is important + } + if (value == null) { + tagMap.remove(tag); + } else { + tagMap.put(tag, value); + } + return this; + } + + @Override + public AgentTracer.SpanBuilder withRequestContextData(RequestContextSlot slot, T data) { + switch (slot) { + case APPSEC: + builderRequestContextDataAppSec = data; + break; + case CI_VISIBILITY: + builderCiVisibilityContextData = data; + break; + case IAST: + builderRequestContextDataIast = data; + break; + } + return this; + } + + @Override + public AgentTracer.SpanBuilder withLink(AgentSpanLink link) { + if (link != null) { + if (this.links == null) { + this.links = new ArrayList<>(); + } + this.links.add(link); + } + return this; + } + + /** + * Build the SpanContext, if the actual span has a parent, the following attributes must be + * propagated: - ServiceName - Baggage - Trace (a list of all spans related) - SpanType + * + * @return the context + */ + private DDSpanContext buildSpanContext() { + final DDTraceId traceId; + final long spanId = idGenerationStrategy.generateSpanId(); + final long parentSpanId; + final Map baggage; + final PendingTrace parentTrace; + final int samplingPriority; + final CharSequence origin; + final Map coreTags; + final Map rootSpanTags; + + final DDSpanContext context; + Object requestContextDataAppSec; + Object requestContextDataIast; + Object ciVisibilityContextData; + final PathwayContext pathwayContext; + final PropagationTags propagationTags; + + // FIXME [API] parentContext should be an interface implemented by ExtractedContext, + // TagContext, DDSpanContext, AgentSpan.Context + AgentSpan.Context parentContext = parent; + if (parentContext == null && !ignoreScope) { + // use the Scope as parent unless overridden or ignored. + final AgentSpan activeSpan = scopeManager.activeSpan(); + if (activeSpan != null) { + parentContext = activeSpan.context(); + } + } + + String parentServiceName = null; + + // Propagate internal trace. + // Note: if we are not in the context of distributed tracing and we are starting the first + // root span, parentContext will be null at this point. + if (parentContext instanceof DDSpanContext) { + final DDSpanContext ddsc = (DDSpanContext) parentContext; + traceId = ddsc.getTraceId(); + parentSpanId = ddsc.getSpanId(); + baggage = ddsc.getBaggageItems(); + parentTrace = ddsc.getTrace(); + samplingPriority = PrioritySampling.UNSET; + origin = null; + coreTags = null; + rootSpanTags = null; + parentServiceName = ddsc.getServiceName(); + if (serviceName == null) { + serviceName = parentServiceName; + } + RequestContext requestContext = ((DDSpanContext) parentContext).getRequestContext(); + if (requestContext != null) { + requestContextDataAppSec = requestContext.getData(RequestContextSlot.APPSEC); + requestContextDataIast = requestContext.getData(RequestContextSlot.IAST); + ciVisibilityContextData = requestContext.getData(RequestContextSlot.CI_VISIBILITY); + } else { + requestContextDataAppSec = null; + requestContextDataIast = null; + ciVisibilityContextData = null; + } + propagationTags = propagationTagsFactory.empty(); + } else { + long endToEndStartTime; + + if (parentContext instanceof ExtractedContext) { + // Propagate external trace + final ExtractedContext extractedContext = (ExtractedContext) parentContext; + traceId = extractedContext.getTraceId(); + parentSpanId = extractedContext.getSpanId(); + samplingPriority = extractedContext.getSamplingPriority(); + endToEndStartTime = extractedContext.getEndToEndStartTime(); + propagationTags = extractedContext.getPropagationTags(); + } else if (parentContext != null) { + traceId = + parentContext.getTraceId() == DDTraceId.ZERO + ? idGenerationStrategy.generateTraceId() + : parentContext.getTraceId(); + parentSpanId = parentContext.getSpanId(); + samplingPriority = parentContext.getSamplingPriority(); + endToEndStartTime = 0; + propagationTags = propagationTagsFactory.empty(); + } else { + // Start a new trace + traceId = idGenerationStrategy.generateTraceId(); + parentSpanId = DDSpanId.ZERO; + samplingPriority = PrioritySampling.UNSET; + endToEndStartTime = 0; + propagationTags = propagationTagsFactory.empty(); + } + + ConfigSnapshot traceConfig; + + // Get header tags and set origin whether propagating or not. + if (parentContext instanceof TagContext) { + TagContext tc = (TagContext) parentContext; + traceConfig = (ConfigSnapshot) tc.getTraceConfig(); + coreTags = tc.getTags(); + origin = tc.getOrigin(); + baggage = tc.getBaggage(); + requestContextDataAppSec = tc.getRequestContextDataAppSec(); + requestContextDataIast = tc.getRequestContextDataIast(); + ciVisibilityContextData = tc.getCiVisibilityContextData(); + } else { + traceConfig = null; + coreTags = null; + origin = null; + baggage = null; + requestContextDataAppSec = null; + requestContextDataIast = null; + ciVisibilityContextData = null; + } + + rootSpanTags = localRootSpanTags; + + parentTrace = createTrace(traceId, traceConfig); + + if (endToEndStartTime > 0) { + parentTrace.beginEndToEnd(endToEndStartTime); + } + } + + // Use parent pathwayContext if present and started + pathwayContext = + parentContext != null + && parentContext.getPathwayContext() != null + && parentContext.getPathwayContext().isStarted() + ? parentContext.getPathwayContext() + : dataStreamsMonitoring.newPathwayContext(); + + // when removing fake services the best upward service name to pick is the local root one + // since a split by tag (i.e. servlet context) might have happened on it. + if (!allowInferredServices) { + final DDSpan rootSpan = parentTrace.getRootSpan(); + serviceName = rootSpan != null ? rootSpan.getServiceName() : null; + } + if (serviceName == null) { + serviceName = CoreTracer.this.serviceName; + } + + final CharSequence operationName = + this.operationName != null ? this.operationName : resourceName; + + final int tagsSize = + (null == tags ? 0 : tags.size()) + + defaultSpanTags.size() + + (null == coreTags ? 0 : coreTags.size()) + + (null == rootSpanTags ? 0 : rootSpanTags.size()); + + if (builderRequestContextDataAppSec != null) { + requestContextDataAppSec = builderRequestContextDataAppSec; + } + if (builderCiVisibilityContextData != null) { + ciVisibilityContextData = builderCiVisibilityContextData; + } + if (builderRequestContextDataIast != null) { + requestContextDataIast = builderRequestContextDataIast; + } + + // some attributes are inherited from the parent + context = + new DDSpanContext( + traceId, + spanId, + parentSpanId, + parentServiceName, + serviceName, + operationName, + resourceName, + samplingPriority, + origin, + baggage, + errorFlag, + spanType, + tagsSize, + parentTrace, + requestContextDataAppSec, + requestContextDataIast, + ciVisibilityContextData, + pathwayContext, + disableSamplingMechanismValidation, + propagationTags, + profilingContextIntegration, + injectBaggageAsTags); + + // By setting the tags on the context we apply decorators to any tags that have been set via + // the builder. This is the order that the tags were added previously, but maybe the `tags` + // set in the builder should come last, so that they override other tags. + context.setAllTags(defaultSpanTags); + context.setAllTags(tags); + context.setAllTags(coreTags); + context.setAllTags(rootSpanTags); + return context; + } + } + + private static class ShutdownHook extends Thread { + private final WeakReference reference; + + private ShutdownHook(final CoreTracer tracer) { + super(AGENT_THREAD_GROUP, "dd-tracer-shutdown-hook"); + reference = new WeakReference<>(tracer); + } + + @Override + public void run() { + final CoreTracer tracer = reference.get(); + if (tracer != null) { + tracer.close(); + } + } + } + + protected class ConfigSnapshot extends DynamicConfig.Snapshot { + final Sampler sampler; + + protected ConfigSnapshot( + DynamicConfig.Builder builder, ConfigSnapshot oldSnapshot) { + super(builder, oldSnapshot); + + if (null == oldSnapshot) { + sampler = CoreTracer.this.initialSampler; + } else if (Objects.equals(getTraceSampleRate(), oldSnapshot.getTraceSampleRate())) { + sampler = oldSnapshot.sampler; + } else { + sampler = Sampler.Builder.forConfig(CoreTracer.this.initialConfig, this); + } + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java b/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java new file mode 100644 index 0000000000..dfa76bf097 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java @@ -0,0 +1,824 @@ +package datadog.trace.core; + +import static datadog.trace.api.DDTags.TRACE_START_TIME; +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static datadog.trace.api.sampling.PrioritySampling.USER_DROP; +import static datadog.trace.bootstrap.instrumentation.api.InstrumentationTags.RECORD_END_TO_END_DURATION_MS; +import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_STATUS; +import static java.util.concurrent.TimeUnit.MICROSECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +import datadog.trace.api.Config; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTags; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.EndpointTracker; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.gateway.Flow; +import datadog.trace.api.gateway.RequestContext; +import datadog.trace.api.metrics.SpanMetricRegistry; +import datadog.trace.api.metrics.SpanMetrics; +import datadog.trace.api.profiling.TransientProfilingContextHolder; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.api.sampling.SamplingMechanism; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; +import datadog.trace.bootstrap.instrumentation.api.AttachableWrapper; +import datadog.trace.bootstrap.instrumentation.api.ErrorPriorities; +import datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Represents a period of time. Associated information is stored in the SpanContext. + * + *

Spans are created by the {@link CoreTracer#buildSpan}. This implementation adds some features + * according to the DD agent. + */ +public class DDSpan + implements AgentSpan, CoreSpan, TransientProfilingContextHolder, AttachableWrapper { + private static final Logger log = LoggerFactory.getLogger(DDSpan.class); + + public static final String CHECKPOINTED_TAG = "checkpointed"; + + static DDSpan create( + final String instrumentationName, + final long timestampMicro, + @Nonnull DDSpanContext context, + final List links) { + final DDSpan span = new DDSpan(instrumentationName, timestampMicro, context, links); + log.debug("Started span: {}", span); + context.getTrace().registerSpan(span); + return span; + } + + /** The metrics for this span instance. */ + private final SpanMetrics metrics; + + /** The context attached to the span */ + private final DDSpanContext context; + + /** Is the source of time an external clock or our internal tick-adjusted clock? */ + private final boolean externalClock; + + /** + * Creation time of span in nanoseconds. Must be greater than zero. For our internal clock we use + * combination of millisecond-precision clock and nanosecond-precision offset from start of the + * trace. See {@link PendingTrace} for details. + */ + private final long startTimeNano; + + private static final AtomicLongFieldUpdater DURATION_NANO_UPDATER = + AtomicLongFieldUpdater.newUpdater(DDSpan.class, "durationNano"); + + /** + * The duration in nanoseconds computed using the startTimeMicro or startTimeNano.


The span's + * states are defined as follows: + *
  • eq 0 -> unfinished. + *
  • lt 0 -> finished but unpublished. + *
  • gt 0 -> finished and published. + */ + private volatile long durationNano; + + private boolean forceKeep; + + private volatile EndpointTracker endpointTracker; + + // Cached OT/OTel wrapper to avoid multiple allocations, e.g. when span is activated + private volatile Object wrapper; + private static final AtomicReferenceFieldUpdater WRAPPER_FIELD_UPDATER = + AtomicReferenceFieldUpdater.newUpdater(DDSpan.class, Object.class, "wrapper"); + + // the request is to be blocked (AppSec) + private volatile Flow.Action.RequestBlockingAction requestBlockingAction; + + /** + * Version of a span that can be set by the long running spans feature: + *
  • eq 0 -> span is not long running. + *
  • lt 0 -> finished span that had running versions previously written. + *
  • gt 0 -> long running span and its write version. + */ + private volatile int longRunningVersion = 0; + + private final List links; + + /** + * Spans should be constructed using the builder, not by calling the constructor directly. + * + * @param instrumentationName instrumentation that creates the span + * @param timestampMicro if greater than zero, use this time instead of the current time + * @param context the context used for the span + */ + private DDSpan( + @Nonnull String instrumentationName, + final long timestampMicro, + @Nonnull DDSpanContext context, + final List links) { + this.context = context; + this.metrics = SpanMetricRegistry.getInstance().get(instrumentationName); + this.metrics.onSpanCreated(); + + if (timestampMicro <= 0L) { + // note: getting internal time from the trace implicitly 'touches' it + startTimeNano = context.getTrace().getCurrentTimeNano(); + externalClock = false; + } else { + startTimeNano = MICROSECONDS.toNanos(timestampMicro); + externalClock = true; + context.getTrace().touch(); // external clock: explicitly update lastReferenced + } + + this.links = links == null ? new CopyOnWriteArrayList<>() : new CopyOnWriteArrayList<>(links); + } + + public boolean isFinished() { + return durationNano != 0; + } + + private void finishAndAddToTrace(final long durationNano) { + // ensure a min duration of 1 + if (DURATION_NANO_UPDATER.compareAndSet(this, 0, Math.max(1, durationNano))) { + setLongRunningVersion(-this.longRunningVersion); + this.metrics.onSpanFinished(); + PendingTrace.PublishState publishState = context.getTrace().onPublish(this); + log.debug("Finished span ({}): {}", publishState, this); + } else { + log.debug("Already finished: {}", this); + } + } + + @Override + public void finish() { + if (!externalClock) { + // no external clock was used, so we can rely on nano time + finishAndAddToTrace(context.getTrace().getCurrentTimeNano() - startTimeNano); + } else { + finish(context.getTrace().getTimeSource().getCurrentTimeMicros()); + } + } + + @Override + public void finish(final long stopTimeMicros) { + long durationNano; + if (!externalClock) { + // first capture wall-clock offset from 'now' to external stop time + long externalOffsetMicros = + stopTimeMicros - context.getTrace().getTimeSource().getCurrentTimeMicros(); + // immediately afterwards calculate internal duration of span to 'now' + // note: getting internal time from the trace implicitly 'touches' it + durationNano = context.getTrace().getCurrentTimeNano() - startTimeNano; + // drop nanosecond precision part of internal duration (expected behaviour) + durationNano = MILLISECONDS.toNanos(NANOSECONDS.toMillis(durationNano)); + // add wall-clock offset to get total duration to external stop time + durationNano += MICROSECONDS.toNanos(externalOffsetMicros); + } else { + durationNano = MICROSECONDS.toNanos(stopTimeMicros) - startTimeNano; + context.getTrace().touch(); // external clock: explicitly update lastReferenced + } + finishAndAddToTrace(durationNano); + } + + @Override + public final void finishWithDuration(final long durationNano) { + finishAndAddToTrace(durationNano); + } + + private static final boolean legacyEndToEndEnabled = + Config.get().isEndToEndDurationEnabled(false, "legacy"); + + @Override + public void beginEndToEnd() { + if (legacyEndToEndEnabled) { + if (null == getBaggageItem(TRACE_START_TIME)) { + setBaggageItem(TRACE_START_TIME, Long.toString(NANOSECONDS.toMillis(startTimeNano))); + } + } else { + context.beginEndToEnd(); + } + } + + @Override + public void finishWithEndToEnd() { + long e2eStart; + if (legacyEndToEndEnabled) { + String value = context.getBaggageItem(TRACE_START_TIME); + try { + e2eStart = null != value ? MILLISECONDS.toNanos(Long.parseLong(value)) : 0; + } catch (RuntimeException e) { + log.debug("Ignoring invalid end-to-end start time {}", value, e); + e2eStart = 0; + } + } else { + e2eStart = context.getEndToEndStartTime(); + } + if (e2eStart > 0) { + phasedFinish(); + // get end time from start+duration, ignoring negative bit set by phasedFinish + long e2eEnd = startTimeNano + (durationNano & Long.MAX_VALUE); + setTag(RECORD_END_TO_END_DURATION_MS, NANOSECONDS.toMillis(Math.max(0, e2eEnd - e2eStart))); + publish(); + } else { + finish(); + } + } + + @Override + public final boolean phasedFinish() { + long durationNano; + if (!externalClock) { + // note: getting internal time from the trace implicitly 'touches' it + durationNano = context.getTrace().getCurrentTimeNano() - startTimeNano; + } else { + durationNano = context.getTrace().getTimeSource().getCurrentTimeNanos() - startTimeNano; + context.getTrace().touch(); // external clock: explicitly update lastReferenced + } + // Flip the negative bit of the result to allow verifying that publish() is only called once. + if (DURATION_NANO_UPDATER.compareAndSet(this, 0, Math.max(1, durationNano) | Long.MIN_VALUE)) { + log.debug("Finished span (PHASED): {}", this); + return true; + } else { + log.debug("Already finished: {}", this); + return false; + } + } + + @Override + public final void publish() { + long durationNano = this.durationNano; + if (durationNano == 0) { + log.debug("Can't publish unfinished span: {}", this); + } else if (durationNano > 0) { + log.debug("Already published: {}", this); + } else if (DURATION_NANO_UPDATER.compareAndSet( + this, durationNano, durationNano & Long.MAX_VALUE)) { + PendingTrace.PublishState publishState = context.getTrace().onPublish(this); + log.debug("Published span ({}): {}", publishState, this); + } + } + + @Override + public DDSpan setError(final boolean error) { + return setError(error, ErrorPriorities.DEFAULT); + } + + @Override + public DDSpan setError(final boolean error, final byte priority) { + context.setErrorFlag(error, priority); + return this; + } + + @Override + public DDSpan setMeasured(boolean measured) { + context.setMeasured(measured); + return this; + } + + public DDSpan forceKeep(boolean forceKeep) { + this.forceKeep = forceKeep; + return this; + } + + @Override + public boolean isForceKeep() { + return forceKeep; + } + + /** + * Check if the span is the root parent. It means that the traceId is the same as the spanId. In + * the context of distributed tracing this will return true if an only if this is the application + * initializing the trace. + * + * @return true if root, false otherwise + */ + public final boolean isRootSpan() { + return context.getParentId() == DDSpanId.ZERO; + } + + @Override + @Deprecated + public AgentSpan getRootSpan() { + return getLocalRootSpan(); + } + + @Override + public DDSpan getLocalRootSpan() { + return context.getTrace().getRootSpan(); + } + + /** + * Checks whether the span is also the local root span + * + * @return {@literal true} if this span is the same as {@linkplain #getLocalRootSpan()} + */ + public boolean isLocalRootSpan() { + return getLocalRootSpan().equals(this); + } + + @Override + public boolean isSameTrace(final AgentSpan otherSpan) { + // FIXME [API] AgentSpan or AgentSpan.Context should have a "getTraceId()" type method + if (otherSpan instanceof DDSpan) { + return getTraceId().equals(otherSpan.getTraceId()); + } + + return false; + } + + @Override + public DDSpan setErrorMessage(final String errorMessage) { + return setTag(DDTags.ERROR_MSG, errorMessage); + } + + @Override + public DDSpan addThrowable(final Throwable error) { + return addThrowable(error, ErrorPriorities.DEFAULT); + } + + @Override + public DDSpan addThrowable(Throwable error, byte errorPriority) { + if (null != error) { + String message = error.getMessage(); + if (!"broken pipe".equalsIgnoreCase(message) + && (error.getCause() == null + || !"broken pipe".equalsIgnoreCase(error.getCause().getMessage()))) { + // broken pipes happen when clients abort connections, + // which might happen because the application is overloaded + // or warming up - capturing the stack trace and keeping + // the trace may exacerbate existing problems. + setError(true, errorPriority); + final StringWriter errorString = new StringWriter(); + error.printStackTrace(new PrintWriter(errorString)); + setTag(DDTags.ERROR_STACK, errorString.toString()); + } + + setTag(DDTags.ERROR_MSG, message); + setTag(DDTags.ERROR_TYPE, error.getClass().getName()); + } + return this; + } + + @Override + public final DDSpan setTag(final String tag, final String value) { + if (value == null || value.isEmpty()) { + // Remove the tag + context.setTag(tag, null); + } else { + context.setTag(tag, value); + } + return this; + } + + @Override + public final DDSpan setTag(final String tag, final boolean value) { + context.setTag(tag, value); + return this; + } + + @Override + public void setRequestBlockingAction(Flow.Action.RequestBlockingAction rba) { + this.requestBlockingAction = rba; + } + + @Override + public Flow.Action.RequestBlockingAction getRequestBlockingAction() { + return requestBlockingAction; + } + + @Override + public DDSpan setTag(final String tag, final int value) { + // can't use tag interceptor because it might set a metric + // http.status is important because it is expected to be a string downstream + if (HTTP_STATUS.equals(tag)) { + context.setHttpStatusCode((short) value); + } + context.setTag(tag, value); + return this; + } + + @Override + public DDSpan setTag(final String tag, final long value) { + context.setTag(tag, value); + return this; + } + + @Override + public DDSpan setTag(final String tag, final double value) { + context.setTag(tag, value); + return this; + } + + @Override + public DDSpan setTag(final String tag, final Number value) { + context.setTag(tag, value); + return this; + } + + @Override + public DDSpan setMetric(final CharSequence metric, final int value) { + context.setMetric(metric, value); + return this; + } + + @Override + public DDSpan setMetric(CharSequence name, float value) { + context.setMetric(name, value); + return this; + } + + @Override + public DDSpan setMetric(final CharSequence metric, final long value) { + context.setMetric(metric, value); + return this; + } + + @Override + public DDSpan setMetric(final CharSequence metric, final double value) { + context.setMetric(metric, value); + return this; + } + + @Override + public DDSpan setFlag(CharSequence name, boolean value) { + context.setMetric(name, value ? 1 : 0); + return this; + } + + @Override + public DDSpan setTag(final String tag, final CharSequence value) { + if (value == null || value.length() == 0) { + // Remove the tag + context.setTag(tag, null); + } else { + context.setTag(tag, value); + } + return this; + } + + @Override + public DDSpan setTag(final String tag, final Object value) { + context.setTag(tag, value); + return this; + } + + // FIXME [API] this is not on AgentSpan or MutableSpan + @Override + public DDSpan removeTag(final String tag) { + context.setTag(tag, null); + return this; + } + + @Override + public Object getTag(final String tag) { + return context.getTag(tag); + } + + @Override + @Nonnull + public final DDSpanContext context() { + return context; + } + + @Override + public final String getBaggageItem(final String key) { + return context.getBaggageItem(key); + } + + @Override + public final DDSpan setBaggageItem(final String key, final String value) { + context.setBaggageItem(key, value); + return this; + } + + @Override + public AgentSpan setHttpStatusCode(int statusCode) { + context.setHttpStatusCode((short) statusCode); + return this; + } + + @Override + public short getHttpStatusCode() { + return context.getHttpStatusCode(); + } + + @Override + public CharSequence getOrigin() { + return context.getOrigin(); + } + + @Override + public final DDSpan setOperationName(final CharSequence operationName) { + context.setOperationName(operationName); + return this; + } + + @Override + public final DDSpan setServiceName(final String serviceName) { + context.setServiceName(serviceName); + return this; + } + + @Override + public final DDSpan setResourceName(final CharSequence resourceName) { + return setResourceName(resourceName, ResourceNamePriorities.DEFAULT); + } + + @Override + public final DDSpan setResourceName(final CharSequence resourceName, byte priority) { + context.setResourceName(resourceName, priority); + return this; + } + + @Override + public boolean eligibleForDropping() { + int samplingPriority = context.getSamplingPriority(); + return samplingPriority == USER_DROP || samplingPriority == SAMPLER_DROP; + } + + @Override + public RequestContext getRequestContext() { + return context.getRequestContext(); + } + + @Override + public Integer forceSamplingDecision() { + PendingTrace trace = this.context.getTrace(); + DDSpan rootSpan = trace.getRootSpan(); + trace.setSamplingPriorityIfNecessary(); + if (rootSpan == null) { + return null; + } + return rootSpan.getSamplingPriority(); + } + + @Deprecated + @Override + public final DDSpan setSamplingPriority(final int newPriority) { + // this method exist only to satisfy MutableSpan. It will be removed in 1.0 + return setSamplingPriority(newPriority, SamplingMechanism.UNKNOWN); + } + + /** + * Set the sampling priority of the root span of this span's trace + * + *

    Has no effect if the span priority has been propagated (injected or extracted). + */ + @Override + public final DDSpan setSamplingPriority(final int newPriority, int samplingMechanism) { + context.setSamplingPriority(newPriority, samplingMechanism); + return this; + } + + @Override + public DDSpan setSamplingPriority( + int samplingPriority, CharSequence rate, double sampleRate, int samplingMechanism) { + if (context.setSamplingPriority(samplingPriority, samplingMechanism)) { + setMetric(rate, sampleRate); + } + return this; + } + + @Override + public DDSpan setSpanSamplingPriority(double rate, int limit) { + context.setSpanSamplingPriority(rate, limit); + return this; + } + + @Override + public final DDSpan setSpanType(final CharSequence type) { + context.setSpanType(type); + return this; + } + + // Getters + + @Override + public long getStartTime() { + return startTimeNano; + } + + @Override + public long getDurationNano() { + return durationNano; + } + + @Override + public String getServiceName() { + return context.getServiceName(); + } + + @Override + public DDTraceId getTraceId() { + return context.getTraceId(); + } + + @Override + public long getSpanId() { + return context.getSpanId(); + } + + @Override + public long getParentId() { + return context.getParentId(); + } + + @Override + public CharSequence getResourceName() { + return context.getResourceName(); + } + + @Override + public CharSequence getOperationName() { + return context.getOperationName(); + } + + @Override + public CharSequence getSpanName() { + return context.getOperationName(); + } + + @Override + public void setSpanName(final CharSequence spanName) { + context.setOperationName(spanName); + } + + @Override // TODO remove for 1.0: No usages within dd-trace-java + public boolean hasResourceName() { + return context.hasResourceName(); + } + + @Override + public byte getResourceNamePriority() { + return context.getResourceNamePriority(); + } + + @Override + public Integer getSamplingPriority() { + final int samplingPriority = context.getSamplingPriority(); + if (samplingPriority == PrioritySampling.UNSET) { + return null; + } else { + return samplingPriority; + } + } + + @Override + public int samplingPriority() { + return context.getSamplingPriority(); + } + + @Override + public String getSpanType() { + final CharSequence spanType = context.getSpanType(); + return null == spanType ? null : spanType.toString(); + } + + @Override + public Map getTags() { + // This is an imutable copy of the tags + return context.getTags(); + } + + @Override + public CharSequence getType() { + return context.getSpanType(); + } + + @Override + public void processTagsAndBaggage(final MetadataConsumer consumer) { + context.processTagsAndBaggage(consumer, longRunningVersion, links); + } + + @Override + public boolean isError() { + return context.getErrorFlag(); + } + + @Override + public int getError() { + return context.getErrorFlag() ? 1 : 0; + } + + @Override + @SuppressWarnings("unchecked") + public U getTag(CharSequence name, U defaultValue) { + Object tag = getTag(String.valueOf(name)); + return null == tag ? defaultValue : (U) tag; + } + + @Override + public U getTag(CharSequence name) { + return getTag(name, null); + } + + @Override + public boolean hasSamplingPriority() { + return context.getTrace().getRootSpan() == this; + } + + @Override + public boolean isMeasured() { + return context.isMeasured(); + } + + @Override + public boolean isTopLevel() { + return context.isTopLevel(); + } + + /** + * Retrieve the {@linkplain EndpointTracker} instance associated with the corresponding local root + * span + * + * @return an {@linkplain EndpointTracker} instance or {@literal null} + */ + @Nullable + public EndpointTracker getEndpointTracker() { + DDSpan localRootSpan = getLocalRootSpan(); + if (localRootSpan == null) { + return null; + } + if (this.equals(localRootSpan)) { + return endpointTracker; + } + return localRootSpan.endpointTracker; + } + + /** + * Attach an end-point tracker to the corresponding local root span. When this method is called + * multiple times the last invocation will 'win' + * + * @param endpointTracker the end-point tracker instance + */ + public void setEndpointTracker(@Nonnull EndpointTracker endpointTracker) { + DDSpan localRootSpan = getLocalRootSpan(); + if (localRootSpan == null) { + log.warn("Span {} has no associated local root span", this); + return; + } + if (this.equals(localRootSpan)) { + this.endpointTracker = endpointTracker; + } else { + localRootSpan.endpointTracker = endpointTracker; + } + } + + public Map getBaggage() { + return Collections.unmodifiableMap(context.getBaggageItems()); + } + + @Override + public String toString() { + return context.toString() + + ", duration_ns=" + + durationNano + + ", forceKeep=" + + forceKeep + + ", links=" + + links; + } + + @Override + public void attachWrapper(Object wrapper) { + WRAPPER_FIELD_UPDATER.compareAndSet(this, null, wrapper); + } + + @Override + public Object getWrapper() { + return WRAPPER_FIELD_UPDATER.get(this); + } + + public void setLongRunningVersion(int longRunningVersion) { + if (this.longRunningVersion < 0) { + return; + } + this.longRunningVersion = longRunningVersion; + } + + @Override + public TraceConfig traceConfig() { + return context.getTrace().getTraceConfig(); + } + + @Override + public void addLink(AgentSpanLink link) { + if (link != null) { + this.links.add(link); + } + } + + // to be accessible in Spock spies, which the field wouldn't otherwise be + public long getStartTimeNano() { + return startTimeNano; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java b/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java new file mode 100644 index 0000000000..c7763468e2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java @@ -0,0 +1,935 @@ +package datadog.trace.core; + +import static datadog.trace.api.DDTags.SPAN_LINKS; +import static datadog.trace.api.cache.RadixTreeCache.HTTP_STATUSES; +import static datadog.trace.bootstrap.instrumentation.api.ErrorPriorities.UNSET; + +import datadog.trace.api.DDTags; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.Functions; +import datadog.trace.api.cache.DDCache; +import datadog.trace.api.cache.DDCaches; +import datadog.trace.api.config.TracerConfig; +import datadog.trace.api.gateway.BlockResponseFunction; +import datadog.trace.api.gateway.RequestContext; +import datadog.trace.api.gateway.RequestContextSlot; +import datadog.trace.api.internal.TraceSegment; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.api.sampling.SamplingMechanism; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; +import datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import datadog.trace.bootstrap.instrumentation.api.ProfilerContext; +import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; +import datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.core.propagation.PropagationTags; +import datadog.trace.core.taginterceptor.TagInterceptor; +import datadog.trace.core.tagprocessor.TagsPostProcessorFactory; +import datadog.trace.util.TagsHelper; +import java.io.Closeable; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * SpanContext represents Span state that must propagate to descendant Spans and across process + * boundaries. + * + *

    SpanContext is logically divided into two pieces: (1) the user-level "Baggage" that propagates + * across Span boundaries and (2) any Datadog fields that are needed to identify or contextualize + * the associated Span instance + */ +public class DDSpanContext + implements AgentSpan.Context, RequestContext, TraceSegment, ProfilerContext { + private static final Logger log = LoggerFactory.getLogger(DDSpanContext.class); + + public static final String PRIORITY_SAMPLING_KEY = "_sampling_priority_v1"; + public static final String SAMPLE_RATE_KEY = "_sample_rate"; + + public static final String SPAN_SAMPLING_MECHANISM_TAG = "_dd.span_sampling.mechanism"; + public static final String SPAN_SAMPLING_RULE_RATE_TAG = "_dd.span_sampling.rule_rate"; + public static final String SPAN_SAMPLING_MAX_PER_SECOND_TAG = "_dd.span_sampling.max_per_second"; + + private static final DDCache THREAD_NAMES = + DDCaches.newFixedSizeCache(256); + + private static final Map EMPTY_BAGGAGE = Collections.emptyMap(); + + /** The collection of all span related to this one */ + private final PendingTrace trace; + + /** Baggage is associated with the whole trace and shared with other spans */ + private volatile Map baggageItems; + + // Not Shared with other span contexts + private final DDTraceId traceId; + private final long spanId; + private final long parentId; + + private final String parentServiceName; + + private final long threadId; + private final UTF8BytesString threadName; + + private volatile short httpStatusCode; + + /** + * Tags are associated to the current span, they will not propagate to the children span. + * + *

    The underlying assumption for using a normal Map with synchronized access instead of a + * ConcurrentHashMap is that even though the tags can be accessed and modified from multiple + * threads, they will rarely, if ever, be read and modified concurrently by multiple threads but + * rather read and accessed in a serial fashion on thread after thread. The synchronization can + * then be wrapped around bulk operations to minimize the costly atomic operations. + */ + private final Map unsafeTags; + + /** The service name is required, otherwise the span are dropped by the agent */ + private volatile String serviceName; + + /** The resource associated to the service (server_web, database, etc.) */ + private volatile CharSequence resourceName; + + private volatile byte resourceNamePriority = ResourceNamePriorities.DEFAULT; + /** Each span have an operation name describing the current span */ + private volatile CharSequence operationName; + /** The type of the span. If null, the Datadog Agent will report as a custom */ + private volatile CharSequence spanType; + /** True indicates that the span reports an error */ + private volatile boolean errorFlag; + + private volatile byte errorFlagPriority = UNSET; + + private volatile boolean measured; + + private volatile boolean topLevel; + + private static final AtomicIntegerFieldUpdater SAMPLING_PRIORITY_UPDATER = + AtomicIntegerFieldUpdater.newUpdater(DDSpanContext.class, "samplingPriority"); + + private volatile int samplingPriority = PrioritySampling.UNSET; + + /** The origin of the trace. (eg. Synthetics, CI App) */ + private volatile CharSequence origin; + + /** RequestContext data for the InstrumentationGateway */ + private final Object requestContextDataAppSec; + + private final Object requestContextDataIast; + private final Object ciVisibilityContextData; + + private final boolean disableSamplingMechanismValidation; + + private final PropagationTags propagationTags; + + private volatile PathwayContext pathwayContext; + + private volatile BlockResponseFunction blockResponseFunction; + + private final ProfilingContextIntegration profilingContextIntegration; + private final boolean injectBaggageAsTags; + private volatile int encodedOperationName; + private volatile int encodedResourceName; + + public DDSpanContext( + final DDTraceId traceId, + final long spanId, + final long parentId, + final CharSequence parentServiceName, + final String serviceName, + final CharSequence operationName, + final CharSequence resourceName, + final int samplingPriority, + final CharSequence origin, + final Map baggageItems, + final boolean errorFlag, + final CharSequence spanType, + final int tagsSize, + final PendingTrace trace, + final Object requestContextDataAppSec, + final Object requestContextDataIast, + final PathwayContext pathwayContext, + final boolean disableSamplingMechanismValidation, + final PropagationTags propagationTags) { + this( + traceId, + spanId, + parentId, + parentServiceName, + serviceName, + operationName, + resourceName, + samplingPriority, + origin, + baggageItems, + errorFlag, + spanType, + tagsSize, + trace, + requestContextDataAppSec, + requestContextDataIast, + null, + pathwayContext, + disableSamplingMechanismValidation, + propagationTags, + ProfilingContextIntegration.NoOp.INSTANCE, + true); + } + + public DDSpanContext( + final DDTraceId traceId, + final long spanId, + final long parentId, + final CharSequence parentServiceName, + final String serviceName, + final CharSequence operationName, + final CharSequence resourceName, + final int samplingPriority, + final CharSequence origin, + final Map baggageItems, + final boolean errorFlag, + final CharSequence spanType, + final int tagsSize, + final PendingTrace trace, + final Object requestContextDataAppSec, + final Object requestContextDataIast, + final PathwayContext pathwayContext, + final boolean disableSamplingMechanismValidation, + final PropagationTags propagationTags, + final boolean injectBaggageAsTags) { + this( + traceId, + spanId, + parentId, + parentServiceName, + serviceName, + operationName, + resourceName, + samplingPriority, + origin, + baggageItems, + errorFlag, + spanType, + tagsSize, + trace, + requestContextDataAppSec, + requestContextDataIast, + null, + pathwayContext, + disableSamplingMechanismValidation, + propagationTags, + ProfilingContextIntegration.NoOp.INSTANCE, + injectBaggageAsTags); + } + + public DDSpanContext( + final DDTraceId traceId, + final long spanId, + final long parentId, + final CharSequence parentServiceName, + final String serviceName, + final CharSequence operationName, + final CharSequence resourceName, + final int samplingPriority, + final CharSequence origin, + final Map baggageItems, + final boolean errorFlag, + final CharSequence spanType, + final int tagsSize, + final PendingTrace trace, + final Object requestContextDataAppSec, + final Object requestContextDataIast, + final PathwayContext pathwayContext, + final boolean disableSamplingMechanismValidation, + final PropagationTags propagationTags, + final ProfilingContextIntegration profilingContextIntegration) { + this( + traceId, + spanId, + parentId, + parentServiceName, + serviceName, + operationName, + resourceName, + samplingPriority, + origin, + baggageItems, + errorFlag, + spanType, + tagsSize, + trace, + requestContextDataAppSec, + requestContextDataIast, + null, + pathwayContext, + disableSamplingMechanismValidation, + propagationTags, + profilingContextIntegration, + true); + } + + public DDSpanContext( + final DDTraceId traceId, + final long spanId, + final long parentId, + final CharSequence parentServiceName, + final String serviceName, + final CharSequence operationName, + final CharSequence resourceName, + final int samplingPriority, + final CharSequence origin, + final Map baggageItems, + final boolean errorFlag, + final CharSequence spanType, + final int tagsSize, + final PendingTrace trace, + final Object requestContextDataAppSec, + final Object requestContextDataIast, + final Object CiVisibilityContextData, + final PathwayContext pathwayContext, + final boolean disableSamplingMechanismValidation, + final PropagationTags propagationTags, + final ProfilingContextIntegration profilingContextIntegration, + final boolean injectBaggageAsTags) { + + assert trace != null; + this.trace = trace; + + assert traceId != null; + this.traceId = traceId; + this.spanId = spanId; + this.parentId = parentId; + this.parentServiceName = String.valueOf(parentServiceName); + + if (baggageItems == null || baggageItems.isEmpty()) { + this.baggageItems = EMPTY_BAGGAGE; + } else { + this.baggageItems = new ConcurrentHashMap<>(baggageItems); + } + + this.requestContextDataAppSec = requestContextDataAppSec; + this.requestContextDataIast = requestContextDataIast; + this.ciVisibilityContextData = CiVisibilityContextData; + + assert pathwayContext != null; + this.pathwayContext = pathwayContext; + + // The +1 is the magic number from the tags below that we set at the end, + // and "* 4 / 3" is to make sure that we don't resize immediately + final int capacity = Math.max((tagsSize <= 0 ? 3 : (tagsSize + 1)) * 4 / 3, 8); + this.unsafeTags = new HashMap<>(capacity); + // must set this before setting the service and resource names below + this.profilingContextIntegration = profilingContextIntegration; + // as fast as we can try to make this operation, we still might need to activate/deactivate + // contexts at alarming rates in unpredictable async applications, so we'll try + // to get away with doing this just once per span + this.encodedOperationName = profilingContextIntegration.encodeOperationName(operationName); + + setServiceName(serviceName); + this.operationName = operationName; + setResourceName(resourceName, ResourceNamePriorities.DEFAULT); + this.errorFlag = errorFlag; + this.spanType = spanType; + + // Additional Metadata + final Thread current = Thread.currentThread(); + this.threadId = current.getId(); + this.threadName = THREAD_NAMES.computeIfAbsent(current.getName(), Functions.UTF8_ENCODE); + + this.disableSamplingMechanismValidation = disableSamplingMechanismValidation; + this.propagationTags = + propagationTags != null + ? propagationTags + : trace.getTracer().getPropagationTagsFactory().empty(); + this.propagationTags.updateTraceIdHighOrderBits(this.traceId.toHighOrderLong()); + this.injectBaggageAsTags = injectBaggageAsTags; + if (origin != null) { + setOrigin(origin); + } + if (samplingPriority != PrioritySampling.UNSET) { + setSamplingPriority(samplingPriority, SamplingMechanism.UNKNOWN); + } + } + + @Override + public DDTraceId getTraceId() { + return traceId; + } + + public long getParentId() { + return parentId; + } + + @Override + public long getSpanId() { + return spanId; + } + + @Override + public long getRootSpanId() { + return getRootSpanContextOrThis().spanId; + } + + @Override + public int getEncodedOperationName() { + return encodedOperationName; + } + + @Override + public int getEncodedResourceName() { + return encodedResourceName; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(final String serviceName) { + this.serviceName = trace.mapServiceName(serviceName); + this.topLevel = isTopLevel(parentServiceName, this.serviceName); + } + + // TODO this logic is inconsistent with hasResourceName + public CharSequence getResourceName() { + return isResourceNameSet() ? resourceName : operationName; + } + + public boolean hasResourceName() { + return isResourceNameSet() || getTag(DDTags.RESOURCE_NAME) != null; + } + + public byte getResourceNamePriority() { + return resourceNamePriority; + } + + public void setResourceName(final CharSequence resourceName, byte priority) { + if (null == resourceName) { + return; + } + if (priority >= this.resourceNamePriority) { + this.resourceNamePriority = priority; + this.resourceName = resourceName; + this.encodedResourceName = profilingContextIntegration.encodeResourceName(resourceName); + } + } + + private boolean isResourceNameSet() { + return resourceName != null && resourceName.length() != 0; + } + + public CharSequence getOperationName() { + return operationName; + } + + public void setOperationName(final CharSequence operationName) { + this.operationName = operationName; + this.encodedOperationName = profilingContextIntegration.encodeOperationName(operationName); + } + + public boolean getErrorFlag() { + return errorFlag; + } + + public void setErrorFlag(final boolean errorFlag, final byte priority) { + if (priority > UNSET && priority >= this.errorFlagPriority) { + this.errorFlag = errorFlag; + this.errorFlagPriority = priority; + } + } + + public boolean isMeasured() { + return measured; + } + + public void setMeasured(boolean measured) { + if (measured != this.measured) { + this.measured = measured; + } + } + + public boolean isTopLevel() { + return topLevel; + } + + private static boolean isTopLevel(String parentServiceName, String serviceName) { + return parentServiceName == null + || parentServiceName.length() == 0 + || !parentServiceName.equals(serviceName); + } + + public CharSequence getSpanType() { + return spanType; + } + + public void setSpanType(final CharSequence spanType) { + this.spanType = spanType; + } + + public void forceKeep() { + // set trace level sampling priority + getRootSpanContextOrThis().forceKeepThisSpan(SamplingMechanism.MANUAL); + } + + private void forceKeepThisSpan(byte samplingMechanism) { + // if the user really wants to keep this trace chunk, we will let them, + // even if the old sampling priority and mechanism have already propagated + if (SAMPLING_PRIORITY_UPDATER.getAndSet(this, PrioritySampling.USER_KEEP) + == PrioritySampling.UNSET) { + propagationTags.updateTraceSamplingPriority(PrioritySampling.USER_KEEP, samplingMechanism); + } + } + + /** @return if sampling priority was set by this method invocation */ + public boolean setSamplingPriority(final int newPriority, final int newMechanism) { + DDSpanContext spanContext = getRootSpanContextOrThis(); + // set trace level sampling priority + return spanContext.setThisSpanSamplingPriority(newPriority, newMechanism); + } + + private DDSpanContext getRootSpanContextOrThis() { + DDSpanContext rootSpanContext = getRootSpanContextIfDifferent(); + return rootSpanContext != null ? rootSpanContext : this; + } + + private DDSpanContext getRootSpanContextIfDifferent() { + if (trace != null) { + final DDSpan rootSpan = trace.getRootSpan(); + if (null != rootSpan && rootSpan.context() != this) { + return rootSpan.context(); + } + } + return null; + } + + private boolean setThisSpanSamplingPriority(final int newPriority, final int newMechanism) { + if (!validateSamplingPriority(newPriority, newMechanism)) { + return false; + } + if (!SAMPLING_PRIORITY_UPDATER.compareAndSet(this, PrioritySampling.UNSET, newPriority)) { + if (log.isDebugEnabled()) { + log.debug( + "samplingPriority locked at priority: {}. Refusing to set to priority: {} mechanism: {}", + samplingPriority, + newPriority, + newMechanism); + } + return false; + } + // set trace level sampling priority tag propagationTags + propagationTags.updateTraceSamplingPriority(newPriority, newMechanism); + return true; + } + + private boolean validateSamplingPriority(final int newPriority, final int newMechanism) { + if (newPriority == PrioritySampling.UNSET) { + log.debug("{}: Refusing to set samplingPriority to UNSET", this); + return false; + } + if (!SamplingMechanism.validateWithSamplingPriority(newMechanism, newPriority)) { + if (disableSamplingMechanismValidation) { + log.debug( + "{}: Bypassing setting setSamplingPriority check (" + + TracerConfig.SAMPLING_MECHANISM_VALIDATION_DISABLED + + ") for a non valid combination of samplingMechanism {} and samplingPriority {}.", + this, + newMechanism, + newPriority); + } else { + log.debug( + "{}: Refusing to set samplingMechanism to {}. Provided samplingPriority {} is not allowed.", + this, + newMechanism, + newPriority); + return false; + } + } + return true; + } + + @Override + public int getSamplingPriority() { + return getRootSpanContextOrThis().samplingPriority; + } + + public void setSpanSamplingPriority(double rate, int limit) { + synchronized (unsafeTags) { + unsafeSetTag(SPAN_SAMPLING_MECHANISM_TAG, SamplingMechanism.SPAN_SAMPLING_RATE); + unsafeSetTag(SPAN_SAMPLING_RULE_RATE_TAG, rate); + if (limit != Integer.MAX_VALUE) { + unsafeSetTag(SPAN_SAMPLING_MAX_PER_SECOND_TAG, limit); + } + } + } + + /** + * Prevent future changes to the context's sampling priority. + * + *

    Used when a span is extracted or injected for propagation. + * + *

    Has no effect if the sampling priority is unset. + * + * @return true if the sampling priority was locked. + */ + @Deprecated + public boolean lockSamplingPriority() { + // this is now effectively a no-op - there is no locking. + // the priority is just CAS'd against UNSET/UNKNOWN, unless it's forced to USER_KEEP/MANUAL + // but is maintained for backwards compatibility, and returns false when it used to + final DDSpan rootSpan = trace.getRootSpan(); + if (null != rootSpan && rootSpan.context() != this) { + return rootSpan.context().lockSamplingPriority(); + } + + return SAMPLING_PRIORITY_UPDATER.get(this) != PrioritySampling.UNSET; + } + + public CharSequence getOrigin() { + return getRootSpanContextOrThis().origin; + } + + public void beginEndToEnd() { + trace.beginEndToEnd(); + } + + public long getEndToEndStartTime() { + return trace.getEndToEndStartTime(); + } + + public void setBaggageItem(final String key, final String value) { + if (baggageItems == EMPTY_BAGGAGE) { + synchronized (this) { + if (baggageItems == EMPTY_BAGGAGE) { + baggageItems = new ConcurrentHashMap<>(4); + } + } + } + baggageItems.put(key, value); + } + + public String getBaggageItem(final String key) { + return baggageItems.get(key); + } + + public Map getBaggageItems() { + return baggageItems; + } + + @Override + public Iterable> baggageItems() { + return baggageItems.entrySet(); + } + + @Override + public PendingTrace getTrace() { + return trace; + } + + public RequestContext getRequestContext() { + return this; + } + + @Override + public PathwayContext getPathwayContext() { + return pathwayContext; + } + + @Override + public void mergePathwayContext(PathwayContext pathwayContext) { + if (pathwayContext == null) { + return; + } + + // This is purposely not thread safe + // The code randomly chooses between the two PathwayContexts. + // If there is a race, then that's okay + if (this.pathwayContext.isStarted()) { + // Randomly select between keeping the current context (0) or replacing (1) + if (ThreadLocalRandom.current().nextInt(2) == 1) { + this.pathwayContext = pathwayContext; + } + } else { + this.pathwayContext = pathwayContext; + } + } + + public CoreTracer getTracer() { + return trace.getTracer(); + } + + public void setHttpStatusCode(short statusCode) { + this.httpStatusCode = statusCode; + } + + public short getHttpStatusCode() { + return httpStatusCode; + } + + public void setOrigin(final CharSequence origin) { + DDSpanContext context = getRootSpanContextOrThis(); + context.origin = origin; + context.propagationTags.updateTraceOrigin(origin); + } + + public void setMetric(final CharSequence key, final Number value) { + synchronized (unsafeTags) { + unsafeSetTag(key.toString(), value); + } + } + + /** + * Sets a tag to the span. Tags are not propagated to the children. + * + *

    Existing tag value with the same value will be replaced. Setting a tag with a {@code null} + * value will remove the tag from the span. + * + * @param tag The tag name. + * @param value The nullable tag value. + */ + public void setTag(final String tag, final Object value) { + if (null == tag) { + return; + } + if (null == value) { + synchronized (unsafeTags) { + unsafeTags.remove(tag); + } + } else if (!trace.getTracer().getTagInterceptor().interceptTag(this, tag, value)) { + synchronized (unsafeTags) { + unsafeSetTag(tag, value); + } + } + } + + void setAllTags(final Map map) { + if (map == null || map.isEmpty()) { + return; + } + + TagInterceptor tagInterceptor = trace.getTracer().getTagInterceptor(); + synchronized (unsafeTags) { + for (final Map.Entry tag : map.entrySet()) { + if (!tagInterceptor.interceptTag(this, tag.getKey(), tag.getValue())) { + unsafeSetTag(tag.getKey(), tag.getValue()); + } + } + } + } + + void unsafeSetTag(final String tag, final Object value) { + unsafeTags.put(tag, value); + } + + Object getTag(final String key) { + switch (key) { + case DDTags.THREAD_ID: + return threadId; + case DDTags.THREAD_NAME: + // maintain previously observable type of the thread name :| + return threadName.toString(); + case Tags.HTTP_STATUS: + return 0 == httpStatusCode ? null : (int) httpStatusCode; + default: + Object value; + synchronized (unsafeTags) { + value = unsafeGetTag(key); + } + // maintain previously observable type of http url :| + return value == null ? null : Tags.HTTP_URL.equals(key) ? value.toString() : value; + } + } + + /** + * This is not thread-safe and must only be used when it can be guaranteed that the context will + * not be mutated. This is internal API and must not be exposed to users. + * + * @param tag + * @return the value associated with the tag + */ + public Object unsafeGetTag(final String tag) { + return unsafeTags.get(tag); + } + + public Map getTags() { + synchronized (unsafeTags) { + Map tags = new HashMap<>(unsafeTags); + tags.put(DDTags.THREAD_ID, threadId); + // maintain previously observable type of the thread name :| + tags.put(DDTags.THREAD_NAME, threadName.toString()); + if (samplingPriority != PrioritySampling.UNSET) { + tags.put(SAMPLE_RATE_KEY, samplingPriority); + } + if (httpStatusCode != 0) { + tags.put(Tags.HTTP_STATUS, (int) httpStatusCode); + } + // maintain previously observable type of http url :| + Object value = tags.get(Tags.HTTP_URL); + if (value != null) { + tags.put(Tags.HTTP_URL, value.toString()); + } + return Collections.unmodifiableMap(tags); + } + } + + public void processTagsAndBaggage( + final MetadataConsumer consumer, int longRunningVersion, List links) { + synchronized (unsafeTags) { + // Tags + Map tags = + TagsPostProcessorFactory.instance().processTagsWithContext(unsafeTags, this); + String linksTag = DDSpanLink.toTag(links); + if (linksTag != null) { + tags.put(SPAN_LINKS, linksTag); + } + // Baggage + Map baggageItemsWithPropagationTags; + if (injectBaggageAsTags) { + baggageItemsWithPropagationTags = new HashMap<>(baggageItems); + propagationTags.fillTagMap(baggageItemsWithPropagationTags); + } else { + baggageItemsWithPropagationTags = propagationTags.createTagMap(); + } + + consumer.accept( + new Metadata( + threadId, + threadName, + tags, + baggageItemsWithPropagationTags, + samplingPriority != PrioritySampling.UNSET ? samplingPriority : getSamplingPriority(), + measured, + topLevel, + httpStatusCode == 0 ? null : HTTP_STATUSES.get(httpStatusCode), + // Get origin from rootSpan.context + getOrigin(), + longRunningVersion)); + } + } + + @Override + public String toString() { + final StringBuilder s = + new StringBuilder() + .append("DDSpan [ t_id=") + .append(traceId) + .append(", s_id=") + .append(spanId) + .append(", p_id=") + .append(parentId) + .append(" ] trace=") + .append(getServiceName()) + .append("/") + .append(getOperationName()) + .append("/") + .append(getResourceName()); + if (errorFlag) { + s.append(" *errored*"); + } + if (measured) { + s.append(" *measured*"); + } + + synchronized (unsafeTags) { + s.append(" tags=").append(new TreeMap<>(getTags())); + } + return s.toString(); + } + + /** RequestContext Implementation */ + @Override + public Object getData(RequestContextSlot slot) { + if (slot == RequestContextSlot.APPSEC) { + return this.requestContextDataAppSec; + } else if (slot == RequestContextSlot.CI_VISIBILITY) { + return this.ciVisibilityContextData; + } else if (slot == RequestContextSlot.IAST) { + return this.requestContextDataIast; + } + return null; + } + + @Override + public void close() throws IOException { + Exception exc = null; + if (this.requestContextDataAppSec instanceof Closeable) { + try { + ((Closeable) this.requestContextDataAppSec).close(); + } catch (IOException | RuntimeException e) { + exc = e; + } + } + if (this.requestContextDataIast instanceof Closeable) { + try { + ((Closeable) this.requestContextDataIast).close(); + } catch (IOException | RuntimeException e) { + exc = e; + } + } + if (exc != null) { + if (exc instanceof RuntimeException) { + throw (RuntimeException) exc; + } else { + throw (IOException) exc; + } + } + } + + @Override + public TraceSegment getTraceSegment() { + return this; + } + + @Override + public void setBlockResponseFunction(BlockResponseFunction blockResponseFunction) { + getRootSpanContextOrThis().blockResponseFunction = blockResponseFunction; + } + + @Override + public BlockResponseFunction getBlockResponseFunction() { + return getRootSpanContextOrThis().blockResponseFunction; + } + + public PropagationTags getPropagationTags() { + return getRootSpanContextOrThis().propagationTags; + } + + /** TraceSegment Implementation */ + @Override + public void setTagTop(String key, Object value, boolean sanitize) { + getRootSpanContextOrThis().setTagCurrent(key, value, sanitize); + } + + @Override + public void setTagCurrent(String key, Object value, boolean sanitize) { + if (sanitize) { + key = TagsHelper.sanitize(key); + } + this.setTag(key, value); + } + + @Override + public void setDataTop(String key, Object value) { + getRootSpanContextOrThis().setDataCurrent(key, value); + } + + @Override + public void effectivelyBlocked() { + setTag("appsec.blocked", "true"); + } + + @Override + public void setDataCurrent(String key, Object value) { + // TODO is this decided? + String tagKey = "_dd." + key + ".json"; + this.setTag(tagKey, value); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanLink.java b/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanLink.java new file mode 100644 index 0000000000..69f0659c08 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanLink.java @@ -0,0 +1,137 @@ +package datadog.trace.core; + +import static datadog.trace.bootstrap.instrumentation.api.SpanLinkAttributes.EMPTY; + +import com.squareup.moshi.FromJson; +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.Moshi; +import com.squareup.moshi.ToJson; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTraceId; +import datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; +import datadog.trace.bootstrap.instrumentation.api.SpanLink; +import datadog.trace.bootstrap.instrumentation.api.SpanLinkAttributes; +import datadog.trace.core.propagation.ExtractedContext; +import datadog.trace.core.propagation.PropagationTags; +import java.util.List; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** This class holds helper methods to encode span links into span context. */ +public class DDSpanLink extends SpanLink { + private static final Logger LOGGER = LoggerFactory.getLogger(DDSpanLink.class); + /** The maximum of characters a span tag value can hold. */ + private static final int TAG_MAX_LENGTH = 25_000; + /** JSON encoder (lazily initialized) */ + private static JsonAdapter encoder; + + protected DDSpanLink( + DDTraceId traceId, long spanId, byte traceFlags, String traceState, Attributes attributes) { + super(traceId, spanId, traceFlags, traceState, attributes); + } + + /** + * Creates a span link from an {@link ExtractedContext}. Gathers the trace and span identifiers, + * and the W3C trace state from the given instance. + * + * @param context The context of the span to get the link to. + * @return A span link to the given context. + */ + public static SpanLink from(ExtractedContext context) { + return from(context, EMPTY); + } + + /** + * Creates a span link from an {@link ExtractedContext} with custom attributes. Gathers the trace + * and span identifiers, and the W3C trace state from the given instance. + * + * @param context The context of the span to get the link to. + * @param attributes The span link attributes. + * @return A span link to the given context with custom attributes. + */ + public static SpanLink from(ExtractedContext context, Attributes attributes) { + byte traceFlags = context.getSamplingPriority() > 0 ? SAMPLED_FLAG : DEFAULT_FLAGS; + String traceState = + context.getPropagationTags() == null + ? "" + : context.getPropagationTags().headerValue(PropagationTags.HeaderType.W3C); + return new DDSpanLink( + context.getTraceId(), context.getSpanId(), traceFlags, traceState, attributes); + } + + /** + * Encode a span link collection into a tag value. + * + * @param links The span link collection to encode. + * @return The encoded tag value, {@code null} if no links. + */ + public static String toTag(List links) { + if (links == null || links.isEmpty()) { + return null; + } + // Manually encode as JSON array + StringBuilder builder = new StringBuilder("["); + int index = 0; + while (index < links.size()) { + String linkAsJson = getEncoder().toJson(links.get(index)); + int arrayCharsNeeded = index == 0 ? 1 : 2; // Closing bracket and comma separator if needed + if (linkAsJson.length() + builder.length() + arrayCharsNeeded >= TAG_MAX_LENGTH) { + // Do no more fit inside a span tag, stop adding span links + break; + } + if (index > 0) { + builder.append(','); + } + builder.append(linkAsJson); + index++; + } + // Notify of dropped links + while (index < links.size()) { + LOGGER.debug("Span tag full. Dropping span links {}", links.get(index)); + index++; + } + return builder.append(']').toString(); + } + + private static JsonAdapter getEncoder() { + if (encoder == null) { + Moshi moshi = new Moshi.Builder().add(new SpanLinkAdapter()).build(); + encoder = moshi.adapter(AgentSpanLink.class); + } + return encoder; + } + + private static class SpanLinkAdapter { + @ToJson + SpanLinkJson toSpanLinkJson(AgentSpanLink link) { + SpanLinkJson json = new SpanLinkJson(); + json.trace_id = link.traceId().toHexString(); + json.span_id = DDSpanId.toHexString(link.spanId()); + json.flags = link.traceFlags() == 0 ? null : link.traceFlags(); + json.tracestate = link.traceState().isEmpty() ? null : link.traceState(); + if (!link.attributes().isEmpty()) { + json.attributes = link.attributes().asMap(); + } + return json; + } + + @FromJson + AgentSpanLink fromSpanLinkJson(SpanLinkJson json) { + return new DDSpanLink( + DDTraceId.fromHex(json.trace_id), + DDSpanId.fromHex(json.span_id), + json.flags, + json.tracestate, + SpanLinkAttributes.fromMap(json.attributes)); + } + } + + private static class SpanLinkJson { + String trace_id; + String span_id; + Byte flags; + String tracestate; + Map attributes; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/DDTraceCoreInfo.java b/features/dd-trace-core/src/main/java/datadog/trace/core/DDTraceCoreInfo.java new file mode 100644 index 0000000000..4f689e1b75 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/DDTraceCoreInfo.java @@ -0,0 +1,36 @@ +package datadog.trace.core; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +public class DDTraceCoreInfo { + + public static final String JAVA_VERSION = System.getProperty("java.version", "unknown"); + public static final String JAVA_VM_NAME = System.getProperty("java.vm.name", "unknown"); + public static final String JAVA_VM_VENDOR = System.getProperty("java.vm.vendor", "unknown"); + + public static final String VERSION; + + static { + String v; + try (final BufferedReader br = + new BufferedReader( + new InputStreamReader( + DDTraceCoreInfo.class.getResourceAsStream("/dd-trace-core.version"), "UTF-8"))) { + final StringBuilder sb = new StringBuilder(); + + for (int c = br.read(); c != -1; c = br.read()) { + sb.append((char) c); + } + + v = sb.toString().trim(); + } catch (final Exception e) { + v = "unknown"; + } + VERSION = v; + } + + public static void main(final String... args) { + System.out.println(VERSION); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/LongRunningTracesTracker.java b/features/dd-trace-core/src/main/java/datadog/trace/core/LongRunningTracesTracker.java new file mode 100644 index 0000000000..11fdbf57f2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/LongRunningTracesTracker.java @@ -0,0 +1,149 @@ +package datadog.trace.core; + +//import datadog.trace.ddagent.DDAgentFeaturesDiscovery; +//import datadog.trace.ddagent.SharedCommunicationObjects; +import datadog.trace.api.Config; +import datadog.trace.core.monitor.HealthMetrics; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class LongRunningTracesTracker { +// private final DDAgentFeaturesDiscovery features; + private final HealthMetrics healthMetrics; + private long lastFlushMilli = 0; + + private final int maxTrackedTraces; + private final int flushPeriodMilli; + private final long maxTrackedDurationMilli = TimeUnit.HOURS.toMillis(12); + private final List traceArray = new ArrayList<>(1 << 4); + private int dropped = 0; + private int write = 0; + private int expired = 0; + + public static final int NOT_TRACKED = -1; + public static final int UNDEFINED = 0; + public static final int TO_TRACK = 1; + public static final int TRACKED = 2; + public static final int WRITE_RUNNING_SPANS = 3; + public static final int EXPIRED = 4; + +// public LongRunningTracesTracker( +// Config config, +// int maxTrackedTraces, +// SharedCommunicationObjects sharedCommunicationObjects, +// HealthMetrics healthMetrics) { +// this.maxTrackedTraces = maxTrackedTraces; +// this.flushPeriodMilli = +// (int) TimeUnit.SECONDS.toMillis(config.getLongRunningTraceFlushInterval()); +// this.features = sharedCommunicationObjects.featuresDiscovery(config); +// this.healthMetrics = healthMetrics; +// } + public LongRunningTracesTracker( + Config config, + int maxTrackedTraces, + HealthMetrics healthMetrics) { + this.maxTrackedTraces = maxTrackedTraces; + this.flushPeriodMilli = + (int) TimeUnit.SECONDS.toMillis(config.getLongRunningTraceFlushInterval()); +// this.features = sharedCommunicationObjects.featuresDiscovery(config); + this.healthMetrics = healthMetrics; + } + + public boolean add(PendingTraceBuffer.Element element) { + if (!(element instanceof PendingTrace)) { + return false; + } + PendingTrace trace = (PendingTrace) element; + // PendingTraces are added only once + if (!trace.compareAndSetLongRunningState(TO_TRACK, TRACKED)) { + return false; + } + this.addTrace(trace); + return true; + } + + private void addTrace(PendingTrace trace) { + if (trace.empty()) { + return; + } + if (traceArray.size() == maxTrackedTraces) { + dropped++; + return; + } + traceArray.add(trace); + } + + public void flushAndCompact(long nowMilli) { + if (nowMilli < lastFlushMilli + TimeUnit.SECONDS.toMillis(1)) { + return; + } + int i = 0; + while (i < traceArray.size()) { + PendingTrace trace = traceArray.get(i); + if (trace == null) { + cleanSlot(i); + continue; + } + if (trace.empty()) { + trace.compareAndSetLongRunningState(WRITE_RUNNING_SPANS, NOT_TRACKED); + cleanSlot(i); + continue; + } +// if (trace.empty() || !features.supportsLongRunning()) { +// trace.compareAndSetLongRunningState(WRITE_RUNNING_SPANS, NOT_TRACKED); +// cleanSlot(i); +// continue; +// } + if (hasExpired(nowMilli, trace)) { + trace.compareAndSetLongRunningState(WRITE_RUNNING_SPANS, EXPIRED); + expired++; + cleanSlot(i); + continue; + } + if (shouldFlush(nowMilli, trace)) { + if (negativeOrNullPriority(trace)) { + trace.compareAndSetLongRunningState(TRACKED, NOT_TRACKED); + cleanSlot(i); + continue; + } + trace.compareAndSetLongRunningState(TRACKED, WRITE_RUNNING_SPANS); + write++; + trace.write(); + } + i++; + } + lastFlushMilli = nowMilli; + flushStats(); + } + + private boolean hasExpired(long nowMilli, PendingTrace trace) { + return (nowMilli - TimeUnit.NANOSECONDS.toMillis(trace.getRunningTraceStartTime())) + > maxTrackedDurationMilli; + } + + private boolean shouldFlush(long nowMilli, PendingTrace trace) { + return nowMilli + - TimeUnit.NANOSECONDS.toMillis( + Math.max(trace.getRunningTraceStartTime(), trace.getLastWriteTime())) + > flushPeriodMilli; + } + + private void cleanSlot(int index) { + int lastElementIndex = traceArray.size() - 1; + traceArray.set(index, traceArray.get(lastElementIndex)); + traceArray.remove(lastElementIndex); + } + + private boolean negativeOrNullPriority(PendingTrace trace) { + Integer prio = trace.evaluateSamplingPriority(); + return prio == null || prio <= 0; + } + + private void flushStats() { + healthMetrics.onLongRunningUpdate(dropped, write, expired); + dropped = 0; + write = 0; + expired = 0; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/Metadata.java b/features/dd-trace-core/src/main/java/datadog/trace/core/Metadata.java new file mode 100644 index 0000000000..f1f7945416 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/Metadata.java @@ -0,0 +1,87 @@ +package datadog.trace.core; + +import static datadog.trace.api.sampling.PrioritySampling.UNSET; + +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import java.util.Map; + +public final class Metadata { + private final long threadId; + private final UTF8BytesString threadName; + private final UTF8BytesString httpStatusCode; + private final Map tags; + private final Map baggage; + + private final int samplingPriority; + private final boolean measured; + private final boolean topLevel; + private final CharSequence origin; + private final int longRunningVersion; + + public Metadata( + long threadId, + UTF8BytesString threadName, + Map tags, + Map baggage, + int samplingPriority, + boolean measured, + boolean topLevel, + UTF8BytesString httpStatusCode, + CharSequence origin, + int longRunningVersion) { + this.threadId = threadId; + this.threadName = threadName; + this.httpStatusCode = httpStatusCode; + this.tags = tags; + this.baggage = baggage; + this.samplingPriority = samplingPriority; + this.measured = measured; + this.topLevel = topLevel; + this.origin = origin; + this.longRunningVersion = longRunningVersion; + } + + public UTF8BytesString getHttpStatusCode() { + return httpStatusCode; + } + + public CharSequence getOrigin() { + return origin; + } + + public long getThreadId() { + return threadId; + } + + public UTF8BytesString getThreadName() { + return threadName; + } + + public Map getTags() { + return tags; + } + + public Map getBaggage() { + return baggage; + } + + public boolean measured() { + return measured; + } + + public int longRunningVersion() { + return longRunningVersion; + } + + public boolean topLevel() { + return topLevel; + } + + public boolean hasSamplingPriority() { + return samplingPriority != UNSET; + } + + public int samplingPriority() { + return samplingPriority; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/MetadataConsumer.java b/features/dd-trace-core/src/main/java/datadog/trace/core/MetadataConsumer.java new file mode 100644 index 0000000000..0166348bc0 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/MetadataConsumer.java @@ -0,0 +1,11 @@ +package datadog.trace.core; + +import java.util.function.Consumer; + +@FunctionalInterface +public interface MetadataConsumer extends Consumer { + + MetadataConsumer NO_OP = (md) -> {}; + + void accept(Metadata metadata); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/PendingTrace.java b/features/dd-trace-core/src/main/java/datadog/trace/core/PendingTrace.java new file mode 100644 index 0000000000..cb6d33f44a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/PendingTrace.java @@ -0,0 +1,500 @@ +package datadog.trace.core; + +import datadog.trace.monitor.Recording; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.api.time.TimeSource; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentTrace; +import datadog.trace.common.sampling.PrioritySampler; +import datadog.trace.core.CoreTracer.ConfigSnapshot; +import datadog.trace.core.monitor.HealthMetrics; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; +import javax.annotation.Nonnull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class implements the following data flow rules when a Span is finished: + * + *

      + *
    • Immediate Write + *
        + *
      • pending ref count == 0 && trace not already written + *
      • not root span && size exceeds partial flush + *
      + *
    • Delayed Write + *
        + *
      • is root span && pending ref count > 0 + *
      • not root span && pending ref count > 0 && trace already written + *
      + *
    + * + * Delayed write is handled by PendingTraceBuffer. + * + *

    When the long-running traces feature is enabled, periodic writes are triggered by the + * PendingTraceBuffer in addition to the other write conditions. Running spans are also written in + * that case.
    + */ +public class PendingTrace implements AgentTrace, PendingTraceBuffer.Element { + + private static final Logger log = LoggerFactory.getLogger(PendingTrace.class); + + static class Factory { + private final CoreTracer tracer; + private final PendingTraceBuffer pendingTraceBuffer; + private final TimeSource timeSource; + private final boolean strictTraceWrites; + private final HealthMetrics healthMetrics; + + Factory( + CoreTracer tracer, + PendingTraceBuffer pendingTraceBuffer, + TimeSource timeSource, + boolean strictTraceWrites, + HealthMetrics healthMetrics) { + this.tracer = tracer; + this.pendingTraceBuffer = pendingTraceBuffer; + this.timeSource = timeSource; + this.strictTraceWrites = strictTraceWrites; + this.healthMetrics = healthMetrics; + } + + /** Used by tests and benchmarks. */ + PendingTrace create(@Nonnull DDTraceId traceId) { + return create(traceId, null); + } + + PendingTrace create(@Nonnull DDTraceId traceId, ConfigSnapshot traceConfig) { + return new PendingTrace( + tracer, + traceId, + pendingTraceBuffer, + timeSource, + traceConfig, + strictTraceWrites, + healthMetrics); + } + } + + private static final List EMPTY = new ArrayList<>(0); + + private final CoreTracer tracer; + private final DDTraceId traceId; + private final PendingTraceBuffer pendingTraceBuffer; + private final TimeSource timeSource; + private final boolean strictTraceWrites; + private final HealthMetrics healthMetrics; + private final ConfigSnapshot traceConfig; + + /** + * Contains finished spans. If the long-running trace feature is enabled it also contains running + * spans that can be written. + */ + private final ConcurrentLinkedDeque spans; + + private volatile int completedSpanCount = 0; + private static final AtomicIntegerFieldUpdater COMPLETED_SPAN_COUNT = + AtomicIntegerFieldUpdater.newUpdater(PendingTrace.class, "completedSpanCount"); + + private volatile int pendingReferenceCount = 0; + private static final AtomicIntegerFieldUpdater PENDING_REFERENCE_COUNT = + AtomicIntegerFieldUpdater.newUpdater(PendingTrace.class, "pendingReferenceCount"); + + private volatile int isEnqueued = 0; + private static final AtomicIntegerFieldUpdater IS_ENQUEUED = + AtomicIntegerFieldUpdater.newUpdater(PendingTrace.class, "isEnqueued"); + + private volatile int longRunningTrackedState = LongRunningTracesTracker.UNDEFINED; + private static final AtomicIntegerFieldUpdater LONG_RUNNING_STATE = + AtomicIntegerFieldUpdater.newUpdater(PendingTrace.class, "longRunningTrackedState"); + + private volatile long runningTraceStartTimeNano = 0; + private static final AtomicLongFieldUpdater RUNNING_TRACE_START_TIME_NANO = + AtomicLongFieldUpdater.newUpdater(PendingTrace.class, "runningTraceStartTimeNano"); + private volatile long lastWriteTimeNano = 0; + private static final AtomicLongFieldUpdater LAST_WRITE_TIME_NANO = + AtomicLongFieldUpdater.newUpdater(PendingTrace.class, "lastWriteTimeNano"); + + /** + * During a trace there are cases where the root span must be accessed (e.g. priority sampling and + * trace-search tags). These use cases are an obstacle to span-streaming. + */ + private volatile DDSpan rootSpan = null; + + private static final AtomicReferenceFieldUpdater ROOT_SPAN = + AtomicReferenceFieldUpdater.newUpdater(PendingTrace.class, DDSpan.class, "rootSpan"); + + private volatile boolean rootSpanWritten = false; + + /** + * Updated with the latest nanoTicks each time getCurrentTimeNano is called (at the start and + * finish of each span). + */ + private volatile long lastReferenced = 0; + + private volatile long endToEndStartTime; + private static final AtomicLongFieldUpdater END_TO_END_START_TIME = + AtomicLongFieldUpdater.newUpdater(PendingTrace.class, "endToEndStartTime"); + + private PendingTrace( + @Nonnull CoreTracer tracer, + @Nonnull DDTraceId traceId, + @Nonnull PendingTraceBuffer pendingTraceBuffer, + @Nonnull TimeSource timeSource, + ConfigSnapshot traceConfig, + boolean strictTraceWrites, + HealthMetrics healthMetrics) { + this.tracer = tracer; + this.traceId = traceId; + this.pendingTraceBuffer = pendingTraceBuffer; + this.timeSource = timeSource; + this.traceConfig = traceConfig != null ? traceConfig : tracer.captureTraceConfig(); + this.strictTraceWrites = strictTraceWrites; + this.healthMetrics = healthMetrics; + this.spans = new ConcurrentLinkedDeque<>(); + } + + CoreTracer getTracer() { + return tracer; + } + + TraceConfig getTraceConfig() { + return traceConfig; + } + + String mapServiceName(String serviceName) { + return traceConfig.getServiceMapping().getOrDefault(serviceName, serviceName); + } + + /** + * Current timestamp in nanoseconds; 'touches' the trace by updating {@link #lastReferenced}. + * + *

    Note: This method uses trace start time as a reference and it gets time with nanosecond + * precision after that. This means time measured within same Trace in different Spans is + * relatively correct with nanosecond precision. + * + * @return timestamp in nanoseconds + */ + public long getCurrentTimeNano() { + long nanoTicks = timeSource.getNanoTicks(); + lastReferenced = nanoTicks; + return tracer.getTimeWithNanoTicks(nanoTicks); + } + + public TimeSource getTimeSource() { + return timeSource; + } + + public void touch() { + lastReferenced = timeSource.getNanoTicks(); + } + + @Override + public boolean lastReferencedNanosAgo(long nanos) { + long currentNanoTicks = timeSource.getNanoTicks(); + long age = currentNanoTicks - lastReferenced; + return nanos < age; + } + + void registerSpan(final DDSpan span) { + ROOT_SPAN.compareAndSet(this, null, span); + PENDING_REFERENCE_COUNT.incrementAndGet(this); + healthMetrics.onCreateSpan(); + if (pendingTraceBuffer.longRunningSpansEnabled()) { + spans.addFirst(span); + trackRunningTrace(span); + } + } + + void trackRunningTrace(final DDSpan span) { + if (!compareAndSetLongRunningState( + LongRunningTracesTracker.UNDEFINED, LongRunningTracesTracker.TO_TRACK)) { + return; + } + RUNNING_TRACE_START_TIME_NANO.set(this, span.getStartTime()); + // If the pendingTraceBuffer is full, this trace won't be tracked by the + // LongRunningTracesTracker. + pendingTraceBuffer.enqueue(this); + } + + public Integer evaluateSamplingPriority() { + DDSpan span = spans.peek(); + if (span == null) { + return null; + } + Integer prio = span.getSamplingPriority(); + if (prio == null) { + prio = span.forceSamplingDecision(); + } + return prio; + } + + public boolean compareAndSetLongRunningState(int expected, int newState) { + return LONG_RUNNING_STATE.compareAndSet(this, expected, newState); + } + + boolean empty() { + return 0 >= COMPLETED_SPAN_COUNT.get(this) + PENDING_REFERENCE_COUNT.get(this); + } + + PublishState onPublish(final DDSpan span) { + if (!pendingTraceBuffer.longRunningSpansEnabled()) { + spans.addFirst(span); + } + // There is a benign race here where the span added above can get written out by a writer in + // progress before the count has been incremented. It's being taken care of in the internal + // write method. + healthMetrics.onFinishSpan(); + COMPLETED_SPAN_COUNT.incrementAndGet(this); + return decrementRefAndMaybeWrite(span == getRootSpan()); + } + + @Override + public DDSpan getRootSpan() { + return rootSpan; + } + + /** @return Long.MAX_VALUE if no spans finished. */ + @Override + public long oldestFinishedTime() { + long oldest = Long.MAX_VALUE; + for (DDSpan span : spans) { + if (span.isFinished()) { + oldest = Math.min(oldest, span.getStartTime() + span.getDurationNano()); + } + } + return oldest; + } + + /** + * When using continuations, it's possible one may be used after all existing spans are otherwise + * completed, so we need to wait till continuations are de-referenced before reporting. + */ + @Override + public void registerContinuation(final AgentScope.Continuation continuation) { + PENDING_REFERENCE_COUNT.incrementAndGet(this); + } + + @Override + public void cancelContinuation(final AgentScope.Continuation continuation) { + decrementRefAndMaybeWrite(false); + healthMetrics.onCancelContinuation(); + } + + enum PublishState { + WRITTEN, + PARTIAL_FLUSH, + ROOT_BUFFERED, + BUFFERED, + PENDING + } + + private PublishState decrementRefAndMaybeWrite(boolean isRootSpan) { + final int count = PENDING_REFERENCE_COUNT.decrementAndGet(this); + if (strictTraceWrites && count < 0) { + throw new IllegalStateException("Pending reference count " + count + " is negative"); + } + int partialFlushMinSpans = tracer.getPartialFlushMinSpans(); + + if (count == 0 && (strictTraceWrites || !rootSpanWritten)) { + // Finished with no pending work ... write immediately + write(); + return PublishState.WRITTEN; + } else if (isRootSpan) { + // Finished root with pending work ... delay write + pendingTraceBuffer.enqueue(this); + return PublishState.ROOT_BUFFERED; + } else if (partialFlushMinSpans > 0 && size() >= partialFlushMinSpans) { + // Trace is getting too big, write anything completed. + partialFlush(); + return PublishState.PARTIAL_FLUSH; + } else if (rootSpanWritten) { + // Late arrival span ... delay write + pendingTraceBuffer.enqueue(this); + return PublishState.BUFFERED; + } + return PublishState.PENDING; + } + + /** Important to note: may be called multiple times. */ + private void partialFlush() { + int size = write(true); + healthMetrics.onPartialFlush(size); + if (log.isDebugEnabled()) { + log.debug("t_id={} -> wrote partial trace of size {}", traceId, size); + } + } + + /** Important to note: may be called multiple times. */ + @Override + public void write() { + write(false); + } + + private int write(boolean isPartial) { + if (!spans.isEmpty()) { + try (Recording recording = tracer.writeTimer()) { + // Only one writer at a time + final List trace; + int completedSpans = 0; + synchronized (this) { + if (!isPartial) { + rootSpanWritten = true; + } + int size = size(); + boolean writeRunningSpans = + LongRunningTracesTracker.WRITE_RUNNING_SPANS == LONG_RUNNING_STATE.get(this); + if (writeRunningSpans) { + size += pendingReferenceCount; + } + // If we get here and size is below 0, then the writer before us wrote out at least one + // more trace than the size it had when it started. Those span(s) had been added to + // finishedSpans by some other thread(s) while the existing spans were being written, but + // the completedSpanCount has not yet been incremented. This means that eventually the + // count(s) will be incremented, and any new spans added during the period that the count + // was negative will be written by someone even if we don't write them right now. + if (size > 0 && (!isPartial || size >= tracer.getPartialFlushMinSpans())) { + trace = new ArrayList<>(size); + completedSpans = enqueueSpansToWrite(trace, writeRunningSpans); + } else { + trace = EMPTY; + } + } + if (!trace.isEmpty()) { + COMPLETED_SPAN_COUNT.addAndGet(this, -completedSpans); + tracer.write(trace); + healthMetrics.onCreateTrace(); + return completedSpans; + } + } + } + return 0; + } + + public int enqueueSpansToWrite(List trace, boolean writeRunningSpans) { + int completedSpans = 0; + boolean runningSpanSeen = false; + long firstRunningSpanID = 0; + long nowNano = 0; + if (writeRunningSpans) { + nowNano = getCurrentTimeNano(); + setLastWriteTime(nowNano); + } + + DDSpan span = spans.pollFirst(); + while (null != span) { + if (runningSpanSeen && span.getSpanId() == firstRunningSpanID) { + // we iterated on all spans as we circled back to the first running span + spans.addFirst(span); + break; + } + if (span.isFinished()) { + trace.add(span); + completedSpans++; + } else { + // keep the running span in the list + spans.add(span); + if (!runningSpanSeen) { + runningSpanSeen = true; + firstRunningSpanID = span.getSpanId(); + } + if (writeRunningSpans) { + span.setLongRunningVersion( + (int) TimeUnit.NANOSECONDS.toMillis(nowNano - span.getStartTime())); + trace.add(span); + } + } + span = spans.pollFirst(); + } + return completedSpans; + } + + public int size() { + return completedSpanCount; + } + + public void beginEndToEnd() { + beginEndToEnd(getCurrentTimeNano()); + } + + void beginEndToEnd(long endToEndStartTime) { + END_TO_END_START_TIME.compareAndSet(this, 0, endToEndStartTime); + } + + public long getEndToEndStartTime() { + return endToEndStartTime; + } + + public long getLastWriteTime() { + return LAST_WRITE_TIME_NANO.get(this); + } + + public long getRunningTraceStartTime() { + return RUNNING_TRACE_START_TIME_NANO.get(this); + } + + public void setLastWriteTime(long now) { + LAST_WRITE_TIME_NANO.set(this, now); + } + + @Override + public boolean setEnqueued(boolean enqueued) { + int expected = enqueued ? 0 : 1; + return IS_ENQUEUED.compareAndSet(this, expected, 1 - expected); + } + + /** + * Called when the pendingTraceBuffer is full and a pendingTrace is offered. + * + *

    If the pendingTrace is not sent to the LongRunningTracesTracker, it will be immediately + * written. Otherwise, the pendingTrace won't be tracked and no write is triggered. + */ + public boolean writeOnBufferFull() { + return !compareAndSetLongRunningState( + LongRunningTracesTracker.TO_TRACK, LongRunningTracesTracker.NOT_TRACKED); + } + + /** + * Calculates the duration of a span in nanoseconds for the transport layer + * + *

    As the internal duration of a running span is 0, the duration is set to the difference + * between the span's start time and the time of the write trigger. + */ + public static long getDurationNano(CoreSpan span) { + long duration = span.getDurationNano(); + if (duration > 0) { + return duration; + } + if (!(span instanceof DDSpan)) { + return duration; + } + DDSpan ddSpan = (DDSpan) span; + PendingTrace trace = ddSpan.context().getTrace(); + return trace.getLastWriteTime() - span.getStartTime(); + } + + public void setSamplingPriorityIfNecessary() { + // There's a race where multiple threads can see PrioritySampling.UNSET here + // This check skips potential complex sampling priority logic when we know its redundant + // Locks inside DDSpanContext ensure the correct behavior in the race case + + if (traceConfig.sampler instanceof PrioritySampler + && rootSpan != null + && rootSpan.context().getSamplingPriority() == PrioritySampling.UNSET) { + + ((PrioritySampler) traceConfig.sampler).setSamplingPriority(rootSpan); + } + } + + public boolean sample(DDSpan spanToSample) { + return traceConfig.sampler.sample(spanToSample); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/PendingTraceBuffer.java b/features/dd-trace-core/src/main/java/datadog/trace/core/PendingTraceBuffer.java new file mode 100644 index 0000000000..e735f1ce4a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/PendingTraceBuffer.java @@ -0,0 +1,302 @@ +package datadog.trace.core; + +import static datadog.trace.util.AgentThreadFactory.AgentThread.TRACE_MONITOR; +import static datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; +import static datadog.trace.util.AgentThreadFactory.newAgentThread; + +import datadog.trace.api.Config; +import datadog.trace.api.time.TimeSource; +import datadog.trace.core.monitor.HealthMetrics; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import org.jctools.queues.MessagePassingQueue; +import org.jctools.queues.MpscBlockingConsumerArrayQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class PendingTraceBuffer implements AutoCloseable { + private static final int BUFFER_SIZE = 1 << 12; // 4096 + + public boolean longRunningSpansEnabled() { + return false; + } + + public interface Element { + long oldestFinishedTime(); + + boolean lastReferencedNanosAgo(long nanos); + + void write(); + + DDSpan getRootSpan(); + + /** + * Set or clear if the {@code Element} is enqueued. Needs to be atomic. + * + * @param enqueued true if the enqueued state should be set or false if it should be cleared + * @return true iff the enqueued value was changed from another value to the new value, false + * otherwise + */ + boolean setEnqueued(boolean enqueued); + + boolean writeOnBufferFull(); + } + + private static class DelayingPendingTraceBuffer extends PendingTraceBuffer { + private static final long FORCE_SEND_DELAY_MS = TimeUnit.SECONDS.toMillis(5); + private static final long SEND_DELAY_NS = TimeUnit.MILLISECONDS.toNanos(500); + private static final long SLEEP_TIME_MS = 100; + + private final MpscBlockingConsumerArrayQueue queue; + private final Thread worker; + private final TimeSource timeSource; + + private volatile boolean closed = false; + private final AtomicInteger flushCounter = new AtomicInteger(0); + + private final LongRunningTracesTracker runningTracesTracker; + + public boolean longRunningSpansEnabled() { + return runningTracesTracker != null; + } + + @Override + public void enqueue(Element pendingTrace) { + if (pendingTrace.setEnqueued(true)) { + if (!queue.offer(pendingTrace)) { + // Mark it as not in the queue + pendingTrace.setEnqueued(false); + + if (!pendingTrace.writeOnBufferFull()) { + return; + } + pendingTrace.write(); + } + } + } + + @Override + public void start() { + worker.start(); + } + + @Override + public void close() { + flush(); + closed = true; + worker.interrupt(); + try { + worker.join(THREAD_JOIN_TIMOUT_MS); + } catch (InterruptedException ignored) { + } + } + + private void yieldOrSleep(final int loop) { + if (loop <= 3) { + Thread.yield(); + } else { + try { + Thread.sleep(10); + } catch (Throwable ignored) { + } + } + } + + @Override + public void flush() { + if (worker.isAlive()) { + int count = flushCounter.get(); + int loop = 1; + boolean signaled = queue.offer(FlushElement.FLUSH_ELEMENT); + while (!closed && !signaled) { + yieldOrSleep(loop++); + signaled = queue.offer(FlushElement.FLUSH_ELEMENT); + } + int newCount = flushCounter.get(); + while (!closed && count >= newCount) { + yieldOrSleep(loop++); + newCount = flushCounter.get(); + } + } + } + + private static final class WriteDrain implements MessagePassingQueue.Consumer { + private static final WriteDrain WRITE_DRAIN = new WriteDrain(); + + @Override + public void accept(Element pendingTrace) { + pendingTrace.write(); + } + } + + private static final class FlushElement implements Element { + static FlushElement FLUSH_ELEMENT = new FlushElement(); + + @Override + public long oldestFinishedTime() { + return 0; + } + + @Override + public boolean lastReferencedNanosAgo(long nanos) { + return false; + } + + @Override + public void write() {} + + @Override + public DDSpan getRootSpan() { + return null; + } + + @Override + public boolean setEnqueued(boolean enqueued) { + return true; + } + + @Override + public boolean writeOnBufferFull() { + return true; + } + } + + private final class Worker implements Runnable { + + @Override + public void run() { + try { + while (!closed && !Thread.currentThread().isInterrupted()) { + + Element pendingTrace = null; + if (longRunningSpansEnabled()) { + pendingTrace = queue.poll(1, TimeUnit.SECONDS); + runningTracesTracker.flushAndCompact(timeSource.getCurrentTimeMillis()); + if (pendingTrace == null) { + continue; + } + } else { + pendingTrace = queue.take(); // block until available; + } + + if (pendingTrace instanceof FlushElement) { + // Since this is an MPSC queue, the drain needs to be called on the consumer thread + queue.drain(WriteDrain.WRITE_DRAIN); + flushCounter.incrementAndGet(); + continue; + } + + // The element is no longer in the queue + pendingTrace.setEnqueued(false); + + if (longRunningSpansEnabled()) { + if (runningTracesTracker.add(pendingTrace)) { + continue; + } + } + + long oldestFinishedTime = pendingTrace.oldestFinishedTime(); + long finishTimestampMillis = TimeUnit.NANOSECONDS.toMillis(oldestFinishedTime); + if (finishTimestampMillis <= timeSource.getCurrentTimeMillis() - FORCE_SEND_DELAY_MS) { + // Root span is getting old. Send the trace to avoid being discarded by agent. + pendingTrace.write(); + continue; + } + + if (pendingTrace.lastReferencedNanosAgo(SEND_DELAY_NS)) { + // Trace has been unmodified long enough, go ahead and write whatever is finished. + pendingTrace.write(); + } else { + // Trace is too new. Requeue it and sleep to avoid a hot loop. + enqueue(pendingTrace); + Thread.sleep(SLEEP_TIME_MS); + } + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + public DelayingPendingTraceBuffer( + int bufferSize, + TimeSource timeSource, + Config config, + HealthMetrics healthMetrics) { + this.queue = new MpscBlockingConsumerArrayQueue<>(bufferSize); + this.worker = newAgentThread(TRACE_MONITOR, new Worker()); + this.timeSource = timeSource; + boolean runningSpansEnabled = config.isLongRunningTraceEnabled(); + this.runningTracesTracker = + runningSpansEnabled + ? new LongRunningTracesTracker( + config, bufferSize, healthMetrics) + : null; + } + } +// public DelayingPendingTraceBuffer( +// int bufferSize, +// TimeSource timeSource, +// Config config, +// SharedCommunicationObjects sharedCommunicationObjects, +// HealthMetrics healthMetrics) { +// this.queue = new MpscBlockingConsumerArrayQueue<>(bufferSize); +// this.worker = newAgentThread(TRACE_MONITOR, new Worker()); +// this.timeSource = timeSource; +// boolean runningSpansEnabled = config.isLongRunningTraceEnabled(); +// this.runningTracesTracker = +// runningSpansEnabled +// ? new LongRunningTracesTracker( +// config, bufferSize, sharedCommunicationObjects, healthMetrics) +// : null; +// } +// } + + static class DiscardingPendingTraceBuffer extends PendingTraceBuffer { + private static final Logger log = LoggerFactory.getLogger(DiscardingPendingTraceBuffer.class); + + @Override + public void start() {} + + @Override + public void close() {} + + @Override + public void flush() {} + + @Override + public void enqueue(Element pendingTrace) { + log.debug( + "PendingTrace enqueued but won't be reported. Root span: {}", pendingTrace.getRootSpan()); + } + } + +// public static PendingTraceBuffer delaying( +// TimeSource timeSource, +// Config config, +// SharedCommunicationObjects sharedCommunicationObjects, +// HealthMetrics healthMetrics) { +// return new DelayingPendingTraceBuffer( +// BUFFER_SIZE, timeSource, config, sharedCommunicationObjects, healthMetrics); +// } + public static PendingTraceBuffer delaying( + TimeSource timeSource, + Config config, + HealthMetrics healthMetrics) { + return new DelayingPendingTraceBuffer( + BUFFER_SIZE, timeSource, config, healthMetrics); + } + + public static PendingTraceBuffer discarding() { + return new DiscardingPendingTraceBuffer(); + } + + public abstract void start(); + + @Override + public abstract void close(); + + public abstract void flush(); + + public abstract void enqueue(Element pendingTrace); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/StatusLogger.java b/features/dd-trace-core/src/main/java/datadog/trace/core/StatusLogger.java new file mode 100644 index 0000000000..cf9609cb1c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/StatusLogger.java @@ -0,0 +1,203 @@ +package datadog.trace.core; + +import static datadog.trace.api.Config.isDatadogProfilerEnablementOverridden; +import static datadog.trace.api.Config.isDatadogProfilerSafeInCurrentEnvironment; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.JsonReader; +import com.squareup.moshi.JsonWriter; +import com.squareup.moshi.Moshi; +import datadog.trace.api.Config; +import datadog.trace.api.ProductActivation; +import datadog.trace.logging.LoggingSettingsDescription; +import datadog.trace.util.AgentTaskScheduler; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.Map; +import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class StatusLogger extends JsonAdapter + implements AgentTaskScheduler.Task, JsonAdapter.Factory { + + public static void logStatus(Config config) { + AgentTaskScheduler.INSTANCE.schedule(new StatusLogger(), config, 500, MILLISECONDS); + } + + @Override + public void run(Config config) { + Logger log = LoggerFactory.getLogger(StatusLogger.class); + if (log.isInfoEnabled()) { + log.info( + "DATADOG TRACER CONFIGURATION {}", + new Moshi.Builder().add(this).build().adapter(Config.class).toJson(config)); + } + if (log.isDebugEnabled()) { + log.debug("class path: {}", System.getProperty("java.class.path")); + } + } + + @Override + public Config fromJson(JsonReader reader) { + throw new UnsupportedOperationException(); + } + + @Override + public void toJson(JsonWriter writer, Config config) throws IOException { + if (null == config) { + return; + } + writer.beginObject(); + writer.name("version"); + writer.value(DDTraceCoreInfo.VERSION); + writer.name("os_name"); + writer.value(System.getProperty("os.name")); + writer.name("os_version"); + writer.value(System.getProperty("os.version")); + writer.name("architecture"); + writer.value(System.getProperty("os.arch")); + writer.name("lang"); + writer.value("jvm"); + writer.name("lang_version"); + writer.value(System.getProperty("java.version")); + writer.name("jvm_vendor"); + writer.value(System.getProperty("java.vendor")); + writer.name("jvm_version"); + writer.value(System.getProperty("java.vm.version")); + writer.name("java_class_version"); + writer.value(System.getProperty("java.class.version")); + writer.name("http_nonProxyHosts"); + writer.value(String.valueOf(System.getProperty("http.nonProxyHosts"))); + writer.name("http_proxyHost"); + writer.value(String.valueOf(System.getProperty("http.proxyHost"))); + writer.name("enabled"); + writer.value(config.isTraceEnabled()); + writer.name("service"); + writer.value(config.getServiceName()); + writer.name("agent_url"); + writer.value(config.getAgentUrl()); + writer.name("agent_unix_domain_socket"); + writer.value(config.getAgentUnixDomainSocket()); + writer.name("agent_named_pipe"); + writer.value(config.getAgentNamedPipe()); + writer.name("agent_error"); + writer.value(!agentServiceCheck(config)); + writer.name("debug"); + writer.value(config.isDebugEnabled()); + writer.name("trace_propagation_style_extract"); + writer.beginArray(); + writeSet(writer, config.getTracePropagationStylesToExtract()); + writer.endArray(); + writer.name("trace_propagation_style_inject"); + writer.beginArray(); + writeSet(writer, config.getTracePropagationStylesToInject()); + writer.endArray(); + writer.name("analytics_enabled"); + writer.value(config.isTraceAnalyticsEnabled()); + writer.name("sample_rate"); + writer.value(config.getTraceSampleRate()); + writer.name("sampling_rules"); + writer.beginArray(); + writeMap(writer, config.getTraceSamplingServiceRules()); + writeMap(writer, config.getTraceSamplingOperationRules()); + writer.endArray(); + writer.name("priority_sampling_enabled"); + writer.value(config.isPrioritySamplingEnabled()); + writer.name("logs_correlation_enabled"); + writer.value(config.isLogsInjectionEnabled()); + writer.name("profiling_enabled"); + writer.value(config.isProfilingEnabled()); + writer.name("remote_config_enabled"); + writer.value(config.isRemoteConfigEnabled()); + writer.name("debugger_enabled"); + writer.value(config.isDebuggerEnabled()); + writer.name("appsec_enabled"); + writer.value(config.getAppSecActivation().toString()); + writer.name("appsec_rules_file_path"); + writer.value(config.getAppSecRulesFile()); + writer.name("telemetry_enabled"); + writer.value(config.isTelemetryEnabled()); + writer.name("telemetry_dependency_collection_enabled"); + writer.value(config.isTelemetryDependencyServiceEnabled()); + writer.name("telemetry_log_collection_enabled"); + writer.value(config.isTelemetryLogCollectionEnabled()); + writer.name("dd_version"); + writer.value(config.getVersion()); + writer.name("health_checks_enabled"); + writer.value(config.isHealthMetricsEnabled()); + writer.name("configuration_file"); + writer.value(config.getConfigFileStatus()); + writer.name("runtime_id"); + writer.value(config.getRuntimeId()); + writer.name("logging_settings"); + writeObjectMap(writer, LoggingSettingsDescription.getDescription()); + writer.name("cws_enabled"); + writer.value(config.isCwsEnabled()); + writer.name("cws_tls_refresh"); + writer.value(config.getCwsTlsRefresh()); + writer.name("datadog_profiler_enabled"); + writer.value(config.isDatadogProfilerEnabled()); + writer.name("datadog_profiler_safe"); + writer.value(isDatadogProfilerSafeInCurrentEnvironment()); + writer.name("datadog_profiler_enabled_overridden"); + writer.value(isDatadogProfilerEnablementOverridden()); + if (config.getIastActivation() != ProductActivation.FULLY_DISABLED) { + writer.name("iast_enabled"); + writer.value(config.getIastActivation().toString()); + } + writer.name("data_streams_enabled"); + writer.value(config.isDataStreamsEnabled()); + writer.endObject(); + } + + private static boolean agentServiceCheck(Config config) { + try (Socket s = new Socket()) { + s.connect(new InetSocketAddress(config.getAgentHost(), config.getAgentPort()), 500); + return true; + } catch (IOException ex) { + return false; + } + } + + private static void writeMap(JsonWriter writer, Map map) throws IOException { + writer.beginObject(); + for (Map.Entry entry : map.entrySet()) { + writer.name(entry.getKey()); + writer.value(entry.getValue()); + } + writer.endObject(); + } + + private static void writeObjectMap(JsonWriter writer, Map map) + throws IOException { + writer.beginObject(); + for (Map.Entry entry : map.entrySet()) { + writer.name(entry.getKey()); + Object value = entry.getValue(); + if (value instanceof Number) { + writer.value((Number) value); + } else if (value instanceof Boolean) { + writer.value((Boolean) value); + } else { + writer.value(String.valueOf(value)); + } + } + writer.endObject(); + } + + private static void writeSet(JsonWriter writer, Set set) throws IOException { + for (Object o : set) { + writer.value(o.toString()); + } + } + + @Override + public JsonAdapter create(Type type, Set annotations, Moshi moshi) { + return this; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextExtractor.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextExtractor.java new file mode 100644 index 0000000000..e51ec15803 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextExtractor.java @@ -0,0 +1,60 @@ +package datadog.trace.core.datastreams; + +import datadog.trace.api.TraceConfig; +import datadog.trace.api.WellKnownTags; +import datadog.trace.api.time.TimeSource; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.TagContext; +import datadog.trace.core.propagation.HttpCodec; +import java.util.function.Supplier; + +public class DataStreamContextExtractor implements HttpCodec.Extractor { + private final HttpCodec.Extractor delegate; + private final TimeSource timeSource; + private final Supplier traceConfigSupplier; + private final WellKnownTags wellKnownTags; + + public DataStreamContextExtractor( + HttpCodec.Extractor delegate, + TimeSource timeSource, + Supplier traceConfigSupplier, + WellKnownTags wellKnownTags) { + this.delegate = delegate; + this.timeSource = timeSource; + this.traceConfigSupplier = traceConfigSupplier; + this.wellKnownTags = wellKnownTags; + } + + @Override + public TagContext extract(C carrier, AgentPropagation.ContextVisitor getter) { + // Delegate the default HTTP extraction + TagContext extracted = this.delegate.extract(carrier, getter); + + if (extracted != null) { + boolean shouldExtractPathwayContext = + extracted.getTraceConfig() == null + ? traceConfigSupplier.get().isDataStreamsEnabled() + : extracted.getTraceConfig().isDataStreamsEnabled(); + + if (shouldExtractPathwayContext) { + DefaultPathwayContext pathwayContext = + DefaultPathwayContext.extract(carrier, getter, this.timeSource, this.wellKnownTags); + + extracted.withPathwayContext(pathwayContext); + } + + return extracted; + } else if (traceConfigSupplier.get().isDataStreamsEnabled()) { + DefaultPathwayContext pathwayContext = + DefaultPathwayContext.extract(carrier, getter, this.timeSource, this.wellKnownTags); + + if (pathwayContext != null) { + extracted = new TagContext(); + extracted.withPathwayContext(pathwayContext); + return extracted; + } + } + + return null; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextInjector.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextInjector.java new file mode 100644 index 0000000000..d354a72c45 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextInjector.java @@ -0,0 +1,109 @@ +package datadog.trace.core.datastreams; + +import static datadog.trace.api.DDTags.PATHWAY_HASH; +import static datadog.trace.bootstrap.instrumentation.api.PathwayContext.PROPAGATION_KEY_BASE64; + +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import java.io.IOException; +import java.util.LinkedHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DataStreamContextInjector { + private static final Logger LOGGER = LoggerFactory.getLogger(DataStreamContextInjector.class); + private final DataStreamsMonitoring dataStreamsMonitoring; + + public DataStreamContextInjector(DataStreamsMonitoring dataStreamsMonitoring) { + this.dataStreamsMonitoring = dataStreamsMonitoring; + } + + public void injectPathwayContext( + AgentSpan span, + C carrier, + AgentPropagation.Setter setter, + LinkedHashMap sortedTags) { + injectPathwayContext(span, carrier, setter, sortedTags, 0, 0, true); + } + + public void injectPathwayContext( + AgentSpan span, + C carrier, + AgentPropagation.Setter setter, + LinkedHashMap sortedTags, + long defaultTimestamp, + long payloadSizeBytes) { + injectPathwayContext( + span, carrier, setter, sortedTags, defaultTimestamp, payloadSizeBytes, true); + } + + /** Same as injectPathwayContext, but the stats collected in the StatsPoint are not sent. */ + public void injectPathwayContextWithoutSendingStats( + AgentSpan span, + C carrier, + AgentPropagation.Setter setter, + LinkedHashMap sortedTags) { + injectPathwayContext(span, carrier, setter, sortedTags, 0, 0, false); + } + + private void injectPathwayContext( + AgentSpan span, + C carrier, + AgentPropagation.Setter setter, + LinkedHashMap sortedTags, + long defaultTimestamp, + long payloadSizeBytes, + boolean sendCheckpoint) { + PathwayContext pathwayContext = span.context().getPathwayContext(); + if (pathwayContext == null + || (span.traceConfig() != null && !span.traceConfig().isDataStreamsEnabled())) { + return; + } + pathwayContext.setCheckpoint( + sortedTags, + sendCheckpoint ? dataStreamsMonitoring::add : pathwayContext::saveStats, + defaultTimestamp, + payloadSizeBytes); + + boolean injected = + setter instanceof AgentPropagation.BinarySetter + ? injectBinaryPathwayContext( + pathwayContext, carrier, (AgentPropagation.BinarySetter) setter) + : injectPathwayContext(pathwayContext, carrier, setter); + + if (injected && pathwayContext.getHash() != 0) { + span.setTag(PATHWAY_HASH, Long.toUnsignedString(pathwayContext.getHash())); + } + } + + private static boolean injectBinaryPathwayContext( + PathwayContext pathwayContext, C carrier, AgentPropagation.BinarySetter setter) { + try { + byte[] encodedContext = pathwayContext.encode(); + if (encodedContext != null) { + LOGGER.debug("Injecting binary pathway context {}", pathwayContext); + setter.set(carrier, PROPAGATION_KEY_BASE64, encodedContext); + return true; + } + } catch (IOException e) { + LOGGER.debug("Unable to set encode pathway context", e); + } + return false; + } + + private static boolean injectPathwayContext( + PathwayContext pathwayContext, C carrier, AgentPropagation.Setter setter) { + try { + String encodedContext = pathwayContext.strEncode(); + if (encodedContext != null) { + LOGGER.debug("Injecting pathway context {}", pathwayContext); + setter.set(carrier, PROPAGATION_KEY_BASE64, encodedContext); + return true; + } + } catch (IOException e) { + LOGGER.debug("Unable to set encode pathway context", e); + } + return false; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java new file mode 100644 index 0000000000..a9460bae22 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java @@ -0,0 +1,31 @@ +package datadog.trace.core.datastreams; + +import datadog.trace.api.experimental.DataStreamsContextCarrier; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation.KeyClassifier; +import java.util.Map; + +public class DataStreamsContextCarrierAdapter + implements AgentPropagation.Setter, + AgentPropagation.ContextVisitor { + + public static final DataStreamsContextCarrierAdapter INSTANCE = + new DataStreamsContextCarrierAdapter(); + + private DataStreamsContextCarrierAdapter() {} + + @Override + public void set(DataStreamsContextCarrier carrier, String key, String value) { + carrier.set(key, value); + } + + @Override + public void forEachKey(DataStreamsContextCarrier carrier, KeyClassifier classifier) { + for (Map.Entry entry : carrier.entries()) { + if (null != entry.getValue() + && !classifier.accept(entry.getKey(), entry.getValue().toString())) { + return; + } + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java new file mode 100644 index 0000000000..d6df69cc8e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java @@ -0,0 +1,40 @@ +package datadog.trace.core.datastreams; + +import datadog.trace.api.experimental.DataStreamsContextCarrier; +import datadog.trace.bootstrap.instrumentation.api.AgentDataStreamsMonitoring; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan.Context; +import datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import datadog.trace.core.propagation.HttpCodec; + +public interface DataStreamsMonitoring extends AgentDataStreamsMonitoring, AutoCloseable { + void start(); + + /** + * Get a context extractor that support {@link PathwayContext} extraction. + * + * @param delegate The extractor to delegate the common trace context extraction. + * @return An extractor with DSM context extraction. + */ + HttpCodec.Extractor extractor(HttpCodec.Extractor delegate); + + /** + * Gets a context injector to propagate {@link PathwayContext}. + * + * @return A context injector if supported, {@code null} otherwise. + */ + DataStreamContextInjector injector(); + + /** + * Injects DSM {@link PathwayContext} into a span {@link Context}. + * + * @param span The span to update. + * @param carrier The carrier of the {@link PathwayContext} to extract and inject. + */ + void mergePathwayContextIntoSpan(AgentSpan span, DataStreamsContextCarrier carrier); + + void clear(); + + @Override + void close(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java new file mode 100644 index 0000000000..07d040dd9a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java @@ -0,0 +1,7 @@ +package datadog.trace.core.datastreams; + +import java.util.Collection; + +public interface DatastreamsPayloadWriter { + void writePayload(Collection data); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java new file mode 100644 index 0000000000..340af2c559 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java @@ -0,0 +1,435 @@ +package datadog.trace.core.datastreams; + +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import com.datadoghq.sketch.ddsketch.encoding.ByteArrayInput; +import com.datadoghq.sketch.ddsketch.encoding.GrowingByteArrayOutput; +import com.datadoghq.sketch.ddsketch.encoding.VarEncodingHelper; +import datadog.trace.api.Config; +import datadog.trace.api.WellKnownTags; +import datadog.trace.api.time.TimeSource; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import datadog.trace.bootstrap.instrumentation.api.StatsPoint; +import datadog.trace.util.FNV64Hash; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DefaultPathwayContext implements PathwayContext { + private static final Logger log = LoggerFactory.getLogger(DefaultPathwayContext.class); + private final Lock lock = new ReentrantLock(); + private final WellKnownTags wellKnownTags; + private final TimeSource timeSource; + private final GrowingByteArrayOutput outputBuffer = + GrowingByteArrayOutput.withInitialCapacity(20); + + // pathwayStartNanos is nanoseconds since epoch + // Nano ticks is necessary because time differences should use a monotonically increasing clock + // ticks is not comparable across JVMs + private long pathwayStartNanos; + private long pathwayStartNanoTicks; + private long edgeStartNanoTicks; + private StatsPoint savedStats; + private long hash; + private boolean started; + // state variables used to memoize the pathway hash with + // direction != current direction + private long closestOppositeDirectionHash; + private String previousDirection; + + private static final Set hashableTagKeys = + new HashSet( + Arrays.asList( + TagsProcessor.GROUP_TAG, + TagsProcessor.TYPE_TAG, + TagsProcessor.DIRECTION_TAG, + TagsProcessor.TOPIC_TAG, + TagsProcessor.EXCHANGE_TAG)); + + public DefaultPathwayContext(TimeSource timeSource, WellKnownTags wellKnownTags) { + this.timeSource = timeSource; + this.wellKnownTags = wellKnownTags; + } + + private DefaultPathwayContext( + TimeSource timeSource, + WellKnownTags wellKnownTags, + long pathwayStartNanos, + long pathwayStartNanoTicks, + long edgeStartNanoTicks, + long hash) { + this.timeSource = timeSource; + this.wellKnownTags = wellKnownTags; + this.pathwayStartNanos = pathwayStartNanos; + this.pathwayStartNanoTicks = pathwayStartNanoTicks; + this.edgeStartNanoTicks = edgeStartNanoTicks; + this.hash = hash; + this.closestOppositeDirectionHash = hash; + this.started = true; + } + + @Override + public boolean isStarted() { + return started; + } + + @Override + public long getHash() { + return hash; + } + + @Override + public void setCheckpoint( + LinkedHashMap sortedTags, Consumer pointConsumer) { + setCheckpoint(sortedTags, pointConsumer, 0, 0); + } + + @Override + public void setCheckpoint( + LinkedHashMap sortedTags, + Consumer pointConsumer, + long defaultTimestamp) { + setCheckpoint(sortedTags, pointConsumer, defaultTimestamp, 0); + } + + @Override + public void setCheckpoint( + LinkedHashMap sortedTags, + Consumer pointConsumer, + long defaultTimestamp, + long payloadSizeBytes) { + long startNanos = timeSource.getCurrentTimeNanos(); + long nanoTicks = timeSource.getNanoTicks(); + lock.lock(); + try { + // So far, each tag key has only one tag value, so we're initializing the capacity to match + // the number of tag keys for now. We should revisit this later if it's no longer the case. + List allTags = new ArrayList<>(sortedTags.size()); + PathwayHashBuilder pathwayHashBuilder = new PathwayHashBuilder(wellKnownTags); + + if (!started) { + if (defaultTimestamp == 0) { + pathwayStartNanos = startNanos; + pathwayStartNanoTicks = nanoTicks; + edgeStartNanoTicks = nanoTicks; + } else { + pathwayStartNanos = MILLISECONDS.toNanos(defaultTimestamp); + pathwayStartNanoTicks = + nanoTicks + - MILLISECONDS.toNanos(timeSource.getCurrentTimeMillis() - defaultTimestamp); + edgeStartNanoTicks = pathwayStartNanoTicks; + } + + hash = 0; + started = true; + log.debug("Started {}", this); + } + + for (Map.Entry entry : sortedTags.entrySet()) { + String tag = TagsProcessor.createTag(entry.getKey(), entry.getValue()); + if (tag == null) { + continue; + } + if (hashableTagKeys.contains(entry.getKey())) { + pathwayHashBuilder.addTag(tag); + } + allTags.add(tag); + } + + long nodeHash = generateNodeHash(pathwayHashBuilder); + // loop protection - a node should not be chosen as parent + // for a sequential node with the same direction, as this + // will cause a `cardinality explosion` for hash / parentHash tag values + if (sortedTags.containsKey(TagsProcessor.DIRECTION_TAG)) { + String direction = sortedTags.get(TagsProcessor.DIRECTION_TAG); + if (direction.equals(previousDirection)) { + hash = closestOppositeDirectionHash; + } else { + previousDirection = direction; + closestOppositeDirectionHash = hash; + } + } + + long newHash = generatePathwayHash(nodeHash, hash); + + long pathwayLatencyNano = nanoTicks - pathwayStartNanoTicks; + long edgeLatencyNano = nanoTicks - edgeStartNanoTicks; + + StatsPoint point = + new StatsPoint( + allTags, + newHash, + hash, + startNanos, + pathwayLatencyNano, + edgeLatencyNano, + payloadSizeBytes); + edgeStartNanoTicks = nanoTicks; + hash = newHash; + + pointConsumer.accept(point); + log.debug("Checkpoint set {}, hash source: {}", this, pathwayHashBuilder); + } finally { + lock.unlock(); + } + } + + @Override + public void saveStats(StatsPoint point) { + this.savedStats = point; + } + + @Override + public StatsPoint getSavedStats() { + return this.savedStats; + } + + @Override + public byte[] encode() throws IOException { + lock.lock(); + try { + if (!started) { + throw new IllegalStateException("Context must be started to encode"); + } + + outputBuffer.clear(); + outputBuffer.writeLongLE(hash); + + long pathwayStartMillis = TimeUnit.NANOSECONDS.toMillis(pathwayStartNanos); + VarEncodingHelper.encodeSignedVarLong(outputBuffer, pathwayStartMillis); + + long edgeStartMillis = + pathwayStartMillis + + TimeUnit.NANOSECONDS.toMillis(edgeStartNanoTicks - pathwayStartNanoTicks); + + VarEncodingHelper.encodeSignedVarLong(outputBuffer, edgeStartMillis); + return Base64.getEncoder().encode(outputBuffer.trimmedCopy()); + } finally { + lock.unlock(); + } + } + + @Override + public String strEncode() throws IOException { + byte[] bytes = encode(); + if (bytes == null) { + return null; + } + return new String(bytes, ISO_8859_1); + } + + @Override + public String toString() { + lock.lock(); + try { + if (started) { + return "PathwayContext[ Hash " + + Long.toUnsignedString(hash) + + ", Start: " + + pathwayStartNanos + + ", StartTicks: " + + pathwayStartNanoTicks + + ", Edge Start Ticks: " + + edgeStartNanoTicks + + ", objectHashcode:" + + hashCode() + + "]"; + } else { + return "PathwayContext [Not Started]"; + } + } finally { + lock.unlock(); + } + } + + private static class PathwayContextExtractor implements AgentPropagation.KeyClassifier { + private final TimeSource timeSource; + private final WellKnownTags wellKnownTags; + private DefaultPathwayContext extractedContext; + + PathwayContextExtractor(TimeSource timeSource, WellKnownTags wellKnownTags) { + this.timeSource = timeSource; + this.wellKnownTags = wellKnownTags; + } + + @Override + public boolean accept(String key, String value) { + if (PathwayContext.PROPAGATION_KEY_BASE64.equalsIgnoreCase(key)) { + try { + extractedContext = strDecode(timeSource, wellKnownTags, value); + } catch (IOException e) { + return false; + } + } + return true; + } + } + + private static class BinaryPathwayContextExtractor + implements AgentPropagation.BinaryKeyClassifier { + private final TimeSource timeSource; + private final WellKnownTags wellKnownTags; + private DefaultPathwayContext extractedContext; + + BinaryPathwayContextExtractor(TimeSource timeSource, WellKnownTags wellKnownTags) { + this.timeSource = timeSource; + this.wellKnownTags = wellKnownTags; + } + + @Override + public boolean accept(String key, byte[] value) { + // older versions support, should be removed in the future + if (PathwayContext.PROPAGATION_KEY.equalsIgnoreCase(key)) { + try { + extractedContext = decode(timeSource, wellKnownTags, value); + } catch (IOException e) { + return false; + } + } + + if (PathwayContext.PROPAGATION_KEY_BASE64.equalsIgnoreCase(key)) { + try { + extractedContext = base64Decode(timeSource, wellKnownTags, value); + } catch (IOException e) { + return false; + } + } + return true; + } + } + + static DefaultPathwayContext extract( + C carrier, + AgentPropagation.ContextVisitor getter, + TimeSource timeSource, + WellKnownTags wellKnownTags) { + if (getter instanceof AgentPropagation.BinaryContextVisitor) { + return extractBinary( + carrier, (AgentPropagation.BinaryContextVisitor) getter, timeSource, wellKnownTags); + } + PathwayContextExtractor pathwayContextExtractor = + new PathwayContextExtractor(timeSource, wellKnownTags); + getter.forEachKey(carrier, pathwayContextExtractor); + if (pathwayContextExtractor.extractedContext == null) { + log.debug("No context extracted"); + } else { + log.debug("Extracted context: {} ", pathwayContextExtractor.extractedContext); + } + return pathwayContextExtractor.extractedContext; + } + + static DefaultPathwayContext extractBinary( + C carrier, + AgentPropagation.BinaryContextVisitor getter, + TimeSource timeSource, + WellKnownTags wellKnownTags) { + BinaryPathwayContextExtractor pathwayContextExtractor = + new BinaryPathwayContextExtractor(timeSource, wellKnownTags); + getter.forEachKey(carrier, pathwayContextExtractor); + if (pathwayContextExtractor.extractedContext == null) { + log.debug("No context extracted"); + } else { + log.debug("Extracted context: {} ", pathwayContextExtractor.extractedContext); + } + return pathwayContextExtractor.extractedContext; + } + + private static DefaultPathwayContext strDecode( + TimeSource timeSource, WellKnownTags wellKnownTags, String data) throws IOException { + byte[] base64Bytes = data.getBytes(UTF_8); + return base64Decode(timeSource, wellKnownTags, base64Bytes); + } + + private static DefaultPathwayContext base64Decode( + TimeSource timeSource, WellKnownTags wellKnownTags, byte[] data) throws IOException { + return decode(timeSource, wellKnownTags, Base64.getDecoder().decode(data)); + } + + private static DefaultPathwayContext decode( + TimeSource timeSource, WellKnownTags wellKnownTags, byte[] data) throws IOException { + ByteArrayInput input = ByteArrayInput.wrap(data); + + long hash = input.readLongLE(); + + long pathwayStartMillis = VarEncodingHelper.decodeSignedVarLong(input); + long pathwayStartNanos = TimeUnit.MILLISECONDS.toNanos(pathwayStartMillis); + + // Convert the start time to the current JVM's nanoclock + long nowNanos = timeSource.getCurrentTimeNanos(); + long nanosSinceStart = nowNanos - pathwayStartNanos; + long nowNanoTicks = timeSource.getNanoTicks(); + long pathwayStartNanoTicks = nowNanoTicks - nanosSinceStart; + + long edgeStartMillis = VarEncodingHelper.decodeSignedVarLong(input); + long edgeStartNanoTicks = + pathwayStartNanoTicks + TimeUnit.MILLISECONDS.toNanos(edgeStartMillis - pathwayStartMillis); + + return new DefaultPathwayContext( + timeSource, + wellKnownTags, + pathwayStartNanos, + pathwayStartNanoTicks, + edgeStartNanoTicks, + hash); + } + + private static class PathwayHashBuilder { + private final StringBuilder builder; + + public PathwayHashBuilder(WellKnownTags wellKnownTags) { + builder = new StringBuilder(); + builder.append(wellKnownTags.getService()); + builder.append(wellKnownTags.getEnv()); + + String primaryTag = Config.get().getPrimaryTag(); + if (primaryTag != null) { + builder.append(primaryTag); + } + } + + public void addTag(String tag) { + builder.append(tag); + } + + public long generateHash() { + return FNV64Hash.generateHash(builder.toString(), FNV64Hash.Version.v1); + } + + @Override + public String toString() { + return builder.toString(); + } + } + + private long generateNodeHash(PathwayHashBuilder pathwayHashBuilder) { + return pathwayHashBuilder.generateHash(); + } + + private long generatePathwayHash(long nodeHash, long parentHash) { + lock.lock(); + try { + outputBuffer.clear(); + outputBuffer.writeLongLE(nodeHash); + outputBuffer.writeLongLE(parentHash); + + return FNV64Hash.generateHash(outputBuffer.backingArray(), 0, 16, FNV64Hash.Version.v1); + } finally { + lock.unlock(); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/MsgPackDatastreamsPayloadWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/MsgPackDatastreamsPayloadWriter.java new file mode 100644 index 0000000000..f2af129367 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/MsgPackDatastreamsPayloadWriter.java @@ -0,0 +1,169 @@ +package datadog.trace.core.datastreams; + +import static java.nio.charset.StandardCharsets.ISO_8859_1; + +import datadog.trace.serialization.GrowableBuffer; +import datadog.trace.serialization.Writable; +import datadog.trace.serialization.WritableFormatter; +import datadog.trace.serialization.msgpack.MsgPackWriter; +import datadog.trace.api.WellKnownTags; +import datadog.trace.common.metrics.Sink; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class MsgPackDatastreamsPayloadWriter implements DatastreamsPayloadWriter { + private static final byte[] ENV = "Env".getBytes(ISO_8859_1); + private static final byte[] VERSION = "Version".getBytes(ISO_8859_1); + private static final byte[] PRIMARY_TAG = "PrimaryTag".getBytes(ISO_8859_1); + private static final byte[] LANG = "Lang".getBytes(ISO_8859_1); + private static final byte[] TRACER_VERSION = "TracerVersion".getBytes(ISO_8859_1); + private static final byte[] STATS = "Stats".getBytes(ISO_8859_1); + private static final byte[] START = "Start".getBytes(ISO_8859_1); + private static final byte[] DURATION = "Duration".getBytes(ISO_8859_1); + private static final byte[] PATHWAY_LATENCY = "PathwayLatency".getBytes(ISO_8859_1); + private static final byte[] EDGE_LATENCY = "EdgeLatency".getBytes(ISO_8859_1); + private static final byte[] PAYLOAD_SIZE = "PayloadSize".getBytes(ISO_8859_1); + private static final byte[] SERVICE = "Service".getBytes(ISO_8859_1); + private static final byte[] EDGE_TAGS = "EdgeTags".getBytes(ISO_8859_1); + private static final byte[] BACKLOGS = "Backlogs".getBytes(ISO_8859_1); + private static final byte[] HASH = "Hash".getBytes(ISO_8859_1); + private static final byte[] PARENT_HASH = "ParentHash".getBytes(ISO_8859_1); + private static final byte[] BACKLOG_VALUE = "Value".getBytes(ISO_8859_1); + private static final byte[] BACKLOG_TAGS = "Tags".getBytes(ISO_8859_1); + + private static final int INITIAL_CAPACITY = 512 * 1024; + + private final WritableFormatter writer; + private final Sink sink; + private final GrowableBuffer buffer; + private final WellKnownTags wellKnownTags; + private final byte[] tracerVersionValue; + private final byte[] primaryTagValue; + + public MsgPackDatastreamsPayloadWriter( + Sink sink, WellKnownTags wellKnownTags, String tracerVersion, String primaryTag) { + buffer = new GrowableBuffer(INITIAL_CAPACITY); + writer = new MsgPackWriter(buffer); + this.sink = sink; + this.wellKnownTags = wellKnownTags; + tracerVersionValue = tracerVersion.getBytes(ISO_8859_1); + primaryTagValue = primaryTag == null ? new byte[0] : primaryTag.getBytes(ISO_8859_1); + } + + public void reset() { + buffer.reset(); + } + + @Override + public void writePayload(Collection data) { + writer.startMap(7); + /* 1 */ + writer.writeUTF8(ENV); + writer.writeUTF8(wellKnownTags.getEnv()); + + /* 2 */ + writer.writeUTF8(SERVICE); + writer.writeUTF8(wellKnownTags.getService()); + + /* 3 */ + writer.writeUTF8(LANG); + writer.writeUTF8(wellKnownTags.getLanguage()); + + /* 4 */ + writer.writeUTF8(PRIMARY_TAG); + writer.writeUTF8(primaryTagValue); + + /* 5 */ + writer.writeUTF8(TRACER_VERSION); + writer.writeUTF8(tracerVersionValue); + + /* 6 */ + writer.writeUTF8(VERSION); + writer.writeUTF8(wellKnownTags.getVersion()); + + /* 7 */ + writer.writeUTF8(STATS); + writer.startArray(data.size()); + + for (StatsBucket bucket : data) { + boolean hasBacklogs = !bucket.getBacklogs().isEmpty(); + writer.startMap(3 + (hasBacklogs ? 1 : 0)); + + /* 1 */ + writer.writeUTF8(START); + writer.writeLong(bucket.getStartTimeNanos()); + + /* 2 */ + writer.writeUTF8(DURATION); + writer.writeLong(bucket.getBucketDurationNanos()); + + /* 3 */ + writer.writeUTF8(STATS); + writeBucket(bucket, writer); + + if (hasBacklogs) { + /* 4 */ + writeBacklogs(bucket.getBacklogs(), writer); + } + } + + buffer.mark(); + sink.accept(buffer.messageCount(), buffer.slice()); + buffer.reset(); + } + + private void writeBucket(StatsBucket bucket, Writable packer) { + Collection groups = bucket.getGroups(); + packer.startArray(groups.size()); + for (StatsGroup group : groups) { + boolean firstNode = group.getEdgeTags().isEmpty(); + + packer.startMap(firstNode ? 5 : 6); + + /* 1 */ + packer.writeUTF8(PATHWAY_LATENCY); + packer.writeBinary(group.getPathwayLatency().serialize()); + + /* 2 */ + packer.writeUTF8(EDGE_LATENCY); + packer.writeBinary(group.getEdgeLatency().serialize()); + + /* 3 */ + packer.writeUTF8(PAYLOAD_SIZE); + packer.writeBinary(group.getPayloadSize().serialize()); + + /* 4 */ + packer.writeUTF8(HASH); + packer.writeUnsignedLong(group.getHash()); + + /* 5 */ + packer.writeUTF8(PARENT_HASH); + packer.writeUnsignedLong(group.getParentHash()); + + if (!firstNode) { + /* 6 */ + packer.writeUTF8(EDGE_TAGS); + packer.startArray(group.getEdgeTags().size()); + for (String tag : group.getEdgeTags()) { + packer.writeString(tag, null); + } + } + } + } + + private void writeBacklogs(Collection, Long>> backlogs, Writable packer) { + packer.writeUTF8(BACKLOGS); + packer.startArray(backlogs.size()); + for (Map.Entry, Long> entry : backlogs) { + packer.startMap(2); + packer.writeUTF8(BACKLOG_TAGS); + packer.startArray(entry.getKey().size()); + for (String tag : entry.getKey()) { + packer.writeString(tag, null); + } + packer.writeUTF8(BACKLOG_VALUE); + packer.writeLong(entry.getValue()); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java new file mode 100644 index 0000000000..957f48894c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java @@ -0,0 +1,77 @@ +package datadog.trace.core.datastreams; + +import datadog.trace.api.experimental.DataStreamsContextCarrier; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import datadog.trace.bootstrap.instrumentation.api.StatsPoint; +import datadog.trace.core.propagation.HttpCodec; + +import java.util.LinkedHashMap; + +public class NoOpDataStreamMonitoring implements DataStreamsMonitoring { + @Override + public void setConsumeCheckpoint(String type, String source, DataStreamsContextCarrier carrier) { + + } + + @Override + public void setProduceCheckpoint(String type, String target, DataStreamsContextCarrier carrier) { + + } + + @Override + public void start() { + + } + + @Override + public HttpCodec.Extractor extractor(HttpCodec.Extractor delegate) { + return null; + } + + @Override + public DataStreamContextInjector injector() { + return null; + } + + @Override + public void mergePathwayContextIntoSpan(AgentSpan span, DataStreamsContextCarrier carrier) { + + } + + @Override + public void clear() { + + } + + @Override + public void close() { + + } + + @Override + public void trackBacklog(LinkedHashMap sortedTags, long value) { + + } + + @Override + public void setCheckpoint(AgentSpan span, LinkedHashMap sortedTags, long defaultTimestamp, long payloadSizeBytes) { + + } + + @Override + public PathwayContext newPathwayContext() { + return AgentTracer.NoopPathwayContext.INSTANCE; + } + + @Override + public void add(StatsPoint statsPoint) { + + } + + @Override + public int shouldSampleSchema(String topic) { + return 0; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/SchemaSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/SchemaSampler.java new file mode 100644 index 0000000000..07af84b758 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/SchemaSampler.java @@ -0,0 +1,29 @@ +package datadog.trace.core.datastreams; + +import java.util.concurrent.atomic.AtomicInteger; + +public class SchemaSampler { + private static final int SAMPLE_INTERVAL_MILLIS = 30 * 1000; + private final AtomicInteger weight; + private volatile long lastSampleMillis; + + public SchemaSampler() { + this.weight = new AtomicInteger(0); + this.lastSampleMillis = 0; + } + + public int shouldSample(long currentTimeMillis) { + weight.incrementAndGet(); + if (currentTimeMillis >= lastSampleMillis + SAMPLE_INTERVAL_MILLIS) { + synchronized (this) { + if (currentTimeMillis >= lastSampleMillis + SAMPLE_INTERVAL_MILLIS) { + lastSampleMillis = currentTimeMillis; + int currentWeight = weight.get(); + weight.set(0); + return currentWeight; + } + } + } + return 0; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsBucket.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsBucket.java new file mode 100644 index 0000000000..de58e3cccf --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsBucket.java @@ -0,0 +1,59 @@ +package datadog.trace.core.datastreams; + +import datadog.trace.bootstrap.instrumentation.api.Backlog; +import datadog.trace.bootstrap.instrumentation.api.StatsPoint; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class StatsBucket { + private final long startTimeNanos; + private final long bucketDurationNanos; + private final Map hashToGroup = new HashMap<>(); + private final Map, Long> backlogs = new HashMap<>(); + + public StatsBucket(long startTimeNanos, long bucketDurationNanos) { + this.startTimeNanos = startTimeNanos; + this.bucketDurationNanos = bucketDurationNanos; + } + + public void addPoint(StatsPoint statsPoint) { + StatsGroup statsGroup = hashToGroup.get(statsPoint.getHash()); + + // FIXME Java 7 + if (statsGroup == null) { + statsGroup = + new StatsGroup( + statsPoint.getEdgeTags(), statsPoint.getHash(), statsPoint.getParentHash()); + hashToGroup.put(statsPoint.getHash(), statsGroup); + } + + statsGroup.add( + statsPoint.getPathwayLatencyNano(), + statsPoint.getEdgeLatencyNano(), + statsPoint.getPayloadSizeBytes()); + } + + public void addBacklog(Backlog backlog) { + backlogs.compute( + backlog.getSortedTags(), + (k, v) -> (v == null) ? backlog.getValue() : Math.max(v, backlog.getValue())); + } + + public long getStartTimeNanos() { + return startTimeNanos; + } + + public long getBucketDurationNanos() { + return bucketDurationNanos; + } + + public Collection getGroups() { + return hashToGroup.values(); + } + + public Collection, Long>> getBacklogs() { + return backlogs.entrySet(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsGroup.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsGroup.java new file mode 100644 index 0000000000..bbdb7dcc4e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsGroup.java @@ -0,0 +1,70 @@ +package datadog.trace.core.datastreams; + +import datadog.trace.core.histogram.Histogram; +import datadog.trace.core.histogram.Histograms; +import java.util.List; + +public class StatsGroup { + private static final double NANOSECONDS_TO_SECOND = 1_000_000_000d; + + private final List edgeTags; + private final long hash; + private final long parentHash; + private final Histogram pathwayLatency; + private final Histogram edgeLatency; + private final Histogram payloadSize; + + public StatsGroup(List edgeTags, long hash, long parentHash) { + this.edgeTags = edgeTags; + this.hash = hash; + this.parentHash = parentHash; + pathwayLatency = Histograms.newHistogram(); + edgeLatency = Histograms.newHistogram(); + payloadSize = Histograms.newHistogram(); + } + + public void add(long pathwayLatencyNano, long edgeLatencyNano, long payloadSizeBytes) { + pathwayLatency.accept(((double) pathwayLatencyNano) / NANOSECONDS_TO_SECOND); + edgeLatency.accept(((double) edgeLatencyNano) / NANOSECONDS_TO_SECOND); + // payload size is set to zero when we cannot compute it + // in that case, it's probably better to have an empty histogram than filling it with zeros + if (payloadSizeBytes != 0) payloadSize.accept((double) payloadSizeBytes); + } + + public List getEdgeTags() { + return edgeTags; + } + + public long getHash() { + return hash; + } + + public long getParentHash() { + return parentHash; + } + + public Histogram getPathwayLatency() { + return pathwayLatency; + } + + public Histogram getEdgeLatency() { + return edgeLatency; + } + + public Histogram getPayloadSize() { + return payloadSize; + } + + @Override + public String toString() { + return "StatsGroup{" + + "edgeTags='" + + edgeTags + + '\'' + + ", hash=" + + hash + + ", parentHash=" + + parentHash + + '}'; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/TagsProcessor.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/TagsProcessor.java new file mode 100644 index 0000000000..287be4daeb --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/TagsProcessor.java @@ -0,0 +1,118 @@ +package datadog.trace.core.datastreams; + +import datadog.trace.api.cache.DDCache; +import datadog.trace.api.cache.DDCaches; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +public class TagsProcessor { + public static final class StringPrefix implements Function { + private final String prefix; + + public StringPrefix(String prefix) { + this.prefix = prefix; + } + + @Override + public String apply(String key) { + return prefix + key; + } + } + + public static final String TYPE_TAG = "type"; + private static final DDCache TYPE_TAG_CACHE = DDCaches.newFixedSizeCache(32); + private static final Function TYPE_TAG_PREFIX = new StringPrefix("type:"); + + public static final String DIRECTION_TAG = "direction"; + // service centric direction - data flowing into the service + public static final String DIRECTION_IN = "in"; + // service centric direction - data flowing out of the service + public static final String DIRECTION_OUT = "out"; + private static final DDCache DIRECTION_TAG_CACHE = DDCaches.newFixedSizeCache(32); + private static final Function DIRECTION_TAG_PREFIX = + new StringPrefix("direction:"); + public static final String TOPIC_TAG = "topic"; + private static final DDCache TOPIC_TAG_CACHE = DDCaches.newFixedSizeCache(32); + private static final Function TOPIC_TAG_PREFIX = new StringPrefix("topic:"); + + public static final String PARTITION_TAG = "partition"; + private static final DDCache PARTITION_TAG_CACHE = DDCaches.newFixedSizeCache(32); + private static final Function PARTITION_TAG_PREFIX = + new StringPrefix("partition:"); + public static final String GROUP_TAG = "group"; + public static final String CONSUMER_GROUP_TAG = "consumer_group"; + private static final DDCache GROUP_TAG_CACHE = DDCaches.newFixedSizeCache(32); + private static final DDCache CONSUMER_GROUP_TAG_CACHE = + DDCaches.newFixedSizeCache(32); + private static final Function GROUP_TAG_PREFIX = new StringPrefix("group:"); + private static final Function CONSUMER_GROUP_TAG_PREFIX = + new StringPrefix("consumer_group:"); + public static final String SUBSCRIPTION_TAG = "subscription"; + private static final DDCache SUBSCRIPTION_TAG_CACHE = + DDCaches.newFixedSizeCache(32); + private static final Function SUBSCRIPTION_TAG_PREFIX = + new StringPrefix("subscription:"); + public static final String EXCHANGE_TAG = "exchange"; + private static final DDCache EXCHANGE_TAG_CACHE = DDCaches.newFixedSizeCache(32); + private static final Function EXCHANGE_TAG_PREFIX = new StringPrefix("exchange:"); + + public static final String HAS_ROUTING_KEY_TAG = "has_routing_key"; + private static final DDCache HAS_ROUTING_KEY_TAG_CACHE = + DDCaches.newFixedSizeCache(2); // true or false + private static final Function HAS_ROUTING_KEY_TAG_PREFIX = + new StringPrefix("has_routing_key:"); + + public static final String KAFKA_CLUSTER_ID_TAG = "kafka_cluster_id"; + private static final DDCache KAFKA_CLUSTER_ID_TAG_CACHE = + DDCaches.newFixedSizeCache(32); + private static final Function KAFKA_CLUSTER_ID_TAG_PREFIX = + new StringPrefix("kafka_cluster_id:"); + + private static final Map> TAG_TO_CACHE = createTagToCacheMap(); + private static final Map> TAG_TO_PREFIX = createTagToPrefixMap(); + + private static Map> createTagToCacheMap() { + Map> result = new HashMap<>(); + result.put(TYPE_TAG, TYPE_TAG_CACHE); + result.put(DIRECTION_TAG, DIRECTION_TAG_CACHE); + result.put(TOPIC_TAG, TOPIC_TAG_CACHE); + result.put(PARTITION_TAG, PARTITION_TAG_CACHE); + result.put(GROUP_TAG, GROUP_TAG_CACHE); + result.put(CONSUMER_GROUP_TAG, CONSUMER_GROUP_TAG_CACHE); + result.put(SUBSCRIPTION_TAG, SUBSCRIPTION_TAG_CACHE); + result.put(EXCHANGE_TAG, EXCHANGE_TAG_CACHE); + result.put(HAS_ROUTING_KEY_TAG, HAS_ROUTING_KEY_TAG_CACHE); + result.put(KAFKA_CLUSTER_ID_TAG, KAFKA_CLUSTER_ID_TAG_CACHE); + return result; + } + + private static Map> createTagToPrefixMap() { + Map> result = new HashMap<>(); + result.put(TYPE_TAG, TYPE_TAG_PREFIX); + result.put(DIRECTION_TAG, DIRECTION_TAG_PREFIX); + result.put(TOPIC_TAG, TOPIC_TAG_PREFIX); + result.put(PARTITION_TAG, PARTITION_TAG_PREFIX); + result.put(GROUP_TAG, GROUP_TAG_PREFIX); + result.put(CONSUMER_GROUP_TAG, CONSUMER_GROUP_TAG_PREFIX); + result.put(SUBSCRIPTION_TAG, SUBSCRIPTION_TAG_PREFIX); + result.put(EXCHANGE_TAG, EXCHANGE_TAG_PREFIX); + result.put(HAS_ROUTING_KEY_TAG, HAS_ROUTING_KEY_TAG_PREFIX); + result.put(KAFKA_CLUSTER_ID_TAG, KAFKA_CLUSTER_ID_TAG_PREFIX); + return result; + } + + // Creates the tag string using the provided tagKey and tagValue. + // Returns null if either tagKey or tagValue is null. + public static String createTag(String tagKey, String tagValue) { + if (tagKey == null || tagValue == null) { + return null; + } + DDCache cache = TAG_TO_CACHE.get(tagKey); + Function prefix = TAG_TO_PREFIX.get(tagKey); + if (cache != null && prefix != null) { + return cache.computeIfAbsent(tagValue, prefix); + } + return tagKey + ":" + tagValue; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histogram.java b/features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histogram.java new file mode 100644 index 0000000000..556177d424 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histogram.java @@ -0,0 +1,59 @@ +package datadog.trace.core.histogram; + +import com.datadoghq.sketch.ddsketch.DDSketch; +import datadog.trace.bootstrap.instrumentation.api.AgentHistogram; +import java.nio.ByteBuffer; + +/** Wrapper around the DDSketch library so that it can be used in an instrumentation */ +public class Histogram implements AgentHistogram { + private final DDSketch sketch; + + public Histogram(DDSketch sketch) { + this.sketch = sketch; + } + + @Override + public double getCount() { + return sketch.getCount(); + } + + @Override + public boolean isEmpty() { + return sketch.isEmpty(); + } + + @Override + public void accept(double value) { + sketch.accept(value); + } + + @Override + public void accept(double value, double count) { + sketch.accept(value, count); + } + + @Override + public double getValueAtQuantile(double quantile) { + return sketch.getValueAtQuantile(quantile); + } + + @Override + public double getMinValue() { + return sketch.getMinValue(); + } + + @Override + public double getMaxValue() { + return sketch.getMaxValue(); + } + + @Override + public void clear() { + sketch.clear(); + } + + @Override + public ByteBuffer serialize() { + return sketch.serialize(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histograms.java b/features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histograms.java new file mode 100644 index 0000000000..4dca763458 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histograms.java @@ -0,0 +1,22 @@ +package datadog.trace.core.histogram; + +import com.datadoghq.sketch.ddsketch.DDSketch; +import com.datadoghq.sketch.ddsketch.DDSketches; +import com.datadoghq.sketch.ddsketch.mapping.BitwiseLinearlyInterpolatedMapping; +import com.datadoghq.sketch.ddsketch.store.CollapsingLowestDenseStore; + +public final class Histograms { + + private static final BitwiseLinearlyInterpolatedMapping INDEX_MAPPING = + new BitwiseLinearlyInterpolatedMapping(1.0 / 128.0); + + public static Histogram newHistogram() { + DDSketch sketch = new DDSketch(INDEX_MAPPING, () -> new CollapsingLowestDenseStore(1024)); + return new Histogram(sketch); + } + + public static Histogram newHistogram(double relativeAccuracy, int maxNumBins) { + DDSketch sketch = DDSketches.logarithmicCollapsingLowestDense(relativeAccuracy, maxNumBins); + return new Histogram(sketch); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java new file mode 100644 index 0000000000..f0dd6cc885 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java @@ -0,0 +1,83 @@ +package datadog.trace.core.monitor; + +import datadog.trace.common.writer.RemoteApi; +import datadog.trace.core.DDSpan; +import java.util.List; + +/** + * Callback for monitoring the health of the DDAgentWriter. Provides hooks for major lifecycle + * events... + * + *

      + *
    • start + *
    • shutdown + *
    • publishing to disruptor + *
    • serializing + *
    • sending to agent + *
    + */ +public abstract class HealthMetrics implements AutoCloseable { + public static HealthMetrics NO_OP = new HealthMetrics() {}; + + public void start() {} + + public void onStart(final int queueCapacity) {} + + public void onShutdown(final boolean flushSuccess) {} + + public void onPublish(final List trace, final int samplingPriority) {} + + public void onFailedPublish(final int samplingPriority, final int spanCount) {} + + public void onPartialPublish(final int numberOfDroppedSpans) {} + + public void onScheduleFlush(final boolean previousIncomplete) {} + + public void onFlush(final boolean early) {} + + public void onPartialFlush(final int sizeInBytes) {} + + public void onSingleSpanSample() {} + + public void onSingleSpanUnsampled() {} + + public void onSerialize(final int serializedSizeInBytes) {} + + public void onFailedSerialize(final List trace, final Throwable optionalCause) {} + + public void onCreateSpan() {} + + public void onFinishSpan() {} + + public void onCreateTrace() {} + + public void onScopeCloseError(int scopeSource) {} + + public void onCaptureContinuation() {} + + public void onCancelContinuation() {} + + public void onFinishContinuation() {} + + public void onActivateScope() {} + + public void onCloseScope() {} + + public void onScopeStackOverflow() {} + + public void onSend( + final int traceCount, final int sizeInBytes, final RemoteApi.Response response) {} + + public void onFailedSend( + final int traceCount, final int sizeInBytes, final RemoteApi.Response response) {} + + public void onLongRunningUpdate(final int dropped, final int write, final int expired) {} + + /** @return Human-readable summary of the current health metrics. */ + public String summary() { + return ""; + } + + @Override + public void close() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/MonitoringImpl.java b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/MonitoringImpl.java new file mode 100644 index 0000000000..275067a96c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/MonitoringImpl.java @@ -0,0 +1,66 @@ +package datadog.trace.core.monitor; + +import datadog.trace.monitor.Counter; +import datadog.trace.monitor.Monitoring; +import datadog.trace.monitor.NoOpCounter; +import datadog.trace.monitor.NoOpRecording; +import datadog.trace.monitor.Recording; +import datadog.trace.api.StatsDClient; +import java.util.concurrent.TimeUnit; + +public final class MonitoringImpl implements Monitoring { + + private final StatsDClient statsd; + private final long flushAfterNanos; + private final boolean enabled; + + public MonitoringImpl(final StatsDClient statsd, long flushInterval, TimeUnit flushUnit) { + this.statsd = statsd; + this.flushAfterNanos = flushUnit.toNanos(flushInterval); + this.enabled = true; + } + + private MonitoringImpl() { + this.statsd = StatsDClient.NO_OP; + this.flushAfterNanos = 0; + this.enabled = false; + } + + @Override + public Recording newTimer(final String name) { + if (!enabled) { + return NoOpRecording.NO_OP; + } + return new Timer(name, statsd, flushAfterNanos); + } + + @Override + public Recording newTimer(final String name, final String... tags) { + if (!enabled) { + return NoOpRecording.NO_OP; + } + return new Timer(name, tags, statsd, flushAfterNanos); + } + + @Override + public Recording newThreadLocalTimer(final String name) { + if (!enabled) { + return NoOpRecording.NO_OP; + } + return new ThreadLocalRecording( + new ThreadLocal() { + @Override + protected Recording initialValue() { + return newTimer(name, "thread:" + Thread.currentThread().getName()); + } + }); + } + + @Override + public Counter newCounter(final String name) { + if (!enabled) { + return NoOpCounter.NO_OP; + } + return new StatsDCounter(name, statsd); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/StatsDCounter.java b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/StatsDCounter.java new file mode 100644 index 0000000000..221ee55712 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/StatsDCounter.java @@ -0,0 +1,27 @@ +package datadog.trace.core.monitor; + +import static datadog.trace.core.monitor.Utils.mergeTags; + +import datadog.trace.monitor.Counter; +import datadog.trace.api.StatsDClient; + +public final class StatsDCounter implements Counter { + + private final String name; + private final String[] tags; + private final StatsDClient statsd; + + StatsDCounter(String name, StatsDClient statsd) { + this.name = name; + this.tags = new String[0]; + this.statsd = statsd; + } + + public void increment(int delta) { + statsd.count(name, delta, tags); + } + + public void incrementErrorCount(String cause, int delta) { + statsd.count(name, delta, mergeTags(tags, new String[] {"cause:" + cause.replace(' ', '_')})); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/ThreadLocalRecording.java b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/ThreadLocalRecording.java new file mode 100644 index 0000000000..546f5183e0 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/ThreadLocalRecording.java @@ -0,0 +1,32 @@ +package datadog.trace.core.monitor; + +import datadog.trace.monitor.Recording; + +public class ThreadLocalRecording extends Recording { + + private final ThreadLocal tls; + + public ThreadLocalRecording(ThreadLocal tls) { + this.tls = tls; + } + + @Override + public Recording start() { + return tls.get().start(); + } + + @Override + public void reset() { + tls.get().reset(); + } + + @Override + public void stop() { + tls.get().stop(); + } + + @Override + public void flush() { + tls.get().flush(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Timer.java b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Timer.java new file mode 100644 index 0000000000..8fe4c7685b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Timer.java @@ -0,0 +1,90 @@ +package datadog.trace.core.monitor; + +import static datadog.trace.core.monitor.Utils.mergeTags; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import datadog.trace.monitor.Recording; +import datadog.trace.api.StatsDClient; +import datadog.trace.core.histogram.Histogram; +import datadog.trace.core.histogram.Histograms; + +/** + * A timer which records times in a histogram, and flushes stats from the histogram after a + * configurable period of time. + */ +public class Timer extends Recording { + + private static final long THIRTY_SECONDS_AS_MICROS = SECONDS.toMicros(30); + + private static final String[] P_50 = new String[] {"stat:p50"}; + private static final String[] P_99 = new String[] {"stat:p99"}; + private static final String[] MAX = new String[] {"stat:max"}; + + private final String name; + private final StatsDClient statsd; + private final Histogram histogram; + private final long flushAfterNanos; + + private final String[] p50Tags; + private final String[] p99Tags; + private final String[] maxTags; + + private long start; + private long lastFlush = 0; + + Timer(final String name, final String[] tags, final StatsDClient statsd, long flushAfterNanos) { + this.name = name; + this.statsd = statsd; + this.flushAfterNanos = flushAfterNanos; + this.histogram = Histograms.newHistogram(); + this.p50Tags = mergeTags(P_50, tags); + this.p99Tags = mergeTags(P_99, tags); + this.maxTags = mergeTags(MAX, tags); + } + + Timer(final String name, final StatsDClient statsd, long flushAfterNanos) { + this(name, null, statsd, flushAfterNanos); + } + + @Override + public Recording start() { + start = System.nanoTime(); + return this; + } + + @Override + public void reset() { + long now = System.nanoTime(); + record(now); + start = now; + } + + @Override + public void stop() { + record(System.nanoTime()); + } + + private void record(long now) { + // if it's longer than 30s, we have bigger problems + histogram.accept(Math.min(NANOSECONDS.toMicros(now - start), THIRTY_SECONDS_AS_MICROS)); + if (now - lastFlush > flushAfterNanos) { + lastFlush = now; + flush(); + } + } + + @Override + public void flush() { + if (histogram.isEmpty()) { + statsd.gauge(name, 0D, p50Tags); + statsd.gauge(name, 0D, p99Tags); + statsd.gauge(name, 0D, maxTags); + } else { + statsd.gauge(name, histogram.getValueAtQuantile(0.50), p50Tags); + statsd.gauge(name, histogram.getValueAtQuantile(0.99), p99Tags); + statsd.gauge(name, histogram.getMaxValue(), maxTags); + } + histogram.clear(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Utils.java b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Utils.java new file mode 100644 index 0000000000..c69de28ec6 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Utils.java @@ -0,0 +1,14 @@ +package datadog.trace.core.monitor; + +import java.util.Arrays; + +public class Utils { + static String[] mergeTags(String[] left, String[] right) { + if (null == right) { + return left; + } + String[] merged = Arrays.copyOf(left, left.length + right.length); + System.arraycopy(right, 0, merged, left.length, right.length); + return merged; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java new file mode 100644 index 0000000000..e39f074585 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java @@ -0,0 +1,357 @@ +package datadog.trace.core.propagation; + +import static datadog.trace.api.TracePropagationStyle.B3MULTI; +import static datadog.trace.api.TracePropagationStyle.B3SINGLE; +import static datadog.trace.core.propagation.HttpCodec.firstHeaderValue; + +import datadog.trace.api.Config; +import datadog.trace.api.DD128bTraceId; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.core.DDSpanContext; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.TreeMap; +import java.util.function.Supplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** A codec designed for HTTP transport via headers using B3 headers */ +class B3HttpCodec { + + private static final Logger log = LoggerFactory.getLogger(B3HttpCodec.class); + + private static final String B3_TRACE_ID = "b3.traceid"; + private static final String B3_SPAN_ID = "b3.spanid"; + static final String TRACE_ID_KEY = "X-B3-TraceId"; + static final String SPAN_ID_KEY = "X-B3-SpanId"; + private static final String SAMPLING_PRIORITY_KEY = "X-B3-Sampled"; + // See https://github.com/openzipkin/b3-propagation#single-header for b3 header documentation + private static final String B3_KEY = "b3"; + private static final String SAMPLING_PRIORITY_ACCEPT = String.valueOf(1); + private static final String SAMPLING_PRIORITY_DROP = String.valueOf(0); + + private B3HttpCodec() { + // This class should not be created. This also makes code coverage checks happy. + } + + public static HttpCodec.Injector newCombinedInjector(boolean paddingEnabled) { + return new HttpCodec.CompoundInjector( + Arrays.asList(newSingleInjector(paddingEnabled), newMultiInjector(paddingEnabled))); + } + + public static HttpCodec.Injector newMultiInjector(boolean paddingEnalbed) { + return new B3MultiInjector(paddingEnalbed); + } + + public static HttpCodec.Injector newSingleInjector(boolean paddingEnabled) { + return new B3SingleInjector(paddingEnabled); + } + + private abstract static class B3Injector implements HttpCodec.Injector { + private final boolean paddingEnabled; + + public B3Injector(boolean paddingEnabled) { + this.paddingEnabled = paddingEnabled; + } + + /** + * Get the TraceId {@link String} representation to inject according the following logic: + * + *
      + *
    • Returns a 32 lower-case hexadecimal character if padding is enabled or for 128-bit + * TraceIds, + *
    • Returns the original String representation if the trace was parsed from B3 extractor, + *
    • Return a non-padded lower-case hexadecimal String for remaining 64-bit TraceIds. + *
    + * + * @param context The context to get the TraceId from. + * @return The TraceId {@link String} representation to inject. + */ + protected final String getInjectedTraceId(DDSpanContext context) { + DDTraceId traceId = context.getTraceId(); + if (this.paddingEnabled || traceId instanceof DD128bTraceId) { + return traceId.toHexString(); + } else if (traceId instanceof B3TraceId) { + return ((B3TraceId) traceId).getOriginal(); + } else { + return DDSpanId.toHexString(traceId.toLong()); + } + } + + /** + * Get the SpanId {@link String} representation to inject according the following logic: + * + *
      + *
    • Returns a 16 lower-case hexadecimal character if padding is enabled, + *
    • Returns a non-padded lower-case hexadecimal character otherwise. + *
    + * + * @param context The context to get the SpanId from. + * @return The SpanId {@link String} representation to inject. + */ + protected final String getInjectedSpanId(DDSpanContext context) { + long spanId = context.getSpanId(); + if (this.paddingEnabled) { + return DDSpanId.toHexStringPadded(spanId); + } else { + return DDSpanId.toHexString(spanId); + } + } + } + + private static final class B3MultiInjector extends B3Injector { + public B3MultiInjector(boolean paddingEnabled) { + super(paddingEnabled); + } + + @Override + public void inject( + final DDSpanContext context, final C carrier, final AgentPropagation.Setter setter) { + final String injectedTraceId = getInjectedTraceId(context); + final String injectedSpanId = getInjectedSpanId(context); + setter.set(carrier, TRACE_ID_KEY, injectedTraceId); + setter.set(carrier, SPAN_ID_KEY, injectedSpanId); + if (context.lockSamplingPriority()) { + final String injectedSamplingPriority = + convertSamplingPriority(context.getSamplingPriority()); + setter.set(carrier, SAMPLING_PRIORITY_KEY, injectedSamplingPriority); + } + log.debug( + "{} - B3 parent context injected - {} {}", + context.getTraceId(), + injectedTraceId, + injectedSpanId); + } + } + + private static final class B3SingleInjector extends B3Injector { + public B3SingleInjector(boolean paddingEnabled) { + super(paddingEnabled); + } + + @Override + public void inject( + final DDSpanContext context, final C carrier, final AgentPropagation.Setter setter) { + final String injectedTraceId = getInjectedTraceId(context); + final String injectedSpanId = getInjectedSpanId(context); + final StringBuilder injectedB3IdBuilder = new StringBuilder(100); + injectedB3IdBuilder.append(injectedTraceId).append('-').append(injectedSpanId); + + if (context.lockSamplingPriority()) { + final String injectedSamplingPriority = + convertSamplingPriority(context.getSamplingPriority()); + injectedB3IdBuilder.append('-').append(injectedSamplingPriority); + } + String injectedB3Id = injectedB3IdBuilder.toString(); + setter.set(carrier, B3_KEY, injectedB3Id); + log.debug("{} - B3 parent context injected - {}", context.getTraceId(), injectedB3Id); + } + } + + private static String convertSamplingPriority(final int samplingPriority) { + return samplingPriority > 0 ? SAMPLING_PRIORITY_ACCEPT : SAMPLING_PRIORITY_DROP; + } + + // Only used from tests + static HttpCodec.Extractor newExtractor( + Config config, Supplier traceConfigSupplier) { + final List extractors = new ArrayList<>(2); + extractors.add(newSingleExtractor(config, traceConfigSupplier)); + extractors.add(newMultiExtractor(config, traceConfigSupplier)); + return new HttpCodec.CompoundExtractor(extractors, config.isTracePropagationExtractFirst()); + } + + public static HttpCodec.Extractor newMultiExtractor( + Config config, Supplier traceConfigSupplier) { + return new TagContextExtractor( + traceConfigSupplier, () -> new B3MultiContextInterpreter(config)); + } + + public static HttpCodec.Extractor newSingleExtractor( + Config config, Supplier traceConfigSupplier) { + return new TagContextExtractor( + traceConfigSupplier, () -> new B3SingleContextInterpreter(config)); + } + + private abstract static class B3BaseContextInterpreter extends ContextInterpreter { + public B3BaseContextInterpreter(Config config) { + super(config); + } + + protected void setSpanId(final String sId) { + spanId = DDSpanId.fromHex(sId); + if (tags.isEmpty()) { + tags = new TreeMap<>(); + } + tags.put(B3_SPAN_ID, sId); + } + + protected boolean setTraceId(final String tId) { + final int length = tId.length(); + if (length > 32) { + log.debug("Header {} exceeded max length of 32: {}", TRACE_ID_KEY, tId); + traceId = DDTraceId.ZERO; + return false; + } else { + B3TraceId b3TraceId = B3TraceId.fromHex(tId); + traceId = b3TraceId.toLong() == 0 ? DDTraceId.ZERO : b3TraceId; + } + if (tags.isEmpty()) { + tags = new TreeMap<>(); + } + tags.put(B3_TRACE_ID, tId); + return true; + } + } + + private static final class B3MultiContextInterpreter extends B3BaseContextInterpreter { + private B3MultiContextInterpreter(Config config) { + super(config); + } + + @Override + public TracePropagationStyle style() { + return B3MULTI; + } + + @Override + public boolean accept(final String key, final String value) { + if (null == key || key.isEmpty() || null == value || value.isEmpty()) { + return true; + } + if (LOG_EXTRACT_HEADER_NAMES) { + log.debug("Header: {}", key); + } + try { + char first = Character.toLowerCase(key.charAt(0)); + switch (first) { + case 'x': + if (TRACE_ID_KEY.equalsIgnoreCase(key)) { + setTraceId(firstHeaderValue(value)); + return true; + } else if (SPAN_ID_KEY.equalsIgnoreCase(key)) { + setSpanId(firstHeaderValue(value)); + return true; + } else if (SAMPLING_PRIORITY_KEY.equalsIgnoreCase(key)) { + samplingPriority = convertSamplingPriority(firstHeaderValue(value)); + return true; + } else if (handledXForwarding(key, value)) { + return true; + } + break; + case 'f': + if (handledForwarding(key, value)) { + return true; + } + break; + case 'u': + if (handledUserAgent(key, value)) { + return true; + } + break; + default: + } + if (handledIpHeaders(key, value)) { + return true; + } + handleTags(key, value); + } catch (RuntimeException e) { + invalidateContext(); + log.debug("Exception when extracting context", e); + return false; + } + return true; + } + } + + private static final class B3SingleContextInterpreter extends B3BaseContextInterpreter { + public B3SingleContextInterpreter(Config config) { + super(config); + } + + @Override + public TracePropagationStyle style() { + return B3SINGLE; + } + + @Override + public boolean accept(String key, String value) { + try { + if (null == key || key.isEmpty() || null == value || value.isEmpty()) { + return true; + } + if (LOG_EXTRACT_HEADER_NAMES) { + log.debug("Header: {}", key); + } + if (B3_KEY.equals(key)) { + return extractB3(firstHeaderValue(value)); + } else { + char first = Character.toLowerCase(key.charAt(0)); + switch (first) { + case 'x': + if (handledXForwarding(key, value)) { + return true; + } + break; + case 'f': + if (handledForwarding(key, value)) { + return true; + } + break; + case 'u': + if (handledUserAgent(key, value)) { + return true; + } + break; + } + } + if (handledIpHeaders(key, value)) { + return true; + } + handleTags(key, value); + } catch (RuntimeException e) { + invalidateContext(); + log.debug("Exception when extracting context", e); + return false; + } + return true; + } + + private boolean extractB3(final String firstValue) { + if (firstValue.length() == 1) { + samplingPriority = convertSamplingPriority(firstValue); + } else { + final int firstIndex = firstValue.indexOf("-"); + final int secondIndex = firstValue.indexOf("-", firstIndex + 1); + if (firstIndex != -1) { + final String b3TraceId = firstValue.substring(0, firstIndex); + if (!setTraceId(b3TraceId)) { + return false; + } + } + if (secondIndex == -1) { + final String b3SpanId = firstValue.substring(firstIndex + 1); + setSpanId(b3SpanId); + } else { + final String b3SpanId = firstValue.substring(firstIndex + 1, secondIndex); + setSpanId(b3SpanId); + final String b3SamplingId = firstValue.substring(secondIndex + 1); + samplingPriority = convertSamplingPriority(b3SamplingId); + } + } + return true; + } + } + + private static int convertSamplingPriority(final String samplingPriority) { + return "1".equals(samplingPriority) + ? PrioritySampling.SAMPLER_KEEP + : PrioritySampling.SAMPLER_DROP; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java new file mode 100644 index 0000000000..a9376cd659 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java @@ -0,0 +1,73 @@ +package datadog.trace.core.propagation; + +import datadog.trace.api.DD128bTraceId; +import datadog.trace.api.DDTraceId; + +/** A B3 {@link DDTraceId} along with its original {@link String} representation. */ +public class B3TraceId extends DDTraceId { + /** The original {@link String} representation. */ + protected final String original; + + protected final DDTraceId delegate; + + /** + * Create a {@link B3TraceId} from a B3 TraceId string. + * + * @param s The B3 TraceId string. + */ + public static B3TraceId fromHex(String s) { + return new B3TraceId(s, DD128bTraceId.fromHex(s)); + } + + protected B3TraceId(String original, DDTraceId delegate) { + this.original = original; + this.delegate = delegate; + } + + /** + * Gets the original B3 TraceId. + * + * @return The original B3 TraceId. + */ + public String getOriginal() { + return this.original; + } + + @Override + public String toHexString() { + return this.delegate.toHexString(); + } + + @Override + public String toHexStringPadded(int size) { + return this.delegate.toHexStringPadded(size); + } + + @Override + public long toLong() { + return this.delegate.toLong(); + } + + @Override + public long toHighOrderLong() { + return this.delegate.toHighOrderLong(); + } + + @Override + public String toString() { + return this.delegate.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + B3TraceId that = (B3TraceId) o; + return delegate.equals(that.delegate); + } + + @Override + public int hashCode() { + return this.delegate.hashCode(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ContextInterpreter.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ContextInterpreter.java new file mode 100644 index 0000000000..01488d3d93 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ContextInterpreter.java @@ -0,0 +1,304 @@ +package datadog.trace.core.propagation; + +import static datadog.trace.core.propagation.HttpCodec.CF_CONNECTING_IP_KEY; +import static datadog.trace.core.propagation.HttpCodec.CF_CONNECTING_IP_V6_KEY; +import static datadog.trace.core.propagation.HttpCodec.FASTLY_CLIENT_IP_KEY; +import static datadog.trace.core.propagation.HttpCodec.FORWARDED_FOR_KEY; +import static datadog.trace.core.propagation.HttpCodec.FORWARDED_KEY; +import static datadog.trace.core.propagation.HttpCodec.TRUE_CLIENT_IP_KEY; +import static datadog.trace.core.propagation.HttpCodec.USER_AGENT_KEY; +import static datadog.trace.core.propagation.HttpCodec.X_CLIENT_IP_KEY; +import static datadog.trace.core.propagation.HttpCodec.X_CLUSTER_CLIENT_IP_KEY; +import static datadog.trace.core.propagation.HttpCodec.X_FORWARDED_FOR_KEY; +import static datadog.trace.core.propagation.HttpCodec.X_FORWARDED_HOST_KEY; +import static datadog.trace.core.propagation.HttpCodec.X_FORWARDED_KEY; +import static datadog.trace.core.propagation.HttpCodec.X_FORWARDED_PORT_KEY; +import static datadog.trace.core.propagation.HttpCodec.X_FORWARDED_PROTO_KEY; +import static datadog.trace.core.propagation.HttpCodec.X_REAL_IP_KEY; + +import datadog.trace.api.Config; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.Functions; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.api.cache.DDCache; +import datadog.trace.api.cache.DDCaches; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.bootstrap.ActiveSubsystems; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.TagContext; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +public abstract class ContextInterpreter implements AgentPropagation.KeyClassifier { + private TraceConfig traceConfig; + + protected Map headerTags; + protected Map baggageMapping; + + protected DDTraceId traceId; + protected long spanId; + protected int samplingPriority; + protected Map tags; + protected Map baggage; + + protected CharSequence origin; + protected long endToEndStartTime; + protected boolean valid; + protected boolean fullContext; + protected final PropagationTags.Factory propagationTagsFactory; + protected PropagationTags propagationTags; + + private TagContext.HttpHeaders httpHeaders; + private final String customIpHeaderName; + private final boolean clientIpResolutionEnabled; + private final boolean clientIpWithoutAppSec; + private boolean collectIpHeaders; + private final boolean requestHeaderTagsCommaAllowed; + + protected static final boolean LOG_EXTRACT_HEADER_NAMES = Config.get().isLogExtractHeaderNames(); + private static final DDCache CACHE = DDCaches.newFixedSizeCache(64); + + protected static String toLowerCase(String key) { + return CACHE.computeIfAbsent(key, Functions.LowerCase.INSTANCE); + } + + protected ContextInterpreter(Config config) { + this.customIpHeaderName = config.getTraceClientIpHeader(); + this.clientIpResolutionEnabled = config.isTraceClientIpResolverEnabled(); + this.clientIpWithoutAppSec = config.isClientIpEnabled(); + this.propagationTagsFactory = PropagationTags.factory(config); + this.requestHeaderTagsCommaAllowed = config.isRequestHeaderTagsCommaAllowed(); + } + + /** + * Gets the propagation style handled by the context interpreter. + * + * @return The propagation style handled. + */ + public abstract TracePropagationStyle style(); + + protected final boolean handledForwarding(String key, String value) { + if (value == null || !collectIpHeaders) { + return false; + } + + if (FORWARDED_KEY.equalsIgnoreCase(key)) { + getHeaders().forwarded = value; + return true; + } + if (FORWARDED_FOR_KEY.equalsIgnoreCase(key)) { + getHeaders().forwardedFor = value; + return true; + } + return false; + } + + protected final boolean handledXForwarding(String key, String value) { + if (value == null || !collectIpHeaders) { + return false; + } + + if (X_FORWARDED_PROTO_KEY.equalsIgnoreCase(key)) { + getHeaders().xForwardedProto = value; + return true; + } + if (X_FORWARDED_HOST_KEY.equalsIgnoreCase(key)) { + getHeaders().xForwardedHost = value; + return true; + } + if (X_FORWARDED_FOR_KEY.equalsIgnoreCase(key)) { + getHeaders().xForwardedFor = value; + return true; + } + if (X_FORWARDED_PORT_KEY.equalsIgnoreCase(key)) { + getHeaders().xForwardedPort = value; + return true; + } + if (X_FORWARDED_KEY.equalsIgnoreCase(key)) { + getHeaders().xForwarded = value; + return true; + } + return false; + } + + protected final boolean handledUserAgent(String key, String value) { + if (value == null || !USER_AGENT_KEY.equalsIgnoreCase(key)) { + return false; + } + + getHeaders().userAgent = value; + return true; + } + + protected final boolean handledIpHeaders(String key, String value) { + if (key == null || key.isEmpty()) { + return false; + } + + if (null != value && customIpHeaderName != null && customIpHeaderName.equalsIgnoreCase(key)) { + getHeaders().customIpHeader = value; + return true; + } + + if (value == null || !collectIpHeaders) { + return false; + } + + // May be ends with 'ip' ? + char last = Character.toLowerCase(key.charAt(key.length() - 1)); + if (last == 'p') { + if (X_CLUSTER_CLIENT_IP_KEY.equalsIgnoreCase(key)) { + getHeaders().xClusterClientIp = value; + return true; + } + if (X_REAL_IP_KEY.equalsIgnoreCase(key)) { + getHeaders().xRealIp = value; + return true; + } + if (X_CLIENT_IP_KEY.equalsIgnoreCase(key)) { + getHeaders().xClientIp = value; + return true; + } + if (TRUE_CLIENT_IP_KEY.equalsIgnoreCase(key)) { + getHeaders().trueClientIp = value; + return true; + } + if (FASTLY_CLIENT_IP_KEY.equalsIgnoreCase(key)) { + getHeaders().fastlyClientIp = value; + return true; + } + if (CF_CONNECTING_IP_KEY.equalsIgnoreCase(key)) { + getHeaders().cfConnectingIp = value; + return true; + } + } else if (CF_CONNECTING_IP_V6_KEY.equalsIgnoreCase(key)) { + getHeaders().cfConnectingIpv6 = value; + return true; + } + + return false; + } + + protected final boolean handleTags(String key, String value) { + if (headerTags.isEmpty() || value == null) { + return false; + } + final String lowerCaseKey = toLowerCase(key); + final String mappedKey = headerTags.get(lowerCaseKey); + if (null != mappedKey) { + if (tags.isEmpty()) { + tags = new TreeMap<>(); + } + tags.put( + mappedKey, + HttpCodec.decode( + requestHeaderTagsCommaAllowed ? value : HttpCodec.firstHeaderValue(value))); + return true; + } + return false; + } + + protected final boolean handleMappedBaggage(String key, String value) { + if (baggageMapping.isEmpty() || value == null) { + return false; + } + final String lowerCaseKey = toLowerCase(key); + final String mappedKey = baggageMapping.get(lowerCaseKey); + if (null != mappedKey) { + if (baggage.isEmpty()) { + baggage = new TreeMap<>(); + } + baggage.put(mappedKey, HttpCodec.decode(value)); + return true; + } + return false; + } + + public ContextInterpreter reset(TraceConfig traceConfig) { + this.traceConfig = traceConfig; + traceId = DDTraceId.ZERO; + spanId = DDSpanId.ZERO; + samplingPriority = PrioritySampling.UNSET; + origin = null; + endToEndStartTime = 0; + tags = Collections.emptyMap(); + baggage = Collections.emptyMap(); + valid = true; + fullContext = true; + httpHeaders = null; + collectIpHeaders = + this.clientIpWithoutAppSec + || this.clientIpResolutionEnabled && ActiveSubsystems.APPSEC_ACTIVE; + headerTags = traceConfig.getRequestHeaderTags(); + baggageMapping = traceConfig.getBaggageMapping(); + return this; + } + + protected TagContext build() { + if (valid) { + if (fullContext && !DDTraceId.ZERO.equals(traceId)) { + if (propagationTags == null) { + propagationTags = propagationTagsFactory.empty(); + } + return new ExtractedContext( + traceId, + spanId, + samplingPriorityOrDefault(traceId, samplingPriority), + origin, + endToEndStartTime, + baggage, + tags, + httpHeaders, + propagationTags, + traceConfig, + style()); + } else if (origin != null + || !tags.isEmpty() + || httpHeaders != null + || !baggage.isEmpty() + || samplingPriority != PrioritySampling.UNSET) { + return new TagContext( + origin, + tags, + httpHeaders, + baggage, + samplingPriorityOrDefault(traceId, samplingPriority), + traceConfig, + style()); + } + } + return null; + } + + protected void invalidateContext() { + this.valid = false; + } + + protected void onlyTagContext() { + this.fullContext = false; + } + + protected int defaultSamplingPriority() { + return PrioritySampling.UNSET; + } + + private TagContext.HttpHeaders getHeaders() { + if (httpHeaders == null) { + httpHeaders = new TagContext.HttpHeaders(); + } + return httpHeaders; + } + + private int samplingPriorityOrDefault(DDTraceId traceId, int samplingPriority) { + return samplingPriority == PrioritySampling.UNSET || DDTraceId.ZERO.equals(traceId) + ? defaultSamplingPriority() + : samplingPriority; + } + + public interface Factory { + ContextInterpreter create(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java new file mode 100644 index 0000000000..135fff0327 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java @@ -0,0 +1,97 @@ +package datadog.trace.core.propagation; + +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.core.DDSpanContext; +import datadog.trace.core.datastreams.DataStreamContextInjector; +import java.util.LinkedHashMap; +import java.util.Map; + +public class CorePropagation implements AgentPropagation { + private final HttpCodec.Injector injector; + private final Map injectors; + private final DataStreamContextInjector dataStreamContextInjector; + private final HttpCodec.Extractor extractor; + + /** + * Constructor + * + * @param extractor The context extractor. + * @param defaultInjector The default injector when no {@link TracePropagationStyle} given. + * @param injectors All the other injectors available for context injection. + * @param dataStreamContextInjector The DSM context injector, as a specific object until generic + * context injection is available. + */ + public CorePropagation( + HttpCodec.Extractor extractor, + HttpCodec.Injector defaultInjector, + Map injectors, + DataStreamContextInjector dataStreamContextInjector) { + this.extractor = extractor; + this.injector = defaultInjector; + this.injectors = injectors; + this.dataStreamContextInjector = dataStreamContextInjector; + } + + @Override + public void inject(final AgentSpan span, final C carrier, final Setter setter) { + inject(span.context(), carrier, setter, null); + } + + @Override + public void inject(AgentSpan.Context context, C carrier, Setter setter) { + inject(context, carrier, setter, null); + } + + @Override + public void inject(AgentSpan span, C carrier, Setter setter, TracePropagationStyle style) { + inject(span.context(), carrier, setter, style); + } + + private void inject( + AgentSpan.Context context, C carrier, Setter setter, TracePropagationStyle style) { + if (!(context instanceof DDSpanContext)) { + return; + } + + final DDSpanContext ddSpanContext = (DDSpanContext) context; + ddSpanContext.getTrace().setSamplingPriorityIfNecessary(); + + if (null == style) { + injector.inject(ddSpanContext, carrier, setter); + } else { + injectors.get(style).inject(ddSpanContext, carrier, setter); + } + } + + @Override + public void injectPathwayContext( + AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags) { + this.dataStreamContextInjector.injectPathwayContext(span, carrier, setter, sortedTags); + } + + @Override + public void injectPathwayContext( + AgentSpan span, + C carrier, + Setter setter, + LinkedHashMap sortedTags, + long defaultTimestamp, + long payloadSizeBytes) { + this.dataStreamContextInjector.injectPathwayContext( + span, carrier, setter, sortedTags, defaultTimestamp, payloadSizeBytes); + } + + @Override + public void injectPathwayContextWithoutSendingStats( + AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags) { + this.dataStreamContextInjector.injectPathwayContextWithoutSendingStats( + span, carrier, setter, sortedTags); + } + + @Override + public AgentSpan.Context.Extracted extract(final C carrier, final ContextVisitor getter) { + return extractor.extract(carrier, getter); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/DatadogHttpCodec.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/DatadogHttpCodec.java new file mode 100644 index 0000000000..9624a54a50 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/DatadogHttpCodec.java @@ -0,0 +1,245 @@ +package datadog.trace.core.propagation; + +import static datadog.trace.api.TracePropagationStyle.DATADOG; +import static datadog.trace.core.propagation.HttpCodec.firstHeaderValue; +import static datadog.trace.core.propagation.XRayHttpCodec.XRayContextInterpreter.handleXRayTraceHeader; +import static datadog.trace.core.propagation.XRayHttpCodec.X_AMZN_TRACE_ID; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +import datadog.trace.api.Config; +import datadog.trace.api.DD128bTraceId; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTags; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.TagContext; +import datadog.trace.core.DDSpanContext; +import datadog.trace.core.propagation.PropagationTags.HeaderType; +import java.util.Map; +import java.util.TreeMap; +import java.util.function.Supplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** A codec designed for HTTP transport via headers using Datadog headers */ +class DatadogHttpCodec { + private static final Logger log = LoggerFactory.getLogger(DatadogHttpCodec.class); + + static final String OT_BAGGAGE_PREFIX = "ot-baggage-"; + static final String TRACE_ID_KEY = "x-datadog-trace-id"; + static final String SPAN_ID_KEY = "x-datadog-parent-id"; + static final String SAMPLING_PRIORITY_KEY = "x-datadog-sampling-priority"; + static final String ORIGIN_KEY = "x-datadog-origin"; + private static final String E2E_START_KEY = OT_BAGGAGE_PREFIX + DDTags.TRACE_START_TIME; + static final String DATADOG_TAGS_KEY = "x-datadog-tags"; + + private DatadogHttpCodec() { + // This class should not be created. This also makes code coverage checks happy. + } + + public static HttpCodec.Injector newInjector(Map invertedBaggageMapping) { + return new Injector(invertedBaggageMapping); + } + + private static class Injector implements HttpCodec.Injector { + + private final Map invertedBaggageMapping; + + public Injector(Map invertedBaggageMapping) { + assert invertedBaggageMapping != null; + this.invertedBaggageMapping = invertedBaggageMapping; + } + + @Override + public void inject( + final DDSpanContext context, final C carrier, final AgentPropagation.Setter setter) { + + setter.set(carrier, TRACE_ID_KEY, context.getTraceId().toString()); + setter.set(carrier, SPAN_ID_KEY, DDSpanId.toString(context.getSpanId())); + if (context.lockSamplingPriority()) { + setter.set(carrier, SAMPLING_PRIORITY_KEY, String.valueOf(context.getSamplingPriority())); + } + final CharSequence origin = context.getOrigin(); + if (origin != null) { + setter.set(carrier, ORIGIN_KEY, origin.toString()); + } + long e2eStart = context.getEndToEndStartTime(); + if (e2eStart > 0) { + setter.set(carrier, E2E_START_KEY, Long.toString(NANOSECONDS.toMillis(e2eStart))); + } + + for (final Map.Entry entry : context.baggageItems()) { + String header = invertedBaggageMapping.get(entry.getKey()); + header = header != null ? header : OT_BAGGAGE_PREFIX + entry.getKey(); + setter.set(carrier, header, HttpCodec.encodeBaggage(entry.getValue())); + } + + // inject x-datadog-tags + String datadogTags = context.getPropagationTags().headerValue(HeaderType.DATADOG); + if (datadogTags != null) { + setter.set(carrier, DATADOG_TAGS_KEY, datadogTags); + } + } + } + + public static HttpCodec.Extractor newExtractor( + Config config, Supplier traceConfigSupplier) { + return new TagContextExtractor( + traceConfigSupplier, () -> new DatadogContextInterpreter(config)); + } + + private static class DatadogContextInterpreter extends ContextInterpreter { + + private static final int TRACE_ID = 0; + private static final int SPAN_ID = 1; + private static final int ORIGIN = 2; + private static final int SAMPLING_PRIORITY = 3; + private static final int OT_BAGGAGE = 4; + private static final int E2E_START = 5; + private static final int DD_TAGS = 6; + private static final int IGNORE = -1; + + private final boolean isAwsPropagationEnabled; + + private DatadogContextInterpreter(Config config) { + super(config); + isAwsPropagationEnabled = config.isAwsPropagationEnabled(); + } + + @Override + public TracePropagationStyle style() { + return DATADOG; + } + + @Override + public boolean accept(String key, String value) { + if (null == key || key.isEmpty()) { + return true; + } + if (LOG_EXTRACT_HEADER_NAMES) { + log.debug("Header: {}", key); + } + String lowerCaseKey = null; + int classification = IGNORE; + char first = Character.toLowerCase(key.charAt(0)); + switch (first) { + case 'x': + if (TRACE_ID_KEY.equalsIgnoreCase(key)) { + classification = TRACE_ID; + } else if (SPAN_ID_KEY.equalsIgnoreCase(key)) { + classification = SPAN_ID; + } else if (SAMPLING_PRIORITY_KEY.equalsIgnoreCase(key)) { + classification = SAMPLING_PRIORITY; + } else if (ORIGIN_KEY.equalsIgnoreCase(key)) { + classification = ORIGIN; + } else if (isAwsPropagationEnabled && X_AMZN_TRACE_ID.equalsIgnoreCase(key)) { + handleXRayTraceHeader(this, value); + return true; + } else if (handledXForwarding(key, value)) { + return true; + } else if (DATADOG_TAGS_KEY.equalsIgnoreCase(key)) { + classification = DD_TAGS; + } + break; + case 'f': + if (handledForwarding(key, value)) { + return true; + } + break; + case 'u': + if (handledUserAgent(key, value)) { + return true; + } + break; + case 'o': + lowerCaseKey = toLowerCase(key); + if (E2E_START_KEY.equals(lowerCaseKey)) { + classification = E2E_START; + } else if (lowerCaseKey.startsWith(OT_BAGGAGE_PREFIX)) { + classification = OT_BAGGAGE; + } + break; + default: + } + + if (classification != IGNORE) { + try { + if (null != value) { + switch (classification) { + case TRACE_ID: + traceId = DDTraceId.from(firstHeaderValue(value)); + break; + case SPAN_ID: + spanId = DDSpanId.from(firstHeaderValue(value)); + break; + case ORIGIN: + origin = firstHeaderValue(value); + break; + case SAMPLING_PRIORITY: + samplingPriority = Integer.parseInt(firstHeaderValue(value)); + break; + case E2E_START: + endToEndStartTime = extractEndToEndStartTime(firstHeaderValue(value)); + break; + case DD_TAGS: + propagationTags = propagationTagsFactory.fromHeaderValue(HeaderType.DATADOG, value); + break; + case OT_BAGGAGE: + { + if (baggage.isEmpty()) { + baggage = new TreeMap<>(); + } + baggage.put( + lowerCaseKey.substring(OT_BAGGAGE_PREFIX.length()), HttpCodec.decode(value)); + } + break; + default: + } + } + } catch (RuntimeException e) { + invalidateContext(); + log.debug("Exception when extracting context", e); + return false; + } + } else { + if (handledIpHeaders(key, value)) { + return true; + } + if (handleTags(key, value)) { + return true; + } + handleMappedBaggage(key, value); + } + return true; + } + + @Override + protected TagContext build() { + restore128bTraceId(); + return super.build(); + } + + private long extractEndToEndStartTime(String value) { + try { + return MILLISECONDS.toNanos(Long.parseLong(value)); + } catch (RuntimeException e) { + log.debug("Ignoring invalid end-to-end start time {}", value, e); + return 0; + } + } + + private void restore128bTraceId() { + long highOrderBits; + // Check if the low-order 64 bits of the TraceId, and propagation tags were parsed + if (traceId != DDTraceId.ZERO + && propagationTags != null + && (highOrderBits = propagationTags.getTraceIdHighOrderBits()) != 0) { + // Restore the 128-bit TraceId + traceId = DD128bTraceId.from(highOrderBits, traceId.toLong()); + } + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ExtractedContext.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ExtractedContext.java new file mode 100644 index 0000000000..d164eec30b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ExtractedContext.java @@ -0,0 +1,103 @@ +package datadog.trace.core.propagation; + +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.bootstrap.instrumentation.api.TagContext; +import java.util.Map; + +/** + * Propagated data resulting from calling tracer.extract with header data from an incoming request. + */ +public class ExtractedContext extends TagContext { + private final DDTraceId traceId; + private final long spanId; + private final long endToEndStartTime; + private final PropagationTags propagationTags; + + public ExtractedContext( + final DDTraceId traceId, + final long spanId, + final int samplingPriority, + final CharSequence origin, + final PropagationTags propagationTags, + final TracePropagationStyle propagationStyle) { + this( + traceId, + spanId, + samplingPriority, + origin, + 0, + null, + null, + null, + propagationTags, + null, + propagationStyle); + } + + public ExtractedContext( + final DDTraceId traceId, + final long spanId, + final int samplingPriority, + final CharSequence origin, + final long endToEndStartTime, + final Map baggage, + final Map tags, + final HttpHeaders httpHeaders, + final PropagationTags propagationTags, + final TraceConfig traceConfig, + final TracePropagationStyle propagationStyle) { + super(origin, tags, httpHeaders, baggage, samplingPriority, traceConfig, propagationStyle); + this.traceId = traceId; + this.spanId = spanId; + this.endToEndStartTime = endToEndStartTime; + this.propagationTags = propagationTags; + } + + @Override + public final DDTraceId getTraceId() { + return traceId; + } + + @Override + public final long getSpanId() { + return spanId; + } + + public final long getEndToEndStartTime() { + return endToEndStartTime; + } + + public PropagationTags getPropagationTags() { + return propagationTags; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("ExtractedContext{"); + if (traceId != null) { + builder.append("traceId=").append(traceId).append(", "); + } + if (spanId != 0) { + builder.append("endToEndStartTime=").append(spanId).append(", "); + } + if (endToEndStartTime != 0) { + builder.append("spanId=").append(spanId).append(", "); + } + if (getOrigin() != null) { + builder.append("origin=").append(getOrigin()).append(", "); + } + if (getTags() != null) { + builder.append("tags=").append(getTags()).append(", "); + } + if (getBaggage() != null) { + builder.append("baggage=").append(getBaggage()).append(", "); + } + if (getSamplingPriority() != PrioritySampling.UNSET) { + builder.append("samplingPriority=").append(getSamplingPriority()).append(", "); + } + return builder.append('}').toString(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java new file mode 100644 index 0000000000..e272bac6d9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java @@ -0,0 +1,288 @@ +package datadog.trace.core.propagation; + +import static datadog.trace.api.TracePropagationStyle.HAYSTACK; +import static datadog.trace.core.propagation.HttpCodec.firstHeaderValue; + +import datadog.trace.api.Config; +import datadog.trace.api.DD64bTraceId; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.core.DDSpanContext; +import java.util.Map; +import java.util.TreeMap; +import java.util.function.Supplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A codec designed for HTTP transport via headers using Haystack headers. + * + * @author Alex Antonov + */ +class HaystackHttpCodec { + + private static final Logger log = LoggerFactory.getLogger(HaystackHttpCodec.class); + + // https://github.com/ExpediaDotCom/haystack-client-java/blob/master/core/src/main/java/com/expedia/www/haystack/client/propagation/DefaultKeyConvention.java + private static final String OT_BAGGAGE_PREFIX = "Baggage-"; + private static final String TRACE_ID_KEY = "Trace-ID"; + private static final String SPAN_ID_KEY = "Span-ID"; + private static final String PARENT_ID_KEY = "Parent-ID"; + + private static final String DD_TRACE_ID_BAGGAGE_KEY = OT_BAGGAGE_PREFIX + "Datadog-Trace-Id"; + private static final String DD_SPAN_ID_BAGGAGE_KEY = OT_BAGGAGE_PREFIX + "Datadog-Span-Id"; + private static final String DD_PARENT_ID_BAGGAGE_KEY = OT_BAGGAGE_PREFIX + "Datadog-Parent-Id"; + + private static final String HAYSTACK_TRACE_ID_BAGGAGE_KEY = "Haystack-Trace-ID"; + private static final String HAYSTACK_SPAN_ID_BAGGAGE_KEY = "Haystack-Span-ID"; + private static final String HAYSTACK_PARENT_ID_BAGGAGE_KEY = "Haystack-Parent-ID"; + + // public static final long DATADOG = new BigInteger("Datadog!".getBytes()).longValue(); + public static final String DATADOG = "44617461-646f-6721"; + + private HaystackHttpCodec() { + // This class should not be created. This also makes code coverage checks happy. + } + + public static HttpCodec.Injector newInjector(Map invertedBaggageMapping) { + return new Injector(invertedBaggageMapping); + } + + private static class Injector implements HttpCodec.Injector { + + private final Map invertedBaggageMapping; + + public Injector(Map invertedBaggageMapping) { + this.invertedBaggageMapping = invertedBaggageMapping; + } + + @Override + public void inject( + final DDSpanContext context, final C carrier, final AgentPropagation.Setter setter) { + try { + // Given that Haystack uses a 128-bit UUID/GUID for all ID representations, need to convert + // from 64-bit BigInteger + // also record the original DataDog IDs into Baggage payload + // + // If the original trace has originated within Haystack system and we have it saved in + // Baggage, and it is equal + // to the converted value in BigInteger, use that instead. + // this will preserve the complete UUID/GUID without losing the most significant bit part + String originalHaystackTraceId = + getBaggageItemIgnoreCase(context.getBaggageItems(), HAYSTACK_TRACE_ID_BAGGAGE_KEY); + String injectedTraceId; + if (originalHaystackTraceId != null + && DDTraceId.fromHex(convertUUIDToHexString(originalHaystackTraceId)) + .equals(context.getTraceId())) { + injectedTraceId = originalHaystackTraceId; + } else { + injectedTraceId = convertLongToUUID(context.getTraceId().toLong()); + } + setter.set(carrier, TRACE_ID_KEY, injectedTraceId); + context.setTag(HAYSTACK_TRACE_ID_BAGGAGE_KEY, injectedTraceId); + setter.set( + carrier, DD_TRACE_ID_BAGGAGE_KEY, HttpCodec.encode(context.getTraceId().toString())); + setter.set(carrier, SPAN_ID_KEY, convertLongToUUID(context.getSpanId())); + setter.set( + carrier, + DD_SPAN_ID_BAGGAGE_KEY, + HttpCodec.encode(DDSpanId.toString(context.getSpanId()))); + setter.set(carrier, PARENT_ID_KEY, convertLongToUUID(context.getParentId())); + setter.set( + carrier, + DD_PARENT_ID_BAGGAGE_KEY, + HttpCodec.encode(DDSpanId.toString(context.getParentId()))); + + for (final Map.Entry entry : context.baggageItems()) { + String header = invertedBaggageMapping.get(entry.getKey()); + header = header != null ? header : OT_BAGGAGE_PREFIX + entry.getKey(); + setter.set(carrier, header, HttpCodec.encodeBaggage(entry.getValue())); + } + log.debug( + "{} - Haystack parent context injected - {}", context.getTraceId(), injectedTraceId); + } catch (final NumberFormatException e) { + log.debug( + "Cannot parse context id(s): {} {}", context.getTraceId(), context.getSpanId(), e); + } + } + + private String getBaggageItemIgnoreCase(Map baggage, String key) { + for (final Map.Entry mapping : baggage.entrySet()) { + if (key.equalsIgnoreCase(mapping.getKey())) { + return mapping.getValue(); + } + } + return null; + } + } + + public static HttpCodec.Extractor newExtractor( + Config config, Supplier traceConfigSupplier) { + return new TagContextExtractor( + traceConfigSupplier, () -> new HaystackContextInterpreter(config)); + } + + private static class HaystackContextInterpreter extends ContextInterpreter { + + private static final String BAGGAGE_PREFIX_LC = "baggage-"; + + private static final int TRACE_ID = 0; + private static final int SPAN_ID = 1; + private static final int PARENT_ID = 2; + private static final int BAGGAGE = 3; + private static final int IGNORE = -1; + + private HaystackContextInterpreter(Config config) { + super(config); + } + + @Override + public TracePropagationStyle style() { + return HAYSTACK; + } + + @Override + public boolean accept(String key, String value) { + if (null == key || key.isEmpty()) { + return true; + } + if (LOG_EXTRACT_HEADER_NAMES) { + log.debug("Header: {}", key); + } + char first = Character.toLowerCase(key.charAt(0)); + String lowerCaseKey = null; + int classification = IGNORE; + switch (first) { + case 't': + if (TRACE_ID_KEY.equalsIgnoreCase(key)) { + classification = TRACE_ID; + } + break; + case 's': + if (SPAN_ID_KEY.equalsIgnoreCase(key)) { + classification = SPAN_ID; + } + break; + case 'p': + if (PARENT_ID_KEY.equalsIgnoreCase(key)) { + classification = PARENT_ID; + } + break; + case 'x': + if (handledXForwarding(key, value)) { + return true; + } + break; + case 'f': + if (handledForwarding(key, value)) { + return true; + } + break; + case 'b': + lowerCaseKey = toLowerCase(key); + if (lowerCaseKey.startsWith(BAGGAGE_PREFIX_LC)) { + classification = BAGGAGE; + } + break; + case 'u': + if (handledUserAgent(key, value)) { + return true; + } + break; + default: + } + + if (IGNORE != classification) { + try { + String firstValue = firstHeaderValue(value); + if (null != firstValue) { + switch (classification) { + case TRACE_ID: + traceId = DD64bTraceId.fromHex(convertUUIDToHexString(value)); + addBaggageItem(HAYSTACK_TRACE_ID_BAGGAGE_KEY, value); + break; + case SPAN_ID: + spanId = DDSpanId.fromHex(convertUUIDToHexString(value)); + addBaggageItem(HAYSTACK_SPAN_ID_BAGGAGE_KEY, value); + break; + case PARENT_ID: + addBaggageItem(HAYSTACK_PARENT_ID_BAGGAGE_KEY, value); + break; + case BAGGAGE: + { + addBaggageItem(lowerCaseKey.substring(BAGGAGE_PREFIX_LC.length()), value); + break; + } + default: + } + } + } catch (RuntimeException e) { + invalidateContext(); + log.debug("Exception when extracting context", e); + return false; + } + } else { + if (handledIpHeaders(key, value)) { + return true; + } + if (handleTags(key, value)) { + return true; + } + handleMappedBaggage(key, value); + } + return true; + } + + private void addBaggageItem(String key, String value) { + if (baggage.isEmpty()) { + baggage = new TreeMap<>(); + } + baggage.put(key, HttpCodec.decode(value)); + } + + @Override + protected int defaultSamplingPriority() { + return PrioritySampling.SAMPLER_KEEP; + } + } + + private static String convertLongToUUID(long id) { + // This is not a true/real UUID, as we don't care about the version and variant markers + // the creation is just taking the least significant bits and doing static most significant + // ones. + // this is done for the purpose of being able to maintain cardinality and idempotence of the + // conversion + String idHex = String.format("%016x", id); + return DATADOG + "-" + idHex.substring(0, 4) + "-" + idHex.substring(4); + } + + private static String convertUUIDToHexString(String value) { + try { + if (value.contains("-")) { + String[] strings = value.split("-"); + // We are only interested in the least significant bit component, dropping the most + // significant one. + if (strings.length == 5) { + String idHex = strings[3] + strings[4]; + return idHex; + } + throw new NumberFormatException("Invalid UUID format: " + value); + } else { + // This could be a regular hex id without separators + int length = value.length(); + if (length == 32) { + return value.substring(16); + } else { + return value; + } + } + } catch (final Exception e) { + throw new IllegalArgumentException( + "Exception when converting UUID to BigInteger: " + value, e); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HttpCodec.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HttpCodec.java new file mode 100644 index 0000000000..c1e8df5c46 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HttpCodec.java @@ -0,0 +1,354 @@ +package datadog.trace.core.propagation; + +import static datadog.trace.api.TracePropagationStyle.TRACECONTEXT; + +import datadog.trace.api.Config; +import datadog.trace.api.DD128bTraceId; +import datadog.trace.api.DD64bTraceId; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.TagContext; +import datadog.trace.core.DDSpanContext; +import datadog.trace.core.DDSpanLink; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Supplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HttpCodec { + + private static final Logger log = LoggerFactory.getLogger(HttpCodec.class); + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded + static final String FORWARDED_KEY = "forwarded"; + static final String FORWARDED_FOR_KEY = "forwarded-for"; + static final String X_FORWARDED_PROTO_KEY = "x-forwarded-proto"; + static final String X_FORWARDED_HOST_KEY = "x-forwarded-host"; + static final String X_FORWARDED_KEY = "x-forwarded"; + static final String X_FORWARDED_FOR_KEY = "x-forwarded-for"; + static final String X_FORWARDED_PORT_KEY = "x-forwarded-port"; + + // other headers which may contain real ip + static final String X_CLIENT_IP_KEY = "x-client-ip"; + static final String TRUE_CLIENT_IP_KEY = "true-client-ip"; + static final String X_CLUSTER_CLIENT_IP_KEY = "x-cluster-client-ip"; + static final String X_REAL_IP_KEY = "x-real-ip"; + static final String USER_AGENT_KEY = "user-agent"; + static final String FASTLY_CLIENT_IP_KEY = "fastly-client-ip"; + static final String CF_CONNECTING_IP_KEY = "cf-connecting-ip"; + static final String CF_CONNECTING_IP_V6_KEY = "cf-connecting-ipv6"; + + public interface Injector { + void inject( + final DDSpanContext context, final C carrier, final AgentPropagation.Setter setter); + } + + /** This interface defines propagated context extractor. */ + public interface Extractor { + /** + * Extracts a propagated context from the given carrier using the provided getter. + * + * @param carrier The carrier containing the propagated context. + * @param getter The getter used to extract data from the carrier. + * @param The type of the carrier. + * @return {@code null} for failed context extraction, a {@link TagContext} instance for partial + * context extraction or an {@link ExtractedContext} for complete context extraction. + */ + TagContext extract(final C carrier, final AgentPropagation.ContextVisitor getter); + + /** + * Cleans up any thread local resources associated with this extractor. + * + *

    Implementations should override this method if they need to clean up any resources. + * + *

    Currently only used from tests. + */ + default void cleanup() {} + } + + public static Injector createInjector( + Config config, + Set styles, + Map invertedBaggageMapping) { + ArrayList injectors = + new ArrayList<>(createInjectors(config, styles, invertedBaggageMapping).values()); + return new CompoundInjector(injectors); + } + + public static Map allInjectorsFor( + Config config, Map reverseBaggageMapping) { + return createInjectors( + config, EnumSet.allOf(TracePropagationStyle.class), reverseBaggageMapping); + } + + private static Map createInjectors( + Config config, + Set propagationStyles, + Map reverseBaggageMapping) { + EnumMap result = new EnumMap<>(TracePropagationStyle.class); + for (TracePropagationStyle style : propagationStyles) { + switch (style) { + case DATADOG: + result.put(style, DatadogHttpCodec.newInjector(reverseBaggageMapping)); + break; + case B3SINGLE: + result.put( + style, + B3HttpCodec.newSingleInjector(config.isTracePropagationStyleB3PaddingEnabled())); + break; + case B3MULTI: + result.put( + style, + B3HttpCodec.newMultiInjector(config.isTracePropagationStyleB3PaddingEnabled())); + break; + case HAYSTACK: + result.put(style, HaystackHttpCodec.newInjector(reverseBaggageMapping)); + break; + case XRAY: + result.put(style, XRayHttpCodec.newInjector(reverseBaggageMapping)); + break; + case NONE: + result.put(style, NoneCodec.INJECTOR); + break; + case TRACECONTEXT: + result.put(style, W3CHttpCodec.newInjector(reverseBaggageMapping)); + break; + default: + log.debug("No implementation found to inject propagation style: {}", style); + break; + } + } + return result; + } + + public static Extractor createExtractor( + Config config, Supplier traceConfigSupplier) { + final List extractors = new ArrayList<>(); + for (final TracePropagationStyle style : config.getTracePropagationStylesToExtract()) { + switch (style) { + case DATADOG: + extractors.add(DatadogHttpCodec.newExtractor(config, traceConfigSupplier)); + break; + case B3SINGLE: + extractors.add(B3HttpCodec.newSingleExtractor(config, traceConfigSupplier)); + break; + case B3MULTI: + extractors.add(B3HttpCodec.newMultiExtractor(config, traceConfigSupplier)); + break; + case HAYSTACK: + extractors.add(HaystackHttpCodec.newExtractor(config, traceConfigSupplier)); + break; + case XRAY: + extractors.add(XRayHttpCodec.newExtractor(config, traceConfigSupplier)); + break; + case NONE: + extractors.add(NoneCodec.EXTRACTOR); + break; + case TRACECONTEXT: + extractors.add(W3CHttpCodec.newExtractor(config, traceConfigSupplier)); + break; + default: + log.debug("No implementation found to extract propagation style: {}", style); + break; + } + } + switch (extractors.size()) { + case 0: + return StubExtractor.INSTANCE; + case 1: + return extractors.get(0); + default: + return new CompoundExtractor(extractors, config.isTracePropagationExtractFirst()); + } + } + + public static class CompoundInjector implements Injector { + + private final List injectors; + + public CompoundInjector(final List injectors) { + this.injectors = injectors; + } + + @Override + public void inject( + final DDSpanContext context, final C carrier, final AgentPropagation.Setter setter) { + log.debug("Inject context {}", context); + for (final Injector injector : injectors) { + injector.inject(context, carrier, setter); + } + } + } + + private static class StubExtractor implements Extractor { + private static final StubExtractor INSTANCE = new StubExtractor(); + + @Override + public TagContext extract(C carrier, AgentPropagation.ContextVisitor getter) { + return null; + } + } + + public static class CompoundExtractor implements Extractor { + private final List extractors; + private final boolean extractFirst; + + public CompoundExtractor(final List extractors, boolean extractFirst) { + this.extractors = extractors; + this.extractFirst = extractFirst; + } + + @Override + public TagContext extract( + final C carrier, final AgentPropagation.ContextVisitor getter) { + ExtractedContext context = null; + TagContext partialContext = null; + // Extract and cache all headers in advance + ExtractionCache extractionCache = new ExtractionCache<>(carrier, getter); + + for (final Extractor extractor : this.extractors) { + TagContext extracted = extractor.extract(extractionCache, extractionCache); + // Check if context is valid + if (extracted instanceof ExtractedContext) { + ExtractedContext extractedContext = (ExtractedContext) extracted; + // If no prior valid context, store it as first valid context + if (context == null) { + context = extractedContext; + // Stop extraction if only extracting first valid context and drop everything else + if (this.extractFirst) { + break; + } + } + // If another valid context is extracted + else { + if (traceIdMatch(context.getTraceId(), extractedContext.getTraceId())) { + boolean comingFromTraceContext = extracted.getPropagationStyle() == TRACECONTEXT; + if (comingFromTraceContext) { + // Propagate newly extracted W3C tracestate to first valid context + String extractedTracestate = + extractedContext.getPropagationTags().getW3CTracestate(); + context.getPropagationTags().updateW3CTracestate(extractedTracestate); + } + } else { + // Terminate extracted context and add it as span link + context.addTerminatedContextLink(DDSpanLink.from((ExtractedContext) extracted)); + // TODO Note: Other vendor tracestate will be lost here + } + } + } + // Check if context is at least partial to keep it as first valid partial context found + else if (extracted != null && partialContext == null) { + partialContext = extracted; + } + } + + if (context != null) { + log.debug("Extract complete context {}", context); + return context; + } else if (partialContext != null) { + log.debug("Extract incomplete context {}", partialContext); + return partialContext; + } else { + log.debug("Extract no context"); + return null; + } + } + } + + private static class ExtractionCache + implements AgentPropagation.KeyClassifier, + AgentPropagation.ContextVisitor> { + /** Cached context key-values (even indexes are header names, odd indexes are header values). */ + private final List keysAndValues; + + public ExtractionCache(C carrier, AgentPropagation.ContextVisitor getter) { + this.keysAndValues = new ArrayList<>(32); + getter.forEachKey(carrier, this); + } + + @Override + public boolean accept(String key, String value) { + this.keysAndValues.add(key); + this.keysAndValues.add(value); + return true; + } + + @Override + public void forEachKey(ExtractionCache carrier, AgentPropagation.KeyClassifier classifier) { + List keysAndValues = carrier.keysAndValues; + for (int i = 0; i < keysAndValues.size(); i += 2) { + classifier.accept(keysAndValues.get(i), keysAndValues.get(i + 1)); + } + } + } + + /** + * Checks if trace identifier matches, even if they are not encoded using the same size (64-bit vs + * 128-bit). + * + * @param a A trace identifier to check. + * @param b Another trace identifier to check. + * @return {@code true} if the trace identifiers matches, {@code false} otherwise. + */ + private static boolean traceIdMatch(DDTraceId a, DDTraceId b) { + if (a instanceof DD128bTraceId && b instanceof DD128bTraceId + || a instanceof DD64bTraceId && b instanceof DD64bTraceId) { + return a.equals(b); + } else { + return a.toLong() == b.toLong(); + } + } + + /** URL encode value */ + static String encode(final String value) { + String encoded = value; + try { + encoded = URLEncoder.encode(value, "UTF-8"); + } catch (final UnsupportedEncodingException e) { + log.debug("Failed to encode value - {}", value); + } + return encoded; + } + + /** + * Encodes baggage value according W3C RFC. + * + * @param value The baggage value. + * @return The encoded baggage value. + */ + static String encodeBaggage(final String value) { + // Fix encoding to comply with https://www.w3.org/TR/baggage/#value and use percent-encoding + // (RFC3986) + // for space ( ) instead of plus (+) from 'application/x-www-form' MIME encoding + return encode(value).replace("+", "%20"); + } + + /** URL decode value */ + static String decode(final String value) { + String decoded = value; + try { + decoded = URLDecoder.decode(value, "UTF-8"); + } catch (final UnsupportedEncodingException | IllegalArgumentException e) { + log.debug("Failed to decode value - {}", value); + } + return decoded; + } + + static String firstHeaderValue(final String value) { + if (value == null) { + return null; + } + + int firstComma = value.indexOf(','); + return firstComma == -1 ? value : value.substring(0, firstComma).trim(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoOpCorePropagation.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoOpCorePropagation.java new file mode 100644 index 0000000000..fad468a5f7 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoOpCorePropagation.java @@ -0,0 +1,59 @@ +package datadog.trace.core.propagation; + +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.core.DDSpanContext; +import datadog.trace.core.datastreams.DataStreamContextInjector; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class NoOpCorePropagation implements AgentPropagation { + private final HttpCodec.Extractor extractor; + + public NoOpCorePropagation(HttpCodec.Extractor extractor) { + this.extractor = extractor; + } + + @Override + public void inject(final AgentSpan span, final C carrier, final Setter setter) { + } + + @Override + public void inject(AgentSpan.Context context, C carrier, Setter setter) { + } + + @Override + public void inject(AgentSpan span, C carrier, Setter setter, TracePropagationStyle style) { + } + + private void inject( + AgentSpan.Context context, C carrier, Setter setter, TracePropagationStyle style) { + } + + @Override + public void injectPathwayContext( + AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags) { + } + + @Override + public void injectPathwayContext( + AgentSpan span, + C carrier, + Setter setter, + LinkedHashMap sortedTags, + long defaultTimestamp, + long payloadSizeBytes) { + } + + @Override + public void injectPathwayContextWithoutSendingStats( + AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags) { + } + + @Override + public AgentSpan.Context.Extracted extract(final C carrier, final ContextVisitor getter) { + return extractor.extract(carrier, getter); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoneCodec.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoneCodec.java new file mode 100644 index 0000000000..377062667a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoneCodec.java @@ -0,0 +1,23 @@ +package datadog.trace.core.propagation; + +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.TagContext; +import datadog.trace.core.DDSpanContext; + +public class NoneCodec { + + public static final HttpCodec.Injector INJECTOR = + new HttpCodec.Injector() { + @Override + public void inject( + DDSpanContext context, C carrier, AgentPropagation.Setter setter) {} + }; + + public static final HttpCodec.Extractor EXTRACTOR = + new HttpCodec.Extractor() { + @Override + public TagContext extract(C carrier, AgentPropagation.ContextVisitor getter) { + return null; + } + }; +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/PropagationTags.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/PropagationTags.java new file mode 100644 index 0000000000..00ed3d0f53 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/PropagationTags.java @@ -0,0 +1,104 @@ +package datadog.trace.core.propagation; + +import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH; + +import datadog.trace.api.Config; +import datadog.trace.core.propagation.ptags.PTagsFactory; +import java.util.HashMap; +import java.util.Map; + +/** + * Encapsulates logic related to the Service Propagation including: + * + *

    + *   - parsing and validation the x-datadog-tags header value
    + *   - dropping non _dd.p.* tags
    + *   - error handling and propagation
    + *   - concurrent updates to the sampling priority
    + *   - producing the x-datadog-tags header value
    + *   - producing meta tags to be sent to the agent
    + * 
    + */ +public abstract class PropagationTags { + + public static PropagationTags.Factory factory(Config config) { + return factory(config.getxDatadogTagsMaxLength()); + } + + public static PropagationTags.Factory factory(int datadogTagsLimit) { + return new PTagsFactory(datadogTagsLimit); + } + + public static PropagationTags.Factory factory() { + return factory(DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH); + } + + public enum HeaderType { + DATADOG, + W3C; + + private static final int numValues = HeaderType.values().length; + + public static int getNumValues() { + return numValues; + } + } + + public interface Factory { + PropagationTags empty(); + + PropagationTags fromHeaderValue(HeaderType headerType, String value); + } + + /** + * Updates the trace-level sampling priority decision if it hasn't already been made and _dd.p.dm + * tag doesn't exist. Called on the root span context. + */ + public abstract void updateTraceSamplingPriority(int samplingPriority, int samplingMechanism); + + public abstract int getSamplingPriority(); + + public abstract void updateTraceOrigin(CharSequence origin); + + public abstract CharSequence getOrigin(); + + public abstract long getTraceIdHighOrderBits(); + + public abstract void updateTraceIdHighOrderBits(long highOrderBits); + + /** + * Gets the original W3C + * tracestate header value. + * + * @return The original W3C tracestate header value. + */ + public abstract String getW3CTracestate(); + + /** + * Stores the original W3C + * tracestate header value. + * + * @param tracestate The original W3C tracestate header value. + */ + public abstract void updateW3CTracestate(String tracestate); + + /** + * Constructs a header value that includes valid propagated _dd.p.* tags and possibly a new + * sampling decision tag _dd.p.dm based on the current state. Returns null if the value length + * exceeds a configured limit or empty. + */ + public abstract String headerValue(HeaderType headerType); + + /** + * Fills a provided tagMap with valid propagated _dd.p.* tags and possibly a new sampling decision + * tags _dd.p.dm (root span only) based on the current state, or sets only an error tag if the + * header value exceeds a configured limit. + */ + public abstract void fillTagMap(Map tagMap); + + public HashMap createTagMap() { + HashMap result = new HashMap<>(); + fillTagMap(result); + return result; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/TagContextExtractor.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/TagContextExtractor.java new file mode 100644 index 0000000000..cb22ef0c08 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/TagContextExtractor.java @@ -0,0 +1,30 @@ +package datadog.trace.core.propagation; + +import datadog.trace.api.TraceConfig; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.TagContext; +import java.util.function.Supplier; + +public class TagContextExtractor implements HttpCodec.Extractor { + + private final Supplier traceConfigSupplier; + private final ThreadLocal ctxInterpreter; + + public TagContextExtractor( + final Supplier traceConfigSupplier, final ContextInterpreter.Factory factory) { + this.traceConfigSupplier = traceConfigSupplier; + this.ctxInterpreter = ThreadLocal.withInitial(factory::create); + } + + @Override + public TagContext extract(final C carrier, final AgentPropagation.ContextVisitor getter) { + ContextInterpreter interpreter = this.ctxInterpreter.get().reset(traceConfigSupplier.get()); + getter.forEachKey(carrier, interpreter); + return interpreter.build(); + } + + @Override + public void cleanup() { + ctxInterpreter.remove(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/W3CHttpCodec.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/W3CHttpCodec.java new file mode 100644 index 0000000000..76ca949e22 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/W3CHttpCodec.java @@ -0,0 +1,373 @@ +package datadog.trace.core.propagation; + +import static datadog.trace.api.TracePropagationStyle.TRACECONTEXT; +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; +import static datadog.trace.core.propagation.HttpCodec.firstHeaderValue; +import static datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +import datadog.trace.api.Config; +import datadog.trace.api.DD128bTraceId; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTags; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.api.internal.util.LongStringUtils; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.api.sampling.SamplingMechanism; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.TagContext; +import datadog.trace.core.DDSpanContext; +import java.util.Map; +import java.util.TreeMap; +import java.util.function.Supplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** A codec designed for HTTP transport via headers using W3C traceparent and tracestate headers */ +class W3CHttpCodec { + private static final Logger log = LoggerFactory.getLogger(W3CHttpCodec.class); + + static final String TRACE_PARENT_KEY = "traceparent"; + static final String TRACE_STATE_KEY = "tracestate"; + static final String OT_BAGGAGE_PREFIX = "ot-baggage-"; + private static final String E2E_START_KEY = OT_BAGGAGE_PREFIX + DDTags.TRACE_START_TIME; + + private static final int TRACE_PARENT_TID_START = 2 + 1; + private static final int TRACE_PARENT_TID_END = TRACE_PARENT_TID_START + 32; + private static final int TRACE_PARENT_SID_START = TRACE_PARENT_TID_END + 1; + private static final int TRACE_PARENT_SID_END = TRACE_PARENT_SID_START + 16; + private static final int TRACE_PARENT_FLAGS_START = TRACE_PARENT_SID_END + 1; + private static final int TRACE_PARENT_FLAGS_SAMPLED = 1; + private static final int TRACE_PARENT_LENGTH = TRACE_PARENT_FLAGS_START + 2; + + private W3CHttpCodec() { + // This class should not be created. This also makes code coverage checks happy. + } + + public static HttpCodec.Injector newInjector(Map invertedBaggageMapping) { + return new Injector(invertedBaggageMapping); + } + + private static class Injector implements HttpCodec.Injector { + + private final Map invertedBaggageMapping; + + public Injector(Map invertedBaggageMapping) { + assert invertedBaggageMapping != null; + this.invertedBaggageMapping = invertedBaggageMapping; + } + + @Override + public void inject( + final DDSpanContext context, final C carrier, final AgentPropagation.Setter setter) { + injectTraceParent(context, carrier, setter); + injectTraceState(context, carrier, setter); + injectBaggage(context, carrier, setter); + } + + private void injectTraceParent( + DDSpanContext context, C carrier, AgentPropagation.Setter setter) { + StringBuilder sb = new StringBuilder(TRACE_PARENT_LENGTH); + sb.append("00-"); + sb.append(context.getTraceId().toHexString()); + sb.append("-"); + sb.append(DDSpanId.toHexStringPadded(context.getSpanId())); + sb.append(context.getSamplingPriority() > 0 ? "-01" : "-00"); + setter.set(carrier, TRACE_PARENT_KEY, sb.toString()); + } + + private void injectTraceState( + DDSpanContext context, C carrier, AgentPropagation.Setter setter) { + PropagationTags propagationTags = context.getPropagationTags(); + String tracestate = propagationTags.headerValue(W3C); + if (tracestate != null && !tracestate.isEmpty()) { + setter.set(carrier, TRACE_STATE_KEY, tracestate); + } + } + + private void injectBaggage( + DDSpanContext context, C carrier, AgentPropagation.Setter setter) { + long e2eStart = context.getEndToEndStartTime(); + if (e2eStart > 0) { + setter.set(carrier, E2E_START_KEY, Long.toString(NANOSECONDS.toMillis(e2eStart))); + } + + for (final Map.Entry entry : context.baggageItems()) { + String header = invertedBaggageMapping.get(entry.getKey()); + header = header != null ? header : OT_BAGGAGE_PREFIX + entry.getKey(); + setter.set(carrier, header, HttpCodec.encodeBaggage(entry.getValue())); + } + } + } + + public static HttpCodec.Extractor newExtractor( + Config config, Supplier traceConfigSupplier) { + return new TagContextExtractor(traceConfigSupplier, () -> new W3CContextInterpreter(config)); + } + + private static class W3CContextInterpreter extends ContextInterpreter { + + private static final int TRACE_PARENT = 0; + private static final int TRACE_STATE = 1; + private static final int OT_BAGGAGE = 2; + private static final int E2E_START = 3; + private static final int IGNORE = -1; + + // We need to delay handling of the tracestate header until after traceparent + private String tracestateHeader = null; + private String traceparentHeader = null; + + private W3CContextInterpreter(Config config) { + super(config); + } + + @Override + public TracePropagationStyle style() { + return TRACECONTEXT; + } + + @Override + public ContextInterpreter reset(TraceConfig traceConfig) { + tracestateHeader = null; + traceparentHeader = null; + return super.reset(traceConfig); + } + + @Override + public boolean accept(String key, String value) { + if (null == key || key.isEmpty()) { + return true; + } + if (LOG_EXTRACT_HEADER_NAMES) { + log.debug("Header: {}", key); + } + String lowerCaseKey = null; + int classification = IGNORE; + char first = Character.toLowerCase(key.charAt(0)); + switch (first) { + case 'f': + if (handledForwarding(key, value)) { + return true; + } + break; + case 'o': + lowerCaseKey = toLowerCase(key); + if (E2E_START_KEY.equals(lowerCaseKey)) { + classification = E2E_START; + } else if (lowerCaseKey.startsWith(OT_BAGGAGE_PREFIX)) { + classification = OT_BAGGAGE; + } + break; + case 't': + if (TRACE_PARENT_KEY.equalsIgnoreCase(key)) { + classification = TRACE_PARENT; + } else if (TRACE_STATE_KEY.equalsIgnoreCase(key)) { + classification = TRACE_STATE; + } + break; + case 'u': + if (handledUserAgent(key, value)) { + return true; + } + break; + case 'x': + if (handledXForwarding(key, value)) { + return true; + } + break; + default: + } + + if (classification != IGNORE) { + try { + if (null != value) { + switch (classification) { + case TRACE_PARENT: + return storeTraceParent(value); + case TRACE_STATE: + return storeTraceState(value); + case E2E_START: + endToEndStartTime = extractEndToEndStartTime(firstHeaderValue(value)); + break; + case OT_BAGGAGE: + { + if (baggage.isEmpty()) { + baggage = new TreeMap<>(); + } + baggage.put( + lowerCaseKey.substring(OT_BAGGAGE_PREFIX.length()), HttpCodec.decode(value)); + } + break; + default: + } + } + } catch (RuntimeException e) { + invalidateContext(); + log.debug("Exception when extracting context", e); + return false; + } + } else { + if (handledIpHeaders(key, value)) { + return true; + } + if (handleTags(key, value)) { + return true; + } + handleMappedBaggage(key, value); + } + return true; + } + + private long extractEndToEndStartTime(String value) { + try { + return MILLISECONDS.toNanos(Long.parseLong(value)); + } catch (RuntimeException e) { + log.debug("Ignoring invalid end-to-end start time {}", value, e); + return 0; + } + } + + private boolean storeTraceParent(String value) { + String trimmed = trim(value); + if (traceparentHeader != null) { + // We should not accept multiple traceparent headers + if (log.isDebugEnabled()) { + log.debug( + "Multiple traceparent headers. Had '{}' and got '{}'", traceparentHeader, trimmed); + } + onlyTagContext(); + } else { + traceparentHeader = trimmed; + } + return true; + } + + private boolean storeTraceState(String value) { + String trimmed = trim(value); + if (!trimmed.isEmpty()) { + // Yes, this is not efficient for multiple headers, but that is hopefully not common + tracestateHeader = tracestateHeader == null ? trimmed : tracestateHeader + "," + trimmed; + } + return true; + } + + /** + * We need to delay handling of the W3C headers until the end since tracestate headers should be + * concatenated before processed, and only if there is a single valid traceparent header present + */ + @Override + protected TagContext build() { + // If there is neither a traceparent nor a tracestate header, then ignore this + if (traceparentHeader == null && tracestateHeader == null) { + onlyTagContext(); + } + if (valid && fullContext) { + try { + if (traceparentHeader == null && tracestateHeader != null) { + throw new IllegalStateException( + "Found no traceparent header but tracestate header '" + tracestateHeader + "'"); + } + // Now we know that we have at least a traceparent header + parseTraceParentHeader(traceparentHeader); + parseTraceStateHeader(tracestateHeader); + } catch (RuntimeException e) { + onlyTagContext(); + log.debug("Exception when building context", e); + } + } + return super.build(); + } + + void parseTraceParentHeader(String tp) { + int length = tp == null ? 0 : tp.length(); + if (length < TRACE_PARENT_LENGTH) { + throw new IllegalStateException("The length of traceparent '" + tp + "' is too short"); + } + long version = LongStringUtils.parseUnsignedLongHex(tp, 0, 2, true); + if (version == 255) { + throw new IllegalStateException("Illegal version number " + tp.substring(0, 2)); + } else if (version == 0 && length > TRACE_PARENT_LENGTH) { + throw new IllegalStateException("The length of traceparent '" + tp + "' is too long"); + } + DDTraceId traceId = DD128bTraceId.fromHex(tp, TRACE_PARENT_TID_START, 32, true); + if (traceId.toLong() == 0) { + throw new IllegalStateException( + "Illegal all zero 64 bit trace id " + + tp.substring(TRACE_PARENT_TID_START, TRACE_PARENT_TID_END)); + } + this.traceId = traceId; + this.spanId = DDSpanId.fromHex(tp, TRACE_PARENT_SID_START, 16, true); + if (this.spanId == 0) { + throw new IllegalStateException( + "Illegal all zero span id " + + tp.substring(TRACE_PARENT_SID_START, TRACE_PARENT_SID_END)); + } + if (version != 0 && length > TRACE_PARENT_LENGTH && tp.charAt(TRACE_PARENT_LENGTH) != '-') { + throw new IllegalStateException("Illegal character after flags in '" + tp + "'"); + } + long flags = LongStringUtils.parseUnsignedLongHex(tp, TRACE_PARENT_FLAGS_START, 2, true); + if ((flags & TRACE_PARENT_FLAGS_SAMPLED) != 0) { + this.samplingPriority = SAMPLER_KEEP; + } else { + this.samplingPriority = SAMPLER_DROP; + } + } + + void parseTraceStateHeader(String tracestate) { + if (tracestate == null || tracestate.isEmpty()) { + this.propagationTags = this.propagationTagsFactory.empty(); + } else { + this.propagationTags = this.propagationTagsFactory.fromHeaderValue(W3C, tracestate); + } + int ptagsPriority = this.propagationTags.getSamplingPriority(); + int contextPriority = this.samplingPriority; + if ((contextPriority == SAMPLER_DROP && ptagsPriority > 0) + || (contextPriority == SAMPLER_KEEP && ptagsPriority <= 0) + || ptagsPriority == PrioritySampling.UNSET) { + // Override Datadog sampling priority with W3C one + this.propagationTags.updateTraceSamplingPriority( + contextPriority, SamplingMechanism.EXTERNAL_OVERRIDE); + } else { + // Use more detailed Datadog sampling priority in context + this.samplingPriority = ptagsPriority; + } + // Use the origin + this.origin = this.propagationTags.getOrigin(); + // Ensure TraceId high-order bits match + this.propagationTags.updateTraceIdHighOrderBits(this.traceId.toHighOrderLong()); + } + + private static String trim(String input) { + if (input == null) { + return ""; + } + final int last = input.length() - 1; + if (last == 0) { + return input; + } + int start; + for (start = 0; start <= last; start++) { + char c = input.charAt(start); + if (c != '\t' && c != ' ') { + break; + } + } + int end; + for (end = last; end > start; end--) { + char c = input.charAt(end); + if (c != '\t' && c != ' ') { + break; + } + } + if (start == 0 && end == last) { + return input; + } else { + return input.substring(start, end + 1); + } + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/XRayHttpCodec.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/XRayHttpCodec.java new file mode 100644 index 0000000000..15e7d54e47 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/XRayHttpCodec.java @@ -0,0 +1,266 @@ +package datadog.trace.core.propagation; + +import static datadog.trace.api.DDTags.ORIGIN_KEY; +import static datadog.trace.api.TracePropagationStyle.XRAY; +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +import datadog.trace.api.Config; +import datadog.trace.api.DD64bTraceId; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTags; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.TracePropagationStyle; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.core.DDSpanContext; +import java.util.Map; +import java.util.TreeMap; +import java.util.function.Supplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A codec designed for AWS requests using the {@code X-Amzn-Trace-Id} tracing header. + * https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader + */ +class XRayHttpCodec { + private static final Logger log = LoggerFactory.getLogger(XRayHttpCodec.class); + + static final String X_AMZN_TRACE_ID = "X-Amzn-Trace-Id"; + + static final String ROOT = "Root"; + static final String PARENT = "Parent"; + static final String SAMPLED = "Sampled"; + static final String SELF = "Self"; + + static final String ROOT_PREFIX = ROOT + "=1-"; + static final String TRACE_ID_PADDING = "-00000000"; + static final String PARENT_PREFIX = PARENT + '='; + static final String SAMPLED_PREFIX = SAMPLED + '='; + static final String SELF_PREFIX = SELF + '='; + static final String ORIGIN_PREFIX = ORIGIN_KEY + '='; + + static final int ROOT_PREAMBLE = ROOT_PREFIX.length() + 8; // prefix plus 8-character epoch + + static final String E2E_START_KEY = DDTags.TRACE_START_TIME; + static final String E2E_START_PREFIX = E2E_START_KEY + '='; + + static final int MAX_ADDITIONAL_BYTES = 256; + + private XRayHttpCodec() { + // This class should not be created. This also makes code coverage checks happy. + } + + public static HttpCodec.Injector newInjector(Map invertedBaggageMapping) { + return new Injector(invertedBaggageMapping); + } + + private static class Injector implements HttpCodec.Injector { + + private final Map invertedBaggageMapping; + + public Injector(Map invertedBaggageMapping) { + this.invertedBaggageMapping = invertedBaggageMapping; + } + + @Override + public void inject(DDSpanContext context, C carrier, AgentPropagation.Setter setter) { + long e2eStart = context.getEndToEndStartTime(); + + StringBuilder buf = + new StringBuilder() + .append(ROOT_PREFIX) + .append( + String.format( + "%08x", + e2eStart > 0 + ? NANOSECONDS.toSeconds(e2eStart) + : MILLISECONDS.toSeconds( + context.getTrace().getTimeSource().getCurrentTimeMillis()))) + .append(TRACE_ID_PADDING) + .append(context.getTraceId().toHexStringPadded(16)) + .append(';' + PARENT_PREFIX) + .append(DDSpanId.toHexStringPadded(context.getSpanId())); + + if (context.lockSamplingPriority()) { + buf.append(';' + SAMPLED_PREFIX) + .append(convertSamplingPriority(context.getSamplingPriority())); + } + + int maxCapacity = buf.length() + MAX_ADDITIONAL_BYTES; + + CharSequence origin = context.getOrigin(); + if (origin != null) { + additionalPart(buf, ORIGIN_KEY, origin.toString(), maxCapacity); + } + if (e2eStart > 0) { + additionalPart( + buf, E2E_START_KEY, Long.toString(NANOSECONDS.toMillis(e2eStart)), maxCapacity); + } + + for (Map.Entry entry : context.baggageItems()) { + String header = invertedBaggageMapping.getOrDefault(entry.getKey(), entry.getKey()); + if (!isReserved(header)) { + additionalPart(buf, header, HttpCodec.encode(entry.getValue()), maxCapacity); + } + } + + setter.set(carrier, X_AMZN_TRACE_ID, buf.toString()); + } + + private boolean isReserved(String key) { + return ROOT.equals(key) || PARENT.equals(key) || SAMPLED.equals(key) || SELF.equals(key); + } + + private char convertSamplingPriority(int samplingPriority) { + return samplingPriority > 0 ? '1' : '0'; + } + + private void additionalPart(StringBuilder buf, String key, String value, int maxCapacity) { + if (buf.length() + key.length() + value.length() + 2 <= maxCapacity) { + buf.append(';').append(key).append('=').append(value); + } + } + } + + public static HttpCodec.Extractor newExtractor( + Config config, Supplier traceConfigSupplier) { + return new TagContextExtractor(traceConfigSupplier, () -> new XRayContextInterpreter(config)); + } + + static class XRayContextInterpreter extends ContextInterpreter { + + private XRayContextInterpreter(Config config) { + super(config); + } + + @Override + public TracePropagationStyle style() { + return XRAY; + } + + @Override + public boolean accept(String key, String value) { + if (null == key || key.isEmpty()) { + return true; + } + if (LOG_EXTRACT_HEADER_NAMES) { + log.debug("Header: {}", key); + } + try { + char first = Character.toLowerCase(key.charAt(0)); + switch (first) { + case 'x': + if (X_AMZN_TRACE_ID.equalsIgnoreCase(key)) { + handleXRayTraceHeader(this, value); + return true; + } else if (handledXForwarding(key, value)) { + return true; + } + break; + case 'f': + if (handledForwarding(key, value)) { + return true; + } + break; + case 'u': + if (handledUserAgent(key, value)) { + return true; + } + break; + default: + } + + if (handledIpHeaders(key, value)) { + return true; + } else { + handleTags(key, value); + } + + if (!baggageMapping.isEmpty()) { + String mappedKey = baggageMapping.get(toLowerCase(key)); + if (null != mappedKey) { + addBaggageItem(this, mappedKey, HttpCodec.decode(value)); + } + } + return true; + } catch (RuntimeException e) { + invalidateContext(); + log.debug("Exception when extracting context", e); + return false; + } + } + + static void handleXRayTraceHeader(ContextInterpreter interpreter, String value) { + if (null != value) { + int rootPart = value.indexOf(ROOT_PREFIX); + if (rootPart < 0 + || !value.regionMatches( + rootPart + ROOT_PREAMBLE, TRACE_ID_PADDING, 0, TRACE_ID_PADDING.length())) { + return; // header doesn't match our padded version, ignore it + } + int startPart = 0; + int length = value.length(); + while (startPart < length) { + int endPart = value.indexOf(';', startPart); + if (endPart < 0) { + endPart = length; + } + String part = value.substring(startPart, endPart).trim(); + if (part.startsWith(ROOT_PREFIX)) { + if (interpreter.traceId == null || interpreter.traceId == DDTraceId.ZERO) { + interpreter.traceId = + DD64bTraceId.fromHex(part.substring(ROOT_PREAMBLE + TRACE_ID_PADDING.length())); + } + } else if (part.startsWith(PARENT_PREFIX)) { + if (interpreter.spanId == DDSpanId.ZERO) { + interpreter.spanId = DDSpanId.fromHex(part.substring(PARENT_PREFIX.length())); + } + } else if (part.startsWith(SAMPLED_PREFIX)) { + if (interpreter.samplingPriority == PrioritySampling.UNSET) { + interpreter.samplingPriority = + convertSamplingPriority(part.charAt(SAMPLED_PREFIX.length())); + } + } else if (part.startsWith(SELF_PREFIX)) { + // Self is added by load-balancers and should be ignored + } else if (part.startsWith(ORIGIN_PREFIX)) { + interpreter.origin = part.substring(ORIGIN_PREFIX.length()); + } else if (part.startsWith(E2E_START_PREFIX)) { + interpreter.endToEndStartTime = + extractEndToEndStartTime(part.substring(E2E_START_PREFIX.length())); + } else { + int eqIndex = part.indexOf('='); + if (eqIndex > 0) { + addBaggageItem(interpreter, part.substring(0, eqIndex), part.substring(eqIndex + 1)); + } + } + startPart = endPart + 1; + } + } + } + + private static long extractEndToEndStartTime(String value) { + try { + return MILLISECONDS.toNanos(Long.parseLong(value)); + } catch (RuntimeException e) { + log.debug("Ignoring invalid end-to-end start time {}", value, e); + return 0; + } + } + + private static int convertSamplingPriority(char samplingPriority) { + return '1' == samplingPriority ? SAMPLER_KEEP : SAMPLER_DROP; + } + + private static void addBaggageItem(ContextInterpreter interpreter, String key, String value) { + if (interpreter.baggage.isEmpty()) { + interpreter.baggage = new TreeMap<>(); + } + interpreter.baggage.put(key, HttpCodec.decode(value)); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java new file mode 100644 index 0000000000..12bd59738a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java @@ -0,0 +1,186 @@ +package datadog.trace.core.propagation.ptags; + +import datadog.trace.core.propagation.PropagationTags; +import datadog.trace.core.propagation.ptags.PTagsFactory.PTags; +import datadog.trace.core.propagation.ptags.TagElement.Encoding; +import datadog.trace.relocate.api.RatelimitedLogger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.IntPredicate; +import org.slf4j.LoggerFactory; + +/** Captures configuration required for PropagationTags logic */ +final class DatadogPTagsCodec extends PTagsCodec { + private static final RatelimitedLogger log = + new RatelimitedLogger(LoggerFactory.getLogger(DatadogPTagsCodec.class), 5, TimeUnit.MINUTES); + private static final String PROPAGATION_ERROR_EXTRACT_MAX_SIZE = "extract_max_size"; + private static final String PROPAGATION_ERROR_DECODING_ERROR = "decoding_error"; + private static final char TAGS_SEPARATOR = ','; + private static final char TAG_KEY_SEPARATOR = '='; + private static final int MIN_ALLOWED_CHAR = 32; + private static final int MAX_ALLOWED_CHAR = 126; + + private final int xDatadogTagsLimit; + + DatadogPTagsCodec(int xDatadogTagsLimit) { + this.xDatadogTagsLimit = xDatadogTagsLimit; + } + + /** + * Parses a header value with next eBNF: + * + *
    +   *   tagset = ( tag, { ",", tag } ) | "";
    +   *   tag = ( identifier - space or equal ), "=", identifier;
    +   *   identifier = allowed characters, { allowed characters };
    +   *   allowed characters = ( ? ASCII characters 32-126 ? - comma );
    +   *   space or equal = " " | "=";
    +   *   comma = ",";
    +   * 
    + * + * All tags prefixed with `_dd.p.` are extracted from tagSet except for `_dd.p.upstream_services`. + * TagSet that doesn't respect the format will be dropped and a warning will be logged. + * + * @return a PropagationTags containing only _dd.p.* tags or an error if the header value is + * invalid + */ + @Override + PropagationTags fromHeaderValue(PTagsFactory tagsFactory, String value) { + if (value == null) { + return tagsFactory.empty(); + } + if (value.length() > xDatadogTagsLimit) { + // Incoming x-datadog-tags value length exceeds datadogTagsLimit + // Set _dd.propagation_error:extract_max_size + return tagsFactory.createInvalid(PROPAGATION_ERROR_EXTRACT_MAX_SIZE); + } + + List tagPairs = null; + int len = value.length(); + int tagPos = 0; + TagValue decisionMakerTagValue = null; + TagValue traceIdTagValue = null; + while (tagPos < len) { + int tagKeyEndsAt = + validateCharsUntilSeparatorOrEnd( + value, tagPos, TAG_KEY_SEPARATOR, DatadogPTagsCodec::isAllowedKeyChar); + if (tagKeyEndsAt < 0 || tagKeyEndsAt == len) { + log.warn("Invalid datadog tags header value: '{}' at {}", value, tagPos); + return tagsFactory.createInvalid(PROPAGATION_ERROR_DECODING_ERROR); + } + int tagValuePos = tagKeyEndsAt + 1; + int tagValueEndsAt = + validateCharsUntilSeparatorOrEnd( + value, tagValuePos, TAGS_SEPARATOR, DatadogPTagsCodec::isAllowedValueChar); + if (tagValueEndsAt < 0) { + log.warn("Invalid datadog tags header value: '{}' at {}", value, tagKeyEndsAt); + return tagsFactory.createInvalid(PROPAGATION_ERROR_DECODING_ERROR); + } + TagKey tagKey = TagKey.from(Encoding.DATADOG, value, tagPos, tagKeyEndsAt); + TagValue tagValue = TagValue.from(Encoding.DATADOG, value, tagValuePos, tagValueEndsAt); + if (tagKey != null) { + if (!tagKey.equals(UPSTREAM_SERVICES_DEPRECATED_TAG)) { + if (!validateTagValue(tagKey, tagValue)) { + log.warn( + "Invalid datadog tags header value: '{}' invalid tag value at {}", + value, + tagValuePos); + if (tagKey.equals(TRACE_ID_TAG)) { + return tagsFactory.createInvalid(PROPAGATION_ERROR_MALFORMED_TID + tagValue); + } + return tagsFactory.createInvalid(PROPAGATION_ERROR_DECODING_ERROR); + } + if (tagKey.equals(DECISION_MAKER_TAG)) { + decisionMakerTagValue = tagValue; + } else if (tagKey.equals(TRACE_ID_TAG)) { + traceIdTagValue = tagValue; + } else { + if (tagPairs == null) { + // This is roughly the size of a two element linked list but can hold six + tagPairs = new ArrayList<>(6); + } + tagPairs.add(tagKey); + tagPairs.add(tagValue); + } + } + } + tagPos = tagValueEndsAt + 1; + } + return tagsFactory.createValid(tagPairs, decisionMakerTagValue, traceIdTagValue); + } + + @Override + protected int estimateHeaderSize(PTags pTags) { + return pTags.getXDatadogTagsSize(); + } + + @Override + protected int appendPrefix(StringBuilder sb, PTags ptags) { + // Calculate the tag size here and return it. Don't do anything else since there is no prefix. + return ptags.getXDatadogTagsSize(); + } + + @Override + protected int appendTag(StringBuilder sb, TagElement key, TagElement value, int size) { + if (size <= xDatadogTagsLimit) { + if (sb.length() > 0) { + sb.append(TAGS_SEPARATOR); + } + sb.append(key.forType(Encoding.DATADOG)); + sb.append(TAG_KEY_SEPARATOR); + sb.append(value.forType(Encoding.DATADOG)); + } + return size; + } + + @Override + protected int appendSuffix(StringBuilder sb, PTags ptags, int size) { + return size; + } + + @Override + protected boolean isTooLarge(StringBuilder sb, int size) { + return size > xDatadogTagsLimit; + } + + @Override + protected boolean isEmpty(StringBuilder sb, int size) { + return sb.length() == 0; + } + + private static int validateCharsUntilSeparatorOrEnd( + String s, int start, char separator, IntPredicate isValid) { + int end = s.length(); + if (start >= end) { + return -1; + } + int pos = start; + char c = s.charAt(pos); + do { + if (!isValid.test(c) || c == separator) { + return -1; + } + pos++; + if (pos < end) { + c = s.charAt(pos); + // It's not allowed to have the separator as the last character so only check + // if there is something after the separator + if (pos < end - 1 && c == separator) { + break; + } + } + } while (pos < end); + + return pos; + } + + private static boolean isAllowedKeyChar(int c) { + // space (MIN_ALLOWED_CHAR) is not allowed + return c > MIN_ALLOWED_CHAR && c <= MAX_ALLOWED_CHAR && c != TAGS_SEPARATOR; + } + + private static boolean isAllowedValueChar(int c) { + return c >= MIN_ALLOWED_CHAR && c <= MAX_ALLOWED_CHAR; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsCodec.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsCodec.java new file mode 100644 index 0000000000..2379c39d36 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsCodec.java @@ -0,0 +1,212 @@ +package datadog.trace.core.propagation.ptags; + +import static datadog.trace.core.propagation.ptags.PTagsFactory.PROPAGATION_ERROR_TAG_KEY; + +import datadog.trace.core.propagation.PropagationTags; +import datadog.trace.core.propagation.ptags.PTagsFactory.PTags; +import datadog.trace.core.propagation.ptags.TagElement.Encoding; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +abstract class PTagsCodec { + private static final String PROPAGATION_ERROR_INJECT_MAX_SIZE = "inject_max_size"; + private static final String PROPAGATION_ERROR_DISABLED = "disabled"; + + protected static final TagKey DECISION_MAKER_TAG = TagKey.from("dm"); + protected static final TagKey TRACE_ID_TAG = TagKey.from("tid"); + protected static final String PROPAGATION_ERROR_MALFORMED_TID = "malformed_tid "; + protected static final String PROPAGATION_ERROR_INCONSISTENT_TID = "inconsistent_tid "; + protected static final TagKey UPSTREAM_SERVICES_DEPRECATED_TAG = TagKey.from("upstream_services"); + + static String headerValue(PTagsCodec codec, PTags ptags) { + int estimate = codec.estimateHeaderSize(ptags); + if (estimate == 0) { + return ""; + } + + // No encoding validation here because we don't allow arbitrary tag change + StringBuilder sb = new StringBuilder(estimate); + int size = codec.appendPrefix(sb, ptags); + if (!ptags.isPropagationTagsDisabled()) { + if (ptags.getDecisionMakerTagValue() != null) { + size = codec.appendTag(sb, DECISION_MAKER_TAG, ptags.getDecisionMakerTagValue(), size); + } + if (ptags.getTraceIdHighOrderBitsHexTagValue() != null) { + size = codec.appendTag(sb, TRACE_ID_TAG, ptags.getTraceIdHighOrderBitsHexTagValue(), size); + } + Iterator it = ptags.getTagPairs().iterator(); + while (it.hasNext() && !codec.isTooLarge(sb, size)) { + TagElement tagKey = it.next(); + TagElement tagValue = it.next(); + size = codec.appendTag(sb, tagKey, tagValue, size); + } + } + size = codec.appendSuffix(sb, ptags, size); + if (codec.isTooLarge(sb, size)) { + return null; + } else { + return codec.isEmpty(sb, size) ? null : sb.toString(); + } + } + + static void fillTagMap(PTags propagationTags, Map tagMap) { + int newSize = propagationTags.getXDatadogTagsSize(); + + if (newSize > propagationTags.getxDatadogTagsLimit()) { + // Outgoing x-datadog-tags value length exceeds the configured limit + // Set _dd.propagation_error:inject_max_size if the configured limit is greater than zero, + // else set _dd.propagation_error:disabled + if (propagationTags.isPropagationTagsDisabled()) { + tagMap.put(PROPAGATION_ERROR_TAG_KEY, PROPAGATION_ERROR_DISABLED); + } else { + tagMap.put(PROPAGATION_ERROR_TAG_KEY, PROPAGATION_ERROR_INJECT_MAX_SIZE); + } + return; + } + + Iterator it = propagationTags.getTagPairs().iterator(); + while (it.hasNext()) { + TagElement tagKey = it.next(); + TagElement tagValue = it.next(); + tagMap.put( + tagKey.forType(Encoding.DATADOG).toString(), + tagValue.forType(Encoding.DATADOG).toString()); + } + if (propagationTags.getDecisionMakerTagValue() != null) { + tagMap.put( + DECISION_MAKER_TAG.forType(Encoding.DATADOG).toString(), + propagationTags.getDecisionMakerTagValue().forType(Encoding.DATADOG).toString()); + } + if (propagationTags.getTraceIdHighOrderBitsHexTagValue() != null) { + tagMap.put( + TRACE_ID_TAG.forType(Encoding.DATADOG).toString(), + propagationTags + .getTraceIdHighOrderBitsHexTagValue() + .forType(Encoding.DATADOG) + .toString()); + } + if (propagationTags.getError() != null) { + tagMap.put(PROPAGATION_ERROR_TAG_KEY, propagationTags.getError()); + } + } + + static int calcXDatadogTagsSize(List tagPairs) { + int size = 0; + int pl = Encoding.DATADOG.getPrefixLength(); + boolean key = true; + for (CharSequence tagPair : tagPairs) { + if (key) { + size += pl; + } + key = !key; + size += tagPair.length(); + size += 1; // tag or key separator + } + return size == 0 ? 0 : size - 1; // exclude last separator + } + + static int calcXDatadogTagsSize(int size, TagKey tagKey, TagValue tagValue) { + if (tagValue != null) { + if (size > 0) { + // tag separator + size += 1; + } + size += tagKey.length(); + // tag key separator + size += 1; + size += tagValue.length(); + size += Encoding.DATADOG.getPrefixLength(); + } + return size; + } + + abstract PropagationTags fromHeaderValue(PTagsFactory tagsFactory, String value); + + protected abstract int estimateHeaderSize(PTags pTags); + + protected abstract int appendPrefix(StringBuilder sb, PTags ptags); + + protected abstract int appendTag(StringBuilder sb, TagElement key, TagElement value, int size); + + protected abstract int appendSuffix(StringBuilder sb, PTags ptags, int size); + + protected abstract boolean isTooLarge(StringBuilder sb, int size); + + protected abstract boolean isEmpty(StringBuilder sb, int size); + + protected static boolean validateTagValue(TagKey tagKey, TagValue tagValue) { + if (tagKey.equals(DECISION_MAKER_TAG) && !validateDecisionMakerTag(tagValue)) { + return false; + } else if (tagKey.equals(TRACE_ID_TAG) && !validateTraceId(tagValue)) { + return false; + } + return true; + } + + /** + * Validates the dm tag format with next eBNF: + * + *
    +   *   _dd.p.dm = [ service hash ], "-", sampling mechanism;
    +   *
    +   *   digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
    +   *   hexadecimal digit = digit | "a" | "b" | "c" | "d" | "e" | "f" ;
    +   *
    +   *   service hash = 10 * hexadecimal digit;
    +   *   sampling mechanism = digit, { digit };
    +   * 
    + */ + private static boolean validateDecisionMakerTag(TagValue value) { + int sepPos = value.indexOf('-'); + if (sepPos < 0) { + // missing separator + return false; + } + if (sepPos != 0 && sepPos != 10) { + // invalid service hash length + return false; + } + int samplingMechanismPos = sepPos + 1; + int len = value.length(); + if (samplingMechanismPos == len) { + // missing sampling mechanism + return false; + } + for (int i = 0; i < sepPos; i++) { + if (!isHexDigit(value.charAt(i))) { + // invalid service hash char + return false; + } + } + for (int i = samplingMechanismPos; i < len; i++) { + if (!isDigit(value.charAt(i))) { + // invalid sampling mechanism + return false; + } + } + return true; + } + + private static boolean validateTraceId(TagValue value) { + // invalid length + if (value.length() != 16) { + return false; + } + for (int i = 0; i < 16; i++) { + // invalid trace id character + if (!isHexDigit(value.charAt(i))) { + return false; + } + } + return true; + } + + protected static boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } + + protected static boolean isHexDigit(char c) { + return c >= 'a' && c <= 'f' || isDigit(c); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsFactory.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsFactory.java new file mode 100644 index 0000000000..21ab986a16 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsFactory.java @@ -0,0 +1,317 @@ +package datadog.trace.core.propagation.ptags; + +import static datadog.trace.core.propagation.PropagationTags.HeaderType.DATADOG; +import static datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; +import static datadog.trace.core.propagation.ptags.PTagsCodec.DECISION_MAKER_TAG; +import static datadog.trace.core.propagation.ptags.PTagsCodec.TRACE_ID_TAG; + +import datadog.trace.api.internal.util.LongStringUtils; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.api.sampling.SamplingMechanism; +import datadog.trace.core.propagation.PropagationTags; +import datadog.trace.core.propagation.PropagationTags.HeaderType; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import javax.annotation.Nonnull; + +public class PTagsFactory implements PropagationTags.Factory { + static final String PROPAGATION_ERROR_TAG_KEY = "_dd.propagation_error"; + + private final EnumMap DEC_ENC_MAP = new EnumMap<>(HeaderType.class); + + private final int xDatadogTagsLimit; + + public PTagsFactory(int xDatadogTagsLimit) { + this.xDatadogTagsLimit = xDatadogTagsLimit; + DEC_ENC_MAP.put(DATADOG, new DatadogPTagsCodec(xDatadogTagsLimit)); + DEC_ENC_MAP.put(W3C, new W3CPTagsCodec()); + } + + boolean isPropagationTagsDisabled() { + return xDatadogTagsLimit <= 0; + } + + int getxDatadogTagsLimit() { + return xDatadogTagsLimit; + } + + PTagsCodec getDecoderEncoder(@Nonnull HeaderType headerType) { + return DEC_ENC_MAP.get(headerType); + } + + @Override + public final PropagationTags empty() { + return createValid(null, null, null); + } + + @Override + public final PropagationTags fromHeaderValue(@Nonnull HeaderType headerType, String value) { + return DEC_ENC_MAP.get(headerType).fromHeaderValue(this, value); + } + + PropagationTags createValid( + List tagPairs, TagValue decisionMakerTagValue, TagValue traceIdTagValue) { + return new PTags(this, tagPairs, decisionMakerTagValue, traceIdTagValue); + } + + PropagationTags createInvalid(String error) { + return PTags.withError(this, error); + } + + static class PTags extends PropagationTags { + private static final String EMPTY = ""; + + protected final PTagsFactory factory; + + // tags that don't require any modifications and propagated as-is + private final List tagPairs; + + private final boolean canChangeDecisionMaker; + + // extracted decision maker tag for easier updates + private volatile TagValue decisionMakerTagValue; + + // xDatadogTagsSize of the tagPairs, does not include the decision maker tag + private volatile int xDatadogTagsSize = -1; + + private volatile int samplingPriority; + private volatile CharSequence origin; + private volatile String[] headerCache = null; + /** The high-order 64 bits of the trace id. */ + private volatile long traceIdHighOrderBits; + /** + * The zero-padded lower-case 16 character hexadecimal representation of the high-order 64 bits + * of the trace id, wrapped into a {@link TagValue}, null if not set. + */ + private volatile TagValue traceIdHighOrderBitsHexTagValue; + /** + * The original W3C tracestate + * header value. + */ + protected volatile String tracestate; + /** + * The {@link PTagsFactory#PROPAGATION_ERROR_TAG_KEY propagation tag error} value, {@code null + * if no error while parsing header}. + */ + protected volatile String error; + + public PTags( + PTagsFactory factory, + List tagPairs, + TagValue decisionMakerTagValue, + TagValue traceIdTagValue) { + this(factory, tagPairs, decisionMakerTagValue, traceIdTagValue, PrioritySampling.UNSET, null); + } + + PTags( + PTagsFactory factory, + List tagPairs, + TagValue decisionMakerTagValue, + TagValue traceIdTagValue, + int samplingPriority, + CharSequence origin) { + assert tagPairs == null || tagPairs.size() % 2 == 0; + this.factory = factory; + this.tagPairs = tagPairs; + this.canChangeDecisionMaker = decisionMakerTagValue == null; + this.decisionMakerTagValue = decisionMakerTagValue; + this.samplingPriority = samplingPriority; + this.origin = origin; + if (traceIdTagValue != null) { + CharSequence traceIdHighOrderBitsHex = traceIdTagValue.forType(TagElement.Encoding.DATADOG); + this.traceIdHighOrderBits = + LongStringUtils.parseUnsignedLongHex( + traceIdHighOrderBitsHex, 0, traceIdHighOrderBitsHex.length(), true); + } + this.traceIdHighOrderBitsHexTagValue = traceIdTagValue; + this.error = null; + } + + static PTags withError(PTagsFactory factory, String error) { + PTags pTags = new PTags(factory, null, null, null, PrioritySampling.UNSET, null); + pTags.error = error; + return pTags; + } + + @Override + public void updateTraceSamplingPriority(int samplingPriority, int samplingMechanism) { + if (samplingPriority != PrioritySampling.UNSET && canChangeDecisionMaker + || samplingMechanism == SamplingMechanism.EXTERNAL_OVERRIDE) { + if (this.samplingPriority != samplingPriority) { + // This should invalidate any cached w3c header + clearCachedHeader(W3C); + } + this.samplingPriority = samplingPriority; + if (samplingPriority > 0) { + // TODO should try to keep the old sampling mechanism if we override the value? + if (samplingMechanism == SamplingMechanism.EXTERNAL_OVERRIDE) { + // There is no specific value for the EXTERNAL_OVERRIDE, so say that it's the DEFAULT + samplingMechanism = SamplingMechanism.DEFAULT; + } + // Protect against possible SamplingMechanism.UNKNOWN (-1) that doesn't comply with the + // format + if (samplingMechanism >= 0) { + TagValue newDM = TagValue.from("-" + samplingMechanism); + if (!newDM.equals(decisionMakerTagValue)) { + // This should invalidate any cached w3c and datadog header + clearCachedHeader(DATADOG); + clearCachedHeader(W3C); + } + decisionMakerTagValue = newDM; + } + } else { + // Drop the decision maker tag + if (decisionMakerTagValue != null) { + // This should invalidate any cached w3c and datadog header + clearCachedHeader(DATADOG); + clearCachedHeader(W3C); + } + decisionMakerTagValue = null; + } + } + } + + @Override + public int getSamplingPriority() { + return samplingPriority; + } + + @Override + public void updateTraceOrigin(CharSequence origin) { + // TODO we should really have UTF8ByteStrings for the regular ones + CharSequence existing = this.origin; + if (Objects.equals(existing, origin)) { + return; + } + // Invalidate any cached w3c header + clearCachedHeader(W3C); + this.origin = TagValue.from(origin); + } + + @Override + public CharSequence getOrigin() { + return origin; + } + + @Override + public long getTraceIdHighOrderBits() { + return traceIdHighOrderBits; + } + + public void updateTraceIdHighOrderBits(long highOrderBits) { + if (traceIdHighOrderBits != highOrderBits) { + traceIdHighOrderBits = highOrderBits; + traceIdHighOrderBitsHexTagValue = + highOrderBits == 0 + ? null + : TagValue.from(LongStringUtils.toHexStringPadded(highOrderBits, 16)); + clearCachedHeader(DATADOG); + } + } + + @Override + @SuppressWarnings("StringEquality") + @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ") + public String headerValue(HeaderType headerType) { + String header = getCachedHeader(headerType); + if (header == null) { + header = PTagsCodec.headerValue(factory.getDecoderEncoder(headerType), this); + if (header != null) { + setCachedHeader(headerType, header); + } else { + // We can still cache the fact that we got back null + setCachedHeader(headerType, EMPTY); + } + } + if (header == EMPTY) { + return null; + } + return header; + } + + @Override + public void fillTagMap(Map tagMap) { + PTagsCodec.fillTagMap(this, tagMap); + } + + private String getCachedHeader(HeaderType headerType) { + String[] cache = headerCache; + if (cache == null) { + return null; + } + return cache[headerType.ordinal()]; + } + + private void setCachedHeader(HeaderType headerType, String header) { + String[] cache = headerCache; + if (cache == null) { + cache = headerCache = new String[HeaderType.getNumValues()]; + } + cache[headerType.ordinal()] = header; + } + + private void clearCachedHeader(HeaderType headerType) { + if (headerType == DATADOG) { + invalidateXDatadogTagsSize(); + } + String[] cache = headerCache; + if (cache == null) { + return; + } + cache[headerType.ordinal()] = null; + } + + int getxDatadogTagsLimit() { + return factory.getxDatadogTagsLimit(); + } + + boolean isPropagationTagsDisabled() { + return factory.isPropagationTagsDisabled(); + } + + List getTagPairs() { + return tagPairs == null ? Collections.emptyList() : tagPairs; + } + + private void invalidateXDatadogTagsSize() { + this.xDatadogTagsSize = -1; + } + + int getXDatadogTagsSize() { + int size = xDatadogTagsSize; + if (size == -1) { + size = PTagsCodec.calcXDatadogTagsSize(getTagPairs()); + size = PTagsCodec.calcXDatadogTagsSize(size, DECISION_MAKER_TAG, decisionMakerTagValue); + size = PTagsCodec.calcXDatadogTagsSize(size, TRACE_ID_TAG, traceIdHighOrderBitsHexTagValue); + xDatadogTagsSize = size; + } + return size; + } + + TagValue getTraceIdHighOrderBitsHexTagValue() { + return traceIdHighOrderBitsHexTagValue; + } + + TagValue getDecisionMakerTagValue() { + return decisionMakerTagValue; + } + + @Override + public String getW3CTracestate() { + return this.tracestate; + } + + @Override + public void updateW3CTracestate(String tracestate) { + this.tracestate = tracestate; + } + + String getError() { + return this.error; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagElement.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagElement.java new file mode 100644 index 0000000000..8805e86d04 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagElement.java @@ -0,0 +1,40 @@ +package datadog.trace.core.propagation.ptags; + +abstract class TagElement implements CharSequence { + public enum Encoding { + DATADOG("_dd.p."), + W3C("t."); + + private final String prefix; + + Encoding(String prefix) { + this.prefix = prefix; + } + + public String getPrefix() { + return prefix; + } + + public int getPrefixLength() { + return prefix.length(); + } + + private static final Encoding[] cachedValues; + private static final int numValues; + + static { + cachedValues = values(); + numValues = cachedValues.length; + } + + static Encoding[] getCachedValues() { + return cachedValues; + } + + static int getNumValues() { + return numValues; + } + } + + abstract CharSequence forType(Encoding encoding); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagKey.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagKey.java new file mode 100644 index 0000000000..75b5276fdd --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagKey.java @@ -0,0 +1,146 @@ +package datadog.trace.core.propagation.ptags; + +import datadog.trace.api.cache.DDCaches; +import datadog.trace.api.cache.DDPartialKeyCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class TagKey extends TagElement { + private static final Logger log = LoggerFactory.getLogger(TagKey.class); + private static final DDPartialKeyCache keyCache = + DDCaches.newFixedSizePartialKeyCache(64); + + static TagKey from(String s) { + if (s == null || isHeaderInvalid(s, 0, s.length(), null)) { + if (log.isDebugEnabled()) { + log.debug("Invalid header s: {}", s); + } + return null; + } + return keyCache.computeIfAbsent( + s, 0, s.length(), TagKey::hash, TagKey::compare, TagKey::produce); + } + + static TagKey from(Encoding encoding, String s) { + if (isHeaderInvalid(encoding, s)) { + if (log.isDebugEnabled()) { + log.debug("Invalid header h: {} s: {}", encoding, s); + } + return null; + } + int pl = encoding.getPrefixLength(); + return keyCache.computeIfAbsent( + s, pl, s.length(), TagKey::hash, TagKey::compare, TagKey::produce); + } + + static TagKey from(Encoding encoding, String s, int start, int end) { + if (isHeaderInvalid(encoding, s, start, end)) { + if (log.isDebugEnabled()) { + log.debug("Invalid header h: {} s: {} b: {} e: {}", encoding, s, start, end); + } + return null; + } + int pl = encoding.getPrefixLength(); + return keyCache.computeIfAbsent( + s, start + pl, end, TagKey::hash, TagKey::compare, TagKey::produce); + } + + private static boolean isHeaderInvalid(Encoding encoding, String s) { + if (encoding == null || s == null) { + return true; + } + return isHeaderInvalid(encoding, s, 0, s.length()); + } + + private static boolean isHeaderInvalid(Encoding encoding, String s, int start, int end) { + if (encoding == null || s == null) { + return true; + } + return isHeaderInvalid(s, start, end, encoding.getPrefix()); + } + + private static boolean isHeaderInvalid(String s, int start, int end, String prefix) { + int pl = prefix == null ? 0 : prefix.length(); + int sl = s.length(); + return start < 0 + || end <= 0 + || (end - start) <= pl + || sl <= pl + || sl < end + || (prefix != null && !s.startsWith(prefix, start)); + } + + private static int hash(String s, int start, int end) { + int h = 0; + end = Integer.min(s.length(), end); + if (start >= 0 && end > 0) { + for (int i = start; i < end; i++) { + h = 31 * h + s.charAt(i); + } + } + return h; + } + + private static boolean compare(String s, int start, int end, TagKey tagKey) { + end = Integer.min(s.length(), end); + if (start < 0 || end < 0 || end - start != tagKey.length()) { + return false; + } + boolean eq = true; + for (int i = start, j = 0; eq && i < end; i++, j++) { + eq = s.charAt(i) == tagKey.charAt(j); + } + return eq; + } + + private static TagKey produce(String s, int hash, int start, int end) { + return new TagKey(s, start, end); + } + + private final String none; + private final String[] keys = new String[Encoding.getNumValues()]; + + TagKey(String s, int start, int end) { + none = (start == 0 && end == s.length()) ? s : s.substring(start, end); + for (Encoding p : Encoding.getCachedValues()) { + keys[p.ordinal()] = p.getPrefix() + none; + } + } + + CharSequence forType(Encoding encoding) { + return keys[encoding.ordinal()]; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TagKey tagKey = (TagKey) o; + return none.equals(tagKey.none); + } + + @Override + public int hashCode() { + return none.hashCode(); + } + + @Override + public String toString() { + return none; + } + + @Override + public int length() { + return none.length(); + } + + @Override + public char charAt(int index) { + return none.charAt(index); + } + + @Override + public CharSequence subSequence(int start, int end) { + return none.subSequence(start, end); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagValue.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagValue.java new file mode 100644 index 0000000000..8c1d6412fe --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagValue.java @@ -0,0 +1,216 @@ +package datadog.trace.core.propagation.ptags; + +import datadog.trace.api.cache.DDCaches; +import datadog.trace.api.cache.DDPartialKeyCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class TagValue extends TagElement { + private static final Logger log = LoggerFactory.getLogger(TagValue.class); + private static final DDPartialKeyCache valueCache = + DDCaches.newFixedSizePartialKeyCache(128); + private static final int DD_SOURCE = Encoding.DATADOG.ordinal(); + + static TagValue from(CharSequence s) { + return from(Encoding.DATADOG, s); + } + + static TagValue from(Encoding encoding, CharSequence s) { + return from(encoding, s, s == null ? -1 : 0, s == null ? -1 : s.length()); + } + + static TagValue from(Encoding encoding, CharSequence s, int start, int end) { + if (s == null || isValueInvalid(s, start, end)) { + if (log.isDebugEnabled()) { + log.debug("Invalid header h: {} s: {} b: {} e: {}", encoding, s, start, end); + } + return null; + } + if (encoding == Encoding.W3C) { + return valueCache.computeIfAbsent( + s, start, end, TagValue::hashW3C, TagValue::compareW3C, TagValue::produceW3C); + } else { + return valueCache.computeIfAbsent( + s, start, end, TagValue::hashDD, TagValue::compareDD, TagValue::produceDD); + } + } + + private static boolean isValueInvalid(CharSequence s, int start, int end) { + return start < 0 || end <= 0 || s.length() < end; + } + + private static int hashDD(CharSequence s, int start, int end) { + return hash(TagValue::convertDDtoW3C, s, start, end); + } + + private static int hashW3C(CharSequence s, int start, int end) { + return hash(TagValue::identity, s, start, end); + } + + private static int hash(CharConverter converter, CharSequence s, int start, int end) { + int h = 0; + end = Integer.min(s.length(), end); + if (start >= 0 && end > 0) { + for (int i = start; i < end; i++) { + h = 31 * h + converter.convert(s.charAt(i)); + } + } + return h; + } + + private static boolean compareDD(CharSequence s, int start, int end, TagValue tagValue) { + return compare(TagValue::identity, s, start, end, tagValue); + } + + private static boolean compareW3C(CharSequence s, int start, int end, TagValue tagValue) { + return compare(TagValue::convertW3CtoDD, s, start, end, tagValue); + } + + private static boolean compare( + CharConverter converter, CharSequence s, int start, int end, TagValue tagValue) { + end = Integer.min(s.length(), end); + if (start < 0 || end < 0 || end - start != tagValue.length()) { + return false; + } + boolean eq = true; + for (int i = start, j = 0; eq && i < end; i++, j++) { + eq = converter.convert(s.charAt(i)) == tagValue.charAt(j); + } + return eq; + } + + private static TagValue produceDD(CharSequence s, int hash, int start, int end) { + return new TagValue(Encoding.DATADOG, hash, s, start, end); + } + + private static TagValue produceW3C(CharSequence s, int hash, int start, int end) { + return new TagValue(Encoding.W3C, hash, s, start, end); + } + + private interface CharConverter { + char convert(char c); + } + + private static char convertDDtoW3C(char c) { + if (c == ',' || c == ';' || c == '~') { + return '_'; + } else if (c == '=') { + return '~'; + } + return c; + } + + private static char identity(char c) { + return c; + } + + private static char convertW3CtoDD(char c) { + if (c == '~') { + return '='; + } + return c; + } + + private final CharSequence[] values = new CharSequence[Encoding.getNumValues()]; + private final int source; + private final int hash; + + TagValue(Encoding encoding, int hash, CharSequence s, int start, int end) { + this.source = encoding.ordinal(); + this.hash = hash; + values[source] = + (start == 0 && end == s.length()) + ? s + : new StringBuilder(end - start).append(s, start, end).toString(); + } + + CharSequence forType(Encoding encoding) { + int ordinal = encoding.ordinal(); + CharSequence cs = values[ordinal]; + if (cs == null) { + CharSequence from = values[source]; + int len = from.length(); + CharConverter cc = source == DD_SOURCE ? TagValue::convertDDtoW3C : TagValue::convertW3CtoDD; + StringBuilder sb = null; + for (int i = 0; i < len; i++) { + char c = from.charAt(i); + char tc = cc.convert(c); + if (tc != c && sb == null) { + sb = new StringBuilder(len); + sb.append(from, 0, i); + } + if (sb != null) { + sb.append(tc); + } + } + cs = values[ordinal] = sb == null ? from : sb.toString(); + } + return cs; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TagValue ov = (TagValue) o; + if (hash != ov.hash) return false; + CharSequence cst = values[source]; + CharSequence cso = ov.values[ov.source]; + int len = cst.length(); + if (len != cso.length()) return false; + if (source == ov.source) { + for (int i = 0; i < len; i++) { + if (cst.charAt(i) != cso.charAt(i)) return false; + } + } else { + CharConverter cct = source == DD_SOURCE ? TagValue::identity : TagValue::convertW3CtoDD; + CharConverter cco = ov.source == DD_SOURCE ? TagValue::identity : TagValue::convertW3CtoDD; + for (int i = 0; i < len; i++) { + if (cct.convert(cst.charAt(i)) != cco.convert(cso.charAt(i))) return false; + } + } + return true; + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public String toString() { + return values[source].toString(); + } + + @Override + public int length() { + return values[source].length(); + } + + @Override + public char charAt(int index) { + if (source == DD_SOURCE) { + return values[source].charAt(index); + } else { + return convertW3CtoDD(values[source].charAt(index)); + } + } + + @Override + public CharSequence subSequence(int start, int end) { + return values[source].subSequence(start, end); + } + + public int indexOf(char c) { + c = source == DD_SOURCE ? c : convertDDtoW3C(c); + CharSequence cs = values[source]; + int len = cs.length(); + int index = -1; + for (int i = 0; i < len; i++) { + if (cs.charAt(i) == c) { + index = i; + } + } + return index; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java new file mode 100644 index 0000000000..f3fd57efcc --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java @@ -0,0 +1,745 @@ +package datadog.trace.core.propagation.ptags; + +import static datadog.trace.api.internal.util.LongStringUtils.toHexStringPadded; + +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.core.propagation.PropagationTags; +import datadog.trace.core.propagation.ptags.PTagsFactory.PTags; +import datadog.trace.core.propagation.ptags.TagElement.Encoding; +import datadog.trace.relocate.api.RatelimitedLogger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.IntPredicate; +import org.slf4j.LoggerFactory; + +public class W3CPTagsCodec extends PTagsCodec { + private static final RatelimitedLogger log = + new RatelimitedLogger(LoggerFactory.getLogger(W3CPTagsCodec.class), 5, TimeUnit.MINUTES); + + private static final int MAX_HEADER_SIZE = 256; + private static final String DATADOG_MEMBER_KEY = "dd="; + private static final int EMPTY_SIZE = DATADOG_MEMBER_KEY.length(); // 3 + private static final char MEMBER_SEPARATOR = ','; + private static final char ELEMENT_SEPARATOR = ';'; + private static final char KEY_VALUE_SEPARATOR = ':'; + private static final int MIN_ALLOWED_CHAR = 32; + private static final int MAX_ALLOWED_CHAR = 126; + private static final int MAX_MEMBER_COUNT = 32; + + @Override + PropagationTags fromHeaderValue(PTagsFactory tagsFactory, String value) { + if (value == null || value.isEmpty()) { + return tagsFactory.empty(); + } + + int len = value.length(); + // Skip over leading whitespace and empty member list elements + int firstMemberStart = findNextMember(value, 0); + if (firstMemberStart == len) { + return tagsFactory.empty(); + } + + // Validate the whole tracestate and figure out where the dd member key and value are located + int memberStart = firstMemberStart; + int ddMemberStart = -1; // dd member start position (inclusive) + int ddMemberValueStart = -1; // dd member value start position (inclusive) + int ddMemberValueEnd = -1; // dd member value end position including OWS (exclusive) + int memberIndex = 0; + int ddMemberIndex = -1; + while (memberStart < len) { + if (memberIndex == MAX_MEMBER_COUNT) { + // TODO should we return one with an error? + // TODO should we try to pick up the `dd` member anyway? + return tagsFactory.empty(); + } + if (ddMemberIndex == -1 && value.startsWith(DATADOG_MEMBER_KEY, memberStart)) { + ddMemberStart = memberStart; + ddMemberIndex = memberIndex; + } + // Validate the member key + int pos = validateMemberKey(value, memberStart); + if (pos < 0) { + // TODO should we return one with an error? + return tagsFactory.empty(); + } + if (ddMemberValueStart == -1 && ddMemberIndex != -1) { + ddMemberValueStart = pos; + } + pos = validateMemberValue(value, pos); + if (pos < 0) { + // TODO should we return one with an error? + return tagsFactory.empty(); + } + if (ddMemberValueEnd == -1 && ddMemberIndex != -1) { + ddMemberValueEnd = pos; + } + memberStart = findNextMember(value, pos); + if (memberStart < 0) { + // TODO should we return one with an error? + return tagsFactory.empty(); + } + memberIndex++; + } + + if (ddMemberIndex == -1) { + // There was no dd member, so create an empty one with the _suffix_ + return empty(tagsFactory, value); + } + + List tagPairs = null; + int tagPos = ddMemberValueStart; + int samplingPriority = PrioritySampling.UNSET; + CharSequence origin = null; + TagValue decisionMakerTagValue = null; + TagValue traceIdTagValue = null; + int maxUnknownSize = 0; + while (tagPos < ddMemberValueEnd) { + int tagKeyEndsAt = + validateCharsUntilSeparatorOrEnd( + value, + tagPos, + ddMemberValueEnd, + KEY_VALUE_SEPARATOR, + false, + W3CPTagsCodec::isAllowedKeyChar); + if (tagKeyEndsAt < 0 || tagKeyEndsAt == ddMemberValueEnd) { + log.warn("Invalid datadog tags header value: '{}' at {}", value, tagPos); + // TODO drop parts? + return empty(tagsFactory, value, firstMemberStart, ddMemberStart, ddMemberValueEnd); + } + int tagValuePos = tagKeyEndsAt + 1; + int tagValueEndsAt = + validateCharsUntilSeparatorOrEnd( + value, + tagValuePos, + ddMemberValueEnd, + ELEMENT_SEPARATOR, + true, + W3CPTagsCodec::isAllowedValueChar); + if (tagValueEndsAt < 0) { + log.warn("Invalid datadog tags header value: '{}' at {}", value, tagKeyEndsAt); + // TODO drop parts? + return empty(tagsFactory, value, firstMemberStart, ddMemberStart, ddMemberValueEnd); + } + int nextTagPos = tagValueEndsAt + 1; + if (tagValueEndsAt == ddMemberValueEnd) { + tagValueEndsAt = stripTrailingOWC(value, tagValuePos, tagValueEndsAt); + } + TagKey tagKey = TagKey.from(Encoding.W3C, value, tagPos, tagKeyEndsAt); + if (tagKey != null) { + TagValue tagValue = TagValue.from(Encoding.W3C, value, tagValuePos, tagValueEndsAt); + if (!tagKey.equals(UPSTREAM_SERVICES_DEPRECATED_TAG)) { + if (!validateTagValue(tagKey, tagValue)) { + log.warn( + "Invalid datadog tags header value: '{}' invalid tag value at {}", + value, + tagValuePos); + if (tagKey.equals(TRACE_ID_TAG)) { + return tagsFactory.createInvalid(PROPAGATION_ERROR_MALFORMED_TID + tagValue); + } + // TODO drop parts? + return empty(tagsFactory, value, firstMemberStart, ddMemberStart, ddMemberValueEnd); + } + if (tagKey.equals(DECISION_MAKER_TAG)) { + decisionMakerTagValue = tagValue; + } else if (tagKey.equals(TRACE_ID_TAG)) { + traceIdTagValue = tagValue; + } else { + if (tagPairs == null) { + // This is roughly the size of a two element linked list but can hold six + tagPairs = new ArrayList<>(6); + } + tagPairs.add(tagKey); + tagPairs.add(tagValue); + } + } + } else { + // This was not a propagating tag, so check if we know it + int keyLength = tagKeyEndsAt - tagPos; + char c = value.charAt(tagPos); + if (keyLength == 1 && c == 's') { + samplingPriority = validateSamplingPriority(value, tagValuePos, tagValueEndsAt); + } else if (keyLength == 1 && c == 'o') { + origin = TagValue.from(Encoding.W3C, value, tagValuePos, tagValueEndsAt); + } else { + if (maxUnknownSize != 0) { + maxUnknownSize++; // delimiter + } + maxUnknownSize += (tagValueEndsAt - tagPos); + } + } + tagPos = nextTagPos; + } + return new W3CPTags( + tagsFactory, + tagPairs, + decisionMakerTagValue, + traceIdTagValue, + samplingPriority, + origin, + value, + firstMemberStart, + ddMemberStart, + ddMemberValueEnd, + maxUnknownSize); + } + + @Override + protected int estimateHeaderSize(PTags pTags) { + int size = EMPTY_SIZE + 1; // 'dd=' and delimiter; + // Yes, this is a bit much, but better safe than sorry + size += pTags.getXDatadogTagsSize(); + if (pTags.getOrigin() != null) { + size += pTags.getOrigin().length() + 3; // 'o:' + delimiter + } + if (pTags.getSamplingPriority() != PrioritySampling.UNSET) { + size += 5; // 's:-?[0-9]' + delimiter + } + if (pTags instanceof W3CPTags) { + W3CPTags w3CPTags = (W3CPTags) pTags; + size += w3CPTags.maxUnknownSize; + if (w3CPTags.ddMemberStart != -1) { + size += + (w3CPTags.tracestate.length() - (w3CPTags.ddMemberValueEnd - w3CPTags.ddMemberStart)); + } + } else if (pTags.tracestate != null) { + // We assume there is no Datadog list-member + size += pTags.tracestate.length(); + } + return size; + } + + @Override + protected int appendPrefix(StringBuilder sb, PTags ptags) { + sb.append(DATADOG_MEMBER_KEY); + // Append sampling priority (s) + if (ptags.getSamplingPriority() != PrioritySampling.UNSET) { + sb.append("s:"); + sb.append(ptags.getSamplingPriority()); + } + // Append origin (o) + CharSequence origin = ptags.getOrigin(); + if (origin != null) { + if (sb.length() > EMPTY_SIZE) { + sb.append(';'); + } + sb.append("o:"); + if (origin instanceof TagValue) { + sb.append(((TagValue) origin).forType(Encoding.W3C)); + } else { + sb.append(origin); + } + } + return sb.length(); + } + + @Override + protected int appendTag(StringBuilder sb, TagElement key, TagElement value, int size) { + return appendTag(sb, key, value, Encoding.W3C, size); + } + + @Override + protected int appendSuffix(StringBuilder sb, PTags ptags, int size) { + // If there is room for appending unknown from W3CPTags + if (size < MAX_HEADER_SIZE && ptags instanceof W3CPTags) { + W3CPTags w3cPTags = (W3CPTags) ptags; + size = cleanUpAndAppendUnknown(sb, w3cPTags, size); + } + // Check empty Datadog list-member only tracestate + if (size == EMPTY_SIZE) { + // If we haven't written anything but the 'dd=', then reset the StringBuilder + sb.setLength(0); + size = 0; + } + // Append all other non-Datadog list-members + int newSize = cleanUpAndAppendSuffix(sb, ptags, size); + if (newSize != size) { + // We don't care about the total size in bytes here, but only the fact that we added something + // that should be returned + size = Math.max(size, EMPTY_SIZE + 1); + } + return size; + } + + @Override + protected boolean isTooLarge(StringBuilder sb, int size) { + return size > MAX_HEADER_SIZE; + } + + @Override + protected boolean isEmpty(StringBuilder sb, int size) { + return size <= EMPTY_SIZE; + } + + private int appendTag( + StringBuilder sb, TagElement key, TagElement value, Encoding encoding, int size) { + if (size >= MAX_HEADER_SIZE) { + return size; + } + int validSize = size; + if (size > EMPTY_SIZE) { + sb.append(ELEMENT_SEPARATOR); + size++; + } + CharSequence s = key.forType(encoding); + sb.append(s); + size += s.length(); + sb.append(KEY_VALUE_SEPARATOR); + size++; + s = value.forType(encoding); + sb.append(s); + size += s.length(); + if (size > MAX_HEADER_SIZE) { + sb.setLength(validSize); + size = validSize; + } + return size; + } + + private static int validateCharsUntilSeparatorOrEnd( + String s, int start, int end, char separator, boolean allowOWC, IntPredicate isValid) { + if (start >= end) { + return -1; + } + int pos = start; + char c = s.charAt(pos); + boolean definitelyOWC = false; + do { + if (allowOWC && isOWC(c)) { + if (c == '\t') { + definitelyOWC = true; + } + } else { + if (definitelyOWC || !isValid.test(c) || c == separator) { + return -1; + } + } + pos++; + if (pos < end) { + c = s.charAt(pos); + // It's not allowed to have the separator as the last character so only check + // if there is something after the separator + if (pos < end - 1 && c == separator) { + break; + } + } + } while (pos < end); + + return pos; + } + + private static boolean isAllowedKeyChar(int c) { + // We already know that the segments have been validated against the valid chars for + // the general tracestate header + return c > MIN_ALLOWED_CHAR && c <= MAX_ALLOWED_CHAR && c != KEY_VALUE_SEPARATOR; + } + + private static boolean isAllowedValueChar(int c) { + // We already know that the segments have been validated against the valid chars for + // the general tracestate header + return c >= MIN_ALLOWED_CHAR && c <= MAX_ALLOWED_CHAR; + } + + private static int validateSamplingPriority(String original, int start, int end) { + try { + return parseIntDecimal(original, start, end); + } catch (Exception ignored) { + return PrioritySampling.UNSET; + } + } + + // Integer.parseInt(s, start, end, radix) is only available from Java9+, so do it by hand + private static int parseIntDecimal(String original, int start, int end) + throws NumberFormatException { + if (start < 0 || start > end || end > original.length()) { + throw new IndexOutOfBoundsException(); + } + + boolean negative = false; + int i = start; + int limit = -Integer.MAX_VALUE; + + if (i < end) { + int firstChar = original.charAt(i); + if (firstChar < '0') { + if (firstChar == '-') { + negative = true; + limit = Integer.MIN_VALUE; + } else if (firstChar != '+') { + throw new NumberFormatException(original); + } + i++; + if (i == end) { + // There needs to be something after the +/- + throw new NumberFormatException(original); + } + } + int multmin = limit / 10; + int result = 0; + while (i < end) { + // Accumulating negatively avoids surprises near MAX_VALUE + int digit = original.charAt(i) - '0'; + if (digit < 0 || digit > 9 || result < multmin) { + throw new NumberFormatException(original); + } + result *= 10; + if (result < limit + digit) { + throw new NumberFormatException(original); + } + i++; + result -= digit; + } + return negative ? result : -result; + } else { + throw new NumberFormatException(""); + } + } + + // This is The Fine Specification for the member key https://www.w3.org/TR/trace-context/#key + private static int validateMemberKey(String original, int start) { + int end = original.length(); + if (start < 0 || start >= end) { + return -1; + } + boolean multi = false; + int length = 1; + int pos = start; + for (; pos < end; pos++, length++) { + if (length > 242) { + if (multi) { + // We're beyond the length of the allowed tenant id and @ delimiter + return -1; + } else if (length > 257) { + // We're beyond the length of the allowed simple key and = delimiter + return -1; + } + } + char c = original.charAt(pos); + if (isLcAlpha(c)) { + continue; + } + if (isDigit(c)) { + if (length == 1) { + multi = true; + } + continue; + } + if (length == 1) { + // The member key can only start with lower case alpha or a number + return -1; + } + if (isValidExtra(c)) { + continue; + } + if (c == '=') { + if (multi) { + // If the member key started with a number then it's a multi tenant key and must have an @ + return -1; + } else { + pos++; + break; + } + } + if (c == '@') { + if (length > 242) { + // We're beyond the length of the allowed tenant id and @ delimiter + return -1; + } + multi = true; + pos++; + break; + } + return -1; + } + + if (multi) { + // Validate the multi tenant system id part + length = 1; + for (; pos < end; pos++, length++) { + if (length > 15) { + // We're beyond the length of the allowed system id and = delimiter + return -1; + } + char c = original.charAt(pos); + if (isLcAlpha(c)) { + continue; + } + if (length == 1) { + // The system id can only start with lower case alpha + return -1; + } + if (isDigit(c) || isValidExtra(c)) { + continue; + } + if (c == '=') { + pos++; + break; + } + } + } + + if (pos >= end) { + // There needs to be something after the equals sign + return -1; + } + + return pos; + } + + // This is The Fine Specification for the member value https://www.w3.org/TR/trace-context/#value + // Please note the wonderful decision to allow ' ' in the value but not let it end with ' ', since + // that is indistinguishable from optional whitespace at the end + private static int validateMemberValue(String original, int start) { + int end = original.length(); + if (start < 0 || start >= end) { + return -1; + } + int length = 1; + int nonOWSLength = 0; + int pos = start; + boolean inWhiteSpace = false; + boolean onlyWhiteSpace = true; + boolean moreNonWSAllowed = true; + for (; pos < end; pos++, length++) { + if (!inWhiteSpace) { + nonOWSLength = length - 1; + } + if (nonOWSLength > 256) { + // We're beyond the length of the allowed member value and ',' delimiter + return -1; + } + char c = original.charAt(pos); + if (c == ' ') { + inWhiteSpace = true; + continue; + } + if (c == '\t') { + inWhiteSpace = true; + // If we encounter a `\t` then we can't have more normal characters after + moreNonWSAllowed = false; + continue; + } + if (c == ',') { + break; + } + if (!moreNonWSAllowed) { + return -1; + } + inWhiteSpace = false; + if (isValidMemberValueChar(c)) { + onlyWhiteSpace = false; + continue; + } + return -1; + } + if (onlyWhiteSpace) { + return -1; + } + if (!inWhiteSpace && length > 257) { + // We're beyond the length of the allowed member value and ',' delimiter + return -1; + } + + return pos; + } + + private static int findNextMember(String original, int start) { + int len = original.length(); + if (start < 0) { + return -1; + } + if (start >= len) { + return len; + } + + int pos = start; + for (; pos < len; pos++) { + char c = original.charAt(pos); + if (isOWC(c) || c == ',') { + continue; + } + break; + } + return pos; + } + + private static boolean isLcAlpha(char c) { + return c >= 'a' && c <= 'z'; + } + + private static boolean isValidExtra(char c) { + return c == '_' || c == '-' || c == '*' || c == '/'; + } + + private static boolean isValidMemberValueChar(char c) { + return c >= ' ' && c <= '~' && c != ',' && c != '='; + } + + private static boolean isOWC(char c) { + return c == ' ' || c == '\t'; + } + + private static int stripTrailingOWC(String original, int start, int end) { + char c = original.charAt(--end); + while (isOWC(c) && end > start) { + c = original.charAt(--end); + } + return ++end; + } + + private static int cleanUpAndAppendUnknown(StringBuilder sb, W3CPTags w3CPTags, int size) { + if (w3CPTags.maxUnknownSize == 0 + || w3CPTags.ddMemberStart == -1 + || w3CPTags.ddMemberStart >= w3CPTags.ddMemberValueEnd) { + return size; + } + String original = w3CPTags.tracestate; + int elementStart = w3CPTags.ddMemberStart + EMPTY_SIZE; // skip over 'dd=' + int okSize = size; + while (elementStart < w3CPTags.ddMemberValueEnd && size < MAX_HEADER_SIZE) { + okSize = size; + int elementEnd = original.indexOf(ELEMENT_SEPARATOR, elementStart); + if (elementEnd < 0) { + elementEnd = w3CPTags.ddMemberValueEnd; + } + if (!original.startsWith(Encoding.W3C.getPrefix(), elementStart)) { + char first = original.charAt(elementStart); + char second = original.charAt(elementStart + 1); + if (second != KEY_VALUE_SEPARATOR || (first != 'o' && first != 's')) { + // only append elements that we don't know about or are not tags + if (sb.length() > EMPTY_SIZE) { + sb.append(ELEMENT_SEPARATOR); + size++; + } + int end = elementEnd; + if (end == w3CPTags.ddMemberValueEnd) { + end = stripTrailingOWC(original, elementStart, end); + } + sb.append(original, elementStart, end); + size += (end - elementStart); + } + } + elementStart = elementEnd + 1; + } + if (size > MAX_HEADER_SIZE) { + sb.setLength(okSize); + size = okSize; + } + return size; + } + + private static int cleanUpAndAppendSuffix(StringBuilder sb, PTags ptags, int size) { + String original = ptags.tracestate; + if (original == null) { + return size; + } + int ddMemberStart = (ptags instanceof W3CPTags) ? ((W3CPTags) ptags).ddMemberStart : -1; + int remainingMemberAllowed = size == 0 ? MAX_MEMBER_COUNT : MAX_MEMBER_COUNT - 1; + int len = original.length(); + int memberStart = findNextMember(original, 0); + while (memberStart < len) { + // Look for member end position + int memberEnd = original.indexOf(MEMBER_SEPARATOR, memberStart); + if (memberEnd < 0) { + memberEnd = len; + } + // Try to define Datadog member start if not already found + if (ddMemberStart == -1) { + if (original.startsWith(DATADOG_MEMBER_KEY, memberStart)) { + ddMemberStart = memberStart; + } + } + // Skip Datadog member (already added with prefix and tags) + if (memberStart != ddMemberStart) { + if (sb.length() > 0) { + sb.append(MEMBER_SEPARATOR); + size++; + } + int end = stripTrailingOWC(original, memberStart, memberEnd); + sb.append(original, memberStart, end); + size += (end - memberStart); + remainingMemberAllowed--; + } + // Check if remaining members are allowed + if (remainingMemberAllowed == 0) { + memberStart = len; + } else { + memberStart = findNextMember(original, memberEnd + 1); + } + } + return size; + } + + private static W3CPTags empty(PTagsFactory factory, String original) { + return empty(factory, original, 0, -1, -1); + } + + private static W3CPTags empty( + PTagsFactory factory, + String original, + int firstMemberStart, + int ddMemberStart, + int ddMemberValueEnd) { + return new W3CPTags( + factory, + null, + null, + null, + PrioritySampling.UNSET, + null, + original, + firstMemberStart, + ddMemberStart, + ddMemberValueEnd, + 0); + } + + private static class W3CPTags extends PTags { + /** The index of the first tracestate list-member position in {@link #tracestate}. */ + private final int firstMemberStart; + /** + * The index of the Datadog tracestate list-member (dd=) position in {@link #tracestate}, {@code + * -1 if Datadog list-member not found}. + */ + private final int ddMemberStart; + /** + * The index of the end Datadog tracestate list-member (dd=) in {@link #tracestate}, {@code -1 + * if Datadog list-member not found}. + */ + private final int ddMemberValueEnd; + + private final int maxUnknownSize; + + public W3CPTags( + PTagsFactory factory, + List tagPairs, + TagValue decisionMakerTagValue, + TagValue traceIdTagValue, + int samplingPriority, + CharSequence origin, + String original, + int firstMemberStart, + int ddMemberStart, + int ddMemberValueEnd, + int maxUnknownSize) { + super(factory, tagPairs, decisionMakerTagValue, traceIdTagValue, samplingPriority, origin); + this.tracestate = original; + this.firstMemberStart = firstMemberStart; + this.ddMemberStart = ddMemberStart; + this.ddMemberValueEnd = ddMemberValueEnd; + this.maxUnknownSize = maxUnknownSize; + } + + @Override + public void updateTraceIdHighOrderBits(long highOrderBits) { + long currentHighOrderBits = getTraceIdHighOrderBits(); + // If defined from parsing but different from expected value, mark as decoding error + if (currentHighOrderBits != 0 && currentHighOrderBits != highOrderBits) { + this.error = + PROPAGATION_ERROR_INCONSISTENT_TID + toHexStringPadded(currentHighOrderBits, 16); + } + super.updateTraceIdHighOrderBits(highOrderBits); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/AbstractContinuation.java b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/AbstractContinuation.java new file mode 100644 index 0000000000..094c8feb59 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/AbstractContinuation.java @@ -0,0 +1,34 @@ +package datadog.trace.core.scopemanager; + +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentTrace; + +/** + * This class must not be a nested class of ContinuableScope to avoid an unconstrained chain of + * references (using too much memory). + */ +abstract class AbstractContinuation implements AgentScope.Continuation { + + final ContinuableScopeManager scopeManager; + final AgentSpan spanUnderScope; + final byte source; + final AgentTrace trace; + + public AbstractContinuation( + ContinuableScopeManager scopeManager, AgentSpan spanUnderScope, byte source) { + this.scopeManager = scopeManager; + this.spanUnderScope = spanUnderScope; + this.source = source; + this.trace = spanUnderScope.context().getTrace(); + } + + AbstractContinuation register() { + trace.registerContinuation(this); + return this; + } + + // Called by ContinuableScopeManager when a continued scope is closed + // Can't use cancel() for SingleContinuation because of the "used" check + abstract void cancelFromContinuedScopeClose(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ConcurrentContinuation.java b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ConcurrentContinuation.java new file mode 100644 index 0000000000..fe5a5986a9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ConcurrentContinuation.java @@ -0,0 +1,95 @@ +package datadog.trace.core.scopemanager; + +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + +/** + * This class must not be a nested class of ContinuableScope to avoid an unconstrained chain of + * references (using too much memory). + * + *

    This {@link AbstractContinuation} differs from the {@link SingleContinuation} in that if it is + * activated, it needs to be canceled in addition to the returned {@link AgentScope} being closed. + * This is to allow multiple concurrent threads that activate the continuation to race in a safe + * way, and close the scopes without fear of closing the related {@link AgentSpan} prematurely. + */ +final class ConcurrentContinuation extends AbstractContinuation { + private static final int START = 1; + private static final int CLOSED = Integer.MIN_VALUE >> 1; + private static final int BARRIER = Integer.MIN_VALUE >> 2; + private volatile int count = START; + + private static final AtomicIntegerFieldUpdater COUNT = + AtomicIntegerFieldUpdater.newUpdater(ConcurrentContinuation.class, "count"); + + public ConcurrentContinuation( + ContinuableScopeManager scopeManager, AgentSpan spanUnderScope, byte source) { + super(scopeManager, spanUnderScope, source); + } + + private boolean tryActivate() { + int current = COUNT.incrementAndGet(this); + if (current < START) { + COUNT.decrementAndGet(this); + } + return current > START; + } + + private boolean tryClose() { + int current = COUNT.get(this); + if (current < BARRIER) { + return false; + } + // Now decrement the counter + current = COUNT.decrementAndGet(this); + // Try to close this if we are between START and BARRIER + while (current < START && current > BARRIER) { + if (COUNT.compareAndSet(this, current, CLOSED)) { + return true; + } + current = COUNT.get(this); + } + return false; + } + + @Override + public AgentScope activate() { + if (tryActivate()) { + return scopeManager.continueSpan(this, spanUnderScope, source); + } else { + return null; + } + } + + @Override + public void cancel() { + if (tryClose()) { + trace.cancelContinuation(this); + } + ContinuableScopeManager.log.debug( + "t_id={} -> canceling continuation {}", spanUnderScope.getTraceId(), this); + } + + @Override + public AgentSpan getSpan() { + return spanUnderScope; + } + + @Override + void cancelFromContinuedScopeClose() { + cancel(); + } + + @Override + public String toString() { + int c = COUNT.get(this); + String s = c < BARRIER ? "CANCELED" : String.valueOf(c); + return getClass().getSimpleName() + + "@" + + Integer.toHexString(hashCode()) + + "(" + + s + + ")->" + + spanUnderScope; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java new file mode 100644 index 0000000000..86667d5a24 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java @@ -0,0 +1,207 @@ +package datadog.trace.core.scopemanager; + +import datadog.trace.api.Stateful; +import datadog.trace.api.scopemanager.ExtendedScopeListener; +import datadog.trace.api.scopemanager.ScopeListener; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AttachableWrapper; +import datadog.trace.bootstrap.instrumentation.api.ScopeSource; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; +import javax.annotation.Nonnull; + +class ContinuableScope implements AgentScope, AttachableWrapper { + private final ContinuableScopeManager scopeManager; + + final AgentSpan span; // package-private so scopeManager can access it directly + + /** Flag to propagate this scope across async boundaries. */ + private boolean isAsyncPropagating; + + private final byte flags; + + private short referenceCount = 1; + + private volatile Object wrapper; + private static final AtomicReferenceFieldUpdater WRAPPER_FIELD_UPDATER = + AtomicReferenceFieldUpdater.newUpdater(ContinuableScope.class, Object.class, "wrapper"); + + private final Stateful scopeState; + + ContinuableScope( + final ContinuableScopeManager scopeManager, + final AgentSpan span, + final byte source, + final boolean isAsyncPropagating, + final Stateful scopeState) { + this.scopeManager = scopeManager; + this.span = span; + this.flags = source; + this.isAsyncPropagating = isAsyncPropagating; + this.scopeState = scopeState; + } + + @Override + public final void close() { + final ScopeStack scopeStack = scopeManager.scopeStack(); + + // fast check first, only perform slower check when there's an inconsistency with the stack + if (!scopeStack.checkTop(this) && !scopeStack.checkOverdueScopes(this)) { + if (ContinuableScopeManager.log.isDebugEnabled()) { + ContinuableScopeManager.log.debug( + "Tried to close {} scope when not on top. Current top: {}", this, scopeStack.top); + } + + byte source = source(); + scopeManager.healthMetrics.onScopeCloseError(source); + if (source == ScopeSource.MANUAL.id() && scopeManager.strictMode) { + throw new RuntimeException("Tried to close scope when not on top"); + } + } + + final boolean alive = decrementReferences(); + scopeManager.healthMetrics.onCloseScope(); + if (!alive) { + cleanup(scopeStack); + } + scopeState.close(); + } + + void cleanup(final ScopeStack scopeStack) { + scopeStack.cleanup(); + } + + /* + * Exists to allow stack unwinding to do a delayed call to close when the close is + * finished properly. e.g. When the scope is back on the top of the stack. + * + * DQH - If we clean-up the delegation code & notification semantics at later time, + * I would hope this becomes unnecessary. + */ + final void onProperClose() { + for (final ScopeListener listener : scopeManager.scopeListeners) { + try { + listener.afterScopeClosed(); + } catch (Exception e) { + ContinuableScopeManager.log.debug("ScopeListener threw exception in close()", e); + } + } + + for (final ExtendedScopeListener listener : scopeManager.extendedScopeListeners) { + try { + listener.afterScopeClosed(); + } catch (Exception e) { + ContinuableScopeManager.log.debug("ScopeListener threw exception in close()", e); + } + } + } + + final void incrementReferences() { + ++referenceCount; + } + + /** Decrements ref count -- returns true if the scope is still alive */ + final boolean decrementReferences() { + return --referenceCount > 0; + } + + final void clearReferences() { + referenceCount = 0; + } + + /** Returns true if the scope is still alive (non-zero ref count) */ + final boolean alive() { + return referenceCount > 0; + } + + @Override + public final boolean isAsyncPropagating() { + return isAsyncPropagating; + } + + @Override + public final AgentSpan span() { + return span; + } + + @Override + public final void setAsyncPropagation(final boolean value) { + isAsyncPropagating = value; + } + + /** + * The continuation returned must be closed or activated or the trace will not finish. + * + * @return The new continuation, or null if this scope is not async propagating. + */ + @Override + public final AbstractContinuation capture() { + return isAsyncPropagating + ? new SingleContinuation(scopeManager, span, source()).register() + : null; + } + + /** + * The continuation returned must be closed or activated or the trace will not finish. + * + * @return The new continuation, or null if this scope is not async propagating. + */ + @Override + public final AbstractContinuation captureConcurrent() { + return isAsyncPropagating + ? new ConcurrentContinuation(scopeManager, span, source()).register() + : null; + } + + @Override + public final String toString() { + return super.toString() + "->" + span; + } + + public final void beforeActivated() { + try { + scopeState.activate(span.context()); + } catch (Throwable e) { + ContinuableScopeManager.ratelimitedLog.warn( + "ScopeState {} threw exception in beforeActivated()", scopeState.getClass(), e); + } + } + + public final void afterActivated() { + for (final ScopeListener listener : scopeManager.scopeListeners) { + try { + listener.afterScopeActivated(); + } catch (Throwable e) { + ContinuableScopeManager.log.debug("ScopeListener threw exception in afterActivated()", e); + } + } + + for (final ExtendedScopeListener listener : scopeManager.extendedScopeListeners) { + try { + listener.afterScopeActivated( + span.getTraceId(), + span.getLocalRootSpan().getSpanId(), + span.context().getSpanId(), + span.traceConfig()); + } catch (Throwable e) { + ContinuableScopeManager.log.debug( + "ExtendedScopeListener threw exception in afterActivated()", e); + } + } + } + + @Override + public byte source() { + return (byte) (flags & 0x7F); + } + + @Override + public void attachWrapper(@Nonnull Object wrapper) { + WRAPPER_FIELD_UPDATER.set(this, wrapper); + } + + @Override + public Object getWrapper() { + return WRAPPER_FIELD_UPDATER.get(this); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java new file mode 100644 index 0000000000..217c33699e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java @@ -0,0 +1,384 @@ +package datadog.trace.core.scopemanager; + +import static datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.NoopAgentSpan; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import datadog.trace.api.Config; +import datadog.trace.api.Stateful; +import datadog.trace.api.scopemanager.ExtendedScopeListener; +import datadog.trace.api.scopemanager.ScopeListener; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentScopeManager; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import datadog.trace.bootstrap.instrumentation.api.ProfilerContext; +import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; +import datadog.trace.bootstrap.instrumentation.api.ScopeSource; +import datadog.trace.bootstrap.instrumentation.api.ScopeState; +import datadog.trace.core.monitor.HealthMetrics; +import datadog.trace.relocate.api.RatelimitedLogger; +import datadog.trace.util.AgentTaskScheduler; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The primary ScopeManager. This class has ownership of the core ThreadLocal containing the + * currently active Scope. Such scopes can be suspended with a Continuation to prevent the trace + * from being reported even if all related spans are finished. It also delegates to other + * ScopeInterceptors to provide additional functionality. + */ +public final class ContinuableScopeManager implements AgentScopeManager { + static final Logger log = LoggerFactory.getLogger(ContinuableScopeManager.class); + static final RatelimitedLogger ratelimitedLog = new RatelimitedLogger(log, 1, MINUTES); + static final long iterationKeepAlive = + SECONDS.toMillis(Config.get().getScopeIterationKeepAlive()); + volatile ConcurrentMap rootIterationScopes; + final List scopeListeners; + final List extendedScopeListeners; + final boolean strictMode; + private final ScopeStackThreadLocal tlsScopeStack; + private final int depthLimit; + private final boolean inheritAsyncPropagation; + final HealthMetrics healthMetrics; + private final ProfilingContextIntegration profilingContextIntegration; + + /** + * Constructor with NOOP Profiling and HealthMetrics implementations. + * + * @param depthLimit The maximum scope depth limit, 0 for unlimited. + * @param strictMode Whether check if the closed spans are the active ones or not. + * @param inheritAsyncPropagation Whether the next span should inherit the active span + * asyncPropagation flag. + */ + public ContinuableScopeManager( + final int depthLimit, final boolean strictMode, final boolean inheritAsyncPropagation) { + this( + depthLimit, + strictMode, + inheritAsyncPropagation, + ProfilingContextIntegration.NoOp.INSTANCE, + HealthMetrics.NO_OP); + } + + /** + * Default constructor. + * + * @param depthLimit The maximum scope depth limit, 0 for unlimited. + * @param strictMode Whether check if the closed spans are the active ones or not. + * @param inheritAsyncPropagation Whether the next span should inherit the active span + * asyncPropagation flag. + */ + public ContinuableScopeManager( + final int depthLimit, + final boolean strictMode, + final boolean inheritAsyncPropagation, + final ProfilingContextIntegration profilingContextIntegration, + final HealthMetrics healthMetrics) { + this.depthLimit = depthLimit == 0 ? Integer.MAX_VALUE : depthLimit; + this.strictMode = strictMode; + this.inheritAsyncPropagation = inheritAsyncPropagation; + this.scopeListeners = new CopyOnWriteArrayList<>(); + this.extendedScopeListeners = new CopyOnWriteArrayList<>(); + this.healthMetrics = healthMetrics; + this.tlsScopeStack = new ScopeStackThreadLocal(profilingContextIntegration); + this.profilingContextIntegration = profilingContextIntegration; + } + + @Override + public AgentScope activate(final AgentSpan span, final ScopeSource source) { + return activate(span, source.id(), false, /* ignored */ false); + } + + @Override + public AgentScope activate( + final AgentSpan span, final ScopeSource source, boolean isAsyncPropagating) { + return activate(span, source.id(), true, isAsyncPropagating); + } + + @Override + public AgentScope.Continuation captureSpan(final AgentSpan span) { + AbstractContinuation continuation = + new SingleContinuation(this, span, ScopeSource.INSTRUMENTATION.id()); + continuation.register(); + healthMetrics.onCaptureContinuation(); + return continuation; + } + + private AgentScope activate( + final AgentSpan span, + final byte source, + final boolean overrideAsyncPropagation, + final boolean isAsyncPropagating) { + ScopeStack scopeStack = scopeStack(); + + final ContinuableScope top = scopeStack.top; + if (top != null && top.span.equals(span)) { + top.incrementReferences(); + return top; + } + + // DQH - This check could go before the check above, since depth limit checking is fast + final int currentDepth = scopeStack.depth(); + if (depthLimit <= currentDepth) { + healthMetrics.onScopeStackOverflow(); + log.debug("Scope depth limit exceeded ({}). Returning NoopScope.", currentDepth); + return AgentTracer.NoopAgentScope.INSTANCE; + } + + assert span != null; + + // Inherit the async propagation from the active scope unless the value is overridden + boolean asyncPropagation = + overrideAsyncPropagation + ? isAsyncPropagating + : inheritAsyncPropagation && top != null + ? top.isAsyncPropagating() + : DEFAULT_ASYNC_PROPAGATING; + + final ContinuableScope scope = + new ContinuableScope(this, span, source, asyncPropagation, createScopeState(span)); + scopeStack.push(scope); + healthMetrics.onActivateScope(); + + return scope; + } + + /** + * Activates a scope for the given {@link AbstractContinuation}. + * + * @param continuation {@code null} if a continuation is re-used + */ + ContinuableScope continueSpan( + final AbstractContinuation continuation, final AgentSpan span, final byte source) { + ScopeStack scopeStack = scopeStack(); + + // optimization: if the top scope is already keeping the same span alive + // then re-use that scope (avoids allocation) and cancel the continuation + final ContinuableScope top = scopeStack.top; + if (top != null && top.span.equals(span)) { + top.incrementReferences(); + if (continuation != null) { + continuation.cancelFromContinuedScopeClose(); + } + return top; + } + + Stateful scopeState = createScopeState(span); + final ContinuableScope scope; + if (continuation != null) { + scope = new ContinuingScope(this, span, source, true, continuation, scopeState); + } else { + scope = new ContinuableScope(this, span, source, true, scopeState); + } + scopeStack.push(scope); + + return scope; + } + + @Override + public void closePrevious(final boolean finishSpan) { + ScopeStack scopeStack = scopeStack(); + + // close any immediately previous iteration scope + final ContinuableScope top = scopeStack.top; + if (top != null && top.source() == ScopeSource.ITERATION.id()) { + if (iterationKeepAlive > 0) { // skip depth check because cancelling is cheap + cancelRootIterationScopeCleanup(scopeStack, top); + } + top.close(); + scopeStack.cleanup(); + if (finishSpan) { + top.span.finishWithEndToEnd(); + healthMetrics.onFinishContinuation(); + } + } + } + + @Override + public AgentScope activateNext(final AgentSpan span) { + ScopeStack scopeStack = scopeStack(); + + final int currentDepth = scopeStack.depth(); + if (depthLimit <= currentDepth) { + healthMetrics.onScopeStackOverflow(); + log.debug("Scope depth limit exceeded ({}). Returning NoopScope.", currentDepth); + return AgentTracer.NoopAgentScope.INSTANCE; + } + + assert span != null; + + final ContinuableScope top = scopeStack.top; + + boolean asyncPropagation = + inheritAsyncPropagation && top != null + ? top.isAsyncPropagating() + : DEFAULT_ASYNC_PROPAGATING; + + final ContinuableScope scope = + new ContinuableScope( + this, span, ScopeSource.ITERATION.id(), asyncPropagation, createScopeState(span)); + + if (iterationKeepAlive > 0 && currentDepth == 0) { + // no surrounding scope to aid cleanup, so use background task instead + scheduleRootIterationScopeCleanup(scopeStack, scope); + } + + scopeStack.push(scope); + + return scope; + } + + @Override + public AgentScope active() { + return scopeStack().active(); + } + + @Override + public AgentSpan activeSpan() { + final ContinuableScope active = scopeStack().active(); + return active == null ? null : active.span; + } + + /** Attach a listener to scope activation events */ + public void addScopeListener(final ScopeListener listener) { + if (listener instanceof ExtendedScopeListener) { + addExtendedScopeListener((ExtendedScopeListener) listener); + } else { + scopeListeners.add(listener); + log.debug("Added scope listener {}", listener); + AgentSpan activeSpan = activeSpan(); + if (activeSpan != null) { + // Notify the listener about the currently active scope + listener.afterScopeActivated(); + } + } + } + + private void addExtendedScopeListener(final ExtendedScopeListener listener) { + extendedScopeListeners.add(listener); + log.debug("Added scope listener {}", listener); + AgentSpan activeSpan = activeSpan(); + if (activeSpan != null && activeSpan != NoopAgentSpan.INSTANCE) { + // Notify the listener about the currently active scope + listener.afterScopeActivated( + activeSpan.getTraceId(), + activeSpan.getLocalRootSpan().getSpanId(), + activeSpan.context().getSpanId(), + activeSpan.traceConfig()); + } + } + + private Stateful createScopeState(AgentSpan span) { + // currently this just manages things the profiler has to do per scope, but could be expanded + // to encapsulate other scope lifecycle activities + // FIXME DDSpanContext is always a ProfilerContext anyway... + if (span.context() instanceof ProfilerContext) { + return profilingContextIntegration.newScopeState((ProfilerContext) span.context()); + } + return Stateful.DEFAULT; + } + + ScopeStack scopeStack() { + return this.tlsScopeStack.get(); + } + + @Override + public ScopeState newScopeState() { + return new ContinuableScopeState(); + } + + private class ContinuableScopeState implements ScopeState { + + private ScopeStack localScopeStack = tlsScopeStack.initialValue(); + + @Override + public void activate() { + tlsScopeStack.set(localScopeStack); + } + + @Override + public void fetchFromActive() { + localScopeStack = tlsScopeStack.get(); + } + } + + static final class ScopeStackThreadLocal extends ThreadLocal { + + private final ProfilingContextIntegration profilingContextIntegration; + + ScopeStackThreadLocal(ProfilingContextIntegration profilingContextIntegration) { + this.profilingContextIntegration = profilingContextIntegration; + } + + @Override + protected ScopeStack initialValue() { + return new ScopeStack(profilingContextIntegration); + } + } + + private void scheduleRootIterationScopeCleanup(ScopeStack scopeStack, ContinuableScope scope) { + if (rootIterationScopes == null) { + synchronized (this) { + if (rootIterationScopes == null) { + rootIterationScopes = new ConcurrentHashMap<>(); + RootIterationCleaner.scheduleFor(rootIterationScopes); + } + } + } + rootIterationScopes.put(scopeStack, scope); + } + + private void cancelRootIterationScopeCleanup(ScopeStack scopeStack, ContinuableScope scope) { + if (rootIterationScopes != null) { + rootIterationScopes.remove(scopeStack, scope); + } + } + + /** + * Background task to clean-up scopes from overdue root iterations that have no surrounding scope. + */ + private static final class RootIterationCleaner + implements AgentTaskScheduler.Task> { + private static final RootIterationCleaner CLEANER = new RootIterationCleaner(); + + public static void scheduleFor(Map rootIterationScopes) { + long period = Math.min(iterationKeepAlive, 10_000); + AgentTaskScheduler.INSTANCE.scheduleAtFixedRate( + CLEANER, rootIterationScopes, iterationKeepAlive, period, TimeUnit.MILLISECONDS); + } + + @Override + public void run(Map rootIterationScopes) { + Iterator> itr = + rootIterationScopes.entrySet().iterator(); + + long cutOff = System.currentTimeMillis() - iterationKeepAlive; + + while (itr.hasNext()) { + Map.Entry entry = itr.next(); + + ScopeStack scopeStack = entry.getKey(); + ContinuableScope rootScope = entry.getValue(); + + if (!rootScope.alive()) { // no need to track this anymore + itr.remove(); + } else if (NANOSECONDS.toMillis(rootScope.span.getStartTime()) < cutOff) { + // mark scope as overdue to allow cleanup and avoid further spans being attached + scopeStack.overdueRootScope = rootScope; + rootScope.span.finishWithEndToEnd(); + itr.remove(); + } + } + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuingScope.java b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuingScope.java new file mode 100644 index 0000000000..f929fdb5df --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuingScope.java @@ -0,0 +1,27 @@ +package datadog.trace.core.scopemanager; + +import datadog.trace.api.Stateful; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; + +final class ContinuingScope extends ContinuableScope { + /** Continuation that created this scope. */ + private final AbstractContinuation continuation; + + ContinuingScope( + final ContinuableScopeManager scopeManager, + final AgentSpan span, + final byte source, + final boolean isAsyncPropagating, + final AbstractContinuation continuation, + final Stateful scopeState) { + super(scopeManager, span, source, isAsyncPropagating, scopeState); + this.continuation = continuation; + } + + @Override + void cleanup(final ScopeStack scopeStack) { + super.cleanup(scopeStack); + + continuation.cancelFromContinuedScopeClose(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java new file mode 100644 index 0000000000..78ea56d7d8 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java @@ -0,0 +1,127 @@ +package datadog.trace.core.scopemanager; + +import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; +import datadog.trace.bootstrap.instrumentation.api.ScopeSource; +import java.util.ArrayDeque; + +/** + * The invariant is that the top of a non-empty stack is always active. Anytime a scope is closed, + * cleanup() is called to ensure the invariant + */ +final class ScopeStack { + + private final ProfilingContextIntegration profilingContextIntegration; + private final ArrayDeque stack = new ArrayDeque<>(); // previous scopes + + ContinuableScope top; // current scope + + // set by background task when a root iteration scope remains unclosed for too long + volatile ContinuableScope overdueRootScope; + + ScopeStack(ProfilingContextIntegration profilingContextIntegration) { + this.profilingContextIntegration = profilingContextIntegration; + } + + ContinuableScope active() { + // avoid attaching further spans to the root scope when it's been marked as overdue + return top != overdueRootScope ? top : null; + } + + /** Removes and closes all scopes up to the nearest live scope */ + void cleanup() { + ContinuableScope curScope = top; + boolean changedTop = false; + while (curScope != null && !curScope.alive()) { + // no longer alive -- trigger listener & null out + curScope.onProperClose(); + changedTop = true; + curScope = stack.poll(); + } + if (curScope != null && curScope == overdueRootScope) { + // we know this scope is the last on the stack and is overdue + curScope.onProperClose(); + overdueRootScope = null; + top = null; + } else if (changedTop) { + top = curScope; + if (curScope != null) { + curScope.beforeActivated(); + curScope.afterActivated(); + } + } + if (top == null) { + onBecomeEmpty(); + } + } + + /** Marks a new scope as current, pushing the previous onto the stack */ + void push(final ContinuableScope scope) { + scope.beforeActivated(); + if (top != null) { + stack.push(top); + } else { + onBecomeNonEmpty(); + } + top = scope; + scope.afterActivated(); + } + + /** Fast check to see if the expectedScope is on top */ + boolean checkTop(final ContinuableScope expectedScope) { + return expectedScope.equals(top); + } + + /** + * Slower check to see if overdue scopes ahead of the expected scope are all ITERATION scopes. + * These represent iterations that are now out-of-scope and can be finished ready for cleanup. + */ + final boolean checkOverdueScopes(final ContinuableScope expectedScope) { + // we already know 'top' isn't the expected scope, so just need to check its source + if (top == null || top.source() != ScopeSource.ITERATION.id()) { + return false; + } + // avoid calling close() as we're already in that method, instead just clear any + // remaining references so the scope gets removed in the subsequent cleanup() call + top.clearReferences(); + top.span.finishWithEndToEnd(); + // now do the same for any previous iteration scopes ahead of the expected scope + for (ContinuableScope scope : stack) { + if (scope.source() != ScopeSource.ITERATION.id()) { + return expectedScope.equals(scope); + } else { + scope.clearReferences(); + scope.span.finishWithEndToEnd(); + } + } + return false; // we didn't find the expected scope + } + + /** Returns the current depth, including the top scope */ + int depth() { + return top != null ? 1 + stack.size() : 0; + } + + // DQH - regrettably needed for pre-existing tests + void clear() { + stack.clear(); + top = null; + } + + /** Notifies profiler that this thread has a context now */ + private void onBecomeNonEmpty() { + try { + profilingContextIntegration.onAttach(); + } catch (Throwable e) { + ContinuableScopeManager.ratelimitedLog.warn("Unexpected profiling exception", e); + } + } + + /** Notifies profiler that this thread no longer has a context */ + private void onBecomeEmpty() { + try { + profilingContextIntegration.onDetach(); + } catch (Throwable e) { + ContinuableScopeManager.ratelimitedLog.warn("Unexpected profiling exception", e); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/SingleContinuation.java b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/SingleContinuation.java new file mode 100644 index 0000000000..06aae99c35 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/SingleContinuation.java @@ -0,0 +1,61 @@ +package datadog.trace.core.scopemanager; + +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + +/** + * This class must not be a nested class of ContinuableScope to avoid an unconstrained chain of + * references (using too much memory). + */ +final class SingleContinuation extends AbstractContinuation { + private static final AtomicIntegerFieldUpdater USED = + AtomicIntegerFieldUpdater.newUpdater(SingleContinuation.class, "used"); + private volatile int used = 0; + + SingleContinuation( + final ContinuableScopeManager scopeManager, + final AgentSpan spanUnderScope, + final byte source) { + super(scopeManager, spanUnderScope, source); + } + + @Override + public AgentScope activate() { + if (USED.compareAndSet(this, 0, 1)) { + return scopeManager.continueSpan(this, spanUnderScope, source); + } else { + ContinuableScopeManager.log.debug( + "Failed to activate continuation. Reusing a continuation not allowed. Spans may be reported separately."); + return scopeManager.continueSpan(null, spanUnderScope, source); + } + } + + @Override + public void cancel() { + if (USED.compareAndSet(this, 0, 1)) { + trace.cancelContinuation(this); + } else { + ContinuableScopeManager.log.debug("Failed to close continuation {}. Already used.", this); + } + } + + @Override + public AgentSpan getSpan() { + return spanUnderScope; + } + + @Override + void cancelFromContinuedScopeClose() { + trace.cancelContinuation(this); + } + + @Override + public String toString() { + return getClass().getSimpleName() + + "@" + + Integer.toHexString(hashCode()) + + "->" + + spanUnderScope; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/RuleFlags.java b/features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/RuleFlags.java new file mode 100644 index 0000000000..3ebcfdd488 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/RuleFlags.java @@ -0,0 +1,55 @@ +package datadog.trace.core.taginterceptor; + +import datadog.trace.api.Config; + +public class RuleFlags { + + public enum Feature { + // These names all derive from the simple class names which + // were exposed as config at some point in the past. + RESOURCE_NAME("ResourceNameRule"), + URL_AS_RESOURCE_NAME("URLAsResourceNameRule"), + STATUS_404("Status404Rule"), + STATUS_404_DECORATOR("Status404Decorator"), + DB_STATEMENT("DBStatementRule"), + FORCE_MANUAL_DROP("ForceManualDropTagInterceptor"), + FORCE_MANUAL_KEEP("ForceManualKeepTagInterceptor"), + PEER_SERVICE("PeerServiceTagInterceptor", false), + SERVICE_NAME("ServiceNameTagInterceptor"), + SERVLET_CONTEXT("ServletContextTagInterceptor"); + + private final String name; + + private final boolean defaultEnabled; + + Feature(String name) { + this.name = name; + this.defaultEnabled = true; + } + + Feature(String name, boolean defaultEnabled) { + this.name = name; + this.defaultEnabled = defaultEnabled; + } + } + + private final boolean[] flags; + + public RuleFlags() { + this(Config.get()); + } + + public RuleFlags(Config config) { + Feature[] features = Feature.values(); + this.flags = new boolean[features.length]; + for (Feature feature : features) { + if (config.isRuleEnabled(feature.name, feature.defaultEnabled)) { + flags[feature.ordinal()] = true; + } + } + } + + public boolean isEnabled(Feature feature) { + return flags[feature.ordinal()]; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/TagInterceptor.java b/features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/TagInterceptor.java new file mode 100644 index 0000000000..475f1d1448 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/TagInterceptor.java @@ -0,0 +1,323 @@ +package datadog.trace.core.taginterceptor; + +import static datadog.trace.api.DDTags.ANALYTICS_SAMPLE_RATE; +import static datadog.trace.api.DDTags.MEASURED; +import static datadog.trace.api.DDTags.ORIGIN_KEY; +import static datadog.trace.api.DDTags.SPAN_TYPE; +import static datadog.trace.api.sampling.PrioritySampling.USER_DROP; +import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_METHOD; +import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_STATUS; +import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_URL; +import static datadog.trace.core.taginterceptor.RuleFlags.Feature.FORCE_MANUAL_DROP; +import static datadog.trace.core.taginterceptor.RuleFlags.Feature.PEER_SERVICE; +import static datadog.trace.core.taginterceptor.RuleFlags.Feature.RESOURCE_NAME; +import static datadog.trace.core.taginterceptor.RuleFlags.Feature.SERVICE_NAME; +import static datadog.trace.core.taginterceptor.RuleFlags.Feature.STATUS_404; +import static datadog.trace.core.taginterceptor.RuleFlags.Feature.STATUS_404_DECORATOR; +import static datadog.trace.core.taginterceptor.RuleFlags.Feature.URL_AS_RESOURCE_NAME; + +import datadog.trace.api.Config; +import datadog.trace.api.ConfigDefaults; +import datadog.trace.api.DDTags; +import datadog.trace.api.Pair; +import datadog.trace.api.config.GeneralConfig; +import datadog.trace.api.env.CapturedEnvironment; +import datadog.trace.api.normalize.HttpResourceNames; +import datadog.trace.api.sampling.SamplingMechanism; +import datadog.trace.bootstrap.instrumentation.api.ErrorPriorities; +import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags; +import datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.bootstrap.instrumentation.api.URIUtils; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.core.DDSpanContext; +import java.net.URI; +import java.util.Set; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class TagInterceptor { + + private static final UTF8BytesString NOT_FOUND_RESOURCE_NAME = UTF8BytesString.create("404"); + + private final RuleFlags ruleFlags; + private final boolean isServiceNameSetByUser; + private final boolean splitByServletContext; + private final String inferredServiceName; + private final Set splitServiceTags; + + private final boolean shouldSet404ResourceName; + private final boolean shouldSetUrlResourceAsName; + + public TagInterceptor(RuleFlags ruleFlags) { + this( + Config.get().isServiceNameSetByUser(), + CapturedEnvironment.get().getProperties().get(GeneralConfig.SERVICE_NAME), + Config.get().getSplitByTags(), + ruleFlags); + } + + public TagInterceptor( + boolean isServiceNameSetByUser, + String inferredServiceName, + Set splitServiceTags, + RuleFlags ruleFlags) { + this.isServiceNameSetByUser = isServiceNameSetByUser; + this.inferredServiceName = inferredServiceName; + this.splitServiceTags = splitServiceTags; + this.ruleFlags = ruleFlags; + splitByServletContext = splitServiceTags.contains(InstrumentationTags.SERVLET_CONTEXT); + + shouldSet404ResourceName = + ruleFlags.isEnabled(URL_AS_RESOURCE_NAME) + && ruleFlags.isEnabled(STATUS_404) + && ruleFlags.isEnabled(STATUS_404_DECORATOR); + shouldSetUrlResourceAsName = ruleFlags.isEnabled(URL_AS_RESOURCE_NAME); + } + + public boolean interceptTag(DDSpanContext span, String tag, Object value) { + switch (tag) { + case DDTags.RESOURCE_NAME: + return interceptResourceName(span, value); + case Tags.DB_STATEMENT: + return interceptDbStatement(span, value); + case DDTags.SERVICE_NAME: + case "service": + return interceptServiceName(SERVICE_NAME, span, value); + case Tags.PEER_SERVICE: + // we still need to intercept and add this tag when the user manually set + span.setTag(DDTags.PEER_SERVICE_SOURCE, Tags.PEER_SERVICE); + return interceptServiceName(PEER_SERVICE, span, value); + case DDTags.MANUAL_KEEP: + if (asBoolean(value)) { + span.forceKeep(); + return true; + } + return false; + case DDTags.MANUAL_DROP: + return interceptSamplingPriority( + FORCE_MANUAL_DROP, USER_DROP, SamplingMechanism.MANUAL, span, value); + case InstrumentationTags.SERVLET_CONTEXT: + return interceptServletContext(span, value); + case SPAN_TYPE: + return interceptSpanType(span, value); + case ANALYTICS_SAMPLE_RATE: + return interceptAnalyticsSampleRate(span, value); + case Tags.ERROR: + return interceptError(span, value); + case HTTP_STATUS: + // not set internally but may come from manual instrumentation + return interceptHttpStatusCode(span, value); + case HTTP_METHOD: + case HTTP_URL: + return interceptUrlResourceAsNameRule(span, tag, value); + case ORIGIN_KEY: + return interceptOrigin(span, value); + case MEASURED: + return interceptMeasured(span, value); + default: + return intercept(span, tag, value); + } + } + + private boolean interceptUrlResourceAsNameRule(DDSpanContext span, String tag, Object value) { + if (shouldSetUrlResourceAsName) { + if (HTTP_METHOD.equals(tag)) { + final Object url = span.unsafeGetTag(HTTP_URL); + if (url != null) { + setResourceFromUrl(span, value.toString(), url); + } + } else if (HTTP_URL.equals(tag)) { + final Object method = span.unsafeGetTag(HTTP_METHOD); + setResourceFromUrl(span, method != null ? method.toString() : null, value); + } + } + return false; + } + + private static void setResourceFromUrl( + @Nonnull final DDSpanContext span, @Nullable final String method, @Nonnull final Object url) { + final String path; + if (url instanceof URIUtils.LazyUrl) { + path = ((URIUtils.LazyUrl) url).path(); + } else { + URI uri = URIUtils.safeParse(url.toString()); + path = uri == null ? null : uri.getPath(); + } + if (path != null) { + final boolean isClient = Tags.SPAN_KIND_CLIENT.equals(span.unsafeGetTag(Tags.SPAN_KIND)); + Pair normalized = + isClient + ? HttpResourceNames.computeForClient(method, path, false) + : HttpResourceNames.computeForServer(method, path, false); + if (normalized.hasLeft()) { + span.setResourceName(normalized.getLeft(), normalized.getRight()); + } + } else { + span.setResourceName( + HttpResourceNames.DEFAULT_RESOURCE_NAME, ResourceNamePriorities.HTTP_PATH_NORMALIZER); + } + } + + private boolean intercept(DDSpanContext span, String tag, Object value) { + if (splitServiceTags.contains(tag)) { + span.setServiceName(String.valueOf(value)); + return true; + } + return false; + } + + private boolean interceptResourceName(DDSpanContext span, Object value) { + if (ruleFlags.isEnabled(RESOURCE_NAME)) { + if (null == value) { + return false; + } + if (value instanceof CharSequence) { + span.setResourceName((CharSequence) value, ResourceNamePriorities.TAG_INTERCEPTOR); + } else { + span.setResourceName(String.valueOf(value), ResourceNamePriorities.TAG_INTERCEPTOR); + } + return true; + } + return false; + } + + private boolean interceptDbStatement(DDSpanContext span, Object value) { + if (value instanceof CharSequence) { + CharSequence resourceName = (CharSequence) value; + if (resourceName.length() > 0) { + span.setResourceName(resourceName, ResourceNamePriorities.TAG_INTERCEPTOR); + } + } + return true; + } + + private boolean interceptError(DDSpanContext span, Object value) { + span.setErrorFlag(asBoolean(value), ErrorPriorities.DEFAULT); + return true; + } + + private boolean interceptAnalyticsSampleRate(DDSpanContext span, Object value) { + Number analyticsSampleRate = getOrTryParse(value); + if (null != analyticsSampleRate) { + span.setMetric(ANALYTICS_SAMPLE_RATE, analyticsSampleRate); + } + return true; + } + + private boolean interceptSpanType(DDSpanContext span, Object value) { + if (value instanceof CharSequence) { + span.setSpanType((CharSequence) value); + } else { + span.setSpanType(String.valueOf(value)); + } + return true; + } + + private boolean interceptServiceName( + RuleFlags.Feature feature, DDSpanContext span, Object value) { + if (ruleFlags.isEnabled(feature)) { + span.setServiceName(String.valueOf(value)); + return true; + } + return false; + } + + private boolean interceptSamplingPriority( + RuleFlags.Feature feature, + int samplingPriority, + int samplingMechanism, + DDSpanContext span, + Object value) { + if (ruleFlags.isEnabled(feature)) { + if (asBoolean(value)) { + span.setSamplingPriority(samplingPriority, samplingMechanism); + } + return true; + } + return false; + } + + private boolean interceptServletContext(DDSpanContext span, Object value) { + // even though this tag is sometimes used to set the service name + // (which has the side effect of marking the span as eligible for metrics + // in the trace agent) we also want to store it in the tags no matter what, + // so will always return false here. + if (!splitByServletContext + && (isServiceNameSetByUser + || !ruleFlags.isEnabled(RuleFlags.Feature.SERVLET_CONTEXT) + || !span.getServiceName().isEmpty() + && !span.getServiceName().equals(inferredServiceName) + && !span.getServiceName().equals(ConfigDefaults.DEFAULT_SERVICE_NAME))) { + return false; + } + String contextName = String.valueOf(value).trim(); + if (!contextName.isEmpty()) { + if (contextName.equals("/")) { + span.setServiceName(Config.get().getRootContextServiceName()); + } else if (contextName.charAt(0) == '/') { + if (contextName.length() > 1) { + span.setServiceName(contextName.substring(1)); + } + } else { + span.setServiceName(contextName); + } + } + return false; + } + + private boolean interceptHttpStatusCode(DDSpanContext span, Object statusCode) { + if (statusCode instanceof Number) { + span.setHttpStatusCode(((Number) statusCode).shortValue()); + if (shouldSet404ResourceName && span.getHttpStatusCode() == 404) { + span.setResourceName(NOT_FOUND_RESOURCE_NAME, ResourceNamePriorities.HTTP_404); + } + return true; + } + try { + span.setHttpStatusCode(Short.parseShort(String.valueOf(statusCode))); + if (shouldSet404ResourceName && span.getHttpStatusCode() == 404) { + span.setResourceName(NOT_FOUND_RESOURCE_NAME, ResourceNamePriorities.HTTP_404); + } + return true; + } catch (Throwable ignore) { + } + return false; + } + + private boolean interceptOrigin(final DDSpanContext span, final Object origin) { + if (origin instanceof CharSequence) { + span.setOrigin((CharSequence) origin); + } else { + span.setOrigin(String.valueOf(origin)); + } + return true; + } + + private static boolean interceptMeasured(DDSpanContext span, Object value) { + if ((value instanceof Number && ((Number) value).intValue() > 0) || asBoolean(value)) { + span.setMeasured(true); + return true; + } + return false; + } + + private static boolean asBoolean(Object value) { + return Boolean.TRUE.equals(value) + || "1".equals(value) + || (!Boolean.FALSE.equals(value) && Boolean.parseBoolean(String.valueOf(value))); + } + + private static Number getOrTryParse(Object value) { + if (value instanceof Number) { + return (Number) value; + } else if (value instanceof String) { + try { + return Double.parseDouble((String) value); + } catch (NumberFormatException ignore) { + + } + } + return null; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/BaseServiceAdder.java b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/BaseServiceAdder.java new file mode 100644 index 0000000000..4081460663 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/BaseServiceAdder.java @@ -0,0 +1,30 @@ +package datadog.trace.core.tagprocessor; + +import datadog.trace.api.DDTags; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.core.DDSpanContext; +import java.util.Map; +import javax.annotation.Nullable; + +public class BaseServiceAdder implements TagsPostProcessor { + private final UTF8BytesString ddService; + + public BaseServiceAdder(@Nullable final String ddService) { + this.ddService = ddService != null ? UTF8BytesString.create(ddService) : null; + } + + @Override + public Map processTags(Map unsafeTags) { + // we are only able to do something if the span service name is known + return unsafeTags; + } + + @Override + public Map processTagsWithContext( + Map unsafeTags, DDSpanContext spanContext) { + if (ddService != null && !ddService.toString().equalsIgnoreCase(spanContext.getServiceName())) { + unsafeTags.put(DDTags.BASE_SERVICE, ddService); + } + return unsafeTags; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java new file mode 100644 index 0000000000..7c473d8d0a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java @@ -0,0 +1,59 @@ +package datadog.trace.core.tagprocessor; + +import datadog.trace.api.Config; +import datadog.trace.api.DDTags; +import datadog.trace.api.naming.NamingSchema; +import datadog.trace.api.naming.SpanNaming; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import java.util.Map; +import javax.annotation.Nonnull; + +public class PeerServiceCalculator implements TagsPostProcessor { + private final NamingSchema.ForPeerService peerServiceNaming; + + private final Map peerServiceMapping; + + private final boolean canRemap; + + public PeerServiceCalculator() { + this(SpanNaming.instance().namingSchema().peerService(), Config.get().getPeerServiceMapping()); + } + + // Visible for testing + PeerServiceCalculator( + @Nonnull final NamingSchema.ForPeerService peerServiceNaming, + @Nonnull final Map peerServiceMapping) { + this.peerServiceNaming = peerServiceNaming; + this.peerServiceMapping = peerServiceMapping; + this.canRemap = !peerServiceMapping.isEmpty(); + } + + @Override + public Map processTags(Map unsafeTags) { + Object peerService = unsafeTags.get(Tags.PEER_SERVICE); + // the user set it + if (peerService != null) { + if (canRemap) { + return remapPeerService(unsafeTags, peerService); + } + } else if (peerServiceNaming.supports()) { + // calculate the defaults (if any) + peerServiceNaming.tags(unsafeTags); + // only remap if the mapping is not empty (saves one get) + return remapPeerService(unsafeTags, canRemap ? unsafeTags.get(Tags.PEER_SERVICE) : null); + } + // we have no peer.service and we do not compute defaults. Leave the map untouched + return unsafeTags; + } + + private Map remapPeerService(Map unsafeTags, Object value) { + if (value != null) { + String mapped = peerServiceMapping.get(value); + if (mapped != null) { + unsafeTags.put(Tags.PEER_SERVICE, mapped); + unsafeTags.put(DDTags.PEER_SERVICE_REMAPPED_FROM, value); + } + } + return unsafeTags; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PostProcessorChain.java b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PostProcessorChain.java new file mode 100644 index 0000000000..ffadb33671 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PostProcessorChain.java @@ -0,0 +1,29 @@ +package datadog.trace.core.tagprocessor; + +import datadog.trace.core.DDSpanContext; +import java.util.Map; +import java.util.Objects; +import javax.annotation.Nonnull; + +public class PostProcessorChain implements TagsPostProcessor { + private final TagsPostProcessor[] chain; + + public PostProcessorChain(@Nonnull final TagsPostProcessor... processors) { + chain = Objects.requireNonNull(processors); + } + + @Override + public Map processTags(Map unsafeTags) { + return processTagsWithContext(unsafeTags, null); + } + + @Override + public Map processTagsWithContext( + Map unsafeTags, DDSpanContext spanContext) { + Map currentTags = unsafeTags; + for (final TagsPostProcessor tagsPostProcessor : chain) { + currentTags = tagsPostProcessor.processTagsWithContext(currentTags, spanContext); + } + return currentTags; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/QueryObfuscator.java b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/QueryObfuscator.java new file mode 100644 index 0000000000..07e4a03db7 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/QueryObfuscator.java @@ -0,0 +1,73 @@ +package datadog.trace.core.tagprocessor; + +import com.google.re2j.Matcher; +import com.google.re2j.Pattern; +import com.google.re2j.PatternSyntaxException; +import datadog.trace.api.DDTags; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.util.Strings; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class QueryObfuscator implements TagsPostProcessor { + + private static final Logger log = LoggerFactory.getLogger(QueryObfuscator.class); + + private static final String DEFAULT_OBFUSCATION_PATTERN = + "(?i)(?:(?:\"|%22)?)(?:(?:old[-_]?|new[-_]?)?p(?:ass)?w(?:or)?d(?:1|2)?|pass(?:[-_]?phrase)?|secret|(?:api[-_]?|private[-_]?|public[-_]?|access[-_]?|secret[-_]?|app(?:lication)?[-_]?)key(?:[-_]?id)?|token|consumer[-_]?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\\s|%20)*(?:=|%3D)[^&]+|(?:\"|%22)(?:\\s|%20)*(?::|%3A)(?:\\s|%20)*(?:\"|%22)(?:%2[^2]|%[^2]|[^\"%])+(?:\"|%22))|(?:bearer(?:\\s|%20)+[a-z0-9._\\-]+|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L](?:[\\w=-]|%3D)+\\.ey[I-L](?:[\\w=-]|%3D)+(?:\\.(?:[\\w.+/=-]|%3D|%2F|%2B)+)?|-{5}BEGIN(?:[a-z\\s]|%20)+PRIVATE(?:\\s|%20)KEY-{5}[^\\-]+-{5}END(?:[a-z\\s]|%20)+PRIVATE(?:\\s|%20)KEY(?:-{5})?(?:\\n|%0A)?|(?:ssh-(?:rsa|dss)|ecdsa-[a-z0-9]+-[a-z0-9]+)(?:\\s|%20|%09)+(?:[a-z0-9/.+]|%2F|%5C|%2B){100,}(?:=|%3D)*(?:(?:\\s|%20|%09)+[a-z0-9._-]+)?)"; + + private final Pattern pattern; + + /** + * If regex is null - then used default regex pattern If regex is empty string - then disable + * regex + */ + public QueryObfuscator(String regex) { + // empty string -> disabled query obfuscation + if ("".equals(regex)) { + this.pattern = null; + return; + } + + // null -> use default regex + if (regex == null) { + regex = DEFAULT_OBFUSCATION_PATTERN; + } + + Pattern pattern = null; + try { + pattern = Pattern.compile(regex); + } catch (PatternSyntaxException e) { + log.error("Could not compile given query obfuscation regex: {}", regex, e); + } + this.pattern = pattern; + } + + private String obfuscate(String query) { + if (pattern != null) { + Matcher matcher = pattern.matcher(query); + while (matcher.find()) { + query = Strings.replace(query, matcher.group(), ""); + } + } + return query; + } + + @Override + public Map processTags(Map unsafeTags) { + Object query = unsafeTags.get(DDTags.HTTP_QUERY); + if (query instanceof CharSequence) { + query = obfuscate(query.toString()); + + unsafeTags.put(DDTags.HTTP_QUERY, query); + + Object url = unsafeTags.get(Tags.HTTP_URL); + if (url instanceof CharSequence) { + unsafeTags.put(Tags.HTTP_URL, url + "?" + query); + } + } + + return unsafeTags; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessor.java b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessor.java new file mode 100644 index 0000000000..55baaa2d4a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessor.java @@ -0,0 +1,13 @@ +package datadog.trace.core.tagprocessor; + +import datadog.trace.core.DDSpanContext; +import java.util.Map; + +public interface TagsPostProcessor { + Map processTags(Map unsafeTags); + + default Map processTagsWithContext( + Map unsafeTags, DDSpanContext spanContext) { + return processTags(unsafeTags); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java new file mode 100644 index 0000000000..74aa721562 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java @@ -0,0 +1,44 @@ +package datadog.trace.core.tagprocessor; + +import datadog.trace.api.Config; +import java.util.ArrayList; +import java.util.List; + +public final class TagsPostProcessorFactory { + private static boolean addBaseService = true; + + private static class Lazy { + private static TagsPostProcessor create() { + final List processors = new ArrayList<>(addBaseService ? 3 : 2); + processors.add(new PeerServiceCalculator()); + if (addBaseService) { + processors.add(new BaseServiceAdder(Config.get().getServiceName())); + } + processors.add(new QueryObfuscator(Config.get().getObfuscationQueryRegexp())); + return new PostProcessorChain( + processors.toArray(processors.toArray(new TagsPostProcessor[0]))); + } + + private static TagsPostProcessor instance = create(); + } + + public static TagsPostProcessor instance() { + return Lazy.instance; + } + + /** + * Mostly used for test purposes. + * + * @param enabled if false, {@link BaseServiceAdder} is not put in the chain. + */ + public static void withAddBaseService(boolean enabled) { + addBaseService = enabled; + Lazy.instance = Lazy.create(); + } + + /** Used for testing purposes. It reset the singleton and restore default options */ + public static void reset() { + withAddBaseService(true); + Lazy.instance = Lazy.create(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/GlobPattern.java b/features/dd-trace-core/src/main/java/datadog/trace/core/util/GlobPattern.java new file mode 100644 index 0000000000..c0fd0499b9 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/util/GlobPattern.java @@ -0,0 +1,47 @@ +package datadog.trace.core.util; + +import java.util.regex.Pattern; + +public final class GlobPattern { + + public static Pattern globToRegexPattern(String globPattern) { + String regex = globToRegex(globPattern); + return Pattern.compile(regex); + } + + private static String globToRegex(String globPattern) { + StringBuilder sb = new StringBuilder(64); + sb.append('^'); + for (int i = 0; i < globPattern.length(); i++) { + char ch = globPattern.charAt(i); + switch (ch) { + case '?': + sb.append('.'); + break; + case '*': + sb.append(".*"); + break; + case '^': + case '$': + case '|': + case '.': + case '\\': + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + sb.append("\\").append(ch); + break; + default: + sb.append(ch); + break; + } + } + sb.append('$'); + return sb.toString(); + } + + private GlobPattern() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/LRUCache.java b/features/dd-trace-core/src/main/java/datadog/trace/core/util/LRUCache.java new file mode 100644 index 0000000000..b8d993ec04 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/util/LRUCache.java @@ -0,0 +1,46 @@ +package datadog.trace.core.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +public final class LRUCache extends LinkedHashMap { + + public interface ExpiryListener { + void accept(Map.Entry expired); + } + + // Copied here since they for some reason are `package` and not `protected` in HashMap + private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; + private static final float DEFAULT_LOAD_FACTOR = 0.75f; + + private final int maxEntries; + private final ExpiryListener expiryListener; + + public LRUCache(int maxEntries) { + this(DEFAULT_INITIAL_CAPACITY, maxEntries); + } + + public LRUCache(int initialCapacity, int maxEntries) { + this(initialCapacity, DEFAULT_LOAD_FACTOR, maxEntries); + } + + public LRUCache(int initialCapacity, float loadFactor, int maxEntries) { + this(null, initialCapacity, loadFactor, maxEntries); + } + + public LRUCache( + ExpiryListener expiryListener, int initialCapacity, float loadFactor, int maxEntries) { + super(initialCapacity, loadFactor, true); // keep track of access order + this.maxEntries = maxEntries; + this.expiryListener = expiryListener; + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + boolean expire = size() > maxEntries; + if (null != expiryListener && expire) { + expiryListener.accept(eldest); + } + return expire; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/Matcher.java b/features/dd-trace-core/src/main/java/datadog/trace/core/util/Matcher.java new file mode 100644 index 0000000000..972954e5eb --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/util/Matcher.java @@ -0,0 +1,7 @@ +package datadog.trace.core.util; + +public interface Matcher { + boolean matches(String str); + + boolean matches(CharSequence charSeq); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/Matchers.java b/features/dd-trace-core/src/main/java/datadog/trace/core/util/Matchers.java new file mode 100644 index 0000000000..4ea92fecbe --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/util/Matchers.java @@ -0,0 +1,69 @@ +package datadog.trace.core.util; + +import java.util.regex.Pattern; + +public final class Matchers { + private Matchers() {} + + public static Matcher compileGlob(String glob) { + if (glob == null || glob.equals("*")) { + // DQH - Decided not to an anyMatcher because that's likely to + // cause our call site to go megamorphic + return null; + } else if (isExact(glob)) { + return new ExactMatcher(glob); + } else { + // DQH - not sure about the error handling here + Pattern pattern = GlobPattern.globToRegexPattern(glob); + return new PatternMatcher(pattern); + } + } + + public static boolean matches(Matcher matcher, String str) { + return (matcher == null) || matcher.matches(str); + } + + public static boolean matches(Matcher matcher, CharSequence charSeq) { + return (matcher == null) || matcher.matches(charSeq); + } + + static boolean isExact(String glob) { + return (glob.indexOf('*') == -1) && (glob.indexOf('?') == -1); + } + + static final class ExactMatcher implements Matcher { + private final String exact; + + ExactMatcher(String exact) { + this.exact = exact; + } + + @Override + public boolean matches(String str) { + return exact.equals(str); + } + + @Override + public boolean matches(CharSequence charSeq) { + return exact.contentEquals(charSeq); + } + } + + static final class PatternMatcher implements Matcher { + private final Pattern pattern; + + PatternMatcher(Pattern pattern) { + this.pattern = pattern; + } + + @Override + public boolean matches(CharSequence charSeq) { + return pattern.matcher(charSeq).matches(); + } + + @Override + public boolean matches(String str) { + return pattern.matcher(str).matches(); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/NoneSystemAccessProvider.java b/features/dd-trace-core/src/main/java/datadog/trace/core/util/NoneSystemAccessProvider.java new file mode 100644 index 0000000000..1f1a9cd3ef --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/util/NoneSystemAccessProvider.java @@ -0,0 +1,8 @@ +package datadog.trace.core.util; + +final class NoneSystemAccessProvider implements SystemAccessProvider { + @Override + public long getThreadCpuTime() { + return Long.MIN_VALUE; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/SimpleRateLimiter.java b/features/dd-trace-core/src/main/java/datadog/trace/core/util/SimpleRateLimiter.java new file mode 100644 index 0000000000..a011c61f61 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/util/SimpleRateLimiter.java @@ -0,0 +1,82 @@ +package datadog.trace.core.util; + +import datadog.trace.api.time.SystemTimeSource; +import datadog.trace.api.time.TimeSource; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Rate limiter that only supports non-blocking retrieval of a single token at a minimum rate of 1 + * per second. Tokens are not smoothed across the second. + */ +public class SimpleRateLimiter { + private final TimeSource timeSource; + private final int capacity; + private final long startNanos; + private final AtomicLong secondsAndCount; + + public SimpleRateLimiter(int rate) { + this(rate, SystemTimeSource.INSTANCE); + } + + protected SimpleRateLimiter(int rate, TimeSource timeSource) { + this.timeSource = timeSource; + this.startNanos = timeSource.getNanoTicks(); + capacity = Math.max(1, rate); + secondsAndCount = new AtomicLong(0); + } + + public boolean tryAcquire() { + long storedSecondsAndCount; + long newSecondsAndCount; + int seconds = 0; + boolean readTime = true; + do { + storedSecondsAndCount = secondsAndCount.get(); + if (readTime) { + // There will be an issue when the application has been running for more than 2^31 seconds, + // roughly 68 years, so that is an acceptable trade off + seconds = (int) TimeUnit.NANOSECONDS.toSeconds(timeSource.getNanoTicks() - startNanos); + readTime = false; + } + final int storedSeconds = getStoredSeconds(storedSecondsAndCount); + final int storedCount = getStoredCount(storedSecondsAndCount); + final int diff = seconds - storedSeconds; + if (diff <= 0) { + // We're roughly in the same second, so try to acquire a token + final int count = storedCount + 1; + if (count > capacity || count < 0) { + // We're all out of tokens + return false; + } + newSecondsAndCount = combineSecondsAndCount(storedSeconds, count); + if (diff < 0) { + // If we fail to acquire a token, then reread the time since it's taken too long + readTime = true; + } + } else { + // At least one second has elapsed, so try to reset the tokens + newSecondsAndCount = combineSecondsAndCount(seconds, 1); + } + } while (!secondsAndCount.compareAndSet(storedSecondsAndCount, newSecondsAndCount)); + + return true; + } + + public int getCapacity() { + return capacity; + } + + private static int getStoredSeconds(long timeAndCount) { + return (int) (timeAndCount >> 32); + } + + private static int getStoredCount(long timeAndCount) { + return (int) (timeAndCount & Integer.MAX_VALUE); + } + + private static long combineSecondsAndCount(int seconds, int count) { + // We can safely assume that count is a positive int + return ((long) (seconds & Integer.MAX_VALUE)) << 32 | count; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccess.java b/features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccess.java new file mode 100644 index 0000000000..da82cf7162 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccess.java @@ -0,0 +1,59 @@ +package datadog.trace.core.util; + +import datadog.trace.api.Config; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class SystemAccess { + private static final Logger log = LoggerFactory.getLogger(SystemAccess.class); + private static volatile SystemAccessProvider systemAccessProvider = SystemAccessProvider.NONE; + + /** + * Disable JMX based system access. Will flip back to the {@linkplain SystemAccessProvider#NONE} + * implementation. + */ + public static void disableJmx() { + log.debug("Disabling JMX system access provider"); + systemAccessProvider = SystemAccessProvider.NONE; + } + + /** Enable JMX accesses */ + public static void enableJmx() { + if (!Config.get().isProfilingEnabled() && !Config.get().isHealthMetricsEnabled()) { + log.debug("Will not enable JMX access. Profiling and metrics are both disabled."); + return; + } + try { + log.debug("Enabling JMX system provider"); + /* + * Can not use direct class reference to JmxSystemProvider since on some rare JVM implementations + * using eager class resolution that class could be resolved at the moment when methods are being loaded, + * potentially triggering j.u.l initialization which is potentially dangerous and can be done only at certain + * point in time. + * Using reflection should alleviate this problem - no class constant to resolve during class load. The JMX + * system provider will be loaded at exact moment when the reflection code is executed. Then it is up + * to the caller to ensure that it is safe to use JMX. + */ + systemAccessProvider = + (SystemAccessProvider) + Class.forName( + "datadog.trace.core.util.JmxSystemAccessProvider", + false, + SystemAccess.class.getClassLoader()) + .getField("INSTANCE") + .get(null); + } catch (final ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + log.info("Unable to initialize JMX system provider", e); + } + } + + /** + * Get the current thread CPU time + * + * @return the actual current thread CPU time or {@linkplain Long#MIN_VALUE} if the JMX provider + * is not available + */ + public static long getCurrentThreadCpuTime() { + return systemAccessProvider.getThreadCpuTime(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccessProvider.java b/features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccessProvider.java new file mode 100644 index 0000000000..b7eb198a29 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccessProvider.java @@ -0,0 +1,15 @@ +package datadog.trace.core.util; + +/** + * A pluggable system provider used by {@linkplain SystemAccess}. {@linkplain SystemAccess} may not + * use JMX classes (even via transitive dependencies) due to potential race in j.u.l initialization. + * Therefore it uses an abstract {@linkplain SystemAccessProvider} type to hold the actual + * implementation which may be switched between the {@linkplain SystemAccessProvider#NONE} and + * {@linkplain JmxSystemAccessProvider} on-the-fly once JMX is safe to use. + */ +public interface SystemAccessProvider { + SystemAccessProvider NONE = new NoneSystemAccessProvider(); + + /** Get the current thread CPU time */ + long getThreadCpuTime(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/TagsMatcher.java b/features/dd-trace-core/src/main/java/datadog/trace/core/util/TagsMatcher.java new file mode 100644 index 0000000000..ef680e5b07 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/util/TagsMatcher.java @@ -0,0 +1,42 @@ +package datadog.trace.core.util; + +import datadog.trace.core.CoreSpan; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class TagsMatcher { + + public static TagsMatcher create(Map tags) { + Map matchers = + tags.entrySet().stream() + .collect( + Collectors.toMap( + Map.Entry::getKey, + entry -> { + String tagValue = entry.getValue(); + if (Matchers.isExact(tagValue)) { + return new Matchers.ExactMatcher(tagValue); + } else { + Pattern pattern = GlobPattern.globToRegexPattern(tagValue); + return new Matchers.PatternMatcher(pattern); + } + })); + return new TagsMatcher(matchers); + } + + private final Map matchers; + + public TagsMatcher(Map matchers) { + this.matchers = matchers; + } + + public > boolean matches(T span) { + return matchers.entrySet().stream() + .allMatch( + entry -> { + String tagValue = span.getTag(entry.getKey()); + return tagValue != null && entry.getValue().matches(tagValue); + }); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/ddagent/DroppingPolicy.java b/features/dd-trace-core/src/main/java/datadog/trace/ddagent/DroppingPolicy.java new file mode 100644 index 0000000000..1b8f9de805 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/ddagent/DroppingPolicy.java @@ -0,0 +1,16 @@ +package datadog.trace.ddagent; + +public interface DroppingPolicy { + + DroppingPolicy DISABLED = new DisabledDroppingPolicy(); + + boolean active(); + + class DisabledDroppingPolicy implements DroppingPolicy { + + @Override + public boolean active() { + return false; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java b/features/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java new file mode 100644 index 0000000000..e0e824b3d1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java @@ -0,0 +1,184 @@ +package datadog.trace.lambda; + +import static datadog.trace.api.TracePropagationStyle.DATADOG; +import static java.util.concurrent.TimeUnit.SECONDS; + +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.Moshi; +import datadog.trace.api.DDSpanId; +import datadog.trace.api.DDTags; +import datadog.trace.api.DDTraceId; +import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.core.propagation.ExtractedContext; +import datadog.trace.core.propagation.PropagationTags; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class communicates with the serverless extension on start invocation and on end invocation. + * The extension is responsible to parse the context and create the invocation span. The tracer will + * also create the span (to be dropped by the extension) so newly created spans will be parenting to + * the right span. + */ +public class LambdaHandler { + + private static final Logger log = LoggerFactory.getLogger(LambdaHandler.class); + + // Note: this header is used to disable tracing for calls to the extension + private static final String DATADOG_META_LANG = "Datadog-Meta-Lang"; + + private static final String DATADOG_TRACE_ID = "x-datadog-trace-id"; + private static final String DATADOG_SPAN_ID = "x-datadog-span-id"; + private static final String DATADOG_SAMPLING_PRIORITY = "x-datadog-sampling-priority"; + private static final String DATADOG_INVOCATION_ERROR = "x-datadog-invocation-error"; + private static final String DATADOG_INVOCATION_ERROR_MSG = "x-datadog-invocation-error-msg"; + private static final String DATADOG_INVOCATION_ERROR_TYPE = "x-datadog-invocation-error-type"; + private static final String DATADOG_INVOCATION_ERROR_STACK = "x-datadog-invocation-error-stack"; + private static final String DATADOG_TAGS_KEY = "x-datadog-tags"; + + private static final String START_INVOCATION = "/lambda/start-invocation"; + private static final String END_INVOCATION = "/lambda/end-invocation"; + + private static final Long REQUEST_TIMEOUT_IN_S = 1L; + + private static OkHttpClient HTTP_CLIENT = + new OkHttpClient.Builder() + .retryOnConnectionFailure(true) + .connectTimeout(REQUEST_TIMEOUT_IN_S, SECONDS) + .writeTimeout(REQUEST_TIMEOUT_IN_S, SECONDS) + .readTimeout(REQUEST_TIMEOUT_IN_S, SECONDS) + .callTimeout(REQUEST_TIMEOUT_IN_S, SECONDS) + .build(); + + private static final MediaType jsonMediaType = MediaType.parse("application/json"); + private static final JsonAdapter adapter = + new Moshi.Builder() + .add(ByteArrayInputStream.class, new ReadFromInputStreamJsonAdapter()) + .add(SkipUnsupportedTypeJsonAdapter.newFactory()) + .build() + .adapter(Object.class); + + private static String EXTENSION_BASE_URL = "http://127.0.0.1:8124"; + + public static AgentSpan.Context notifyStartInvocation( + Object event, PropagationTags.Factory propagationTagsFactory) { + RequestBody body = RequestBody.create(jsonMediaType, writeValueAsString(event)); + try (Response response = + HTTP_CLIENT + .newCall( + new Request.Builder() + .url(EXTENSION_BASE_URL + START_INVOCATION) + .addHeader(DATADOG_META_LANG, "java") + .post(body) + .build()) + .execute()) { + if (response.isSuccessful()) { + final String traceID = response.headers().get(DATADOG_TRACE_ID); + final String priority = response.headers().get(DATADOG_SAMPLING_PRIORITY); + if (null != traceID && null != priority) { + int samplingPriority = PrioritySampling.UNSET; + try { + samplingPriority = Integer.parseInt(priority); + } catch (final NumberFormatException ignored) { + log.warn("could not read the sampling priority, defaulting to UNSET"); + } + log.debug( + "notifyStartInvocation success, found traceID = {} and samplingPriority = {}", + traceID, + samplingPriority); + PropagationTags propagationTags = + propagationTagsFactory.fromHeaderValue( + PropagationTags.HeaderType.DATADOG, response.headers().get(DATADOG_TAGS_KEY)); + return new ExtractedContext( + DDTraceId.from(traceID), + DDSpanId.ZERO, + samplingPriority, + null, + propagationTags, + DATADOG); + } else { + log.debug( + "could not find traceID or sampling priority in notifyStartInvocation, not injecting the context"); + } + } + } catch (Throwable ignored) { + log.error("could not reach the extension"); + } + return null; + } + + public static boolean notifyEndInvocation(AgentSpan span, Object result, boolean isError) { + + if (null == span || null == span.getSamplingPriority()) { + log.error( + "could not notify the extension as the lambda span is null or no sampling priority has been found"); + return false; + } + RequestBody body = RequestBody.create(jsonMediaType, writeValueAsString(result)); + Request.Builder builder = + new Request.Builder() + .url(EXTENSION_BASE_URL + END_INVOCATION) + .addHeader(DATADOG_TRACE_ID, span.getTraceId().toString()) + .addHeader(DATADOG_SPAN_ID, DDSpanId.toString(span.getSpanId())) + .addHeader(DATADOG_SAMPLING_PRIORITY, span.getSamplingPriority().toString()) + .addHeader(DATADOG_META_LANG, "java") + .post(body); + + Object errorMessage = span.getTag(DDTags.ERROR_MSG); + if (errorMessage != null) { + builder.addHeader(DATADOG_INVOCATION_ERROR_MSG, errorMessage.toString()); + } + + Object errorType = span.getTag(DDTags.ERROR_TYPE); + if (errorType != null) { + builder.addHeader(DATADOG_INVOCATION_ERROR_TYPE, errorType.toString()); + } + + Object errorStack = span.getTag(DDTags.ERROR_STACK); + if (errorStack != null) { + String encodedErrStack = + Base64.getEncoder() + .encodeToString(errorStack.toString().getBytes(StandardCharsets.UTF_8)); + builder.addHeader(DATADOG_INVOCATION_ERROR_STACK, encodedErrStack); + } + + if (isError) { + builder.addHeader(DATADOG_INVOCATION_ERROR, "true"); + } + + try (Response response = HTTP_CLIENT.newCall(builder.build()).execute()) { + if (response.isSuccessful()) { + log.debug("notifyEndInvocation success"); + return true; + } + } catch (Exception e) { + log.error("could not reach the extension, not injecting the context", e); + } + return false; + } + + public static String writeValueAsString(Object obj) { + String json = "{}"; + if (null != obj) { + try { + json = adapter.toJson(obj); + } catch (Exception e) { + log.debug("could not write the value into a string", e); + } + } + return json; + } + + public static void setExtensionBaseUrl(String extensionBaseUrl) { + EXTENSION_BASE_URL = extensionBaseUrl; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java b/features/dd-trace-core/src/main/java/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java new file mode 100644 index 0000000000..76b6081d24 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java @@ -0,0 +1,34 @@ +package datadog.trace.lambda; + +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.JsonReader; +import com.squareup.moshi.JsonWriter; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import okio.BufferedSink; + +public final class ReadFromInputStreamJsonAdapter extends JsonAdapter { + + @Override + public ByteArrayInputStream fromJson(JsonReader reader) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void toJson(JsonWriter writer, ByteArrayInputStream inputStream) throws IOException { + if (inputStream != null) { + BufferedSink sink = writer.valueSink(); + byte[] bytes = getInputBytes(inputStream); + sink.write(bytes); + sink.flush(); + } + } + + private byte[] getInputBytes(ByteArrayInputStream inputStream) throws IOException { + inputStream.mark(0); + byte[] bytes = new byte[inputStream.available()]; + inputStream.read(bytes); + inputStream.reset(); + return bytes; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/lambda/SkipUnsupportedTypeJsonAdapter.java b/features/dd-trace-core/src/main/java/datadog/trace/lambda/SkipUnsupportedTypeJsonAdapter.java new file mode 100644 index 0000000000..6be76c0522 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/lambda/SkipUnsupportedTypeJsonAdapter.java @@ -0,0 +1,39 @@ +package datadog.trace.lambda; + +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.JsonReader; +import com.squareup.moshi.JsonWriter; +import com.squareup.moshi.Moshi; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Set; + +public final class SkipUnsupportedTypeJsonAdapter extends JsonAdapter { + + @Override + public T fromJson(JsonReader reader) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void toJson(JsonWriter writer, T value) throws IOException { + // nothing to do when we deal with an unsupported type, let's skip it. + writer.beginObject(); + writer.endObject(); + } + + public static Factory newFactory() { + return new Factory() { + @Override + public JsonAdapter create( + Type requestedType, Set annotations, Moshi moshi) { + try { + return moshi.nextAdapter(this, requestedType, annotations); + } catch (IllegalArgumentException e) { + return new SkipUnsupportedTypeJsonAdapter<>(); + } + } + }; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/logging/GlobalLogLevelSwitcher.java b/features/dd-trace-core/src/main/java/datadog/trace/logging/GlobalLogLevelSwitcher.java new file mode 100644 index 0000000000..400772b7f2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/logging/GlobalLogLevelSwitcher.java @@ -0,0 +1,53 @@ +package datadog.trace.logging; + +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GlobalLogLevelSwitcher implements LogLevelSwitcher { + private static volatile LogLevelSwitcher INSTANCE = null; + + public static LogLevelSwitcher get() { + LogLevelSwitcher switcher = INSTANCE; + if (switcher == null) { + ILoggerFactory factory = LoggerFactory.getILoggerFactory(); + INSTANCE = switcher = new GlobalLogLevelSwitcher(factory); + } + return switcher; + } + + private final Logger log; + private final LogLevelSwitcher delegate; + + GlobalLogLevelSwitcher(ILoggerFactory factory) { + log = factory.getLogger(GlobalLogLevelSwitcher.class.getName()); + if (factory instanceof LogLevelSwitcher) { + delegate = (LogLevelSwitcher) factory; + } else { + log.error( + "Unable to find global log level switcher, found {}", factory.getClass().getSimpleName()); + delegate = null; + } + } + + @Override + public void switchLevel(LogLevel level) { + if (delegate != null) { + delegate.switchLevel(level); + } + } + + @Override + public void restore() { + if (delegate != null) { + delegate.restore(); + } + } + + @Override + public void reinitialize() { + if (delegate != null) { + delegate.reinitialize(); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java b/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java new file mode 100644 index 0000000000..7fb8ab5981 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java @@ -0,0 +1,39 @@ +package datadog.trace.logging; + +/** Log level enum. */ +public enum LogLevel { + TRACE, + DEBUG, + INFO, + WARN, + ERROR, + OFF; + + /** + * Case insensitive conversion from {@link String} to {@link LogLevel}. + * + *

    Fallback is {@link #INFO}. + * + * @param level the {@link LogLevel} as a {@link String} + * @return the corresponding {@link LogLevel} enum + */ + public static LogLevel fromString(String level) { + String upper = level.toUpperCase(); + try { + return Enum.valueOf(LogLevel.class, upper); + } catch (Throwable t) { + // INFO is the fallback + return LogLevel.INFO; + } + } + + /** + * Check if a {@link LogLevel} is enabled for this {@link LogLevel}. + * + * @param level the {@link LogLevel} to check + * @return true if the {@code level} is enabled, false otherwise + */ + public boolean isEnabled(LogLevel level) { + return this.compareTo(level) >= 0; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevelSwitcher.java b/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevelSwitcher.java new file mode 100644 index 0000000000..3e1adfe12f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevelSwitcher.java @@ -0,0 +1,18 @@ +package datadog.trace.logging; + +/** Enables temporary runtime switching of LogLevel. */ +public interface LogLevelSwitcher { + + /** + * Temporarily switch the current LogLevel to a new LogLevel + * + * @param level the LogLevel to switch to + */ + void switchLevel(LogLevel level); + + /** Restore the LogLevel to the original setting. */ + void restore(); + + /** Re-execute logging settings initialization */ + void reinitialize(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/logging/LoggingSettingsDescription.java b/features/dd-trace-core/src/main/java/datadog/trace/logging/LoggingSettingsDescription.java new file mode 100644 index 0000000000..90924168ae --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/logging/LoggingSettingsDescription.java @@ -0,0 +1,20 @@ +package datadog.trace.logging; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public final class LoggingSettingsDescription { + private LoggingSettingsDescription() {} + + private static volatile Map description = Collections.emptyMap(); + + public static void setDescription(Map description) { + LoggingSettingsDescription.description = + Collections.unmodifiableMap(new HashMap<>(description)); + } + + public static Map getDescription() { + return description; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/monitor/Counter.java b/features/dd-trace-core/src/main/java/datadog/trace/monitor/Counter.java new file mode 100644 index 0000000000..c7d01ccd12 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/monitor/Counter.java @@ -0,0 +1,14 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.monitor; + +public interface Counter { + + void increment(int delta); + + void incrementErrorCount(String cause, int delta); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/monitor/Monitoring.java b/features/dd-trace-core/src/main/java/datadog/trace/monitor/Monitoring.java new file mode 100644 index 0000000000..6a75d6b304 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/monitor/Monitoring.java @@ -0,0 +1,46 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.monitor; + +import datadog.trace.monitor.NoOpCounter; +import datadog.trace.monitor.NoOpRecording; + +public interface Monitoring { + Monitoring DISABLED = new DisabledMonitoring(); + + Recording newTimer(String name); + + Recording newTimer(String name, String... tags); + + Recording newThreadLocalTimer(String name); + + Counter newCounter(String name); + + class DisabledMonitoring implements Monitoring { + private DisabledMonitoring() {} + + @Override + public Recording newTimer(String name) { + return NoOpRecording.NO_OP; + } + + @Override + public Recording newTimer(String name, String... tags) { + return NoOpRecording.NO_OP; + } + + @Override + public Recording newThreadLocalTimer(String name) { + return NoOpRecording.NO_OP; + } + + @Override + public Counter newCounter(String name) { + return NoOpCounter.NO_OP; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpCounter.java b/features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpCounter.java new file mode 100644 index 0000000000..e2a78e0605 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpCounter.java @@ -0,0 +1,16 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.monitor; + +public final class NoOpCounter implements Counter { + + public static final Counter NO_OP = new NoOpCounter(); + + public void increment(int delta) {} + + public void incrementErrorCount(String cause, int delta) {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpRecording.java b/features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpRecording.java new file mode 100644 index 0000000000..8f1c05ffa6 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpRecording.java @@ -0,0 +1,26 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.monitor; + +public class NoOpRecording extends Recording { + + public static final Recording NO_OP = new NoOpRecording(); + + @Override + public Recording start() { + return this; + } + + @Override + public void reset() {} + + @Override + public void stop() {} + + @Override + public void flush() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/monitor/Recording.java b/features/dd-trace-core/src/main/java/datadog/trace/monitor/Recording.java new file mode 100644 index 0000000000..501f553850 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/monitor/Recording.java @@ -0,0 +1,22 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.monitor; + +public abstract class Recording implements AutoCloseable { + @Override + public void close() { + stop(); + } + + public abstract Recording start(); + + public abstract void reset(); + + public abstract void stop(); + + public abstract void flush(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/relocate/api/IOLogger.java b/features/dd-trace-core/src/main/java/datadog/trace/relocate/api/IOLogger.java new file mode 100644 index 0000000000..a43ff21390 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/relocate/api/IOLogger.java @@ -0,0 +1,117 @@ +package datadog.trace.relocate.api; + +import org.slf4j.Logger; + +import java.util.concurrent.TimeUnit; + +/** Logger specialized on logging IO-related activity */ +public class IOLogger { + private boolean logNextSuccess = false; + private final Logger log; + private final RatelimitedLogger ratelimitedLogger; + + public IOLogger(final Logger log) { + this(log, new RatelimitedLogger(log, 5, TimeUnit.MINUTES)); + } + + // Visible for testing + IOLogger(final Logger log, final RatelimitedLogger ratelimitedLogger) { + this.log = log; + this.ratelimitedLogger = ratelimitedLogger; + } + + /** @return true if actually logged the message, false otherwise */ + public boolean success(final String format, final Object... arguments) { + if (log.isDebugEnabled()) { + log.debug(format, arguments); + return true; + } + + if (this.logNextSuccess) { + this.logNextSuccess = false; + if (log.isInfoEnabled()) { + log.info(format, arguments); + return true; + } + } + + return false; + } + + /** @return true if actually logged the message, false otherwise */ + public boolean error(final String message) { + return error(message, null, null); + } + + /** @return true if actually logged the message, false otherwise */ + public boolean error(final String message, Exception exception) { + return error(message, null, exception); + } + + /** @return true if actually logged the message, false otherwise */ + public boolean error(final String message, Response response) { + return error(message, response, null); + } + + /** @return true if actually logged the message, false otherwise */ + public boolean error(final String message, Response response, Exception exception) { + if (log.isDebugEnabled()) { + if (response != null) { + log.debug( + "{} Status: {}, Response: {}, Body: {}", + message, + response.getStatusCode(), + response.getMessage(), + response.getBody()); + } else if (exception != null) { + log.debug(message, exception); + } else { + log.debug(message); + } + return true; + } + boolean hasLogged; + if (response != null) { + hasLogged = + ratelimitedLogger.warn( + "{} Status: {} {}", message, response.getStatusCode(), response.getMessage()); + } else if (exception != null) { + // NOTE: We do not pass the full exception to warn on purpose. We don't want to + // print a full stacktrace unless we're in debug mode + hasLogged = + ratelimitedLogger.warn( + "{} {}: {}", message, exception.getClass().getName(), exception.getMessage()); + } else { + hasLogged = ratelimitedLogger.warn(message); + } + if (hasLogged) { + this.logNextSuccess = true; + } + + return hasLogged; + } + + public static final class Response { + private final int statusCode; + private final String message; + private final String body; + + public Response(int statusCode, String message, String body) { + this.statusCode = statusCode; + this.message = message; + this.body = body; + } + + public int getStatusCode() { + return statusCode; + } + + public String getMessage() { + return message; + } + + public String getBody() { + return body; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/relocate/api/RatelimitedLogger.java b/features/dd-trace-core/src/main/java/datadog/trace/relocate/api/RatelimitedLogger.java new file mode 100644 index 0000000000..fe0273a0f4 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/relocate/api/RatelimitedLogger.java @@ -0,0 +1,70 @@ +package datadog.trace.relocate.api; + +import org.slf4j.Logger; + +import java.util.Locale; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import datadog.trace.api.time.SystemTimeSource; +import datadog.trace.api.time.TimeSource; + +/** + * Logger that logs message once per given delay if debugging is disabled. If debugging is enabled + * then it logs every time. + */ +public class RatelimitedLogger { + + private final Logger log; + private final long delayNanos; + private final String noLogMessage; + private final TimeSource timeSource; + + private final AtomicLong nextLogNanos; + + public RatelimitedLogger(final Logger log, final int delay, final TimeUnit timeUnit) { + this(log, delay, timeUnit, SystemTimeSource.INSTANCE); + } + + // Visible for testing + RatelimitedLogger( + final Logger log, final int delay, final TimeUnit timeUnit, final TimeSource timeSource) { + this.log = log; + this.delayNanos = timeUnit.toNanos(delay); + this.noLogMessage = createNoLogMessage(" (Will not log warnings for ", ")", delay, timeUnit); + this.timeSource = timeSource; + nextLogNanos = new AtomicLong(timeSource.getNanoTicks()); + } + + /** @return true if actually logged the message, false otherwise */ + public boolean warn(final String format, final Object... arguments) { + if (log.isDebugEnabled()) { + log.warn(format, arguments); + return true; + } + if (log.isWarnEnabled()) { + final long next = nextLogNanos.get(); + final long now = timeSource.getNanoTicks(); + if (now - next >= 0 && nextLogNanos.compareAndSet(next, now + delayNanos)) { + log.warn(format + noLogMessage, arguments); + return true; + } + } + return false; + } + + private static String createNoLogMessage( + String prefix, String postfix, int delay, TimeUnit timeUnit) { + StringBuilder noLogStringBuilder = new StringBuilder(prefix); + noLogStringBuilder.append(delay); + noLogStringBuilder.append(' '); + String unit = timeUnit.name().toLowerCase(Locale.ROOT); + unit = + delay == 1 + ? unit.substring(0, unit.length() - 1) + : unit; // should we drop the plural s or not? + noLogStringBuilder.append(unit); + noLogStringBuilder.append(postfix); + return noLogStringBuilder.toString(); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/ByteBufferConsumer.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/ByteBufferConsumer.java new file mode 100644 index 0000000000..ba6201e884 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/ByteBufferConsumer.java @@ -0,0 +1,8 @@ +package datadog.trace.serialization; + +import java.nio.ByteBuffer; + +public interface ByteBufferConsumer { + + void accept(int messageCount, ByteBuffer buffer); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/Codec.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/Codec.java new file mode 100644 index 0000000000..9a3c38e51d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/Codec.java @@ -0,0 +1,295 @@ +package datadog.trace.serialization; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import datadog.trace.serialization.EncodingCache; +import datadog.trace.serialization.ValueWriter; +import datadog.trace.serialization.Writable; + +public final class Codec extends ClassValue> { + + public static final Codec INSTANCE = new Codec(); + + private final Map, ValueWriter> config; + + public Codec(Map, ValueWriter> config) { + this.config = config; + } + + @SuppressWarnings("unchecked") + public Codec() { + this(Collections., ValueWriter>emptyMap()); + } + + @Override + protected ValueWriter computeValue(Class clazz) { + ValueWriter writer = config.get(clazz); + if (null != writer) { + return writer; + } + if (Number.class.isAssignableFrom(clazz)) { + if (Double.class == clazz) { + return new DoubleWriter(); + } + if (Float.class == clazz) { + return new FloatWriter(); + } + if (Integer.class == clazz) { + return new IntWriter(); + } + if (Long.class == clazz) { + return new LongWriter(); + } + if (Short.class == clazz) { + return new ShortWriter(); + } + // This is some other Number type, that will be treated as a metric by the + // serializer, so let's write out its double value to be protocol compatible + return new NumberDoubleWriter(); + } + if (clazz.isArray()) { + if (byte[].class == clazz) { + return new ByteArrayWriter(); + } + if (int[].class == clazz) { + return new IntArrayWriter(); + } + if (long[].class == clazz) { + return new LongArrayWriter(); + } + if (double[].class == clazz) { + return new DoubleArrayWriter(); + } + if (float[].class == clazz) { + return new FloatArrayWriter(); + } + if (short[].class == clazz) { + return new ShortArrayWriter(); + } + if (char[].class == clazz) { + return new CharArrayWriter(); + } + if (boolean[].class == clazz) { + return new BooleanArrayWriter(); + } + return new ObjectArrayWriter(); + } + if (Boolean.class == clazz) { + return new BooleanWriter(); + } + if (CharSequence.class.isAssignableFrom(clazz)) { + return CharSequenceWriter.INSTANCE; + } + if (Map.class.isAssignableFrom(clazz)) { + return new MapWriter(); + } + if (Collection.class.isAssignableFrom(clazz)) { + return new CollectionWriter(); + } + if (ByteBuffer.class.isAssignableFrom(clazz)) { + return new ByteBufferWriter(); + } + return DefaultWriter.INSTANCE; + } + + private static final class IntArrayWriter implements ValueWriter { + + @Override + public void write(int[] value, Writable packer, EncodingCache encodingCache) { + packer.startArray(value.length); + for (int i : value) { + packer.writeInt(i); + } + } + } + + private static final class ShortArrayWriter implements ValueWriter { + + @Override + public void write(short[] value, Writable packer, EncodingCache encodingCache) { + packer.startArray(value.length); + for (short i : value) { + packer.writeInt(i); + } + } + } + + private static final class ByteArrayWriter implements ValueWriter { + + @Override + public void write(byte[] value, Writable packer, EncodingCache encodingCache) { + packer.writeBinary(value, 0, value.length); + } + } + + private static final class ByteBufferWriter implements ValueWriter { + + @Override + public void write(ByteBuffer buffer, Writable packer, EncodingCache encodingCache) { + packer.writeBinary(buffer); + } + } + + private static final class BooleanArrayWriter implements ValueWriter { + + @Override + public void write(boolean[] value, Writable packer, EncodingCache encodingCache) { + packer.startArray(value.length); + for (boolean i : value) { + packer.writeBoolean(i); + } + } + } + + private static final class DoubleArrayWriter implements ValueWriter { + + @Override + public void write(double[] value, Writable packer, EncodingCache encodingCache) { + packer.startArray(value.length); + for (double i : value) { + packer.writeDouble(i); + } + } + } + + private static final class FloatArrayWriter implements ValueWriter { + + @Override + public void write(float[] value, Writable packer, EncodingCache encodingCache) { + packer.startArray(value.length); + for (float i : value) { + packer.writeFloat(i); + } + } + } + + private static final class LongArrayWriter implements ValueWriter { + + @Override + public void write(long[] value, Writable packer, EncodingCache encodingCache) { + packer.startArray(value.length); + for (long i : value) { + packer.writeLong(i); + } + } + } + + private static final class CollectionWriter implements ValueWriter> { + + @Override + public void write(Collection collection, Writable packer, EncodingCache encodingCache) { + packer.startArray(collection.size()); + for (Object value : collection) { + packer.writeObject(value, encodingCache); + } + } + } + + private static final class ObjectArrayWriter implements ValueWriter { + + @Override + public void write(Object[] array, Writable packer, EncodingCache encodingCache) { + packer.startArray(array.length); + for (Object value : array) { + packer.writeObject(value, encodingCache); + } + } + } + + private static final class MapWriter implements ValueWriter> { + + @Override + public void write( + Map value, Writable packer, EncodingCache encodingCache) { + packer.writeMap(value, encodingCache); + } + } + + private static final class DoubleWriter implements ValueWriter { + + @Override + public void write(Double value, Writable packer, EncodingCache encodingCache) { + packer.writeDouble(value); + } + } + + private static final class BooleanWriter implements ValueWriter { + + @Override + public void write(Boolean value, Writable packer, EncodingCache encodingCache) { + packer.writeBoolean(value); + } + } + + private static final class FloatWriter implements ValueWriter { + + @Override + public void write(Float value, Writable packer, EncodingCache encodingCache) { + packer.writeFloat(value); + } + } + + private static final class IntWriter implements ValueWriter { + + @Override + public void write(Integer value, Writable packer, EncodingCache encodingCache) { + packer.writeInt(value); + } + } + + private static final class ShortWriter implements ValueWriter { + + @Override + public void write(Short value, Writable packer, EncodingCache encodingCache) { + packer.writeInt(value); + } + } + + private static final class LongWriter implements ValueWriter { + + @Override + public void write(Long value, Writable packer, EncodingCache encodingCache) { + packer.writeLong(value); + } + } + + private static final class NumberDoubleWriter implements ValueWriter { + + @Override + public void write(Number value, Writable packer, EncodingCache encodingCache) { + packer.writeDouble(value.doubleValue()); + } + } + + private static final class CharSequenceWriter implements ValueWriter { + + public static final CharSequenceWriter INSTANCE = new CharSequenceWriter(); + + @Override + public void write(CharSequence value, Writable packer, EncodingCache encodingCache) { + packer.writeString(value, encodingCache); + } + } + + private static final class CharArrayWriter implements ValueWriter { + + @Override + public void write(char[] value, Writable packer, EncodingCache encodingCache) { + packer.writeString(CharBuffer.wrap(value), null); + } + } + + private static final class DefaultWriter implements ValueWriter { + + public static final DefaultWriter INSTANCE = new DefaultWriter(); + + @Override + public void write(Object value, Writable packer, EncodingCache encodingCache) { + CharSequenceWriter.INSTANCE.write(String.valueOf(value), packer, null); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/EncodingCache.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/EncodingCache.java new file mode 100644 index 0000000000..9bcb163279 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/EncodingCache.java @@ -0,0 +1,7 @@ +package datadog.trace.serialization; + +// TODO @FunctionalInterface +public interface EncodingCache { + + byte[] encode(CharSequence s); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/FlushingBuffer.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/FlushingBuffer.java new file mode 100644 index 0000000000..a062207a7b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/FlushingBuffer.java @@ -0,0 +1,107 @@ +package datadog.trace.serialization; + +import java.nio.ByteBuffer; + +import datadog.trace.serialization.ByteBufferConsumer; +import datadog.trace.serialization.StreamingBuffer; + +public final class FlushingBuffer implements StreamingBuffer { + + private final ByteBuffer buffer; + private final ByteBufferConsumer consumer; + + private int messageCount; + private int mark; + + public FlushingBuffer(int capacity, ByteBufferConsumer consumer) { + this.buffer = ByteBuffer.allocate(capacity); + this.consumer = consumer; + } + + @Override + public int capacity() { + return buffer.capacity(); + } + + @Override + public boolean isDirty() { + return mark > 0; + } + + @Override + public void mark() { + mark = buffer.position(); + ++messageCount; + } + + @Override + public boolean flush() { + if (messageCount == 0) { + return false; + } + buffer.limit(mark); + buffer.flip(); + ByteBuffer toPublish = buffer.slice(); + consumer.accept(messageCount, toPublish); + reset(); + return true; + } + + @Override + public void put(byte b) { + buffer.put(b); + } + + @Override + public void putShort(short s) { + buffer.putShort(s); + } + + @Override + public void putChar(char c) { + buffer.putChar(c); + } + + @Override + public void putInt(int i) { + buffer.putInt(i); + } + + @Override + public void putLong(long l) { + buffer.putLong(l); + } + + @Override + public void putFloat(float f) { + buffer.putFloat(f); + } + + @Override + public void putDouble(double d) { + buffer.putDouble(d); + } + + @Override + public void put(byte[] bytes) { + buffer.put(bytes); + } + + @Override + public void put(byte[] bytes, int offset, int length) { + buffer.put(bytes, offset, length); + } + + @Override + public void put(ByteBuffer buffer) { + this.buffer.put(buffer); + } + + @Override + public void reset() { + messageCount = 0; + buffer.position(0); + buffer.limit(buffer.capacity()); + mark = 0; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/GrowableBuffer.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/GrowableBuffer.java new file mode 100644 index 0000000000..87575bdcc2 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/GrowableBuffer.java @@ -0,0 +1,128 @@ +package datadog.trace.serialization; + +import java.nio.ByteBuffer; + +import datadog.trace.serialization.StreamingBuffer; + +/** + * This buffer doesn't have a bounded length, and grows linearly. Don't use it except when + * serialising the contents of a bounded data structure. + */ +public final class GrowableBuffer implements StreamingBuffer { + + private final int initialCapacity; + private ByteBuffer buffer; + private int messageCount; + + public GrowableBuffer(int initialCapacity) { + this.initialCapacity = initialCapacity; + this.buffer = ByteBuffer.allocate(initialCapacity); + } + + public ByteBuffer slice() { + buffer.flip(); + return buffer.slice(); + } + + public int messageCount() { + return messageCount; + } + + @Override + public void reset() { + messageCount = 0; + buffer.position(0); + buffer.limit(buffer.capacity()); + } + + @Override + public int capacity() { + return buffer.capacity(); + } + + @Override + public boolean isDirty() { + return messageCount > 0; + } + + @Override + public void mark() { + ++messageCount; + } + + @Override + public boolean flush() { + return false; + } + + @Override + public void put(byte b) { + checkCapacity(1); + buffer.put(b); + } + + @Override + public void putShort(short s) { + checkCapacity(2); + buffer.putShort(s); + } + + @Override + public void putChar(char c) { + checkCapacity(2); + buffer.putChar(c); + } + + @Override + public void putInt(int i) { + checkCapacity(4); + buffer.putInt(i); + } + + @Override + public void putLong(long l) { + checkCapacity(8); + buffer.putLong(l); + } + + @Override + public void putFloat(float f) { + checkCapacity(4); + buffer.putFloat(f); + } + + @Override + public void putDouble(double d) { + checkCapacity(8); + buffer.putDouble(d); + } + + @Override + public void put(byte[] bytes) { + checkCapacity(bytes.length); + buffer.put(bytes); + } + + @Override + public void put(byte[] bytes, int offset, int length) { + checkCapacity(length); + buffer.put(bytes, offset, length); + } + + @Override + public void put(ByteBuffer buffer) { + checkCapacity(buffer.remaining()); + this.buffer.put(buffer); + } + + private void checkCapacity(int required) { + if (buffer.remaining() < required) { + // round up to next multiple of required + int newSize = (buffer.capacity() + required + initialCapacity - 1) & -initialCapacity; + ByteBuffer newBuffer = ByteBuffer.allocate(newSize); + buffer.flip(); + newBuffer.put(buffer); + buffer = newBuffer; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/Mapper.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/Mapper.java new file mode 100644 index 0000000000..7218d97f9d --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/Mapper.java @@ -0,0 +1,8 @@ +package datadog.trace.serialization; + +import datadog.trace.serialization.Writable; + +// TODO @FunctionalInterface +public interface Mapper { + void map(T data, Writable packer); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/MessageFormatter.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/MessageFormatter.java new file mode 100644 index 0000000000..a8461baaee --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/MessageFormatter.java @@ -0,0 +1,7 @@ +package datadog.trace.serialization; + +public interface MessageFormatter { + boolean format(T message, Mapper mapper); + + void flush(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/StreamingBuffer.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/StreamingBuffer.java new file mode 100644 index 0000000000..01b81c80d0 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/StreamingBuffer.java @@ -0,0 +1,36 @@ +package datadog.trace.serialization; + +import java.nio.ByteBuffer; + +public interface StreamingBuffer { + + int capacity(); + + boolean isDirty(); + + void mark(); + + boolean flush(); + + void put(byte b); + + void putShort(short s); + + void putChar(char c); + + void putInt(int i); + + void putLong(long l); + + void putFloat(float f); + + void putDouble(double d); + + void put(byte[] bytes); + + void put(byte[] bytes, int offset, int length); + + void put(ByteBuffer buffer); + + void reset(); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/ValueWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/ValueWriter.java new file mode 100644 index 0000000000..73c947bfae --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/ValueWriter.java @@ -0,0 +1,8 @@ +package datadog.trace.serialization; + +import datadog.trace.serialization.EncodingCache; + +// TODO @FunctionalInterface +public interface ValueWriter { + void write(T value, Writable writable, EncodingCache encodingCache); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/Writable.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/Writable.java new file mode 100644 index 0000000000..8476b13f83 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/Writable.java @@ -0,0 +1,67 @@ +package datadog.trace.serialization; + +import datadog.trace.serialization.EncodingCache; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import java.nio.ByteBuffer; +import java.util.Map; + +public interface Writable { + void writeNull(); + + void writeBoolean(boolean value); + + void writeObject(Object value, EncodingCache encodingCache); + + void writeObjectString(Object value, EncodingCache encodingCache); + + void writeMap(Map map, EncodingCache encodingCache); + + void writeString(CharSequence s, EncodingCache encodingCache); + + void writeUTF8(byte[] string, int offset, int length); + + void writeUTF8(byte[] string); + + void writeUTF8(UTF8BytesString string); + + void writeBinary(byte[] binary); + + void writeBinary(byte[] binary, int offset, int length); + + /** + * Start a part of the message containing key-value pairs + * + * @param elementCount how many key-value pairs in the section of the message + */ + void startMap(int elementCount); + + /** + * Start a part of the message containing fields or values at ordinal positions + * + * @param elementCount how many fields in the section of the message + */ + void startStruct(int elementCount); + + /** + * Start a part of the message containing positional values + * + * @param elementCount how many array elements in the section of the message + */ + void startArray(int elementCount); + + void writeBinary(ByteBuffer buffer); + + void writeInt(int value); + + void writeSignedInt(int value); + + void writeLong(long value); + + void writeUnsignedLong(long value); + + void writeSignedLong(long value); + + void writeFloat(float value); + + void writeDouble(double value); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/WritableFormatter.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/WritableFormatter.java new file mode 100644 index 0000000000..856f09666b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/WritableFormatter.java @@ -0,0 +1,3 @@ +package datadog.trace.serialization; + +public interface WritableFormatter extends Writable, MessageFormatter {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/msgpack/MsgPackWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/msgpack/MsgPackWriter.java new file mode 100644 index 0000000000..31cbe8db51 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/serialization/msgpack/MsgPackWriter.java @@ -0,0 +1,581 @@ +package datadog.trace.serialization.msgpack; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import datadog.trace.serialization.Codec; +import datadog.trace.serialization.EncodingCache; +import datadog.trace.serialization.Mapper; +import datadog.trace.serialization.StreamingBuffer; +import datadog.trace.serialization.ValueWriter; +import datadog.trace.serialization.WritableFormatter; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Not thread-safe (use one per thread). */ +public class MsgPackWriter implements WritableFormatter { + + private static final Logger log = LoggerFactory.getLogger(MsgPackWriter.class); + + // see https://github.com/msgpack/msgpack/blob/master/spec.md + public static final byte NULL = (byte) 0xC0; + + public static final byte FALSE = (byte) 0xC2; + public static final byte TRUE = (byte) 0xC3; + + public static final byte UINT8 = (byte) 0xCC; + public static final byte UINT16 = (byte) 0xCD; + public static final byte UINT32 = (byte) 0xCE; + public static final byte UINT64 = (byte) 0xCF; + + public static final byte INT8 = (byte) 0xD0; + public static final byte INT16 = (byte) 0xD1; + public static final byte INT32 = (byte) 0xD2; + public static final byte INT64 = (byte) 0xD3; + + public static final byte FLOAT32 = (byte) 0xCA; + public static final byte FLOAT64 = (byte) 0xCB; + + public static final byte STR8 = (byte) 0xD9; + public static final byte STR16 = (byte) 0xDA; + public static final byte STR32 = (byte) 0xDB; + + public static final byte BIN8 = (byte) 0xC4; + public static final byte BIN16 = (byte) 0xC5; + public static final byte BIN32 = (byte) 0xC6; + + public static final byte ARRAY16 = (byte) 0xDC; + public static final byte ARRAY32 = (byte) 0xDD; + + public static final byte MAP16 = (byte) 0xDE; + public static final byte MAP32 = (byte) 0xDF; + + public static final int NEGFIXNUM = 0xE0; + public static final int FIXSTR = 0xA0; + public static final int FIXARRAY = 0x90; + public static final int FIXMAP = 0x80; + + private final Codec codec; + + private final StreamingBuffer buffer; + + public MsgPackWriter(StreamingBuffer buffer) { + this(Codec.INSTANCE, buffer); + } + + public MsgPackWriter(Codec codec, StreamingBuffer buffer) { + this.codec = codec; + this.buffer = buffer; + } + + @Override + public void flush() { + if (buffer.isDirty()) { + buffer.flush(); + } + } + + @Override + public boolean format(T message, Mapper mapper) { + try { + mapper.map(message, this); + buffer.mark(); + return true; + } catch (BufferOverflowException overflow) { + // if the buffer has finite capacity, it will overflow + // if we tried to serialise a message larger than the + // max capacity, then reject the message + if (buffer.flush()) { + try { + mapper.map(message, this); + buffer.mark(); + return true; + } catch (BufferOverflowException fatal) { + log.debug( + "dropping message because its serialized size is too large (> {}MB)", + (buffer.capacity() >>> 20)); + } + } + buffer.reset(); + return false; + } + } + + // NOTE - implementations pulled up to this level should + // not write directly to the buffer + + @Override + public void writeMap(Map map, EncodingCache encodingCache) { + startMap(map.size()); + for (Map.Entry entry : map.entrySet()) { + writeString(entry.getKey(), encodingCache); + writeObject(entry.getValue(), encodingCache); + } + } + + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public void writeObject(Object value, EncodingCache encodingCache) { + // unpeel a very common case, but should try to move away from sending + // UTF8BytesString down this codepath at all + if (value instanceof UTF8BytesString) { + writeUTF8((UTF8BytesString) value); + } else if (null == value) { + writeNull(); + } else { + ValueWriter writer = codec.get(value.getClass()); + writer.write(value, this, encodingCache); + } + } + + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public void writeObjectString(Object value, EncodingCache encodingCache) { + // unpeel a very common case, but should try to move away from sending + // UTF8BytesString down this codepath at all + if (value instanceof UTF8BytesString) { + writeUTF8((UTF8BytesString) value); + } else if (null == value) { + writeNull(); + } else { + String s = String.valueOf(value); + if (null != encodingCache) { + byte[] utf8 = encodingCache.encode(s); + if (null != utf8) { + writeUTF8(utf8); + return; + } + } + writeUTF8(s.getBytes(UTF_8)); + } + } + + @Override + public void writeNull() { + buffer.put(NULL); + } + + @Override + public void writeBoolean(boolean value) { + buffer.put(value ? TRUE : FALSE); + } + + @Override + public void writeString(CharSequence s, EncodingCache encodingCache) { + if (null == s) { + writeNull(); + } else { + if (null != encodingCache) { + byte[] utf8 = encodingCache.encode(s); + if (null != utf8) { + writeUTF8(utf8); + return; + } + } + if (s instanceof UTF8BytesString) { + writeUTF8((UTF8BytesString) s); + } else { + writeUTF8(String.valueOf(s).getBytes(UTF_8)); + } + } + } + + @Override + public void writeUTF8(byte[] string, int offset, int length) { + writeStringHeader(length); + buffer.put(string, offset, length); + } + + @Override + public void writeUTF8(byte[] string) { + writeUTF8(string, 0, string.length); + } + + @Override + public void writeUTF8(UTF8BytesString string) { + writeStringHeader(string.encodedLength()); + buffer.put(string.getUtf8Bytes()); + } + + @Override + public void writeBinary(byte[] binary) { + writeBinaryHeader(binary.length); + buffer.put(binary); + } + + @Override + public void writeBinary(byte[] binary, int offset, int length) { + writeBinaryHeader(length); + buffer.put(binary, offset, length); + } + + @Override + public void writeBinary(ByteBuffer binary) { + ByteBuffer slice = binary.slice(); + writeBinaryHeader(slice.limit() - slice.position()); + buffer.put(slice); + } + + @Override + public void writeInt(int value) { + if (value < 0) { + switch (Integer.numberOfLeadingZeros(~value)) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + buffer.put(INT32); + buffer.putInt(value); + break; + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + buffer.put(INT16); + buffer.putChar((char) value); + break; + case 25: + case 26: + buffer.put(INT8); + buffer.put((byte) value); + break; + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + default: + buffer.put((byte) (NEGFIXNUM | value)); + } + } else { + switch (Integer.numberOfLeadingZeros(value)) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + buffer.put(UINT32); + buffer.putInt(value); + break; + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + buffer.put(UINT16); + buffer.putChar((char) value); + break; + case 24: + buffer.put(UINT8); + buffer.put((byte) value); + break; + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + default: + buffer.put((byte) value); + } + } + } + + @Override + public void writeSignedInt(int value) { + writeInt(value); + } + + @Override + public void writeLong(long value) { + writeLongInternal(value, false); + } + + @Override + public void writeUnsignedLong(long value) { + writeLongInternal(value, true); + } + + public void writeLongInternal(long value, boolean forceUnsigned) { + if (value < 0 && !forceUnsigned) { + switch (Long.numberOfLeadingZeros(~value)) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + buffer.put(INT64); + buffer.putLong(value); + break; + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + buffer.put(INT32); + buffer.putInt((int) value); + break; + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + buffer.put(INT16); + buffer.putChar((char) value); + break; + case 57: + case 58: + buffer.put(INT8); + buffer.put((byte) value); + break; + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + default: + buffer.put((byte) (NEGFIXNUM | value)); + } + } else { + switch (Long.numberOfLeadingZeros(value)) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + buffer.put(UINT64); + buffer.putLong(value); + break; + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + buffer.put(UINT32); + buffer.putInt((int) value); + break; + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + buffer.put(UINT16); + buffer.putChar((char) value); + break; + case 56: + buffer.put(UINT8); + buffer.put((byte) value); + break; + case 57: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + default: + buffer.put((byte) value); + } + } + } + + @Override + public void writeSignedLong(long value) { + writeLong(value); + } + + @Override + public void writeFloat(float value) { + // The datadog agent fails to decode FLOAT32 even though the code in read_bytes.go looks like + // it will try to decode FLOAT32 just fine. Even if there will be a fix in a future datadog + // agent release, we need to be backwards compatible here by sending it as a FLOAT64 instead. + buffer.put(FLOAT64); + buffer.putDouble(value); + } + + @Override + public void writeDouble(double value) { + buffer.put(FLOAT64); + buffer.putDouble(value); + } + + @Override + public void startMap(int elementCount) { + if (elementCount < 0x10) { + buffer.put((byte) (FIXMAP | elementCount)); + } else if (elementCount < 0x10000) { + buffer.put(MAP16); + buffer.putShort((short) elementCount); + } else { + buffer.put(MAP32); + buffer.putInt(elementCount); + } + } + + @Override + public void startStruct(int elementCount) { + startArray(elementCount); + } + + @Override + public void startArray(int elementCount) { + if (elementCount < 0x10) { + buffer.put((byte) (FIXARRAY | elementCount)); + } else if (elementCount < 0x10000) { + buffer.put(ARRAY16); + buffer.putShort((short) elementCount); + } else { + buffer.put(ARRAY32); + buffer.putInt(elementCount); + } + } + + void writeStringHeader(int length) { + if (length < 0x10) { + buffer.put((byte) (FIXSTR | length)); + } else if (length < 0x100) { + buffer.put(STR8); + buffer.put((byte) length); + } else if (length < 0x10000) { + buffer.put(STR16); + buffer.putShort((short) length); + } else { + buffer.put(STR32); + buffer.putInt(length); + } + } + + void writeBinaryHeader(int length) { + if (length < 0x100) { + buffer.put(BIN8); + buffer.put((byte) length); + } else if (length < 0x10000) { + buffer.put(BIN16); + buffer.putShort((short) length); + } else { + buffer.put(BIN32); + buffer.putInt(length); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/AgentProxySelector.java b/features/dd-trace-core/src/main/java/datadog/trace/util/AgentProxySelector.java new file mode 100644 index 0000000000..7bbb171ad1 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/AgentProxySelector.java @@ -0,0 +1,36 @@ +package datadog.trace.util; + +import java.io.IOException; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.SocketAddress; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import datadog.trace.api.Config; + +public final class AgentProxySelector extends ProxySelector { + public static final ProxySelector INSTANCE = new AgentProxySelector(); + + private static final List DIRECT = Collections.singletonList(Proxy.NO_PROXY); + + private final Set noProxyHosts = Config.get().getNoProxyHosts(); + + private final ProxySelector defaultProxySelector = ProxySelector.getDefault(); + + @Override + public List select(final URI uri) { + if (null != uri.getHost() && noProxyHosts.contains(uri.getHost())) { + return DIRECT; + } else { + return defaultProxySelector.select(uri); + } + } + + @Override + public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) { + defaultProxySelector.connectFailed(uri, sa, ioe); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/AgentTaskScheduler.java b/features/dd-trace-core/src/main/java/datadog/trace/util/AgentTaskScheduler.java new file mode 100644 index 0000000000..e7a0821c64 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/AgentTaskScheduler.java @@ -0,0 +1,348 @@ +package datadog.trace.util; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; +import static datadog.trace.util.AgentThreadFactory.AGENT_THREAD_GROUP; +import static datadog.trace.util.AgentThreadFactory.AgentThread.TASK_SCHEDULER; +import static datadog.trace.util.AgentThreadFactory.newAgentThread; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.ref.WeakReference; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Delayed; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import datadog.trace.util.AgentThreadFactory.AgentThread; + +public class AgentTaskScheduler implements Executor { + private static final Logger log = LoggerFactory.getLogger(AgentTaskScheduler.class); + public static final AgentTaskScheduler INSTANCE = new AgentTaskScheduler(TASK_SCHEDULER); + + private static final long SHUTDOWN_TIMEOUT = 5; // seconds + + public interface Task { + void run(T target); + } + + public interface Target { + T get(); + } + + public static final class RunnableTask implements Task { + public static final RunnableTask INSTANCE = new RunnableTask(); + + @Override + public void run(final Runnable target) { + target.run(); + } + } + + public static class Scheduled implements Target { + private volatile T referent; + + private Scheduled(final T referent) { + this.referent = referent; + } + + @Override + public T get() { + return referent; + } + + public void cancel() { + referent = null; + } + } + + private static final class WeakTarget extends WeakReference implements Target { + private WeakTarget(final T referent) { + super(referent); + } + } + + private final DelayQueue> workQueue = new DelayQueue<>(); + private final AgentThread agentThread; + private volatile Thread worker; + private volatile boolean shutdown; + + public AgentTaskScheduler(final AgentThread agentThread) { + this.agentThread = agentThread; + } + + @Override + public void execute(final Runnable target) { + schedule(RunnableTask.INSTANCE, target, 0, MILLISECONDS); + } + + public Scheduled schedule( + final Task task, final T target, final long initialDelay, final TimeUnit unit) { + final Scheduled scheduled = new Scheduled<>(target); + scheduleTarget(task, scheduled, initialDelay, 0, unit); + return scheduled; + } + + public Scheduled schedule( + final Runnable target, final long initialDelay, final TimeUnit unit) { + return schedule(RunnableTask.INSTANCE, target, initialDelay, unit); + } + + /** + * Adds a random jitter of up to 10 seconds to the delay. This avoids a fleet of traced + * applications starting at the same time and scheduling the same publishing task in sync + */ + public Scheduled scheduleWithJitter( + final Task task, final T target, final long initialDelay, final TimeUnit unit) { + + // schedule to start after geometrically distributed number of seconds expressed in + // milliseconds, with p = 0.25, meaning the probability that the aggregator will not + // have started by the nth second is 0.25(0.75)^n-1 (or a 1% chance of not having + // started within 10 seconds, where a cap is applied) + long randomMillis = + unit.toMillis(initialDelay) + + Math.min( + (long) + (1000D + * Math.log(ThreadLocalRandom.current().nextDouble()) + / Math.log(1 - 0.25)), + 10_000); + + return schedule(task, target, randomMillis, MILLISECONDS); + } + + public Scheduled scheduleWithJitter( + final Runnable target, final long initialDelay, final TimeUnit unit) { + return scheduleWithJitter(RunnableTask.INSTANCE, target, initialDelay, unit); + } + + public Scheduled scheduleAtFixedRate( + final Task task, + final T target, + final long initialDelay, + final long period, + final TimeUnit unit) { + final Scheduled scheduled = new Scheduled<>(target); + scheduleTarget(task, scheduled, initialDelay, period, unit); + return scheduled; + } + + public Scheduled scheduleAtFixedRate( + final Runnable target, final long initialDelay, final long period, final TimeUnit unit) { + return scheduleAtFixedRate(RunnableTask.INSTANCE, target, initialDelay, period, unit); + } + + public void weakScheduleAtFixedRate( + final Task task, + final T target, + final long initialDelay, + final long period, + final TimeUnit unit) { + scheduleTarget(task, new WeakTarget<>(target), initialDelay, period, unit); + } + + public void weakScheduleAtFixedRate( + final Runnable target, final long initialDelay, final long period, final TimeUnit unit) { + weakScheduleAtFixedRate(RunnableTask.INSTANCE, target, initialDelay, period, unit); + } + + private void scheduleTarget( + final Task task, + final Target target, + final long initialDelay, + final long period, + final TimeUnit unit) { + + if (target == null || target.get() == null) { + return; + } + + if (!shutdown && worker == null) { + synchronized (workQueue) { + if (!shutdown && worker == null) { + prepareWorkQueue(); + try { + worker = newAgentThread(agentThread, new Worker()); + // register hook after worker is assigned, but before we start it + Runtime.getRuntime().addShutdownHook(new ShutdownHook()); + worker.start(); + } catch (final IllegalStateException e) { + shutdown = true; // couldn't add hook, JVM is shutting down + } + } + } + } + + if (!shutdown) { + workQueue.offer(new PeriodicTask<>(task, target, initialDelay, period, unit)); + } else { + log.debug("Agent task scheduler is shutdown. Will not run {}", describeTask(task, target)); + } + } + + private void prepareWorkQueue() { + try { + // exercise 'poll' method to make sure all relevant queue synchronizer types are preloaded + // here rather than in the Worker when it calls 'take' - this avoids a potential loop-back + workQueue.poll(1, NANOSECONDS); + } catch (final InterruptedException e) { + // ignore, we only want to preload queue internals + } + } + + // for testing + int taskCount() { + return workQueue.size(); + } + + public boolean isShutdown() { + return shutdown; + } + + public static void initialize() { + AgentTaskScheduler.INSTANCE.placeholder(); + } + + private void placeholder() { + /* + * Placeholder empty method body used only to make compiler happy when initializing this class by accessing + * the static INSTANCE field. + */ + } + + public void shutdown(final long timeout, final TimeUnit unit) { + shutdown = true; + final Thread t = worker; + if (t != null) { + t.interrupt(); + if (timeout > 0) { + try { + t.join(unit.toMillis(timeout)); + } catch (final InterruptedException e) { + // continue shutdown... + } + } + } + } + + private static String describeTask(final Task task, final Target target) { + return "periodic task " + task.getClass().getSimpleName() + " with target " + target.get(); + } + + private final class ShutdownHook extends Thread { + ShutdownHook() { + super(AGENT_THREAD_GROUP, agentThread.threadName + "-shutdown-hook"); + } + + @Override + public void run() { + shutdown(SHUTDOWN_TIMEOUT, SECONDS); + } + } + + private final class Worker implements Runnable { + @Override + public void run() { + while (!shutdown) { + PeriodicTask work = null; + try { + work = workQueue.take(); + work.run(); + } catch (final Throwable e) { + if (work != null) { + log.debug("Uncaught exception from {}", work, e); + } + } finally { + if (work != null && work.reschedule()) { + workQueue.offer(work); + } + } + } + workQueue.clear(); + worker = null; + } + } + + private static final AtomicInteger TASK_SEQUENCE_GENERATOR = new AtomicInteger(); + + private static final class PeriodicTask implements Delayed { + + private final Task task; + private final Target target; + private final long period; + private final int taskSequence; + + private long nextFireTime; + + public PeriodicTask( + final Task task, + final Target target, + final long initialDelay, + final long period, + final TimeUnit unit) { + + this.task = task; + this.target = target; + this.period = unit.toNanos(period); + this.taskSequence = TASK_SEQUENCE_GENERATOR.getAndIncrement(); + + nextFireTime = System.nanoTime() + unit.toNanos(initialDelay); + } + + public void run() { + final T t = target.get(); + if (t != null) { + task.run(t); + } + } + + public boolean reschedule() { + if (period > 0 && target.get() != null) { + nextFireTime += period; + return true; + } + return false; + } + + @Override + public long getDelay(final TimeUnit unit) { + return unit.convert(nextFireTime - System.nanoTime(), NANOSECONDS); + } + + @Override + public int compareTo(final Delayed other) { + if (this == other) { + return 0; + } + long taskOrder; + if (other instanceof PeriodicTask) { + final PeriodicTask otherTask = (PeriodicTask) other; + taskOrder = nextFireTime - otherTask.nextFireTime; + if (taskOrder == 0) { + taskOrder = taskSequence - otherTask.taskSequence; + } + } else { + taskOrder = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS); + } + return taskOrder < 0 ? -1 : (taskOrder > 0 ? 1 : 0); + } + + @Override + public boolean equals(Object obj) { + try { + return obj == null ? false : (this.compareTo((Delayed) obj) != 0 ? false : true); + } catch (ClassCastException e) { + return false; + } + } + + @Override + public String toString() { + return describeTask(task, target); + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/AgentThreadFactory.java b/features/dd-trace-core/src/main/java/datadog/trace/util/AgentThreadFactory.java new file mode 100644 index 0000000000..9602db255e --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/AgentThreadFactory.java @@ -0,0 +1,115 @@ +package datadog.trace.util; + +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ThreadFactory; + +/** A {@link ThreadFactory} implementation that starts all agent {@link Thread}s as daemons. */ +public final class AgentThreadFactory implements ThreadFactory { + public static final ThreadGroup AGENT_THREAD_GROUP = new ThreadGroup("dd-trace-java"); + + public static final long THREAD_JOIN_TIMOUT_MS = 800; + + // known agent threads + public enum AgentThread { + TASK_SCHEDULER("dd-task-scheduler"), + + TRACE_STARTUP("dd-agent-startup-datadog-tracer"), + TRACE_MONITOR("dd-trace-monitor"), + TRACE_PROCESSOR("dd-trace-processor"), + SPAN_SAMPLING_PROCESSOR("dd-span-sampling-processor"), + TRACE_CASSANDRA_ASYNC_SESSION("dd-cassandra-session-executor"), + + METRICS_AGGREGATOR("dd-metrics-aggregator"), + STATSD_CLIENT("dd-statsd-client"), + + JMX_STARTUP("dd-agent-startup-jmxfetch"), + JMX_COLLECTOR("dd-jmx-collector"), + + PROFILER_STARTUP("dd-agent-startup-datadog-profiler"), + PROFILER_RECORDING_SCHEDULER("dd-profiler-recording-scheduler"), + PROFILER_HTTP_DISPATCHER("dd-profiler-http-dispatcher"), + + APPSEC_HTTP_DISPATCHER("dd-appsec-http-dispatcher"), + + TELEMETRY("dd-telemetry"), + + FLEET_MANAGEMENT_POLLER("dd-fleet-management-poller"), + REMOTE_CONFIG("dd-remote-config"), + + TRACER_FLARE("dd-tracer-flare"), + + CWS_TLS("dd-cws-tls"), + + PROCESS_SUPERVISOR("dd-process-supervisor"), + + DATA_STREAMS_MONITORING("dd-data-streams-monitor"), + + DEBUGGER_HTTP_DISPATCHER("dd-debugger-upload-http-dispatcher"), + + CI_SHELL_COMMAND("dd-ci-shell-command"), + CI_GIT_DATA_UPLOADER("dd-ci-git-data-uploader"), + CI_GIT_DATA_SHUTDOWN_HOOK("dd-ci-git-data-shutdown-hook"), + CI_TEST_EVENTS_SHUTDOWN_HOOK("dd-ci-test-events-shutdown-hook"), + CI_PROJECT_CONFIGURATOR("dd-ci-project-configurator"), + CI_SIGNAL_SERVER("dd-ci-signal-server"); + + public final String threadName; + + AgentThread(final String threadName) { + this.threadName = threadName; + } + } + + private final AgentThread agentThread; + + /** + * Constructs a new agent {@code ThreadFactory}. + * + * @param agentThread the agent thread created by this factory. + */ + public AgentThreadFactory(final AgentThread agentThread) { + this.agentThread = agentThread; + } + + @Override + public Thread newThread(final Runnable runnable) { + return newAgentThread(agentThread, runnable); + } + + /** + * Constructs a new agent {@code Thread} as a daemon with a null ContextClassLoader. + * + * @param agentThread the agent thread to create. + * @param runnable work to run on the new thread. + */ + public static Thread newAgentThread(final AgentThread agentThread, final Runnable runnable) { + return newAgentThread(agentThread, null, runnable, true); + } + + public static Thread newAgentThread( + final AgentThread agentThread, final Runnable runnable, boolean daemon) { + return newAgentThread(agentThread, null, runnable, daemon); + } + + public static Thread newAgentThread( + final AgentThread agentThread, + final String nameSuffix, + final Runnable runnable, + boolean daemon) { + final String threadName = + nameSuffix != null ? agentThread.threadName + nameSuffix : agentThread.threadName; + final Thread thread = new Thread(AGENT_THREAD_GROUP, runnable, threadName); + thread.setDaemon(daemon); + thread.setContextClassLoader(null); + thread.setUncaughtExceptionHandler( + new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(final Thread thread, final Throwable e) { + LoggerFactory.getLogger(runnable.getClass()) + .error("Uncaught exception {} in {}", e, agentThread.threadName, e); + } + }); + return thread; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/ClassNameTrie.java b/features/dd-trace-core/src/main/java/datadog/trace/util/ClassNameTrie.java new file mode 100644 index 0000000000..378e85e7a7 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/ClassNameTrie.java @@ -0,0 +1,927 @@ +package datadog.trace.util; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Immutable space-efficient trie that captures a mapping of package/class names to numbers. + * + *

    Each node of the trie is represented as a series of {@code char}s using this layout: + * + *

    + * +--------------------------------------+
    + * | number of branches                   |
    + * +--------------------------------------+--------------------------------------+----
    + * | char for branch 0                    | char for branch 1                    | ...
    + * +--------------------------------------+--------------------------------------+----
    + * | segment-length/leaf/bud for branch 0 | segment-length/leaf/bud for branch 1 | ...
    + * +--------------------------------------+--------------------------------------+----
    + * | offset to jump to branch 1           | offset to jump to branch 2           | ...
    + * +--------------------------------------+--------------------------------------+----
    + * 
    + * + * Each node is followed by its child nodes according to branch order, separated by the characters + * expected for that segment of the trie. Segments that represent the end of a name with no further + * branches are followed by a leaf character instead of a child node. + * + *

    Leaves mark a definite end of the match, while buds mark a potential end that could continue + * to a different result if there are more characters to match. A match is a success when either the + * entire key is matched or the match is a glob. + * + *

    The jump for branch 0 is assumed to be 0 and is always omitted, that is any continuation of + * the trie for branch 0 immediately follows the current node. Long jumps that don't fit into a char + * are replaced by an index into a long jump table. + * + *

    For example this mapping: + * + *

    + * 2 akka.stream.*
    + * 0 akka.stream.impl.FanIn$SubInput
    + * 0 akka.stream.impl.FanOut$SubstreamSubscription
    + * 0 akka.stream.impl.fusing.ActorGraphInterpreter$*
    + * 0 akka.stream.stage.GraphStageLogic$*
    + * 0 akka.stream.stage.TimerGraphStageLogic$*
    + * 2 ch.qos.logback.*
    + * 0 ch.qos.logback.classic.Logger
    + * 0 ch.qos.logback.classic.spi.LoggingEvent*
    + * 0 ch.qos.logback.core.AsyncAppenderBase$Worker
    + * 
    + * + * is generated into a string trie with this structure: (formatted for readability) + * + *
    + * | 2 | a | c | length (10) | length (13) | jump (150)
    + * kka.stream | 1 | . | bud+glob (2)
    + *            | 2 | i | s | length (4) | length (5) | jump (83)
    + *            mpl. | 2 | F | f | length (2) | length (28) | jump (44)
    + *                 an | 2 | I | O | length (10) | length (24) | jump (11)
    + *                    n$SubInput | leaf (0)
    + *                    ut$SubstreamSubscription | leaf (0)
    + *                 using.ActorGraphInterpreter$ | leaf+glob (0)
    + *            tage. | 2 | G | T | length (15) | length (20) | jump (16)
    + *                  raphStageLogic$ | leaf+glob (0)
    + *                  imerGraphStageLogic$ | leaf+glob (0)
    + * h.qos.logback | 1 | . | bud+glob (2)
    + *               | 1 | c | length (0)
    + *               | 2 | l | o | length (6) | length (27) | jump (40)
    + *               assic. | 2 | L | s | length (5) | length (14) | jump (6)
    + *                      ogger | leaf (0)
    + *                      pi.LoggingEvent | leaf+glob (0)
    + *               re.AsyncAppenderBase$Worker | leaf(0)
    + * 
    + */ +public final class ClassNameTrie { + + /** Marks a leaf in the trie, where the rest of the bits are the index to be returned. */ + private static final char LEAF_MARKER = 0x8000; + + /** Marks a 'bud' in the trie; the same as a leaf except the trie continues beneath it. */ + private static final char BUD_MARKER = 0x4000; + + /** Marks a glob in the trie, where a match succeeds even if the key has extra characters. */ + private static final char GLOB_MARKER = 0x2000; + + /** Maximum value that can be held in a single node of the trie. */ + private static final char MAX_NODE_VALUE = 0x1FFF; + + /** Marks a long jump that was replaced by an index into the long jump table. */ + private static final char LONG_JUMP_MARKER = 0x8000; + + /** A branch has at most 3 control characters: key, value, and optional jump offset/id. */ + private static final int BRANCH_CONTROL_CHARS = 3; + + /** Constant to account for the fact that the last branch doesn't have a jump offset/id. */ + private static final int NO_END_JUMP = 1; + + private static final int FILE_MAGIC = 0xDD097213; + + /** The compressed trie. */ + private final char[] trieData; + + /** Long jump offsets. */ + private final int[] longJumps; + + public int apply(String key) { + return apply(trieData, longJumps, key); + } + + public static int apply(char[] data, int[] longJumps, String key) { + int keyLength = key.length(); + int keyIndex = 0; + int dataIndex = 0; + int result = -1; + + while (keyIndex < keyLength) { + char c = key.charAt(keyIndex++); + char branchCount = data[dataIndex++]; + + // trie is ordered, so we can use binary search to pick the right branch + int branchIndex = + Arrays.binarySearch(data, dataIndex, dataIndex + branchCount, c == '/' ? '.' : c); + + if (branchIndex < 0) { + return result; // key doesn't match against any future branches + } + + int valueIndex = branchIndex + branchCount; + char value = data[valueIndex]; + int segmentLength = 0; + + if ((value & (LEAF_MARKER | BUD_MARKER)) != 0) { + // update result if we've matched the key, or we're at a glob + if (keyIndex == keyLength || (value & GLOB_MARKER) != 0) { + result = value & MAX_NODE_VALUE; + } + // stop if there's no more characters left in the key, or we've reached a leaf + if (keyIndex == keyLength || (value & LEAF_MARKER) != 0) { + return result; + } + } else { + segmentLength = value; // value is the length of the segment before the next node + } + + // move on to the segment/node for the picked branch... + if (branchIndex > dataIndex) { + int branchJump = data[valueIndex + branchCount - 1]; + if ((branchJump & LONG_JUMP_MARKER) != 0) { + branchJump = longJumps[branchJump & ~LONG_JUMP_MARKER]; + } + dataIndex += branchJump; + } + + // ...always include moving past the current node + dataIndex += (branchCount * BRANCH_CONTROL_CHARS) - NO_END_JUMP; + + // attempt to match any inline segment that precedes the next node + if (segmentLength > 0) { + if (keyLength - keyIndex < segmentLength) { + return result; // not enough characters left in the key + } + int segmentEnd = dataIndex + segmentLength; + while (dataIndex < segmentEnd) { + c = key.charAt(keyIndex++); + if ((c == '/' ? '.' : c) != data[dataIndex++]) { + return result; // segment doesn't match + } + } + // peek ahead - it will either be a node or a leaf + value = data[dataIndex]; + if ((value & LEAF_MARKER) != 0) { + // update result if we've matched the key, or we're at a glob + if (keyIndex == keyLength || (value & GLOB_MARKER) != 0) { + result = value & MAX_NODE_VALUE; + } + return result; // no more characters left to match in the trie + } + } + } + + return result; // no more characters left to match in the key + } + + /** Reads trie content from an external resource. */ + public static ClassNameTrie readFrom(DataInput in) throws IOException { + int magic = in.readInt(); + if (magic != FILE_MAGIC) { + throw new IOException("Unexpected file magic " + magic); + } + int trieLength = in.readInt(); + char[] trieData = new char[trieLength]; + for (int i = 0; i < trieLength; i++) { + byte b = in.readByte(); + char c; + if ((b & 0x80) == 0) { + // read 7-bit non-zero char as 1 byte + c = (char) b; + } else if ((b & 0xE0) == 0xE0) { + // read 16-bit char as 3 bytes (4+6+6) + c = (char) (((b & 0x0F) << 12) | ((in.readByte() & 0x3F) << 6) | (in.readByte() & 0x3F)); + } else { + // read 11-bit char as 2 bytes (5+6) + c = (char) (((b & 0x1F) << 6) | (in.readByte() & 0x3F)); + } + trieData[i] = c; + } + int longJumpCount = in.readInt(); + int[] longJumps; + if (longJumpCount > 0) { + longJumps = new int[longJumpCount]; + for (int i = 0; i < longJumpCount; i++) { + longJumps[i] = in.readInt(); + } + } else { + longJumps = null; + } + return new ClassNameTrie(trieData, longJumps); + } + + ClassNameTrie(char[] trieData, int[] longJumps) { + this.trieData = trieData; + this.longJumps = longJumps; + } + + /** Builds an in-memory trie that represents a mapping of {class-name} to {number}. */ + public static class Builder { + public static final ClassNameTrie EMPTY_TRIE = new ClassNameTrie(new char[] {0x0000}, null); + + private static final Pattern MAPPING_LINE = Pattern.compile("^\\s*(?:([0-9]+)\\s+)?([^\\s#]+)"); + + private char[] trieData; + private int trieLength; + private int[] longJumps; + private int longJumpCount; + + public Builder() {} + + public Builder(ClassNameTrie trie) { + trieData = trie.trieData; + trieLength = trieData.length; + longJumps = trie.longJumps; + longJumpCount = null != longJumps ? longJumps.length : 0; + } + + public boolean isEmpty() { + return trieLength == 0; + } + + /** Allow querying while the class-name trie is being built. */ + public int apply(String key) { + return trieLength > 0 ? ClassNameTrie.apply(trieData, longJumps, key) : -1; + } + + public ClassNameTrie buildTrie() { + if (trieLength == 0) { + return EMPTY_TRIE; + } + // avoid unnecessary allocation when compaction isn't required + if (trieData.length > trieLength) { + trieData = Arrays.copyOfRange(trieData, 0, trieLength); + } + if (null != longJumps && longJumps.length > longJumpCount) { + longJumps = Arrays.copyOfRange(longJumps, 0, longJumpCount); + } + return new ClassNameTrie(trieData, longJumps); + } + + /** Writes trie content to an external resource. */ + public void writeTo(DataOutput out) throws IOException { + out.writeInt(FILE_MAGIC); + out.writeInt(trieLength); + for (int i = 0; i < trieLength; i++) { + char c = trieData[i]; + if (c >= 0x0001 && c <= 0x007F) { + // write 7-bit non-zero char as 1 byte + out.writeByte(c); + } else if (c > 0x07FF) { + // write 16-bit char as 3 bytes (4+6+6) + out.writeByte(0xE0 | ((c >> 12) & 0x0F)); + out.writeByte(0x80 | ((c >> 6) & 0x3F)); + out.writeByte(0x80 | (c & 0x3F)); + } else { + // write 11-bit char as 2 bytes (5+6) + out.writeByte(0xC0 | ((c >> 6) & 0x1F)); + out.writeByte(0x80 | (c & 0x3F)); + } + } + out.writeInt(longJumpCount); + for (int i = 0; i < longJumpCount; i++) { + out.writeInt(longJumps[i]); + } + } + + /** Reads a class-name mapping file into the current builder */ + public void readClassNameMapping(Path triePath) throws IOException { + for (String l : Files.readAllLines(triePath, StandardCharsets.UTF_8)) { + Matcher m = MAPPING_LINE.matcher(l); + if (m.find()) { + put(m.group(2), m.group(1) != null ? Integer.parseInt(m.group(1)) : 1); + } + } + } + + /** Merges a new class-name mapping into the current builder */ + public void put(String className, int number) { + if (null == className || className.isEmpty()) { + throw new IllegalArgumentException("Null or empty class name"); + } + if (number < 0) { + throw new IllegalArgumentException("Number for " + className + " is negative: " + number); + } + if (number > MAX_NODE_VALUE) { + throw new IllegalArgumentException("Number for " + className + " is too big: " + number); + } + + String key; + char value; + // package/class-names ending in '*' are marked as globs + if (className.charAt(className.length() - 1) == '*') { + key = className.substring(0, className.length() - 1); + value = (char) (number | GLOB_MARKER); + } else { + key = className; + value = (char) number; + } + + if (trieLength == 0) { + int keyLength = key.length(); + trieLength = (keyLength > 1 ? 3 : 2) + keyLength; + trieData = new char[8192]; // create table on first mapping + trieData[0] = (char) 1; + trieData[1] = key.charAt(0); + if (keyLength > 1) { + trieData[2] = (char) (keyLength - 1); + key.getChars(1, keyLength, trieData, 3); + } + trieData[trieLength - 1] = (char) (value | LEAF_MARKER); + } else { + insertMapping(key, value); + } + } + + /** Makes a hole in the current trie data to fit a new node/branch, etc. */ + private void makeHole(int start, int length) { + char[] oldData = trieData; + if (trieLength + length > oldData.length) { + trieData = new char[Math.max(trieLength + length, oldData.length + (oldData.length >> 1))]; + System.arraycopy(oldData, 0, trieData, 0, start); + } + System.arraycopy(oldData, start, trieData, start + length, trieLength - start); + trieLength += length; + } + + /** Moves jump values that won't fit into the long-jump table and replaces them with an id. */ + private char setJump(int jump) { + if (jump < LONG_JUMP_MARKER) { + return (char) jump; // jump is small enough to fit into the trie + } + if (longJumpCount == 0) { + longJumps = new int[16]; // create table on first long-jump + } else if (longJumpCount == longJumps.length) { + int[] oldJumps = longJumps; + // expand table by 50% to fit additional long-jumps + longJumps = new int[longJumpCount + (longJumpCount >> 1)]; + System.arraycopy(oldJumps, 0, longJumps, 0, longJumpCount); + } + longJumps[longJumpCount] = jump; + return (char) (longJumpCount++ | LONG_JUMP_MARKER); + } + + /** Restores jump values previously moved into the long-jump table. */ + private int getJump(char jump) { + return (jump & LONG_JUMP_MARKER) == 0 ? jump : longJumps[jump & ~LONG_JUMP_MARKER]; + } + + /** + * Increases jump by the given offset, this may result in it moving into the long-jump table. + */ + private char updateJump(char jump, int offset) { + if (jump < LONG_JUMP_MARKER) { + return setJump(jump + offset); + } + longJumps[jump & ~LONG_JUMP_MARKER] += offset; + return jump; + } + + private void insertMapping(String key, char valueToInsert) { + BitSet jumpsToOffset = new BitSet(); + + int keyLength = key.length(); + int keyIndex = 0; + int dataIndex = 0; + int subTrieEnd = trieLength; + int jumpOffset = 0; + + while (keyIndex < keyLength) { + char c = key.charAt(keyIndex++); + char branchCount = trieData[dataIndex++]; + + // trie is ordered, so we can use binary search to pick the right branch + int branchIndex = Arrays.binarySearch(trieData, dataIndex, dataIndex + branchCount, c); + + if (branchIndex < 0) { + jumpOffset = + insertBranch( + dataIndex, + key, + keyIndex - 1, + valueToInsert, + branchCount, + ~branchIndex - dataIndex, + subTrieEnd); + break; + } + + int valueIndex = branchIndex + branchCount; + char value = trieData[valueIndex]; + + if ((value & (LEAF_MARKER | BUD_MARKER)) != 0 && keyIndex == keyLength) { + // duplicate key: overwrite existing value in the tree with the new value + trieData[valueIndex] = (char) ((value & ~MAX_NODE_VALUE) | valueToInsert); + return; + } + + int branch = branchIndex - dataIndex; + if (branch < branchCount - 1) { + int nextJumpIndex = valueIndex + branchCount; + int nextBranchJump = getJump(trieData[nextJumpIndex]); + + // update subTrieEnd to reflect we've moved down a left/centre branch + subTrieEnd = + dataIndex + (branchCount * BRANCH_CONTROL_CHARS) - NO_END_JUMP + nextBranchJump; + + // remember to update jump offsets on right once we know how much we've added + for (int b = branch + 1; b < branchCount; b++) { + jumpsToOffset.set(nextJumpIndex++); + } + } + + // move on to the segment/node for the picked branch... + if (branch > 0) { + dataIndex += getJump(trieData[valueIndex + branchCount - 1]); + } + + // ...always include moving past the current node + dataIndex += (branchCount * BRANCH_CONTROL_CHARS) - NO_END_JUMP; + + if ((value & LEAF_MARKER) != 0) { + // change leaf branch to a bud and append our new leaf node below it + trieData[valueIndex] = (char) ((value & ~LEAF_MARKER) | BUD_MARKER); + jumpOffset = appendLeaf(dataIndex, key, keyIndex, valueToInsert); + break; + } else if ((value & BUD_MARKER) != 0) { + // ignore bud as we still have more of the key to match + continue; + } else if (keyIndex == keyLength) { + // branch originally led to a segment - record it's now a bud + trieData[valueIndex] = (char) (valueToInsert | BUD_MARKER); + if (value > 0) { + // add the usual node preamble before the old segment + jumpOffset = prependNode(dataIndex, value - 1); + } + break; + } + + // must be a segment - try to match as much as possible before we insert a bud/leaf + if (value > 0) { + int segmentLength = value; + int segmentEnd = dataIndex + segmentLength; + while (keyIndex < keyLength && dataIndex < segmentEnd) { + c = key.charAt(keyIndex); + if (c != trieData[dataIndex]) { + break; + } + keyIndex++; + dataIndex++; + } + if (dataIndex < segmentEnd) { + if (keyIndex == keyLength) { + // key is shorter than segment; add bud at the point the key ends + trieData[valueIndex] -= segmentEnd - (dataIndex - 1); + jumpOffset = insertBud(dataIndex - 1, valueToInsert, segmentEnd); + } else { + // key diverges from segment; add leaf on left/right to capture that + trieData[valueIndex] -= segmentEnd - dataIndex; + if (c < trieData[dataIndex]) { + jumpOffset = insertLeafLeft(dataIndex, key, keyIndex, valueToInsert, segmentEnd); + } else { + jumpOffset = + insertLeafRight( + dataIndex, key, keyIndex, valueToInsert, segmentEnd, subTrieEnd); + } + } + break; // nothing more to add + } + + // peek ahead - it will either be a node or a leaf + value = trieData[dataIndex]; + if ((value & LEAF_MARKER) != 0) { + if (keyIndex < keyLength) { + // key goes past leaf segment, extend old leaf with a bud node and add our new leaf + trieData[valueIndex]--; + jumpOffset = appendLeaf(dataIndex, key, keyIndex, valueToInsert); + break; + } else { + // duplicate key: overwrite existing value in the tree with the new value + trieData[dataIndex] = (char) ((value & ~MAX_NODE_VALUE) | valueToInsert); + return; + } + } else /* segment is followed by a node */ { + if (keyIndex == keyLength) { + // key stops at boundary between segment and node, insert bud node just before this + trieData[valueIndex]--; + jumpOffset = prependNode(dataIndex - 1, valueToInsert | BUD_MARKER); + break; + } + } + } + } + + if (jumpOffset > 0) { + // now we know how much we added, update all jumps that need to jump past our addition + for (int i = jumpsToOffset.nextSetBit(0); i >= 0; i = jumpsToOffset.nextSetBit(i + 1)) { + trieData[i] = updateJump(trieData[i], jumpOffset); + } + } + } + + private int insertBranch( + int dataIndex, + String key, + int keyIndex, + int value, + int branchCount, + int newBranch, + int subTrieEnd) { + + int remainingKeyLength = key.length() - keyIndex; + int insertedCharacters = 3 /* segment-length, jump, value */ + remainingKeyLength; + + // can collapse branch if the key only has a single character left + boolean collapseRight = remainingKeyLength == 1; + if (collapseRight) { + remainingKeyLength = 0; + insertedCharacters = 3; /* branch-key, value, jump */ + } + + int i = dataIndex + newBranch, j = i + insertedCharacters; + + makeHole(i, insertedCharacters); + + // update branch count leading into our branches + trieData[dataIndex - 1] = (char) (branchCount + 1); + + // insert our new branch key + trieData[i++] = key.charAt(keyIndex); + System.arraycopy(trieData, j, trieData, i, branchCount); + i += branchCount; + j += branchCount; + + // insert our new branch value + trieData[i++] = (char) (collapseRight ? value | LEAF_MARKER : remainingKeyLength - 1); + + int subTrieStart = dataIndex + (branchCount * BRANCH_CONTROL_CHARS) - NO_END_JUMP; + + int precedingJump; + if (newBranch < branchCount) { + // adding branch on left/centre + System.arraycopy(trieData, j, trieData, i, branchCount); + i += branchCount; + j += branchCount; + precedingJump = newBranch > 0 ? getJump(trieData[i - 1]) : 0; + // calculate jump for next branch, using previous jump as a reference + trieData[i++] = setJump(precedingJump + remainingKeyLength); + for (int b = newBranch + 1; b < branchCount; b++) { + // update old branch jumps on right to account for added content + trieData[i++] = updateJump(trieData[j++], remainingKeyLength); + } + } else { + // adding branch on right + System.arraycopy(trieData, j, trieData, i, branchCount - 1); + i += branchCount - 1; + j += branchCount - 1; + // calculate jump needed to reach our new branch based on the size of the old sub-trie + precedingJump = subTrieEnd - subTrieStart; + trieData[i++] = setJump(precedingJump); + } + + // now move up the sub-trie content before our new branch + System.arraycopy(trieData, subTrieStart + insertedCharacters, trieData, i, precedingJump); + i += precedingJump; + + if (!collapseRight) { + // lastly add the rest of our key as a leaf segment under our new branch + key.getChars(keyIndex + 1, key.length(), trieData, i); + i += remainingKeyLength - 1; + trieData[i++] = (char) (value | LEAF_MARKER); + } + + return insertedCharacters; + } + + private int prependNode(int dataIndex, int value) { + int insertedCharacters = 2; /* branch count, value */ + + // can collapse branch if it would lead to a leaf segment of zero-length + boolean collapseRight = value == 0 && (trieData[dataIndex + 1] & LEAF_MARKER) != 0; + if (collapseRight) { + insertedCharacters--; + } + + int i = dataIndex, j = i + insertedCharacters; + + makeHole(i, insertedCharacters); + + trieData[i++] = 1; + trieData[i++] = trieData[j]; + if (!collapseRight) { + trieData[i++] = (char) value; + } + + return insertedCharacters; + } + + private int insertBud(int dataIndex, int value, int segmentEnd) { + int insertedCharacters = 4; // branch count (bud), value, branch count (rest), segment-length + int pivot = dataIndex + 2; + + // can collapse right branch if it would lead to a leaf segment of zero-length + boolean collapseRight = pivot == segmentEnd && (trieData[segmentEnd] & LEAF_MARKER) != 0; + if (collapseRight) { + insertedCharacters = 3; + } + + int i = dataIndex, j = i + insertedCharacters; + + makeHole(i, insertedCharacters); + + trieData[i++] = 1; + trieData[i++] = trieData[j]; + trieData[i++] = (char) (value | BUD_MARKER); + trieData[i++] = 1; + trieData[i++] = trieData[j + 1]; + if (!collapseRight) { + trieData[i++] = (char) (segmentEnd - pivot); + } + + return insertedCharacters; + } + + private int insertLeafLeft(int dataIndex, String key, int keyIndex, int value, int segmentEnd) { + int remainingKeyLength = key.length() - keyIndex; + int insertedCharacters = + 5 /* branch count, 2 * segment-length, jump, value */ + remainingKeyLength; + int pivot = dataIndex + 1; + + // can collapse left branch if the key only has a single character left + boolean collapseLeft = remainingKeyLength == 1; + if (collapseLeft) { + insertedCharacters--; + } + // can collapse right branch if it would lead to a leaf segment of zero-length + boolean collapseRight = pivot == segmentEnd && (trieData[segmentEnd] & LEAF_MARKER) != 0; + if (collapseRight) { + insertedCharacters--; + pivot++; + } + + int i = dataIndex, j = i + insertedCharacters; + + makeHole(i, insertedCharacters); + + trieData[i++] = 2; + trieData[i++] = key.charAt(keyIndex); + trieData[i++] = trieData[j]; + trieData[i++] = (char) (collapseLeft ? value | LEAF_MARKER : remainingKeyLength - 1); + trieData[i++] = (char) (collapseRight ? trieData[j + 1] : segmentEnd - pivot); + if (!collapseLeft) { + trieData[i++] = (char) remainingKeyLength; + key.getChars(keyIndex + 1, key.length(), trieData, i); + i += remainingKeyLength - 1; + trieData[i++] = (char) (value | LEAF_MARKER); + } else { + trieData[i++] = 0; + } + + return insertedCharacters; + } + + private int insertLeafRight( + int dataIndex, String key, int keyIndex, int value, int segmentEnd, int subTrieEnd) { + int remainingKeyLength = key.length() - keyIndex; + int insertedCharacters = + 5 /* branch count, 2 * segment-length, jump, value */ + remainingKeyLength; + int pivot = dataIndex + 1; + + // can collapse left branch if it would lead to a leaf segment of zero-length + boolean collapseLeft = pivot == segmentEnd && (trieData[segmentEnd] & LEAF_MARKER) != 0; + if (collapseLeft) { + insertedCharacters--; + pivot++; + } + // can collapse right branch if the key only has a single character left + boolean collapseRight = remainingKeyLength == 1; + if (collapseRight) { + insertedCharacters--; + } + + int i = dataIndex, j = i + insertedCharacters; + + makeHole(i, insertedCharacters); + + trieData[i++] = 2; + trieData[i++] = trieData[j]; + trieData[i++] = key.charAt(keyIndex); + trieData[i++] = (char) (collapseLeft ? trieData[j + 1] : segmentEnd - pivot); + trieData[i++] = (char) (collapseRight ? value | LEAF_MARKER : remainingKeyLength - 1); + trieData[i++] = setJump(subTrieEnd - pivot); + System.arraycopy(trieData, pivot + insertedCharacters, trieData, i, subTrieEnd - pivot); + i += subTrieEnd - pivot; + if (!collapseRight) { + key.getChars(keyIndex + 1, key.length(), trieData, i); + i += remainingKeyLength - 1; + trieData[i++] = (char) (value | LEAF_MARKER); + } + + return insertedCharacters; + } + + private int appendLeaf(int dataIndex, String key, int keyIndex, int value) { + int remainingKeyLength = key.length() - keyIndex; + int insertedCharacters = 3 /* branch count, segment-length, value */ + remainingKeyLength; + + // if we're adding this to a leaf segment then we need to introduce a bud first + boolean insertBud = dataIndex < trieLength && (trieData[dataIndex] & LEAF_MARKER) != 0; + if (insertBud) { + insertedCharacters++; + } + // can collapse right branch if the key only has a single character left + boolean collapseRight = remainingKeyLength == 1; + if (collapseRight) { + insertedCharacters--; + } + + int i = dataIndex, j = i + insertedCharacters; + + makeHole(i, insertedCharacters); + + if (insertBud) { + char c = trieData[i - 1]; + trieData[i - 1] = 1; + trieData[i++] = c; + trieData[i++] = (char) ((trieData[j] & ~LEAF_MARKER) | BUD_MARKER); + } + trieData[i++] = 1; + trieData[i++] = key.charAt(keyIndex); + if (!collapseRight) { + trieData[i++] = (char) (remainingKeyLength - 1); + key.getChars(keyIndex + 1, key.length(), trieData, i); + i += remainingKeyLength - 1; + } + trieData[i++] = (char) (value | LEAF_MARKER); + + return insertedCharacters; + } + } + + /** Generates Java source for a trie described as a series of "{number} {class-name}" lines. */ + public static class JavaGenerator { + public static void main(String[] args) throws IOException { + if (args.length < 2) { + throw new IllegalArgumentException("Expected: trie-dir java-dir [file.trie ...]"); + } + Path trieDir = Paths.get(args[0]).toAbsolutePath().normalize(); + if (!Files.isDirectory(trieDir)) { + throw new IllegalArgumentException("Bad trie directory: " + trieDir); + } + Path javaDir = Paths.get(args[1]).toAbsolutePath().normalize(); + if (!Files.isDirectory(javaDir)) { + throw new IllegalArgumentException("Bad java directory: " + javaDir); + } + for (int i = 2; i < args.length; i++) { + Path triePath = trieDir.resolve(args[i]).normalize(); + String className = toClassName(triePath.getFileName().toString()); + Path pkgPath = trieDir.relativize(triePath.getParent()); + String pkgName = pkgPath.toString().replace(File.separatorChar, '.'); + Path javaPath = javaDir.resolve(pkgPath).resolve(className + ".java"); + generateJavaFile(triePath, javaPath, pkgName, className); + } + } + + /** Converts snake-case trie names to camel-case Java class names. */ + private static String toClassName(String trieName) { + StringBuilder className = new StringBuilder(); + boolean upperNext = true; + for (int i = 0; i < trieName.length(); i++) { + char c = trieName.charAt(i); + if (c == '_' | c == '.') { + upperNext = true; + } else { + className.append(upperNext ? Character.toUpperCase(c) : c); + upperNext = false; + } + } + return className.toString(); + } + + /** Reads a trie file and writes out the equivalent Java file. */ + private static void generateJavaFile( + Path triePath, Path javaPath, String pkgName, String className) throws IOException { + Builder trie = new Builder(); + trie.readClassNameMapping(triePath); + List lines = new ArrayList<>(); + if (!pkgName.isEmpty()) { + lines.add("package " + pkgName + ';'); + } + lines.add(""); + lines.add("import datadog.trace.util.ClassNameTrie;"); + lines.add(""); + lines.add("// Generated from '" + triePath.getFileName() + "' - DO NOT EDIT!"); + lines.add("public final class " + className + " {"); + lines.add(""); + boolean hasLongJumps = generateJavaTrie(lines, "", trie); + lines.add(""); + lines.add(" public static int apply(String key) {"); + if (hasLongJumps) { + lines.add(" return ClassNameTrie.apply(TRIE_DATA, LONG_JUMPS, key);"); + } else { + lines.add(" return ClassNameTrie.apply(TRIE_DATA, null, key);"); + } + lines.add(" }"); + lines.add(""); + lines.add(" private " + className + "() {}"); + lines.add("}"); + Files.write(javaPath, lines, StandardCharsets.UTF_8); + } + + /** Writes the Java form of the trie as a series of lines. */ + public static boolean generateJavaTrie( + List lines, String prefix, Builder trie) { + boolean hasLongJumps = trie.longJumpCount > 0; + int firstLineNumber = lines.size(); + int chunk = 1; + lines.add(" private static final String " + prefix + "TRIE_TEXT_" + chunk + " ="); + int chunkSize = 0; + StringBuilder buf = new StringBuilder(); + buf.append(" \""); + for (int i = 0; i < trie.trieLength; i++) { + char c = trie.trieData[i]; + if (++chunkSize > 10_000) { + chunk++; + chunkSize = 0; + lines.add(buf + "\";"); + lines.add(""); + lines.add(" private static final String " + prefix + "TRIE_TEXT_" + chunk + " ="); + buf.setLength(0); + buf.append(" \""); + } else if (buf.length() > 120) { + lines.add(buf + "\""); + buf.setLength(0); + buf.append(" + \""); + } + if (c <= 0x00FF) { + buf.append(String.format("\\%03o", (int) c)); + } else { + buf.append(String.format("\\u%04x", (int) c)); + } + } + lines.add(buf + "\";"); + lines.add(""); + if (chunk > 1) { + lines.add(" private static final char[] " + prefix + "TRIE_DATA;"); + lines.add(" static {"); + lines.add(" int dataLength = 0;"); + for (int n = 1; n <= chunk; n++) { + lines.add(" dataLength += " + prefix + "TRIE_TEXT_" + n + ".length();"); + } + lines.add(" " + prefix + "TRIE_DATA = new char[dataLength];"); + lines.add(" int dataIndex = 0;"); + lines.add(" String chunk;"); + for (int n = 1; n <= chunk; n++) { + lines.add(" chunk = " + prefix + "TRIE_TEXT_" + n + ";"); + lines.add(" chunk.getChars(0, chunk.length(), " + prefix + "TRIE_DATA, dataIndex);"); + lines.add(" dataIndex += chunk.length();"); + } + lines.add(" }"); + } else { + // only one chunk so can simplify char array creation + lines.set(firstLineNumber, " private static final String " + prefix + "TRIE_TEXT ="); + lines.add( + " private static final char[] " + + prefix + + "TRIE_DATA = " + + prefix + + "TRIE_TEXT.toCharArray();"); + } + if (hasLongJumps) { + lines.add(""); + lines.add(" private static final int[] " + prefix + "LONG_JUMPS = {"); + buf.setLength(0); + buf.append(" "); + for (int i = 0; i < trie.longJumpCount; i++) { + int jump = trie.longJumps[i]; + if (buf.length() > 90) { + lines.add(buf.toString()); + buf.setLength(0); + buf.append(" "); + } + buf.append(' ').append(String.format("0x%06X", jump)).append(','); + } + lines.add(buf.toString()); + lines.add(" };"); + } + return hasLongJumps; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/CollectionUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/util/CollectionUtils.java new file mode 100644 index 0000000000..9b7c19bc95 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/CollectionUtils.java @@ -0,0 +1,53 @@ +package datadog.trace.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public final class CollectionUtils { + + /** + * Converts the input to an immutable set if available on the current platform. Otherwise returns + * the input as a set. + * + * @param input the input. + * @param the type of the elements of the input. + * @return an immutable copy of the input if possible. + */ + @SuppressWarnings("unchecked") + public static Set tryMakeImmutableSet(Collection input) { + return new HashSet<>(input); + } + + /** + * Converts the input to an immutable list if available on the current platform. Otherwise returns + * the input as a list. + * + * @param input the input. + * @param the type of the elements of the input. + * @return an immutable copy of the input if possible. + */ + @SuppressWarnings("unchecked") + public static List tryMakeImmutableList(Collection input) { + return new ArrayList<>(input); + } + + /** + * Converts the input to an immutable map if available on the current platform. Otherwise returns + * the input. + * + * @param input the input. + * @param the key type + * @param the value type + * @return an immutable copy of the input if possible. + */ + @SuppressWarnings("unchecked") + public static Map tryMakeImmutableMap(Map input) { + return new HashMap<>(input); + } + +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/FNV64Hash.java b/features/dd-trace-core/src/main/java/datadog/trace/util/FNV64Hash.java new file mode 100644 index 0000000000..8c91e4accc --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/FNV64Hash.java @@ -0,0 +1,54 @@ +package datadog.trace.util; + +/** + * Calculates the FNV 64 bit hash. Longs should be treated as though they were unsigned + * + *

    http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-1 + */ +public class FNV64Hash { + private static final long FNV_INIT = 0xcbf29ce484222325L; + private static final long FNV_PRIME = 0x100000001b3L; + + public enum Version { + v1, + v1A + } + + public static long generateHash(String data, Version version) { + return generateHash(data.getBytes(), version); + } + + public static long generateHash(byte[] data, Version version) { + return generateHash(data, 0, data.length, version); + } + + public static long generateHash(byte[] data, int start, int length, Version version) { + if (version == Version.v1) { + return generateFNV1Hash(data, start, length); + } else { + return generateFNV1AHash(data, start, length); + } + } + + private static long generateFNV1Hash(byte[] data, int start, int length) { + long hash = FNV_INIT; + + for (int i = start; i < start + length; i++) { + hash *= FNV_PRIME; + hash ^= 0xffL & data[i]; + } + + return hash; + } + + private static long generateFNV1AHash(byte[] data, int start, int length) { + long hash = FNV_INIT; + + for (int i = start; i < start + length; i++) { + hash ^= 0xffL & data[i]; + hash *= FNV_PRIME; + } + + return hash; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/MethodHandles.java b/features/dd-trace-core/src/main/java/datadog/trace/util/MethodHandles.java new file mode 100644 index 0000000000..a7e0a2d94f --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/MethodHandles.java @@ -0,0 +1,176 @@ +package datadog.trace.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Arrays; + +public class MethodHandles { + + private static final Logger log = LoggerFactory.getLogger(MethodHandles.class); + + private final java.lang.invoke.MethodHandles.Lookup lookup = + java.lang.invoke.MethodHandles.lookup(); + private final ClassLoader classLoader; + + public MethodHandles(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public MethodHandle privateFieldGetter(String className, String fieldName) { + Class clazz = loadClass(className); + return clazz != null ? privateFieldGetter(clazz, fieldName) : null; + } + + public MethodHandle privateFieldGetter(Class clazz, String fieldName) { + return AccessController.doPrivileged( + (PrivilegedAction) + () -> { + try { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + String packageName = clazz.getPackage().getName(); + sm.checkPackageAccess(packageName); + } + + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return lookup.unreflectGetter(field); + + } catch (Throwable t) { + log.debug( + "Could not get private field {} getter from class {}", + fieldName, + clazz.getName(), + t); + return null; + } + }); + } + + public MethodHandle privateFieldSetter(String className, String fieldName) { + Class clazz = loadClass(className); + return clazz != null ? privateFieldSetter(clazz, fieldName) : null; + } + + public MethodHandle privateFieldSetter(Class clazz, String fieldName) { + return AccessController.doPrivileged( + (PrivilegedAction) + () -> { + try { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + String packageName = clazz.getPackage().getName(); + sm.checkPackageAccess(packageName); + } + + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return lookup.unreflectSetter(field); + + } catch (Throwable t) { + log.debug( + "Could not get private field {} setter from class {}", + fieldName, + clazz.getName(), + t); + return null; + } + }); + } + + public MethodHandle constructor(String className, Class... parameterTypes) { + Class clazz = loadClass(className); + return clazz != null ? constructor(clazz, parameterTypes) : null; + } + + public MethodHandle constructor(Class clazz, Class... parameterTypes) { + return AccessController.doPrivileged( + (PrivilegedAction) + () -> { + try { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + String packageName = clazz.getPackage().getName(); + sm.checkPackageAccess(packageName); + } + + Constructor constructor = clazz.getDeclaredConstructor(parameterTypes); + constructor.setAccessible(true); + return lookup.unreflectConstructor(constructor); + + } catch (Throwable t) { + log.debug( + "Could not get constructor accepting {} from class {}", + Arrays.toString(parameterTypes), + clazz.getName(), + t); + return null; + } + }); + } + + public MethodHandle method(String className, String methodName, Class... parameterTypes) { + Class clazz = loadClass(className); + return clazz != null ? method(clazz, methodName, parameterTypes) : null; + } + + public MethodHandle method(Class clazz, String methodName, Class... parameterTypes) { + return AccessController.doPrivileged( + (PrivilegedAction) + () -> { + try { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + String packageName = clazz.getPackage().getName(); + sm.checkPackageAccess(packageName); + } + + Method method = clazz.getDeclaredMethod(methodName, parameterTypes); + method.setAccessible(true); + return lookup.unreflect(method); + + } catch (Throwable t) { + log.debug( + "Could not get method {} accepting {} from class {}", + methodName, + Arrays.toString(parameterTypes), + clazz, + t); + return null; + } + }); + } + + private Class loadClass(String className) { + try { + return classLoader.loadClass(className); + } catch (Throwable t) { + log.debug("Could not load class {}", className, t); + return null; + } + } + + @SuppressWarnings("unchecked") + public T invoke(MethodHandle handle, Object... arguments) { + if (handle == null) { + return null; + } + try { + return (T) handle.invokeWithArguments(arguments); + } catch (Throwable t) { + log.error( + "Error while invoking method handle {} with arguments {}", + handle, + Arrays.toString(arguments), + t); + return null; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/PidHelper.java b/features/dd-trace-core/src/main/java/datadog/trace/util/PidHelper.java new file mode 100644 index 0000000000..45219d8976 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/PidHelper.java @@ -0,0 +1,68 @@ +package datadog.trace.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.function.Supplier; + +import datadog.trace.api.Platform; + +/** Get PID in reasonably cross-platform way. */ +public final class PidHelper { + private static final Logger log = LoggerFactory.getLogger(PidHelper.class); + + private static final String PID = findPid(); + + private static final long PID_AS_LONG = parsePid(); + + public static String getPid() { + return PID; + } + + /** Returns 0 if the PID is not a number. */ + public static long getPidAsLong() { + return PID_AS_LONG; + } + + private static String findPid() { + String pid = ""; + if (Platform.isJavaVersionAtLeast(9)) { + try { + pid = + Strings.trim( + ((Supplier) + Class.forName("datadog.trace.util.JDK9PidSupplier") + .getDeclaredConstructor() + .newInstance()) + .get()); + } catch (Throwable e) { + log.debug("JDK9PidSupplier not available", e); + } + } + if (pid.isEmpty()) { + try { + // assumption: first part of runtime vmId is our process id +// String vmId = ManagementFactory.getRuntimeMXBean().getName(); + String vmId =""; + int pidEnd = vmId.indexOf('@'); + if (pidEnd > 0) { + pid = vmId.substring(0, pidEnd).trim(); + } + } catch (Throwable e) { + log.debug("Process id not available", e); + } + } + return pid; + } + + private static long parsePid() { + if (!PID.isEmpty()) { + try { + return Long.parseLong(PID); + } catch (NumberFormatException e) { + log.warn("Cannot parse PID {} as number. Default to 0", PID, e); + } + } + return 0L; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessSupervisor.java b/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessSupervisor.java new file mode 100644 index 0000000000..738d1b77a5 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessSupervisor.java @@ -0,0 +1,150 @@ +package datadog.trace.util; + +import static datadog.trace.util.AgentThreadFactory.AgentThread.PROCESS_SUPERVISOR; +import static datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; +import static datadog.trace.util.ProcessSupervisor.Health.FAULTED; +import static datadog.trace.util.ProcessSupervisor.Health.HEALTHY; +import static datadog.trace.util.ProcessSupervisor.Health.INTERRUPTED; +import static datadog.trace.util.ProcessSupervisor.Health.READY_TO_START; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Closeable; + +/** Starts an external process and restarts the process if it dies */ +public class ProcessSupervisor implements Closeable { + + public enum Health { + NEVER_CHECKED, + READY_TO_START, + INTERRUPTED, + FAULTED, + HEALTHY + } + + @FunctionalInterface + public interface HealthCheck { + Health run(Health previousHealth) throws InterruptedException; + } + + public static final HealthCheck ALWAYS_READY = health -> READY_TO_START; + + private static final Logger log = LoggerFactory.getLogger(ProcessSupervisor.class); + + private static final long HEALTHY_DELAY_MILLIS = 10_000; + private static final long FAULTED_DELAY_MILLIS = 2_000; + private static final int MAX_FAULTS = 5; + + private final String imageName; + private final ProcessBuilder processBuilder; + private final HealthCheck healthCheck; + private final Thread supervisorThread; + + private long nextCheckMillis = 0; + private Health currentHealth = Health.NEVER_CHECKED; + private Process currentProcess; + private int faults; + + private volatile boolean stopping = false; + + /** + * @param imageName For logging purposes + * @param processBuilder Builder to create the process + */ + public ProcessSupervisor(String imageName, ProcessBuilder processBuilder) { + this(imageName, processBuilder, ALWAYS_READY); + } + + public ProcessSupervisor( + String imageName, ProcessBuilder processBuilder, HealthCheck healthCheck) { + this.imageName = imageName; + this.processBuilder = processBuilder; + this.healthCheck = healthCheck; + this.supervisorThread = AgentThreadFactory.newAgentThread(PROCESS_SUPERVISOR, this::mainLoop); + this.supervisorThread.start(); + } + + private void mainLoop() { + try { + while (!stopping) { + if (currentHealth == FAULTED && ++faults >= MAX_FAULTS) { + log.warn("Failed to start process [{}] after {} attempts", imageName, faults); + break; + } + try { + long delayMillis = nextCheckMillis - System.currentTimeMillis(); + if (delayMillis > 0) { + Thread.sleep(delayMillis); + } + currentHealth = healthCheck.run(currentHealth); + if (currentHealth == READY_TO_START) { + startProcessAndWait(); + } + } catch (InterruptedException e) { + currentHealth = INTERRUPTED; + } catch (Throwable e) { + log.warn("Exception starting process: [{}]", imageName, e); + currentHealth = FAULTED; + } + scheduleNextHealthCheck(); + } + } finally { + stopProcess(); + } + } + + private void scheduleNextHealthCheck() { + long now = System.currentTimeMillis(); + if (currentHealth == HEALTHY) { + nextCheckMillis = now + HEALTHY_DELAY_MILLIS; + } else if (currentHealth == FAULTED) { + nextCheckMillis = now + FAULTED_DELAY_MILLIS; + } else { // interrupted + nextCheckMillis = Long.max(nextCheckMillis, now + 100); + } + } + + private void startProcessAndWait() throws Exception { + if (currentProcess == null) { + log.debug("Starting process: [{}]", imageName); + currentProcess = processBuilder.start(); + currentHealth = HEALTHY; + faults = 0; + } + + // Block until the process exits + int code = currentProcess.waitFor(); + log.debug("Process [{}] has exited with code {}", imageName, code); + currentHealth = code == 0 ? INTERRUPTED : FAULTED; + + // Process is dead, no longer needs to be tracked + currentProcess = null; + } + + private void stopProcess() { + if (currentProcess != null) { + log.debug("Stopping process: [{}]", imageName); + currentProcess.destroy(); + if (currentProcess.isAlive()) { + currentProcess.destroyForcibly(); + } + currentProcess = null; + } + } + + @Override + public void close() { + stopping = true; + supervisorThread.interrupt(); + try { + supervisorThread.join(THREAD_JOIN_TIMOUT_MS); + } catch (Throwable ignored) { + } + } + + // Package reachable for testing + Process getCurrentProcess() { + return currentProcess; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessUtils.java new file mode 100644 index 0000000000..8b7ba1f2f5 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessUtils.java @@ -0,0 +1,51 @@ +package datadog.trace.util; + +import androidx.annotation.Nullable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.function.Supplier; + +import datadog.trace.api.Platform; + +public abstract class ProcessUtils { + + private static final Logger log = LoggerFactory.getLogger(ProcessUtils.class); + + /** + * Attempts to get path to the JVM that is used by the current process. + * + *

    This is done on the best effort basis: depending on the Java version, vendor, current OS or + * other environment details this method might return either of the following: + * + *

      + *
    • Path to the {@code java} command that was used to start the process + *
    • Path to home dir of the JDK/JRE that the process uses + *
    • {@code null} if neither of the options above is available + *
    + * + * @return Path to the {@code java} command, JDK/JRE home, or {@code null} if neither could be + * determined + */ + @Nullable + public static String getCurrentJvmPath() { + if (Platform.isJavaVersionAtLeast(9)) { + try { + Supplier jdk9Supplier = + (Supplier) + Class.forName("datadog.trace.util.JDK9ExecutableSupplier") + .getDeclaredConstructor() + .newInstance(); + return jdk9Supplier.get(); + } catch (Throwable e) { + log.debug("Could not get process executable path using JDK9ExecutableSupplier", e); + } + } + + // JDK/JRE home, does not include "bin/java" portion + return System.getProperty("java.home"); + } + + private ProcessUtils() {} +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java b/features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java new file mode 100644 index 0000000000..3ee4dd0a0c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java @@ -0,0 +1,359 @@ +package datadog.trace.util; + +import androidx.annotation.NonNull; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ThreadLocalRandom; + +public final class Strings { + + public static String escapeToJson(String string) { + if (string == null || string.isEmpty()) { + return ""; + } + + final StringBuilder sb = new StringBuilder(); + int sz = string.length(); + for (int i = 0; i < sz; ++i) { + char ch = string.charAt(i); + if (ch > 4095) { + sb.append("\\u").append(hex(ch)); + } else if (ch > 255) { + sb.append("\\u0").append(hex(ch)); + } else if (ch > 127) { + sb.append("\\u00").append(hex(ch)); + } else if (ch < ' ') { + switch (ch) { + case '\b': + sb.append((char) 92).append((char) 98); + break; + case '\t': + sb.append((char) 92).append((char) 116); + break; + case '\n': + sb.append((char) 92).append((char) 110); + break; + case '\u000b': + default: + if (ch > 15) { + sb.append("\\u00").append(hex(ch)); + } else { + sb.append("\\u000").append(hex(ch)); + } + break; + case '\f': + sb.append((char) 92).append((char) 102); + break; + case '\r': + sb.append((char) 92).append((char) 114); + break; + } + } else { + switch (ch) { + case '"': + sb.append((char) 92).append((char) 34); + break; + case '\'': + sb.append((char) 92).append((char) 39); + break; + case '/': + sb.append((char) 92).append((char) 47); + break; + case '\\': + sb.append((char) 92).append((char) 92); + break; + default: + sb.append(ch); + } + } + } + + return sb.toString(); + } + + public static String toEnvVar(String string) { + return string.replace('.', '_').replace('-', '_').toUpperCase(); + } + + /** com.foo.Bar -> com/foo/Bar.class */ + public static String getResourceName(final String className) { + if (!className.endsWith(".class")) { + return className.replace('.', '/') + ".class"; + } else { + return className; + } + } + + /** com/foo/Bar.class -> com.foo.Bar */ + public static String getClassName(final String resourceName) { + if (resourceName.endsWith(".class")) { + return resourceName.substring(0, resourceName.length() - 6).replace('/', '.'); + } + return resourceName.replace('/', '.'); + } + + /** com.foo.Bar -> com/foo/Bar */ + public static String getInternalName(final String className) { + return className.replace('.', '/'); + } + + /** com.foo.Bar -> com.foo */ + public static String getPackageName(final String className) { + int lastDot = className.lastIndexOf('.'); + return lastDot < 0 ? "" : className.substring(0, lastDot); + } + + public static String join(CharSequence joiner, Iterable strings) { + if (strings == null) { + return ""; + } + + Iterator it = strings.iterator(); + // no elements + if (!it.hasNext()) { + return ""; + } + + // first element + CharSequence first = it.next(); + if (!it.hasNext()) { + return first.toString(); + } + + // remaining elements with joiner + StringBuilder sb = new StringBuilder(first); + while (it.hasNext()) { + sb.append(joiner).append(it.next()); + } + return sb.toString(); + } + + public static String join(CharSequence joiner, CharSequence... strings) { + int len = strings.length; + if (len > 0) { + if (len == 1) { + return strings[0].toString(); + } + StringBuilder sb = new StringBuilder(strings[0]); + for (int i = 1; i < len; ++i) { + sb.append(joiner).append(strings[i]); + } + return sb.toString(); + } + return ""; + } + + // reimplementation of string functions without regex + public static String replace(String str, String delimiter, String replacement) { + StringBuilder sb = new StringBuilder(str); + int matchIndex, curIndex = 0; + while ((matchIndex = sb.indexOf(delimiter, curIndex)) != -1) { + sb.replace(matchIndex, matchIndex + delimiter.length(), replacement); + curIndex = matchIndex + replacement.length(); + } + return sb.toString(); + } + + public static String replaceFirst(String str, String delimiter, String replacement) { + StringBuilder sb = new StringBuilder(str); + int i = sb.indexOf(delimiter); + if (i != -1) { + sb.replace(i, i + delimiter.length(), replacement); + } + return sb.toString(); + } + + /** + * Converts the property name, e.g. 'service.name' into a public environment variable name, e.g. + * `DD_SERVICE_NAME`. + * + * @param setting The setting name, e.g. `service.name` + * @return The public facing environment variable name + */ + @NonNull + public static String propertyNameToEnvironmentVariableName(final String setting) { + return "DD_" + toEnvVar(setting); + } + + /** + * Converts the system property name, e.g. 'dd.service.name' into a public environment variable + * name, e.g. `DD_SERVICE_NAME`. + * + * @param setting The system property name, e.g. `dd.service.name` + * @return The public facing environment variable name + */ + @NonNull + public static String systemPropertyNameToEnvironmentVariableName(final String setting) { + return setting.replace('.', '_').replace('-', '_').toUpperCase(); + } + + /** + * Converts the property name, e.g. 'service.name' into a public system property name, e.g. + * `dd.service.name`. + * + * @param setting The setting name, e.g. `service.name` + * @return The public facing system property name + */ + @NonNull + public static String propertyNameToSystemPropertyName(final String setting) { + return "dd." + setting; + } + + @NonNull + public static String normalizedHeaderTag(String str) { + if (str.isEmpty()) { + return ""; + } + StringBuilder builder = new StringBuilder(str.length()); + int firstNonWhiteSpace = -1; + int lastNonWhitespace = -1; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (Character.isWhitespace(c)) { + builder.append('_'); + } else { + firstNonWhiteSpace = firstNonWhiteSpace == -1 ? i : firstNonWhiteSpace; + lastNonWhitespace = i; + if (Character.isLetterOrDigit(c) || c == '_' || c == '-' || c == '/') { + builder.append(Character.toLowerCase(c)); + } else { + builder.append('_'); + } + } + } + if (firstNonWhiteSpace == -1) { + return ""; + } else { + str = builder.substring(firstNonWhiteSpace, lastNonWhitespace + 1); + return str; + } + } + + @NonNull + public static String trim(final String string) { + return null == string ? "" : string.trim(); + } + + private static String hex(char ch) { + return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH); + } + + public static String sha256(String input) throws NoSuchAlgorithmException { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8)); + StringBuilder hexString = new StringBuilder(2 * hash.length); + for (int i = 0; i < hash.length; i++) { + String hex = Integer.toHexString(0xFF & hash[i]); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } + + public static String truncate(String input, int limit) { + return (String) truncate((CharSequence) input, limit); + } + + public static CharSequence truncate(CharSequence input, int limit) { + if (input == null || input.length() <= limit) { + return input; + } + return input.subSequence(0, limit); + } + + public static String toJson(final Map map) { + return toJson(map, false); + } + + public static String toJson(final Map map, boolean valuesAreJson) { + if (map == null || map.isEmpty()) { + return "{}"; + } + final StringBuilder sb = new StringBuilder("{"); + final Iterator> entriesIter = map.entrySet().iterator(); + while (entriesIter.hasNext()) { + final Entry entry = entriesIter.next(); + + sb.append("\"").append(escapeToJson(entry.getKey())).append("\":"); + + if (valuesAreJson) { + sb.append(entry.getValue()); + } else { + sb.append("\"").append(escapeToJson(String.valueOf(entry.getValue()))).append("\""); + } + + if (entriesIter.hasNext()) { + sb.append(","); + } + } + sb.append("}"); + return sb.toString(); + } + + public static String toJson(final Iterable items) { + if (items == null) { + return "[]"; + } + StringBuilder json = new StringBuilder("["); + Iterator it = items.iterator(); + while (it.hasNext()) { + String item = it.next(); + json.append('"').append(escapeToJson(item)).append('"'); + if (it.hasNext()) { + json.append(","); + } + } + json.append("]"); + return json.toString(); + } + + /** + * Checks that a string is not blank, i.e. contains at least one character that is not a + * whitespace + * + * @param s The string to be checked + * @return {@code true} if string is not blank, {@code false} otherwise (string is {@code null}, + * empty, or contains only whitespace characters) + */ + public static boolean isNotBlank(String s) { + if (s == null || s.isEmpty()) { + return false; + } + + // the code below traverses string characters one by one + // and checks if there is any character that is not a whitespace (space, tab, newline, etc); + final int length = s.length(); + for (int offset = 0; offset < length; ) { + // codepoints are used instead of chars, to properly handle non-unicode symbols + final int codepoint = s.codePointAt(offset); + if (!Character.isWhitespace(codepoint)) { + return true; + } + offset += Character.charCount(codepoint); + } + + return false; + } + + /** + * Generates a random string of the given length from lowercase characters a-z + * + * @param length length of the string + * @return random string containing lowercase latin characters + */ + public static String random(int length) { + char[] c = new char[length]; + for (int i = 0; i < length; i++) { + c[i] = (char) ('a' + ThreadLocalRandom.current().nextInt(26)); + } + return new String(c); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/TagsHelper.java b/features/dd-trace-core/src/main/java/datadog/trace/util/TagsHelper.java new file mode 100644 index 0000000000..e0f2da7fab --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/TagsHelper.java @@ -0,0 +1,83 @@ +package datadog.trace.util; + +import java.util.Locale; + +/** Helper class for handling tags */ +public final class TagsHelper { + private static final int MAX_LENGTH = 200; + + /** + * Taken from: + * https://github.com/DataDog/logs-backend/blob/d0b3289ce2c63c1e8f961f03fc4e03318fb36b0f/processing/src/main/java/com/dd/logs/processing/common/Tags.java#L44 + * + *

    Sanitizes a tag, more or less following (but not exactly) as per recommended DataDog + * guidelines. + * + *

    See the exact guidelines: + * https://docs.datadoghq.com/getting_started/tagging/#tags-best-practices + * + *

    1. Tags must start with a letter, and after that may contain: - Alphanumerics - Underscores + * - Minuses - Colons - Periods - Slashes Other special characters get converted to underscores. + * Note: A tag cannot end with a colon (e.g., tag:) + * + *

    2. Tags can be up to 200 characters long and support unicode. + * + *

    3. Tags are converted to lowercase. + * + *

    4. A tag can have a value or a key:value syntax: For optimal functionality, we recommend + * constructing tags that use the key:value syntax. The key is always what precedes the first + * colon of the global tag definition, e.g.: - role:database:mysql is parsed as key:role , + * value:database:mysql - role_database:mysql is parsed as key:role_database , value:mysql + * Examples of commonly used metric tag keys are env, instance, name, and role. + * + *

    5. device, host, and source are reserved tag keys and cannot be specified in the standard + * way. + * + *

    6. Tags shouldn't originate from unbounded sources, such as EPOCH timestamps or user IDs. + * These tags may impact platform performance and billing. + * + *

    Changes: we trim leading and trailing spaces. + * + * @param tag The tag to sanitize. + * @return A sanitized tag, or null if the provided tag was null. + */ + public static String sanitize(String tag) { + if (tag == null) { + return null; + } + String lower = tag.toLowerCase(Locale.ROOT).trim(); + int length = Math.min(lower.length(), MAX_LENGTH); + StringBuilder sanitized = new StringBuilder(length); + for (int i = 0; i < length; ++i) { + char c = lower.charAt(i); + if (isValid(c)) { + sanitized.append(c); + } else { + sanitized.append('_'); + } + } + return sanitized.toString(); + } + + static boolean isValid(char c) { + return (c >= 'a' && c <= 'z') + || (c >= '0' && c <= '9') + || c == '-' + || c == '_' + || c == '.' + || c == '/' + || c == ':'; + } + + public static String concatTags(String... tags) { + if (tags == null || tags.length == 0) { + return ""; + } + StringBuilder sb = new StringBuilder(); + for (String tag : tags) { + sb.append(tag); + sb.append(","); + } + return sb.substring(0, sb.length() - 1); // Remove last comma + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/TraceUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/util/TraceUtils.java new file mode 100644 index 0000000000..b5c1a1b76a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/TraceUtils.java @@ -0,0 +1,216 @@ +package datadog.trace.util; + +import static datadog.trace.util.Strings.truncate; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility methods to normalize trace data. This normalization is recommended if the trace is sent + * to a public HTTP intake directly instead of using a Datadog Agent. The normalization methods try + * to mimic the normalization is done in the Datadog Agent. + */ +public class TraceUtils { + + private static final int MAX_TYPE_LEN = 100; + private static final int MAX_SERVICE_LEN = 100; + private static final int MAX_OP_NAME_LEN = 100; + private static final int MAX_ENV_LEN = 200; + + static final String DEFAULT_SERVICE_NAME = "unnamed-service"; + static final String DEFAULT_OPERATION_NAME = "unnamed_operation"; + static final String DEFAULT_ENV = "none"; + + private static final Logger log = LoggerFactory.getLogger(TraceUtils.class); + + public static String normalizeServiceName(final String service) { + if (service == null || service.isEmpty()) { + log.debug( + "Fixing malformed trace. Service is empty (reason:service_empty), setting span.service={}.", + service); + return DEFAULT_SERVICE_NAME; + } + + String svc = service; + if (svc.length() > MAX_SERVICE_LEN) { + log.debug( + "Fixing malformed trace. Service is too long (reason:service_truncate), truncating span.service to length={}.", + MAX_SERVICE_LEN); + svc = truncate(svc, MAX_SERVICE_LEN); + } + + return normalizeTag(svc); + } + + public static CharSequence normalizeOperationName(final CharSequence opName) { + if (opName == null || opName.length() == 0) { + return DEFAULT_OPERATION_NAME; + } + + CharSequence name = opName; + if (name.length() > MAX_OP_NAME_LEN) { + log.debug( + "Fixing malformed trace. Name is too long (reason:span_name_truncate), truncating span.name to length={}.", + MAX_OP_NAME_LEN); + name = truncate(name, MAX_OP_NAME_LEN); + } + + name = normalizeSpanName(name); + if (name.length() == 0) { + name = DEFAULT_OPERATION_NAME; + } + return name; + } + + public static CharSequence normalizeSpanType(final CharSequence spanType) { + if (spanType != null && spanType.length() > MAX_TYPE_LEN) { + log.debug( + "Fixing malformed trace. Type is too long (reason:type_truncate), truncating span.type to length={}", + MAX_TYPE_LEN); + return truncate(spanType, MAX_TYPE_LEN); + } + return spanType; + } + + public static String normalizeEnv(final String env) { + if (env == null || env.length() == 0) { + return DEFAULT_ENV; + } + + String e = truncate(env, MAX_ENV_LEN); + return normalizeTag(e); + } + + public static boolean isValidStatusCode(final int httpStatusCode) { + return (httpStatusCode >= 100 && httpStatusCode < 600); + } + + // spotless:off + + /** + * Normalizes a tag value: + * - Only letters, digits, ":", ".", "-", "_" and "/" are allowed. + * - If a non-valid char is found, it's replaced with "_". If it's the last char, it's removed. + * - It must start with a letter or ":". + * - It applies lower case. + * + * @param tag value + * @return normalized tag value + */ + // spotless:on + public static String normalizeTag(final String tag) { + if (tag == null || tag.isEmpty()) { + return ""; + } + + StringBuilder builder = new StringBuilder(tag.length()); + boolean isJumping = false; + for (int i = 0; i < tag.length(); ++i) { + char ch = tag.charAt(i); + if (ch >= 'a' && ch <= 'z' || ch == ':') { + isJumping = false; + builder.append(ch); + continue; + } + if (ch >= 'A' && ch <= 'Z') { + isJumping = false; + ch += 'a' - 'A'; + builder.append(ch); + continue; + } + if (Character.isUpperCase(ch)) { + ch = Character.toLowerCase(ch); + } + if (Character.isLetter(ch)) { + isJumping = false; + builder.append(ch); + continue; + } + if (builder.length() == 0) { + // this character can't start the string, trim + continue; + } + if (Character.isDigit(ch) || ch == '.' || ch == '/' || ch == '-') { + isJumping = false; + builder.append(ch); + continue; + } + if (!isJumping) { + builder.append('_'); + isJumping = true; + } + } + // If last added character was due to a bad pattern, just remove the last added underscore + if (isJumping) { + builder.setLength(builder.length() - 1); + } + return builder.toString(); + } + + // spotless:off + + /** + * Normalizes the span name: + * - Only alphanumeric chars, "_" and "." are allowed. + * - If a non-valid char is found, it's replaced with "_". If it's the last char, it's removed. + * - Multiple underscores "___" transformed into a single one "_" + * - Pattern "-." transformed into "." + * + * @param name + * @return normalized span name + */ + // spotless:on + private static CharSequence normalizeSpanName(final CharSequence name) { + if (name.length() == 0) { + return name; + } + + final StringBuilder builder = new StringBuilder(name.length()); + + int i = 0; + char previousCh = 0; + // skip non-alphabetic characters + for (i = 0; i < name.length() && !isAlpha(name.charAt(i)); i++) {} + + // if there were no alphabetic characters it wasn't valid + if (i == name.length()) { + return ""; + } + + for (; i < name.length(); i++) { + char ch = name.charAt(i); + + if (isAlphaNum(ch)) { + builder.append(ch); + previousCh = ch; + } else if (ch == '.') { + if (previousCh == '_') { + // overwrite underscores that happen before periods + builder.setLength(builder.length() - 1); + } + builder.append(ch); + previousCh = ch; + } else { + if (previousCh != '.' && previousCh != '_') { + builder.append('_'); + previousCh = '_'; + } + } + } + + if (previousCh == '_') { + builder.setLength(builder.length() - 1); + } + return builder.toString(); + } + + // fast isAlpha for ascii + private static boolean isAlpha(char ch) { + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); + } + + // fast isAlphaNumeric for ascii + private static boolean isAlphaNum(char ch) { + return isAlpha(ch) || (ch >= '0' && ch <= '9'); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/AbstractStackWalker.java b/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/AbstractStackWalker.java new file mode 100644 index 0000000000..17c90ae02a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/AbstractStackWalker.java @@ -0,0 +1,23 @@ +package datadog.trace.util.stacktrace; + +import java.util.function.Function; +import java.util.stream.Stream; + +public abstract class AbstractStackWalker implements StackWalker { + + @Override + public T walk(Function, T> consumer) { + return doGetStack(input -> consumer.apply(doFilterStack(input))); + } + + final Stream doFilterStack(Stream stream) { + return stream.filter(AbstractStackWalker::isNotDatadogTraceStackElement); + } + + abstract T doGetStack(Function, T> consumer); + + static boolean isNotDatadogTraceStackElement(final StackTraceElement el) { + final String clazz = el.getClassName(); + return !clazz.startsWith("datadog.trace.") && !clazz.startsWith("com.datadog.iast."); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/DefaultStackWalker.java b/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/DefaultStackWalker.java new file mode 100644 index 0000000000..a19d0b702b --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/DefaultStackWalker.java @@ -0,0 +1,20 @@ +package datadog.trace.util.stacktrace; + +import java.util.Arrays; +import java.util.function.Function; +import java.util.stream.Stream; + +public class DefaultStackWalker extends AbstractStackWalker { + + DefaultStackWalker() {} + + @Override + public boolean isEnabled() { + return true; + } + + @Override + T doGetStack(final Function, T> consumer) { + return consumer.apply(Arrays.stream(new Throwable().getStackTrace())); + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackUtils.java new file mode 100644 index 0000000000..5f3cc6a22c --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackUtils.java @@ -0,0 +1,88 @@ +package datadog.trace.util.stacktrace; + +import java.util.Arrays; +import java.util.function.Function; +import java.util.function.Predicate; + +public abstract class StackUtils { + + public static E update( + final E exception, final Function filter) { + final StackTraceElement[] stack = exception.getStackTrace(); + exception.setStackTrace(filter.apply(stack)); + return exception; + } + + public static E filter( + final E exception, final Predicate filter) { + return update( + exception, stack -> Arrays.stream(stack).filter(filter).toArray(StackTraceElement[]::new)); + } + + public static E filterFirst( + final E exception, final Predicate filter) { + return filter(exception, new OneTimePredicate<>(filter)); + } + + public static E filterDatadog(final E exception) { + return filter(exception, AbstractStackWalker::isNotDatadogTraceStackElement); + } + + public static E filterFirstDatadog(final E exception) { + return filterFirst(exception, AbstractStackWalker::isNotDatadogTraceStackElement); + } + + public static E filterUntil( + final E exception, final Predicate trace) { + return update( + exception, + stack -> { + final StackTraceElement[] source = exception.getStackTrace(); + for (int i = 0; i < source.length; i++) { + if (trace.test(source[i])) { + final StackTraceElement[] result = new StackTraceElement[source.length - i - 1]; + System.arraycopy(source, i + 1, result, 0, result.length); + return result; + } + } + return source; + }); + } + + public static E filterPackagesIn( + final E exception, final String[] packages) { + return filter( + exception, + ste -> { + final String clazz = ste.getClassName(); + for (String p : packages) { + if (clazz.startsWith(p)) { + return true; + } + } + return false; + }); + } + + private static class OneTimePredicate implements Predicate { + + private final Predicate delegate; + private boolean filtered; + + private OneTimePredicate(final Predicate delegate) { + this.delegate = delegate; + } + + @Override + public boolean test(final T item) { + if (filtered) { + return true; + } + final boolean test = delegate.test(item); + if (!test) { + filtered = true; + } + return test; + } + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalker.java b/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalker.java new file mode 100644 index 0000000000..9364fb306a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalker.java @@ -0,0 +1,12 @@ +package datadog.trace.util.stacktrace; + +import java.util.function.Function; +import java.util.stream.Stream; + +public interface StackWalker { + + boolean isEnabled(); + + /** StackTrace should be returned without any element from the dd-trace-java-agent itself. */ + T walk(Function, T> consumer); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalkerFactory.java b/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalkerFactory.java new file mode 100644 index 0000000000..ec93321e9a --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalkerFactory.java @@ -0,0 +1,63 @@ +package datadog.trace.util.stacktrace; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Objects; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import datadog.trace.api.Platform; + +public class StackWalkerFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(StackWalkerFactory.class); + + public static final StackWalker INSTANCE; + + static { + Stream stream = Stream.of(hotspot(), jdk9()).map(Supplier::get); + INSTANCE = + stream + .filter(Objects::nonNull) + .filter(StackWalker::isEnabled) + .findFirst() + .orElseGet(defaultStackWalker()); + } + + private static Supplier defaultStackWalker() { + return DefaultStackWalker::new; + } + +// private static Supplier hotspot() { +// return () -> { +// if (!Platform.isJavaVersion(8)) { +// return null; +// } +// return new HotSpotStackWalker(); +// }; +// } + + private static Supplier hotspot() { + return () -> { + return null; + }; + } + + private static Supplier jdk9() { + return () -> { + if (!Platform.isJavaVersionAtLeast(9)) { + return null; + } + try { + return (StackWalker) + Class.forName("datadog.trace.util.stacktrace.JDK9StackWalker") + .getDeclaredConstructor() + .newInstance(); + } catch (Throwable e) { + LOGGER.warn("JDK9StackWalker not available", e); + return null; + } + }; + } +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java b/features/dd-trace-core/src/main/java/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java new file mode 100644 index 0000000000..5feb71d160 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java @@ -0,0 +1,15 @@ +package datadog.trace.util.throwable; + +/** + * This error represents a critical agent configuration issue that needs to be signalled to the + * client in a fail-fast manner. It is reserved for the rare cases when we want to abort the entire + * process rather than proceeding to start without the properly initialised agent. + * + *

    This class is referred to by name in some parts of the code, so please be cautious when + * renaming or moving it. + */ +public class FatalAgentMisconfigurationError extends Error { + public FatalAgentMisconfigurationError(String message) { + super(message); + } +} diff --git a/features/dd-trace-core/transitiveDependencies b/features/dd-trace-core/transitiveDependencies new file mode 100644 index 0000000000..72288f83cd --- /dev/null +++ b/features/dd-trace-core/transitiveDependencies @@ -0,0 +1,32 @@ +Dependencies List + +androidx.annotation:annotation:1.1.0 : 27 Kb +com.datadoghq:sketches-java:0.8.2 : 125 Kb +com.github.spotbugs:spotbugs-annotations:4.2.0 : 14 Kb +com.github.spotbugs:spotbugs:4.2.0 : 3 Mb +com.google.code.findbugs:jsr305:3.0.2 : 19 Kb +com.google.re2j:re2j:1.7 : 111 Kb +com.squareup.moshi:moshi:1.11.0 : 148 Kb +com.squareup.okhttp3:okhttp:4.11.0 : 768 Kb +com.squareup.okio:okio-jvm:3.2.0 : 337 Kb +net.jcip:jcip-annotations:1.0 : 2 Kb +org.apache.bcel:bcel:6.5.0 : 678 Kb +org.apache.commons:commons-lang3:3.11 : 564 Kb +org.apache.commons:commons-text:1.9 : 211 Kb +org.dom4j:dom4j:2.1.3 : 316 Kb +org.jctools:jctools-core:3.3.0 : 328 Kb +org.jetbrains.kotlin:kotlin-stdlib-common:1.8.10 : 212 Kb +org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.10 : 963 b +org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10 : 969 b +org.jetbrains.kotlin:kotlin-stdlib:1.8.10 : 1598 Kb +org.jetbrains:annotations:13.0 : 17 Kb +org.json:json:20200518 : 64 Kb +org.ow2.asm:asm-analysis:9.0 : 32 Kb +org.ow2.asm:asm-commons:9.0 : 69 Kb +org.ow2.asm:asm-tree:9.0 : 51 Kb +org.ow2.asm:asm-util:9.0 : 82 Kb +org.ow2.asm:asm:9.0 : 118 Kb +org.slf4j:slf4j-api:1.7.30 : 40 Kb + +Total transitive dependencies size : 9 Mb + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7d02b4ebe2..e5cfc17417 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -83,6 +83,17 @@ coroutines = "1.4.2" # Local Server ktor = "1.6.0" +# Otel +slf4j = "1.7.30" +moshi = "1.11.0" +jctools = "3.3.0" +openTelemetry = "1.4.0" +desugarJdk = "2.0.4" +datatadogSketchesJava = "0.8.2" +re2j = "1.7" +spotbugs = "4.2.0" + + [libraries] # Classpaths @@ -217,6 +228,16 @@ ktorCore = { module = "io.ktor:ktor", version.ref = "ktor" } ktorNetty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" } ktorGson = { module = "io.ktor:ktor-gson", version.ref = "ktor" } +# Otel +slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } +moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" } +jctools = { module = "org.jctools:jctools-core", version.ref = "jctools" } +openTelemetry = { module = "io.opentelemetry:opentelemetry-api", version.ref = "openTelemetry" } +desugarJdk = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugarJdk" } +datadogSketchesJava = { module = "com.datadoghq:sketches-java", version.ref = "datatadogSketchesJava" } +re2j = { module = "com.google.re2j:re2j", version.ref = "re2j" } +spotbugs = { module = "com.github.spotbugs:spotbugs", version.ref = "spotbugs" } + [bundles] jUnit5 = [ @@ -286,3 +307,4 @@ ktor = [ [plugins] versionsGradlePlugin = { id = "com.github.ben-manes.versions", version.ref = "versionsGradlePlugin" } + diff --git a/settings.gradle.kts b/settings.gradle.kts index 44d7bb1496..070361649c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -52,3 +52,6 @@ include(":tools:unit") include(":tools:noopfactory") include(":tools:javabackport") include(":tools:lint") + +// Otel +include(":features:dd-trace-core") From 31c4fee1ae508426512b4b4d0eb955cf2cf1bee3 Mon Sep 17 00:00:00 2001 From: Marius Constantin Date: Wed, 21 Feb 2024 10:46:37 +0100 Subject: [PATCH 02/55] Fix Lint issues --- features/dd-trace-core/api/apiSurface | 0 features/dd-trace-core/api/dd-trace-core.api | 490 +- features/dd-trace-core/build.gradle.kts | 11 +- features/dd-trace-core/lint.xml | 2 +- .../main/java/datadog/trace/api/Config.java | 7226 +++++++++-------- .../trace/api/IdGenerationStrategy.java | 15 +- .../main/java/datadog/trace/api/Platform.java | 2 +- .../datadog/trace/api/PropagationStyle.java | 3 +- .../trace/api/TracePropagationStyle.java | 2 +- .../api/cache/QualifiedClassNameCache.java | 61 - .../trace/api/civisibility/CIVisibility.java | 50 - .../datadog/trace/api/git/CommitInfo.java | 93 - .../trace/api/git/EmbeddedGitInfoBuilder.java | 77 - .../java/datadog/trace/api/git/GitInfo.java | 80 - .../datadog/trace/api/git/GitInfoBuilder.java | 9 - .../trace/api/git/GitInfoProvider.java | 167 - .../java/datadog/trace/api/git/GitUtils.java | 228 - .../datadog/trace/api/git/PersonInfo.java | 103 - .../datadog/trace/api/git/RawParseUtils.java | 392 - .../api/git/UserSuppliedGitInfoBuilder.java | 108 - .../trace/api/profiling/ObservableType.java | 1 - .../api/profiling/ProfilingListener.java | 10 - .../api/profiling/ProfilingListeners.java | 44 - .../profiling/ProfilingListenersRegistry.java | 28 - .../trace/api/sampling/AdaptiveSampler.java | 317 - .../trace/api/sampling/ConstantSampler.java | 25 - .../config/provider/ConfigConverter.java | 22 - .../instrumentation/api/AgentTracer.java | 12 - .../common/GitMetadataTraceInterceptor.java | 38 - .../trace/common/metrics/Aggregator.java | 194 - .../trace/common/metrics/InboxItem.java | 27 - .../common/metrics/NoOpMetricsAggregator.java | 30 +- .../metrics/SerializingMetricWriter.java | 136 - .../datadog/trace/common/writer/Payload.java | 89 - .../common/writer/PayloadDispatcherImpl.java | 129 - .../java/datadog/trace/core/CoreTracer.java | 19 - .../MsgPackDatastreamsPayloadWriter.java | 169 - .../datadog/trace/lambda/LambdaHandler.java | 184 - .../SkipUnsupportedTypeJsonAdapter.java | 39 - .../java/datadog/trace/logging/LogLevel.java | 4 +- .../datadog/trace/serialization/Codec.java | 295 - .../serialization/msgpack/MsgPackWriter.java | 581 -- .../datadog/trace/util/ClassNameTrie.java | 927 --- .../java/datadog/trace/util/FileUtils.java | 28 + .../datadog/trace/util/MethodHandles.java | 176 - .../datadog/trace/util/ProcessSupervisor.java | 150 - .../main/java/datadog/trace/util/Strings.java | 6 +- .../datadog/trace/util/FileUtilsTest.kt | 67 + 48 files changed, 3844 insertions(+), 9022 deletions(-) delete mode 100644 features/dd-trace-core/api/apiSurface delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/cache/QualifiedClassNameCache.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIVisibility.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/CommitInfo.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/EmbeddedGitInfoBuilder.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfo.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoBuilder.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoProvider.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/GitUtils.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/PersonInfo.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/RawParseUtils.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListener.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListeners.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListenersRegistry.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/sampling/AdaptiveSampler.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/sampling/ConstantSampler.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/GitMetadataTraceInterceptor.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Aggregator.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/SerializingMetricWriter.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcherImpl.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/MsgPackDatastreamsPayloadWriter.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/lambda/SkipUnsupportedTypeJsonAdapter.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/Codec.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/serialization/msgpack/MsgPackWriter.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/ClassNameTrie.java create mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/FileUtils.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/MethodHandles.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/util/ProcessSupervisor.java create mode 100644 features/dd-trace-core/src/test/kotlin/datadog/trace/util/FileUtilsTest.kt diff --git a/features/dd-trace-core/api/apiSurface b/features/dd-trace-core/api/apiSurface deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/features/dd-trace-core/api/dd-trace-core.api b/features/dd-trace-core/api/dd-trace-core.api index 6cb2342e7d..1b07554c55 100644 --- a/features/dd-trace-core/api/dd-trace-core.api +++ b/features/dd-trace-core/api/dd-trace-core.api @@ -1,93 +1,3 @@ -public class datadog/appsec/api/blocking/Blocking { - public static fun forUser (Ljava/lang/String;)Ldatadog/appsec/api/blocking/Blocking$UserBlockingSpec; - public static fun setBlockingService (Ldatadog/appsec/api/blocking/BlockingService;)V - public static fun tryCommitBlockingResponse (ILdatadog/appsec/api/blocking/BlockingContentType;)Z - public static fun tryCommitBlockingResponse (ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z -} - -public class datadog/appsec/api/blocking/Blocking$UserBlockingSpec { - public fun blockIfMatch ()V - public fun shouldBlock ()Ldatadog/appsec/api/blocking/BlockingDetails; -} - -public final class datadog/appsec/api/blocking/BlockingContentType : java/lang/Enum { - public static final field AUTO Ldatadog/appsec/api/blocking/BlockingContentType; - public static final field HTML Ldatadog/appsec/api/blocking/BlockingContentType; - public static final field JSON Ldatadog/appsec/api/blocking/BlockingContentType; - public static final field NONE Ldatadog/appsec/api/blocking/BlockingContentType; - public static fun valueOf (Ljava/lang/String;)Ldatadog/appsec/api/blocking/BlockingContentType; - public static fun values ()[Ldatadog/appsec/api/blocking/BlockingContentType; -} - -public class datadog/appsec/api/blocking/BlockingDetails { - public final field blockingContentType Ldatadog/appsec/api/blocking/BlockingContentType; - public final field extraHeaders Ljava/util/Map; - public final field statusCode I - public fun (ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)V -} - -public class datadog/appsec/api/blocking/BlockingException : java/lang/RuntimeException { - public fun ()V - public fun (Ljava/lang/String;)V - public fun (Ljava/lang/String;Ljava/lang/Throwable;)V - public fun (Ljava/lang/Throwable;)V -} - -public abstract interface class datadog/appsec/api/blocking/BlockingService { - public static final field NOOP Ldatadog/appsec/api/blocking/BlockingService; - public abstract fun shouldBlockUser (Ljava/lang/String;)Ldatadog/appsec/api/blocking/BlockingDetails; - public abstract fun tryCommitBlockingResponse (ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z -} - -public class datadog/appsec/api/blocking/BlockingService$BlockingServiceNoop : datadog/appsec/api/blocking/BlockingService { - public fun shouldBlockUser (Ljava/lang/String;)Ldatadog/appsec/api/blocking/BlockingDetails; - public fun tryCommitBlockingResponse (ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z -} - -public class datadog/container/ContainerInfo { - public field cGroups Ljava/util/List; - public field containerId Ljava/lang/String; - public field podId Ljava/lang/String; - public fun ()V - public static fun fromDefaultProcFile ()Ldatadog/container/ContainerInfo; - public static fun get ()Ldatadog/container/ContainerInfo; - public fun getCGroups ()Ljava/util/List; - public fun getContainerId ()Ljava/lang/String; - public fun getPodId ()Ljava/lang/String; - public static fun isRunningInContainer ()Z - public static fun parse (Ljava/lang/String;)Ldatadog/container/ContainerInfo; - public fun setContainerId (Ljava/lang/String;)V - public fun setPodId (Ljava/lang/String;)V - public fun setcGroups (Ljava/util/List;)V -} - -public class datadog/container/ContainerInfo$CGroupInfo { - public field containerId Ljava/lang/String; - public field controllers Ljava/util/List; - public field id I - public field path Ljava/lang/String; - public field podId Ljava/lang/String; - public fun ()V - public fun getContainerId ()Ljava/lang/String; - public fun getControllers ()Ljava/util/List; - public fun getId ()I - public fun getPath ()Ljava/lang/String; - public fun getPodId ()Ljava/lang/String; - public fun setContainerId (Ljava/lang/String;)V - public fun setControllers (Ljava/util/List;)V - public fun setId (I)V - public fun setPath (Ljava/lang/String;)V - public fun setPodId (Ljava/lang/String;)V -} - -public class datadog/container/ServerlessInfo { - public fun ()V - public static fun get ()Ldatadog/container/ServerlessInfo; - public fun getFunctionName ()Ljava/lang/String; - public fun hasExtension ()Z - public fun isRunningInServerlessEnvironment ()Z -} - public abstract interface annotation class datadog/trace/advice/ActiveRequestContext : java/lang/annotation/Annotation { } @@ -1033,13 +943,6 @@ public abstract interface class datadog/trace/api/cache/DDPartialKeyCache$Produc public abstract fun apply (Ljava/lang/Object;III)Ljava/lang/Object; } -public final class datadog/trace/api/cache/QualifiedClassNameCache : java/lang/ClassValue { - public fun (Ljava/util/function/Function;Ldatadog/trace/api/Functions$Join;)V - public fun (Ljava/util/function/Function;Ldatadog/trace/api/Functions$Join;I)V - public fun getClassName (Ljava/lang/Class;)Ljava/lang/CharSequence; - public fun getQualifiedName (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/CharSequence; -} - public final class datadog/trace/api/cache/RadixTreeCache { public static final field HTTP_STATUSES Ldatadog/trace/api/cache/RadixTreeCache; public static final field PORTS Ldatadog/trace/api/cache/RadixTreeCache; @@ -1055,17 +958,6 @@ public abstract interface class datadog/trace/api/civisibility/CIConstants { public static final field TEST_SKIP Ljava/lang/String; } -public class datadog/trace/api/civisibility/CIVisibility { - public fun ()V - public static fun registerSessionFactory (Ldatadog/trace/api/civisibility/CIVisibility$SessionFactory;)V - public static fun startSession (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTestSession; - public static fun startSession (Ljava/lang/String;Ljava/nio/file/Path;Ljava/lang/String;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTestSession; -} - -public abstract interface class datadog/trace/api/civisibility/CIVisibility$SessionFactory { - public abstract fun startSession (Ljava/lang/String;Ljava/nio/file/Path;Ljava/lang/String;Ljava/lang/Long;)Ldatadog/trace/api/civisibility/DDTestSession; -} - public abstract interface class datadog/trace/api/civisibility/DDTest { public abstract fun end (Ljava/lang/Long;)V public abstract fun setErrorInfo (Ljava/lang/Throwable;)V @@ -1815,7 +1707,7 @@ public abstract interface class datadog/trace/api/function/TriFunction { } public abstract interface class datadog/trace/api/gateway/BlockResponseFunction { - public abstract fun tryCommitBlockingResponse (Ldatadog/trace/api/internal/TraceSegment;ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z + public abstract fun tryCommitBlockingResponse (Ldatadog/trace/api/internal/TraceSegment;ILdatadog/trace/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z } public abstract interface class datadog/trace/api/gateway/CallbackProvider { @@ -1868,10 +1760,10 @@ public class datadog/trace/api/gateway/Flow$Action$Noop : datadog/trace/api/gate } public class datadog/trace/api/gateway/Flow$Action$RequestBlockingAction : datadog/trace/api/gateway/Flow$Action { - public fun (ILdatadog/appsec/api/blocking/BlockingContentType;)V - public fun (ILdatadog/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)V + public fun (ILdatadog/trace/appsec/api/blocking/BlockingContentType;)V + public fun (ILdatadog/trace/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)V public static fun forRedirect (ILjava/lang/String;)Ldatadog/trace/api/gateway/Flow$Action$RequestBlockingAction; - public fun getBlockingContentType ()Ldatadog/appsec/api/blocking/BlockingContentType; + public fun getBlockingContentType ()Ldatadog/trace/appsec/api/blocking/BlockingContentType; public fun getExtraHeaders ()Ljava/util/Map; public fun getStatusCode ()I public fun isBlocking ()Z @@ -1946,115 +1838,6 @@ public class datadog/trace/api/gateway/SubscriptionService$SubscriptionServiceNo public fun reset ()V } -public class datadog/trace/api/git/CommitInfo { - public static final field NOOP Ldatadog/trace/api/git/CommitInfo; - public fun (Ljava/lang/String;)V - public fun (Ljava/lang/String;Ldatadog/trace/api/git/PersonInfo;Ldatadog/trace/api/git/PersonInfo;Ljava/lang/String;)V - public fun equals (Ljava/lang/Object;)Z - public fun getAuthor ()Ldatadog/trace/api/git/PersonInfo; - public fun getCommitter ()Ldatadog/trace/api/git/PersonInfo; - public fun getFullMessage ()Ljava/lang/String; - public fun getSha ()Ljava/lang/String; - public fun hashCode ()I - public fun isEmpty ()Z - public fun toString ()Ljava/lang/String; -} - -public class datadog/trace/api/git/EmbeddedGitInfoBuilder : datadog/trace/api/git/GitInfoBuilder { - public fun ()V - public fun build (Ljava/lang/String;)Ldatadog/trace/api/git/GitInfo; - public fun order ()I -} - -public class datadog/trace/api/git/GitInfo { - public static final field DD_GIT_BRANCH Ljava/lang/String; - public static final field DD_GIT_COMMIT_AUTHOR_DATE Ljava/lang/String; - public static final field DD_GIT_COMMIT_AUTHOR_EMAIL Ljava/lang/String; - public static final field DD_GIT_COMMIT_AUTHOR_NAME Ljava/lang/String; - public static final field DD_GIT_COMMIT_COMMITTER_DATE Ljava/lang/String; - public static final field DD_GIT_COMMIT_COMMITTER_EMAIL Ljava/lang/String; - public static final field DD_GIT_COMMIT_COMMITTER_NAME Ljava/lang/String; - public static final field DD_GIT_COMMIT_MESSAGE Ljava/lang/String; - public static final field DD_GIT_COMMIT_SHA Ljava/lang/String; - public static final field DD_GIT_REPOSITORY_URL Ljava/lang/String; - public static final field DD_GIT_TAG Ljava/lang/String; - public static final field NOOP Ldatadog/trace/api/git/GitInfo; - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ldatadog/trace/api/git/CommitInfo;)V - public fun equals (Ljava/lang/Object;)Z - public fun getBranch ()Ljava/lang/String; - public fun getCommit ()Ldatadog/trace/api/git/CommitInfo; - public fun getRepositoryURL ()Ljava/lang/String; - public fun getTag ()Ljava/lang/String; - public fun hashCode ()I - public fun isEmpty ()Z -} - -public abstract interface class datadog/trace/api/git/GitInfoBuilder { - public abstract fun build (Ljava/lang/String;)Ldatadog/trace/api/git/GitInfo; - public abstract fun order ()I -} - -public class datadog/trace/api/git/GitInfoProvider { - public static final field INSTANCE Ldatadog/trace/api/git/GitInfoProvider; - public fun ()V - public fun getGitInfo ()Ldatadog/trace/api/git/GitInfo; - public fun getGitInfo (Ljava/lang/String;)Ldatadog/trace/api/git/GitInfo; - public fun invalidateCache ()V - public fun registerGitInfoBuilder (Ldatadog/trace/api/git/GitInfoBuilder;)V -} - -public class datadog/trace/api/git/GitUtils { - public fun ()V - public static fun filterSensitiveInfo (Ljava/lang/String;)Ljava/lang/String; - public static fun inflate ([B)[B - public static fun isTagReference (Ljava/lang/String;)Z - public static fun isValidCommitSha (Ljava/lang/String;)Z - public static fun normalizeBranch (Ljava/lang/String;)Ljava/lang/String; - public static fun normalizeTag (Ljava/lang/String;)Ljava/lang/String; - public static fun splitAuthorAndEmail (Ljava/lang/String;)Ldatadog/trace/api/git/PersonInfo; -} - -public class datadog/trace/api/git/PersonInfo { - public static final field NOOP Ldatadog/trace/api/git/PersonInfo; - public fun ()V - public fun (Ljava/lang/String;Ljava/lang/String;)V - public fun (Ljava/lang/String;Ljava/lang/String;JI)V - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - public fun equals (Ljava/lang/Object;)Z - public fun getEmail ()Ljava/lang/String; - public fun getIso8601Date ()Ljava/lang/String; - public fun getName ()Ljava/lang/String; - public fun hashCode ()I - public fun isEmpty ()Z - public fun toString ()Ljava/lang/String; -} - -public final class datadog/trace/api/git/RawParseUtils { - public static final field AUTHOR [B - public static final field COMMITTER [B - public static final fun author ([BI)I - public static fun commitMessage ([BI)I - public static fun committer ([BI)I - public static fun decode ([BII)Ljava/lang/String; - public static fun extractBinaryString ([BII)Ljava/lang/String; - public static fun findByte ([BB)I - public static fun lastIndexOfTrim ([BCI)I - public static fun match ([BI[B)I - public static fun next ([BIC)I - public static fun nextLF ([BI)I - public static fun nextLF ([BIC)I - public static fun parseBase10 ([BI)I - public static fun parseLongBase10 ([BI)J - public static fun parseTimeZoneOffset ([BI)I - public static fun tagMessage ([BI)I -} - -public class datadog/trace/api/git/UserSuppliedGitInfoBuilder : datadog/trace/api/git/GitInfoBuilder { - public fun ()V - public fun build (Ljava/lang/String;)Ldatadog/trace/api/git/GitInfo; - public fun order ()I -} - public class datadog/trace/api/http/StoredBodyFactories { public static fun maybeCreateForByte (Ljava/nio/charset/Charset;Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;)Ldatadog/trace/api/http/StoredByteBody; public static fun maybeCreateForByte (Ljava/nio/charset/Charset;Ljava/lang/Object;)Ldatadog/trace/api/http/StoredByteBody; @@ -2918,20 +2701,6 @@ public final class datadog/trace/api/profiling/ProfilingContextAttribute$NoOp : public fun ()V } -public abstract interface class datadog/trace/api/profiling/ProfilingListener { - public abstract fun onData (Ljava/lang/Object;)V -} - -public final class datadog/trace/api/profiling/ProfilingListeners { - public fun addListener (Ldatadog/trace/api/profiling/ProfilingListener;)V - public fun fireOnData (Ldatadog/trace/api/profiling/ObservableType;)V - public fun removeListener (Ldatadog/trace/api/profiling/ProfilingListener;)V -} - -public final class datadog/trace/api/profiling/ProfilingListenersRegistry { - public static fun getHost (Ljava/lang/Class;)Ldatadog/trace/api/profiling/ProfilingListeners; -} - public abstract interface class datadog/trace/api/profiling/ProfilingScope : datadog/trace/api/profiling/ProfilingContext, java/lang/AutoCloseable { public static final field NO_OP Ldatadog/trace/api/profiling/ProfilingScope; public abstract fun close ()V @@ -3013,27 +2782,6 @@ public class datadog/trace/api/profiling/Timing$NoOp : datadog/trace/api/profili public abstract interface class datadog/trace/api/profiling/TransientProfilingContextHolder { } -public class datadog/trace/api/sampling/AdaptiveSampler : datadog/trace/api/sampling/Sampler { - public fun (Ljava/time/Duration;IIILdatadog/trace/api/sampling/AdaptiveSampler$ConfigListener;)V - protected fun (Ljava/time/Duration;IIILdatadog/trace/api/sampling/AdaptiveSampler$ConfigListener;Ldatadog/trace/util/AgentTaskScheduler;Z)V - public fun (Ljava/time/Duration;IIIZ)V - public fun drop ()Z - public fun keep ()Z - public fun sample ()Z - public fun start ()V -} - -public abstract interface class datadog/trace/api/sampling/AdaptiveSampler$ConfigListener { - public abstract fun onWindowRoll (JJJDD)V -} - -public class datadog/trace/api/sampling/ConstantSampler : datadog/trace/api/sampling/Sampler { - public fun (Z)V - public fun drop ()Z - public fun keep ()Z - public fun sample ()Z -} - public class datadog/trace/api/sampling/PrioritySampling { public static final field SAMPLER_DROP B public static final field SAMPLER_KEEP B @@ -3208,6 +2956,52 @@ public abstract interface class datadog/trace/api/time/TimeSource { public abstract fun getNanoTicks ()J } +public class datadog/trace/appsec/api/blocking/Blocking { + public static fun forUser (Ljava/lang/String;)Ldatadog/trace/appsec/api/blocking/Blocking$UserBlockingSpec; + public static fun setBlockingService (Ldatadog/trace/appsec/api/blocking/BlockingService;)V + public static fun tryCommitBlockingResponse (ILdatadog/trace/appsec/api/blocking/BlockingContentType;)Z + public static fun tryCommitBlockingResponse (ILdatadog/trace/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z +} + +public class datadog/trace/appsec/api/blocking/Blocking$UserBlockingSpec { + public fun blockIfMatch ()V + public fun shouldBlock ()Ldatadog/trace/appsec/api/blocking/BlockingDetails; +} + +public final class datadog/trace/appsec/api/blocking/BlockingContentType : java/lang/Enum { + public static final field AUTO Ldatadog/trace/appsec/api/blocking/BlockingContentType; + public static final field HTML Ldatadog/trace/appsec/api/blocking/BlockingContentType; + public static final field JSON Ldatadog/trace/appsec/api/blocking/BlockingContentType; + public static final field NONE Ldatadog/trace/appsec/api/blocking/BlockingContentType; + public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/appsec/api/blocking/BlockingContentType; + public static fun values ()[Ldatadog/trace/appsec/api/blocking/BlockingContentType; +} + +public class datadog/trace/appsec/api/blocking/BlockingDetails { + public final field blockingContentType Ldatadog/trace/appsec/api/blocking/BlockingContentType; + public final field extraHeaders Ljava/util/Map; + public final field statusCode I + public fun (ILdatadog/trace/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)V +} + +public class datadog/trace/appsec/api/blocking/BlockingException : java/lang/RuntimeException { + public fun ()V + public fun (Ljava/lang/String;)V + public fun (Ljava/lang/String;Ljava/lang/Throwable;)V + public fun (Ljava/lang/Throwable;)V +} + +public abstract interface class datadog/trace/appsec/api/blocking/BlockingService { + public static final field NOOP Ldatadog/trace/appsec/api/blocking/BlockingService; + public abstract fun shouldBlockUser (Ljava/lang/String;)Ldatadog/trace/appsec/api/blocking/BlockingDetails; + public abstract fun tryCommitBlockingResponse (ILdatadog/trace/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z +} + +public class datadog/trace/appsec/api/blocking/BlockingService$BlockingServiceNoop : datadog/trace/appsec/api/blocking/BlockingService { + public fun shouldBlockUser (Ljava/lang/String;)Ldatadog/trace/appsec/api/blocking/BlockingDetails; + public fun tryCommitBlockingResponse (ILdatadog/trace/appsec/api/blocking/BlockingContentType;Ljava/util/Map;)Z +} + public class datadog/trace/bootstrap/ActiveSubsystems { public static field APPSEC_ACTIVE Z public fun ()V @@ -3722,8 +3516,6 @@ public abstract interface class datadog/trace/bootstrap/instrumentation/api/Agen public abstract fun getUniversalCallbackProvider ()Ldatadog/trace/api/gateway/CallbackProvider; public abstract fun newHistogram (DI)Ldatadog/trace/bootstrap/instrumentation/api/AgentHistogram; public abstract fun noopSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; - public abstract fun notifyExtensionEnd (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Z)V - public abstract fun notifyExtensionStart (Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; public abstract fun propagate ()Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation; public abstract fun registerCheckpointer (Ldatadog/trace/api/EndpointCheckpointer;)V public abstract fun registerTimer (Ldatadog/trace/api/profiling/Timer;)V @@ -4304,12 +4096,6 @@ public class datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor public fun onTraceComplete (Ljava/util/Collection;)Ljava/util/Collection; } -public class datadog/trace/common/GitMetadataTraceInterceptor : datadog/trace/api/interceptor/AbstractTraceInterceptor { - public static final field INSTANCE Ldatadog/trace/api/interceptor/TraceInterceptor; - protected fun (Ldatadog/trace/api/interceptor/AbstractTraceInterceptor$Priority;)V - public fun onTraceComplete (Ljava/util/Collection;)Ljava/util/Collection; -} - public final class datadog/trace/common/metrics/AggregateMetric { public fun ()V public fun clear ()V @@ -4380,15 +4166,6 @@ public final class datadog/trace/common/metrics/NoOpMetricsAggregator : datadog/ public fun start ()V } -public final class datadog/trace/common/metrics/SerializingMetricWriter : datadog/trace/common/metrics/MetricWriter { - public fun (Ldatadog/trace/api/WellKnownTags;Ldatadog/trace/common/metrics/Sink;)V - public fun (Ldatadog/trace/api/WellKnownTags;Ldatadog/trace/common/metrics/Sink;I)V - public fun add (Ldatadog/trace/common/metrics/MetricKey;Ldatadog/trace/common/metrics/AggregateMetric;)V - public fun finishBucket ()V - public fun reset ()V - public fun startBucket (IJJ)V -} - public abstract interface class datadog/trace/common/metrics/Sink : datadog/trace/serialization/ByteBufferConsumer { public abstract fun register (Ldatadog/trace/common/metrics/EventListener;)V } @@ -4596,28 +4373,6 @@ public class datadog/trace/common/writer/LoggingWriter : datadog/trace/common/wr public abstract class datadog/trace/common/writer/Payload { protected field body Ljava/nio/ByteBuffer; public fun ()V - public fun droppedSpans ()J - public fun droppedTraces ()J - protected fun msgpackArrayHeader (I)Ljava/nio/ByteBuffer; - protected fun msgpackArrayHeaderSize (I)I - protected fun msgpackMapHeader (I)Ljava/nio/ByteBuffer; - protected fun msgpackMapHeaderSize (I)I - public abstract fun sizeInBytes ()I - public abstract fun toRequest ()Lokhttp3/RequestBody; - public fun traceCount ()I - public fun withBody (ILjava/nio/ByteBuffer;)Ldatadog/trace/common/writer/Payload; - public fun withDroppedSpans (J)Ldatadog/trace/common/writer/Payload; - public fun withDroppedTraces (J)Ldatadog/trace/common/writer/Payload; - public abstract fun writeTo (Ljava/nio/channels/WritableByteChannel;)V -} - -public class datadog/trace/common/writer/PayloadDispatcherImpl : datadog/trace/common/writer/PayloadDispatcher, datadog/trace/serialization/ByteBufferConsumer { - public fun (Ldatadog/trace/common/writer/RemoteMapperDiscovery;Ldatadog/trace/common/writer/RemoteApi;Ldatadog/trace/core/monitor/HealthMetrics;Ldatadog/trace/monitor/Monitoring;)V - public fun accept (ILjava/nio/ByteBuffer;)V - public fun addTrace (Ljava/util/List;)V - public fun flush ()V - public fun getApis ()Ljava/util/Collection; - public fun onDroppedTrace (I)V } public class datadog/trace/common/writer/PrintingWriter : datadog/trace/common/writer/Writer { @@ -4893,8 +4648,6 @@ public class datadog/trace/core/CoreTracer : datadog/trace/bootstrap/instrumenta public fun newHistogram (DI)Ldatadog/trace/bootstrap/instrumentation/api/AgentHistogram; public fun newScopeState ()Ldatadog/trace/bootstrap/instrumentation/api/ScopeState; public fun noopSpan ()Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan; - public fun notifyExtensionEnd (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Z)V - public fun notifyExtensionStart (Ljava/lang/Object;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; public fun onRootSpanFinished (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ldatadog/trace/api/EndpointTracker;)V public fun onRootSpanStarted (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;)Ldatadog/trace/api/EndpointTracker; public fun propagate ()Ldatadog/trace/bootstrap/instrumentation/api/AgentPropagation; @@ -5344,12 +5097,6 @@ public class datadog/trace/core/datastreams/DefaultPathwayContext : datadog/trac public fun toString ()Ljava/lang/String; } -public class datadog/trace/core/datastreams/MsgPackDatastreamsPayloadWriter : datadog/trace/core/datastreams/DatastreamsPayloadWriter { - public fun (Ldatadog/trace/common/metrics/Sink;Ldatadog/trace/api/WellKnownTags;Ljava/lang/String;Ljava/lang/String;)V - public fun reset ()V - public fun writePayload (Ljava/util/Collection;)V -} - public class datadog/trace/core/datastreams/NoOpDataStreamMonitoring : datadog/trace/core/datastreams/DataStreamsMonitoring { public fun ()V public fun add (Ldatadog/trace/bootstrap/instrumentation/api/StatsPoint;)V @@ -5812,14 +5559,6 @@ public class datadog/trace/ddagent/DroppingPolicy$DisabledDroppingPolicy : datad public fun active ()Z } -public class datadog/trace/lambda/LambdaHandler { - public fun ()V - public static fun notifyEndInvocation (Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan;Ljava/lang/Object;Z)Z - public static fun notifyStartInvocation (Ljava/lang/Object;Ldatadog/trace/core/propagation/PropagationTags$Factory;)Ldatadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; - public static fun setExtensionBaseUrl (Ljava/lang/String;)V - public static fun writeValueAsString (Ljava/lang/Object;)Ljava/lang/String; -} - public final class datadog/trace/lambda/ReadFromInputStreamJsonAdapter : com/squareup/moshi/JsonAdapter { public fun ()V public fun fromJson (Lcom/squareup/moshi/JsonReader;)Ljava/io/ByteArrayInputStream; @@ -5828,13 +5567,6 @@ public final class datadog/trace/lambda/ReadFromInputStreamJsonAdapter : com/squ public synthetic fun toJson (Lcom/squareup/moshi/JsonWriter;Ljava/lang/Object;)V } -public final class datadog/trace/lambda/SkipUnsupportedTypeJsonAdapter : com/squareup/moshi/JsonAdapter { - public fun ()V - public fun fromJson (Lcom/squareup/moshi/JsonReader;)Ljava/lang/Object; - public static fun newFactory ()Lcom/squareup/moshi/JsonAdapter$Factory; - public fun toJson (Lcom/squareup/moshi/JsonWriter;Ljava/lang/Object;)V -} - public class datadog/trace/logging/GlobalLogLevelSwitcher : datadog/trace/logging/LogLevelSwitcher { public static fun get ()Ldatadog/trace/logging/LogLevelSwitcher; public fun reinitialize ()V @@ -5936,12 +5668,6 @@ public abstract interface class datadog/trace/serialization/ByteBufferConsumer { public abstract fun accept (ILjava/nio/ByteBuffer;)V } -public final class datadog/trace/serialization/Codec : java/lang/ClassValue { - public static final field INSTANCE Ldatadog/trace/serialization/Codec; - public fun ()V - public fun (Ljava/util/Map;)V -} - public abstract interface class datadog/trace/serialization/EncodingCache { public abstract fun encode (Ljava/lang/CharSequence;)[B } @@ -6045,63 +5771,6 @@ public abstract interface class datadog/trace/serialization/Writable { public abstract interface class datadog/trace/serialization/WritableFormatter : datadog/trace/serialization/MessageFormatter, datadog/trace/serialization/Writable { } -public class datadog/trace/serialization/msgpack/MsgPackWriter : datadog/trace/serialization/WritableFormatter { - public static final field ARRAY16 B - public static final field ARRAY32 B - public static final field BIN16 B - public static final field BIN32 B - public static final field BIN8 B - public static final field FALSE B - public static final field FIXARRAY I - public static final field FIXMAP I - public static final field FIXSTR I - public static final field FLOAT32 B - public static final field FLOAT64 B - public static final field INT16 B - public static final field INT32 B - public static final field INT64 B - public static final field INT8 B - public static final field MAP16 B - public static final field MAP32 B - public static final field NEGFIXNUM I - public static final field NULL B - public static final field STR16 B - public static final field STR32 B - public static final field STR8 B - public static final field TRUE B - public static final field UINT16 B - public static final field UINT32 B - public static final field UINT64 B - public static final field UINT8 B - public fun (Ldatadog/trace/serialization/Codec;Ldatadog/trace/serialization/StreamingBuffer;)V - public fun (Ldatadog/trace/serialization/StreamingBuffer;)V - public fun flush ()V - public fun format (Ljava/lang/Object;Ldatadog/trace/serialization/Mapper;)Z - public fun startArray (I)V - public fun startMap (I)V - public fun startStruct (I)V - public fun writeBinary (Ljava/nio/ByteBuffer;)V - public fun writeBinary ([B)V - public fun writeBinary ([BII)V - public fun writeBoolean (Z)V - public fun writeDouble (D)V - public fun writeFloat (F)V - public fun writeInt (I)V - public fun writeLong (J)V - public fun writeLongInternal (JZ)V - public fun writeMap (Ljava/util/Map;Ldatadog/trace/serialization/EncodingCache;)V - public fun writeNull ()V - public fun writeObject (Ljava/lang/Object;Ldatadog/trace/serialization/EncodingCache;)V - public fun writeObjectString (Ljava/lang/Object;Ldatadog/trace/serialization/EncodingCache;)V - public fun writeSignedInt (I)V - public fun writeSignedLong (J)V - public fun writeString (Ljava/lang/CharSequence;Ldatadog/trace/serialization/EncodingCache;)V - public fun writeUTF8 (Ldatadog/trace/bootstrap/instrumentation/api/UTF8BytesString;)V - public fun writeUTF8 ([B)V - public fun writeUTF8 ([BII)V - public fun writeUnsignedLong (J)V -} - public final class datadog/trace/util/AgentProxySelector : java/net/ProxySelector { public static final field INSTANCE Ljava/net/ProxySelector; public fun ()V @@ -6190,30 +5859,6 @@ public final class datadog/trace/util/AgentThreadFactory$AgentThread : java/lang public static fun values ()[Ldatadog/trace/util/AgentThreadFactory$AgentThread; } -public final class datadog/trace/util/ClassNameTrie { - public fun apply (Ljava/lang/String;)I - public static fun apply ([C[ILjava/lang/String;)I - public static fun readFrom (Ljava/io/DataInput;)Ldatadog/trace/util/ClassNameTrie; -} - -public class datadog/trace/util/ClassNameTrie$Builder { - public static final field EMPTY_TRIE Ldatadog/trace/util/ClassNameTrie; - public fun ()V - public fun (Ldatadog/trace/util/ClassNameTrie;)V - public fun apply (Ljava/lang/String;)I - public fun buildTrie ()Ldatadog/trace/util/ClassNameTrie; - public fun isEmpty ()Z - public fun put (Ljava/lang/String;I)V - public fun readClassNameMapping (Ljava/nio/file/Path;)V - public fun writeTo (Ljava/io/DataOutput;)V -} - -public class datadog/trace/util/ClassNameTrie$JavaGenerator { - public fun ()V - public static fun generateJavaTrie (Ljava/util/List;Ljava/lang/String;Ldatadog/trace/util/ClassNameTrie$Builder;)Z - public static fun main ([Ljava/lang/String;)V -} - public final class datadog/trace/util/CollectionUtils { public fun ()V public static fun tryMakeImmutableList (Ljava/util/Collection;)Ljava/util/List; @@ -6235,17 +5880,9 @@ public final class datadog/trace/util/FNV64Hash$Version : java/lang/Enum { public static fun values ()[Ldatadog/trace/util/FNV64Hash$Version; } -public class datadog/trace/util/MethodHandles { - public fun (Ljava/lang/ClassLoader;)V - public fun constructor (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; - public fun constructor (Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; - public fun invoke (Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object; - public fun method (Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; - public fun method (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; - public fun privateFieldGetter (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/invoke/MethodHandle; - public fun privateFieldGetter (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/invoke/MethodHandle; - public fun privateFieldSetter (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/invoke/MethodHandle; - public fun privateFieldSetter (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/invoke/MethodHandle; +public class datadog/trace/util/FileUtils { + public fun ()V + public static fun readAllBytes (Ljava/lang/String;)[B } public final class datadog/trace/util/PidHelper { @@ -6254,27 +5891,6 @@ public final class datadog/trace/util/PidHelper { public static fun getPidAsLong ()J } -public class datadog/trace/util/ProcessSupervisor : java/io/Closeable { - public static final field ALWAYS_READY Ldatadog/trace/util/ProcessSupervisor$HealthCheck; - public fun (Ljava/lang/String;Ljava/lang/ProcessBuilder;)V - public fun (Ljava/lang/String;Ljava/lang/ProcessBuilder;Ldatadog/trace/util/ProcessSupervisor$HealthCheck;)V - public fun close ()V -} - -public final class datadog/trace/util/ProcessSupervisor$Health : java/lang/Enum { - public static final field FAULTED Ldatadog/trace/util/ProcessSupervisor$Health; - public static final field HEALTHY Ldatadog/trace/util/ProcessSupervisor$Health; - public static final field INTERRUPTED Ldatadog/trace/util/ProcessSupervisor$Health; - public static final field NEVER_CHECKED Ldatadog/trace/util/ProcessSupervisor$Health; - public static final field READY_TO_START Ldatadog/trace/util/ProcessSupervisor$Health; - public static fun valueOf (Ljava/lang/String;)Ldatadog/trace/util/ProcessSupervisor$Health; - public static fun values ()[Ldatadog/trace/util/ProcessSupervisor$Health; -} - -public abstract interface class datadog/trace/util/ProcessSupervisor$HealthCheck { - public abstract fun run (Ldatadog/trace/util/ProcessSupervisor$Health;)Ldatadog/trace/util/ProcessSupervisor$Health; -} - public abstract class datadog/trace/util/ProcessUtils { public static fun getCurrentJvmPath ()Ljava/lang/String; } diff --git a/features/dd-trace-core/build.gradle.kts b/features/dd-trace-core/build.gradle.kts index ffb720e938..a1cbcce03c 100644 --- a/features/dd-trace-core/build.gradle.kts +++ b/features/dd-trace-core/build.gradle.kts @@ -2,20 +2,23 @@ import com.datadog.gradle.config.androidLibraryConfig import com.datadog.gradle.config.dependencyUpdateConfig import com.datadog.gradle.config.javadocConfig import com.datadog.gradle.config.junitConfig +import com.datadog.gradle.config.kotlinConfig +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { // Build id("com.android.library") + kotlin("android") // Analysis tools id("com.github.ben-manes.versions") // Tests id("de.mobilej.unmock") + id("org.jetbrains.kotlinx.kover") // Internal Generation id("thirdPartyLicences") - id("apiSurface") id("transitiveDependencies") id("binary-compatibility-validator") } @@ -37,15 +40,17 @@ dependencies { implementation(libs.jctools) implementation(libs.kotlin) implementation(libs.okHttp) - implementation(libs.kotlin) implementation(libs.androidXAnnotation) implementation(libs.datadogSketchesJava) implementation(libs.re2j) compileOnly(libs.spotbugs) // TODO: RUM-3268 Port and enable the groovy unit tests -} + testImplementation(libs.bundles.jUnit5) + testImplementation(libs.bundles.testTools) +} +kotlinConfig(jvmBytecodeTarget = JvmTarget.JVM_11) androidLibraryConfig() junitConfig() javadocConfig() diff --git a/features/dd-trace-core/lint.xml b/features/dd-trace-core/lint.xml index 4fbde87523..9253c42b22 100644 --- a/features/dd-trace-core/lint.xml +++ b/features/dd-trace-core/lint.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Config.java b/features/dd-trace-core/src/main/java/datadog/trace/api/Config.java index 983f1b3182..834582c423 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/Config.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/Config.java @@ -318,6 +318,8 @@ import static datadog.trace.util.CollectionUtils.tryMakeImmutableSet; import static datadog.trace.util.Strings.propertyNameToEnvironmentVariableName; +import android.os.Build; + import androidx.annotation.NonNull; import org.slf4j.Logger; @@ -365,6 +367,7 @@ import datadog.trace.bootstrap.config.provider.CapturedEnvironmentConfigSource; import datadog.trace.bootstrap.config.provider.ConfigProvider; import datadog.trace.bootstrap.config.provider.SystemPropertiesConfigSource; +import datadog.trace.util.FileUtils; import datadog.trace.util.PidHelper; import datadog.trace.util.Strings; import datadog.trace.util.throwable.FatalAgentMisconfigurationError; @@ -389,3777 +392,3818 @@ */ public class Config { - private static final Logger log = LoggerFactory.getLogger(Config.class); - - private static final Pattern COLON = Pattern.compile(":"); - - private final InstrumenterConfig instrumenterConfig; - - private final long startTimeMillis = System.currentTimeMillis(); - private final boolean timelineEventsEnabled; - - /** - * this is a random UUID that gets generated on JVM start up and is attached to every root span - * and every JMX metric that is sent out. - */ - static class RuntimeIdHolder { - static final String runtimeId = UUID.randomUUID().toString(); - } - - static class HostNameHolder { - static final String hostName = initHostName(); - } - - private final boolean runtimeIdEnabled; - - /** This is the version of the runtime, ex: 1.8.0_332, 11.0.15, 17.0.3 */ - private final String runtimeVersion; - - private final String applicationKey; - /** - * Note: this has effect only on profiling site. Traces are sent to Datadog agent and are not - * affected by this setting. If CI Visibility is used with agentless mode, api key is used when - * sending data (including traces) to backend - */ - private final String apiKey; - /** - * Note: this has effect only on profiling site. Traces are sent to Datadog agent and are not - * affected by this setting. - */ - private final String site; - - private final String serviceName; - private final boolean serviceNameSetByUser; - private final String rootContextServiceName; - private final boolean integrationSynapseLegacyOperationName; - private final String writerType; - private final boolean injectBaggageAsTagsEnabled; - private final boolean agentConfiguredUsingDefault; - private final String agentUrl; - private final String agentHost; - private final int agentPort; - private final String agentUnixDomainSocket; - private final String agentNamedPipe; - private final int agentTimeout; - private final Set noProxyHosts; - private final boolean prioritySamplingEnabled; - private final String prioritySamplingForce; - private final boolean traceResolverEnabled; - private final int spanAttributeSchemaVersion; - private final boolean peerServiceDefaultsEnabled; - private final Map peerServiceComponentOverrides; - private final boolean removeIntegrationServiceNamesEnabled; - private final Map peerServiceMapping; - private final Map serviceMapping; - private final Map tags; - private final Map spanTags; - private final Map jmxTags; - private final Map requestHeaderTags; - private final Map responseHeaderTags; - private final Map baggageMapping; - private final boolean requestHeaderTagsCommaAllowed; - private final BitSet httpServerErrorStatuses; - private final BitSet httpClientErrorStatuses; - private final boolean httpServerTagQueryString; - private final boolean httpServerRawQueryString; - private final boolean httpServerRawResource; - private final boolean httpServerDecodedResourcePreserveSpaces; - private final boolean httpServerRouteBasedNaming; - private final Map httpServerPathResourceNameMapping; - private final Map httpClientPathResourceNameMapping; - private final boolean httpResourceRemoveTrailingSlash; - private final boolean httpClientTagQueryString; - private final boolean httpClientTagHeaders; - private final boolean httpClientSplitByDomain; - private final boolean dbClientSplitByInstance; - private final boolean dbClientSplitByInstanceTypeSuffix; - private final boolean dbClientSplitByHost; - private final Set splitByTags; - private final int scopeDepthLimit; - private final boolean scopeStrictMode; - private final boolean scopeInheritAsyncPropagation; - private final int scopeIterationKeepAlive; - private final int partialFlushMinSpans; - private final boolean traceStrictWritesEnabled; - private final boolean logExtractHeaderNames; - private final Set propagationStylesToExtract; - private final Set propagationStylesToInject; - private final boolean tracePropagationStyleB3PaddingEnabled; - private final Set tracePropagationStylesToExtract; - private final Set tracePropagationStylesToInject; - private final boolean tracePropagationExtractFirst; - private final int clockSyncPeriod; - private final boolean logsInjectionEnabled; - - private final String dogStatsDNamedPipe; - private final int dogStatsDStartDelay; - - private final Integer statsDClientQueueSize; - private final Integer statsDClientSocketBuffer; - private final Integer statsDClientSocketTimeout; - - private final boolean runtimeMetricsEnabled; - private final boolean jmxFetchEnabled; - private final String jmxFetchConfigDir; - private final List jmxFetchConfigs; - @Deprecated private final List jmxFetchMetricsConfigs; - private final Integer jmxFetchCheckPeriod; - private final Integer jmxFetchInitialRefreshBeansPeriod; - private final Integer jmxFetchRefreshBeansPeriod; - private final String jmxFetchStatsdHost; - private final Integer jmxFetchStatsdPort; - private final boolean jmxFetchMultipleRuntimeServicesEnabled; - private final int jmxFetchMultipleRuntimeServicesLimit; - - // These values are default-ed to those of jmx fetch values as needed - private final boolean healthMetricsEnabled; - private final String healthMetricsStatsdHost; - private final Integer healthMetricsStatsdPort; - private final boolean perfMetricsEnabled; - - private final boolean tracerMetricsEnabled; - private final boolean tracerMetricsBufferingEnabled; - private final int tracerMetricsMaxAggregates; - private final int tracerMetricsMaxPending; - - private final boolean reportHostName; - - private final boolean traceAnalyticsEnabled; - private final String traceClientIpHeader; - private final boolean traceClientIpResolverEnabled; - - private final boolean traceGitMetadataEnabled; - - private final Map traceSamplingServiceRules; - private final Map traceSamplingOperationRules; - private final String traceSamplingRules; - private final Double traceSampleRate; - private final int traceRateLimit; - private final String spanSamplingRules; - private final String spanSamplingRulesFile; - - private final boolean profilingEnabled; - private final boolean profilingAgentless; - private final boolean isDatadogProfilerEnabled; - @Deprecated private final String profilingUrl; - private final Map profilingTags; - private final int profilingStartDelay; - private final boolean profilingStartForceFirst; - private final int profilingUploadPeriod; - private final String profilingTemplateOverrideFile; - private final int profilingUploadTimeout; - private final String profilingUploadCompression; - private final String profilingProxyHost; - private final int profilingProxyPort; - private final String profilingProxyUsername; - private final String profilingProxyPassword; - private final int profilingExceptionSampleLimit; - private final int profilingDirectAllocationSampleLimit; - private final int profilingExceptionHistogramTopItems; - private final int profilingExceptionHistogramMaxCollectionSize; - private final boolean profilingExcludeAgentThreads; - private final boolean profilingUploadSummaryOn413Enabled; - private final boolean profilingRecordExceptionMessage; - - private final boolean crashTrackingAgentless; - private final Map crashTrackingTags; - - private final boolean clientIpEnabled; - - private final boolean appSecReportingInband; - private final String appSecRulesFile; - private final int appSecReportMinTimeout; - private final int appSecReportMaxTimeout; - private final int appSecTraceRateLimit; - private final boolean appSecWafMetrics; - private final int appSecWafTimeout; - private final String appSecObfuscationParameterKeyRegexp; - private final String appSecObfuscationParameterValueRegexp; - private final String appSecHttpBlockedTemplateHtml; - private final String appSecHttpBlockedTemplateJson; - private final UserEventTrackingMode appSecUserEventsTracking; - private final boolean apiSecurityEnabled; - private final float apiSecurityRequestSampleRate; - - private final IastDetectionMode iastDetectionMode; - private final int iastMaxConcurrentRequests; - private final int iastVulnerabilitiesPerRequest; - private final float iastRequestSampling; - private final boolean iastDebugEnabled; - private final Verbosity iastTelemetryVerbosity; - private final boolean iastRedactionEnabled; - private final String iastRedactionNamePattern; - private final String iastRedactionValuePattern; - private final int iastMaxRangeCount; - private final int iastTruncationMaxValueLength; - private final boolean iastStacktraceLeakSuppress; - - private final boolean ciVisibilityTraceSanitationEnabled; - private final boolean ciVisibilityAgentlessEnabled; - private final String ciVisibilityAgentlessUrl; - - private final boolean ciVisibilitySourceDataEnabled; - private final boolean ciVisibilitySourceDataRootCheckEnabled; - private final boolean ciVisibilityBuildInstrumentationEnabled; - private final Long ciVisibilitySessionId; - private final Long ciVisibilityModuleId; - private final String ciVisibilityAgentJarUri; - private final boolean ciVisibilityAutoConfigurationEnabled; - private final String ciVisibilityAdditionalChildProcessJvmArgs; - private final boolean ciVisibilityCompilerPluginAutoConfigurationEnabled; - private final boolean ciVisibilityCodeCoverageEnabled; - private final boolean ciVisibilityCodeCoveragePercentageCalculationEnabled; - private final String ciVisibilityCodeCoverageReportDumpDir; - private final String ciVisibilityCompilerPluginVersion; - private final String ciVisibilityJacocoPluginVersion; - private final boolean ciVisibilityJacocoPluginVersionProvided; - private final List ciVisibilityCodeCoverageIncludes; - private final List ciVisibilityCodeCoverageExcludes; - private final String[] ciVisibilityCodeCoverageIncludedPackages; - private final String[] ciVisibilityCodeCoverageExcludedPackages; - private final List ciVisibilityJacocoGradleSourceSets; - private final Integer ciVisibilityDebugPort; - private final boolean ciVisibilityGitUploadEnabled; - private final boolean ciVisibilityGitUnshallowEnabled; - private final boolean ciVisibilityGitUnshallowDefer; - private final long ciVisibilityGitCommandTimeoutMillis; - private final String ciVisibilityGitRemoteName; - private final long ciVisibilityBackendApiTimeoutMillis; - private final long ciVisibilityGitUploadTimeoutMillis; - private final String ciVisibilitySignalServerHost; - private final int ciVisibilitySignalServerPort; - private final boolean ciVisibilityItrEnabled; - private final boolean ciVisibilityCiProviderIntegrationEnabled; - private final boolean ciVisibilityRepoIndexSharingEnabled; - private final int ciVisibilityModuleExecutionSettingsCacheSize; - private final int ciVisibilityJvmInfoCacheSize; - private final boolean ciVisibilityCoverageSegmentsEnabled; - private final int ciVisibilityCoverageRootPackagesLimit; - private final String ciVisibilityInjectedTracerVersion; - private final List ciVisibilityResourceFolderNames; - private final boolean ciVisibilityFlakyRetryEnabled; - private final int ciVisibilityFlakyRetryCount; - private final String ciVisibilityModuleName; - - private final boolean remoteConfigEnabled; - private final boolean remoteConfigIntegrityCheckEnabled; - private final String remoteConfigUrl; - private final float remoteConfigPollIntervalSeconds; - private final long remoteConfigMaxPayloadSize; - private final String remoteConfigTargetsKeyId; - private final String remoteConfigTargetsKey; - - private final String DBMPropagationMode; - - private final boolean debuggerEnabled; - private final int debuggerUploadTimeout; - private final int debuggerUploadFlushInterval; - private final boolean debuggerClassFileDumpEnabled; - private final int debuggerPollInterval; - private final int debuggerDiagnosticsInterval; - private final boolean debuggerMetricEnabled; - private final String debuggerProbeFileLocation; - private final int debuggerUploadBatchSize; - private final long debuggerMaxPayloadSize; - private final boolean debuggerVerifyByteCode; - private final boolean debuggerInstrumentTheWorld; - private final String debuggerExcludeFiles; - private final int debuggerCaptureTimeout; - private final String debuggerRedactedIdentifiers; - private final String debuggerRedactedTypes; - private final boolean debuggerSymbolEnabled; - private final boolean debuggerSymbolForceUpload; - private final String debuggerSymbolIncludes; - private final int debuggerSymbolFlushThreshold; - - private final boolean awsPropagationEnabled; - private final boolean sqsPropagationEnabled; - - private final boolean kafkaClientPropagationEnabled; - private final Set kafkaClientPropagationDisabledTopics; - private final boolean kafkaClientBase64DecodingEnabled; - - private final boolean jmsPropagationEnabled; - private final Set jmsPropagationDisabledTopics; - private final Set jmsPropagationDisabledQueues; - private final int jmsUnacknowledgedMaxAge; - - private final boolean rabbitPropagationEnabled; - private final Set rabbitPropagationDisabledQueues; - private final Set rabbitPropagationDisabledExchanges; - - private final boolean rabbitIncludeRoutingKeyInResource; - - private final boolean messageBrokerSplitByDestination; - - private final boolean hystrixTagsEnabled; - private final boolean hystrixMeasuredEnabled; - - private final boolean igniteCacheIncludeKeys; - - private final String obfuscationQueryRegexp; - - // TODO: remove at a future point. - private final boolean playReportHttpStatus; - - private final boolean servletPrincipalEnabled; - private final boolean servletAsyncTimeoutError; - - private final boolean springDataRepositoryInterfaceResourceName; - - private final int xDatadogTagsMaxLength; - - private final boolean traceAgentV05Enabled; - - private final boolean debugEnabled; - private final boolean triageEnabled; - private final boolean startupLogsEnabled; - private final String configFileStatus; - - private final IdGenerationStrategy idGenerationStrategy; - - private final boolean secureRandom; - - private final boolean trace128bitTraceIdGenerationEnabled; - - private final Set grpcIgnoredInboundMethods; - private final Set grpcIgnoredOutboundMethods; - private final boolean grpcServerTrimPackageResource; - private final BitSet grpcServerErrorStatuses; - private final BitSet grpcClientErrorStatuses; - - private final boolean cwsEnabled; - private final int cwsTlsRefresh; - - private final boolean dataStreamsEnabled; - private final float dataStreamsBucketDurationSeconds; - - private final Set iastWeakHashAlgorithms; - - private final Pattern iastWeakCipherAlgorithms; - - private final boolean iastDeduplicationEnabled; - - private final float telemetryHeartbeatInterval; - private final long telemetryExtendedHeartbeatInterval; - private final float telemetryMetricsInterval; - private final boolean isTelemetryDependencyServiceEnabled; - private final boolean telemetryMetricsEnabled; - private final boolean isTelemetryLogCollectionEnabled; - - private final boolean azureAppServices; - private final String traceAgentPath; - private final List traceAgentArgs; - private final String dogStatsDPath; - private final List dogStatsDArgs; - - private String env; - private String version; - private final String primaryTag; - - private final ConfigProvider configProvider; - - private final boolean longRunningTraceEnabled; - private final long longRunningTraceFlushInterval; - private final boolean elasticsearchBodyEnabled; - private final boolean elasticsearchParamsEnabled; - private final boolean elasticsearchBodyAndParamsEnabled; - private final boolean sparkTaskHistogramEnabled; - private final boolean jaxRsExceptionAsErrorsEnabled; - - private final float traceFlushIntervalSeconds; - - private final boolean telemetryDebugRequestsEnabled; - - // Read order: System Properties -> Env Variables, [-> properties file], [-> default value] - private Config() { - this(ConfigProvider.createDefault()); - } - - private Config(final ConfigProvider configProvider) { - this(configProvider, new InstrumenterConfig(configProvider)); - } - - private Config(final ConfigProvider configProvider, final InstrumenterConfig instrumenterConfig) { - this.configProvider = configProvider; - this.instrumenterConfig = instrumenterConfig; - configFileStatus = configProvider.getConfigFileStatus(); - runtimeIdEnabled = configProvider.getBoolean(RUNTIME_ID_ENABLED, true); - runtimeVersion = System.getProperty("java.version", "unknown"); - - // Note: We do not want APiKey to be loaded from property for security reasons - // Note: we do not use defined default here - // FIXME: We should use better authentication mechanism - final String apiKeyFile = configProvider.getString(API_KEY_FILE); - String tmpApiKey = - configProvider.getStringExcludingSource(API_KEY, null, SystemPropertiesConfigSource.class); - if (apiKeyFile != null) { - try { - tmpApiKey = - new String(Files.readAllBytes(Paths.get(apiKeyFile)), StandardCharsets.UTF_8).trim(); - } catch (final IOException e) { - log.error( - "Cannot read API key from file {}, skipping. Exception {}", apiKeyFile, e.getMessage()); - } - } - site = configProvider.getString(SITE, DEFAULT_SITE); - - String tmpApplicationKey = - configProvider.getStringExcludingSource( - APPLICATION_KEY, null, SystemPropertiesConfigSource.class); - String applicationKeyFile = configProvider.getString(APPLICATION_KEY_FILE); - if (applicationKeyFile != null) { - try { - tmpApplicationKey = - new String(Files.readAllBytes(Paths.get(applicationKeyFile)), StandardCharsets.UTF_8) - .trim(); - } catch (final IOException e) { - log.error("Cannot read API key from file {}, skipping", applicationKeyFile, e); - } - } - applicationKey = tmpApplicationKey; - - String userProvidedServiceName = - configProvider.getStringExcludingSource( - SERVICE, null, CapturedEnvironmentConfigSource.class, SERVICE_NAME); - - if (userProvidedServiceName == null) { - serviceNameSetByUser = false; - serviceName = configProvider.getString(SERVICE, DEFAULT_SERVICE_NAME, SERVICE_NAME); - } else { - serviceNameSetByUser = true; - serviceName = userProvidedServiceName; - } - - rootContextServiceName = - configProvider.getString( - SERVLET_ROOT_CONTEXT_SERVICE_NAME, DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME); - - integrationSynapseLegacyOperationName = - configProvider.getBoolean(INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME, false); - writerType = configProvider.getString(WRITER_TYPE, DEFAULT_AGENT_WRITER_TYPE); - injectBaggageAsTagsEnabled = - configProvider.getBoolean(WRITER_BAGGAGE_INJECT, DEFAULT_WRITER_BAGGAGE_INJECT); - String lambdaInitType = getEnv("AWS_LAMBDA_INITIALIZATION_TYPE"); - if (lambdaInitType != null && lambdaInitType.equals("snap-start")) { - secureRandom = true; - } else { - secureRandom = configProvider.getBoolean(SECURE_RANDOM, DEFAULT_SECURE_RANDOM); - } - elasticsearchBodyEnabled = - configProvider.getBoolean(ELASTICSEARCH_BODY_ENABLED, DEFAULT_ELASTICSEARCH_BODY_ENABLED); - elasticsearchParamsEnabled = - configProvider.getBoolean( - ELASTICSEARCH_PARAMS_ENABLED, DEFAULT_ELASTICSEARCH_PARAMS_ENABLED); - elasticsearchBodyAndParamsEnabled = - configProvider.getBoolean( - ELASTICSEARCH_BODY_AND_PARAMS_ENABLED, DEFAULT_ELASTICSEARCH_BODY_AND_PARAMS_ENABLED); - String strategyName = configProvider.getString(ID_GENERATION_STRATEGY); - trace128bitTraceIdGenerationEnabled = - configProvider.getBoolean( - TRACE_128_BIT_TRACEID_GENERATION_ENABLED, - DEFAULT_TRACE_128_BIT_TRACEID_GENERATION_ENABLED); - if (secureRandom) { - strategyName = "SECURE_RANDOM"; - } - if (strategyName == null) { - strategyName = "RANDOM"; - } - IdGenerationStrategy strategy = - IdGenerationStrategy.fromName(strategyName, trace128bitTraceIdGenerationEnabled); - if (strategy == null) { - log.warn( - "*** you are trying to use an unknown id generation strategy {} - falling back to RANDOM", - strategyName); - strategyName = "RANDOM"; - strategy = IdGenerationStrategy.fromName(strategyName, trace128bitTraceIdGenerationEnabled); - } - if (!strategyName.equals("RANDOM") && !strategyName.equals("SECURE_RANDOM")) { - log.warn( - "*** you are using an unsupported id generation strategy {} - this can impact correctness of traces", - strategyName); - } - idGenerationStrategy = strategy; - - String agentHostFromEnvironment = null; - int agentPortFromEnvironment = -1; - String unixSocketFromEnvironment = null; - boolean rebuildAgentUrl = false; - - final String agentUrlFromEnvironment = configProvider.getString(TRACE_AGENT_URL); - if (agentUrlFromEnvironment != null) { - try { - final URI parsedAgentUrl = new URI(agentUrlFromEnvironment); - agentHostFromEnvironment = parsedAgentUrl.getHost(); - agentPortFromEnvironment = parsedAgentUrl.getPort(); - if ("unix".equals(parsedAgentUrl.getScheme())) { - unixSocketFromEnvironment = parsedAgentUrl.getPath(); - } - } catch (URISyntaxException e) { - log.warn("{} not configured correctly: {}. Ignoring", TRACE_AGENT_URL, e.getMessage()); - } - } + private static final Logger log = LoggerFactory.getLogger(Config.class); - if (agentHostFromEnvironment == null) { - agentHostFromEnvironment = configProvider.getString(AGENT_HOST); - rebuildAgentUrl = true; - } + private static final Pattern COLON = Pattern.compile(":"); - if (agentPortFromEnvironment < 0) { - agentPortFromEnvironment = configProvider.getInteger(TRACE_AGENT_PORT, -1, AGENT_PORT_LEGACY); - rebuildAgentUrl = true; - } + private final InstrumenterConfig instrumenterConfig; + + private final long startTimeMillis = System.currentTimeMillis(); + private final boolean timelineEventsEnabled; - if (agentHostFromEnvironment == null) { - agentHost = DEFAULT_AGENT_HOST; - } else { - agentHost = agentHostFromEnvironment; + /** + * this is a random UUID that gets generated on JVM start up and is attached to every root span + * and every JMX metric that is sent out. + */ + static class RuntimeIdHolder { + static final String runtimeId = UUID.randomUUID().toString(); } - if (agentPortFromEnvironment < 0) { - agentPort = DEFAULT_TRACE_AGENT_PORT; - } else { - agentPort = agentPortFromEnvironment; + static class HostNameHolder { + static final String hostName = initHostName(); } - if (rebuildAgentUrl) { - agentUrl = "http://" + agentHost + ":" + agentPort; - } else { - agentUrl = agentUrlFromEnvironment; + private final boolean runtimeIdEnabled; + + /** + * This is the version of the runtime, ex: 1.8.0_332, 11.0.15, 17.0.3 + */ + private final String runtimeVersion; + + private final String applicationKey; + /** + * Note: this has effect only on profiling site. Traces are sent to Datadog agent and are not + * affected by this setting. If CI Visibility is used with agentless mode, api key is used when + * sending data (including traces) to backend + */ + private final String apiKey; + /** + * Note: this has effect only on profiling site. Traces are sent to Datadog agent and are not + * affected by this setting. + */ + private final String site; + + private final String serviceName; + private final boolean serviceNameSetByUser; + private final String rootContextServiceName; + private final boolean integrationSynapseLegacyOperationName; + private final String writerType; + private final boolean injectBaggageAsTagsEnabled; + private final boolean agentConfiguredUsingDefault; + private final String agentUrl; + private final String agentHost; + private final int agentPort; + private final String agentUnixDomainSocket; + private final String agentNamedPipe; + private final int agentTimeout; + private final Set noProxyHosts; + private final boolean prioritySamplingEnabled; + private final String prioritySamplingForce; + private final boolean traceResolverEnabled; + private final int spanAttributeSchemaVersion; + private final boolean peerServiceDefaultsEnabled; + private final Map peerServiceComponentOverrides; + private final boolean removeIntegrationServiceNamesEnabled; + private final Map peerServiceMapping; + private final Map serviceMapping; + private final Map tags; + private final Map spanTags; + private final Map jmxTags; + private final Map requestHeaderTags; + private final Map responseHeaderTags; + private final Map baggageMapping; + private final boolean requestHeaderTagsCommaAllowed; + private final BitSet httpServerErrorStatuses; + private final BitSet httpClientErrorStatuses; + private final boolean httpServerTagQueryString; + private final boolean httpServerRawQueryString; + private final boolean httpServerRawResource; + private final boolean httpServerDecodedResourcePreserveSpaces; + private final boolean httpServerRouteBasedNaming; + private final Map httpServerPathResourceNameMapping; + private final Map httpClientPathResourceNameMapping; + private final boolean httpResourceRemoveTrailingSlash; + private final boolean httpClientTagQueryString; + private final boolean httpClientTagHeaders; + private final boolean httpClientSplitByDomain; + private final boolean dbClientSplitByInstance; + private final boolean dbClientSplitByInstanceTypeSuffix; + private final boolean dbClientSplitByHost; + private final Set splitByTags; + private final int scopeDepthLimit; + private final boolean scopeStrictMode; + private final boolean scopeInheritAsyncPropagation; + private final int scopeIterationKeepAlive; + private final int partialFlushMinSpans; + private final boolean traceStrictWritesEnabled; + private final boolean logExtractHeaderNames; + private final Set propagationStylesToExtract; + private final Set propagationStylesToInject; + private final boolean tracePropagationStyleB3PaddingEnabled; + private final Set tracePropagationStylesToExtract; + private final Set tracePropagationStylesToInject; + private final boolean tracePropagationExtractFirst; + private final int clockSyncPeriod; + private final boolean logsInjectionEnabled; + + private final String dogStatsDNamedPipe; + private final int dogStatsDStartDelay; + + private final Integer statsDClientQueueSize; + private final Integer statsDClientSocketBuffer; + private final Integer statsDClientSocketTimeout; + + private final boolean runtimeMetricsEnabled; + private final boolean jmxFetchEnabled; + private final String jmxFetchConfigDir; + private final List jmxFetchConfigs; + @Deprecated + private final List jmxFetchMetricsConfigs; + private final Integer jmxFetchCheckPeriod; + private final Integer jmxFetchInitialRefreshBeansPeriod; + private final Integer jmxFetchRefreshBeansPeriod; + private final String jmxFetchStatsdHost; + private final Integer jmxFetchStatsdPort; + private final boolean jmxFetchMultipleRuntimeServicesEnabled; + private final int jmxFetchMultipleRuntimeServicesLimit; + + // These values are default-ed to those of jmx fetch values as needed + private final boolean healthMetricsEnabled; + private final String healthMetricsStatsdHost; + private final Integer healthMetricsStatsdPort; + private final boolean perfMetricsEnabled; + + private final boolean tracerMetricsEnabled; + private final boolean tracerMetricsBufferingEnabled; + private final int tracerMetricsMaxAggregates; + private final int tracerMetricsMaxPending; + + private final boolean reportHostName; + + private final boolean traceAnalyticsEnabled; + private final String traceClientIpHeader; + private final boolean traceClientIpResolverEnabled; + + private final boolean traceGitMetadataEnabled; + + private final Map traceSamplingServiceRules; + private final Map traceSamplingOperationRules; + private final String traceSamplingRules; + private final Double traceSampleRate; + private final int traceRateLimit; + private final String spanSamplingRules; + private final String spanSamplingRulesFile; + + private final boolean profilingEnabled; + private final boolean profilingAgentless; + private final boolean isDatadogProfilerEnabled; + @Deprecated + private final String profilingUrl; + private final Map profilingTags; + private final int profilingStartDelay; + private final boolean profilingStartForceFirst; + private final int profilingUploadPeriod; + private final String profilingTemplateOverrideFile; + private final int profilingUploadTimeout; + private final String profilingUploadCompression; + private final String profilingProxyHost; + private final int profilingProxyPort; + private final String profilingProxyUsername; + private final String profilingProxyPassword; + private final int profilingExceptionSampleLimit; + private final int profilingDirectAllocationSampleLimit; + private final int profilingExceptionHistogramTopItems; + private final int profilingExceptionHistogramMaxCollectionSize; + private final boolean profilingExcludeAgentThreads; + private final boolean profilingUploadSummaryOn413Enabled; + private final boolean profilingRecordExceptionMessage; + + private final boolean crashTrackingAgentless; + private final Map crashTrackingTags; + + private final boolean clientIpEnabled; + + private final boolean appSecReportingInband; + private final String appSecRulesFile; + private final int appSecReportMinTimeout; + private final int appSecReportMaxTimeout; + private final int appSecTraceRateLimit; + private final boolean appSecWafMetrics; + private final int appSecWafTimeout; + private final String appSecObfuscationParameterKeyRegexp; + private final String appSecObfuscationParameterValueRegexp; + private final String appSecHttpBlockedTemplateHtml; + private final String appSecHttpBlockedTemplateJson; + private final UserEventTrackingMode appSecUserEventsTracking; + private final boolean apiSecurityEnabled; + private final float apiSecurityRequestSampleRate; + + private final IastDetectionMode iastDetectionMode; + private final int iastMaxConcurrentRequests; + private final int iastVulnerabilitiesPerRequest; + private final float iastRequestSampling; + private final boolean iastDebugEnabled; + private final Verbosity iastTelemetryVerbosity; + private final boolean iastRedactionEnabled; + private final String iastRedactionNamePattern; + private final String iastRedactionValuePattern; + private final int iastMaxRangeCount; + private final int iastTruncationMaxValueLength; + private final boolean iastStacktraceLeakSuppress; + + private final boolean ciVisibilityTraceSanitationEnabled; + private final boolean ciVisibilityAgentlessEnabled; + private final String ciVisibilityAgentlessUrl; + + private final boolean ciVisibilitySourceDataEnabled; + private final boolean ciVisibilitySourceDataRootCheckEnabled; + private final boolean ciVisibilityBuildInstrumentationEnabled; + private final Long ciVisibilitySessionId; + private final Long ciVisibilityModuleId; + private final String ciVisibilityAgentJarUri; + private final boolean ciVisibilityAutoConfigurationEnabled; + private final String ciVisibilityAdditionalChildProcessJvmArgs; + private final boolean ciVisibilityCompilerPluginAutoConfigurationEnabled; + private final boolean ciVisibilityCodeCoverageEnabled; + private final boolean ciVisibilityCodeCoveragePercentageCalculationEnabled; + private final String ciVisibilityCodeCoverageReportDumpDir; + private final String ciVisibilityCompilerPluginVersion; + private final String ciVisibilityJacocoPluginVersion; + private final boolean ciVisibilityJacocoPluginVersionProvided; + private final List ciVisibilityCodeCoverageIncludes; + private final List ciVisibilityCodeCoverageExcludes; + private final String[] ciVisibilityCodeCoverageIncludedPackages; + private final String[] ciVisibilityCodeCoverageExcludedPackages; + private final List ciVisibilityJacocoGradleSourceSets; + private final Integer ciVisibilityDebugPort; + private final boolean ciVisibilityGitUploadEnabled; + private final boolean ciVisibilityGitUnshallowEnabled; + private final boolean ciVisibilityGitUnshallowDefer; + private final long ciVisibilityGitCommandTimeoutMillis; + private final String ciVisibilityGitRemoteName; + private final long ciVisibilityBackendApiTimeoutMillis; + private final long ciVisibilityGitUploadTimeoutMillis; + private final String ciVisibilitySignalServerHost; + private final int ciVisibilitySignalServerPort; + private final boolean ciVisibilityItrEnabled; + private final boolean ciVisibilityCiProviderIntegrationEnabled; + private final boolean ciVisibilityRepoIndexSharingEnabled; + private final int ciVisibilityModuleExecutionSettingsCacheSize; + private final int ciVisibilityJvmInfoCacheSize; + private final boolean ciVisibilityCoverageSegmentsEnabled; + private final int ciVisibilityCoverageRootPackagesLimit; + private final String ciVisibilityInjectedTracerVersion; + private final List ciVisibilityResourceFolderNames; + private final boolean ciVisibilityFlakyRetryEnabled; + private final int ciVisibilityFlakyRetryCount; + private final String ciVisibilityModuleName; + + private final boolean remoteConfigEnabled; + private final boolean remoteConfigIntegrityCheckEnabled; + private final String remoteConfigUrl; + private final float remoteConfigPollIntervalSeconds; + private final long remoteConfigMaxPayloadSize; + private final String remoteConfigTargetsKeyId; + private final String remoteConfigTargetsKey; + + private final String DBMPropagationMode; + + private final boolean debuggerEnabled; + private final int debuggerUploadTimeout; + private final int debuggerUploadFlushInterval; + private final boolean debuggerClassFileDumpEnabled; + private final int debuggerPollInterval; + private final int debuggerDiagnosticsInterval; + private final boolean debuggerMetricEnabled; + private final String debuggerProbeFileLocation; + private final int debuggerUploadBatchSize; + private final long debuggerMaxPayloadSize; + private final boolean debuggerVerifyByteCode; + private final boolean debuggerInstrumentTheWorld; + private final String debuggerExcludeFiles; + private final int debuggerCaptureTimeout; + private final String debuggerRedactedIdentifiers; + private final String debuggerRedactedTypes; + private final boolean debuggerSymbolEnabled; + private final boolean debuggerSymbolForceUpload; + private final String debuggerSymbolIncludes; + private final int debuggerSymbolFlushThreshold; + + private final boolean awsPropagationEnabled; + private final boolean sqsPropagationEnabled; + + private final boolean kafkaClientPropagationEnabled; + private final Set kafkaClientPropagationDisabledTopics; + private final boolean kafkaClientBase64DecodingEnabled; + + private final boolean jmsPropagationEnabled; + private final Set jmsPropagationDisabledTopics; + private final Set jmsPropagationDisabledQueues; + private final int jmsUnacknowledgedMaxAge; + + private final boolean rabbitPropagationEnabled; + private final Set rabbitPropagationDisabledQueues; + private final Set rabbitPropagationDisabledExchanges; + + private final boolean rabbitIncludeRoutingKeyInResource; + + private final boolean messageBrokerSplitByDestination; + + private final boolean hystrixTagsEnabled; + private final boolean hystrixMeasuredEnabled; + + private final boolean igniteCacheIncludeKeys; + + private final String obfuscationQueryRegexp; + + // TODO: remove at a future point. + private final boolean playReportHttpStatus; + + private final boolean servletPrincipalEnabled; + private final boolean servletAsyncTimeoutError; + + private final boolean springDataRepositoryInterfaceResourceName; + + private final int xDatadogTagsMaxLength; + + private final boolean traceAgentV05Enabled; + + private final boolean debugEnabled; + private final boolean triageEnabled; + private final boolean startupLogsEnabled; + private final String configFileStatus; + + private final IdGenerationStrategy idGenerationStrategy; + + private final boolean secureRandom; + + private final boolean trace128bitTraceIdGenerationEnabled; + + private final Set grpcIgnoredInboundMethods; + private final Set grpcIgnoredOutboundMethods; + private final boolean grpcServerTrimPackageResource; + private final BitSet grpcServerErrorStatuses; + private final BitSet grpcClientErrorStatuses; + + private final boolean cwsEnabled; + private final int cwsTlsRefresh; + + private final boolean dataStreamsEnabled; + private final float dataStreamsBucketDurationSeconds; + + private final Set iastWeakHashAlgorithms; + + private final Pattern iastWeakCipherAlgorithms; + + private final boolean iastDeduplicationEnabled; + + private final float telemetryHeartbeatInterval; + private final long telemetryExtendedHeartbeatInterval; + private final float telemetryMetricsInterval; + private final boolean isTelemetryDependencyServiceEnabled; + private final boolean telemetryMetricsEnabled; + private final boolean isTelemetryLogCollectionEnabled; + + private final boolean azureAppServices; + private final String traceAgentPath; + private final List traceAgentArgs; + private final String dogStatsDPath; + private final List dogStatsDArgs; + + private String env; + private String version; + private final String primaryTag; + + private final ConfigProvider configProvider; + + private final boolean longRunningTraceEnabled; + private final long longRunningTraceFlushInterval; + private final boolean elasticsearchBodyEnabled; + private final boolean elasticsearchParamsEnabled; + private final boolean elasticsearchBodyAndParamsEnabled; + private final boolean sparkTaskHistogramEnabled; + private final boolean jaxRsExceptionAsErrorsEnabled; + + private final float traceFlushIntervalSeconds; + + private final boolean telemetryDebugRequestsEnabled; + + // Read order: System Properties -> Env Variables, [-> properties file], [-> default value] + private Config() { + this(ConfigProvider.createDefault()); } - if (unixSocketFromEnvironment == null) { - unixSocketFromEnvironment = configProvider.getString(AGENT_UNIX_DOMAIN_SOCKET); - String unixPrefix = "unix://"; - // handle situation where someone passes us a unix:// URL instead of a socket path - if (unixSocketFromEnvironment != null && unixSocketFromEnvironment.startsWith(unixPrefix)) { - unixSocketFromEnvironment = unixSocketFromEnvironment.substring(unixPrefix.length()); - } + private Config(final ConfigProvider configProvider) { + this(configProvider, new InstrumenterConfig(configProvider)); } - agentUnixDomainSocket = unixSocketFromEnvironment; + private Config(final ConfigProvider configProvider, final InstrumenterConfig instrumenterConfig) { + this.configProvider = configProvider; + this.instrumenterConfig = instrumenterConfig; + configFileStatus = configProvider.getConfigFileStatus(); + runtimeIdEnabled = configProvider.getBoolean(RUNTIME_ID_ENABLED, true); + runtimeVersion = System.getProperty("java.version", "unknown"); + + // Note: We do not want APiKey to be loaded from property for security reasons + // Note: we do not use defined default here + // FIXME: We should use better authentication mechanism + final String apiKeyFile = configProvider.getString(API_KEY_FILE); + String tmpApiKey = + configProvider.getStringExcludingSource(API_KEY, null, SystemPropertiesConfigSource.class); + if (apiKeyFile != null) { + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + tmpApiKey = + new String(Files.readAllBytes(Paths.get(apiKeyFile)), StandardCharsets.UTF_8).trim(); + } else { + tmpApiKey = new String(FileUtils.readAllBytes(apiKeyFile), StandardCharsets.UTF_8).trim(); + } + } catch (final IOException e) { + log.error( + "Cannot read API key from file {}, skipping. Exception {}", apiKeyFile, e.getMessage()); + } + } + site = configProvider.getString(SITE, DEFAULT_SITE); + + String tmpApplicationKey = + configProvider.getStringExcludingSource( + APPLICATION_KEY, null, SystemPropertiesConfigSource.class); + String applicationKeyFile = configProvider.getString(APPLICATION_KEY_FILE); + if (applicationKeyFile != null) { + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + tmpApplicationKey = + new String(Files.readAllBytes(Paths.get(applicationKeyFile)), StandardCharsets.UTF_8) + .trim(); + } else { + tmpApplicationKey = new String(FileUtils.readAllBytes(applicationKeyFile), StandardCharsets.UTF_8).trim(); + } + } catch (final IOException e) { + log.error("Cannot read API key from file {}, skipping", applicationKeyFile, e); + } + } + applicationKey = tmpApplicationKey; + + String userProvidedServiceName = + configProvider.getStringExcludingSource( + SERVICE, null, CapturedEnvironmentConfigSource.class, SERVICE_NAME); + + if (userProvidedServiceName == null) { + serviceNameSetByUser = false; + serviceName = configProvider.getString(SERVICE, DEFAULT_SERVICE_NAME, SERVICE_NAME); + } else { + serviceNameSetByUser = true; + serviceName = userProvidedServiceName; + } + + rootContextServiceName = + configProvider.getString( + SERVLET_ROOT_CONTEXT_SERVICE_NAME, DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME); + + integrationSynapseLegacyOperationName = + configProvider.getBoolean(INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME, false); + writerType = configProvider.getString(WRITER_TYPE, DEFAULT_AGENT_WRITER_TYPE); + injectBaggageAsTagsEnabled = + configProvider.getBoolean(WRITER_BAGGAGE_INJECT, DEFAULT_WRITER_BAGGAGE_INJECT); + String lambdaInitType = getEnv("AWS_LAMBDA_INITIALIZATION_TYPE"); + if (lambdaInitType != null && lambdaInitType.equals("snap-start")) { + secureRandom = true; + } else { + secureRandom = configProvider.getBoolean(SECURE_RANDOM, DEFAULT_SECURE_RANDOM); + } + elasticsearchBodyEnabled = + configProvider.getBoolean(ELASTICSEARCH_BODY_ENABLED, DEFAULT_ELASTICSEARCH_BODY_ENABLED); + elasticsearchParamsEnabled = + configProvider.getBoolean( + ELASTICSEARCH_PARAMS_ENABLED, DEFAULT_ELASTICSEARCH_PARAMS_ENABLED); + elasticsearchBodyAndParamsEnabled = + configProvider.getBoolean( + ELASTICSEARCH_BODY_AND_PARAMS_ENABLED, DEFAULT_ELASTICSEARCH_BODY_AND_PARAMS_ENABLED); + String strategyName = configProvider.getString(ID_GENERATION_STRATEGY); + trace128bitTraceIdGenerationEnabled = + configProvider.getBoolean( + TRACE_128_BIT_TRACEID_GENERATION_ENABLED, + DEFAULT_TRACE_128_BIT_TRACEID_GENERATION_ENABLED); + if (secureRandom) { + strategyName = "SECURE_RANDOM"; + } + if (strategyName == null) { + strategyName = "RANDOM"; + } + IdGenerationStrategy strategy = + IdGenerationStrategy.fromName(strategyName, trace128bitTraceIdGenerationEnabled); + if (strategy == null) { + log.warn( + "*** you are trying to use an unknown id generation strategy {} - falling back to RANDOM", + strategyName); + strategyName = "RANDOM"; + strategy = IdGenerationStrategy.fromName(strategyName, trace128bitTraceIdGenerationEnabled); + } + if (!strategyName.equals("RANDOM") && !strategyName.equals("SECURE_RANDOM")) { + log.warn( + "*** you are using an unsupported id generation strategy {} - this can impact correctness of traces", + strategyName); + } + idGenerationStrategy = strategy; + + String agentHostFromEnvironment = null; + int agentPortFromEnvironment = -1; + String unixSocketFromEnvironment = null; + boolean rebuildAgentUrl = false; + + final String agentUrlFromEnvironment = configProvider.getString(TRACE_AGENT_URL); + if (agentUrlFromEnvironment != null) { + try { + final URI parsedAgentUrl = new URI(agentUrlFromEnvironment); + agentHostFromEnvironment = parsedAgentUrl.getHost(); + agentPortFromEnvironment = parsedAgentUrl.getPort(); + if ("unix".equals(parsedAgentUrl.getScheme())) { + unixSocketFromEnvironment = parsedAgentUrl.getPath(); + } + } catch (URISyntaxException e) { + log.warn("{} not configured correctly: {}. Ignoring", TRACE_AGENT_URL, e.getMessage()); + } + } + + if (agentHostFromEnvironment == null) { + agentHostFromEnvironment = configProvider.getString(AGENT_HOST); + rebuildAgentUrl = true; + } + + if (agentPortFromEnvironment < 0) { + agentPortFromEnvironment = configProvider.getInteger(TRACE_AGENT_PORT, -1, AGENT_PORT_LEGACY); + rebuildAgentUrl = true; + } + + if (agentHostFromEnvironment == null) { + agentHost = DEFAULT_AGENT_HOST; + } else { + agentHost = agentHostFromEnvironment; + } + + if (agentPortFromEnvironment < 0) { + agentPort = DEFAULT_TRACE_AGENT_PORT; + } else { + agentPort = agentPortFromEnvironment; + } - agentNamedPipe = configProvider.getString(AGENT_NAMED_PIPE); + if (rebuildAgentUrl) { + agentUrl = "http://" + agentHost + ":" + agentPort; + } else { + agentUrl = agentUrlFromEnvironment; + } - agentConfiguredUsingDefault = - agentHostFromEnvironment == null - && agentPortFromEnvironment < 0 - && unixSocketFromEnvironment == null - && agentNamedPipe == null; + if (unixSocketFromEnvironment == null) { + unixSocketFromEnvironment = configProvider.getString(AGENT_UNIX_DOMAIN_SOCKET); + String unixPrefix = "unix://"; + // handle situation where someone passes us a unix:// URL instead of a socket path + if (unixSocketFromEnvironment != null && unixSocketFromEnvironment.startsWith(unixPrefix)) { + unixSocketFromEnvironment = unixSocketFromEnvironment.substring(unixPrefix.length()); + } + } - agentTimeout = configProvider.getInteger(AGENT_TIMEOUT, DEFAULT_AGENT_TIMEOUT); + agentUnixDomainSocket = unixSocketFromEnvironment; - // DD_PROXY_NO_PROXY is specified as a space-separated list of hosts - noProxyHosts = tryMakeImmutableSet(configProvider.getSpacedList(PROXY_NO_PROXY)); + agentNamedPipe = configProvider.getString(AGENT_NAMED_PIPE); - prioritySamplingEnabled = - configProvider.getBoolean(PRIORITY_SAMPLING, DEFAULT_PRIORITY_SAMPLING_ENABLED); - prioritySamplingForce = - configProvider.getString(PRIORITY_SAMPLING_FORCE, DEFAULT_PRIORITY_SAMPLING_FORCE); + agentConfiguredUsingDefault = + agentHostFromEnvironment == null + && agentPortFromEnvironment < 0 + && unixSocketFromEnvironment == null + && agentNamedPipe == null; - traceResolverEnabled = - configProvider.getBoolean(TRACE_RESOLVER_ENABLED, DEFAULT_TRACE_RESOLVER_ENABLED); - serviceMapping = configProvider.getMergedMap(SERVICE_MAPPING); + agentTimeout = configProvider.getInteger(AGENT_TIMEOUT, DEFAULT_AGENT_TIMEOUT); - { - final Map tags = new HashMap<>(configProvider.getMergedMap(GLOBAL_TAGS)); - tags.putAll(configProvider.getMergedMap(TAGS)); - this.tags = getMapWithPropertiesDefinedByEnvironment(tags, ENV, VERSION); - } + // DD_PROXY_NO_PROXY is specified as a space-separated list of hosts + noProxyHosts = tryMakeImmutableSet(configProvider.getSpacedList(PROXY_NO_PROXY)); - spanTags = configProvider.getMergedMap(SPAN_TAGS); - jmxTags = configProvider.getMergedMap(JMX_TAGS); + prioritySamplingEnabled = + configProvider.getBoolean(PRIORITY_SAMPLING, DEFAULT_PRIORITY_SAMPLING_ENABLED); + prioritySamplingForce = + configProvider.getString(PRIORITY_SAMPLING_FORCE, DEFAULT_PRIORITY_SAMPLING_FORCE); - primaryTag = configProvider.getString(PRIMARY_TAG); + traceResolverEnabled = + configProvider.getBoolean(TRACE_RESOLVER_ENABLED, DEFAULT_TRACE_RESOLVER_ENABLED); + serviceMapping = configProvider.getMergedMap(SERVICE_MAPPING); - if (isEnabled(false, HEADER_TAGS, ".legacy.parsing.enabled")) { - requestHeaderTags = configProvider.getMergedMap(HEADER_TAGS); - responseHeaderTags = Collections.emptyMap(); - if (configProvider.isSet(REQUEST_HEADER_TAGS)) { - logIgnoredSettingWarning(REQUEST_HEADER_TAGS, HEADER_TAGS, ".legacy.parsing.enabled"); - } - if (configProvider.isSet(RESPONSE_HEADER_TAGS)) { - logIgnoredSettingWarning(RESPONSE_HEADER_TAGS, HEADER_TAGS, ".legacy.parsing.enabled"); - } - } else { - requestHeaderTags = - configProvider.getMergedMapWithOptionalMappings( - "http.request.headers.", true, HEADER_TAGS, REQUEST_HEADER_TAGS); - responseHeaderTags = - configProvider.getMergedMapWithOptionalMappings( - "http.response.headers.", true, HEADER_TAGS, RESPONSE_HEADER_TAGS); - } - requestHeaderTagsCommaAllowed = - configProvider.getBoolean(REQUEST_HEADER_TAGS_COMMA_ALLOWED, true); + { + final Map tags = new HashMap<>(configProvider.getMergedMap(GLOBAL_TAGS)); + tags.putAll(configProvider.getMergedMap(TAGS)); + this.tags = getMapWithPropertiesDefinedByEnvironment(tags, ENV, VERSION); + } + + spanTags = configProvider.getMergedMap(SPAN_TAGS); + jmxTags = configProvider.getMergedMap(JMX_TAGS); + + primaryTag = configProvider.getString(PRIMARY_TAG); + + if (isEnabled(false, HEADER_TAGS, ".legacy.parsing.enabled")) { + requestHeaderTags = configProvider.getMergedMap(HEADER_TAGS); + responseHeaderTags = Collections.emptyMap(); + if (configProvider.isSet(REQUEST_HEADER_TAGS)) { + logIgnoredSettingWarning(REQUEST_HEADER_TAGS, HEADER_TAGS, ".legacy.parsing.enabled"); + } + if (configProvider.isSet(RESPONSE_HEADER_TAGS)) { + logIgnoredSettingWarning(RESPONSE_HEADER_TAGS, HEADER_TAGS, ".legacy.parsing.enabled"); + } + } else { + requestHeaderTags = + configProvider.getMergedMapWithOptionalMappings( + "http.request.headers.", true, HEADER_TAGS, REQUEST_HEADER_TAGS); + responseHeaderTags = + configProvider.getMergedMapWithOptionalMappings( + "http.response.headers.", true, HEADER_TAGS, RESPONSE_HEADER_TAGS); + } + requestHeaderTagsCommaAllowed = + configProvider.getBoolean(REQUEST_HEADER_TAGS_COMMA_ALLOWED, true); + + baggageMapping = configProvider.getMergedMap(BAGGAGE_MAPPING); + + spanAttributeSchemaVersion = schemaVersionFromConfig(); + + // following two only used in v0. + // in v1+ defaults are always calculated regardless this feature flag + peerServiceDefaultsEnabled = + configProvider.getBoolean(TRACE_PEER_SERVICE_DEFAULTS_ENABLED, false); + peerServiceComponentOverrides = + configProvider.getMergedMap(TRACE_PEER_SERVICE_COMPONENT_OVERRIDES); + // feature flag to remove fake services in v0 + removeIntegrationServiceNamesEnabled = + configProvider.getBoolean(TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED, false); + + peerServiceMapping = configProvider.getMergedMap(TRACE_PEER_SERVICE_MAPPING); + + httpServerPathResourceNameMapping = + configProvider.getOrderedMap(TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING); + + httpClientPathResourceNameMapping = + configProvider.getOrderedMap(TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING); + + httpResourceRemoveTrailingSlash = + configProvider.getBoolean( + TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH, + DEFAULT_TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH); + + httpServerErrorStatuses = + configProvider.getIntegerRange( + HTTP_SERVER_ERROR_STATUSES, DEFAULT_HTTP_SERVER_ERROR_STATUSES); + + httpClientErrorStatuses = + configProvider.getIntegerRange( + HTTP_CLIENT_ERROR_STATUSES, DEFAULT_HTTP_CLIENT_ERROR_STATUSES); + + httpServerTagQueryString = + configProvider.getBoolean( + HTTP_SERVER_TAG_QUERY_STRING, DEFAULT_HTTP_SERVER_TAG_QUERY_STRING); + + httpServerRawQueryString = configProvider.getBoolean(HTTP_SERVER_RAW_QUERY_STRING, true); + + httpServerRawResource = configProvider.getBoolean(HTTP_SERVER_RAW_RESOURCE, false); + + httpServerDecodedResourcePreserveSpaces = + configProvider.getBoolean(HTTP_SERVER_DECODED_RESOURCE_PRESERVE_SPACES, true); + + httpServerRouteBasedNaming = + configProvider.getBoolean( + HTTP_SERVER_ROUTE_BASED_NAMING, DEFAULT_HTTP_SERVER_ROUTE_BASED_NAMING); + + httpClientTagQueryString = + configProvider.getBoolean( + HTTP_CLIENT_TAG_QUERY_STRING, DEFAULT_HTTP_CLIENT_TAG_QUERY_STRING); + + httpClientTagHeaders = configProvider.getBoolean(HTTP_CLIENT_TAG_HEADERS, true); + + httpClientSplitByDomain = + configProvider.getBoolean( + HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, DEFAULT_HTTP_CLIENT_SPLIT_BY_DOMAIN); + + dbClientSplitByInstance = + configProvider.getBoolean( + DB_CLIENT_HOST_SPLIT_BY_INSTANCE, DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE); + + dbClientSplitByInstanceTypeSuffix = + configProvider.getBoolean( + DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX, + DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX); + + dbClientSplitByHost = + configProvider.getBoolean( + DB_CLIENT_HOST_SPLIT_BY_HOST, DEFAULT_DB_CLIENT_HOST_SPLIT_BY_HOST); + + DBMPropagationMode = + configProvider.getString( + DB_DBM_PROPAGATION_MODE_MODE, DEFAULT_DB_DBM_PROPAGATION_MODE_MODE); + + splitByTags = tryMakeImmutableSet(configProvider.getList(SPLIT_BY_TAGS)); + + springDataRepositoryInterfaceResourceName = + configProvider.getBoolean(SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME, true); + + scopeDepthLimit = configProvider.getInteger(SCOPE_DEPTH_LIMIT, DEFAULT_SCOPE_DEPTH_LIMIT); + + scopeStrictMode = configProvider.getBoolean(SCOPE_STRICT_MODE, false); + + scopeInheritAsyncPropagation = configProvider.getBoolean(SCOPE_INHERIT_ASYNC_PROPAGATION, true); + + scopeIterationKeepAlive = + configProvider.getInteger(SCOPE_ITERATION_KEEP_ALIVE, DEFAULT_SCOPE_ITERATION_KEEP_ALIVE); + + boolean partialFlushEnabled = configProvider.getBoolean(PARTIAL_FLUSH_ENABLED, true); + partialFlushMinSpans = + !partialFlushEnabled + ? 0 + : configProvider.getInteger(PARTIAL_FLUSH_MIN_SPANS, DEFAULT_PARTIAL_FLUSH_MIN_SPANS); + + traceStrictWritesEnabled = configProvider.getBoolean(TRACE_STRICT_WRITES_ENABLED, false); + + logExtractHeaderNames = + configProvider.getBoolean( + PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED, + DEFAULT_PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED); + + tracePropagationStyleB3PaddingEnabled = + isEnabled(true, TRACE_PROPAGATION_STYLE, ".b3.padding.enabled"); + { + // The dd.propagation.style.(extract|inject) settings have been deprecated in + // favor of dd.trace.propagation.style(|.extract|.inject) settings. + // The different propagation settings when set will be applied in the following order of + // precedence, and warnings will be logged for both deprecation and overrides. + // * dd.trace.propagation.style.(extract|inject) + // * dd.trace.propagation.style + // * dd.propagation.style.(extract|inject) + Set deprecatedExtract = + getSettingsSetFromEnvironment( + PROPAGATION_STYLE_EXTRACT, PropagationStyle::valueOfConfigName, true); + Set deprecatedInject = + getSettingsSetFromEnvironment( + PROPAGATION_STYLE_INJECT, PropagationStyle::valueOfConfigName, true); + Set common = + getSettingsSetFromEnvironment( + TRACE_PROPAGATION_STYLE, TracePropagationStyle::valueOfDisplayName, false); + Set extract = + getSettingsSetFromEnvironment( + TRACE_PROPAGATION_STYLE_EXTRACT, TracePropagationStyle::valueOfDisplayName, false); + Set inject = + getSettingsSetFromEnvironment( + TRACE_PROPAGATION_STYLE_INJECT, TracePropagationStyle::valueOfDisplayName, false); + String extractOrigin = TRACE_PROPAGATION_STYLE_EXTRACT; + String injectOrigin = TRACE_PROPAGATION_STYLE_INJECT; + // Check if we should use the common setting for extraction + if (extract.isEmpty()) { + extract = common; + extractOrigin = TRACE_PROPAGATION_STYLE; + } else if (!common.isEmpty()) { + // The more specific settings will override the common setting, so log a warning + logOverriddenSettingWarning( + TRACE_PROPAGATION_STYLE, TRACE_PROPAGATION_STYLE_EXTRACT, extract); + } + // Check if we should use the common setting for injection + if (inject.isEmpty()) { + inject = common; + injectOrigin = TRACE_PROPAGATION_STYLE; + } else if (!common.isEmpty()) { + // The more specific settings will override the common setting, so log a warning + logOverriddenSettingWarning( + TRACE_PROPAGATION_STYLE, TRACE_PROPAGATION_STYLE_INJECT, inject); + } + // Check if we should use the deprecated setting for extraction + if (extract.isEmpty()) { + // If we don't have a new setting, we convert the deprecated one + extract = convertSettingsSet(deprecatedExtract, PropagationStyle::getNewStyles); + if (!extract.isEmpty()) { + logDeprecatedConvertedSetting( + PROPAGATION_STYLE_EXTRACT, + deprecatedExtract, + TRACE_PROPAGATION_STYLE_EXTRACT, + extract); + } + } else if (!deprecatedExtract.isEmpty()) { + // If we have a new setting, we log a warning + logOverriddenDeprecatedSettingWarning(PROPAGATION_STYLE_EXTRACT, extractOrigin, extract); + } + // Check if we should use the deprecated setting for injection + if (inject.isEmpty()) { + // If we don't have a new setting, we convert the deprecated one + inject = convertSettingsSet(deprecatedInject, PropagationStyle::getNewStyles); + if (!inject.isEmpty()) { + logDeprecatedConvertedSetting( + PROPAGATION_STYLE_INJECT, deprecatedInject, TRACE_PROPAGATION_STYLE_INJECT, inject); + } + } else if (!deprecatedInject.isEmpty()) { + // If we have a new setting, we log a warning + logOverriddenDeprecatedSettingWarning(PROPAGATION_STYLE_INJECT, injectOrigin, inject); + } + // Now we can check if we should pick the default injection/extraction + tracePropagationStylesToExtract = + extract.isEmpty() ? DEFAULT_TRACE_PROPAGATION_STYLE : extract; + tracePropagationStylesToInject = inject.isEmpty() ? DEFAULT_TRACE_PROPAGATION_STYLE : inject; + // These setting are here for backwards compatibility until they can be removed in a major + // release of the tracer + propagationStylesToExtract = + deprecatedExtract.isEmpty() ? DEFAULT_PROPAGATION_STYLE : deprecatedExtract; + propagationStylesToInject = + deprecatedInject.isEmpty() ? DEFAULT_PROPAGATION_STYLE : deprecatedInject; + } + + tracePropagationExtractFirst = + configProvider.getBoolean( + TRACE_PROPAGATION_EXTRACT_FIRST, DEFAULT_TRACE_PROPAGATION_EXTRACT_FIRST); + + clockSyncPeriod = configProvider.getInteger(CLOCK_SYNC_PERIOD, DEFAULT_CLOCK_SYNC_PERIOD); - baggageMapping = configProvider.getMergedMap(BAGGAGE_MAPPING); + logsInjectionEnabled = + configProvider.getBoolean(LOGS_INJECTION_ENABLED, DEFAULT_LOGS_INJECTION_ENABLED); - spanAttributeSchemaVersion = schemaVersionFromConfig(); + dogStatsDNamedPipe = configProvider.getString(DOGSTATSD_NAMED_PIPE); - // following two only used in v0. - // in v1+ defaults are always calculated regardless this feature flag - peerServiceDefaultsEnabled = - configProvider.getBoolean(TRACE_PEER_SERVICE_DEFAULTS_ENABLED, false); - peerServiceComponentOverrides = - configProvider.getMergedMap(TRACE_PEER_SERVICE_COMPONENT_OVERRIDES); - // feature flag to remove fake services in v0 - removeIntegrationServiceNamesEnabled = - configProvider.getBoolean(TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED, false); + dogStatsDStartDelay = + configProvider.getInteger( + DOGSTATSD_START_DELAY, DEFAULT_DOGSTATSD_START_DELAY, JMX_FETCH_START_DELAY); - peerServiceMapping = configProvider.getMergedMap(TRACE_PEER_SERVICE_MAPPING); + statsDClientQueueSize = configProvider.getInteger(STATSD_CLIENT_QUEUE_SIZE); + statsDClientSocketBuffer = configProvider.getInteger(STATSD_CLIENT_SOCKET_BUFFER); + statsDClientSocketTimeout = configProvider.getInteger(STATSD_CLIENT_SOCKET_TIMEOUT); - httpServerPathResourceNameMapping = - configProvider.getOrderedMap(TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING); + runtimeMetricsEnabled = configProvider.getBoolean(RUNTIME_METRICS_ENABLED, true); - httpClientPathResourceNameMapping = - configProvider.getOrderedMap(TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING); + jmxFetchEnabled = + runtimeMetricsEnabled + && configProvider.getBoolean(JMX_FETCH_ENABLED, DEFAULT_JMX_FETCH_ENABLED); + jmxFetchConfigDir = configProvider.getString(JMX_FETCH_CONFIG_DIR); + jmxFetchConfigs = tryMakeImmutableList(configProvider.getList(JMX_FETCH_CONFIG)); + jmxFetchMetricsConfigs = + tryMakeImmutableList(configProvider.getList(JMX_FETCH_METRICS_CONFIGS)); + jmxFetchCheckPeriod = configProvider.getInteger(JMX_FETCH_CHECK_PERIOD); + jmxFetchInitialRefreshBeansPeriod = + configProvider.getInteger(JMX_FETCH_INITIAL_REFRESH_BEANS_PERIOD); + jmxFetchRefreshBeansPeriod = configProvider.getInteger(JMX_FETCH_REFRESH_BEANS_PERIOD); - httpResourceRemoveTrailingSlash = - configProvider.getBoolean( - TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH, - DEFAULT_TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH); - - httpServerErrorStatuses = - configProvider.getIntegerRange( - HTTP_SERVER_ERROR_STATUSES, DEFAULT_HTTP_SERVER_ERROR_STATUSES); - - httpClientErrorStatuses = - configProvider.getIntegerRange( - HTTP_CLIENT_ERROR_STATUSES, DEFAULT_HTTP_CLIENT_ERROR_STATUSES); - - httpServerTagQueryString = - configProvider.getBoolean( - HTTP_SERVER_TAG_QUERY_STRING, DEFAULT_HTTP_SERVER_TAG_QUERY_STRING); - - httpServerRawQueryString = configProvider.getBoolean(HTTP_SERVER_RAW_QUERY_STRING, true); - - httpServerRawResource = configProvider.getBoolean(HTTP_SERVER_RAW_RESOURCE, false); - - httpServerDecodedResourcePreserveSpaces = - configProvider.getBoolean(HTTP_SERVER_DECODED_RESOURCE_PRESERVE_SPACES, true); - - httpServerRouteBasedNaming = - configProvider.getBoolean( - HTTP_SERVER_ROUTE_BASED_NAMING, DEFAULT_HTTP_SERVER_ROUTE_BASED_NAMING); - - httpClientTagQueryString = - configProvider.getBoolean( - HTTP_CLIENT_TAG_QUERY_STRING, DEFAULT_HTTP_CLIENT_TAG_QUERY_STRING); - - httpClientTagHeaders = configProvider.getBoolean(HTTP_CLIENT_TAG_HEADERS, true); - - httpClientSplitByDomain = - configProvider.getBoolean( - HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, DEFAULT_HTTP_CLIENT_SPLIT_BY_DOMAIN); - - dbClientSplitByInstance = - configProvider.getBoolean( - DB_CLIENT_HOST_SPLIT_BY_INSTANCE, DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE); - - dbClientSplitByInstanceTypeSuffix = - configProvider.getBoolean( - DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX, - DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX); - - dbClientSplitByHost = - configProvider.getBoolean( - DB_CLIENT_HOST_SPLIT_BY_HOST, DEFAULT_DB_CLIENT_HOST_SPLIT_BY_HOST); - - DBMPropagationMode = - configProvider.getString( - DB_DBM_PROPAGATION_MODE_MODE, DEFAULT_DB_DBM_PROPAGATION_MODE_MODE); - - splitByTags = tryMakeImmutableSet(configProvider.getList(SPLIT_BY_TAGS)); - - springDataRepositoryInterfaceResourceName = - configProvider.getBoolean(SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME, true); - - scopeDepthLimit = configProvider.getInteger(SCOPE_DEPTH_LIMIT, DEFAULT_SCOPE_DEPTH_LIMIT); - - scopeStrictMode = configProvider.getBoolean(SCOPE_STRICT_MODE, false); - - scopeInheritAsyncPropagation = configProvider.getBoolean(SCOPE_INHERIT_ASYNC_PROPAGATION, true); - - scopeIterationKeepAlive = - configProvider.getInteger(SCOPE_ITERATION_KEEP_ALIVE, DEFAULT_SCOPE_ITERATION_KEEP_ALIVE); - - boolean partialFlushEnabled = configProvider.getBoolean(PARTIAL_FLUSH_ENABLED, true); - partialFlushMinSpans = - !partialFlushEnabled - ? 0 - : configProvider.getInteger(PARTIAL_FLUSH_MIN_SPANS, DEFAULT_PARTIAL_FLUSH_MIN_SPANS); - - traceStrictWritesEnabled = configProvider.getBoolean(TRACE_STRICT_WRITES_ENABLED, false); - - logExtractHeaderNames = - configProvider.getBoolean( - PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED, - DEFAULT_PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED); - - tracePropagationStyleB3PaddingEnabled = - isEnabled(true, TRACE_PROPAGATION_STYLE, ".b3.padding.enabled"); - { - // The dd.propagation.style.(extract|inject) settings have been deprecated in - // favor of dd.trace.propagation.style(|.extract|.inject) settings. - // The different propagation settings when set will be applied in the following order of - // precedence, and warnings will be logged for both deprecation and overrides. - // * dd.trace.propagation.style.(extract|inject) - // * dd.trace.propagation.style - // * dd.propagation.style.(extract|inject) - Set deprecatedExtract = - getSettingsSetFromEnvironment( - PROPAGATION_STYLE_EXTRACT, PropagationStyle::valueOfConfigName, true); - Set deprecatedInject = - getSettingsSetFromEnvironment( - PROPAGATION_STYLE_INJECT, PropagationStyle::valueOfConfigName, true); - Set common = - getSettingsSetFromEnvironment( - TRACE_PROPAGATION_STYLE, TracePropagationStyle::valueOfDisplayName, false); - Set extract = - getSettingsSetFromEnvironment( - TRACE_PROPAGATION_STYLE_EXTRACT, TracePropagationStyle::valueOfDisplayName, false); - Set inject = - getSettingsSetFromEnvironment( - TRACE_PROPAGATION_STYLE_INJECT, TracePropagationStyle::valueOfDisplayName, false); - String extractOrigin = TRACE_PROPAGATION_STYLE_EXTRACT; - String injectOrigin = TRACE_PROPAGATION_STYLE_INJECT; - // Check if we should use the common setting for extraction - if (extract.isEmpty()) { - extract = common; - extractOrigin = TRACE_PROPAGATION_STYLE; - } else if (!common.isEmpty()) { - // The more specific settings will override the common setting, so log a warning - logOverriddenSettingWarning( - TRACE_PROPAGATION_STYLE, TRACE_PROPAGATION_STYLE_EXTRACT, extract); - } - // Check if we should use the common setting for injection - if (inject.isEmpty()) { - inject = common; - injectOrigin = TRACE_PROPAGATION_STYLE; - } else if (!common.isEmpty()) { - // The more specific settings will override the common setting, so log a warning - logOverriddenSettingWarning( - TRACE_PROPAGATION_STYLE, TRACE_PROPAGATION_STYLE_INJECT, inject); - } - // Check if we should use the deprecated setting for extraction - if (extract.isEmpty()) { - // If we don't have a new setting, we convert the deprecated one - extract = convertSettingsSet(deprecatedExtract, PropagationStyle::getNewStyles); - if (!extract.isEmpty()) { - logDeprecatedConvertedSetting( - PROPAGATION_STYLE_EXTRACT, - deprecatedExtract, - TRACE_PROPAGATION_STYLE_EXTRACT, - extract); + jmxFetchStatsdPort = configProvider.getInteger(JMX_FETCH_STATSD_PORT, DOGSTATSD_PORT); + jmxFetchStatsdHost = + configProvider.getString( + JMX_FETCH_STATSD_HOST, + // default to agent host if an explicit port has been set + null != jmxFetchStatsdPort && jmxFetchStatsdPort > 0 ? agentHost : null, + DOGSTATSD_HOST); + + jmxFetchMultipleRuntimeServicesEnabled = + configProvider.getBoolean( + JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED, + DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED); + jmxFetchMultipleRuntimeServicesLimit = + configProvider.getInteger( + JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT, + DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT); + + // Writer.Builder createMonitor will use the values of the JMX fetch & agent to fill-in defaults + healthMetricsEnabled = + runtimeMetricsEnabled + && configProvider.getBoolean(HEALTH_METRICS_ENABLED, DEFAULT_HEALTH_METRICS_ENABLED); + healthMetricsStatsdHost = configProvider.getString(HEALTH_METRICS_STATSD_HOST); + healthMetricsStatsdPort = configProvider.getInteger(HEALTH_METRICS_STATSD_PORT); + perfMetricsEnabled = + runtimeMetricsEnabled + && configProvider.getBoolean(PERF_METRICS_ENABLED, DEFAULT_PERF_METRICS_ENABLED); + + tracerMetricsEnabled = configProvider.getBoolean(TRACER_METRICS_ENABLED, false); + tracerMetricsBufferingEnabled = + configProvider.getBoolean(TRACER_METRICS_BUFFERING_ENABLED, false); + tracerMetricsMaxAggregates = configProvider.getInteger(TRACER_METRICS_MAX_AGGREGATES, 2048); + tracerMetricsMaxPending = configProvider.getInteger(TRACER_METRICS_MAX_PENDING, 2048); + + reportHostName = + configProvider.getBoolean(TRACE_REPORT_HOSTNAME, DEFAULT_TRACE_REPORT_HOSTNAME); + + traceAgentV05Enabled = + configProvider.getBoolean(ENABLE_TRACE_AGENT_V05, DEFAULT_TRACE_AGENT_V05_ENABLED); + + traceAnalyticsEnabled = + configProvider.getBoolean(TRACE_ANALYTICS_ENABLED, DEFAULT_TRACE_ANALYTICS_ENABLED); + + String traceClientIpHeader = configProvider.getString(TRACE_CLIENT_IP_HEADER); + if (traceClientIpHeader == null) { + traceClientIpHeader = configProvider.getString(APPSEC_IP_ADDR_HEADER); } - } else if (!deprecatedExtract.isEmpty()) { - // If we have a new setting, we log a warning - logOverriddenDeprecatedSettingWarning(PROPAGATION_STYLE_EXTRACT, extractOrigin, extract); - } - // Check if we should use the deprecated setting for injection - if (inject.isEmpty()) { - // If we don't have a new setting, we convert the deprecated one - inject = convertSettingsSet(deprecatedInject, PropagationStyle::getNewStyles); - if (!inject.isEmpty()) { - logDeprecatedConvertedSetting( - PROPAGATION_STYLE_INJECT, deprecatedInject, TRACE_PROPAGATION_STYLE_INJECT, inject); + if (traceClientIpHeader != null) { + traceClientIpHeader = traceClientIpHeader.toLowerCase(Locale.ROOT); } - } else if (!deprecatedInject.isEmpty()) { - // If we have a new setting, we log a warning - logOverriddenDeprecatedSettingWarning(PROPAGATION_STYLE_INJECT, injectOrigin, inject); - } - // Now we can check if we should pick the default injection/extraction - tracePropagationStylesToExtract = - extract.isEmpty() ? DEFAULT_TRACE_PROPAGATION_STYLE : extract; - tracePropagationStylesToInject = inject.isEmpty() ? DEFAULT_TRACE_PROPAGATION_STYLE : inject; - // These setting are here for backwards compatibility until they can be removed in a major - // release of the tracer - propagationStylesToExtract = - deprecatedExtract.isEmpty() ? DEFAULT_PROPAGATION_STYLE : deprecatedExtract; - propagationStylesToInject = - deprecatedInject.isEmpty() ? DEFAULT_PROPAGATION_STYLE : deprecatedInject; - } - - tracePropagationExtractFirst = - configProvider.getBoolean( - TRACE_PROPAGATION_EXTRACT_FIRST, DEFAULT_TRACE_PROPAGATION_EXTRACT_FIRST); - - clockSyncPeriod = configProvider.getInteger(CLOCK_SYNC_PERIOD, DEFAULT_CLOCK_SYNC_PERIOD); - - logsInjectionEnabled = - configProvider.getBoolean(LOGS_INJECTION_ENABLED, DEFAULT_LOGS_INJECTION_ENABLED); - - dogStatsDNamedPipe = configProvider.getString(DOGSTATSD_NAMED_PIPE); - - dogStatsDStartDelay = - configProvider.getInteger( - DOGSTATSD_START_DELAY, DEFAULT_DOGSTATSD_START_DELAY, JMX_FETCH_START_DELAY); - - statsDClientQueueSize = configProvider.getInteger(STATSD_CLIENT_QUEUE_SIZE); - statsDClientSocketBuffer = configProvider.getInteger(STATSD_CLIENT_SOCKET_BUFFER); - statsDClientSocketTimeout = configProvider.getInteger(STATSD_CLIENT_SOCKET_TIMEOUT); - - runtimeMetricsEnabled = configProvider.getBoolean(RUNTIME_METRICS_ENABLED, true); - - jmxFetchEnabled = - runtimeMetricsEnabled - && configProvider.getBoolean(JMX_FETCH_ENABLED, DEFAULT_JMX_FETCH_ENABLED); - jmxFetchConfigDir = configProvider.getString(JMX_FETCH_CONFIG_DIR); - jmxFetchConfigs = tryMakeImmutableList(configProvider.getList(JMX_FETCH_CONFIG)); - jmxFetchMetricsConfigs = - tryMakeImmutableList(configProvider.getList(JMX_FETCH_METRICS_CONFIGS)); - jmxFetchCheckPeriod = configProvider.getInteger(JMX_FETCH_CHECK_PERIOD); - jmxFetchInitialRefreshBeansPeriod = - configProvider.getInteger(JMX_FETCH_INITIAL_REFRESH_BEANS_PERIOD); - jmxFetchRefreshBeansPeriod = configProvider.getInteger(JMX_FETCH_REFRESH_BEANS_PERIOD); - - jmxFetchStatsdPort = configProvider.getInteger(JMX_FETCH_STATSD_PORT, DOGSTATSD_PORT); - jmxFetchStatsdHost = - configProvider.getString( - JMX_FETCH_STATSD_HOST, - // default to agent host if an explicit port has been set - null != jmxFetchStatsdPort && jmxFetchStatsdPort > 0 ? agentHost : null, - DOGSTATSD_HOST); - - jmxFetchMultipleRuntimeServicesEnabled = - configProvider.getBoolean( - JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED, - DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED); - jmxFetchMultipleRuntimeServicesLimit = - configProvider.getInteger( - JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT, - DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT); - - // Writer.Builder createMonitor will use the values of the JMX fetch & agent to fill-in defaults - healthMetricsEnabled = - runtimeMetricsEnabled - && configProvider.getBoolean(HEALTH_METRICS_ENABLED, DEFAULT_HEALTH_METRICS_ENABLED); - healthMetricsStatsdHost = configProvider.getString(HEALTH_METRICS_STATSD_HOST); - healthMetricsStatsdPort = configProvider.getInteger(HEALTH_METRICS_STATSD_PORT); - perfMetricsEnabled = - runtimeMetricsEnabled - && configProvider.getBoolean(PERF_METRICS_ENABLED, DEFAULT_PERF_METRICS_ENABLED); - - tracerMetricsEnabled = configProvider.getBoolean(TRACER_METRICS_ENABLED, false); - tracerMetricsBufferingEnabled = - configProvider.getBoolean(TRACER_METRICS_BUFFERING_ENABLED, false); - tracerMetricsMaxAggregates = configProvider.getInteger(TRACER_METRICS_MAX_AGGREGATES, 2048); - tracerMetricsMaxPending = configProvider.getInteger(TRACER_METRICS_MAX_PENDING, 2048); - - reportHostName = - configProvider.getBoolean(TRACE_REPORT_HOSTNAME, DEFAULT_TRACE_REPORT_HOSTNAME); - - traceAgentV05Enabled = - configProvider.getBoolean(ENABLE_TRACE_AGENT_V05, DEFAULT_TRACE_AGENT_V05_ENABLED); - - traceAnalyticsEnabled = - configProvider.getBoolean(TRACE_ANALYTICS_ENABLED, DEFAULT_TRACE_ANALYTICS_ENABLED); - - String traceClientIpHeader = configProvider.getString(TRACE_CLIENT_IP_HEADER); - if (traceClientIpHeader == null) { - traceClientIpHeader = configProvider.getString(APPSEC_IP_ADDR_HEADER); - } - if (traceClientIpHeader != null) { - traceClientIpHeader = traceClientIpHeader.toLowerCase(Locale.ROOT); - } - this.traceClientIpHeader = traceClientIpHeader; - - traceClientIpResolverEnabled = - configProvider.getBoolean(TRACE_CLIENT_IP_RESOLVER_ENABLED, true); - - traceGitMetadataEnabled = configProvider.getBoolean(TRACE_GIT_METADATA_ENABLED, true); - - traceSamplingServiceRules = configProvider.getMergedMap(TRACE_SAMPLING_SERVICE_RULES); - traceSamplingOperationRules = configProvider.getMergedMap(TRACE_SAMPLING_OPERATION_RULES); - traceSamplingRules = configProvider.getString(TRACE_SAMPLING_RULES); - traceSampleRate = configProvider.getDouble(TRACE_SAMPLE_RATE); - traceRateLimit = configProvider.getInteger(TRACE_RATE_LIMIT, DEFAULT_TRACE_RATE_LIMIT); - spanSamplingRules = configProvider.getString(SPAN_SAMPLING_RULES); - spanSamplingRulesFile = configProvider.getString(SPAN_SAMPLING_RULES_FILE); - - // For the native image 'instrumenterConfig.isProfilingEnabled()' value will be 'baked-in' based - // on whether - // the profiler was enabled at build time or not. - // Otherwise just do the standard config lookup by key. - profilingEnabled = - configProvider.getBoolean( - ProfilingConfig.PROFILING_ENABLED, instrumenterConfig.isProfilingEnabled()); - profilingAgentless = - configProvider.getBoolean(PROFILING_AGENTLESS, PROFILING_AGENTLESS_DEFAULT); - isDatadogProfilerEnabled = - !isDatadogProfilerEnablementOverridden() - && configProvider.getBoolean( - PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment()); - profilingUrl = configProvider.getString(PROFILING_URL); - - if (tmpApiKey == null) { - final String oldProfilingApiKeyFile = configProvider.getString(PROFILING_API_KEY_FILE_OLD); - tmpApiKey = getEnv(propertyNameToEnvironmentVariableName(PROFILING_API_KEY_OLD)); - if (oldProfilingApiKeyFile != null) { - try { - tmpApiKey = - new String( - Files.readAllBytes(Paths.get(oldProfilingApiKeyFile)), StandardCharsets.UTF_8) - .trim(); - } catch (final IOException e) { - log.error("Cannot read API key from file {}, skipping", oldProfilingApiKeyFile, e); + this.traceClientIpHeader = traceClientIpHeader; + + traceClientIpResolverEnabled = + configProvider.getBoolean(TRACE_CLIENT_IP_RESOLVER_ENABLED, true); + + traceGitMetadataEnabled = configProvider.getBoolean(TRACE_GIT_METADATA_ENABLED, true); + + traceSamplingServiceRules = configProvider.getMergedMap(TRACE_SAMPLING_SERVICE_RULES); + traceSamplingOperationRules = configProvider.getMergedMap(TRACE_SAMPLING_OPERATION_RULES); + traceSamplingRules = configProvider.getString(TRACE_SAMPLING_RULES); + traceSampleRate = configProvider.getDouble(TRACE_SAMPLE_RATE); + traceRateLimit = configProvider.getInteger(TRACE_RATE_LIMIT, DEFAULT_TRACE_RATE_LIMIT); + spanSamplingRules = configProvider.getString(SPAN_SAMPLING_RULES); + spanSamplingRulesFile = configProvider.getString(SPAN_SAMPLING_RULES_FILE); + + // For the native image 'instrumenterConfig.isProfilingEnabled()' value will be 'baked-in' based + // on whether + // the profiler was enabled at build time or not. + // Otherwise just do the standard config lookup by key. + profilingEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_ENABLED, instrumenterConfig.isProfilingEnabled()); + profilingAgentless = + configProvider.getBoolean(PROFILING_AGENTLESS, PROFILING_AGENTLESS_DEFAULT); + isDatadogProfilerEnabled = + !isDatadogProfilerEnablementOverridden() + && configProvider.getBoolean( + PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment()); + profilingUrl = configProvider.getString(PROFILING_URL); + + if (tmpApiKey == null) { + final String oldProfilingApiKeyFile = configProvider.getString(PROFILING_API_KEY_FILE_OLD); + tmpApiKey = getEnv(propertyNameToEnvironmentVariableName(PROFILING_API_KEY_OLD)); + if (oldProfilingApiKeyFile != null) { + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + tmpApiKey = + new String( + Files.readAllBytes(Paths.get(oldProfilingApiKeyFile)), StandardCharsets.UTF_8) + .trim(); + }else{ + tmpApiKey = new String(FileUtils.readAllBytes(oldProfilingApiKeyFile), StandardCharsets.UTF_8) + .trim(); + } + } catch (final IOException e) { + log.error("Cannot read API key from file {}, skipping", oldProfilingApiKeyFile, e); + } + } } - } - } - if (tmpApiKey == null) { - final String veryOldProfilingApiKeyFile = - configProvider.getString(PROFILING_API_KEY_FILE_VERY_OLD); - tmpApiKey = getEnv(propertyNameToEnvironmentVariableName(PROFILING_API_KEY_VERY_OLD)); - if (veryOldProfilingApiKeyFile != null) { - try { - tmpApiKey = - new String( - Files.readAllBytes(Paths.get(veryOldProfilingApiKeyFile)), - StandardCharsets.UTF_8) - .trim(); - } catch (final IOException e) { - log.error("Cannot read API key from file {}, skipping", veryOldProfilingApiKeyFile, e); + if (tmpApiKey == null) { + final String veryOldProfilingApiKeyFile = + configProvider.getString(PROFILING_API_KEY_FILE_VERY_OLD); + tmpApiKey = getEnv(propertyNameToEnvironmentVariableName(PROFILING_API_KEY_VERY_OLD)); + if (veryOldProfilingApiKeyFile != null) { + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + tmpApiKey = + new String( + Files.readAllBytes(Paths.get(veryOldProfilingApiKeyFile)), + StandardCharsets.UTF_8) + .trim(); + } else { + tmpApiKey = new String(FileUtils.readAllBytes(veryOldProfilingApiKeyFile), StandardCharsets.UTF_8) + .trim(); + } + } catch (final IOException e) { + log.error("Cannot read API key from file {}, skipping", veryOldProfilingApiKeyFile, e); + } + } + } + + profilingTags = configProvider.getMergedMap(PROFILING_TAGS); + profilingStartDelay = + configProvider.getInteger(PROFILING_START_DELAY, PROFILING_START_DELAY_DEFAULT); + profilingStartForceFirst = + configProvider.getBoolean(PROFILING_START_FORCE_FIRST, PROFILING_START_FORCE_FIRST_DEFAULT); + profilingUploadPeriod = + configProvider.getInteger(PROFILING_UPLOAD_PERIOD, PROFILING_UPLOAD_PERIOD_DEFAULT); + profilingTemplateOverrideFile = configProvider.getString(PROFILING_TEMPLATE_OVERRIDE_FILE); + profilingUploadTimeout = + configProvider.getInteger(PROFILING_UPLOAD_TIMEOUT, PROFILING_UPLOAD_TIMEOUT_DEFAULT); + profilingUploadCompression = + configProvider.getString( + PROFILING_UPLOAD_COMPRESSION, PROFILING_UPLOAD_COMPRESSION_DEFAULT); + profilingProxyHost = configProvider.getString(PROFILING_PROXY_HOST); + profilingProxyPort = + configProvider.getInteger(PROFILING_PROXY_PORT, PROFILING_PROXY_PORT_DEFAULT); + profilingProxyUsername = configProvider.getString(PROFILING_PROXY_USERNAME); + profilingProxyPassword = configProvider.getString(PROFILING_PROXY_PASSWORD); + + profilingExceptionSampleLimit = + configProvider.getInteger( + PROFILING_EXCEPTION_SAMPLE_LIMIT, PROFILING_EXCEPTION_SAMPLE_LIMIT_DEFAULT); + profilingDirectAllocationSampleLimit = + configProvider.getInteger( + PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT, + PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT); + profilingExceptionHistogramTopItems = + configProvider.getInteger( + PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS, + PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS_DEFAULT); + profilingExceptionHistogramMaxCollectionSize = + configProvider.getInteger( + PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE, + PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE_DEFAULT); + + profilingExcludeAgentThreads = configProvider.getBoolean(PROFILING_EXCLUDE_AGENT_THREADS, true); + + profilingRecordExceptionMessage = + configProvider.getBoolean( + PROFILING_EXCEPTION_RECORD_MESSAGE, PROFILING_EXCEPTION_RECORD_MESSAGE_DEFAULT); + + profilingUploadSummaryOn413Enabled = + configProvider.getBoolean( + PROFILING_UPLOAD_SUMMARY_ON_413, PROFILING_UPLOAD_SUMMARY_ON_413_DEFAULT); + + crashTrackingAgentless = + configProvider.getBoolean(CRASH_TRACKING_AGENTLESS, CRASH_TRACKING_AGENTLESS_DEFAULT); + crashTrackingTags = configProvider.getMergedMap(CRASH_TRACKING_TAGS); + + float telemetryInterval = + configProvider.getFloat(TELEMETRY_HEARTBEAT_INTERVAL, DEFAULT_TELEMETRY_HEARTBEAT_INTERVAL); + if (telemetryInterval < 0.1 || telemetryInterval > 3600) { + log.warn( + "Invalid Telemetry heartbeat interval: {}. The value must be in range 0.1-3600", + telemetryInterval); + telemetryInterval = DEFAULT_TELEMETRY_HEARTBEAT_INTERVAL; + } + telemetryHeartbeatInterval = telemetryInterval; + + telemetryExtendedHeartbeatInterval = + configProvider.getLong( + TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL, DEFAULT_TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL); + + telemetryInterval = + configProvider.getFloat(TELEMETRY_METRICS_INTERVAL, DEFAULT_TELEMETRY_METRICS_INTERVAL); + if (telemetryInterval < 0.1 || telemetryInterval > 3600) { + log.warn( + "Invalid Telemetry metrics interval: {}. The value must be in range 0.1-3600", + telemetryInterval); + telemetryInterval = DEFAULT_TELEMETRY_METRICS_INTERVAL; + } + telemetryMetricsInterval = telemetryInterval; + + telemetryMetricsEnabled = + configProvider.getBoolean(GeneralConfig.TELEMETRY_METRICS_ENABLED, true); + + isTelemetryDependencyServiceEnabled = + configProvider.getBoolean( + TELEMETRY_DEPENDENCY_COLLECTION_ENABLED, + DEFAULT_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED); + + isTelemetryLogCollectionEnabled = + configProvider.getBoolean( + TELEMETRY_LOG_COLLECTION_ENABLED, DEFAULT_TELEMETRY_LOG_COLLECTION_ENABLED); + + clientIpEnabled = configProvider.getBoolean(CLIENT_IP_ENABLED, DEFAULT_CLIENT_IP_ENABLED); + + appSecReportingInband = + configProvider.getBoolean(APPSEC_REPORTING_INBAND, DEFAULT_APPSEC_REPORTING_INBAND); + appSecRulesFile = configProvider.getString(APPSEC_RULES_FILE, null); + + // Default AppSec report timeout min=5, max=60 + appSecReportMaxTimeout = configProvider.getInteger(APPSEC_REPORT_TIMEOUT_SEC, 60); + appSecReportMinTimeout = Math.min(appSecReportMaxTimeout, 5); + + appSecTraceRateLimit = + configProvider.getInteger(APPSEC_TRACE_RATE_LIMIT, DEFAULT_APPSEC_TRACE_RATE_LIMIT); + + appSecWafMetrics = configProvider.getBoolean(APPSEC_WAF_METRICS, DEFAULT_APPSEC_WAF_METRICS); + + appSecWafTimeout = configProvider.getInteger(APPSEC_WAF_TIMEOUT, DEFAULT_APPSEC_WAF_TIMEOUT); + + appSecObfuscationParameterKeyRegexp = + configProvider.getString(APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP, null); + appSecObfuscationParameterValueRegexp = + configProvider.getString(APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP, null); + + appSecHttpBlockedTemplateHtml = + configProvider.getString(APPSEC_HTTP_BLOCKED_TEMPLATE_HTML, null); + appSecHttpBlockedTemplateJson = + configProvider.getString(APPSEC_HTTP_BLOCKED_TEMPLATE_JSON, null); + appSecUserEventsTracking = + UserEventTrackingMode.fromString( + configProvider.getStringNotEmpty( + APPSEC_AUTOMATED_USER_EVENTS_TRACKING, SAFE.toString())); + apiSecurityEnabled = + configProvider.getBoolean(API_SECURITY_ENABLED, DEFAULT_API_SECURITY_ENABLED); + apiSecurityRequestSampleRate = + configProvider.getFloat( + API_SECURITY_REQUEST_SAMPLE_RATE, DEFAULT_API_SECURITY_REQUEST_SAMPLE_RATE); + + iastDebugEnabled = configProvider.getBoolean(IAST_DEBUG_ENABLED, DEFAULT_IAST_DEBUG_ENABLED); + + iastDetectionMode = + configProvider.getEnum(IAST_DETECTION_MODE, IastDetectionMode.class, DEFAULT); + iastMaxConcurrentRequests = iastDetectionMode.getIastMaxConcurrentRequests(configProvider); + iastVulnerabilitiesPerRequest = + iastDetectionMode.getIastVulnerabilitiesPerRequest(configProvider); + iastRequestSampling = iastDetectionMode.getIastRequestSampling(configProvider); + iastDeduplicationEnabled = iastDetectionMode.isIastDeduplicationEnabled(configProvider); + iastWeakHashAlgorithms = + tryMakeImmutableSet( + configProvider.getSet(IAST_WEAK_HASH_ALGORITHMS, DEFAULT_IAST_WEAK_HASH_ALGORITHMS)); + iastWeakCipherAlgorithms = + getPattern( + DEFAULT_IAST_WEAK_CIPHER_ALGORITHMS, + configProvider.getString(IAST_WEAK_CIPHER_ALGORITHMS)); + iastTelemetryVerbosity = + configProvider.getEnum(IAST_TELEMETRY_VERBOSITY, Verbosity.class, Verbosity.INFORMATION); + iastRedactionEnabled = + configProvider.getBoolean(IAST_REDACTION_ENABLED, DEFAULT_IAST_REDACTION_ENABLED); + iastRedactionNamePattern = + configProvider.getString(IAST_REDACTION_NAME_PATTERN, DEFAULT_IAST_REDACTION_NAME_PATTERN); + iastRedactionValuePattern = + configProvider.getString( + IAST_REDACTION_VALUE_PATTERN, DEFAULT_IAST_REDACTION_VALUE_PATTERN); + iastTruncationMaxValueLength = + configProvider.getInteger( + IAST_TRUNCATION_MAX_VALUE_LENGTH, DEFAULT_IAST_TRUNCATION_MAX_VALUE_LENGTH); + iastMaxRangeCount = iastDetectionMode.getIastMaxRangeCount(configProvider); + iastStacktraceLeakSuppress = + configProvider.getBoolean( + IAST_STACKTRACE_LEAK_SUPPRESS, DEFAULT_IAST_STACKTRACE_LEAK_SUPPRESS); + + ciVisibilityTraceSanitationEnabled = + configProvider.getBoolean(CIVISIBILITY_TRACE_SANITATION_ENABLED, true); + + ciVisibilityAgentlessEnabled = + configProvider.getBoolean( + CIVISIBILITY_AGENTLESS_ENABLED, DEFAULT_CIVISIBILITY_AGENTLESS_ENABLED); + + ciVisibilitySourceDataEnabled = + configProvider.getBoolean( + CIVISIBILITY_SOURCE_DATA_ENABLED, DEFAULT_CIVISIBILITY_SOURCE_DATA_ENABLED); + + ciVisibilitySourceDataRootCheckEnabled = + configProvider.getBoolean( + CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED, + DEFAULT_CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED); + + ciVisibilityBuildInstrumentationEnabled = + configProvider.getBoolean( + CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED, + DEFAULT_CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED); + + ciVisibilitySessionId = configProvider.getLong(CIVISIBILITY_SESSION_ID); + ciVisibilityModuleId = configProvider.getLong(CIVISIBILITY_MODULE_ID); + + final String ciVisibilityAgentlessUrlStr = configProvider.getString(CIVISIBILITY_AGENTLESS_URL); + URI parsedCiVisibilityUri = null; + if (ciVisibilityAgentlessUrlStr != null && !ciVisibilityAgentlessUrlStr.isEmpty()) { + try { + parsedCiVisibilityUri = new URL(ciVisibilityAgentlessUrlStr).toURI(); + } catch (MalformedURLException | URISyntaxException ex) { + log.error( + "Cannot parse CI Visibility agentless URL '{}', skipping", ciVisibilityAgentlessUrlStr); + } + } + if (parsedCiVisibilityUri != null) { + ciVisibilityAgentlessUrl = ciVisibilityAgentlessUrlStr; + } else { + ciVisibilityAgentlessUrl = null; + } + + ciVisibilityAgentJarUri = configProvider.getString(CIVISIBILITY_AGENT_JAR_URI); + ciVisibilityAutoConfigurationEnabled = + configProvider.getBoolean( + CIVISIBILITY_AUTO_CONFIGURATION_ENABLED, + DEFAULT_CIVISIBILITY_AUTO_CONFIGURATION_ENABLED); + ciVisibilityAdditionalChildProcessJvmArgs = + configProvider.getString(CIVISIBILITY_ADDITIONAL_CHILD_PROCESS_JVM_ARGS); + ciVisibilityCompilerPluginAutoConfigurationEnabled = + configProvider.getBoolean( + CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED, + DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED); + ciVisibilityCodeCoverageEnabled = + configProvider.getBoolean(CIVISIBILITY_CODE_COVERAGE_ENABLED, true); + ciVisibilityCodeCoveragePercentageCalculationEnabled = + configProvider.getBoolean(CIVISIBILITY_CODE_COVERAGE_PERCENTAGE_CALCULATION_ENABLED, true); + ciVisibilityCodeCoverageReportDumpDir = + configProvider.getString(CIVISIBILITY_CODE_COVERAGE_REPORT_DUMP_DIR); + ciVisibilityCompilerPluginVersion = + configProvider.getString( + CIVISIBILITY_COMPILER_PLUGIN_VERSION, DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_VERSION); + ciVisibilityJacocoPluginVersion = + configProvider.getString( + CIVISIBILITY_JACOCO_PLUGIN_VERSION, DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_VERSION); + ciVisibilityJacocoPluginVersionProvided = + configProvider.getString(CIVISIBILITY_JACOCO_PLUGIN_VERSION) != null; + ciVisibilityCodeCoverageIncludes = + Arrays.asList( + COLON.split(configProvider.getString(CIVISIBILITY_CODE_COVERAGE_INCLUDES, ":"))); + ciVisibilityCodeCoverageExcludes = + Arrays.asList( + COLON.split( + configProvider.getString( + CIVISIBILITY_CODE_COVERAGE_EXCLUDES, + DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_EXCLUDES))); + ciVisibilityCodeCoverageIncludedPackages = + convertJacocoExclusionFormatToPackagePrefixes(ciVisibilityCodeCoverageIncludes); + ciVisibilityCodeCoverageExcludedPackages = + convertJacocoExclusionFormatToPackagePrefixes(ciVisibilityCodeCoverageExcludes); + ciVisibilityJacocoGradleSourceSets = + configProvider.getList( + CIVISIBILITY_JACOCO_GRADLE_SOURCE_SETS, Collections.singletonList("main")); + ciVisibilityDebugPort = configProvider.getInteger(CIVISIBILITY_DEBUG_PORT); + ciVisibilityGitUploadEnabled = + configProvider.getBoolean( + CIVISIBILITY_GIT_UPLOAD_ENABLED, DEFAULT_CIVISIBILITY_GIT_UPLOAD_ENABLED); + ciVisibilityGitUnshallowEnabled = + configProvider.getBoolean( + CIVISIBILITY_GIT_UNSHALLOW_ENABLED, DEFAULT_CIVISIBILITY_GIT_UNSHALLOW_ENABLED); + ciVisibilityGitUnshallowDefer = + configProvider.getBoolean(CIVISIBILITY_GIT_UNSHALLOW_DEFER, true); + ciVisibilityGitCommandTimeoutMillis = + configProvider.getLong( + CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS, + DEFAULT_CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS); + ciVisibilityBackendApiTimeoutMillis = + configProvider.getLong( + CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS, + DEFAULT_CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS); + ciVisibilityGitUploadTimeoutMillis = + configProvider.getLong( + CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS, DEFAULT_CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS); + ciVisibilityGitRemoteName = + configProvider.getString( + CIVISIBILITY_GIT_REMOTE_NAME, DEFAULT_CIVISIBILITY_GIT_REMOTE_NAME); + ciVisibilitySignalServerHost = + configProvider.getString( + CIVISIBILITY_SIGNAL_SERVER_HOST, DEFAULT_CIVISIBILITY_SIGNAL_SERVER_HOST); + ciVisibilitySignalServerPort = + configProvider.getInteger( + CIVISIBILITY_SIGNAL_SERVER_PORT, DEFAULT_CIVISIBILITY_SIGNAL_SERVER_PORT); + ciVisibilityItrEnabled = configProvider.getBoolean(CIVISIBILITY_ITR_ENABLED, true); + ciVisibilityCiProviderIntegrationEnabled = + configProvider.getBoolean(CIVISIBILITY_CIPROVIDER_INTEGRATION_ENABLED, true); + ciVisibilityRepoIndexSharingEnabled = + configProvider.getBoolean(CIVISIBILITY_REPO_INDEX_SHARING_ENABLED, true); + ciVisibilityModuleExecutionSettingsCacheSize = + configProvider.getInteger(CIVISIBILITY_MODULE_EXECUTION_SETTINGS_CACHE_SIZE, 16); + ciVisibilityJvmInfoCacheSize = configProvider.getInteger(CIVISIBILITY_JVM_INFO_CACHE_SIZE, 8); + ciVisibilityCoverageSegmentsEnabled = + configProvider.getBoolean(CIVISIBILITY_CODE_COVERAGE_SEGMENTS_ENABLED, false); + ciVisibilityCoverageRootPackagesLimit = + configProvider.getInteger(CIVISIBILITY_CODE_COVERAGE_ROOT_PACKAGES_LIMIT, 50); + ciVisibilityInjectedTracerVersion = + configProvider.getString(CIVISIBILITY_INJECTED_TRACER_VERSION); + ciVisibilityResourceFolderNames = + configProvider.getList( + CIVISIBILITY_RESOURCE_FOLDER_NAMES, DEFAULT_CIVISIBILITY_RESOURCE_FOLDER_NAMES); + ciVisibilityFlakyRetryEnabled = + configProvider.getBoolean(CIVISIBILITY_FLAKY_RETRY_ENABLED, false); + ciVisibilityFlakyRetryCount = configProvider.getInteger(CIVISIBILITY_FLAKY_RETRY_COUNT, 5); + ciVisibilityModuleName = configProvider.getString(CIVISIBILITY_MODULE_NAME); + + remoteConfigEnabled = + configProvider.getBoolean(REMOTE_CONFIG_ENABLED, DEFAULT_REMOTE_CONFIG_ENABLED); + remoteConfigIntegrityCheckEnabled = + configProvider.getBoolean( + REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED, DEFAULT_REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED); + remoteConfigUrl = configProvider.getString(REMOTE_CONFIG_URL); + remoteConfigPollIntervalSeconds = + configProvider.getFloat( + REMOTE_CONFIG_POLL_INTERVAL_SECONDS, DEFAULT_REMOTE_CONFIG_POLL_INTERVAL_SECONDS); + remoteConfigMaxPayloadSize = + configProvider.getInteger( + REMOTE_CONFIG_MAX_PAYLOAD_SIZE, DEFAULT_REMOTE_CONFIG_MAX_PAYLOAD_SIZE) + * 1024; + remoteConfigTargetsKeyId = + configProvider.getString( + REMOTE_CONFIG_TARGETS_KEY_ID, DEFAULT_REMOTE_CONFIG_TARGETS_KEY_ID); + remoteConfigTargetsKey = + configProvider.getString(REMOTE_CONFIG_TARGETS_KEY, DEFAULT_REMOTE_CONFIG_TARGETS_KEY); + + debuggerEnabled = configProvider.getBoolean(DEBUGGER_ENABLED, DEFAULT_DEBUGGER_ENABLED); + debuggerUploadTimeout = + configProvider.getInteger(DEBUGGER_UPLOAD_TIMEOUT, DEFAULT_DEBUGGER_UPLOAD_TIMEOUT); + debuggerUploadFlushInterval = + configProvider.getInteger( + DEBUGGER_UPLOAD_FLUSH_INTERVAL, DEFAULT_DEBUGGER_UPLOAD_FLUSH_INTERVAL); + debuggerClassFileDumpEnabled = + configProvider.getBoolean( + DEBUGGER_CLASSFILE_DUMP_ENABLED, DEFAULT_DEBUGGER_CLASSFILE_DUMP_ENABLED); + debuggerPollInterval = + configProvider.getInteger(DEBUGGER_POLL_INTERVAL, DEFAULT_DEBUGGER_POLL_INTERVAL); + debuggerDiagnosticsInterval = + configProvider.getInteger( + DEBUGGER_DIAGNOSTICS_INTERVAL, DEFAULT_DEBUGGER_DIAGNOSTICS_INTERVAL); + debuggerMetricEnabled = + runtimeMetricsEnabled + && configProvider.getBoolean( + DEBUGGER_METRICS_ENABLED, DEFAULT_DEBUGGER_METRICS_ENABLED); + debuggerProbeFileLocation = configProvider.getString(DEBUGGER_PROBE_FILE_LOCATION); + debuggerUploadBatchSize = + configProvider.getInteger(DEBUGGER_UPLOAD_BATCH_SIZE, DEFAULT_DEBUGGER_UPLOAD_BATCH_SIZE); + debuggerMaxPayloadSize = + configProvider.getInteger(DEBUGGER_MAX_PAYLOAD_SIZE, DEFAULT_DEBUGGER_MAX_PAYLOAD_SIZE) + * 1024; + debuggerVerifyByteCode = + configProvider.getBoolean(DEBUGGER_VERIFY_BYTECODE, DEFAULT_DEBUGGER_VERIFY_BYTECODE); + debuggerInstrumentTheWorld = + configProvider.getBoolean( + DEBUGGER_INSTRUMENT_THE_WORLD, DEFAULT_DEBUGGER_INSTRUMENT_THE_WORLD); + debuggerExcludeFiles = configProvider.getString(DEBUGGER_EXCLUDE_FILES); + debuggerCaptureTimeout = + configProvider.getInteger(DEBUGGER_CAPTURE_TIMEOUT, DEFAULT_DEBUGGER_CAPTURE_TIMEOUT); + debuggerRedactedIdentifiers = configProvider.getString(DEBUGGER_REDACTED_IDENTIFIERS, null); + debuggerRedactedTypes = configProvider.getString(DEBUGGER_REDACTED_TYPES, null); + debuggerSymbolEnabled = + configProvider.getBoolean(DEBUGGER_SYMBOL_ENABLED, DEFAULT_DEBUGGER_SYMBOL_ENABLED); + debuggerSymbolForceUpload = + configProvider.getBoolean( + DEBUGGER_SYMBOL_FORCE_UPLOAD, DEFAULT_DEBUGGER_SYMBOL_FORCE_UPLOAD); + debuggerSymbolIncludes = configProvider.getString(DEBUGGER_SYMBOL_INCLUDES, null); + debuggerSymbolFlushThreshold = + configProvider.getInteger( + DEBUGGER_SYMBOL_FLUSH_THRESHOLD, DEFAULT_DEBUGGER_SYMBOL_FLUSH_THRESHOLD); + + awsPropagationEnabled = isPropagationEnabled(true, "aws", "aws-sdk"); + sqsPropagationEnabled = isPropagationEnabled(true, "sqs"); + + kafkaClientPropagationEnabled = isPropagationEnabled(true, "kafka", "kafka.client"); + kafkaClientPropagationDisabledTopics = + tryMakeImmutableSet(configProvider.getList(KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS)); + kafkaClientBase64DecodingEnabled = + configProvider.getBoolean(KAFKA_CLIENT_BASE64_DECODING_ENABLED, false); + + jmsPropagationEnabled = isPropagationEnabled(true, "jms"); + jmsPropagationDisabledTopics = + tryMakeImmutableSet(configProvider.getList(JMS_PROPAGATION_DISABLED_TOPICS)); + jmsPropagationDisabledQueues = + tryMakeImmutableSet(configProvider.getList(JMS_PROPAGATION_DISABLED_QUEUES)); + jmsUnacknowledgedMaxAge = configProvider.getInteger(JMS_UNACKNOWLEDGED_MAX_AGE, 3600); + + rabbitPropagationEnabled = isPropagationEnabled(true, "rabbit", "rabbitmq"); + rabbitPropagationDisabledQueues = + tryMakeImmutableSet(configProvider.getList(RABBIT_PROPAGATION_DISABLED_QUEUES)); + rabbitPropagationDisabledExchanges = + tryMakeImmutableSet(configProvider.getList(RABBIT_PROPAGATION_DISABLED_EXCHANGES)); + rabbitIncludeRoutingKeyInResource = + configProvider.getBoolean(RABBIT_INCLUDE_ROUTINGKEY_IN_RESOURCE, true); + + messageBrokerSplitByDestination = + configProvider.getBoolean(MESSAGE_BROKER_SPLIT_BY_DESTINATION, false); + + grpcIgnoredInboundMethods = + tryMakeImmutableSet(configProvider.getList(GRPC_IGNORED_INBOUND_METHODS)); + final List tmpGrpcIgnoredOutboundMethods = new ArrayList<>(); + tmpGrpcIgnoredOutboundMethods.addAll(configProvider.getList(GRPC_IGNORED_OUTBOUND_METHODS)); + // When tracing shadowing will be possible we can instrument the stubs to silent tracing + // starting from interception points + if (InstrumenterConfig.get() + .isIntegrationEnabled(Collections.singleton("google-pubsub"), true)) { + tmpGrpcIgnoredOutboundMethods.addAll( + configProvider.getList( + GOOGLE_PUBSUB_IGNORED_GRPC_METHODS, + Arrays.asList( + "google.pubsub.v1.Subscriber/ModifyAckDeadline", + "google.pubsub.v1.Subscriber/Acknowledge", + "google.pubsub.v1.Subscriber/Pull", + "google.pubsub.v1.Subscriber/StreamingPull", + "google.pubsub.v1.Publisher/Publish"))); } - } - } - - profilingTags = configProvider.getMergedMap(PROFILING_TAGS); - profilingStartDelay = - configProvider.getInteger(PROFILING_START_DELAY, PROFILING_START_DELAY_DEFAULT); - profilingStartForceFirst = - configProvider.getBoolean(PROFILING_START_FORCE_FIRST, PROFILING_START_FORCE_FIRST_DEFAULT); - profilingUploadPeriod = - configProvider.getInteger(PROFILING_UPLOAD_PERIOD, PROFILING_UPLOAD_PERIOD_DEFAULT); - profilingTemplateOverrideFile = configProvider.getString(PROFILING_TEMPLATE_OVERRIDE_FILE); - profilingUploadTimeout = - configProvider.getInteger(PROFILING_UPLOAD_TIMEOUT, PROFILING_UPLOAD_TIMEOUT_DEFAULT); - profilingUploadCompression = - configProvider.getString( - PROFILING_UPLOAD_COMPRESSION, PROFILING_UPLOAD_COMPRESSION_DEFAULT); - profilingProxyHost = configProvider.getString(PROFILING_PROXY_HOST); - profilingProxyPort = - configProvider.getInteger(PROFILING_PROXY_PORT, PROFILING_PROXY_PORT_DEFAULT); - profilingProxyUsername = configProvider.getString(PROFILING_PROXY_USERNAME); - profilingProxyPassword = configProvider.getString(PROFILING_PROXY_PASSWORD); - - profilingExceptionSampleLimit = - configProvider.getInteger( - PROFILING_EXCEPTION_SAMPLE_LIMIT, PROFILING_EXCEPTION_SAMPLE_LIMIT_DEFAULT); - profilingDirectAllocationSampleLimit = - configProvider.getInteger( - PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT, - PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT); - profilingExceptionHistogramTopItems = - configProvider.getInteger( - PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS, - PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS_DEFAULT); - profilingExceptionHistogramMaxCollectionSize = - configProvider.getInteger( - PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE, - PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE_DEFAULT); - - profilingExcludeAgentThreads = configProvider.getBoolean(PROFILING_EXCLUDE_AGENT_THREADS, true); - - profilingRecordExceptionMessage = - configProvider.getBoolean( - PROFILING_EXCEPTION_RECORD_MESSAGE, PROFILING_EXCEPTION_RECORD_MESSAGE_DEFAULT); - - profilingUploadSummaryOn413Enabled = - configProvider.getBoolean( - PROFILING_UPLOAD_SUMMARY_ON_413, PROFILING_UPLOAD_SUMMARY_ON_413_DEFAULT); - - crashTrackingAgentless = - configProvider.getBoolean(CRASH_TRACKING_AGENTLESS, CRASH_TRACKING_AGENTLESS_DEFAULT); - crashTrackingTags = configProvider.getMergedMap(CRASH_TRACKING_TAGS); - - float telemetryInterval = - configProvider.getFloat(TELEMETRY_HEARTBEAT_INTERVAL, DEFAULT_TELEMETRY_HEARTBEAT_INTERVAL); - if (telemetryInterval < 0.1 || telemetryInterval > 3600) { - log.warn( - "Invalid Telemetry heartbeat interval: {}. The value must be in range 0.1-3600", - telemetryInterval); - telemetryInterval = DEFAULT_TELEMETRY_HEARTBEAT_INTERVAL; - } - telemetryHeartbeatInterval = telemetryInterval; - - telemetryExtendedHeartbeatInterval = - configProvider.getLong( - TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL, DEFAULT_TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL); - - telemetryInterval = - configProvider.getFloat(TELEMETRY_METRICS_INTERVAL, DEFAULT_TELEMETRY_METRICS_INTERVAL); - if (telemetryInterval < 0.1 || telemetryInterval > 3600) { - log.warn( - "Invalid Telemetry metrics interval: {}. The value must be in range 0.1-3600", - telemetryInterval); - telemetryInterval = DEFAULT_TELEMETRY_METRICS_INTERVAL; - } - telemetryMetricsInterval = telemetryInterval; - - telemetryMetricsEnabled = - configProvider.getBoolean(GeneralConfig.TELEMETRY_METRICS_ENABLED, true); - - isTelemetryDependencyServiceEnabled = - configProvider.getBoolean( - TELEMETRY_DEPENDENCY_COLLECTION_ENABLED, - DEFAULT_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED); - - isTelemetryLogCollectionEnabled = - configProvider.getBoolean( - TELEMETRY_LOG_COLLECTION_ENABLED, DEFAULT_TELEMETRY_LOG_COLLECTION_ENABLED); - - clientIpEnabled = configProvider.getBoolean(CLIENT_IP_ENABLED, DEFAULT_CLIENT_IP_ENABLED); - - appSecReportingInband = - configProvider.getBoolean(APPSEC_REPORTING_INBAND, DEFAULT_APPSEC_REPORTING_INBAND); - appSecRulesFile = configProvider.getString(APPSEC_RULES_FILE, null); - - // Default AppSec report timeout min=5, max=60 - appSecReportMaxTimeout = configProvider.getInteger(APPSEC_REPORT_TIMEOUT_SEC, 60); - appSecReportMinTimeout = Math.min(appSecReportMaxTimeout, 5); - - appSecTraceRateLimit = - configProvider.getInteger(APPSEC_TRACE_RATE_LIMIT, DEFAULT_APPSEC_TRACE_RATE_LIMIT); - - appSecWafMetrics = configProvider.getBoolean(APPSEC_WAF_METRICS, DEFAULT_APPSEC_WAF_METRICS); - - appSecWafTimeout = configProvider.getInteger(APPSEC_WAF_TIMEOUT, DEFAULT_APPSEC_WAF_TIMEOUT); - - appSecObfuscationParameterKeyRegexp = - configProvider.getString(APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP, null); - appSecObfuscationParameterValueRegexp = - configProvider.getString(APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP, null); - - appSecHttpBlockedTemplateHtml = - configProvider.getString(APPSEC_HTTP_BLOCKED_TEMPLATE_HTML, null); - appSecHttpBlockedTemplateJson = - configProvider.getString(APPSEC_HTTP_BLOCKED_TEMPLATE_JSON, null); - appSecUserEventsTracking = - UserEventTrackingMode.fromString( - configProvider.getStringNotEmpty( - APPSEC_AUTOMATED_USER_EVENTS_TRACKING, SAFE.toString())); - apiSecurityEnabled = - configProvider.getBoolean(API_SECURITY_ENABLED, DEFAULT_API_SECURITY_ENABLED); - apiSecurityRequestSampleRate = - configProvider.getFloat( - API_SECURITY_REQUEST_SAMPLE_RATE, DEFAULT_API_SECURITY_REQUEST_SAMPLE_RATE); - - iastDebugEnabled = configProvider.getBoolean(IAST_DEBUG_ENABLED, DEFAULT_IAST_DEBUG_ENABLED); - - iastDetectionMode = - configProvider.getEnum(IAST_DETECTION_MODE, IastDetectionMode.class, DEFAULT); - iastMaxConcurrentRequests = iastDetectionMode.getIastMaxConcurrentRequests(configProvider); - iastVulnerabilitiesPerRequest = - iastDetectionMode.getIastVulnerabilitiesPerRequest(configProvider); - iastRequestSampling = iastDetectionMode.getIastRequestSampling(configProvider); - iastDeduplicationEnabled = iastDetectionMode.isIastDeduplicationEnabled(configProvider); - iastWeakHashAlgorithms = - tryMakeImmutableSet( - configProvider.getSet(IAST_WEAK_HASH_ALGORITHMS, DEFAULT_IAST_WEAK_HASH_ALGORITHMS)); - iastWeakCipherAlgorithms = - getPattern( - DEFAULT_IAST_WEAK_CIPHER_ALGORITHMS, - configProvider.getString(IAST_WEAK_CIPHER_ALGORITHMS)); - iastTelemetryVerbosity = - configProvider.getEnum(IAST_TELEMETRY_VERBOSITY, Verbosity.class, Verbosity.INFORMATION); - iastRedactionEnabled = - configProvider.getBoolean(IAST_REDACTION_ENABLED, DEFAULT_IAST_REDACTION_ENABLED); - iastRedactionNamePattern = - configProvider.getString(IAST_REDACTION_NAME_PATTERN, DEFAULT_IAST_REDACTION_NAME_PATTERN); - iastRedactionValuePattern = - configProvider.getString( - IAST_REDACTION_VALUE_PATTERN, DEFAULT_IAST_REDACTION_VALUE_PATTERN); - iastTruncationMaxValueLength = - configProvider.getInteger( - IAST_TRUNCATION_MAX_VALUE_LENGTH, DEFAULT_IAST_TRUNCATION_MAX_VALUE_LENGTH); - iastMaxRangeCount = iastDetectionMode.getIastMaxRangeCount(configProvider); - iastStacktraceLeakSuppress = - configProvider.getBoolean( - IAST_STACKTRACE_LEAK_SUPPRESS, DEFAULT_IAST_STACKTRACE_LEAK_SUPPRESS); - - ciVisibilityTraceSanitationEnabled = - configProvider.getBoolean(CIVISIBILITY_TRACE_SANITATION_ENABLED, true); - - ciVisibilityAgentlessEnabled = - configProvider.getBoolean( - CIVISIBILITY_AGENTLESS_ENABLED, DEFAULT_CIVISIBILITY_AGENTLESS_ENABLED); - - ciVisibilitySourceDataEnabled = - configProvider.getBoolean( - CIVISIBILITY_SOURCE_DATA_ENABLED, DEFAULT_CIVISIBILITY_SOURCE_DATA_ENABLED); - - ciVisibilitySourceDataRootCheckEnabled = - configProvider.getBoolean( - CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED, - DEFAULT_CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED); - - ciVisibilityBuildInstrumentationEnabled = - configProvider.getBoolean( - CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED, - DEFAULT_CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED); - - ciVisibilitySessionId = configProvider.getLong(CIVISIBILITY_SESSION_ID); - ciVisibilityModuleId = configProvider.getLong(CIVISIBILITY_MODULE_ID); - - final String ciVisibilityAgentlessUrlStr = configProvider.getString(CIVISIBILITY_AGENTLESS_URL); - URI parsedCiVisibilityUri = null; - if (ciVisibilityAgentlessUrlStr != null && !ciVisibilityAgentlessUrlStr.isEmpty()) { - try { - parsedCiVisibilityUri = new URL(ciVisibilityAgentlessUrlStr).toURI(); - } catch (MalformedURLException | URISyntaxException ex) { - log.error( - "Cannot parse CI Visibility agentless URL '{}', skipping", ciVisibilityAgentlessUrlStr); - } - } - if (parsedCiVisibilityUri != null) { - ciVisibilityAgentlessUrl = ciVisibilityAgentlessUrlStr; - } else { - ciVisibilityAgentlessUrl = null; - } - - ciVisibilityAgentJarUri = configProvider.getString(CIVISIBILITY_AGENT_JAR_URI); - ciVisibilityAutoConfigurationEnabled = - configProvider.getBoolean( - CIVISIBILITY_AUTO_CONFIGURATION_ENABLED, - DEFAULT_CIVISIBILITY_AUTO_CONFIGURATION_ENABLED); - ciVisibilityAdditionalChildProcessJvmArgs = - configProvider.getString(CIVISIBILITY_ADDITIONAL_CHILD_PROCESS_JVM_ARGS); - ciVisibilityCompilerPluginAutoConfigurationEnabled = - configProvider.getBoolean( - CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED, - DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED); - ciVisibilityCodeCoverageEnabled = - configProvider.getBoolean(CIVISIBILITY_CODE_COVERAGE_ENABLED, true); - ciVisibilityCodeCoveragePercentageCalculationEnabled = - configProvider.getBoolean(CIVISIBILITY_CODE_COVERAGE_PERCENTAGE_CALCULATION_ENABLED, true); - ciVisibilityCodeCoverageReportDumpDir = - configProvider.getString(CIVISIBILITY_CODE_COVERAGE_REPORT_DUMP_DIR); - ciVisibilityCompilerPluginVersion = - configProvider.getString( - CIVISIBILITY_COMPILER_PLUGIN_VERSION, DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_VERSION); - ciVisibilityJacocoPluginVersion = - configProvider.getString( - CIVISIBILITY_JACOCO_PLUGIN_VERSION, DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_VERSION); - ciVisibilityJacocoPluginVersionProvided = - configProvider.getString(CIVISIBILITY_JACOCO_PLUGIN_VERSION) != null; - ciVisibilityCodeCoverageIncludes = - Arrays.asList( - COLON.split(configProvider.getString(CIVISIBILITY_CODE_COVERAGE_INCLUDES, ":"))); - ciVisibilityCodeCoverageExcludes = - Arrays.asList( - COLON.split( + grpcIgnoredOutboundMethods = tryMakeImmutableSet(tmpGrpcIgnoredOutboundMethods); + grpcServerTrimPackageResource = + configProvider.getBoolean(GRPC_SERVER_TRIM_PACKAGE_RESOURCE, false); + grpcServerErrorStatuses = + configProvider.getIntegerRange( + GRPC_SERVER_ERROR_STATUSES, DEFAULT_GRPC_SERVER_ERROR_STATUSES); + grpcClientErrorStatuses = + configProvider.getIntegerRange( + GRPC_CLIENT_ERROR_STATUSES, DEFAULT_GRPC_CLIENT_ERROR_STATUSES); + + hystrixTagsEnabled = configProvider.getBoolean(HYSTRIX_TAGS_ENABLED, false); + hystrixMeasuredEnabled = configProvider.getBoolean(HYSTRIX_MEASURED_ENABLED, false); + + igniteCacheIncludeKeys = configProvider.getBoolean(IGNITE_CACHE_INCLUDE_KEYS, false); + + obfuscationQueryRegexp = configProvider.getString( - CIVISIBILITY_CODE_COVERAGE_EXCLUDES, - DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_EXCLUDES))); - ciVisibilityCodeCoverageIncludedPackages = - convertJacocoExclusionFormatToPackagePrefixes(ciVisibilityCodeCoverageIncludes); - ciVisibilityCodeCoverageExcludedPackages = - convertJacocoExclusionFormatToPackagePrefixes(ciVisibilityCodeCoverageExcludes); - ciVisibilityJacocoGradleSourceSets = - configProvider.getList( - CIVISIBILITY_JACOCO_GRADLE_SOURCE_SETS, Collections.singletonList("main")); - ciVisibilityDebugPort = configProvider.getInteger(CIVISIBILITY_DEBUG_PORT); - ciVisibilityGitUploadEnabled = - configProvider.getBoolean( - CIVISIBILITY_GIT_UPLOAD_ENABLED, DEFAULT_CIVISIBILITY_GIT_UPLOAD_ENABLED); - ciVisibilityGitUnshallowEnabled = - configProvider.getBoolean( - CIVISIBILITY_GIT_UNSHALLOW_ENABLED, DEFAULT_CIVISIBILITY_GIT_UNSHALLOW_ENABLED); - ciVisibilityGitUnshallowDefer = - configProvider.getBoolean(CIVISIBILITY_GIT_UNSHALLOW_DEFER, true); - ciVisibilityGitCommandTimeoutMillis = - configProvider.getLong( - CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS, - DEFAULT_CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS); - ciVisibilityBackendApiTimeoutMillis = - configProvider.getLong( - CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS, - DEFAULT_CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS); - ciVisibilityGitUploadTimeoutMillis = - configProvider.getLong( - CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS, DEFAULT_CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS); - ciVisibilityGitRemoteName = - configProvider.getString( - CIVISIBILITY_GIT_REMOTE_NAME, DEFAULT_CIVISIBILITY_GIT_REMOTE_NAME); - ciVisibilitySignalServerHost = - configProvider.getString( - CIVISIBILITY_SIGNAL_SERVER_HOST, DEFAULT_CIVISIBILITY_SIGNAL_SERVER_HOST); - ciVisibilitySignalServerPort = - configProvider.getInteger( - CIVISIBILITY_SIGNAL_SERVER_PORT, DEFAULT_CIVISIBILITY_SIGNAL_SERVER_PORT); - ciVisibilityItrEnabled = configProvider.getBoolean(CIVISIBILITY_ITR_ENABLED, true); - ciVisibilityCiProviderIntegrationEnabled = - configProvider.getBoolean(CIVISIBILITY_CIPROVIDER_INTEGRATION_ENABLED, true); - ciVisibilityRepoIndexSharingEnabled = - configProvider.getBoolean(CIVISIBILITY_REPO_INDEX_SHARING_ENABLED, true); - ciVisibilityModuleExecutionSettingsCacheSize = - configProvider.getInteger(CIVISIBILITY_MODULE_EXECUTION_SETTINGS_CACHE_SIZE, 16); - ciVisibilityJvmInfoCacheSize = configProvider.getInteger(CIVISIBILITY_JVM_INFO_CACHE_SIZE, 8); - ciVisibilityCoverageSegmentsEnabled = - configProvider.getBoolean(CIVISIBILITY_CODE_COVERAGE_SEGMENTS_ENABLED, false); - ciVisibilityCoverageRootPackagesLimit = - configProvider.getInteger(CIVISIBILITY_CODE_COVERAGE_ROOT_PACKAGES_LIMIT, 50); - ciVisibilityInjectedTracerVersion = - configProvider.getString(CIVISIBILITY_INJECTED_TRACER_VERSION); - ciVisibilityResourceFolderNames = - configProvider.getList( - CIVISIBILITY_RESOURCE_FOLDER_NAMES, DEFAULT_CIVISIBILITY_RESOURCE_FOLDER_NAMES); - ciVisibilityFlakyRetryEnabled = - configProvider.getBoolean(CIVISIBILITY_FLAKY_RETRY_ENABLED, false); - ciVisibilityFlakyRetryCount = configProvider.getInteger(CIVISIBILITY_FLAKY_RETRY_COUNT, 5); - ciVisibilityModuleName = configProvider.getString(CIVISIBILITY_MODULE_NAME); - - remoteConfigEnabled = - configProvider.getBoolean(REMOTE_CONFIG_ENABLED, DEFAULT_REMOTE_CONFIG_ENABLED); - remoteConfigIntegrityCheckEnabled = - configProvider.getBoolean( - REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED, DEFAULT_REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED); - remoteConfigUrl = configProvider.getString(REMOTE_CONFIG_URL); - remoteConfigPollIntervalSeconds = - configProvider.getFloat( - REMOTE_CONFIG_POLL_INTERVAL_SECONDS, DEFAULT_REMOTE_CONFIG_POLL_INTERVAL_SECONDS); - remoteConfigMaxPayloadSize = - configProvider.getInteger( - REMOTE_CONFIG_MAX_PAYLOAD_SIZE, DEFAULT_REMOTE_CONFIG_MAX_PAYLOAD_SIZE) - * 1024; - remoteConfigTargetsKeyId = - configProvider.getString( - REMOTE_CONFIG_TARGETS_KEY_ID, DEFAULT_REMOTE_CONFIG_TARGETS_KEY_ID); - remoteConfigTargetsKey = - configProvider.getString(REMOTE_CONFIG_TARGETS_KEY, DEFAULT_REMOTE_CONFIG_TARGETS_KEY); - - debuggerEnabled = configProvider.getBoolean(DEBUGGER_ENABLED, DEFAULT_DEBUGGER_ENABLED); - debuggerUploadTimeout = - configProvider.getInteger(DEBUGGER_UPLOAD_TIMEOUT, DEFAULT_DEBUGGER_UPLOAD_TIMEOUT); - debuggerUploadFlushInterval = - configProvider.getInteger( - DEBUGGER_UPLOAD_FLUSH_INTERVAL, DEFAULT_DEBUGGER_UPLOAD_FLUSH_INTERVAL); - debuggerClassFileDumpEnabled = - configProvider.getBoolean( - DEBUGGER_CLASSFILE_DUMP_ENABLED, DEFAULT_DEBUGGER_CLASSFILE_DUMP_ENABLED); - debuggerPollInterval = - configProvider.getInteger(DEBUGGER_POLL_INTERVAL, DEFAULT_DEBUGGER_POLL_INTERVAL); - debuggerDiagnosticsInterval = - configProvider.getInteger( - DEBUGGER_DIAGNOSTICS_INTERVAL, DEFAULT_DEBUGGER_DIAGNOSTICS_INTERVAL); - debuggerMetricEnabled = - runtimeMetricsEnabled - && configProvider.getBoolean( - DEBUGGER_METRICS_ENABLED, DEFAULT_DEBUGGER_METRICS_ENABLED); - debuggerProbeFileLocation = configProvider.getString(DEBUGGER_PROBE_FILE_LOCATION); - debuggerUploadBatchSize = - configProvider.getInteger(DEBUGGER_UPLOAD_BATCH_SIZE, DEFAULT_DEBUGGER_UPLOAD_BATCH_SIZE); - debuggerMaxPayloadSize = - configProvider.getInteger(DEBUGGER_MAX_PAYLOAD_SIZE, DEFAULT_DEBUGGER_MAX_PAYLOAD_SIZE) - * 1024; - debuggerVerifyByteCode = - configProvider.getBoolean(DEBUGGER_VERIFY_BYTECODE, DEFAULT_DEBUGGER_VERIFY_BYTECODE); - debuggerInstrumentTheWorld = - configProvider.getBoolean( - DEBUGGER_INSTRUMENT_THE_WORLD, DEFAULT_DEBUGGER_INSTRUMENT_THE_WORLD); - debuggerExcludeFiles = configProvider.getString(DEBUGGER_EXCLUDE_FILES); - debuggerCaptureTimeout = - configProvider.getInteger(DEBUGGER_CAPTURE_TIMEOUT, DEFAULT_DEBUGGER_CAPTURE_TIMEOUT); - debuggerRedactedIdentifiers = configProvider.getString(DEBUGGER_REDACTED_IDENTIFIERS, null); - debuggerRedactedTypes = configProvider.getString(DEBUGGER_REDACTED_TYPES, null); - debuggerSymbolEnabled = - configProvider.getBoolean(DEBUGGER_SYMBOL_ENABLED, DEFAULT_DEBUGGER_SYMBOL_ENABLED); - debuggerSymbolForceUpload = - configProvider.getBoolean( - DEBUGGER_SYMBOL_FORCE_UPLOAD, DEFAULT_DEBUGGER_SYMBOL_FORCE_UPLOAD); - debuggerSymbolIncludes = configProvider.getString(DEBUGGER_SYMBOL_INCLUDES, null); - debuggerSymbolFlushThreshold = - configProvider.getInteger( - DEBUGGER_SYMBOL_FLUSH_THRESHOLD, DEFAULT_DEBUGGER_SYMBOL_FLUSH_THRESHOLD); - - awsPropagationEnabled = isPropagationEnabled(true, "aws", "aws-sdk"); - sqsPropagationEnabled = isPropagationEnabled(true, "sqs"); - - kafkaClientPropagationEnabled = isPropagationEnabled(true, "kafka", "kafka.client"); - kafkaClientPropagationDisabledTopics = - tryMakeImmutableSet(configProvider.getList(KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS)); - kafkaClientBase64DecodingEnabled = - configProvider.getBoolean(KAFKA_CLIENT_BASE64_DECODING_ENABLED, false); - - jmsPropagationEnabled = isPropagationEnabled(true, "jms"); - jmsPropagationDisabledTopics = - tryMakeImmutableSet(configProvider.getList(JMS_PROPAGATION_DISABLED_TOPICS)); - jmsPropagationDisabledQueues = - tryMakeImmutableSet(configProvider.getList(JMS_PROPAGATION_DISABLED_QUEUES)); - jmsUnacknowledgedMaxAge = configProvider.getInteger(JMS_UNACKNOWLEDGED_MAX_AGE, 3600); - - rabbitPropagationEnabled = isPropagationEnabled(true, "rabbit", "rabbitmq"); - rabbitPropagationDisabledQueues = - tryMakeImmutableSet(configProvider.getList(RABBIT_PROPAGATION_DISABLED_QUEUES)); - rabbitPropagationDisabledExchanges = - tryMakeImmutableSet(configProvider.getList(RABBIT_PROPAGATION_DISABLED_EXCHANGES)); - rabbitIncludeRoutingKeyInResource = - configProvider.getBoolean(RABBIT_INCLUDE_ROUTINGKEY_IN_RESOURCE, true); - - messageBrokerSplitByDestination = - configProvider.getBoolean(MESSAGE_BROKER_SPLIT_BY_DESTINATION, false); - - grpcIgnoredInboundMethods = - tryMakeImmutableSet(configProvider.getList(GRPC_IGNORED_INBOUND_METHODS)); - final List tmpGrpcIgnoredOutboundMethods = new ArrayList<>(); - tmpGrpcIgnoredOutboundMethods.addAll(configProvider.getList(GRPC_IGNORED_OUTBOUND_METHODS)); - // When tracing shadowing will be possible we can instrument the stubs to silent tracing - // starting from interception points - if (InstrumenterConfig.get() - .isIntegrationEnabled(Collections.singleton("google-pubsub"), true)) { - tmpGrpcIgnoredOutboundMethods.addAll( - configProvider.getList( - GOOGLE_PUBSUB_IGNORED_GRPC_METHODS, - Arrays.asList( - "google.pubsub.v1.Subscriber/ModifyAckDeadline", - "google.pubsub.v1.Subscriber/Acknowledge", - "google.pubsub.v1.Subscriber/Pull", - "google.pubsub.v1.Subscriber/StreamingPull", - "google.pubsub.v1.Publisher/Publish"))); - } - grpcIgnoredOutboundMethods = tryMakeImmutableSet(tmpGrpcIgnoredOutboundMethods); - grpcServerTrimPackageResource = - configProvider.getBoolean(GRPC_SERVER_TRIM_PACKAGE_RESOURCE, false); - grpcServerErrorStatuses = - configProvider.getIntegerRange( - GRPC_SERVER_ERROR_STATUSES, DEFAULT_GRPC_SERVER_ERROR_STATUSES); - grpcClientErrorStatuses = - configProvider.getIntegerRange( - GRPC_CLIENT_ERROR_STATUSES, DEFAULT_GRPC_CLIENT_ERROR_STATUSES); - - hystrixTagsEnabled = configProvider.getBoolean(HYSTRIX_TAGS_ENABLED, false); - hystrixMeasuredEnabled = configProvider.getBoolean(HYSTRIX_MEASURED_ENABLED, false); - - igniteCacheIncludeKeys = configProvider.getBoolean(IGNITE_CACHE_INCLUDE_KEYS, false); - - obfuscationQueryRegexp = - configProvider.getString( - OBFUSCATION_QUERY_STRING_REGEXP, null, "obfuscation.query.string.regexp"); - - playReportHttpStatus = configProvider.getBoolean(PLAY_REPORT_HTTP_STATUS, false); - - servletPrincipalEnabled = configProvider.getBoolean(SERVLET_PRINCIPAL_ENABLED, false); - - xDatadogTagsMaxLength = - configProvider.getInteger( - TRACE_X_DATADOG_TAGS_MAX_LENGTH, DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH); - - servletAsyncTimeoutError = configProvider.getBoolean(SERVLET_ASYNC_TIMEOUT_ERROR, true); - - debugEnabled = configProvider.getBoolean(TRACE_DEBUG, false); - triageEnabled = configProvider.getBoolean(TRACE_TRIAGE, debugEnabled); // debug implies triage - - startupLogsEnabled = - configProvider.getBoolean(STARTUP_LOGS_ENABLED, DEFAULT_STARTUP_LOGS_ENABLED); - - cwsEnabled = configProvider.getBoolean(CWS_ENABLED, DEFAULT_CWS_ENABLED); - cwsTlsRefresh = configProvider.getInteger(CWS_TLS_REFRESH, DEFAULT_CWS_TLS_REFRESH); - - dataStreamsEnabled = - configProvider.getBoolean(DATA_STREAMS_ENABLED, DEFAULT_DATA_STREAMS_ENABLED); - dataStreamsBucketDurationSeconds = - configProvider.getFloat( - DATA_STREAMS_BUCKET_DURATION_SECONDS, DEFAULT_DATA_STREAMS_BUCKET_DURATION); - - azureAppServices = configProvider.getBoolean(AZURE_APP_SERVICES, false); - traceAgentPath = configProvider.getString(TRACE_AGENT_PATH); - String traceAgentArgsString = configProvider.getString(TRACE_AGENT_ARGS); - if (traceAgentArgsString == null) { - traceAgentArgs = Collections.emptyList(); - } else { - traceAgentArgs = - Collections.unmodifiableList( - new ArrayList<>(parseStringIntoSetOfNonEmptyStrings(traceAgentArgsString))); - } - - dogStatsDPath = configProvider.getString(DOGSTATSD_PATH); - String dogStatsDArgsString = configProvider.getString(DOGSTATSD_ARGS); - if (dogStatsDArgsString == null) { - dogStatsDArgs = Collections.emptyList(); - } else { - dogStatsDArgs = - Collections.unmodifiableList( - new ArrayList<>(parseStringIntoSetOfNonEmptyStrings(dogStatsDArgsString))); - } - - // Setting this last because we have a few places where this can come from - apiKey = tmpApiKey; - - boolean longRunningEnabled = - configProvider.getBoolean( - TracerConfig.TRACE_LONG_RUNNING_ENABLED, - ConfigDefaults.DEFAULT_TRACE_LONG_RUNNING_ENABLED); - long longRunningTraceFlushInterval = - configProvider.getLong( - TracerConfig.TRACE_LONG_RUNNING_FLUSH_INTERVAL, - ConfigDefaults.DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL); - - if (longRunningEnabled - && (longRunningTraceFlushInterval < 20 || longRunningTraceFlushInterval > 450)) { - log.warn( - "Provided long running trace flush interval of {} seconds. It should be between 20 seconds and 7.5 minutes." - + "Setting the flush interval to the default value of {} seconds .", - longRunningTraceFlushInterval, - DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL); - longRunningTraceFlushInterval = DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL; - } - longRunningTraceEnabled = longRunningEnabled; - this.longRunningTraceFlushInterval = longRunningTraceFlushInterval; - - this.sparkTaskHistogramEnabled = - configProvider.getBoolean( - SPARK_TASK_HISTOGRAM_ENABLED, ConfigDefaults.DEFAULT_SPARK_TASK_HISTOGRAM_ENABLED); - - this.jaxRsExceptionAsErrorsEnabled = - configProvider.getBoolean( - JAX_RS_EXCEPTION_AS_ERROR_ENABLED, - ConfigDefaults.DEFAULT_JAX_RS_EXCEPTION_AS_ERROR_ENABLED); - - this.traceFlushIntervalSeconds = - configProvider.getFloat( - TracerConfig.TRACE_FLUSH_INTERVAL, ConfigDefaults.DEFAULT_TRACE_FLUSH_INTERVAL); - if (profilingAgentless && apiKey == null) { - log.warn( - "Agentless profiling activated but no api key provided. Profile uploading will likely fail"); - } - - if (isCiVisibilityEnabled() - && ciVisibilityAgentlessEnabled - && (apiKey == null || apiKey.isEmpty())) { - throw new FatalAgentMisconfigurationError( - "Attempt to start in Agentless mode without API key. " - + "Please ensure that either an API key is configured, or the tracer is set up to work with the Agent"); - } - - this.telemetryDebugRequestsEnabled = - configProvider.getBoolean( - GeneralConfig.TELEMETRY_DEBUG_REQUESTS_ENABLED, - ConfigDefaults.DEFAULT_TELEMETRY_DEBUG_REQUESTS_ENABLED); - - timelineEventsEnabled = - configProvider.getBoolean( - ProfilingConfig.PROFILING_TIMELINE_EVENTS_ENABLED, - ProfilingConfig.PROFILING_TIMELINE_EVENTS_ENABLED_DEFAULT); - - log.debug("New instance: {}", this); - } - - /** - * Converts a list of packages in Jacoco exclusion format ({@code - * my.package.*,my.other.package.*}) to list of package prefixes suitable for use with ASM ({@code - * my/package/,my/other/package/}) - */ - private static String[] convertJacocoExclusionFormatToPackagePrefixes(List packages) { - return packages.stream() - .map(s -> (s.endsWith("*") ? s.substring(0, s.length() - 1) : s).replace('.', '/')) - .toArray(String[]::new); - } - - public ConfigProvider configProvider() { - return configProvider; - } - - public long getStartTimeMillis() { - return startTimeMillis; - } - - public String getRuntimeId() { - return runtimeIdEnabled ? RuntimeIdHolder.runtimeId : ""; - } - - public Long getProcessId() { - return PidHelper.getPidAsLong(); - } - - public String getRuntimeVersion() { - return runtimeVersion; - } - - public String getApiKey() { - return apiKey; - } - - public String getApplicationKey() { - return applicationKey; - } - - public String getSite() { - return site; - } - - public String getHostName() { - return HostNameHolder.hostName; - } - - public String getServiceName() { - return serviceName; - } - - public boolean isServiceNameSetByUser() { - return serviceNameSetByUser; - } - - public String getRootContextServiceName() { - return rootContextServiceName; - } - - public boolean isTraceEnabled() { - return instrumenterConfig.isTraceEnabled(); - } - - public boolean isLongRunningTraceEnabled() { - return longRunningTraceEnabled; - } - - public long getLongRunningTraceFlushInterval() { - return longRunningTraceFlushInterval; - } - - public float getTraceFlushIntervalSeconds() { - return traceFlushIntervalSeconds; - } - - public boolean isIntegrationSynapseLegacyOperationName() { - return integrationSynapseLegacyOperationName; - } - - public String getWriterType() { - return writerType; - } - - public boolean isInjectBaggageAsTagsEnabled() { - return injectBaggageAsTagsEnabled; - } - - public boolean isAgentConfiguredUsingDefault() { - return agentConfiguredUsingDefault; - } - - public String getAgentUrl() { - return agentUrl; - } - - public String getAgentHost() { - return agentHost; - } - - public int getAgentPort() { - return agentPort; - } - - public String getAgentUnixDomainSocket() { - return agentUnixDomainSocket; - } + OBFUSCATION_QUERY_STRING_REGEXP, null, "obfuscation.query.string.regexp"); + + playReportHttpStatus = configProvider.getBoolean(PLAY_REPORT_HTTP_STATUS, false); + + servletPrincipalEnabled = configProvider.getBoolean(SERVLET_PRINCIPAL_ENABLED, false); - public String getAgentNamedPipe() { - return agentNamedPipe; - } + xDatadogTagsMaxLength = + configProvider.getInteger( + TRACE_X_DATADOG_TAGS_MAX_LENGTH, DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH); - public int getAgentTimeout() { - return agentTimeout; - } + servletAsyncTimeoutError = configProvider.getBoolean(SERVLET_ASYNC_TIMEOUT_ERROR, true); - public Set getNoProxyHosts() { - return noProxyHosts; - } + debugEnabled = configProvider.getBoolean(TRACE_DEBUG, false); + triageEnabled = configProvider.getBoolean(TRACE_TRIAGE, debugEnabled); // debug implies triage - public boolean isPrioritySamplingEnabled() { - return prioritySamplingEnabled; - } + startupLogsEnabled = + configProvider.getBoolean(STARTUP_LOGS_ENABLED, DEFAULT_STARTUP_LOGS_ENABLED); - public String getPrioritySamplingForce() { - return prioritySamplingForce; - } + cwsEnabled = configProvider.getBoolean(CWS_ENABLED, DEFAULT_CWS_ENABLED); + cwsTlsRefresh = configProvider.getInteger(CWS_TLS_REFRESH, DEFAULT_CWS_TLS_REFRESH); + + dataStreamsEnabled = + configProvider.getBoolean(DATA_STREAMS_ENABLED, DEFAULT_DATA_STREAMS_ENABLED); + dataStreamsBucketDurationSeconds = + configProvider.getFloat( + DATA_STREAMS_BUCKET_DURATION_SECONDS, DEFAULT_DATA_STREAMS_BUCKET_DURATION); + + azureAppServices = configProvider.getBoolean(AZURE_APP_SERVICES, false); + traceAgentPath = configProvider.getString(TRACE_AGENT_PATH); + String traceAgentArgsString = configProvider.getString(TRACE_AGENT_ARGS); + if (traceAgentArgsString == null) { + traceAgentArgs = Collections.emptyList(); + } else { + traceAgentArgs = + Collections.unmodifiableList( + new ArrayList<>(parseStringIntoSetOfNonEmptyStrings(traceAgentArgsString))); + } + + dogStatsDPath = configProvider.getString(DOGSTATSD_PATH); + String dogStatsDArgsString = configProvider.getString(DOGSTATSD_ARGS); + if (dogStatsDArgsString == null) { + dogStatsDArgs = Collections.emptyList(); + } else { + dogStatsDArgs = + Collections.unmodifiableList( + new ArrayList<>(parseStringIntoSetOfNonEmptyStrings(dogStatsDArgsString))); + } + + // Setting this last because we have a few places where this can come from + apiKey = tmpApiKey; + + boolean longRunningEnabled = + configProvider.getBoolean( + TracerConfig.TRACE_LONG_RUNNING_ENABLED, + DEFAULT_TRACE_LONG_RUNNING_ENABLED); + long longRunningTraceFlushInterval = + configProvider.getLong( + TracerConfig.TRACE_LONG_RUNNING_FLUSH_INTERVAL, + DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL); + + if (longRunningEnabled + && (longRunningTraceFlushInterval < 20 || longRunningTraceFlushInterval > 450)) { + log.warn( + "Provided long running trace flush interval of {} seconds. It should be between 20 seconds and 7.5 minutes." + + "Setting the flush interval to the default value of {} seconds .", + longRunningTraceFlushInterval, + DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL); + longRunningTraceFlushInterval = DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL; + } + longRunningTraceEnabled = longRunningEnabled; + this.longRunningTraceFlushInterval = longRunningTraceFlushInterval; + + this.sparkTaskHistogramEnabled = + configProvider.getBoolean( + SPARK_TASK_HISTOGRAM_ENABLED, DEFAULT_SPARK_TASK_HISTOGRAM_ENABLED); + + this.jaxRsExceptionAsErrorsEnabled = + configProvider.getBoolean( + JAX_RS_EXCEPTION_AS_ERROR_ENABLED, + DEFAULT_JAX_RS_EXCEPTION_AS_ERROR_ENABLED); + + this.traceFlushIntervalSeconds = + configProvider.getFloat( + TracerConfig.TRACE_FLUSH_INTERVAL, DEFAULT_TRACE_FLUSH_INTERVAL); + if (profilingAgentless && apiKey == null) { + log.warn( + "Agentless profiling activated but no api key provided. Profile uploading will likely fail"); + } - public boolean isTraceResolverEnabled() { - return traceResolverEnabled; - } + if (isCiVisibilityEnabled() + && ciVisibilityAgentlessEnabled + && (apiKey == null || apiKey.isEmpty())) { + throw new FatalAgentMisconfigurationError( + "Attempt to start in Agentless mode without API key. " + + "Please ensure that either an API key is configured, or the tracer is set up to work with the Agent"); + } - public Set getIastWeakHashAlgorithms() { - return iastWeakHashAlgorithms; - } + this.telemetryDebugRequestsEnabled = + configProvider.getBoolean( + GeneralConfig.TELEMETRY_DEBUG_REQUESTS_ENABLED, + DEFAULT_TELEMETRY_DEBUG_REQUESTS_ENABLED); - public Pattern getIastWeakCipherAlgorithms() { - return iastWeakCipherAlgorithms; - } + timelineEventsEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_TIMELINE_EVENTS_ENABLED, + ProfilingConfig.PROFILING_TIMELINE_EVENTS_ENABLED_DEFAULT); - public boolean isIastDeduplicationEnabled() { - return iastDeduplicationEnabled; - } + log.debug("New instance: {}", this); + } - public int getSpanAttributeSchemaVersion() { - return spanAttributeSchemaVersion; - } + /** + * Converts a list of packages in Jacoco exclusion format ({@code + * my.package.*,my.other.package.*}) to list of package prefixes suitable for use with ASM ({@code + * my/package/,my/other/package/}) + */ + private static String[] convertJacocoExclusionFormatToPackagePrefixes(List packages) { + return packages.stream() + .map(s -> (s.endsWith("*") ? s.substring(0, s.length() - 1) : s).replace('.', '/')) + .toArray(String[]::new); + } - public boolean isPeerServiceDefaultsEnabled() { - return peerServiceDefaultsEnabled; - } + public ConfigProvider configProvider() { + return configProvider; + } - public Map getPeerServiceComponentOverrides() { - return peerServiceComponentOverrides; - } + public long getStartTimeMillis() { + return startTimeMillis; + } - public boolean isRemoveIntegrationServiceNamesEnabled() { - return removeIntegrationServiceNamesEnabled; - } + public String getRuntimeId() { + return runtimeIdEnabled ? RuntimeIdHolder.runtimeId : ""; + } - public Map getPeerServiceMapping() { - return peerServiceMapping; - } + public Long getProcessId() { + return PidHelper.getPidAsLong(); + } - public Map getServiceMapping() { - return serviceMapping; - } + public String getRuntimeVersion() { + return runtimeVersion; + } - public Map getRequestHeaderTags() { - return requestHeaderTags; - } + public String getApiKey() { + return apiKey; + } - public Map getResponseHeaderTags() { - return responseHeaderTags; - } + public String getApplicationKey() { + return applicationKey; + } - public boolean isRequestHeaderTagsCommaAllowed() { - return requestHeaderTagsCommaAllowed; - } + public String getSite() { + return site; + } - public Map getBaggageMapping() { - return baggageMapping; - } + public String getHostName() { + return HostNameHolder.hostName; + } - public Map getHttpServerPathResourceNameMapping() { - return httpServerPathResourceNameMapping; - } + public String getServiceName() { + return serviceName; + } - public Map getHttpClientPathResourceNameMapping() { - return httpClientPathResourceNameMapping; - } + public boolean isServiceNameSetByUser() { + return serviceNameSetByUser; + } - public boolean getHttpResourceRemoveTrailingSlash() { - return httpResourceRemoveTrailingSlash; - } + public String getRootContextServiceName() { + return rootContextServiceName; + } - public BitSet getHttpServerErrorStatuses() { - return httpServerErrorStatuses; - } + public boolean isTraceEnabled() { + return instrumenterConfig.isTraceEnabled(); + } - public BitSet getHttpClientErrorStatuses() { - return httpClientErrorStatuses; - } + public boolean isLongRunningTraceEnabled() { + return longRunningTraceEnabled; + } - public boolean isHttpServerTagQueryString() { - return httpServerTagQueryString; - } + public long getLongRunningTraceFlushInterval() { + return longRunningTraceFlushInterval; + } - public boolean isHttpServerRawQueryString() { - return httpServerRawQueryString; - } + public float getTraceFlushIntervalSeconds() { + return traceFlushIntervalSeconds; + } - public boolean isHttpServerRawResource() { - return httpServerRawResource; - } + public boolean isIntegrationSynapseLegacyOperationName() { + return integrationSynapseLegacyOperationName; + } - public boolean isHttpServerDecodedResourcePreserveSpaces() { - return httpServerDecodedResourcePreserveSpaces; - } + public String getWriterType() { + return writerType; + } - public boolean isHttpServerRouteBasedNaming() { - return httpServerRouteBasedNaming; - } + public boolean isInjectBaggageAsTagsEnabled() { + return injectBaggageAsTagsEnabled; + } - public boolean isHttpClientTagQueryString() { - return httpClientTagQueryString; - } + public boolean isAgentConfiguredUsingDefault() { + return agentConfiguredUsingDefault; + } - public boolean isHttpClientTagHeaders() { - return httpClientTagHeaders; - } + public String getAgentUrl() { + return agentUrl; + } - public boolean isHttpClientSplitByDomain() { - return httpClientSplitByDomain; - } + public String getAgentHost() { + return agentHost; + } - public boolean isDbClientSplitByInstance() { - return dbClientSplitByInstance; - } + public int getAgentPort() { + return agentPort; + } - public boolean isDbClientSplitByInstanceTypeSuffix() { - return dbClientSplitByInstanceTypeSuffix; - } + public String getAgentUnixDomainSocket() { + return agentUnixDomainSocket; + } - public boolean isDbClientSplitByHost() { - return dbClientSplitByHost; - } + public String getAgentNamedPipe() { + return agentNamedPipe; + } - public Set getSplitByTags() { - return splitByTags; - } + public int getAgentTimeout() { + return agentTimeout; + } - public int getScopeDepthLimit() { - return scopeDepthLimit; - } + public Set getNoProxyHosts() { + return noProxyHosts; + } - public boolean isScopeStrictMode() { - return scopeStrictMode; - } + public boolean isPrioritySamplingEnabled() { + return prioritySamplingEnabled; + } - public boolean isScopeInheritAsyncPropagation() { - return scopeInheritAsyncPropagation; - } + public String getPrioritySamplingForce() { + return prioritySamplingForce; + } - public int getScopeIterationKeepAlive() { - return scopeIterationKeepAlive; - } + public boolean isTraceResolverEnabled() { + return traceResolverEnabled; + } - public int getPartialFlushMinSpans() { - return partialFlushMinSpans; - } + public Set getIastWeakHashAlgorithms() { + return iastWeakHashAlgorithms; + } - public boolean isTraceStrictWritesEnabled() { - return traceStrictWritesEnabled; - } + public Pattern getIastWeakCipherAlgorithms() { + return iastWeakCipherAlgorithms; + } - public boolean isLogExtractHeaderNames() { - return logExtractHeaderNames; - } + public boolean isIastDeduplicationEnabled() { + return iastDeduplicationEnabled; + } - @Deprecated - public Set getPropagationStylesToExtract() { - return propagationStylesToExtract; - } - - @Deprecated - public Set getPropagationStylesToInject() { - return propagationStylesToInject; - } + public int getSpanAttributeSchemaVersion() { + return spanAttributeSchemaVersion; + } - public boolean isTracePropagationStyleB3PaddingEnabled() { - return tracePropagationStyleB3PaddingEnabled; - } + public boolean isPeerServiceDefaultsEnabled() { + return peerServiceDefaultsEnabled; + } - public Set getTracePropagationStylesToExtract() { - return tracePropagationStylesToExtract; - } + public Map getPeerServiceComponentOverrides() { + return peerServiceComponentOverrides; + } - public Set getTracePropagationStylesToInject() { - return tracePropagationStylesToInject; - } + public boolean isRemoveIntegrationServiceNamesEnabled() { + return removeIntegrationServiceNamesEnabled; + } - public boolean isTracePropagationExtractFirst() { - return tracePropagationExtractFirst; - } + public Map getPeerServiceMapping() { + return peerServiceMapping; + } - public int getClockSyncPeriod() { - return clockSyncPeriod; - } + public Map getServiceMapping() { + return serviceMapping; + } - public String getDogStatsDNamedPipe() { - return dogStatsDNamedPipe; - } + public Map getRequestHeaderTags() { + return requestHeaderTags; + } - public int getDogStatsDStartDelay() { - return dogStatsDStartDelay; - } + public Map getResponseHeaderTags() { + return responseHeaderTags; + } - public Integer getStatsDClientQueueSize() { - return statsDClientQueueSize; - } + public boolean isRequestHeaderTagsCommaAllowed() { + return requestHeaderTagsCommaAllowed; + } - public Integer getStatsDClientSocketBuffer() { - return statsDClientSocketBuffer; - } + public Map getBaggageMapping() { + return baggageMapping; + } - public Integer getStatsDClientSocketTimeout() { - return statsDClientSocketTimeout; - } - - public boolean isRuntimeMetricsEnabled() { - return runtimeMetricsEnabled; - } - - public boolean isJmxFetchEnabled() { - return jmxFetchEnabled; - } - - public String getJmxFetchConfigDir() { - return jmxFetchConfigDir; - } - - public List getJmxFetchConfigs() { - return jmxFetchConfigs; - } - - public List getJmxFetchMetricsConfigs() { - return jmxFetchMetricsConfigs; - } - - public Integer getJmxFetchCheckPeriod() { - return jmxFetchCheckPeriod; - } - - public Integer getJmxFetchRefreshBeansPeriod() { - return jmxFetchRefreshBeansPeriod; - } - - public Integer getJmxFetchInitialRefreshBeansPeriod() { - return jmxFetchInitialRefreshBeansPeriod; - } - - public String getJmxFetchStatsdHost() { - return jmxFetchStatsdHost; - } - - public Integer getJmxFetchStatsdPort() { - return jmxFetchStatsdPort; - } - - public boolean isJmxFetchMultipleRuntimeServicesEnabled() { - return jmxFetchMultipleRuntimeServicesEnabled; - } - - public int getJmxFetchMultipleRuntimeServicesLimit() { - return jmxFetchMultipleRuntimeServicesLimit; - } - - public boolean isHealthMetricsEnabled() { - return healthMetricsEnabled; - } - - public String getHealthMetricsStatsdHost() { - return healthMetricsStatsdHost; - } - - public Integer getHealthMetricsStatsdPort() { - return healthMetricsStatsdPort; - } + public Map getHttpServerPathResourceNameMapping() { + return httpServerPathResourceNameMapping; + } - public boolean isPerfMetricsEnabled() { - return perfMetricsEnabled; - } + public Map getHttpClientPathResourceNameMapping() { + return httpClientPathResourceNameMapping; + } - public boolean isTracerMetricsEnabled() { - return tracerMetricsEnabled; - } + public boolean getHttpResourceRemoveTrailingSlash() { + return httpResourceRemoveTrailingSlash; + } - public boolean isTracerMetricsBufferingEnabled() { - return tracerMetricsBufferingEnabled; - } + public BitSet getHttpServerErrorStatuses() { + return httpServerErrorStatuses; + } - public int getTracerMetricsMaxAggregates() { - return tracerMetricsMaxAggregates; - } + public BitSet getHttpClientErrorStatuses() { + return httpClientErrorStatuses; + } - public int getTracerMetricsMaxPending() { - return tracerMetricsMaxPending; - } + public boolean isHttpServerTagQueryString() { + return httpServerTagQueryString; + } - public boolean isLogsInjectionEnabled() { - return logsInjectionEnabled; - } + public boolean isHttpServerRawQueryString() { + return httpServerRawQueryString; + } - public boolean isReportHostName() { - return reportHostName; - } + public boolean isHttpServerRawResource() { + return httpServerRawResource; + } - public boolean isTraceAnalyticsEnabled() { - return traceAnalyticsEnabled; - } + public boolean isHttpServerDecodedResourcePreserveSpaces() { + return httpServerDecodedResourcePreserveSpaces; + } - public String getTraceClientIpHeader() { - return traceClientIpHeader; - } + public boolean isHttpServerRouteBasedNaming() { + return httpServerRouteBasedNaming; + } - // whether to collect headers and run the client ip resolution (also requires appsec to be enabled - // or clientIpEnabled) - public boolean isTraceClientIpResolverEnabled() { - return traceClientIpResolverEnabled; - } - - public boolean isTraceGitMetadataEnabled() { - return traceGitMetadataEnabled; - } - - public Map getTraceSamplingServiceRules() { - return traceSamplingServiceRules; - } - - public Map getTraceSamplingOperationRules() { - return traceSamplingOperationRules; - } - - public String getTraceSamplingRules() { - return traceSamplingRules; - } - - public Double getTraceSampleRate() { - return traceSampleRate; - } - - public int getTraceRateLimit() { - return traceRateLimit; - } - - public String getSpanSamplingRules() { - return spanSamplingRules; - } - - public String getSpanSamplingRulesFile() { - return spanSamplingRulesFile; - } - - public boolean isProfilingEnabled() { - if (Platform.isNativeImage()) { - if (!instrumenterConfig.isProfilingEnabled() && profilingEnabled) { - log.warn( - "Profiling was not enabled during the native image build. " - + "Please set DD_PROFILING_ENABLED=true in your native image build configuration if you want" - + "to use profiling."); - } - } - return profilingEnabled && instrumenterConfig.isProfilingEnabled(); - } - - public boolean isProfilingTimelineEventsEnabled() { - return timelineEventsEnabled; - } - - public boolean isProfilingAgentless() { - return profilingAgentless; - } - - public int getProfilingStartDelay() { - return profilingStartDelay; - } - - public boolean isProfilingStartForceFirst() { - return profilingStartForceFirst; - } - - public int getProfilingUploadPeriod() { - return profilingUploadPeriod; - } - - public String getProfilingTemplateOverrideFile() { - return profilingTemplateOverrideFile; - } - - public int getProfilingUploadTimeout() { - return profilingUploadTimeout; - } - - public String getProfilingUploadCompression() { - return profilingUploadCompression; - } - - public String getProfilingProxyHost() { - return profilingProxyHost; - } - - public int getProfilingProxyPort() { - return profilingProxyPort; - } - - public String getProfilingProxyUsername() { - return profilingProxyUsername; - } - - public String getProfilingProxyPassword() { - return profilingProxyPassword; - } - - public int getProfilingExceptionSampleLimit() { - return profilingExceptionSampleLimit; - } - - public int getProfilingDirectAllocationSampleLimit() { - return profilingDirectAllocationSampleLimit; - } - - public int getProfilingExceptionHistogramTopItems() { - return profilingExceptionHistogramTopItems; - } - - public int getProfilingExceptionHistogramMaxCollectionSize() { - return profilingExceptionHistogramMaxCollectionSize; - } - - public boolean isProfilingExcludeAgentThreads() { - return profilingExcludeAgentThreads; - } - - public boolean isProfilingUploadSummaryOn413Enabled() { - return profilingUploadSummaryOn413Enabled; - } - - public boolean isProfilingRecordExceptionMessage() { - return profilingRecordExceptionMessage; - } - - public boolean isDatadogProfilerEnabled() { - return isDatadogProfilerEnabled; - } - - public static boolean isDatadogProfilerEnablementOverridden() { - // old non-LTS versions without important backports - // also, we have no windows binaries - return Platform.isWindows() - || Platform.isJavaVersion(18) - || Platform.isJavaVersion(16) - || Platform.isJavaVersion(15) - || Platform.isJavaVersion(14) - || Platform.isJavaVersion(13) - || Platform.isJavaVersion(12) - || Platform.isJavaVersion(10) - || Platform.isJavaVersion(9); - } - - public static boolean isDatadogProfilerSafeInCurrentEnvironment() { - // don't want to put this logic (which will evolve) in the public ProfilingConfig, and can't - // access Platform there - if (!Platform.isJ9() && Platform.isJavaVersion(8)) { - String arch = System.getProperty("os.arch"); - if ("aarch64".equalsIgnoreCase(arch) || "arm64".equalsIgnoreCase(arch)) { - return false; - } - } - if (Platform.isGraalVM()) { - // let's be conservative about GraalVM and require opt-in from the users - return false; - } - boolean result = - Platform.isJ9() - || !Platform.isJavaVersion(18) // missing AGCT fixes - || Platform.isJavaVersionAtLeast(17, 0, 5) - || (Platform.isJavaVersion(11) && Platform.isJavaVersionAtLeast(11, 0, 17)) - || (Platform.isJavaVersion(8) && Platform.isJavaVersionAtLeast(8, 0, 352)); - - if (result && Platform.isJ9()) { - // Semeru JDK 11 and JDK 17 have problems with unloaded classes and jmethodids, leading to JVM - // crash - // The ASGCT based profilers are only activated in JDK 11.0.18+ and JDK 17.0.6+ - result &= - !((Platform.isJavaVersion(11) && Platform.isJavaVersionAtLeast(11, 0, 18)) - || ((Platform.isJavaVersion(17) && Platform.isJavaVersionAtLeast(17, 0, 6)))); - } - return result; - } - - public boolean isCrashTrackingAgentless() { - return crashTrackingAgentless; - } - - public boolean isTelemetryEnabled() { - return instrumenterConfig.isTelemetryEnabled(); - } - - public float getTelemetryHeartbeatInterval() { - return telemetryHeartbeatInterval; - } - - public long getTelemetryExtendedHeartbeatInterval() { - return telemetryExtendedHeartbeatInterval; - } - - public float getTelemetryMetricsInterval() { - return telemetryMetricsInterval; - } - - public boolean isTelemetryDependencyServiceEnabled() { - return isTelemetryDependencyServiceEnabled; - } - - public boolean isTelemetryMetricsEnabled() { - return telemetryMetricsEnabled; - } - - public boolean isTelemetryLogCollectionEnabled() { - return isTelemetryLogCollectionEnabled; - } - - public boolean isClientIpEnabled() { - return clientIpEnabled; - } - - public ProductActivation getAppSecActivation() { - return instrumenterConfig.getAppSecActivation(); - } - - public boolean isAppSecReportingInband() { - return appSecReportingInband; - } - - public int getAppSecReportMinTimeout() { - return appSecReportMinTimeout; - } - - public int getAppSecReportMaxTimeout() { - return appSecReportMaxTimeout; - } - - public int getAppSecTraceRateLimit() { - return appSecTraceRateLimit; - } - - public boolean isAppSecWafMetrics() { - return appSecWafMetrics; - } - - // in microseconds - public int getAppSecWafTimeout() { - return appSecWafTimeout; - } - - public String getAppSecObfuscationParameterKeyRegexp() { - return appSecObfuscationParameterKeyRegexp; - } - - public String getAppSecObfuscationParameterValueRegexp() { - return appSecObfuscationParameterValueRegexp; - } - - public String getAppSecHttpBlockedTemplateHtml() { - return appSecHttpBlockedTemplateHtml; - } - - public String getAppSecHttpBlockedTemplateJson() { - return appSecHttpBlockedTemplateJson; - } - - public UserEventTrackingMode getAppSecUserEventsTrackingMode() { - return appSecUserEventsTracking; - } - - public boolean isApiSecurityEnabled() { - return apiSecurityEnabled; - } + public boolean isHttpClientTagQueryString() { + return httpClientTagQueryString; + } - public float getApiSecurityRequestSampleRate() { - return apiSecurityRequestSampleRate; - } + public boolean isHttpClientTagHeaders() { + return httpClientTagHeaders; + } - public ProductActivation getIastActivation() { - return instrumenterConfig.getIastActivation(); - } + public boolean isHttpClientSplitByDomain() { + return httpClientSplitByDomain; + } - public boolean isIastDebugEnabled() { - return iastDebugEnabled; - } + public boolean isDbClientSplitByInstance() { + return dbClientSplitByInstance; + } - public int getIastMaxConcurrentRequests() { - return iastMaxConcurrentRequests; - } + public boolean isDbClientSplitByInstanceTypeSuffix() { + return dbClientSplitByInstanceTypeSuffix; + } - public int getIastVulnerabilitiesPerRequest() { - return iastVulnerabilitiesPerRequest; - } + public boolean isDbClientSplitByHost() { + return dbClientSplitByHost; + } - public float getIastRequestSampling() { - return iastRequestSampling; - } + public Set getSplitByTags() { + return splitByTags; + } - public Verbosity getIastTelemetryVerbosity() { - return isTelemetryEnabled() ? iastTelemetryVerbosity : Verbosity.OFF; - } + public int getScopeDepthLimit() { + return scopeDepthLimit; + } - public boolean isIastRedactionEnabled() { - return iastRedactionEnabled; - } + public boolean isScopeStrictMode() { + return scopeStrictMode; + } - public String getIastRedactionNamePattern() { - return iastRedactionNamePattern; - } + public boolean isScopeInheritAsyncPropagation() { + return scopeInheritAsyncPropagation; + } - public String getIastRedactionValuePattern() { - return iastRedactionValuePattern; - } + public int getScopeIterationKeepAlive() { + return scopeIterationKeepAlive; + } - public int getIastTruncationMaxValueLength() { - return iastTruncationMaxValueLength; - } + public int getPartialFlushMinSpans() { + return partialFlushMinSpans; + } - public int getIastMaxRangeCount() { - return iastMaxRangeCount; - } + public boolean isTraceStrictWritesEnabled() { + return traceStrictWritesEnabled; + } - public boolean isIastStacktraceLeakSuppress() { - return iastStacktraceLeakSuppress; - } + public boolean isLogExtractHeaderNames() { + return logExtractHeaderNames; + } - public boolean isCiVisibilityEnabled() { - return instrumenterConfig.isCiVisibilityEnabled(); - } + @Deprecated + public Set getPropagationStylesToExtract() { + return propagationStylesToExtract; + } - public boolean isUsmEnabled() { - return instrumenterConfig.isUsmEnabled(); - } + @Deprecated + public Set getPropagationStylesToInject() { + return propagationStylesToInject; + } - public boolean isCiVisibilityTraceSanitationEnabled() { - return ciVisibilityTraceSanitationEnabled; - } + public boolean isTracePropagationStyleB3PaddingEnabled() { + return tracePropagationStyleB3PaddingEnabled; + } - public boolean isCiVisibilityAgentlessEnabled() { - return ciVisibilityAgentlessEnabled; - } + public Set getTracePropagationStylesToExtract() { + return tracePropagationStylesToExtract; + } - public String getCiVisibilityAgentlessUrl() { - return ciVisibilityAgentlessUrl; - } + public Set getTracePropagationStylesToInject() { + return tracePropagationStylesToInject; + } - public boolean isCiVisibilitySourceDataEnabled() { - return ciVisibilitySourceDataEnabled; - } + public boolean isTracePropagationExtractFirst() { + return tracePropagationExtractFirst; + } - public boolean isCiVisibilitySourceDataRootCheckEnabled() { - return ciVisibilitySourceDataRootCheckEnabled; - } + public int getClockSyncPeriod() { + return clockSyncPeriod; + } - public boolean isCiVisibilityBuildInstrumentationEnabled() { - return ciVisibilityBuildInstrumentationEnabled; - } + public String getDogStatsDNamedPipe() { + return dogStatsDNamedPipe; + } - public Long getCiVisibilitySessionId() { - return ciVisibilitySessionId; - } + public int getDogStatsDStartDelay() { + return dogStatsDStartDelay; + } - public Long getCiVisibilityModuleId() { - return ciVisibilityModuleId; - } + public Integer getStatsDClientQueueSize() { + return statsDClientQueueSize; + } - public String getCiVisibilityAgentJarUri() { - return ciVisibilityAgentJarUri; - } + public Integer getStatsDClientSocketBuffer() { + return statsDClientSocketBuffer; + } - public File getCiVisibilityAgentJarFile() { - if (ciVisibilityAgentJarUri == null || ciVisibilityAgentJarUri.isEmpty()) { - throw new IllegalArgumentException("Agent JAR URI is not set in config"); + public Integer getStatsDClientSocketTimeout() { + return statsDClientSocketTimeout; } - try { - URI agentJarUri = new URI(ciVisibilityAgentJarUri); - return new File(agentJarUri); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Malformed agent JAR URI: " + ciVisibilityAgentJarUri, e); + public boolean isRuntimeMetricsEnabled() { + return runtimeMetricsEnabled; } - } - public boolean isCiVisibilityAutoConfigurationEnabled() { - return ciVisibilityAutoConfigurationEnabled; - } + public boolean isJmxFetchEnabled() { + return jmxFetchEnabled; + } - public String getCiVisibilityAdditionalChildProcessJvmArgs() { - return ciVisibilityAdditionalChildProcessJvmArgs; - } + public String getJmxFetchConfigDir() { + return jmxFetchConfigDir; + } - public boolean isCiVisibilityCompilerPluginAutoConfigurationEnabled() { - return ciVisibilityCompilerPluginAutoConfigurationEnabled; - } + public List getJmxFetchConfigs() { + return jmxFetchConfigs; + } - public boolean isCiVisibilityCodeCoverageEnabled() { - return ciVisibilityCodeCoverageEnabled; - } + public List getJmxFetchMetricsConfigs() { + return jmxFetchMetricsConfigs; + } - public boolean isCiVisibilityCodeCoveragePercentageCalculationEnabled() { - return ciVisibilityCodeCoveragePercentageCalculationEnabled; - } + public Integer getJmxFetchCheckPeriod() { + return jmxFetchCheckPeriod; + } - public String getCiVisibilityCodeCoverageReportDumpDir() { - return ciVisibilityCodeCoverageReportDumpDir; - } + public Integer getJmxFetchRefreshBeansPeriod() { + return jmxFetchRefreshBeansPeriod; + } - public String getCiVisibilityCompilerPluginVersion() { - return ciVisibilityCompilerPluginVersion; - } + public Integer getJmxFetchInitialRefreshBeansPeriod() { + return jmxFetchInitialRefreshBeansPeriod; + } - public String getCiVisibilityJacocoPluginVersion() { - return ciVisibilityJacocoPluginVersion; - } + public String getJmxFetchStatsdHost() { + return jmxFetchStatsdHost; + } - public boolean isCiVisibilityJacocoPluginVersionProvided() { - return ciVisibilityJacocoPluginVersionProvided; - } + public Integer getJmxFetchStatsdPort() { + return jmxFetchStatsdPort; + } - public List getCiVisibilityCodeCoverageIncludes() { - return ciVisibilityCodeCoverageIncludes; - } + public boolean isJmxFetchMultipleRuntimeServicesEnabled() { + return jmxFetchMultipleRuntimeServicesEnabled; + } - public List getCiVisibilityCodeCoverageExcludes() { - return ciVisibilityCodeCoverageExcludes; - } + public int getJmxFetchMultipleRuntimeServicesLimit() { + return jmxFetchMultipleRuntimeServicesLimit; + } - public String[] getCiVisibilityCodeCoverageIncludedPackages() { - return ciVisibilityCodeCoverageIncludedPackages; - } + public boolean isHealthMetricsEnabled() { + return healthMetricsEnabled; + } - public String[] getCiVisibilityCodeCoverageExcludedPackages() { - return ciVisibilityCodeCoverageExcludedPackages; - } + public String getHealthMetricsStatsdHost() { + return healthMetricsStatsdHost; + } - public List getCiVisibilityJacocoGradleSourceSets() { - return ciVisibilityJacocoGradleSourceSets; - } + public Integer getHealthMetricsStatsdPort() { + return healthMetricsStatsdPort; + } - public Integer getCiVisibilityDebugPort() { - return ciVisibilityDebugPort; - } + public boolean isPerfMetricsEnabled() { + return perfMetricsEnabled; + } - public boolean isCiVisibilityGitUploadEnabled() { - return ciVisibilityGitUploadEnabled; - } + public boolean isTracerMetricsEnabled() { + return tracerMetricsEnabled; + } - public boolean isCiVisibilityGitUnshallowEnabled() { - return ciVisibilityGitUnshallowEnabled; - } + public boolean isTracerMetricsBufferingEnabled() { + return tracerMetricsBufferingEnabled; + } - public boolean isCiVisibilityGitUnshallowDefer() { - return ciVisibilityGitUnshallowDefer; - } + public int getTracerMetricsMaxAggregates() { + return tracerMetricsMaxAggregates; + } - public long getCiVisibilityGitCommandTimeoutMillis() { - return ciVisibilityGitCommandTimeoutMillis; - } + public int getTracerMetricsMaxPending() { + return tracerMetricsMaxPending; + } - public long getCiVisibilityBackendApiTimeoutMillis() { - return ciVisibilityBackendApiTimeoutMillis; - } + public boolean isLogsInjectionEnabled() { + return logsInjectionEnabled; + } - public long getCiVisibilityGitUploadTimeoutMillis() { - return ciVisibilityGitUploadTimeoutMillis; - } + public boolean isReportHostName() { + return reportHostName; + } - public String getCiVisibilityGitRemoteName() { - return ciVisibilityGitRemoteName; - } + public boolean isTraceAnalyticsEnabled() { + return traceAnalyticsEnabled; + } - public int getCiVisibilitySignalServerPort() { - return ciVisibilitySignalServerPort; - } + public String getTraceClientIpHeader() { + return traceClientIpHeader; + } - public String getCiVisibilitySignalServerHost() { - return ciVisibilitySignalServerHost; - } + // whether to collect headers and run the client ip resolution (also requires appsec to be enabled + // or clientIpEnabled) + public boolean isTraceClientIpResolverEnabled() { + return traceClientIpResolverEnabled; + } - public boolean isCiVisibilityItrEnabled() { - return ciVisibilityItrEnabled; - } + public boolean isTraceGitMetadataEnabled() { + return traceGitMetadataEnabled; + } - public boolean isCiVisibilityCiProviderIntegrationEnabled() { - return ciVisibilityCiProviderIntegrationEnabled; - } + public Map getTraceSamplingServiceRules() { + return traceSamplingServiceRules; + } - public boolean isCiVisibilityRepoIndexSharingEnabled() { - return ciVisibilityRepoIndexSharingEnabled; - } + public Map getTraceSamplingOperationRules() { + return traceSamplingOperationRules; + } - public int getCiVisibilityModuleExecutionSettingsCacheSize() { - return ciVisibilityModuleExecutionSettingsCacheSize; - } + public String getTraceSamplingRules() { + return traceSamplingRules; + } - public int getCiVisibilityJvmInfoCacheSize() { - return ciVisibilityJvmInfoCacheSize; - } + public Double getTraceSampleRate() { + return traceSampleRate; + } - public boolean isCiVisibilityCoverageSegmentsEnabled() { - return ciVisibilityCoverageSegmentsEnabled; - } + public int getTraceRateLimit() { + return traceRateLimit; + } - public int getCiVisibilityCoverageRootPackagesLimit() { - return ciVisibilityCoverageRootPackagesLimit; - } + public String getSpanSamplingRules() { + return spanSamplingRules; + } - public String getCiVisibilityInjectedTracerVersion() { - return ciVisibilityInjectedTracerVersion; - } + public String getSpanSamplingRulesFile() { + return spanSamplingRulesFile; + } - public List getCiVisibilityResourceFolderNames() { - return ciVisibilityResourceFolderNames; - } + public boolean isProfilingEnabled() { + if (Platform.isNativeImage()) { + if (!instrumenterConfig.isProfilingEnabled() && profilingEnabled) { + log.warn( + "Profiling was not enabled during the native image build. " + + "Please set DD_PROFILING_ENABLED=true in your native image build configuration if you want" + + "to use profiling."); + } + } + return profilingEnabled && instrumenterConfig.isProfilingEnabled(); + } - public boolean isCiVisibilityFlakyRetryEnabled() { - return ciVisibilityFlakyRetryEnabled; - } + public boolean isProfilingTimelineEventsEnabled() { + return timelineEventsEnabled; + } - public int getCiVisibilityFlakyRetryCount() { - return ciVisibilityFlakyRetryCount; - } + public boolean isProfilingAgentless() { + return profilingAgentless; + } - public String getCiVisibilityModuleName() { - return ciVisibilityModuleName; - } + public int getProfilingStartDelay() { + return profilingStartDelay; + } - public String getAppSecRulesFile() { - return appSecRulesFile; - } + public boolean isProfilingStartForceFirst() { + return profilingStartForceFirst; + } - public long getRemoteConfigMaxPayloadSizeBytes() { - return remoteConfigMaxPayloadSize; - } + public int getProfilingUploadPeriod() { + return profilingUploadPeriod; + } - public boolean isRemoteConfigEnabled() { - return remoteConfigEnabled; - } + public String getProfilingTemplateOverrideFile() { + return profilingTemplateOverrideFile; + } - public boolean isRemoteConfigIntegrityCheckEnabled() { - return remoteConfigIntegrityCheckEnabled; - } + public int getProfilingUploadTimeout() { + return profilingUploadTimeout; + } - public String getFinalRemoteConfigUrl() { - return remoteConfigUrl; - } + public String getProfilingUploadCompression() { + return profilingUploadCompression; + } - public float getRemoteConfigPollIntervalSeconds() { - return remoteConfigPollIntervalSeconds; - } + public String getProfilingProxyHost() { + return profilingProxyHost; + } - public String getRemoteConfigTargetsKeyId() { - return remoteConfigTargetsKeyId; - } + public int getProfilingProxyPort() { + return profilingProxyPort; + } - public String getRemoteConfigTargetsKey() { - return remoteConfigTargetsKey; - } + public String getProfilingProxyUsername() { + return profilingProxyUsername; + } - public boolean isDebuggerEnabled() { - return debuggerEnabled; - } + public String getProfilingProxyPassword() { + return profilingProxyPassword; + } - public int getDebuggerUploadTimeout() { - return debuggerUploadTimeout; - } + public int getProfilingExceptionSampleLimit() { + return profilingExceptionSampleLimit; + } - public int getDebuggerUploadFlushInterval() { - return debuggerUploadFlushInterval; - } + public int getProfilingDirectAllocationSampleLimit() { + return profilingDirectAllocationSampleLimit; + } - public boolean isDebuggerClassFileDumpEnabled() { - return debuggerClassFileDumpEnabled; - } + public int getProfilingExceptionHistogramTopItems() { + return profilingExceptionHistogramTopItems; + } - public int getDebuggerPollInterval() { - return debuggerPollInterval; - } + public int getProfilingExceptionHistogramMaxCollectionSize() { + return profilingExceptionHistogramMaxCollectionSize; + } - public int getDebuggerDiagnosticsInterval() { - return debuggerDiagnosticsInterval; - } + public boolean isProfilingExcludeAgentThreads() { + return profilingExcludeAgentThreads; + } - public boolean isDebuggerMetricsEnabled() { - return debuggerMetricEnabled; - } + public boolean isProfilingUploadSummaryOn413Enabled() { + return profilingUploadSummaryOn413Enabled; + } - public int getDebuggerUploadBatchSize() { - return debuggerUploadBatchSize; - } + public boolean isProfilingRecordExceptionMessage() { + return profilingRecordExceptionMessage; + } - public long getDebuggerMaxPayloadSize() { - return debuggerMaxPayloadSize; - } - - public boolean isDebuggerVerifyByteCode() { - return debuggerVerifyByteCode; - } - - public boolean isDebuggerInstrumentTheWorld() { - return debuggerInstrumentTheWorld; - } - - public String getDebuggerExcludeFiles() { - return debuggerExcludeFiles; - } - - public int getDebuggerCaptureTimeout() { - return debuggerCaptureTimeout; - } - - public boolean isDebuggerSymbolEnabled() { - return debuggerSymbolEnabled; - } - - public boolean isDebuggerSymbolForceUpload() { - return debuggerSymbolForceUpload; - } - - public String getDebuggerSymbolIncludes() { - return debuggerSymbolIncludes; - } - - public int getDebuggerSymbolFlushThreshold() { - return debuggerSymbolFlushThreshold; - } - - public String getFinalDebuggerProbeUrl() { - // by default poll from datadog agent - return "http://" + agentHost + ":" + agentPort; - } - - public String getFinalDebuggerSnapshotUrl() { - // by default send to datadog agent - return agentUrl + "/debugger/v1/input"; - } - - public String getFinalDebuggerSymDBUrl() { - return agentUrl + "/symdb/v1/input"; - } - - public String getDebuggerProbeFileLocation() { - return debuggerProbeFileLocation; - } - - public String getDebuggerRedactedIdentifiers() { - return debuggerRedactedIdentifiers; - } - - public String getDebuggerRedactedTypes() { - return debuggerRedactedTypes; - } - - public boolean isAwsPropagationEnabled() { - return awsPropagationEnabled; - } - - public boolean isSqsPropagationEnabled() { - return sqsPropagationEnabled; - } - - public boolean isKafkaClientPropagationEnabled() { - return kafkaClientPropagationEnabled; - } - - public boolean isKafkaClientPropagationDisabledForTopic(String topic) { - return null != topic && kafkaClientPropagationDisabledTopics.contains(topic); - } - - public boolean isJmsPropagationEnabled() { - return jmsPropagationEnabled; - } - - public boolean isJmsPropagationDisabledForDestination(final String queueOrTopic) { - return null != queueOrTopic - && (jmsPropagationDisabledQueues.contains(queueOrTopic) - || jmsPropagationDisabledTopics.contains(queueOrTopic)); - } - - public int getJmsUnacknowledgedMaxAge() { - return jmsUnacknowledgedMaxAge; - } - - public boolean isKafkaClientBase64DecodingEnabled() { - return kafkaClientBase64DecodingEnabled; - } - - public boolean isRabbitPropagationEnabled() { - return rabbitPropagationEnabled; - } - - public boolean isRabbitPropagationDisabledForDestination(final String queueOrExchange) { - return null != queueOrExchange - && (rabbitPropagationDisabledQueues.contains(queueOrExchange) - || rabbitPropagationDisabledExchanges.contains(queueOrExchange)); - } - - public boolean isRabbitIncludeRoutingKeyInResource() { - return rabbitIncludeRoutingKeyInResource; - } - - public boolean isMessageBrokerSplitByDestination() { - return messageBrokerSplitByDestination; - } - - public boolean isHystrixTagsEnabled() { - return hystrixTagsEnabled; - } - - public boolean isHystrixMeasuredEnabled() { - return hystrixMeasuredEnabled; - } - - public boolean isIgniteCacheIncludeKeys() { - return igniteCacheIncludeKeys; - } - - public String getObfuscationQueryRegexp() { - return obfuscationQueryRegexp; - } - - public boolean getPlayReportHttpStatus() { - return playReportHttpStatus; - } - - public boolean isServletPrincipalEnabled() { - return servletPrincipalEnabled; - } - - public boolean isSpringDataRepositoryInterfaceResourceName() { - return springDataRepositoryInterfaceResourceName; - } - - public int getxDatadogTagsMaxLength() { - return xDatadogTagsMaxLength; - } - - public boolean isServletAsyncTimeoutError() { - return servletAsyncTimeoutError; - } - - public boolean isTraceAgentV05Enabled() { - return traceAgentV05Enabled; - } - - public boolean isDebugEnabled() { - return debugEnabled; - } - - public boolean isTriageEnabled() { - return triageEnabled; - } - - public boolean isStartupLogsEnabled() { - return startupLogsEnabled; - } - - public boolean isCwsEnabled() { - return cwsEnabled; - } - - public int getCwsTlsRefresh() { - return cwsTlsRefresh; - } - - public boolean isAzureAppServices() { - return azureAppServices; - } - - public boolean isDataStreamsEnabled() { - return dataStreamsEnabled; - } + public boolean isDatadogProfilerEnabled() { + return isDatadogProfilerEnabled; + } - public float getDataStreamsBucketDurationSeconds() { - return dataStreamsBucketDurationSeconds; - } + public static boolean isDatadogProfilerEnablementOverridden() { + // old non-LTS versions without important backports + // also, we have no windows binaries + return Platform.isWindows() + || Platform.isJavaVersion(18) + || Platform.isJavaVersion(16) + || Platform.isJavaVersion(15) + || Platform.isJavaVersion(14) + || Platform.isJavaVersion(13) + || Platform.isJavaVersion(12) + || Platform.isJavaVersion(10) + || Platform.isJavaVersion(9); + } - public long getDataStreamsBucketDurationNanoseconds() { - // Rounds to the nearest millisecond before converting to nanos - int milliseconds = Math.round(dataStreamsBucketDurationSeconds * 1000); - return TimeUnit.MILLISECONDS.toNanos(milliseconds); - } - - public String getTraceAgentPath() { - return traceAgentPath; - } - - public List getTraceAgentArgs() { - return traceAgentArgs; - } - - public String getDogStatsDPath() { - return dogStatsDPath; - } - - public List getDogStatsDArgs() { - return dogStatsDArgs; - } - - public String getConfigFileStatus() { - return configFileStatus; - } - - public IdGenerationStrategy getIdGenerationStrategy() { - return idGenerationStrategy; - } - - public boolean isTrace128bitTraceIdGenerationEnabled() { - return trace128bitTraceIdGenerationEnabled; - } - - public Set getGrpcIgnoredInboundMethods() { - return grpcIgnoredInboundMethods; - } - - public Set getGrpcIgnoredOutboundMethods() { - return grpcIgnoredOutboundMethods; - } - - public boolean isGrpcServerTrimPackageResource() { - return grpcServerTrimPackageResource; - } - - public BitSet getGrpcServerErrorStatuses() { - return grpcServerErrorStatuses; - } - - public BitSet getGrpcClientErrorStatuses() { - return grpcClientErrorStatuses; - } - - public boolean isElasticsearchBodyEnabled() { - return elasticsearchBodyEnabled; - } - - public boolean isElasticsearchParamsEnabled() { - return elasticsearchParamsEnabled; - } - - public boolean isElasticsearchBodyAndParamsEnabled() { - return elasticsearchBodyAndParamsEnabled; - } - - public boolean isSparkTaskHistogramEnabled() { - return sparkTaskHistogramEnabled; - } - - public boolean isJaxRsExceptionAsErrorEnabled() { - return jaxRsExceptionAsErrorsEnabled; - } - - /** @return A map of tags to be applied only to the local application root span. */ - public Map getLocalRootSpanTags() { - final Map runtimeTags = getRuntimeTags(); - final Map result = new HashMap<>(runtimeTags.size() + 2); - result.putAll(runtimeTags); - result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE); - result.put(SCHEMA_VERSION_TAG_KEY, SpanNaming.instance().version()); - result.put(PROFILING_ENABLED, isProfilingEnabled() ? 1 : 0); - - if (reportHostName) { - final String hostName = getHostName(); - if (null != hostName && !hostName.isEmpty()) { - result.put(INTERNAL_HOST_NAME, hostName); - } - } - - if (azureAppServices) { - result.putAll(getAzureAppServicesTags()); - } - - result.putAll(getProcessIdTag()); - - return Collections.unmodifiableMap(result); - } - - public WellKnownTags getWellKnownTags() { - return new WellKnownTags( - getRuntimeId(), - reportHostName ? getHostName() : "", - getEnv(), - serviceName, - getVersion(), - LANGUAGE_TAG_VALUE); - } - - public String getPrimaryTag() { - return primaryTag; - } - - public Set getMetricsIgnoredResources() { - return tryMakeImmutableSet(configProvider.getList(TRACER_METRICS_IGNORED_RESOURCES)); - } - - public String getEnv() { - // intentionally not thread safe - if (env == null) { - env = getMergedSpanTags().get("env"); - if (env == null) { - env = ""; - } - } - - return env; - } - - public String getVersion() { - // intentionally not thread safe - if (version == null) { - version = getMergedSpanTags().get("version"); - if (version == null) { - version = ""; - } - } - - return version; - } - - public Map getMergedSpanTags() { - // Do not include runtimeId into span tags: we only want that added to the root span - final Map result = newHashMap(getGlobalTags().size() + spanTags.size()); - result.putAll(getGlobalTags()); - result.putAll(spanTags); - return Collections.unmodifiableMap(result); - } - - public Map getMergedJmxTags() { - final Map runtimeTags = getRuntimeTags(); - final Map result = - newHashMap( - getGlobalTags().size() + jmxTags.size() + runtimeTags.size() + 1 /* for serviceName */); - result.putAll(getGlobalTags()); - result.putAll(jmxTags); - result.putAll(runtimeTags); - // service name set here instead of getRuntimeTags because apm already manages the service tag - // and may chose to override it. - // Additionally, infra/JMX metrics require `service` rather than APM's `service.name` tag - result.put(SERVICE_TAG, serviceName); - return Collections.unmodifiableMap(result); - } - - public Map getMergedProfilingTags() { - final Map runtimeTags = getRuntimeTags(); - final String host = getHostName(); - final Map result = - newHashMap( - getGlobalTags().size() - + profilingTags.size() - + runtimeTags.size() - + 4 /* for serviceName and host and language and runtime_version */); - result.put(HOST_TAG, host); // Host goes first to allow to override it - result.putAll(getGlobalTags()); - result.putAll(profilingTags); - result.putAll(runtimeTags); - // service name set here instead of getRuntimeTags because apm already manages the service tag - // and may chose to override it. - result.put(SERVICE_TAG, serviceName); - result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE); - result.put(RUNTIME_VERSION_TAG, runtimeVersion); - return Collections.unmodifiableMap(result); - } - - public Map getMergedCrashTrackingTags() { - final Map runtimeTags = getRuntimeTags(); - final String host = getHostName(); - final Map result = - newHashMap( - getGlobalTags().size() - + crashTrackingTags.size() - + runtimeTags.size() - + 3 /* for serviceName and host and language */); - result.put(HOST_TAG, host); // Host goes first to allow to override it - result.putAll(getGlobalTags()); - result.putAll(crashTrackingTags); - result.putAll(runtimeTags); - // service name set here instead of getRuntimeTags because apm already manages the service tag - // and may chose to override it. - result.put(SERVICE_TAG, serviceName); - result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE); - return Collections.unmodifiableMap(result); - } - - /** - * Returns the sample rate for the specified instrumentation or {@link - * ConfigDefaults#DEFAULT_ANALYTICS_SAMPLE_RATE} if none specified. - */ - public float getInstrumentationAnalyticsSampleRate(final String... aliases) { - for (final String alias : aliases) { - final String configKey = alias + ".analytics.sample-rate"; - final Float rate = configProvider.getFloat("trace." + configKey, configKey); - if (null != rate) { - return rate; - } - } - return DEFAULT_ANALYTICS_SAMPLE_RATE; - } - - /** - * Provide 'global' tags, i.e. tags set everywhere. We have to support old (dd.trace.global.tags) - * version of this setting if new (dd.tags) version has not been specified. - */ - public Map getGlobalTags() { - return tags; - } - - /** - * Return a map of tags required by the datadog backend to link runtime metrics (i.e. jmx) and - * traces. - * - *

    These tags must be applied to every runtime metrics and placed on the root span of every - * trace. - * - * @return A map of tag-name -> tag-value - */ - private Map getRuntimeTags() { - return Collections.singletonMap(RUNTIME_ID_TAG, getRuntimeId()); - } - - private Map getProcessIdTag() { - return Collections.singletonMap(PID_TAG, getProcessId()); - } - - private Map getAzureAppServicesTags() { - // These variable names and derivations are copied from the dotnet tracer - // See - // https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/src/Datadog.Trace/PlatformHelpers/AzureAppServices.cs - // and - // https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/src/Datadog.Trace/TraceContext.cs#L207 - Map aasTags = new HashMap<>(); - - /// The site name of the site instance in Azure where the traced application is running. - String siteName = getEnv("WEBSITE_SITE_NAME"); - if (siteName != null) { - aasTags.put("aas.site.name", siteName); - } - - // The kind of application instance running in Azure. - // Possible values: app, api, mobileapp, app_linux, app_linux_container, functionapp, - // functionapp_linux, functionapp_linux_container - - // The type of application instance running in Azure. - // Possible values: app, function - if (getEnv("FUNCTIONS_WORKER_RUNTIME") != null - || getEnv("FUNCTIONS_EXTENSIONS_VERSION") != null) { - aasTags.put("aas.site.kind", "functionapp"); - aasTags.put("aas.site.type", "function"); - } else { - aasTags.put("aas.site.kind", "app"); - aasTags.put("aas.site.type", "app"); - } - - // The resource group of the site instance in Azure App Services - String resourceGroup = getEnv("WEBSITE_RESOURCE_GROUP"); - if (resourceGroup != null) { - aasTags.put("aas.resource.group", resourceGroup); - } - - // Example: 8c500027-5f00-400e-8f00-60000000000f+apm-dotnet-EastUSwebspace - // Format: {subscriptionId}+{planResourceGroup}-{hostedInRegion} - String websiteOwner = getEnv("WEBSITE_OWNER_NAME"); - int plusIndex = websiteOwner == null ? -1 : websiteOwner.indexOf("+"); - - // The subscription ID of the site instance in Azure App Services - String subscriptionId = null; - if (plusIndex > 0) { - subscriptionId = websiteOwner.substring(0, plusIndex); - aasTags.put("aas.subscription.id", subscriptionId); - } - - if (subscriptionId != null && siteName != null && resourceGroup != null) { - // The resource ID of the site instance in Azure App Services - String resourceId = - "/subscriptions/" - + subscriptionId - + "/resourcegroups/" - + resourceGroup - + "/providers/microsoft.web/sites/" - + siteName; - resourceId = resourceId.toLowerCase(Locale.ROOT); - aasTags.put("aas.resource.id", resourceId); - } else { - log.warn( - "Unable to generate resource id subscription id: {}, site name: {}, resource group {}", - subscriptionId, - siteName, - resourceGroup); - } - - // The instance ID in Azure - String instanceId = getEnv("WEBSITE_INSTANCE_ID"); - instanceId = instanceId == null ? "unknown" : instanceId; - aasTags.put("aas.environment.instance_id", instanceId); - - // The instance name in Azure - String instanceName = getEnv("COMPUTERNAME"); - instanceName = instanceName == null ? "unknown" : instanceName; - aasTags.put("aas.environment.instance_name", instanceName); - - // The operating system in Azure - String operatingSystem = getEnv("WEBSITE_OS"); - operatingSystem = operatingSystem == null ? "unknown" : operatingSystem; - aasTags.put("aas.environment.os", operatingSystem); - - // The version of the extension installed - String siteExtensionVersion = getEnv("DD_AAS_JAVA_EXTENSION_VERSION"); - siteExtensionVersion = siteExtensionVersion == null ? "unknown" : siteExtensionVersion; - aasTags.put("aas.environment.extension_version", siteExtensionVersion); - - aasTags.put("aas.environment.runtime", getProp("java.vm.name", "unknown")); - - return aasTags; - } - - private int schemaVersionFromConfig() { - String versionStr = - configProvider.getString(TRACE_SPAN_ATTRIBUTE_SCHEMA, "v" + SpanNaming.SCHEMA_MIN_VERSION); - Matcher matcher = Pattern.compile("^v?(0|[1-9]\\d*)$").matcher(versionStr); - int parsedVersion = -1; - if (matcher.matches()) { - parsedVersion = Integer.parseInt(matcher.group(1)); - } - if (parsedVersion < SpanNaming.SCHEMA_MIN_VERSION - || parsedVersion > SpanNaming.SCHEMA_MAX_VERSION) { - log.warn( - "Invalid attribute schema version {} invalid or out of range [v{}, v{}]. Defaulting to v{}", - versionStr, - SpanNaming.SCHEMA_MIN_VERSION, - SpanNaming.SCHEMA_MAX_VERSION, - SpanNaming.SCHEMA_MIN_VERSION); - parsedVersion = SpanNaming.SCHEMA_MIN_VERSION; - } - return parsedVersion; - } - - public String getFinalProfilingUrl() { - if (profilingUrl != null) { - // when profilingUrl is set we use it regardless of apiKey/agentless config - return profilingUrl; - } else if (profilingAgentless) { - // when agentless profiling is turned on we send directly to our intake - return "https://intake.profile." + site + "/api/v2/profile"; - } else { - // when profilingUrl and agentless are not set we send to the dd trace agent running locally - return "http://" + agentHost + ":" + agentPort + "/profiling/v1/input"; - } - } - - public String getFinalCrashTrackingTelemetryUrl() { - if (crashTrackingAgentless) { - // when agentless crashTracking is turned on we send directly to our intake - return "https://all-http-intake.logs." + site + "/api/v2/apmtelemetry"; - } else { - // when agentless are not set we send to the dd trace agent running locally - return "http://" + agentHost + ":" + agentPort + "/telemetry/proxy/api/v2/apmtelemetry"; - } - } - - public boolean isJmxFetchIntegrationEnabled( - final Iterable integrationNames, final boolean defaultEnabled) { - return configProvider.isEnabled(integrationNames, "jmxfetch.", ".enabled", defaultEnabled); - } - - public boolean isRuleEnabled(final String name) { - return isRuleEnabled(name, true); - } - - public boolean isRuleEnabled(final String name, boolean defaultEnabled) { - boolean enabled = configProvider.getBoolean("trace." + name + ".enabled", defaultEnabled); - boolean lowerEnabled = - configProvider.getBoolean( - "trace." + name.toLowerCase(Locale.ROOT) + ".enabled", defaultEnabled); - return defaultEnabled ? enabled && lowerEnabled : enabled || lowerEnabled; - } - - /** - * @param integrationNames - * @param defaultEnabled - * @return - * @deprecated This method should only be used internally. Use the instance getter instead {@link - * #isJmxFetchIntegrationEnabled(Iterable, boolean)}. - */ - public static boolean jmxFetchIntegrationEnabled( - final SortedSet integrationNames, final boolean defaultEnabled) { - return Config.get().isJmxFetchIntegrationEnabled(integrationNames, defaultEnabled); - } - - public boolean isEndToEndDurationEnabled( - final boolean defaultEnabled, final String... integrationNames) { - return configProvider.isEnabled( - Arrays.asList(integrationNames), "", ".e2e.duration.enabled", defaultEnabled); - } - - public boolean isPropagationEnabled( - final boolean defaultEnabled, final String... integrationNames) { - return configProvider.isEnabled( - Arrays.asList(integrationNames), "", ".propagation.enabled", defaultEnabled); - } - - public boolean isLegacyTracingEnabled( - final boolean defaultEnabled, final String... integrationNames) { - return SpanNaming.instance().namingSchema().allowInferredServices() - && configProvider.isEnabled( - Arrays.asList(integrationNames), "", ".legacy.tracing.enabled", defaultEnabled); - } - - public boolean isTimeInQueueEnabled( - final boolean defaultEnabled, final String... integrationNames) { - return SpanNaming.instance().namingSchema().allowInferredServices() - && configProvider.isEnabled( - Arrays.asList(integrationNames), "", ".time-in-queue.enabled", defaultEnabled); - } - - public boolean isEnabled( - final boolean defaultEnabled, final String settingName, String settingSuffix) { - return configProvider.isEnabled( - Collections.singletonList(settingName), "", settingSuffix, defaultEnabled); - } - - public String getDBMPropagationMode() { - return DBMPropagationMode; - } - - private void logIgnoredSettingWarning( - String setting, String overridingSetting, String overridingSuffix) { - log.warn( - "Setting {} ignored since {}{} is enabled.", - propertyNameToSystemPropertyName(setting), - propertyNameToSystemPropertyName(overridingSetting), - overridingSuffix); - } - - private void logOverriddenSettingWarning(String setting, String overridingSetting, Object value) { - log.warn( - "Setting {} is overridden by setting {} with value {}.", - propertyNameToSystemPropertyName(setting), - propertyNameToSystemPropertyName(overridingSetting), - value); - } - - private void logOverriddenDeprecatedSettingWarning( - String setting, String overridingSetting, Object value) { - log.warn( - "Setting {} is deprecated and overridden by setting {} with value {}.", - propertyNameToSystemPropertyName(setting), - propertyNameToSystemPropertyName(overridingSetting), - value); - } - - private void logDeprecatedConvertedSetting( - String deprecatedSetting, Object oldValue, String newSetting, Object newValue) { - log.warn( - "Setting {} is deprecated and the value {} has been converted to {} for setting {}.", - propertyNameToSystemPropertyName(deprecatedSetting), - oldValue, - newValue, - propertyNameToSystemPropertyName(newSetting)); - } - - public boolean isTraceAnalyticsIntegrationEnabled( - final SortedSet integrationNames, final boolean defaultEnabled) { - return configProvider.isEnabled(integrationNames, "", ".analytics.enabled", defaultEnabled); - } - - public boolean isTraceAnalyticsIntegrationEnabled( - final boolean defaultEnabled, final String... integrationNames) { - return configProvider.isEnabled( - Arrays.asList(integrationNames), "", ".analytics.enabled", defaultEnabled); - } - - public boolean isSamplingMechanismValidationDisabled() { - return configProvider.getBoolean(TracerConfig.SAMPLING_MECHANISM_VALIDATION_DISABLED, false); - } - - public > T getEnumValue( - final String name, final Class type, final T defaultValue) { - return configProvider.getEnum(name, type, defaultValue); - } - - /** - * @param integrationNames - * @param defaultEnabled - * @return - * @deprecated This method should only be used internally. Use the instance getter instead {@link - * #isTraceAnalyticsIntegrationEnabled(SortedSet, boolean)}. - */ - public static boolean traceAnalyticsIntegrationEnabled( - final SortedSet integrationNames, final boolean defaultEnabled) { - return Config.get().isTraceAnalyticsIntegrationEnabled(integrationNames, defaultEnabled); - } - - public boolean isTelemetryDebugRequestsEnabled() { - return telemetryDebugRequestsEnabled; - } - - private Set getSettingsSetFromEnvironment( - String name, Function mapper, boolean splitOnWS) { - final String value = configProvider.getString(name, ""); - return convertStringSetToSet( - name, parseStringIntoSetOfNonEmptyStrings(value, splitOnWS), mapper); - } - - private Set convertSettingsSet(Set fromSet, Function> mapper) { - if (fromSet.isEmpty()) { - return Collections.emptySet(); - } - Set result = new LinkedHashSet<>(fromSet.size()); - for (F from : fromSet) { - for (T to : mapper.apply(from)) { - result.add(to); - } - } - return Collections.unmodifiableSet(result); - } - - public static final String PREFIX = "dd."; - - /** - * Converts the property name, e.g. 'service.name' into a public system property name, e.g. - * `dd.service.name`. - * - * @param setting The setting name, e.g. `service.name` - * @return The public facing system property name - */ - @NonNull - private static String propertyNameToSystemPropertyName(final String setting) { - return PREFIX + setting; - } - - @NonNull - private static Map newHashMap(final int size) { - return new HashMap<>(size + 1, 1f); - } - - /** - * @param map - * @param propNames - * @return new unmodifiable copy of {@param map} where properties are overwritten from environment - */ - @NonNull - private Map getMapWithPropertiesDefinedByEnvironment( - @NonNull final Map map, @NonNull final String... propNames) { - final Map res = new HashMap<>(map); - for (final String propName : propNames) { - final String val = configProvider.getString(propName); - if (val != null) { - res.put(propName, val); - } - } - return Collections.unmodifiableMap(res); - } - - @NonNull - private static Set parseStringIntoSetOfNonEmptyStrings(final String str) { - return parseStringIntoSetOfNonEmptyStrings(str, true); - } - - @NonNull - private static Set parseStringIntoSetOfNonEmptyStrings( - final String str, boolean splitOnWS) { - // Using LinkedHashSet to preserve original string order - final Set result = new LinkedHashSet<>(); - // Java returns single value when splitting an empty string. We do not need that value, so - // we need to throw it out. - int start = 0; - int i = 0; - for (; i < str.length(); ++i) { - char c = str.charAt(i); - if (c == ',' || (splitOnWS && Character.isWhitespace(c))) { - if (i - start - 1 > 0) { - result.add(str.substring(start, i)); + public static boolean isDatadogProfilerSafeInCurrentEnvironment() { + // don't want to put this logic (which will evolve) in the public ProfilingConfig, and can't + // access Platform there + if (!Platform.isJ9() && Platform.isJavaVersion(8)) { + String arch = System.getProperty("os.arch"); + if ("aarch64".equalsIgnoreCase(arch) || "arm64".equalsIgnoreCase(arch)) { + return false; + } } - start = i + 1; - } - } - if (i - start - 1 > 0) { - result.add(str.substring(start)); - } - return Collections.unmodifiableSet(result); - } - - private static Set convertStringSetToSet( - String setting, final Set input, Function mapper) { - if (input.isEmpty()) { - return Collections.emptySet(); - } - // Using LinkedHashSet to preserve original string order - final Set result = new LinkedHashSet<>(); - for (final String value : input) { - try { - result.add(mapper.apply(value)); - } catch (final IllegalArgumentException e) { - log.warn( - "Cannot recognize config string value {} for setting {}", - value, - propertyNameToSystemPropertyName(setting)); - } - } - return Collections.unmodifiableSet(result); - } - - /** Returns the detected hostname. First tries locally, then using DNS */ - static String initHostName() { - String possibleHostname; - - // Try environment variable. This works in almost all environments - if (isWindowsOS()) { - possibleHostname = getEnv("COMPUTERNAME"); - } else { - possibleHostname = getEnv("HOSTNAME"); - } - - if (possibleHostname != null && !possibleHostname.isEmpty()) { - log.debug("Determined hostname from environment variable"); - return possibleHostname.trim(); - } - - // Try hostname files - final String[] hostNameFiles = new String[] {"/proc/sys/kernel/hostname", "/etc/hostname"}; - for (final String hostNameFile : hostNameFiles) { - try { - final Path hostNamePath = FileSystems.getDefault().getPath(hostNameFile); - if (Files.isRegularFile(hostNamePath)) { - byte[] bytes = Files.readAllBytes(hostNamePath); - possibleHostname = new String(bytes, StandardCharsets.ISO_8859_1); + if (Platform.isGraalVM()) { + // let's be conservative about GraalVM and require opt-in from the users + return false; + } + boolean result = + Platform.isJ9() + || !Platform.isJavaVersion(18) // missing AGCT fixes + || Platform.isJavaVersionAtLeast(17, 0, 5) + || (Platform.isJavaVersion(11) && Platform.isJavaVersionAtLeast(11, 0, 17)) + || (Platform.isJavaVersion(8) && Platform.isJavaVersionAtLeast(8, 0, 352)); + + if (result && Platform.isJ9()) { + // Semeru JDK 11 and JDK 17 have problems with unloaded classes and jmethodids, leading to JVM + // crash + // The ASGCT based profilers are only activated in JDK 11.0.18+ and JDK 17.0.6+ + result &= + !((Platform.isJavaVersion(11) && Platform.isJavaVersionAtLeast(11, 0, 18)) + || ((Platform.isJavaVersion(17) && Platform.isJavaVersionAtLeast(17, 0, 6)))); } - } catch (Throwable t) { - // Ignore - } - possibleHostname = Strings.trim(possibleHostname); - if (!possibleHostname.isEmpty()) { - log.debug("Determined hostname from file {}", hostNameFile); - return possibleHostname; - } - } - - // Try hostname command - try (final BufferedReader reader = - new BufferedReader( - new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))) { - possibleHostname = reader.readLine(); - } catch (final Throwable ignore) { - // Ignore. Hostname command is not always available - } - - if (possibleHostname != null && !possibleHostname.isEmpty()) { - log.debug("Determined hostname from hostname command"); - return possibleHostname.trim(); - } - - // From DNS - try { - return InetAddress.getLocalHost().getHostName(); - } catch (final UnknownHostException e) { - // If we are not able to detect the hostname we do not throw an exception. - } - - return null; - } - - private static boolean isWindowsOS() { - return getProp("os.name").startsWith("Windows"); - } - - private static String getEnv(String name) { - String value = System.getenv(name); - if (value != null) { - ConfigCollector.get().put(name, value, ConfigOrigin.ENV); - } - return value; - } - - private static Pattern getPattern(String defaultValue, String userValue) { - try { - if (userValue != null) { - return Pattern.compile(userValue); - } - } catch (Exception e) { - log.debug("Cannot create pattern from user value {}", userValue); - } - return Pattern.compile(defaultValue); - } - - private static String getProp(String name) { - return getProp(name, null); - } - - private static String getProp(String name, String def) { - String value = System.getProperty(name, def); - if (value != null) { - ConfigCollector.get().put(name, value, ConfigOrigin.JVM_PROP); - } - return value; - } - - // This has to be placed after all other static fields to give them a chance to initialize - - private static final Config INSTANCE = - new Config( - Platform.isNativeImageBuilder() - ? ConfigProvider.withoutCollector() - : ConfigProvider.getInstance(), - InstrumenterConfig.get()); - - public static Config get() { - return INSTANCE; - } - - /** - * This method is deprecated since the method of configuration will be changed in the future. The - * properties instance should instead be passed directly into the DDTracer builder: - * - *

    -   *   DDTracer.builder().withProperties(new Properties()).build()
    -   * 
    - * - *

    Config keys for use in Properties instance construction can be found in {@link - * GeneralConfig} and {@link TracerConfig}. - * - * @deprecated - */ - @Deprecated - public static Config get(final Properties properties) { - if (properties == null || properties.isEmpty()) { - return INSTANCE; - } else { - return new Config(ConfigProvider.withPropertiesOverride(properties)); - } - } - - @Override - public String toString() { - return "Config{" - + "instrumenterConfig=" - + instrumenterConfig - + ", runtimeId='" - + getRuntimeId() - + '\'' - + ", runtimeVersion='" - + runtimeVersion - + ", apiKey=" - + (apiKey == null ? "null" : "****") - + ", site='" - + site - + '\'' - + ", hostName='" - + getHostName() - + '\'' - + ", serviceName='" - + serviceName - + '\'' - + ", serviceNameSetByUser=" - + serviceNameSetByUser - + ", rootContextServiceName=" - + rootContextServiceName - + ", integrationSynapseLegacyOperationName=" - + integrationSynapseLegacyOperationName - + ", writerType='" - + writerType - + '\'' - + ", agentConfiguredUsingDefault=" - + agentConfiguredUsingDefault - + ", agentUrl='" - + agentUrl - + '\'' - + ", agentHost='" - + agentHost - + '\'' - + ", agentPort=" - + agentPort - + ", agentUnixDomainSocket='" - + agentUnixDomainSocket - + '\'' - + ", agentTimeout=" - + agentTimeout - + ", noProxyHosts=" - + noProxyHosts - + ", prioritySamplingEnabled=" - + prioritySamplingEnabled - + ", prioritySamplingForce='" - + prioritySamplingForce - + '\'' - + ", traceResolverEnabled=" - + traceResolverEnabled - + ", serviceMapping=" - + serviceMapping - + ", tags=" - + tags - + ", spanTags=" - + spanTags - + ", jmxTags=" - + jmxTags - + ", requestHeaderTags=" - + requestHeaderTags - + ", responseHeaderTags=" - + responseHeaderTags - + ", baggageMapping=" - + baggageMapping - + ", httpServerErrorStatuses=" - + httpServerErrorStatuses - + ", httpClientErrorStatuses=" - + httpClientErrorStatuses - + ", httpServerTagQueryString=" - + httpServerTagQueryString - + ", httpServerRawQueryString=" - + httpServerRawQueryString - + ", httpServerRawResource=" - + httpServerRawResource - + ", httpServerRouteBasedNaming=" - + httpServerRouteBasedNaming - + ", httpServerPathResourceNameMapping=" - + httpServerPathResourceNameMapping - + ", httpClientPathResourceNameMapping=" - + httpClientPathResourceNameMapping - + ", httpClientTagQueryString=" - + httpClientTagQueryString - + ", httpClientSplitByDomain=" - + httpClientSplitByDomain - + ", httpResourceRemoveTrailingSlash" - + httpResourceRemoveTrailingSlash - + ", dbClientSplitByInstance=" - + dbClientSplitByInstance - + ", dbClientSplitByInstanceTypeSuffix=" - + dbClientSplitByInstanceTypeSuffix - + ", dbClientSplitByHost=" - + dbClientSplitByHost - + ", DBMPropagationMode=" - + DBMPropagationMode - + ", splitByTags=" - + splitByTags - + ", scopeDepthLimit=" - + scopeDepthLimit - + ", scopeStrictMode=" - + scopeStrictMode - + ", scopeInheritAsyncPropagation=" - + scopeInheritAsyncPropagation - + ", scopeIterationKeepAlive=" - + scopeIterationKeepAlive - + ", partialFlushMinSpans=" - + partialFlushMinSpans - + ", traceStrictWritesEnabled=" - + traceStrictWritesEnabled - + ", tracePropagationStylesToExtract=" - + tracePropagationStylesToExtract - + ", tracePropagationStylesToInject=" - + tracePropagationStylesToInject - + ", tracePropagationExtractFirst=" - + tracePropagationExtractFirst - + ", clockSyncPeriod=" - + clockSyncPeriod - + ", jmxFetchEnabled=" - + jmxFetchEnabled - + ", dogStatsDStartDelay=" - + dogStatsDStartDelay - + ", jmxFetchConfigDir='" - + jmxFetchConfigDir - + '\'' - + ", jmxFetchConfigs=" - + jmxFetchConfigs - + ", jmxFetchMetricsConfigs=" - + jmxFetchMetricsConfigs - + ", jmxFetchCheckPeriod=" - + jmxFetchCheckPeriod - + ", jmxFetchInitialRefreshBeansPeriod=" - + jmxFetchInitialRefreshBeansPeriod - + ", jmxFetchRefreshBeansPeriod=" - + jmxFetchRefreshBeansPeriod - + ", jmxFetchStatsdHost='" - + jmxFetchStatsdHost - + '\'' - + ", jmxFetchStatsdPort=" - + jmxFetchStatsdPort - + ", jmxFetchMultipleRuntimeServicesEnabled=" - + jmxFetchMultipleRuntimeServicesEnabled - + ", jmxFetchMultipleRuntimeServicesLimit=" - + jmxFetchMultipleRuntimeServicesLimit - + ", healthMetricsEnabled=" - + healthMetricsEnabled - + ", healthMetricsStatsdHost='" - + healthMetricsStatsdHost - + '\'' - + ", healthMetricsStatsdPort=" - + healthMetricsStatsdPort - + ", perfMetricsEnabled=" - + perfMetricsEnabled - + ", tracerMetricsEnabled=" - + tracerMetricsEnabled - + ", tracerMetricsBufferingEnabled=" - + tracerMetricsBufferingEnabled - + ", tracerMetricsMaxAggregates=" - + tracerMetricsMaxAggregates - + ", tracerMetricsMaxPending=" - + tracerMetricsMaxPending - + ", reportHostName=" - + reportHostName - + ", traceAnalyticsEnabled=" - + traceAnalyticsEnabled - + ", traceSamplingServiceRules=" - + traceSamplingServiceRules - + ", traceSamplingOperationRules=" - + traceSamplingOperationRules - + ", traceSamplingJsonRules=" - + traceSamplingRules - + ", traceSampleRate=" - + traceSampleRate - + ", traceRateLimit=" - + traceRateLimit - + ", spanSamplingRules=" - + spanSamplingRules - + ", spanSamplingRulesFile=" - + spanSamplingRulesFile - + ", profilingAgentless=" - + profilingAgentless - + ", profilingUrl='" - + profilingUrl - + '\'' - + ", profilingTags=" - + profilingTags - + ", profilingStartDelay=" - + profilingStartDelay - + ", profilingStartForceFirst=" - + profilingStartForceFirst - + ", profilingUploadPeriod=" - + profilingUploadPeriod - + ", profilingTemplateOverrideFile='" - + profilingTemplateOverrideFile - + '\'' - + ", profilingUploadTimeout=" - + profilingUploadTimeout - + ", profilingUploadCompression='" - + profilingUploadCompression - + '\'' - + ", profilingProxyHost='" - + profilingProxyHost - + '\'' - + ", profilingProxyPort=" - + profilingProxyPort - + ", profilingProxyUsername='" - + profilingProxyUsername - + '\'' - + ", profilingProxyPassword=" - + (profilingProxyPassword == null ? "null" : "****") - + ", profilingExceptionSampleLimit=" - + profilingExceptionSampleLimit - + ", profilingExceptionHistogramTopItems=" - + profilingExceptionHistogramTopItems - + ", profilingExceptionHistogramMaxCollectionSize=" - + profilingExceptionHistogramMaxCollectionSize - + ", profilingExcludeAgentThreads=" - + profilingExcludeAgentThreads - + ", crashTrackingTags=" - + crashTrackingTags - + ", crashTrackingAgentless=" - + crashTrackingAgentless - + ", remoteConfigEnabled=" - + remoteConfigEnabled - + ", remoteConfigUrl=" - + remoteConfigUrl - + ", remoteConfigPollIntervalSeconds=" - + remoteConfigPollIntervalSeconds - + ", remoteConfigMaxPayloadSize=" - + remoteConfigMaxPayloadSize - + ", remoteConfigIntegrityCheckEnabled=" - + remoteConfigIntegrityCheckEnabled - + ", debuggerEnabled=" - + debuggerEnabled - + ", debuggerUploadTimeout=" - + debuggerUploadTimeout - + ", debuggerUploadFlushInterval=" - + debuggerUploadFlushInterval - + ", debuggerClassFileDumpEnabled=" - + debuggerClassFileDumpEnabled - + ", debuggerPollInterval=" - + debuggerPollInterval - + ", debuggerDiagnosticsInterval=" - + debuggerDiagnosticsInterval - + ", debuggerMetricEnabled=" - + debuggerMetricEnabled - + ", debuggerProbeFileLocation=" - + debuggerProbeFileLocation - + ", debuggerUploadBatchSize=" - + debuggerUploadBatchSize - + ", debuggerMaxPayloadSize=" - + debuggerMaxPayloadSize - + ", debuggerVerifyByteCode=" - + debuggerVerifyByteCode - + ", debuggerInstrumentTheWorld=" - + debuggerInstrumentTheWorld - + ", debuggerExcludeFile=" - + debuggerExcludeFiles - + ", awsPropagationEnabled=" - + awsPropagationEnabled - + ", sqsPropagationEnabled=" - + sqsPropagationEnabled - + ", kafkaClientPropagationEnabled=" - + kafkaClientPropagationEnabled - + ", kafkaClientPropagationDisabledTopics=" - + kafkaClientPropagationDisabledTopics - + ", kafkaClientBase64DecodingEnabled=" - + kafkaClientBase64DecodingEnabled - + ", jmsPropagationEnabled=" - + jmsPropagationEnabled - + ", jmsPropagationDisabledTopics=" - + jmsPropagationDisabledTopics - + ", jmsPropagationDisabledQueues=" - + jmsPropagationDisabledQueues - + ", rabbitPropagationEnabled=" - + rabbitPropagationEnabled - + ", rabbitPropagationDisabledQueues=" - + rabbitPropagationDisabledQueues - + ", rabbitPropagationDisabledExchanges=" - + rabbitPropagationDisabledExchanges - + ", messageBrokerSplitByDestination=" - + messageBrokerSplitByDestination - + ", hystrixTagsEnabled=" - + hystrixTagsEnabled - + ", hystrixMeasuredEnabled=" - + hystrixMeasuredEnabled - + ", igniteCacheIncludeKeys=" - + igniteCacheIncludeKeys - + ", servletPrincipalEnabled=" - + servletPrincipalEnabled - + ", servletAsyncTimeoutError=" - + servletAsyncTimeoutError - + ", datadogTagsLimit=" - + xDatadogTagsMaxLength - + ", traceAgentV05Enabled=" - + traceAgentV05Enabled - + ", debugEnabled=" - + debugEnabled - + ", triageEnabled=" - + triageEnabled - + ", startLogsEnabled=" - + startupLogsEnabled - + ", configFile='" - + configFileStatus - + '\'' - + ", idGenerationStrategy=" - + idGenerationStrategy - + ", trace128bitTraceIdGenerationEnabled=" - + trace128bitTraceIdGenerationEnabled - + ", grpcIgnoredInboundMethods=" - + grpcIgnoredInboundMethods - + ", grpcIgnoredOutboundMethods=" - + grpcIgnoredOutboundMethods - + ", grpcServerErrorStatuses=" - + grpcServerErrorStatuses - + ", grpcClientErrorStatuses=" - + grpcClientErrorStatuses - + ", clientIpEnabled=" - + clientIpEnabled - + ", appSecReportingInband=" - + appSecReportingInband - + ", appSecRulesFile='" - + appSecRulesFile - + "'" - + ", appSecHttpBlockedTemplateHtml=" - + appSecHttpBlockedTemplateHtml - + ", appSecWafTimeout=" - + appSecWafTimeout - + " us, appSecHttpBlockedTemplateJson=" - + appSecHttpBlockedTemplateJson - + ", apiSecurityEnabled=" - + apiSecurityEnabled - + ", apiSecurityRequestSampleRate=" - + apiSecurityRequestSampleRate - + ", cwsEnabled=" - + cwsEnabled - + ", cwsTlsRefresh=" - + cwsTlsRefresh - + ", longRunningTraceEnabled=" - + longRunningTraceEnabled - + ", longRunningTraceFlushInterval=" - + longRunningTraceFlushInterval - + ", elasticsearchBodyEnabled=" - + elasticsearchBodyEnabled - + ", elasticsearchParamsEnabled=" - + elasticsearchParamsEnabled - + ", elasticsearchBodyAndParamsEnabled=" - + elasticsearchBodyAndParamsEnabled - + ", traceFlushInterval=" - + traceFlushIntervalSeconds - + ", injectBaggageAsTagsEnabled=" - + injectBaggageAsTagsEnabled - + ", logsInjectionEnabled=" - + logsInjectionEnabled - + ", sparkTaskHistogramEnabled=" - + sparkTaskHistogramEnabled - + ", jaxRsExceptionAsErrorsEnabled=" - + jaxRsExceptionAsErrorsEnabled - + ", peerServiceDefaultsEnabled=" - + peerServiceDefaultsEnabled - + ", peerServiceComponentOverrides=" - + peerServiceComponentOverrides - + ", removeIntegrationServiceNamesEnabled=" - + removeIntegrationServiceNamesEnabled - + ", spanAttributeSchemaVersion=" - + spanAttributeSchemaVersion - + ", telemetryDebugRequestsEnabled=" - + telemetryDebugRequestsEnabled - + ", telemetryMetricsEnabled=" - + telemetryMetricsEnabled - + '}'; - } + return result; + } + + public boolean isCrashTrackingAgentless() { + return crashTrackingAgentless; + } + + public boolean isTelemetryEnabled() { + return instrumenterConfig.isTelemetryEnabled(); + } + + public float getTelemetryHeartbeatInterval() { + return telemetryHeartbeatInterval; + } + + public long getTelemetryExtendedHeartbeatInterval() { + return telemetryExtendedHeartbeatInterval; + } + + public float getTelemetryMetricsInterval() { + return telemetryMetricsInterval; + } + + public boolean isTelemetryDependencyServiceEnabled() { + return isTelemetryDependencyServiceEnabled; + } + + public boolean isTelemetryMetricsEnabled() { + return telemetryMetricsEnabled; + } + + public boolean isTelemetryLogCollectionEnabled() { + return isTelemetryLogCollectionEnabled; + } + + public boolean isClientIpEnabled() { + return clientIpEnabled; + } + + public ProductActivation getAppSecActivation() { + return instrumenterConfig.getAppSecActivation(); + } + + public boolean isAppSecReportingInband() { + return appSecReportingInband; + } + + public int getAppSecReportMinTimeout() { + return appSecReportMinTimeout; + } + + public int getAppSecReportMaxTimeout() { + return appSecReportMaxTimeout; + } + + public int getAppSecTraceRateLimit() { + return appSecTraceRateLimit; + } + + public boolean isAppSecWafMetrics() { + return appSecWafMetrics; + } + + // in microseconds + public int getAppSecWafTimeout() { + return appSecWafTimeout; + } + + public String getAppSecObfuscationParameterKeyRegexp() { + return appSecObfuscationParameterKeyRegexp; + } + + public String getAppSecObfuscationParameterValueRegexp() { + return appSecObfuscationParameterValueRegexp; + } + + public String getAppSecHttpBlockedTemplateHtml() { + return appSecHttpBlockedTemplateHtml; + } + + public String getAppSecHttpBlockedTemplateJson() { + return appSecHttpBlockedTemplateJson; + } + + public UserEventTrackingMode getAppSecUserEventsTrackingMode() { + return appSecUserEventsTracking; + } + + public boolean isApiSecurityEnabled() { + return apiSecurityEnabled; + } + + public float getApiSecurityRequestSampleRate() { + return apiSecurityRequestSampleRate; + } + + public ProductActivation getIastActivation() { + return instrumenterConfig.getIastActivation(); + } + + public boolean isIastDebugEnabled() { + return iastDebugEnabled; + } + + public int getIastMaxConcurrentRequests() { + return iastMaxConcurrentRequests; + } + + public int getIastVulnerabilitiesPerRequest() { + return iastVulnerabilitiesPerRequest; + } + + public float getIastRequestSampling() { + return iastRequestSampling; + } + + public Verbosity getIastTelemetryVerbosity() { + return isTelemetryEnabled() ? iastTelemetryVerbosity : Verbosity.OFF; + } + + public boolean isIastRedactionEnabled() { + return iastRedactionEnabled; + } + + public String getIastRedactionNamePattern() { + return iastRedactionNamePattern; + } + + public String getIastRedactionValuePattern() { + return iastRedactionValuePattern; + } + + public int getIastTruncationMaxValueLength() { + return iastTruncationMaxValueLength; + } + + public int getIastMaxRangeCount() { + return iastMaxRangeCount; + } + + public boolean isIastStacktraceLeakSuppress() { + return iastStacktraceLeakSuppress; + } + + public boolean isCiVisibilityEnabled() { + return instrumenterConfig.isCiVisibilityEnabled(); + } + + public boolean isUsmEnabled() { + return instrumenterConfig.isUsmEnabled(); + } + + public boolean isCiVisibilityTraceSanitationEnabled() { + return ciVisibilityTraceSanitationEnabled; + } + + public boolean isCiVisibilityAgentlessEnabled() { + return ciVisibilityAgentlessEnabled; + } + + public String getCiVisibilityAgentlessUrl() { + return ciVisibilityAgentlessUrl; + } + + public boolean isCiVisibilitySourceDataEnabled() { + return ciVisibilitySourceDataEnabled; + } + + public boolean isCiVisibilitySourceDataRootCheckEnabled() { + return ciVisibilitySourceDataRootCheckEnabled; + } + + public boolean isCiVisibilityBuildInstrumentationEnabled() { + return ciVisibilityBuildInstrumentationEnabled; + } + + public Long getCiVisibilitySessionId() { + return ciVisibilitySessionId; + } + + public Long getCiVisibilityModuleId() { + return ciVisibilityModuleId; + } + + public String getCiVisibilityAgentJarUri() { + return ciVisibilityAgentJarUri; + } + + public File getCiVisibilityAgentJarFile() { + if (ciVisibilityAgentJarUri == null || ciVisibilityAgentJarUri.isEmpty()) { + throw new IllegalArgumentException("Agent JAR URI is not set in config"); + } + + try { + URI agentJarUri = new URI(ciVisibilityAgentJarUri); + return new File(agentJarUri); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Malformed agent JAR URI: " + ciVisibilityAgentJarUri, e); + } + } + + public boolean isCiVisibilityAutoConfigurationEnabled() { + return ciVisibilityAutoConfigurationEnabled; + } + + public String getCiVisibilityAdditionalChildProcessJvmArgs() { + return ciVisibilityAdditionalChildProcessJvmArgs; + } + + public boolean isCiVisibilityCompilerPluginAutoConfigurationEnabled() { + return ciVisibilityCompilerPluginAutoConfigurationEnabled; + } + + public boolean isCiVisibilityCodeCoverageEnabled() { + return ciVisibilityCodeCoverageEnabled; + } + + public boolean isCiVisibilityCodeCoveragePercentageCalculationEnabled() { + return ciVisibilityCodeCoveragePercentageCalculationEnabled; + } + + public String getCiVisibilityCodeCoverageReportDumpDir() { + return ciVisibilityCodeCoverageReportDumpDir; + } + + public String getCiVisibilityCompilerPluginVersion() { + return ciVisibilityCompilerPluginVersion; + } + + public String getCiVisibilityJacocoPluginVersion() { + return ciVisibilityJacocoPluginVersion; + } + + public boolean isCiVisibilityJacocoPluginVersionProvided() { + return ciVisibilityJacocoPluginVersionProvided; + } + + public List getCiVisibilityCodeCoverageIncludes() { + return ciVisibilityCodeCoverageIncludes; + } + + public List getCiVisibilityCodeCoverageExcludes() { + return ciVisibilityCodeCoverageExcludes; + } + + public String[] getCiVisibilityCodeCoverageIncludedPackages() { + return ciVisibilityCodeCoverageIncludedPackages; + } + + public String[] getCiVisibilityCodeCoverageExcludedPackages() { + return ciVisibilityCodeCoverageExcludedPackages; + } + + public List getCiVisibilityJacocoGradleSourceSets() { + return ciVisibilityJacocoGradleSourceSets; + } + + public Integer getCiVisibilityDebugPort() { + return ciVisibilityDebugPort; + } + + public boolean isCiVisibilityGitUploadEnabled() { + return ciVisibilityGitUploadEnabled; + } + + public boolean isCiVisibilityGitUnshallowEnabled() { + return ciVisibilityGitUnshallowEnabled; + } + + public boolean isCiVisibilityGitUnshallowDefer() { + return ciVisibilityGitUnshallowDefer; + } + + public long getCiVisibilityGitCommandTimeoutMillis() { + return ciVisibilityGitCommandTimeoutMillis; + } + + public long getCiVisibilityBackendApiTimeoutMillis() { + return ciVisibilityBackendApiTimeoutMillis; + } + + public long getCiVisibilityGitUploadTimeoutMillis() { + return ciVisibilityGitUploadTimeoutMillis; + } + + public String getCiVisibilityGitRemoteName() { + return ciVisibilityGitRemoteName; + } + + public int getCiVisibilitySignalServerPort() { + return ciVisibilitySignalServerPort; + } + + public String getCiVisibilitySignalServerHost() { + return ciVisibilitySignalServerHost; + } + + public boolean isCiVisibilityItrEnabled() { + return ciVisibilityItrEnabled; + } + + public boolean isCiVisibilityCiProviderIntegrationEnabled() { + return ciVisibilityCiProviderIntegrationEnabled; + } + + public boolean isCiVisibilityRepoIndexSharingEnabled() { + return ciVisibilityRepoIndexSharingEnabled; + } + + public int getCiVisibilityModuleExecutionSettingsCacheSize() { + return ciVisibilityModuleExecutionSettingsCacheSize; + } + + public int getCiVisibilityJvmInfoCacheSize() { + return ciVisibilityJvmInfoCacheSize; + } + + public boolean isCiVisibilityCoverageSegmentsEnabled() { + return ciVisibilityCoverageSegmentsEnabled; + } + + public int getCiVisibilityCoverageRootPackagesLimit() { + return ciVisibilityCoverageRootPackagesLimit; + } + + public String getCiVisibilityInjectedTracerVersion() { + return ciVisibilityInjectedTracerVersion; + } + + public List getCiVisibilityResourceFolderNames() { + return ciVisibilityResourceFolderNames; + } + + public boolean isCiVisibilityFlakyRetryEnabled() { + return ciVisibilityFlakyRetryEnabled; + } + + public int getCiVisibilityFlakyRetryCount() { + return ciVisibilityFlakyRetryCount; + } + + public String getCiVisibilityModuleName() { + return ciVisibilityModuleName; + } + + public String getAppSecRulesFile() { + return appSecRulesFile; + } + + public long getRemoteConfigMaxPayloadSizeBytes() { + return remoteConfigMaxPayloadSize; + } + + public boolean isRemoteConfigEnabled() { + return remoteConfigEnabled; + } + + public boolean isRemoteConfigIntegrityCheckEnabled() { + return remoteConfigIntegrityCheckEnabled; + } + + public String getFinalRemoteConfigUrl() { + return remoteConfigUrl; + } + + public float getRemoteConfigPollIntervalSeconds() { + return remoteConfigPollIntervalSeconds; + } + + public String getRemoteConfigTargetsKeyId() { + return remoteConfigTargetsKeyId; + } + + public String getRemoteConfigTargetsKey() { + return remoteConfigTargetsKey; + } + + public boolean isDebuggerEnabled() { + return debuggerEnabled; + } + + public int getDebuggerUploadTimeout() { + return debuggerUploadTimeout; + } + + public int getDebuggerUploadFlushInterval() { + return debuggerUploadFlushInterval; + } + + public boolean isDebuggerClassFileDumpEnabled() { + return debuggerClassFileDumpEnabled; + } + + public int getDebuggerPollInterval() { + return debuggerPollInterval; + } + + public int getDebuggerDiagnosticsInterval() { + return debuggerDiagnosticsInterval; + } + + public boolean isDebuggerMetricsEnabled() { + return debuggerMetricEnabled; + } + + public int getDebuggerUploadBatchSize() { + return debuggerUploadBatchSize; + } + + public long getDebuggerMaxPayloadSize() { + return debuggerMaxPayloadSize; + } + + public boolean isDebuggerVerifyByteCode() { + return debuggerVerifyByteCode; + } + + public boolean isDebuggerInstrumentTheWorld() { + return debuggerInstrumentTheWorld; + } + + public String getDebuggerExcludeFiles() { + return debuggerExcludeFiles; + } + + public int getDebuggerCaptureTimeout() { + return debuggerCaptureTimeout; + } + + public boolean isDebuggerSymbolEnabled() { + return debuggerSymbolEnabled; + } + + public boolean isDebuggerSymbolForceUpload() { + return debuggerSymbolForceUpload; + } + + public String getDebuggerSymbolIncludes() { + return debuggerSymbolIncludes; + } + + public int getDebuggerSymbolFlushThreshold() { + return debuggerSymbolFlushThreshold; + } + + public String getFinalDebuggerProbeUrl() { + // by default poll from datadog agent + return "http://" + agentHost + ":" + agentPort; + } + + public String getFinalDebuggerSnapshotUrl() { + // by default send to datadog agent + return agentUrl + "/debugger/v1/input"; + } + + public String getFinalDebuggerSymDBUrl() { + return agentUrl + "/symdb/v1/input"; + } + + public String getDebuggerProbeFileLocation() { + return debuggerProbeFileLocation; + } + + public String getDebuggerRedactedIdentifiers() { + return debuggerRedactedIdentifiers; + } + + public String getDebuggerRedactedTypes() { + return debuggerRedactedTypes; + } + + public boolean isAwsPropagationEnabled() { + return awsPropagationEnabled; + } + + public boolean isSqsPropagationEnabled() { + return sqsPropagationEnabled; + } + + public boolean isKafkaClientPropagationEnabled() { + return kafkaClientPropagationEnabled; + } + + public boolean isKafkaClientPropagationDisabledForTopic(String topic) { + return null != topic && kafkaClientPropagationDisabledTopics.contains(topic); + } + + public boolean isJmsPropagationEnabled() { + return jmsPropagationEnabled; + } + + public boolean isJmsPropagationDisabledForDestination(final String queueOrTopic) { + return null != queueOrTopic + && (jmsPropagationDisabledQueues.contains(queueOrTopic) + || jmsPropagationDisabledTopics.contains(queueOrTopic)); + } + + public int getJmsUnacknowledgedMaxAge() { + return jmsUnacknowledgedMaxAge; + } + + public boolean isKafkaClientBase64DecodingEnabled() { + return kafkaClientBase64DecodingEnabled; + } + + public boolean isRabbitPropagationEnabled() { + return rabbitPropagationEnabled; + } + + public boolean isRabbitPropagationDisabledForDestination(final String queueOrExchange) { + return null != queueOrExchange + && (rabbitPropagationDisabledQueues.contains(queueOrExchange) + || rabbitPropagationDisabledExchanges.contains(queueOrExchange)); + } + + public boolean isRabbitIncludeRoutingKeyInResource() { + return rabbitIncludeRoutingKeyInResource; + } + + public boolean isMessageBrokerSplitByDestination() { + return messageBrokerSplitByDestination; + } + + public boolean isHystrixTagsEnabled() { + return hystrixTagsEnabled; + } + + public boolean isHystrixMeasuredEnabled() { + return hystrixMeasuredEnabled; + } + + public boolean isIgniteCacheIncludeKeys() { + return igniteCacheIncludeKeys; + } + + public String getObfuscationQueryRegexp() { + return obfuscationQueryRegexp; + } + + public boolean getPlayReportHttpStatus() { + return playReportHttpStatus; + } + + public boolean isServletPrincipalEnabled() { + return servletPrincipalEnabled; + } + + public boolean isSpringDataRepositoryInterfaceResourceName() { + return springDataRepositoryInterfaceResourceName; + } + + public int getxDatadogTagsMaxLength() { + return xDatadogTagsMaxLength; + } + + public boolean isServletAsyncTimeoutError() { + return servletAsyncTimeoutError; + } + + public boolean isTraceAgentV05Enabled() { + return traceAgentV05Enabled; + } + + public boolean isDebugEnabled() { + return debugEnabled; + } + + public boolean isTriageEnabled() { + return triageEnabled; + } + + public boolean isStartupLogsEnabled() { + return startupLogsEnabled; + } + + public boolean isCwsEnabled() { + return cwsEnabled; + } + + public int getCwsTlsRefresh() { + return cwsTlsRefresh; + } + + public boolean isAzureAppServices() { + return azureAppServices; + } + + public boolean isDataStreamsEnabled() { + return dataStreamsEnabled; + } + + public float getDataStreamsBucketDurationSeconds() { + return dataStreamsBucketDurationSeconds; + } + + public long getDataStreamsBucketDurationNanoseconds() { + // Rounds to the nearest millisecond before converting to nanos + int milliseconds = Math.round(dataStreamsBucketDurationSeconds * 1000); + return TimeUnit.MILLISECONDS.toNanos(milliseconds); + } + + public String getTraceAgentPath() { + return traceAgentPath; + } + + public List getTraceAgentArgs() { + return traceAgentArgs; + } + + public String getDogStatsDPath() { + return dogStatsDPath; + } + + public List getDogStatsDArgs() { + return dogStatsDArgs; + } + + public String getConfigFileStatus() { + return configFileStatus; + } + + public IdGenerationStrategy getIdGenerationStrategy() { + return idGenerationStrategy; + } + + public boolean isTrace128bitTraceIdGenerationEnabled() { + return trace128bitTraceIdGenerationEnabled; + } + + public Set getGrpcIgnoredInboundMethods() { + return grpcIgnoredInboundMethods; + } + + public Set getGrpcIgnoredOutboundMethods() { + return grpcIgnoredOutboundMethods; + } + + public boolean isGrpcServerTrimPackageResource() { + return grpcServerTrimPackageResource; + } + + public BitSet getGrpcServerErrorStatuses() { + return grpcServerErrorStatuses; + } + + public BitSet getGrpcClientErrorStatuses() { + return grpcClientErrorStatuses; + } + + public boolean isElasticsearchBodyEnabled() { + return elasticsearchBodyEnabled; + } + + public boolean isElasticsearchParamsEnabled() { + return elasticsearchParamsEnabled; + } + + public boolean isElasticsearchBodyAndParamsEnabled() { + return elasticsearchBodyAndParamsEnabled; + } + + public boolean isSparkTaskHistogramEnabled() { + return sparkTaskHistogramEnabled; + } + + public boolean isJaxRsExceptionAsErrorEnabled() { + return jaxRsExceptionAsErrorsEnabled; + } + + /** + * @return A map of tags to be applied only to the local application root span. + */ + public Map getLocalRootSpanTags() { + final Map runtimeTags = getRuntimeTags(); + final Map result = new HashMap<>(runtimeTags.size() + 2); + result.putAll(runtimeTags); + result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE); + result.put(SCHEMA_VERSION_TAG_KEY, SpanNaming.instance().version()); + result.put(PROFILING_ENABLED, isProfilingEnabled() ? 1 : 0); + + if (reportHostName) { + final String hostName = getHostName(); + if (null != hostName && !hostName.isEmpty()) { + result.put(INTERNAL_HOST_NAME, hostName); + } + } + + if (azureAppServices) { + result.putAll(getAzureAppServicesTags()); + } + + result.putAll(getProcessIdTag()); + + return Collections.unmodifiableMap(result); + } + + public WellKnownTags getWellKnownTags() { + return new WellKnownTags( + getRuntimeId(), + reportHostName ? getHostName() : "", + getEnv(), + serviceName, + getVersion(), + LANGUAGE_TAG_VALUE); + } + + public String getPrimaryTag() { + return primaryTag; + } + + public Set getMetricsIgnoredResources() { + return tryMakeImmutableSet(configProvider.getList(TRACER_METRICS_IGNORED_RESOURCES)); + } + + public String getEnv() { + // intentionally not thread safe + if (env == null) { + env = getMergedSpanTags().get("env"); + if (env == null) { + env = ""; + } + } + + return env; + } + + public String getVersion() { + // intentionally not thread safe + if (version == null) { + version = getMergedSpanTags().get("version"); + if (version == null) { + version = ""; + } + } + + return version; + } + + public Map getMergedSpanTags() { + // Do not include runtimeId into span tags: we only want that added to the root span + final Map result = newHashMap(getGlobalTags().size() + spanTags.size()); + result.putAll(getGlobalTags()); + result.putAll(spanTags); + return Collections.unmodifiableMap(result); + } + + public Map getMergedJmxTags() { + final Map runtimeTags = getRuntimeTags(); + final Map result = + newHashMap( + getGlobalTags().size() + jmxTags.size() + runtimeTags.size() + 1 /* for serviceName */); + result.putAll(getGlobalTags()); + result.putAll(jmxTags); + result.putAll(runtimeTags); + // service name set here instead of getRuntimeTags because apm already manages the service tag + // and may chose to override it. + // Additionally, infra/JMX metrics require `service` rather than APM's `service.name` tag + result.put(SERVICE_TAG, serviceName); + return Collections.unmodifiableMap(result); + } + + public Map getMergedProfilingTags() { + final Map runtimeTags = getRuntimeTags(); + final String host = getHostName(); + final Map result = + newHashMap( + getGlobalTags().size() + + profilingTags.size() + + runtimeTags.size() + + 4 /* for serviceName and host and language and runtime_version */); + result.put(HOST_TAG, host); // Host goes first to allow to override it + result.putAll(getGlobalTags()); + result.putAll(profilingTags); + result.putAll(runtimeTags); + // service name set here instead of getRuntimeTags because apm already manages the service tag + // and may chose to override it. + result.put(SERVICE_TAG, serviceName); + result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE); + result.put(RUNTIME_VERSION_TAG, runtimeVersion); + return Collections.unmodifiableMap(result); + } + + public Map getMergedCrashTrackingTags() { + final Map runtimeTags = getRuntimeTags(); + final String host = getHostName(); + final Map result = + newHashMap( + getGlobalTags().size() + + crashTrackingTags.size() + + runtimeTags.size() + + 3 /* for serviceName and host and language */); + result.put(HOST_TAG, host); // Host goes first to allow to override it + result.putAll(getGlobalTags()); + result.putAll(crashTrackingTags); + result.putAll(runtimeTags); + // service name set here instead of getRuntimeTags because apm already manages the service tag + // and may chose to override it. + result.put(SERVICE_TAG, serviceName); + result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE); + return Collections.unmodifiableMap(result); + } + + /** + * Returns the sample rate for the specified instrumentation or {@link + * ConfigDefaults#DEFAULT_ANALYTICS_SAMPLE_RATE} if none specified. + */ + public float getInstrumentationAnalyticsSampleRate(final String... aliases) { + for (final String alias : aliases) { + final String configKey = alias + ".analytics.sample-rate"; + final Float rate = configProvider.getFloat("trace." + configKey, configKey); + if (null != rate) { + return rate; + } + } + return DEFAULT_ANALYTICS_SAMPLE_RATE; + } + + /** + * Provide 'global' tags, i.e. tags set everywhere. We have to support old (dd.trace.global.tags) + * version of this setting if new (dd.tags) version has not been specified. + */ + public Map getGlobalTags() { + return tags; + } + + /** + * Return a map of tags required by the datadog backend to link runtime metrics (i.e. jmx) and + * traces. + * + *

    These tags must be applied to every runtime metrics and placed on the root span of every + * trace. + * + * @return A map of tag-name -> tag-value + */ + private Map getRuntimeTags() { + return Collections.singletonMap(RUNTIME_ID_TAG, getRuntimeId()); + } + + private Map getProcessIdTag() { + return Collections.singletonMap(PID_TAG, getProcessId()); + } + + private Map getAzureAppServicesTags() { + // These variable names and derivations are copied from the dotnet tracer + // See + // https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/src/Datadog.Trace/PlatformHelpers/AzureAppServices.cs + // and + // https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/src/Datadog.Trace/TraceContext.cs#L207 + Map aasTags = new HashMap<>(); + + /// The site name of the site instance in Azure where the traced application is running. + String siteName = getEnv("WEBSITE_SITE_NAME"); + if (siteName != null) { + aasTags.put("aas.site.name", siteName); + } + + // The kind of application instance running in Azure. + // Possible values: app, api, mobileapp, app_linux, app_linux_container, functionapp, + // functionapp_linux, functionapp_linux_container + + // The type of application instance running in Azure. + // Possible values: app, function + if (getEnv("FUNCTIONS_WORKER_RUNTIME") != null + || getEnv("FUNCTIONS_EXTENSIONS_VERSION") != null) { + aasTags.put("aas.site.kind", "functionapp"); + aasTags.put("aas.site.type", "function"); + } else { + aasTags.put("aas.site.kind", "app"); + aasTags.put("aas.site.type", "app"); + } + + // The resource group of the site instance in Azure App Services + String resourceGroup = getEnv("WEBSITE_RESOURCE_GROUP"); + if (resourceGroup != null) { + aasTags.put("aas.resource.group", resourceGroup); + } + + // Example: 8c500027-5f00-400e-8f00-60000000000f+apm-dotnet-EastUSwebspace + // Format: {subscriptionId}+{planResourceGroup}-{hostedInRegion} + String websiteOwner = getEnv("WEBSITE_OWNER_NAME"); + int plusIndex = websiteOwner == null ? -1 : websiteOwner.indexOf("+"); + + // The subscription ID of the site instance in Azure App Services + String subscriptionId = null; + if (plusIndex > 0) { + subscriptionId = websiteOwner.substring(0, plusIndex); + aasTags.put("aas.subscription.id", subscriptionId); + } + + if (subscriptionId != null && siteName != null && resourceGroup != null) { + // The resource ID of the site instance in Azure App Services + String resourceId = + "/subscriptions/" + + subscriptionId + + "/resourcegroups/" + + resourceGroup + + "/providers/microsoft.web/sites/" + + siteName; + resourceId = resourceId.toLowerCase(Locale.ROOT); + aasTags.put("aas.resource.id", resourceId); + } else { + log.warn( + "Unable to generate resource id subscription id: {}, site name: {}, resource group {}", + subscriptionId, + siteName, + resourceGroup); + } + + // The instance ID in Azure + String instanceId = getEnv("WEBSITE_INSTANCE_ID"); + instanceId = instanceId == null ? "unknown" : instanceId; + aasTags.put("aas.environment.instance_id", instanceId); + + // The instance name in Azure + String instanceName = getEnv("COMPUTERNAME"); + instanceName = instanceName == null ? "unknown" : instanceName; + aasTags.put("aas.environment.instance_name", instanceName); + + // The operating system in Azure + String operatingSystem = getEnv("WEBSITE_OS"); + operatingSystem = operatingSystem == null ? "unknown" : operatingSystem; + aasTags.put("aas.environment.os", operatingSystem); + + // The version of the extension installed + String siteExtensionVersion = getEnv("DD_AAS_JAVA_EXTENSION_VERSION"); + siteExtensionVersion = siteExtensionVersion == null ? "unknown" : siteExtensionVersion; + aasTags.put("aas.environment.extension_version", siteExtensionVersion); + + aasTags.put("aas.environment.runtime", getProp("java.vm.name", "unknown")); + + return aasTags; + } + + private int schemaVersionFromConfig() { + String versionStr = + configProvider.getString(TRACE_SPAN_ATTRIBUTE_SCHEMA, "v" + SpanNaming.SCHEMA_MIN_VERSION); + Matcher matcher = Pattern.compile("^v?(0|[1-9]\\d*)$").matcher(versionStr); + int parsedVersion = -1; + if (matcher.matches()) { + parsedVersion = Integer.parseInt(matcher.group(1)); + } + if (parsedVersion < SpanNaming.SCHEMA_MIN_VERSION + || parsedVersion > SpanNaming.SCHEMA_MAX_VERSION) { + log.warn( + "Invalid attribute schema version {} invalid or out of range [v{}, v{}]. Defaulting to v{}", + versionStr, + SpanNaming.SCHEMA_MIN_VERSION, + SpanNaming.SCHEMA_MAX_VERSION, + SpanNaming.SCHEMA_MIN_VERSION); + parsedVersion = SpanNaming.SCHEMA_MIN_VERSION; + } + return parsedVersion; + } + + public String getFinalProfilingUrl() { + if (profilingUrl != null) { + // when profilingUrl is set we use it regardless of apiKey/agentless config + return profilingUrl; + } else if (profilingAgentless) { + // when agentless profiling is turned on we send directly to our intake + return "https://intake.profile." + site + "/api/v2/profile"; + } else { + // when profilingUrl and agentless are not set we send to the dd trace agent running locally + return "http://" + agentHost + ":" + agentPort + "/profiling/v1/input"; + } + } + + public String getFinalCrashTrackingTelemetryUrl() { + if (crashTrackingAgentless) { + // when agentless crashTracking is turned on we send directly to our intake + return "https://all-http-intake.logs." + site + "/api/v2/apmtelemetry"; + } else { + // when agentless are not set we send to the dd trace agent running locally + return "http://" + agentHost + ":" + agentPort + "/telemetry/proxy/api/v2/apmtelemetry"; + } + } + + public boolean isJmxFetchIntegrationEnabled( + final Iterable integrationNames, final boolean defaultEnabled) { + return configProvider.isEnabled(integrationNames, "jmxfetch.", ".enabled", defaultEnabled); + } + + public boolean isRuleEnabled(final String name) { + return isRuleEnabled(name, true); + } + + public boolean isRuleEnabled(final String name, boolean defaultEnabled) { + boolean enabled = configProvider.getBoolean("trace." + name + ".enabled", defaultEnabled); + boolean lowerEnabled = + configProvider.getBoolean( + "trace." + name.toLowerCase(Locale.ROOT) + ".enabled", defaultEnabled); + return defaultEnabled ? enabled && lowerEnabled : enabled || lowerEnabled; + } + + /** + * @param integrationNames + * @param defaultEnabled + * @return + * @deprecated This method should only be used internally. Use the instance getter instead {@link + * #isJmxFetchIntegrationEnabled(Iterable, boolean)}. + */ + public static boolean jmxFetchIntegrationEnabled( + final SortedSet integrationNames, final boolean defaultEnabled) { + return Config.get().isJmxFetchIntegrationEnabled(integrationNames, defaultEnabled); + } + + public boolean isEndToEndDurationEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".e2e.duration.enabled", defaultEnabled); + } + + public boolean isPropagationEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".propagation.enabled", defaultEnabled); + } + + public boolean isLegacyTracingEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return SpanNaming.instance().namingSchema().allowInferredServices() + && configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".legacy.tracing.enabled", defaultEnabled); + } + + public boolean isTimeInQueueEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return SpanNaming.instance().namingSchema().allowInferredServices() + && configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".time-in-queue.enabled", defaultEnabled); + } + + public boolean isEnabled( + final boolean defaultEnabled, final String settingName, String settingSuffix) { + return configProvider.isEnabled( + Collections.singletonList(settingName), "", settingSuffix, defaultEnabled); + } + + public String getDBMPropagationMode() { + return DBMPropagationMode; + } + + private void logIgnoredSettingWarning( + String setting, String overridingSetting, String overridingSuffix) { + log.warn( + "Setting {} ignored since {}{} is enabled.", + propertyNameToSystemPropertyName(setting), + propertyNameToSystemPropertyName(overridingSetting), + overridingSuffix); + } + + private void logOverriddenSettingWarning(String setting, String overridingSetting, Object value) { + log.warn( + "Setting {} is overridden by setting {} with value {}.", + propertyNameToSystemPropertyName(setting), + propertyNameToSystemPropertyName(overridingSetting), + value); + } + + private void logOverriddenDeprecatedSettingWarning( + String setting, String overridingSetting, Object value) { + log.warn( + "Setting {} is deprecated and overridden by setting {} with value {}.", + propertyNameToSystemPropertyName(setting), + propertyNameToSystemPropertyName(overridingSetting), + value); + } + + private void logDeprecatedConvertedSetting( + String deprecatedSetting, Object oldValue, String newSetting, Object newValue) { + log.warn( + "Setting {} is deprecated and the value {} has been converted to {} for setting {}.", + propertyNameToSystemPropertyName(deprecatedSetting), + oldValue, + newValue, + propertyNameToSystemPropertyName(newSetting)); + } + + public boolean isTraceAnalyticsIntegrationEnabled( + final SortedSet integrationNames, final boolean defaultEnabled) { + return configProvider.isEnabled(integrationNames, "", ".analytics.enabled", defaultEnabled); + } + + public boolean isTraceAnalyticsIntegrationEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".analytics.enabled", defaultEnabled); + } + + public boolean isSamplingMechanismValidationDisabled() { + return configProvider.getBoolean(TracerConfig.SAMPLING_MECHANISM_VALIDATION_DISABLED, false); + } + + public > T getEnumValue( + final String name, final Class type, final T defaultValue) { + return configProvider.getEnum(name, type, defaultValue); + } + + /** + * @param integrationNames + * @param defaultEnabled + * @return + * @deprecated This method should only be used internally. Use the instance getter instead {@link + * #isTraceAnalyticsIntegrationEnabled(SortedSet, boolean)}. + */ + public static boolean traceAnalyticsIntegrationEnabled( + final SortedSet integrationNames, final boolean defaultEnabled) { + return Config.get().isTraceAnalyticsIntegrationEnabled(integrationNames, defaultEnabled); + } + + public boolean isTelemetryDebugRequestsEnabled() { + return telemetryDebugRequestsEnabled; + } + + private Set getSettingsSetFromEnvironment( + String name, Function mapper, boolean splitOnWS) { + final String value = configProvider.getString(name, ""); + return convertStringSetToSet( + name, parseStringIntoSetOfNonEmptyStrings(value, splitOnWS), mapper); + } + + private Set convertSettingsSet(Set fromSet, Function> mapper) { + if (fromSet.isEmpty()) { + return Collections.emptySet(); + } + Set result = new LinkedHashSet<>(fromSet.size()); + for (F from : fromSet) { + for (T to : mapper.apply(from)) { + result.add(to); + } + } + return Collections.unmodifiableSet(result); + } + + public static final String PREFIX = "dd."; + + /** + * Converts the property name, e.g. 'service.name' into a public system property name, e.g. + * `dd.service.name`. + * + * @param setting The setting name, e.g. `service.name` + * @return The public facing system property name + */ + @NonNull + private static String propertyNameToSystemPropertyName(final String setting) { + return PREFIX + setting; + } + + @NonNull + private static Map newHashMap(final int size) { + return new HashMap<>(size + 1, 1f); + } + + /** + * @param map + * @param propNames + * @return new unmodifiable copy of {@param map} where properties are overwritten from environment + */ + @NonNull + private Map getMapWithPropertiesDefinedByEnvironment( + @NonNull final Map map, @NonNull final String... propNames) { + final Map res = new HashMap<>(map); + for (final String propName : propNames) { + final String val = configProvider.getString(propName); + if (val != null) { + res.put(propName, val); + } + } + return Collections.unmodifiableMap(res); + } + + @NonNull + private static Set parseStringIntoSetOfNonEmptyStrings(final String str) { + return parseStringIntoSetOfNonEmptyStrings(str, true); + } + + @NonNull + private static Set parseStringIntoSetOfNonEmptyStrings( + final String str, boolean splitOnWS) { + // Using LinkedHashSet to preserve original string order + final Set result = new LinkedHashSet<>(); + // Java returns single value when splitting an empty string. We do not need that value, so + // we need to throw it out. + int start = 0; + int i = 0; + for (; i < str.length(); ++i) { + char c = str.charAt(i); + if (c == ',' || (splitOnWS && Character.isWhitespace(c))) { + if (i - start - 1 > 0) { + result.add(str.substring(start, i)); + } + start = i + 1; + } + } + if (i - start - 1 > 0) { + result.add(str.substring(start)); + } + return Collections.unmodifiableSet(result); + } + + private static Set convertStringSetToSet( + String setting, final Set input, Function mapper) { + if (input.isEmpty()) { + return Collections.emptySet(); + } + // Using LinkedHashSet to preserve original string order + final Set result = new LinkedHashSet<>(); + for (final String value : input) { + try { + result.add(mapper.apply(value)); + } catch (final IllegalArgumentException e) { + log.warn( + "Cannot recognize config string value {} for setting {}", + value, + propertyNameToSystemPropertyName(setting)); + } + } + return Collections.unmodifiableSet(result); + } + + /** + * Returns the detected hostname. First tries locally, then using DNS + */ + static String initHostName() { + String possibleHostname; + + // Try environment variable. This works in almost all environments + if (isWindowsOS()) { + possibleHostname = getEnv("COMPUTERNAME"); + } else { + possibleHostname = getEnv("HOSTNAME"); + } + + if (possibleHostname != null && !possibleHostname.isEmpty()) { + log.debug("Determined hostname from environment variable"); + return possibleHostname.trim(); + } + + // Try hostname files + final String[] hostNameFiles = new String[]{"/proc/sys/kernel/hostname", "/etc/hostname"}; + for (final String hostNameFile : hostNameFiles) { + try { + byte[] hostnameBytes = readHostnameFromFile(hostNameFile); + if (hostnameBytes != null) { + possibleHostname = new String(hostnameBytes, StandardCharsets.UTF_8); + } + } catch (Throwable t) { + // Ignore + } + possibleHostname = Strings.trim(possibleHostname); + if (!possibleHostname.isEmpty()) { + log.debug("Determined hostname from file {}", hostNameFile); + return possibleHostname; + } + } + + // Try hostname command + try (final BufferedReader reader = + new BufferedReader( + new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))) { + possibleHostname = reader.readLine(); + } catch (final Throwable ignore) { + // Ignore. Hostname command is not always available + } + + if (possibleHostname != null && !possibleHostname.isEmpty()) { + log.debug("Determined hostname from hostname command"); + return possibleHostname.trim(); + } + + // From DNS + try { + return InetAddress.getLocalHost().getHostName(); + } catch (final UnknownHostException e) { + // If we are not able to detect the hostname we do not throw an exception. + } + + return null; + } + + private static byte[] readHostnameFromFile(String hostnameFilePath) throws IOException { + final Path hostNamePath; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + hostNamePath = FileSystems.getDefault().getPath(hostnameFilePath); + if (Files.isRegularFile(hostNamePath)) { + return Files.readAllBytes(hostNamePath); + } + } else { + File file = new File(hostnameFilePath); + if (file.exists()) { + return FileUtils.readAllBytes(file.getAbsolutePath()); + } + } + return null; + } + + private static boolean isWindowsOS() { + return getProp("os.name").startsWith("Windows"); + } + + private static String getEnv(String name) { + String value = System.getenv(name); + if (value != null) { + ConfigCollector.get().put(name, value, ConfigOrigin.ENV); + } + return value; + } + + private static Pattern getPattern(String defaultValue, String userValue) { + try { + if (userValue != null) { + return Pattern.compile(userValue); + } + } catch (Exception e) { + log.debug("Cannot create pattern from user value {}", userValue); + } + return Pattern.compile(defaultValue); + } + + private static String getProp(String name) { + return getProp(name, null); + } + + private static String getProp(String name, String def) { + String value = System.getProperty(name, def); + if (value != null) { + ConfigCollector.get().put(name, value, ConfigOrigin.JVM_PROP); + } + return value; + } + + // This has to be placed after all other static fields to give them a chance to initialize + + private static final Config INSTANCE = + new Config( + Platform.isNativeImageBuilder() + ? ConfigProvider.withoutCollector() + : ConfigProvider.getInstance(), + InstrumenterConfig.get()); + + public static Config get() { + return INSTANCE; + } + + /** + * This method is deprecated since the method of configuration will be changed in the future. The + * properties instance should instead be passed directly into the DDTracer builder: + * + *

    +     *   DDTracer.builder().withProperties(new Properties()).build()
    +     * 
    + * + *

    Config keys for use in Properties instance construction can be found in {@link + * GeneralConfig} and {@link TracerConfig}. + * + * @deprecated + */ + @Deprecated + public static Config get(final Properties properties) { + if (properties == null || properties.isEmpty()) { + return INSTANCE; + } else { + return new Config(ConfigProvider.withPropertiesOverride(properties)); + } + } + + @Override + public String toString() { + return "Config{" + + "instrumenterConfig=" + + instrumenterConfig + + ", runtimeId='" + + getRuntimeId() + + '\'' + + ", runtimeVersion='" + + runtimeVersion + + ", apiKey=" + + (apiKey == null ? "null" : "****") + + ", site='" + + site + + '\'' + + ", hostName='" + + getHostName() + + '\'' + + ", serviceName='" + + serviceName + + '\'' + + ", serviceNameSetByUser=" + + serviceNameSetByUser + + ", rootContextServiceName=" + + rootContextServiceName + + ", integrationSynapseLegacyOperationName=" + + integrationSynapseLegacyOperationName + + ", writerType='" + + writerType + + '\'' + + ", agentConfiguredUsingDefault=" + + agentConfiguredUsingDefault + + ", agentUrl='" + + agentUrl + + '\'' + + ", agentHost='" + + agentHost + + '\'' + + ", agentPort=" + + agentPort + + ", agentUnixDomainSocket='" + + agentUnixDomainSocket + + '\'' + + ", agentTimeout=" + + agentTimeout + + ", noProxyHosts=" + + noProxyHosts + + ", prioritySamplingEnabled=" + + prioritySamplingEnabled + + ", prioritySamplingForce='" + + prioritySamplingForce + + '\'' + + ", traceResolverEnabled=" + + traceResolverEnabled + + ", serviceMapping=" + + serviceMapping + + ", tags=" + + tags + + ", spanTags=" + + spanTags + + ", jmxTags=" + + jmxTags + + ", requestHeaderTags=" + + requestHeaderTags + + ", responseHeaderTags=" + + responseHeaderTags + + ", baggageMapping=" + + baggageMapping + + ", httpServerErrorStatuses=" + + httpServerErrorStatuses + + ", httpClientErrorStatuses=" + + httpClientErrorStatuses + + ", httpServerTagQueryString=" + + httpServerTagQueryString + + ", httpServerRawQueryString=" + + httpServerRawQueryString + + ", httpServerRawResource=" + + httpServerRawResource + + ", httpServerRouteBasedNaming=" + + httpServerRouteBasedNaming + + ", httpServerPathResourceNameMapping=" + + httpServerPathResourceNameMapping + + ", httpClientPathResourceNameMapping=" + + httpClientPathResourceNameMapping + + ", httpClientTagQueryString=" + + httpClientTagQueryString + + ", httpClientSplitByDomain=" + + httpClientSplitByDomain + + ", httpResourceRemoveTrailingSlash" + + httpResourceRemoveTrailingSlash + + ", dbClientSplitByInstance=" + + dbClientSplitByInstance + + ", dbClientSplitByInstanceTypeSuffix=" + + dbClientSplitByInstanceTypeSuffix + + ", dbClientSplitByHost=" + + dbClientSplitByHost + + ", DBMPropagationMode=" + + DBMPropagationMode + + ", splitByTags=" + + splitByTags + + ", scopeDepthLimit=" + + scopeDepthLimit + + ", scopeStrictMode=" + + scopeStrictMode + + ", scopeInheritAsyncPropagation=" + + scopeInheritAsyncPropagation + + ", scopeIterationKeepAlive=" + + scopeIterationKeepAlive + + ", partialFlushMinSpans=" + + partialFlushMinSpans + + ", traceStrictWritesEnabled=" + + traceStrictWritesEnabled + + ", tracePropagationStylesToExtract=" + + tracePropagationStylesToExtract + + ", tracePropagationStylesToInject=" + + tracePropagationStylesToInject + + ", tracePropagationExtractFirst=" + + tracePropagationExtractFirst + + ", clockSyncPeriod=" + + clockSyncPeriod + + ", jmxFetchEnabled=" + + jmxFetchEnabled + + ", dogStatsDStartDelay=" + + dogStatsDStartDelay + + ", jmxFetchConfigDir='" + + jmxFetchConfigDir + + '\'' + + ", jmxFetchConfigs=" + + jmxFetchConfigs + + ", jmxFetchMetricsConfigs=" + + jmxFetchMetricsConfigs + + ", jmxFetchCheckPeriod=" + + jmxFetchCheckPeriod + + ", jmxFetchInitialRefreshBeansPeriod=" + + jmxFetchInitialRefreshBeansPeriod + + ", jmxFetchRefreshBeansPeriod=" + + jmxFetchRefreshBeansPeriod + + ", jmxFetchStatsdHost='" + + jmxFetchStatsdHost + + '\'' + + ", jmxFetchStatsdPort=" + + jmxFetchStatsdPort + + ", jmxFetchMultipleRuntimeServicesEnabled=" + + jmxFetchMultipleRuntimeServicesEnabled + + ", jmxFetchMultipleRuntimeServicesLimit=" + + jmxFetchMultipleRuntimeServicesLimit + + ", healthMetricsEnabled=" + + healthMetricsEnabled + + ", healthMetricsStatsdHost='" + + healthMetricsStatsdHost + + '\'' + + ", healthMetricsStatsdPort=" + + healthMetricsStatsdPort + + ", perfMetricsEnabled=" + + perfMetricsEnabled + + ", tracerMetricsEnabled=" + + tracerMetricsEnabled + + ", tracerMetricsBufferingEnabled=" + + tracerMetricsBufferingEnabled + + ", tracerMetricsMaxAggregates=" + + tracerMetricsMaxAggregates + + ", tracerMetricsMaxPending=" + + tracerMetricsMaxPending + + ", reportHostName=" + + reportHostName + + ", traceAnalyticsEnabled=" + + traceAnalyticsEnabled + + ", traceSamplingServiceRules=" + + traceSamplingServiceRules + + ", traceSamplingOperationRules=" + + traceSamplingOperationRules + + ", traceSamplingJsonRules=" + + traceSamplingRules + + ", traceSampleRate=" + + traceSampleRate + + ", traceRateLimit=" + + traceRateLimit + + ", spanSamplingRules=" + + spanSamplingRules + + ", spanSamplingRulesFile=" + + spanSamplingRulesFile + + ", profilingAgentless=" + + profilingAgentless + + ", profilingUrl='" + + profilingUrl + + '\'' + + ", profilingTags=" + + profilingTags + + ", profilingStartDelay=" + + profilingStartDelay + + ", profilingStartForceFirst=" + + profilingStartForceFirst + + ", profilingUploadPeriod=" + + profilingUploadPeriod + + ", profilingTemplateOverrideFile='" + + profilingTemplateOverrideFile + + '\'' + + ", profilingUploadTimeout=" + + profilingUploadTimeout + + ", profilingUploadCompression='" + + profilingUploadCompression + + '\'' + + ", profilingProxyHost='" + + profilingProxyHost + + '\'' + + ", profilingProxyPort=" + + profilingProxyPort + + ", profilingProxyUsername='" + + profilingProxyUsername + + '\'' + + ", profilingProxyPassword=" + + (profilingProxyPassword == null ? "null" : "****") + + ", profilingExceptionSampleLimit=" + + profilingExceptionSampleLimit + + ", profilingExceptionHistogramTopItems=" + + profilingExceptionHistogramTopItems + + ", profilingExceptionHistogramMaxCollectionSize=" + + profilingExceptionHistogramMaxCollectionSize + + ", profilingExcludeAgentThreads=" + + profilingExcludeAgentThreads + + ", crashTrackingTags=" + + crashTrackingTags + + ", crashTrackingAgentless=" + + crashTrackingAgentless + + ", remoteConfigEnabled=" + + remoteConfigEnabled + + ", remoteConfigUrl=" + + remoteConfigUrl + + ", remoteConfigPollIntervalSeconds=" + + remoteConfigPollIntervalSeconds + + ", remoteConfigMaxPayloadSize=" + + remoteConfigMaxPayloadSize + + ", remoteConfigIntegrityCheckEnabled=" + + remoteConfigIntegrityCheckEnabled + + ", debuggerEnabled=" + + debuggerEnabled + + ", debuggerUploadTimeout=" + + debuggerUploadTimeout + + ", debuggerUploadFlushInterval=" + + debuggerUploadFlushInterval + + ", debuggerClassFileDumpEnabled=" + + debuggerClassFileDumpEnabled + + ", debuggerPollInterval=" + + debuggerPollInterval + + ", debuggerDiagnosticsInterval=" + + debuggerDiagnosticsInterval + + ", debuggerMetricEnabled=" + + debuggerMetricEnabled + + ", debuggerProbeFileLocation=" + + debuggerProbeFileLocation + + ", debuggerUploadBatchSize=" + + debuggerUploadBatchSize + + ", debuggerMaxPayloadSize=" + + debuggerMaxPayloadSize + + ", debuggerVerifyByteCode=" + + debuggerVerifyByteCode + + ", debuggerInstrumentTheWorld=" + + debuggerInstrumentTheWorld + + ", debuggerExcludeFile=" + + debuggerExcludeFiles + + ", awsPropagationEnabled=" + + awsPropagationEnabled + + ", sqsPropagationEnabled=" + + sqsPropagationEnabled + + ", kafkaClientPropagationEnabled=" + + kafkaClientPropagationEnabled + + ", kafkaClientPropagationDisabledTopics=" + + kafkaClientPropagationDisabledTopics + + ", kafkaClientBase64DecodingEnabled=" + + kafkaClientBase64DecodingEnabled + + ", jmsPropagationEnabled=" + + jmsPropagationEnabled + + ", jmsPropagationDisabledTopics=" + + jmsPropagationDisabledTopics + + ", jmsPropagationDisabledQueues=" + + jmsPropagationDisabledQueues + + ", rabbitPropagationEnabled=" + + rabbitPropagationEnabled + + ", rabbitPropagationDisabledQueues=" + + rabbitPropagationDisabledQueues + + ", rabbitPropagationDisabledExchanges=" + + rabbitPropagationDisabledExchanges + + ", messageBrokerSplitByDestination=" + + messageBrokerSplitByDestination + + ", hystrixTagsEnabled=" + + hystrixTagsEnabled + + ", hystrixMeasuredEnabled=" + + hystrixMeasuredEnabled + + ", igniteCacheIncludeKeys=" + + igniteCacheIncludeKeys + + ", servletPrincipalEnabled=" + + servletPrincipalEnabled + + ", servletAsyncTimeoutError=" + + servletAsyncTimeoutError + + ", datadogTagsLimit=" + + xDatadogTagsMaxLength + + ", traceAgentV05Enabled=" + + traceAgentV05Enabled + + ", debugEnabled=" + + debugEnabled + + ", triageEnabled=" + + triageEnabled + + ", startLogsEnabled=" + + startupLogsEnabled + + ", configFile='" + + configFileStatus + + '\'' + + ", idGenerationStrategy=" + + idGenerationStrategy + + ", trace128bitTraceIdGenerationEnabled=" + + trace128bitTraceIdGenerationEnabled + + ", grpcIgnoredInboundMethods=" + + grpcIgnoredInboundMethods + + ", grpcIgnoredOutboundMethods=" + + grpcIgnoredOutboundMethods + + ", grpcServerErrorStatuses=" + + grpcServerErrorStatuses + + ", grpcClientErrorStatuses=" + + grpcClientErrorStatuses + + ", clientIpEnabled=" + + clientIpEnabled + + ", appSecReportingInband=" + + appSecReportingInband + + ", appSecRulesFile='" + + appSecRulesFile + + "'" + + ", appSecHttpBlockedTemplateHtml=" + + appSecHttpBlockedTemplateHtml + + ", appSecWafTimeout=" + + appSecWafTimeout + + " us, appSecHttpBlockedTemplateJson=" + + appSecHttpBlockedTemplateJson + + ", apiSecurityEnabled=" + + apiSecurityEnabled + + ", apiSecurityRequestSampleRate=" + + apiSecurityRequestSampleRate + + ", cwsEnabled=" + + cwsEnabled + + ", cwsTlsRefresh=" + + cwsTlsRefresh + + ", longRunningTraceEnabled=" + + longRunningTraceEnabled + + ", longRunningTraceFlushInterval=" + + longRunningTraceFlushInterval + + ", elasticsearchBodyEnabled=" + + elasticsearchBodyEnabled + + ", elasticsearchParamsEnabled=" + + elasticsearchParamsEnabled + + ", elasticsearchBodyAndParamsEnabled=" + + elasticsearchBodyAndParamsEnabled + + ", traceFlushInterval=" + + traceFlushIntervalSeconds + + ", injectBaggageAsTagsEnabled=" + + injectBaggageAsTagsEnabled + + ", logsInjectionEnabled=" + + logsInjectionEnabled + + ", sparkTaskHistogramEnabled=" + + sparkTaskHistogramEnabled + + ", jaxRsExceptionAsErrorsEnabled=" + + jaxRsExceptionAsErrorsEnabled + + ", peerServiceDefaultsEnabled=" + + peerServiceDefaultsEnabled + + ", peerServiceComponentOverrides=" + + peerServiceComponentOverrides + + ", removeIntegrationServiceNamesEnabled=" + + removeIntegrationServiceNamesEnabled + + ", spanAttributeSchemaVersion=" + + spanAttributeSchemaVersion + + ", telemetryDebugRequestsEnabled=" + + telemetryDebugRequestsEnabled + + ", telemetryMetricsEnabled=" + + telemetryMetricsEnabled + + '}'; + } } diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java b/features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java index 31c1b78a23..ab7b347fb3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java @@ -2,7 +2,10 @@ import static java.lang.Long.MAX_VALUE; +import android.os.Build; + import java.security.SecureRandom; +import java.util.Locale; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicLong; @@ -24,7 +27,7 @@ public static IdGenerationStrategy fromName(String name) { } public static IdGenerationStrategy fromName(String name, boolean traceId128BitGenerationEnabled) { - switch (name.toUpperCase()) { + switch (name.toUpperCase(Locale.US)) { case "RANDOM": return new Random(traceId128BitGenerationEnabled); case "SEQUENTIAL": @@ -92,8 +95,16 @@ interface ThrowingSupplier { static final class SRandom extends IdGenerationStrategy { private final SecureRandom secureRandom; + private static ThrowingSupplier getSecureRandomSupplier() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return SecureRandom::getInstanceStrong; + }else{ + return SecureRandom::new; + } + } + SRandom(boolean traceId128BitGenerationEnabled) { - this(traceId128BitGenerationEnabled, SecureRandom::getInstanceStrong); + this(traceId128BitGenerationEnabled, getSecureRandomSupplier()); } SRandom(boolean traceId128BitGenerationEnabled, ThrowingSupplier supplier) { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java b/features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java index dc580a3756..c73148a455 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java @@ -329,7 +329,7 @@ public static boolean isIbm8() { } public static boolean isGraalVM() { - return RUNTIME.vendorVersion.toLowerCase().contains("graalvm"); + return RUNTIME.vendorVersion.toLowerCase(Locale.US).contains("graalvm"); } public static String getLangVersion() { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java b/features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java index 89bdb67d1e..a7ec2c0958 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java @@ -3,6 +3,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Locale; /** * These are the old propagation styles that have been deprecated in favor of the propagation styles @@ -26,6 +27,6 @@ public List getNewStyles() { } public static PropagationStyle valueOfConfigName(String configName) { - return valueOf(configName.toUpperCase().trim()); + return valueOf(configName.toUpperCase(Locale.US).trim()); } } diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java b/features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java index 192978cc38..dd6e4b64ec 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java @@ -25,7 +25,7 @@ public enum TracePropagationStyle { NONE; public static TracePropagationStyle valueOfDisplayName(String displayName) { - String convertedName = displayName.toUpperCase().replace(' ', '_'); + String convertedName = displayName.toUpperCase(Locale.US).replace(' ', '_'); // Another name for B3 for cross tracer compatibility switch (convertedName) { case "B3_SINGLE_HEADER": diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/QualifiedClassNameCache.java b/features/dd-trace-core/src/main/java/datadog/trace/api/cache/QualifiedClassNameCache.java deleted file mode 100644 index 715eec5d85..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/QualifiedClassNameCache.java +++ /dev/null @@ -1,61 +0,0 @@ -package datadog.trace.api.cache; - -import java.util.function.Function; - -import datadog.trace.api.Functions; - -public final class QualifiedClassNameCache extends ClassValue { - - private final Function, CharSequence> formatter; - private final Functions.Join joiner; - private final int leafSize; - - public QualifiedClassNameCache( - Function, CharSequence> formatter, Functions.Join joiner) { - this(formatter, joiner, 16); - } - - public QualifiedClassNameCache( - Function, CharSequence> formatter, Functions.Join joiner, int leafSize) { - this.formatter = formatter; - this.joiner = joiner; - this.leafSize = leafSize; - } - - @Override - protected Leaf computeValue(Class type) { - return new Leaf(formatter.apply(type), joiner, leafSize); - } - - static final class Leaf { - - private final CharSequence name; - - private final DDCache cache; - private final Function joiner; - - private Leaf(CharSequence name, Functions.Join joiner, int leafSize) { - this.name = name; - // the class provides a natural bound on the number of elements - // (e.g. the number of methods) - this.cache = DDCaches.newUnboundedCache(leafSize); - this.joiner = joiner.curry(name); - } - - CharSequence get(CharSequence name) { - return cache.computeIfAbsent(name, joiner); - } - - CharSequence getName() { - return name; - } - } - - public CharSequence getClassName(Class klass) { - return get(klass).getName(); - } - - public CharSequence getQualifiedName(Class klass, String qualifier) { - return get(klass).get(qualifier); - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIVisibility.java b/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIVisibility.java deleted file mode 100644 index 79dce10d42..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIVisibility.java +++ /dev/null @@ -1,50 +0,0 @@ -package datadog.trace.api.civisibility; - -import androidx.annotation.Nullable; - -import java.nio.file.Path; -import java.nio.file.Paths; - -import datadog.trace.api.civisibility.noop.NoOpDDTestSession; - -public class CIVisibility { - - private static volatile SessionFactory SESSION_FACTORY = - (projectName, projectRoot, component, startTime) -> NoOpDDTestSession.INSTANCE; - - /** - * This a hook for injecting SessionFactory implementation. It should only be used internally by - * the tracer logic - * - * @param sessionFactory Session factory instance - */ - public static void registerSessionFactory(SessionFactory sessionFactory) { - SESSION_FACTORY = sessionFactory; - } - - /** - * Marks the start of a new test session. - * - * @param projectName The name of the tested project - * @param component The name of the test component (typically corresponds to the name of the - * testing framework used). This will be added as prefix to reported span names - * @param startTime Optional start time in microseconds. If {@code null} is supplied, current time - * will be assumed - * @return Handle to the test session instance - */ - public static DDTestSession startSession( - String projectName, String component, @Nullable Long startTime) { - Path projectRoot = Paths.get("").toAbsolutePath(); - return SESSION_FACTORY.startSession(projectName, projectRoot, component, startTime); - } - - public static DDTestSession startSession( - String projectName, Path projectRoot, String component, @Nullable Long startTime) { - return SESSION_FACTORY.startSession(projectName, projectRoot, component, startTime); - } - - public interface SessionFactory { - DDTestSession startSession( - String projectName, Path projectRoot, String component, Long startTime); - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/CommitInfo.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/CommitInfo.java deleted file mode 100644 index 3cd7182a2d..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/git/CommitInfo.java +++ /dev/null @@ -1,93 +0,0 @@ -package datadog.trace.api.git; - -import java.util.Objects; - -public class CommitInfo { - - public static final CommitInfo NOOP = - new CommitInfo(null, PersonInfo.NOOP, PersonInfo.NOOP, null); - - private final String sha; - private final PersonInfo author; - private final PersonInfo committer; - private final String fullMessage; - - public CommitInfo(final String sha) { - this(sha, PersonInfo.NOOP, PersonInfo.NOOP, null); - } - - public CommitInfo( - final String sha, - final PersonInfo author, - final PersonInfo committer, - final String fullMessage) { - this.sha = sha; - this.author = author; - this.committer = committer; - this.fullMessage = fullMessage; - } - - public String getSha() { - return sha; - } - - public PersonInfo getAuthor() { - return author; - } - - public PersonInfo getCommitter() { - return committer; - } - - public String getFullMessage() { - return fullMessage; - } - - public boolean isEmpty() { - return (sha == null || sha.isEmpty()) - && (author == null || author.isEmpty()) - && (committer == null || committer.isEmpty()) - && (fullMessage == null || fullMessage.isEmpty()); - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final CommitInfo that = (CommitInfo) o; - return Objects.equals(sha, that.sha) - && Objects.equals(author, that.author) - && Objects.equals(committer, that.committer) - && Objects.equals(fullMessage, that.fullMessage); - } - - @Override - public int hashCode() { - int hash = 1; - hash = 31 * hash + (sha == null ? 0 : sha.hashCode()); - hash = 31 * hash + (author == null ? 0 : author.hashCode()); - hash = 31 * hash + (committer == null ? 0 : committer.hashCode()); - hash = 31 * hash + (fullMessage == null ? 0 : fullMessage.hashCode()); - return hash; - } - - @Override - public String toString() { - return "CommitInfo{" - + "sha='" - + sha - + '\'' - + ", author=" - + author - + ", committer=" - + committer - + ", fullMessage='" - + fullMessage - + '\'' - + '}'; - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/EmbeddedGitInfoBuilder.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/EmbeddedGitInfoBuilder.java deleted file mode 100644 index 62f03a49d9..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/git/EmbeddedGitInfoBuilder.java +++ /dev/null @@ -1,77 +0,0 @@ -package datadog.trace.api.git; - -import androidx.annotation.Nullable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -public class EmbeddedGitInfoBuilder implements GitInfoBuilder { - - private static final Logger log = LoggerFactory.getLogger(EmbeddedGitInfoBuilder.class); - - private static final String EMBEDDED_GIT_PROPERTIES_FILE_NAME = "git.properties"; - - private final String resourceName; - - public EmbeddedGitInfoBuilder() { - this(EMBEDDED_GIT_PROPERTIES_FILE_NAME); - } - - EmbeddedGitInfoBuilder(String resourceName) { - this.resourceName = resourceName; - } - - @Override - public GitInfo build(@Nullable String repositoryPath) { - Properties gitProperties = new Properties(); - try (InputStream is = ClassLoader.getSystemResourceAsStream(resourceName)) { - if (is != null) { - gitProperties.load(is); - } else { - log.debug("Could not find embedded Git properties resource: {}", resourceName); - } - } catch (IOException e) { - log.error("Error reading embedded Git properties from {}", resourceName, e); - } - - String commitSha = gitProperties.getProperty("git.commit.id"); - if (commitSha == null) { - commitSha = gitProperties.getProperty("git.commit.id.full"); - } - - String committerTime = gitProperties.getProperty("git.commit.committer.time"); - if (committerTime == null) { - committerTime = gitProperties.getProperty("git.commit.time"); - } - - String authorTime = gitProperties.getProperty("git.commit.author.time"); - if (authorTime == null) { - authorTime = gitProperties.getProperty("git.commit.time"); - } - - return new GitInfo( - gitProperties.getProperty("git.remote.origin.url"), - gitProperties.getProperty("git.branch"), - gitProperties.getProperty("git.tags"), - new CommitInfo( - commitSha, - new PersonInfo( - gitProperties.getProperty("git.commit.user.name"), - gitProperties.getProperty("git.commit.user.email"), - authorTime), - new PersonInfo( - gitProperties.getProperty("git.commit.user.name"), - gitProperties.getProperty("git.commit.user.email"), - committerTime), - gitProperties.getProperty("git.commit.message.full"))); - } - - @Override - public int order() { - return Integer.MAX_VALUE; - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfo.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfo.java deleted file mode 100644 index 4708d3b502..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfo.java +++ /dev/null @@ -1,80 +0,0 @@ -package datadog.trace.api.git; - -import java.util.Objects; - -public class GitInfo { - - public static final GitInfo NOOP = new GitInfo(null, null, null, CommitInfo.NOOP); - - public static final String DD_GIT_REPOSITORY_URL = "DD_GIT_REPOSITORY_URL"; - public static final String DD_GIT_BRANCH = "DD_GIT_BRANCH"; - public static final String DD_GIT_TAG = "DD_GIT_TAG"; - public static final String DD_GIT_COMMIT_SHA = "DD_GIT_COMMIT_SHA"; - public static final String DD_GIT_COMMIT_MESSAGE = "DD_GIT_COMMIT_MESSAGE"; - public static final String DD_GIT_COMMIT_AUTHOR_NAME = "DD_GIT_COMMIT_AUTHOR_NAME"; - public static final String DD_GIT_COMMIT_AUTHOR_EMAIL = "DD_GIT_COMMIT_AUTHOR_EMAIL"; - public static final String DD_GIT_COMMIT_AUTHOR_DATE = "DD_GIT_COMMIT_AUTHOR_DATE"; - public static final String DD_GIT_COMMIT_COMMITTER_NAME = "DD_GIT_COMMIT_COMMITTER_NAME"; - public static final String DD_GIT_COMMIT_COMMITTER_EMAIL = "DD_GIT_COMMIT_COMMITTER_EMAIL"; - public static final String DD_GIT_COMMIT_COMMITTER_DATE = "DD_GIT_COMMIT_COMMITTER_DATE"; - - private final String repositoryURL; - private final String branch; - private final String tag; - private final CommitInfo commit; - - public GitInfo(String repositoryURL, String branch, String tag, CommitInfo commit) { - this.repositoryURL = repositoryURL; - this.branch = branch; - this.tag = tag; - this.commit = commit; - } - - public String getRepositoryURL() { - return repositoryURL; - } - - public String getBranch() { - return branch; - } - - public String getTag() { - return tag; - } - - public CommitInfo getCommit() { - return commit; - } - - public boolean isEmpty() { - return (repositoryURL == null || repositoryURL.isEmpty()) - && (branch == null || branch.isEmpty()) - && (tag == null || tag.isEmpty()) - && (commit == null || commit.isEmpty()); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - GitInfo gitInfo = (GitInfo) o; - return Objects.equals(repositoryURL, gitInfo.repositoryURL) - && Objects.equals(branch, gitInfo.branch) - && Objects.equals(tag, gitInfo.tag) - && Objects.equals(commit, gitInfo.commit); - } - - @Override - public int hashCode() { - int hash = 1; - hash = 31 * hash + (repositoryURL == null ? 0 : repositoryURL.hashCode()); - hash = 31 * hash + (branch == null ? 0 : branch.hashCode()); - hash = 31 * hash + (tag == null ? 0 : tag.hashCode()); - hash = 31 * hash + (commit == null ? 0 : commit.hashCode()); - return hash; - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoBuilder.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoBuilder.java deleted file mode 100644 index 9951d5df1b..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoBuilder.java +++ /dev/null @@ -1,9 +0,0 @@ -package datadog.trace.api.git; - -import androidx.annotation.Nullable; - -public interface GitInfoBuilder { - GitInfo build(@Nullable String repositoryPath); - - int order(); -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoProvider.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoProvider.java deleted file mode 100644 index d1c23f01e4..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitInfoProvider.java +++ /dev/null @@ -1,167 +0,0 @@ -package datadog.trace.api.git; - -import androidx.annotation.Nullable; - -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Predicate; - -import datadog.trace.api.cache.DDCache; -import datadog.trace.api.cache.DDCaches; -import datadog.trace.util.Strings; - -public class GitInfoProvider { - - public static final GitInfoProvider INSTANCE; - - static { - INSTANCE = new GitInfoProvider(); - INSTANCE.registerGitInfoBuilder(new UserSuppliedGitInfoBuilder()); - } - - private volatile Collection builders = Collections.emptyList(); - - // in regular cases git info has to be built only once, - // but there is a rare exception: - // when attaching to a Gradle Daemon, - // it is possible to have builds from multiple repositories - // executed in the same process; - // 4 is chosen somewhat randomly, since we want to make memory footprint small - // and having more than 4 builds from different repos running in parallel - // in the same daemon is unlikely - private final DDCache gitInfoCache = DDCaches.newFixedSizeCache(4); - - public GitInfo getGitInfo() { - return getGitInfo(null); - } - - public GitInfo getGitInfo(@Nullable String repositoryPath) { - if (repositoryPath == null) { - repositoryPath = Paths.get("").toAbsolutePath().toString(); - } - return gitInfoCache.computeIfAbsent(repositoryPath, this::buildGitInfo); - } - - private GitInfo buildGitInfo(String repositoryPath) { - Evaluator evaluator = new Evaluator(repositoryPath, builders); - return new GitInfo( - evaluator.get( - gi -> GitUtils.filterSensitiveInfo(gi.getRepositoryURL()), - GitInfoProvider::validateGitRemoteUrl), - evaluator.get(GitInfo::getBranch, Strings::isNotBlank), - evaluator.get(GitInfo::getTag, Strings::isNotBlank), - new CommitInfo( - evaluator.get(gi1 -> gi1.getCommit().getSha(), Strings::isNotBlank), - new PersonInfo( - evaluator.getIfCommitShaMatches( - gi -> gi.getCommit().getAuthor().getName(), Strings::isNotBlank), - evaluator.getIfCommitShaMatches( - gi -> gi.getCommit().getAuthor().getEmail(), Strings::isNotBlank), - evaluator.getIfCommitShaMatches( - gi -> gi.getCommit().getAuthor().getIso8601Date(), Strings::isNotBlank)), - new PersonInfo( - evaluator.getIfCommitShaMatches( - gi -> gi.getCommit().getCommitter().getName(), Strings::isNotBlank), - evaluator.getIfCommitShaMatches( - gi -> gi.getCommit().getCommitter().getEmail(), Strings::isNotBlank), - evaluator.getIfCommitShaMatches( - gi -> gi.getCommit().getCommitter().getIso8601Date(), Strings::isNotBlank)), - evaluator.getIfCommitShaMatches( - gi -> gi.getCommit().getFullMessage(), Strings::isNotBlank))); - } - - private static boolean validateGitRemoteUrl(String s) { - // we cannot work with URL that uses "file://" protocol - return Strings.isNotBlank(s) && !s.startsWith("file:"); - } - - /** - * Uses provided GitInfoBuilder instances to get GitInfo data. - * - *

    Provided builders are sorted according to priority: those builders that are first in the - * list have higher priority. - * - *

    GitInfo is evaluated at most once for each builder, and the evaluation is lazy: if all - * required info can be retrieved from a higher-priority builder, those with lower priority will - * not be evaluated. - */ - private static final class Evaluator { - private final String repositoryPath; - private final Map infos; - - private Evaluator(String repositoryPath, Collection builders) { - this.repositoryPath = repositoryPath; - this.infos = new LinkedHashMap<>(); - for (GitInfoBuilder builder : builders) { - infos.put(builder, null); - } - } - - private String get(Function function, Predicate validator) { - return get(function, validator, false); - } - - /** - * If a builder with a higher priority has commit SHA that differs from that of a builder with - * lower priority, lower-priority info will be ignored. - */ - private String getIfCommitShaMatches( - Function function, Predicate validator) { - return get(function, validator, true); - } - - private String get( - Function function, - Predicate validator, - boolean checkShaIntegrity) { - String commitSha = null; - for (Map.Entry e : infos.entrySet()) { - GitInfo info = e.getValue(); - if (info == null) { - GitInfoBuilder builder = e.getKey(); - info = builder.build(repositoryPath); - e.setValue(info); - } - - if (checkShaIntegrity) { - CommitInfo currentCommit = info.getCommit(); - String currentCommitSha = currentCommit != null ? currentCommit.getSha() : null; - if (Strings.isNotBlank(currentCommitSha)) { - if (commitSha == null) { - commitSha = currentCommitSha; - } else if (!commitSha.equals(currentCommitSha)) { - // We already have a commit SHA from source that has higher priority. - // Commit SHA from current source is different, so we have to skip it - continue; - } - } - } - - String result = function.apply(info); - if (validator.test(result)) { - return result; - } - } - return null; - } - } - - public synchronized void registerGitInfoBuilder(GitInfoBuilder builder) { - List updatedBuilders = new ArrayList<>(builders); - updatedBuilders.add(builder); - updatedBuilders.sort(Comparator.comparingInt(GitInfoBuilder::order)); - builders = updatedBuilders; - gitInfoCache.clear(); - } - - public synchronized void invalidateCache() { - gitInfoCache.clear(); - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitUtils.java deleted file mode 100644 index 036f569880..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/git/GitUtils.java +++ /dev/null @@ -1,228 +0,0 @@ -package datadog.trace.api.git; - -import static datadog.trace.api.git.RawParseUtils.decode; -import static datadog.trace.api.git.RawParseUtils.nextLF; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.regex.Pattern; -import java.util.zip.DataFormatException; -import java.util.zip.Inflater; - -public class GitUtils { - - private static final Pattern ORIGIN_PATTERN = Pattern.compile("origin/", Pattern.LITERAL); - private static final Pattern REFS_HEADS_PATTERN = Pattern.compile("refs/heads/", Pattern.LITERAL); - private static final Pattern REFS_TAGS_PATTERN = Pattern.compile("refs/tags/", Pattern.LITERAL); - private static final Pattern TAGS_PATTERN = Pattern.compile("tags/", Pattern.LITERAL); - - private static final Logger log = LoggerFactory.getLogger(GitUtils.class); - - /** - * Normalizes Git tag references: - * - *

      - *
    • refs/tags/my-tag -> my tag - *
    - * - * @param rawTagRef - * @return git reference normalized. - */ - public static String normalizeTag(final String rawTagRef) { - return normalizeRef(rawTagRef); - } - - /** - * Normalizes Git branch references: - * - *
      - *
    • origin/my-branch -> my-branch - *
    • refs/heads/my-branch -> my-branch - *
    - * - *

    If the reference starts with "tags/" or contains "/tags/",null is returned - * - * @param rawBranchRef - * @return git reference normalized. - */ - public static String normalizeBranch(final String rawBranchRef) { - if (isTagReference(rawBranchRef)) { - return null; - } else { - return normalizeRef(rawBranchRef); - } - } - - public static boolean isTagReference(final String ref) { - return ref != null && (ref.startsWith("tags/") || ref.contains("/tags/")); - } - - private static String normalizeRef(final String rawRef) { - if (rawRef == null || rawRef.isEmpty()) { - return null; - } - - String ref = rawRef; - if (ref.startsWith("origin")) { - ref = ORIGIN_PATTERN.matcher(ref).replaceAll(""); - } else if (ref.startsWith("refs/heads")) { - ref = REFS_HEADS_PATTERN.matcher(ref).replaceAll(""); - } - - if (ref.startsWith("refs/tags")) { - return REFS_TAGS_PATTERN.matcher(ref).replaceAll(""); - } else if (ref.startsWith("tags")) { - return TAGS_PATTERN.matcher(ref).replaceAll(""); - } - - return ref; - } - - private static final Pattern SSH_PROTOCOL_AND_USER_INFO = Pattern.compile("^(ssh://).*?@"); - - /** - * Removes the user info of a certain URL. E.g: https://user:password@host.com/path -> - * https://host.com/path - * - * @param urlStr - * @return url without user info. - */ - public static String filterSensitiveInfo(final String urlStr) { - if (urlStr == null || urlStr.isEmpty()) { - return null; - } - try { - if (urlStr.startsWith("http")) { - final URI url = new URI(urlStr); - final String userInfo = url.getRawUserInfo(); - return Pattern.compile(userInfo + "@", Pattern.LITERAL).matcher(urlStr).replaceAll(""); - } else { - return SSH_PROTOCOL_AND_USER_INFO.matcher(urlStr).replaceAll("$1"); - } - } catch (final Exception ex) { - return urlStr; - } - } - - /** - * Splits the git author in the form `John Doe ` in a PersonInfo with name: - * John Doe and email: john.doe@email.com - * - * @param rawAuthor - * @return PersonInfo - */ - public static PersonInfo splitAuthorAndEmail(String rawAuthor) { - if (rawAuthor == null || rawAuthor.isEmpty()) { - return PersonInfo.NOOP; - } - - final byte[] raw = rawAuthor.getBytes(StandardCharsets.UTF_8); - final int nameB = 0; - - // First, we find the index where the email starts and ends: - final int emailB = nextLF(raw, nameB, '<'); - final int emailE = nextLF(raw, emailB, '>'); - if (emailB >= raw.length - || raw[emailB] == '\n' - || (emailE >= raw.length - 1 && raw[emailE - 1] != '>')) { - return PersonInfo.NOOP; - } - - // We need to find which is the index where the name ends, - // using the relative position where the email starts. - final int nameEnd = emailB - 2 >= nameB && raw[emailB - 2] == ' ' ? emailB - 2 : emailB - 1; - - // Once we have the indexes where the name starts and ends - // we can extract the name. - final String name = decode(raw, nameB, nameEnd); - - // Same approach to extract the email, using the indexes - // where the email starts and ends. - final String email = decode(raw, emailB, emailE - 1); - - return new PersonInfo(name, email); - } - - /** - * Decompress the byte array passed as argument using Java Inflater. The git objects are stored - * using ZLib compression. - * - *

    If the decompression process requires a preset dictionary or the input is not enough, we - * return null. - * - * @param bytes compress data - * @return decompressed data or null - * @throws DataFormatException - */ - public static byte[] inflate(final byte[] bytes) throws DataFormatException { - try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) { - - // Git objects are compressed with ZLib. - // We need to decompress it using Inflater. - final Inflater ifr = new Inflater(); - try { - ifr.setInput(bytes); - final byte[] tmp = new byte[4 * 1024]; - while (!ifr.finished()) { - final int size = ifr.inflate(tmp); - if (size != 0) { - baos.write(tmp, 0, size); - } else { - // Inflater can return !finished but 0 bytes inflated. - if (ifr.needsDictionary()) { - logErrorInflating( - "The data was compressed using a preset dictionary. We cannot decompress it."); - return null; - } else if (ifr.needsInput()) { - logErrorInflating("The provided data is not enough. It might be corrupted"); - return null; - } else { - // At this point, neither dictionary nor input is needed. - // We break the loop and we will use the decompressed data that we already have. - break; - } - } - } - - return baos.toByteArray(); - } finally { - ifr.end(); - } - } catch (final IOException e) { - return null; - } - } - - private static void logErrorInflating(final String reason) { - log.warn("Could not decompressed git object: Reason {}", reason); - } - - /** - * Checks if the provided string is a valid commit SHA: - * - *

      - *
    • length >= 40 - *
    • every character is a hexadecimal digit - *
    - */ - public static boolean isValidCommitSha(final String commitSha) { - if (commitSha == null || commitSha.length() < 40) { - return false; - } - for (char c : commitSha.toCharArray()) { - if (!isHex(c)) { - return false; - } - } - return true; - } - - private static boolean isHex(char c) { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/PersonInfo.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/PersonInfo.java deleted file mode 100644 index 3b1019f894..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/git/PersonInfo.java +++ /dev/null @@ -1,103 +0,0 @@ -package datadog.trace.api.git; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Objects; -import java.util.TimeZone; - -public class PersonInfo { - - public static final PersonInfo NOOP = new PersonInfo(); - - private static final String DATE_FORMAT_ISO8601 = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; - - private final String name; - private final String email; - private final String iso8601Date; - - public PersonInfo() { - this(null, null, 0, 0); - } - - public PersonInfo(final String name, final String email) { - this(name, email, 0, 0); - } - - public PersonInfo(final String name, final String email, final String iso8601date) { - this.name = name; - this.email = email; - iso8601Date = iso8601date; - } - - public PersonInfo(String name, String email, long when, int tzOffset) { - this.name = name; - this.email = email; - iso8601Date = buildISO8601Date(when); - } - - public String getName() { - return name; - } - - public String getEmail() { - return email; - } - - public String getIso8601Date() { - return iso8601Date; - } - - public boolean isEmpty() { - return (name == null || name.isEmpty()) - && (email == null || email.isEmpty()) - && (iso8601Date == null || iso8601Date.isEmpty()); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - PersonInfo that = (PersonInfo) o; - return Objects.equals(name, that.name) - && Objects.equals(email, that.email) - && Objects.equals(iso8601Date, that.iso8601Date); - } - - @Override - public int hashCode() { - int hash = 1; - hash = 31 * hash + (name == null ? 0 : name.hashCode()); - hash = 31 * hash + (email == null ? 0 : email.hashCode()); - hash = 31 * hash + (iso8601Date == null ? 0 : iso8601Date.hashCode()); - return hash; - } - - @Override - public String toString() { - return "PersonInfo{" - + "name='" - + name - + '\'' - + ", email='" - + email - + '\'' - + ", ISO8601Date='" - + iso8601Date - + '\'' - + '}'; - } - - private static String buildISO8601Date(final long when) { - if (when <= 0) { - return null; - } - - final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_ISO8601); - sdf.setTimeZone(TimeZone.getTimeZone("UTC")); - return sdf.format(new Date(when)); - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/RawParseUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/RawParseUtils.java deleted file mode 100644 index 40d91a2634..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/git/RawParseUtils.java +++ /dev/null @@ -1,392 +0,0 @@ -package datadog.trace.api.git; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import java.nio.ByteBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CodingErrorAction; -import java.util.Arrays; - -/** - * Contains utility methods to be used in the byte[] content of a certain Git object. This class is - * based on the RawParseUtils class which is kept in the JGit library. - * https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java - */ -public final class RawParseUtils { - - private RawParseUtils() {} - - public static final byte[] COMMITTER = "committer ".getBytes(); - public static final byte[] AUTHOR = "author ".getBytes(); - - private static final byte[] digits10; - - static { - digits10 = new byte['9' + 1]; - Arrays.fill(digits10, (byte) -1); - for (char i = '0'; i <= '9'; i++) { - digits10[i] = (byte) (i - '0'); - } - } - - /** - * Locate the position of the commit message body. - * - * @param b buffer to scan. - * @param ptr position in buffer to start the scan at. Most callers should pass 0 to ensure the - * scan starts from the beginning of the commit buffer. - * @return position of the user's message buffer. - */ - public static int commitMessage(final byte[] b, int ptr) { - final int sz = b.length; - if (ptr == 0) { - ptr += 46; // skip the "tree ..." line. - } - while (ptr < sz && b[ptr] == 'p') { - ptr += 48; // skip this parent. - } - - // Skip any remaining header lines, ignoring what their actual - // header line type is. This is identical to the logic for a tag. - // - return tagMessage(b, ptr); - } - - /** - * Locate the position of the tag message body. - * - * @param b buffer to scan. - * @param ptr position in buffer to start the scan at. Most callers should pass 0 to ensure the - * scan starts from the beginning of the tag buffer. - * @return position of the user's message buffer. - */ - public static int tagMessage(final byte[] b, int ptr) { - final int sz = b.length; - if (ptr == 0) { - ptr += 48; // skip the "object ..." line. - } - while (ptr < sz && b[ptr] != '\n') { - ptr = nextLF(b, ptr); - } - if (ptr < sz && b[ptr] == '\n') { - return ptr + 1; - } - return -1; - } - - /** - * Locate the "committer " header line data. - * - * @param b buffer to scan. - * @param ptr position in buffer to start the scan at. Most callers should pass 0 to ensure the - * scan starts from the beginning of the commit buffer and does not accidentally look at - * message body. - * @return position just after the space in "committer ", so the first character of the - * committer's name. If no committer header can be located -1 is returned. - */ - public static int committer(final byte[] b, int ptr) { - final int sz = b.length; - if (ptr == 0) { - ptr += 46; // skip the "tree ..." line. - } - while (ptr < sz && b[ptr] == 'p') { - ptr += 48; // skip this parent. - } - if (ptr < sz && b[ptr] == 'a') { - ptr = nextLF(b, ptr); - } - return match(b, ptr, COMMITTER); - } - - /** - * Locate the "author " header line data. - * - * @param b buffer to scan. - * @param ptr position in buffer to start the scan at. Most callers should pass 0 to ensure the - * scan starts from the beginning of the commit buffer and does not accidentally look at - * message body. - * @return position just after the space in "author ", so the first character of the author's - * name. If no author header can be located -1 is returned. - */ - public static final int author(final byte[] b, int ptr) { - final int sz = b.length; - if (ptr == 0) { - ptr += 46; // skip the "tree ..." line. - } - while (ptr < sz && b[ptr] == 'p') { - ptr += 48; // skip this parent. - } - return match(b, ptr, AUTHOR); - } - - /** - * Locate the first position after the next LF. - * - *

    This method stops on the first '\n' it finds. - * - * @param b buffer to scan. - * @param ptr position within buffer to start looking for LF at. - * @return new position just after the first LF found. - */ - public static int nextLF(final byte[] b, final int ptr) { - return next(b, ptr, '\n'); - } - - /** - * Locate the first position after either the given character or LF. - * - *

    This method stops on the first match it finds from either chrA or '\n'. - * - * @param b buffer to scan. - * @param ptr position within buffer to start looking for chrA or LF at. - * @param chrA character to find. - * @return new position just after the first chrA or LF to be found. - */ - public static int nextLF(final byte[] b, int ptr, final char chrA) { - final int sz = b.length; - while (ptr < sz) { - final byte c = b[ptr++]; - if (c == chrA || c == '\n') { - return ptr; - } - } - return ptr; - } - - /** - * Locate the first position after a given character. - * - * @param b buffer to scan. - * @param ptr position within buffer to start looking for chrA at. - * @param chrA character to find. - * @return new position just after chrA. - */ - public static int next(final byte[] b, int ptr, final char chrA) { - final int sz = b.length; - while (ptr < sz) { - if (b[ptr++] == chrA) { - return ptr; - } - } - return ptr; - } - - /** - * Determine if b[ptr] matches src. - * - * @param b the buffer to scan. - * @param ptr first position within b, this should match src[0]. - * @param src the buffer to test for equality with b. - * @return ptr + src.length if b[ptr..src.length] == src; else -1. - */ - public static int match(final byte[] b, int ptr, final byte[] src) { - if (ptr + src.length > b.length) { - return -1; - } - for (int i = 0; i < src.length; i++, ptr++) { - if (b[ptr] != src[i]) { - return -1; - } - } - return ptr; - } - - /** - * Decode a region of the buffer under the specified character set if possible. - * - *

    If the byte stream cannot be decoded that way, the platform default is tried and if that too - * fails, the fail-safe ISO-8859-1 encoding is tried. - * - * @param buffer buffer to pull raw bytes from. - * @param start first position within the buffer to take data from. - * @param end one position past the last location within the buffer to take data from. - * @return a string representation of the range [start,end), after decoding the - * region through the specified character set. - */ - public static String decode(final byte[] buffer, final int start, final int end) { - final ByteBuffer b = ByteBuffer.wrap(buffer, start, end - start); - b.mark(); - - try { - final CharsetDecoder d = UTF_8.newDecoder(); - d.onMalformedInput(CodingErrorAction.REPORT); - d.onUnmappableCharacter(CodingErrorAction.REPORT); - return d.decode(b).toString(); - } catch (final CharacterCodingException e) { - b.reset(); - - // Fall back to an ISO-8859-1 style encoding. At least all of - // the bytes will be present in the output. - // - return extractBinaryString(buffer, start, end); - } - } - - /** - * Decode a region of the buffer under the ISO-8859-1 encoding. - * - *

    Each byte is treated as a single character in the 8859-1 character encoding, performing a - * raw binary->char conversion. - * - * @param buffer buffer to pull raw bytes from. - * @param start first position within the buffer to take data from. - * @param end one position past the last location within the buffer to take data from. - * @return a string representation of the range [start,end). - */ - public static String extractBinaryString(final byte[] buffer, final int start, final int end) { - final StringBuilder r = new StringBuilder(end - start); - for (int i = start; i < end; i++) { - r.append((char) (buffer[i] & 0xff)); - } - return r.toString(); - } - - /** - * Get last index of {@code ch} in raw, trimming spaces. - * - * @param raw buffer to scan. - * @param ch character to find. - * @param pos starting position. - * @return last index of {@code ch} in raw, trimming spaces. - * @since 4.1 - */ - public static int lastIndexOfTrim(final byte[] raw, final char ch, int pos) { - while (pos >= 0 && raw[pos] == ' ') { - pos--; - } - - while (pos >= 0 && raw[pos] != ch) { - pos--; - } - - return pos; - } - - /** - * Parse a base 10 numeric from a sequence of ASCII digits into a long. - * - *

    Digit sequences can begin with an optional run of spaces before the sequence, and may start - * with a '+' or a '-' to indicate sign position. Any other characters will cause the method to - * stop and return the current result to the caller. - * - * @param b buffer to scan. - * @param ptr position within buffer to start parsing digits at. - * @return the value at this location; 0 if the location is not a valid numeric. - */ - public static long parseLongBase10(final byte[] b, int ptr) { - long r = 0; - int sign = 0; - try { - final int sz = b.length; - while (ptr < sz && b[ptr] == ' ') { - ptr++; - } - if (ptr >= sz) { - return 0; - } - - switch (b[ptr]) { - case '-': - sign = -1; - ptr++; - break; - case '+': - ptr++; - break; - default: - break; - } - - while (ptr < sz) { - final byte v = digits10[b[ptr]]; - if (v < 0) { - break; - } - r = (r * 10) + v; - ptr++; - } - } catch (final ArrayIndexOutOfBoundsException e) { - // Not a valid digit. - } - return sign < 0 ? -r : r; - } - - /** - * Parse a base 10 numeric from a sequence of ASCII digits into an int. - * - *

    Digit sequences can begin with an optional run of spaces before the sequence, and may start - * with a '+' or a '-' to indicate sign position. Any other characters will cause the method to - * stop and return the current result to the caller. - * - * @param b buffer to scan. - * @param ptr position within buffer to start parsing digits at. - * @return the value at this location; 0 if the location is not a valid numeric. - */ - public static int parseBase10(final byte[] b, int ptr) { - int r = 0; - int sign = 0; - try { - final int sz = b.length; - while (ptr < sz && b[ptr] == ' ') { - ptr++; - } - if (ptr >= sz) { - return 0; - } - - switch (b[ptr]) { - case '-': - sign = -1; - ptr++; - break; - case '+': - ptr++; - break; - default: - break; - } - - while (ptr < sz) { - final byte v = digits10[b[ptr]]; - if (v < 0) { - break; - } - r = (r * 10) + v; - ptr++; - } - } catch (final ArrayIndexOutOfBoundsException e) { - // Not a valid digit. - } - return sign < 0 ? -r : r; - } - - /** - * Parse a Git style timezone string. - * - *

    The sequence "-0315" will be parsed as the numeric value -195, as the lower two positions - * count minutes, not 100ths of an hour. - * - * @param b buffer to scan. - * @param ptr position within buffer to start parsing digits at. - * @return the timezone at this location, expressed in minutes. - * @since 4.1 - */ - public static int parseTimeZoneOffset(final byte[] b, final int ptr) { - final int v = parseBase10(b, ptr); - final int tzMins = v % 100; - final int tzHours = v / 100; - return tzHours * 60 + tzMins; - } - - public static int findByte(final byte[] bytes, final byte b) { - int i = 0; - while (i < bytes.length) { - if (bytes[i] == b) { - return i; - } - i += 1; - } - return -1; - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java b/features/dd-trace-core/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java deleted file mode 100644 index 5df26b5ecd..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java +++ /dev/null @@ -1,108 +0,0 @@ -package datadog.trace.api.git; - -import static datadog.trace.api.git.GitInfo.DD_GIT_BRANCH; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_AUTHOR_DATE; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_AUTHOR_EMAIL; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_AUTHOR_NAME; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_COMMITTER_DATE; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_COMMITTER_EMAIL; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_COMMITTER_NAME; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_MESSAGE; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_SHA; -import static datadog.trace.api.git.GitInfo.DD_GIT_REPOSITORY_URL; -import static datadog.trace.api.git.GitInfo.DD_GIT_TAG; - -import androidx.annotation.Nullable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import datadog.trace.api.Config; -import datadog.trace.api.config.GeneralConfig; -import datadog.trace.bootstrap.instrumentation.api.Tags; - -public class UserSuppliedGitInfoBuilder implements GitInfoBuilder { - - private static final Logger log = LoggerFactory.getLogger(UserSuppliedGitInfoBuilder.class); - - @Override - public GitInfo build(@Nullable String repositoryPath) { - String gitRepositoryUrl = System.getenv(DD_GIT_REPOSITORY_URL); - if (gitRepositoryUrl == null) { - gitRepositoryUrl = Config.get().getGlobalTags().get(Tags.GIT_REPOSITORY_URL); - } - - // The user can set the DD_GIT_BRANCH manually but - // using the value returned by the CI Provider, so - // we need to normalize the value. Also, it can contain - // the tag (e.g. origin/tags/0.1.0) - String gitTag = System.getenv(DD_GIT_TAG); - String gitBranch = null; - final String gitBranchOrTag = System.getenv(DD_GIT_BRANCH); - if (gitBranchOrTag != null) { - if (!GitUtils.isTagReference(gitBranchOrTag)) { - gitBranch = GitUtils.normalizeBranch(gitBranchOrTag); - } else if (gitTag == null) { - gitTag = GitUtils.normalizeTag(gitBranchOrTag); - } - } - - String gitCommitSha = System.getenv(DD_GIT_COMMIT_SHA); - if (gitCommitSha == null) { - gitCommitSha = Config.get().getGlobalTags().get(Tags.GIT_COMMIT_SHA); - } - - final String gitCommitMessage = System.getenv(DD_GIT_COMMIT_MESSAGE); - final String gitCommitAuthorName = System.getenv(DD_GIT_COMMIT_AUTHOR_NAME); - final String gitCommitAuthorEmail = System.getenv(DD_GIT_COMMIT_AUTHOR_EMAIL); - final String gitCommitAuthorDate = System.getenv(DD_GIT_COMMIT_AUTHOR_DATE); - final String gitCommitCommitterName = System.getenv(DD_GIT_COMMIT_COMMITTER_NAME); - final String gitCommitCommitterEmail = System.getenv(DD_GIT_COMMIT_COMMITTER_EMAIL); - final String gitCommitCommitterDate = System.getenv(DD_GIT_COMMIT_COMMITTER_DATE); - - GitInfo gitInfo = - new GitInfo( - gitRepositoryUrl, - gitBranch, - gitTag, - new CommitInfo( - gitCommitSha, - new PersonInfo(gitCommitAuthorName, gitCommitAuthorEmail, gitCommitAuthorDate), - new PersonInfo( - gitCommitCommitterName, gitCommitCommitterEmail, gitCommitCommitterDate), - gitCommitMessage)); - - if (!gitInfo.isEmpty()) { - // if there is any git metadata supplied by the user, we want to check that repo URL and - // commit SHA are valid - String repoUrl = gitInfo.getRepositoryURL(); - if (repoUrl == null || repoUrl.isEmpty()) { - log.error( - "Could not resolve git repository URL (can be provided via " - + GitInfo.DD_GIT_REPOSITORY_URL - + " env var, " - + GeneralConfig.TAGS - + " config property or by embedding git metadata at build time)"); - } - - String commitSha = gitInfo.getCommit().getSha(); - if (!GitUtils.isValidCommitSha(commitSha)) { - log.error( - "Git commit SHA could not be resolved or is invalid: " - + commitSha - + " (can be provided via " - + GitInfo.DD_GIT_COMMIT_SHA - + " env var, " - + GeneralConfig.TAGS - + " config property or by embedding git metadata at build time; must be a full-length SHA_"); - } - } - - return gitInfo; - } - - @Override - public int order() { - return 0; - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java index 4d711a3c69..fc2749fd5d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java @@ -1,4 +1,3 @@ package datadog.trace.api.profiling; -/** A generic interface for observable types served by {@linkplain ProfilingListenersRegistry} */ public interface ObservableType {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListener.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListener.java deleted file mode 100644 index 423479d699..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListener.java +++ /dev/null @@ -1,10 +0,0 @@ -package datadog.trace.api.profiling; - -/** - * A simple generified listener/observer type - * - * @param the observed data type - */ -public interface ProfilingListener { - void onData(Type observable); -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListeners.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListeners.java deleted file mode 100644 index 1e75ead09b..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListeners.java +++ /dev/null @@ -1,44 +0,0 @@ -package datadog.trace.api.profiling; - -import java.util.Collection; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * A listener host. Allows registering listeners and firing 'on-data' events - * - * @param the observable type - */ -public final class ProfilingListeners { - private final Collection> listeners = new ConcurrentLinkedQueue<>(); - - ProfilingListeners() {} - - /** - * Notify all listeners about the data - * - * @param data the observed data - */ - public void fireOnData(Type data) { - for (ProfilingListener listener : listeners) { - listener.onData(data); - } - } - - /** - * Add a listener - * - * @param listener listener instance - */ - public void addListener(ProfilingListener listener) { - listeners.add(listener); - } - - /** - * Remove a listener - * - * @param listener listener instance - */ - public void removeListener(ProfilingListener listener) { - listeners.remove(listener); - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListenersRegistry.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListenersRegistry.java deleted file mode 100644 index b35efde106..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingListenersRegistry.java +++ /dev/null @@ -1,28 +0,0 @@ -package datadog.trace.api.profiling; - -/** - * A {@linkplain ProfilingListeners} registry. Allows retrieving a specific {@linkplain - * ProfilingListeners} instance for the given observable type. - */ -public final class ProfilingListenersRegistry { - private static final ClassValue> listenersPerType = - new ClassValue>() { - @Override - protected ProfilingListeners computeValue(Class type) { - return new ProfilingListeners<>(); - } - }; - - private ProfilingListenersRegistry() {} - - /** - * Retrieve the {@Profiling} - * - * @param type - * @param - * @return - */ - public static ProfilingListeners getHost(Class type) { - return (ProfilingListeners) listenersPerType.get(type); - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/AdaptiveSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/AdaptiveSampler.java deleted file mode 100644 index 09d8f78801..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/AdaptiveSampler.java +++ /dev/null @@ -1,317 +0,0 @@ -package datadog.trace.api.sampling; - -import androidx.annotation.Nullable; - -import java.time.Duration; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.atomic.LongAdder; - -import datadog.trace.util.AgentTaskScheduler; -import datadog.trace.util.AgentTaskScheduler.Task; - -/** - * An adaptive streaming (non-remembering) sampler. - * - *

    The sampler attempts to generate at most N samples per fixed time window in randomized - * fashion. For this it divides the timeline into 'sampling windows' of constant duration. Each - * sampling window targets a constant number of samples which are scattered randomly (uniform - * distribution) throughout the window duration and once the window is over the real stats of - * incoming events and the number of gathered samples is used to recompute the target probability to - * use in the following window. - * - *

    This will guarantee, if the windows are not excessively large, that the sampler will be able - * to adjust to the changes in the rate of incoming events. - * - *

    However, there might so rapid changes in incoming events rate that we will optimistically use - * all allowed samples well before the current window has elapsed or, on the other end of the - * spectrum, there will be to few incoming events and the sampler will not be able to generate the - * target number of samples. - * - *

    To smooth out these hiccups the sampler maintains an under-sampling budget which can be used - * to compensate for too rapid changes in the incoming events rate and maintain the target average - * number of samples per window. - */ -public class AdaptiveSampler implements Sampler { - - private static final class Counts { - private final LongAdder testCount = new LongAdder(); - private static final AtomicLongFieldUpdater SAMPLE_COUNT = - AtomicLongFieldUpdater.newUpdater(Counts.class, "sampleCount"); - private volatile long sampleCount = 0L; - - void addTest() { - testCount.increment(); - } - - boolean addSample(final long limit) { - return SAMPLE_COUNT.getAndAccumulate(this, limit, (prev, lim) -> Math.min(prev + 1, lim)) - < limit; - } - - void addSample() { - SAMPLE_COUNT.incrementAndGet(this); - } - - void reset() { - testCount.reset(); - SAMPLE_COUNT.set(this, 0); - } - - long sampleCount() { - return SAMPLE_COUNT.get(this); - } - - long testCount() { - return testCount.sum(); - } - } - - @FunctionalInterface - public interface ConfigListener { - void onWindowRoll( - long totalCount, long sampledCount, long budget, double totalAverage, double probability); - } - - /* - * Exponential Moving Average (EMA) last element weight. - * Check out papers about using EMA for streaming data - eg. - * https://nestedsoftware.com/2018/04/04/exponential-moving-average-on-streaming-data-4hhl.24876.html - * - * Corresponds to 'lookback' of N values: - * With T being the index of the most recent value the lookback of N values means that for all values with index - * T-K, where K > N, the relative weight of that value computed as (1 - alpha)^K is less or equal than the - * weight assigned by a plain arithmetic average (= 1/N). - */ - private final double emaAlpha; - private final int samplesPerWindow; - - private final AtomicReference countsRef; - - // these attributes need to be volatile since they are accessed from user threds as well as the - // maintenance one - private volatile double probability = 1d; - private volatile long samplesBudget; - - // these attributes are accessed solely from the window maintenance thread - private double totalCountRunningAverage = 0d; - private double avgSamples; - - private final int budgetLookback; - private final double budgetAlpha; - - // accessed exclusively from the window maintenance task - does not require any synchronization - private int countsSlotIdx = 0; - private final Counts[] countsSlots = new Counts[] {new Counts(), new Counts()}; - - private final ConfigListener listener; - - private final Duration windowDuration; - private final AgentTaskScheduler taskScheduler; - - /** - * Create a new sampler instance - * - * @param windowDuration the sampling window duration - * @param samplesPerWindow the maximum number of samples in the sampling window - * @param averageLookback the number of windows to consider in averaging the sampling rate - * @param budgetLookback the number of windows to consider when computing the sampling budget - * @param listener an optional listener receiving the sampler config changes - * @param taskScheduler agent task scheduler to use for periodic rolls - */ - protected AdaptiveSampler( - final Duration windowDuration, - final int samplesPerWindow, - final int averageLookback, - final int budgetLookback, - final @Nullable ConfigListener listener, - final AgentTaskScheduler taskScheduler, - boolean startSampler) { - - if (averageLookback < 1) { - throw new IllegalArgumentException("'averageLookback' argument must be at least 1"); - } - if (budgetLookback < 1) { - throw new IllegalArgumentException("'budgetLookback' argument must be at least 1"); - } - this.samplesPerWindow = samplesPerWindow; - this.budgetLookback = budgetLookback; - samplesBudget = samplesPerWindow + (long) budgetLookback * samplesPerWindow; - emaAlpha = computeIntervalAlpha(averageLookback); - budgetAlpha = computeIntervalAlpha(budgetLookback); - countsRef = new AtomicReference<>(countsSlots[0]); - this.listener = listener; - if (listener != null) { - listener.onWindowRoll(0, 0, samplesBudget, totalCountRunningAverage, probability); - } - - this.windowDuration = windowDuration; - this.taskScheduler = taskScheduler; - - if (startSampler) { - start(); - } - } - - /** - * Create a new sampler instance with automatic window roll. - * - * @param windowDuration the sampling window duration - * @param samplesPerWindow the maximum number of samples in the sampling window - * @param averageLookback the number of windows to consider in averaging the sampling rate - * @param budgetLookback the number of windows to consider when computing the sampling budget - */ - public AdaptiveSampler( - final Duration windowDuration, - final int samplesPerWindow, - final int averageLookback, - final int budgetLookback, - boolean startSampler) { - this( - windowDuration, - samplesPerWindow, - averageLookback, - budgetLookback, - null, - AgentTaskScheduler.INSTANCE, - startSampler); - } - - /** - * Create a new sampler instance with automatic window roll. The instance is automatically - * started. - * - * @param windowDuration the sampling window duration - * @param samplesPerWindow the maximum number of samples in the sampling window - * @param averageLookback the number of windows to consider in averaging the sampling rate - * @param budgetLookback the number of windows to consider when computing the sampling budget - * @param listener an optional listener receiving the sampler config changes - */ - public AdaptiveSampler( - final Duration windowDuration, - final int samplesPerWindow, - final int averageLookback, - final int budgetLookback, - final ConfigListener listener) { - this( - windowDuration, - samplesPerWindow, - averageLookback, - budgetLookback, - listener, - AgentTaskScheduler.INSTANCE, - true); - } - - public void start() { - taskScheduler.weakScheduleAtFixedRate( - RollWindowTask.INSTANCE, - this, - windowDuration.toNanos(), - windowDuration.toNanos(), - TimeUnit.NANOSECONDS); - } - - @Override - public boolean sample() { - final Counts counts = countsRef.get(); - counts.addTest(); - if (ThreadLocalRandom.current().nextDouble() < probability) { - return counts.addSample(samplesBudget); - } - - return false; - } - - @Override - public boolean keep() { - final Counts counts = countsRef.get(); - counts.addTest(); - counts.addSample(); - return true; - } - - @Override - public boolean drop() { - final Counts counts = countsRef.get(); - counts.addTest(); - return false; - } - - private void rollWindow() { - - final Counts counts = countsSlots[countsSlotIdx]; - try { - /* - * Semi-atomically replace the Counts instance such that sample requests during window maintenance will be - * using the newly created counts instead of the ones currently processed by the maintenance routine. - * We are ok with slightly racy outcome where totaCount and sampledCount may not be totally in sync - * because it allows to avoid contention in the hot-path and the effect on the overall sample rate is minimal - * and will get compensated in the long run. - * Theoretically, a compensating system might be devised but it will always require introducing a single point - * of contention and add a fair amount of complexity. Considering that we are ok with keeping the target sampling - * rate within certain error margins and this data race is not breaking the margin it is better to keep the - * code simple and reasonably fast. - */ - countsSlotIdx = (countsSlotIdx++) % 2; - countsRef.set(countsSlots[countsSlotIdx]); - final long totalCount = counts.testCount(); - final long sampledCount = counts.sampleCount(); - - samplesBudget = calculateBudgetEma(sampledCount); - - if (totalCountRunningAverage == 0 || emaAlpha <= 0.0d) { - totalCountRunningAverage = totalCount; - } else { - totalCountRunningAverage = - totalCountRunningAverage + emaAlpha * (totalCount - totalCountRunningAverage); - } - - if (totalCountRunningAverage <= 0) { - probability = 1; - } else { - probability = Math.min(samplesBudget / totalCountRunningAverage, 1d); - } - if (listener != null) { - listener.onWindowRoll( - totalCount, sampledCount, samplesBudget, totalCountRunningAverage, probability); - } - } finally { - // Reset the previous counts slot - counts.reset(); - } - } - - private long calculateBudgetEma(final long sampledCount) { - avgSamples = - Double.isNaN(avgSamples) || budgetAlpha <= 0.0d - ? sampledCount - : avgSamples + budgetAlpha * (sampledCount - avgSamples); - return Math.round(Math.max(samplesPerWindow - avgSamples, 0) * budgetLookback); - } - - private static double computeIntervalAlpha(final int lookback) { - return 1 - Math.pow(lookback, -1d / lookback); - } - - private static class RollWindowTask implements Task { - - static final RollWindowTask INSTANCE = new RollWindowTask(); - - @Override - public void run(final AdaptiveSampler target) { - target.rollWindow(); - } - } - - // access for tests - long testCount() { - return countsRef.get().testCount(); - } - - long sampleCount() { - return countsRef.get().sampleCount(); - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/ConstantSampler.java b/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/ConstantSampler.java deleted file mode 100644 index e0fb334f63..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/ConstantSampler.java +++ /dev/null @@ -1,25 +0,0 @@ -package datadog.trace.api.sampling; - -public class ConstantSampler implements Sampler { - - private final boolean constant; - - public ConstantSampler(boolean constant) { - this.constant = constant; - } - - @Override - public boolean sample() { - return constant; - } - - @Override - public boolean keep() { - return true; - } - - @Override - public boolean drop() { - return false; - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java index 99d162e528..4ef4e3b4b5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java @@ -353,28 +353,6 @@ public static Boolean booleanValueOf(String value) { } } - private static class ValueOfLookup extends ClassValue { - private static final MethodHandles.Lookup PUBLIC_LOOKUP = MethodHandles.publicLookup(); - - @Override - protected MethodHandle computeValue(Class type) { - try { - if (Boolean.class.equals(type)) { - return MethodHandles.lookup() - .findStatic( - ConfigConverter.class, - "booleanValueOf", - MethodType.methodType(Boolean.class, String.class)); - } - - return PUBLIC_LOOKUP.findStatic(type, "valueOf", MethodType.methodType(type, String.class)); - } catch (final NoSuchMethodException | IllegalAccessException e) { - log.debug("Can't invoke or access 'valueOf': ", e); - throw new RuntimeException(e); - } - } - } - public static String renderIntegerRange(BitSet bitset) { StringBuilder sb = new StringBuilder(); int start = 0; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java index 4ee911f550..f7b33a668d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java @@ -273,10 +273,6 @@ default SpanBuilder buildSpan(CharSequence spanName) { CallbackProvider getUniversalCallbackProvider(); - Context notifyExtensionStart(Object event); - - void notifyExtensionEnd(AgentSpan span, Object result, boolean isError); - AgentDataStreamsMonitoring getDataStreamsMonitoring(); Timer getTimer(); @@ -486,14 +482,6 @@ public EndpointTracker onRootSpanStarted(AgentSpan root) { return EndpointTracker.NO_OP; } - @Override - public Context notifyExtensionStart(Object event) { - return null; - } - - @Override - public void notifyExtensionEnd(AgentSpan span, Object result, boolean isError) {} - @Override public ScopeState newScopeState() { return null; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/GitMetadataTraceInterceptor.java b/features/dd-trace-core/src/main/java/datadog/trace/common/GitMetadataTraceInterceptor.java deleted file mode 100644 index 584d79f8ff..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/GitMetadataTraceInterceptor.java +++ /dev/null @@ -1,38 +0,0 @@ -package datadog.trace.common; - -import datadog.trace.api.DDTags; -import datadog.trace.api.git.GitInfo; -import datadog.trace.api.git.GitInfoProvider; -import datadog.trace.api.interceptor.AbstractTraceInterceptor; -import datadog.trace.api.interceptor.MutableSpan; -import datadog.trace.api.interceptor.TraceInterceptor; -import datadog.trace.bootstrap.instrumentation.api.Tags; -import datadog.trace.core.DDSpan; -import java.util.Collection; - -public class GitMetadataTraceInterceptor extends AbstractTraceInterceptor { - - public static final TraceInterceptor INSTANCE = - new GitMetadataTraceInterceptor(Priority.GIT_METADATA); - - protected GitMetadataTraceInterceptor(Priority priority) { - super(priority); - } - - @Override - public Collection onTraceComplete( - Collection trace) { - if (trace.isEmpty()) { - return trace; - } - - final DDSpan firstSpan = (DDSpan) trace.iterator().next(); - String ciWorkspacePath = (String) firstSpan.getTag(Tags.CI_WORKSPACE_PATH); - - GitInfo gitInfo = GitInfoProvider.INSTANCE.getGitInfo(ciWorkspacePath); - firstSpan.setTag(DDTags.INTERNAL_GIT_REPOSITORY_URL, gitInfo.getRepositoryURL()); - firstSpan.setTag(DDTags.INTERNAL_GIT_COMMIT_SHA, gitInfo.getCommit().getSha()); - - return trace; - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Aggregator.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Aggregator.java deleted file mode 100644 index b2b8b1820f..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Aggregator.java +++ /dev/null @@ -1,194 +0,0 @@ -package datadog.trace.common.metrics; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import datadog.trace.common.metrics.SignalItem.StopSignal; -import datadog.trace.core.util.LRUCache; -import java.util.Iterator; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import org.jctools.maps.NonBlockingHashMap; -import org.jctools.queues.MessagePassingQueue; -import org.jctools.queues.MpscCompoundQueue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class Aggregator implements Runnable { - - private static final long DEFAULT_SLEEP_MILLIS = 10; - - private static final Logger log = LoggerFactory.getLogger(Aggregator.class); - - private final Queue batchPool; - private final MpscCompoundQueue inbox; - private final LRUCache aggregates; - private final NonBlockingHashMap pending; - private final Set commonKeys; - private final MetricWriter writer; - // the reporting interval controls how much history will be buffered - // when the agent is unresponsive (only 10 pending requests will be - // buffered by OkHttpSink) - private final long reportingIntervalNanos; - - private final long sleepMillis; - - private boolean dirty; - - Aggregator( - MetricWriter writer, - Queue batchPool, - MpscCompoundQueue inbox, - NonBlockingHashMap pending, - final Set commonKeys, - int maxAggregates, - long reportingInterval, - TimeUnit reportingIntervalTimeUnit) { - this( - writer, - batchPool, - inbox, - pending, - commonKeys, - maxAggregates, - reportingInterval, - reportingIntervalTimeUnit, - DEFAULT_SLEEP_MILLIS); - } - - Aggregator( - MetricWriter writer, - Queue batchPool, - MpscCompoundQueue inbox, - NonBlockingHashMap pending, - final Set commonKeys, - int maxAggregates, - long reportingInterval, - TimeUnit reportingIntervalTimeUnit, - long sleepMillis) { - this.writer = writer; - this.batchPool = batchPool; - this.inbox = inbox; - this.commonKeys = commonKeys; - this.aggregates = - new LRUCache<>( - new CommonKeyCleaner(commonKeys), maxAggregates * 4 / 3, 0.75f, maxAggregates); - this.pending = pending; - this.reportingIntervalNanos = reportingIntervalTimeUnit.toNanos(reportingInterval); - this.sleepMillis = sleepMillis; - } - - public void clearAggregates() { - this.aggregates.clear(); - } - - @Override - public void run() { - Thread currentThread = Thread.currentThread(); - Drainer drainer = new Drainer(); - while (!currentThread.isInterrupted() && !drainer.stopped) { - try { - if (!inbox.isEmpty()) { - inbox.drain(drainer); - } else { - Thread.sleep(sleepMillis); - } - } catch (InterruptedException e) { - currentThread.interrupt(); - } catch (Throwable error) { - log.debug("error aggregating metrics", error); - } - } - log.debug("metrics aggregator exited"); - } - - private final class Drainer implements MessagePassingQueue.Consumer { - - boolean stopped = false; - - @Override - public void accept(InboxItem item) { - if (item instanceof SignalItem) { - SignalItem signal = (SignalItem) item; - if (!stopped) { - report(wallClockTime(), signal); - stopped = item instanceof StopSignal; - if (stopped) { - signal.complete(); - } - } else { - signal.ignore(); - } - } else if (item instanceof Batch && !stopped) { - Batch batch = (Batch) item; - MetricKey key = batch.getKey(); - // important that it is still *this* batch pending, must not remove otherwise - pending.remove(key, batch); - AggregateMetric aggregate = aggregates.computeIfAbsent(key, k -> new AggregateMetric()); - batch.contributeTo(aggregate); - dirty = true; - // return the batch for reuse - batchPool.offer(batch); - } - } - } - - private void report(long when, SignalItem signal) { - boolean skipped = true; - if (dirty) { - try { - expungeStaleAggregates(); - if (!aggregates.isEmpty()) { - skipped = false; - writer.startBucket(aggregates.size(), when, reportingIntervalNanos); - for (Map.Entry aggregate : aggregates.entrySet()) { - writer.add(aggregate.getKey(), aggregate.getValue()); - aggregate.getValue().clear(); - } - // note that this may do IO and block - writer.finishBucket(); - } - } catch (Throwable error) { - writer.reset(); - log.debug("Error publishing metrics. Dropping payload", error); - } - dirty = false; - } - signal.complete(); - if (skipped) { - log.debug("skipped metrics reporting because no points have changed"); - } - } - - private void expungeStaleAggregates() { - Iterator> it = aggregates.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry pair = it.next(); - AggregateMetric metric = pair.getValue(); - if (metric.getHitCount() == 0) { - it.remove(); - commonKeys.remove(pair.getKey()); - } - } - } - - private long wallClockTime() { - return MILLISECONDS.toNanos(System.currentTimeMillis()); - } - - private static final class CommonKeyCleaner - implements LRUCache.ExpiryListener { - - private final Set commonKeys; - - private CommonKeyCleaner(Set commonKeys) { - this.commonKeys = commonKeys; - } - - @Override - public void accept(Map.Entry expired) { - commonKeys.remove(expired.getKey()); - } - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java index 7d66cad6a1..f6297f126f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java @@ -1,31 +1,4 @@ package datadog.trace.common.metrics; -import java.util.concurrent.CompletableFuture; - interface InboxItem {} -abstract class SignalItem implements InboxItem { - final CompletableFuture future; - - public SignalItem() { - this.future = new CompletableFuture<>(); - } - - void complete() { - this.future.complete(true); - } - - void ignore() { - this.future.complete(false); - } - - static final class StopSignal extends SignalItem { - static final StopSignal STOP = new StopSignal(); - - private StopSignal() {} - } - - static final class ReportSignal extends SignalItem { - static final ReportSignal REPORT = new ReportSignal(); - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java index a15c008e10..ae34266f26 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java @@ -5,7 +5,10 @@ import datadog.trace.core.CoreSpan; import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; public final class NoOpMetricsAggregator implements MetricsAggregator { @@ -21,7 +24,32 @@ public boolean report() { @Override public Future forceReport() { - return CompletableFuture.completedFuture(FALSE); + return new Future() { + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return false; + } + + @Override + public Boolean get() throws ExecutionException, InterruptedException { + return FALSE; + } + + @Override + public Boolean get(long timeout, TimeUnit unit) throws ExecutionException, InterruptedException, TimeoutException { + return FALSE; + } + }; } @Override diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/SerializingMetricWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/SerializingMetricWriter.java deleted file mode 100644 index 37287c3fbf..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/SerializingMetricWriter.java +++ /dev/null @@ -1,136 +0,0 @@ -package datadog.trace.common.metrics; - -import static java.nio.charset.StandardCharsets.ISO_8859_1; - -import datadog.trace.serialization.GrowableBuffer; -import datadog.trace.serialization.WritableFormatter; -import datadog.trace.serialization.msgpack.MsgPackWriter; -import datadog.trace.api.WellKnownTags; - -public final class SerializingMetricWriter implements MetricWriter { - - private static final byte[] SEQUENCE = "Seq".getBytes(ISO_8859_1); - private static final byte[] RUNTIME_ID = "RuntimeId".getBytes(ISO_8859_1); - private static final byte[] HOSTNAME = "Hostname".getBytes(ISO_8859_1); - private static final byte[] NAME = "Name".getBytes(ISO_8859_1); - private static final byte[] ENV = "Env".getBytes(ISO_8859_1); - private static final byte[] SERVICE = "Service".getBytes(ISO_8859_1); - private static final byte[] RESOURCE = "Resource".getBytes(ISO_8859_1); - private static final byte[] VERSION = "Version".getBytes(ISO_8859_1); - private static final byte[] HITS = "Hits".getBytes(ISO_8859_1); - private static final byte[] ERRORS = "Errors".getBytes(ISO_8859_1); - private static final byte[] TOP_LEVEL_HITS = "TopLevelHits".getBytes(ISO_8859_1); - private static final byte[] DURATION = "Duration".getBytes(ISO_8859_1); - private static final byte[] TYPE = "Type".getBytes(ISO_8859_1); - private static final byte[] HTTP_STATUS_CODE = "HTTPStatusCode".getBytes(ISO_8859_1); - private static final byte[] SYNTHETICS = "Synthetics".getBytes(ISO_8859_1); - private static final byte[] START = "Start".getBytes(ISO_8859_1); - private static final byte[] STATS = "Stats".getBytes(ISO_8859_1); - private static final byte[] OK_SUMMARY = "OkSummary".getBytes(ISO_8859_1); - private static final byte[] ERROR_SUMMARY = "ErrorSummary".getBytes(ISO_8859_1); - - private final WellKnownTags wellKnownTags; - private final WritableFormatter writer; - private final Sink sink; - private final GrowableBuffer buffer; - private long sequence = 0; - - public SerializingMetricWriter(WellKnownTags wellKnownTags, Sink sink) { - this(wellKnownTags, sink, 512 * 1024); - } - - public SerializingMetricWriter(WellKnownTags wellKnownTags, Sink sink, int initialCapacity) { - this.wellKnownTags = wellKnownTags; - this.buffer = new GrowableBuffer(initialCapacity); - this.writer = new MsgPackWriter(buffer); - this.sink = sink; - } - - @Override - public void startBucket(int metricCount, long start, long duration) { - writer.startMap(6); - - writer.writeUTF8(RUNTIME_ID); - writer.writeUTF8(wellKnownTags.getRuntimeId()); - - writer.writeUTF8(SEQUENCE); - writer.writeLong(sequence++); - - writer.writeUTF8(HOSTNAME); - writer.writeUTF8(wellKnownTags.getHostname()); - - writer.writeUTF8(ENV); - writer.writeUTF8(wellKnownTags.getEnv()); - - writer.writeUTF8(VERSION); - writer.writeUTF8(wellKnownTags.getVersion()); - - writer.writeUTF8(STATS); - writer.startArray(1); - - writer.startMap(3); - - writer.writeUTF8(START); - writer.writeLong(start); - - writer.writeUTF8(DURATION); - writer.writeLong(duration); - - writer.writeUTF8(STATS); - writer.startArray(metricCount); - } - - @Override - public void add(MetricKey key, AggregateMetric aggregate) { - - writer.startMap(12); - - writer.writeUTF8(NAME); - writer.writeUTF8(key.getOperationName()); - - writer.writeUTF8(SERVICE); - writer.writeUTF8(key.getService()); - - writer.writeUTF8(RESOURCE); - writer.writeUTF8(key.getResource()); - - writer.writeUTF8(TYPE); - writer.writeUTF8(key.getType()); - - writer.writeUTF8(HTTP_STATUS_CODE); - writer.writeInt(key.getHttpStatusCode()); - - writer.writeUTF8(SYNTHETICS); - writer.writeBoolean(key.isSynthetics()); - - writer.writeUTF8(HITS); - writer.writeInt(aggregate.getHitCount()); - - writer.writeUTF8(ERRORS); - writer.writeInt(aggregate.getErrorCount()); - - writer.writeUTF8(TOP_LEVEL_HITS); - writer.writeInt(aggregate.getTopLevelCount()); - - writer.writeUTF8(DURATION); - writer.writeLong(aggregate.getDuration()); - - writer.writeUTF8(OK_SUMMARY); - writer.writeBinary(aggregate.getOkLatencies().serialize()); - - writer.writeUTF8(ERROR_SUMMARY); - writer.writeBinary(aggregate.getErrorLatencies().serialize()); - } - - @Override - public void finishBucket() { - buffer.mark(); - sink.accept(buffer.messageCount(), buffer.slice()); - buffer.reset(); - } - - @Override - public void reset() { - buffer.reset(); - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java index a523d44de9..24ec61b608 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java @@ -1,99 +1,10 @@ package datadog.trace.common.writer; -import static datadog.trace.serialization.msgpack.MsgPackWriter.ARRAY16; -import static datadog.trace.serialization.msgpack.MsgPackWriter.ARRAY32; -import static datadog.trace.serialization.msgpack.MsgPackWriter.FIXARRAY; -import static datadog.trace.serialization.msgpack.MsgPackWriter.FIXMAP; -import static datadog.trace.serialization.msgpack.MsgPackWriter.MAP16; -import static datadog.trace.serialization.msgpack.MsgPackWriter.MAP32; - -import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.channels.WritableByteChannel; -import okhttp3.RequestBody; public abstract class Payload { private static final ByteBuffer EMPTY_ARRAY = ByteBuffer.allocate(1).put(0, (byte) 0x90); - - private int traceCount = 0; - private long droppedTraces = 0; - private long droppedSpans = 0; protected ByteBuffer body = EMPTY_ARRAY.duplicate(); - public Payload withBody(int traceCount, ByteBuffer body) { - this.traceCount = traceCount; - if (null != body) { - this.body = body; - } - return this; - } - - public Payload withDroppedTraces(long droppedTraceCount) { - this.droppedTraces += droppedTraceCount; - return this; - } - - public Payload withDroppedSpans(long droppedSpanCount) { - this.droppedSpans += droppedSpanCount; - return this; - } - - public int traceCount() { - return traceCount; - } - - public long droppedTraces() { - return droppedTraces; - } - - public long droppedSpans() { - return droppedSpans; - } - - public abstract int sizeInBytes(); - - public abstract void writeTo(WritableByteChannel channel) throws IOException; - - public abstract RequestBody toRequest(); - - protected int msgpackArrayHeaderSize(int count) { - if (count < 0x10) { - return 1; - } else if (count < 0x10000) { - return 3; - } else { - return 5; - } - } - - protected int msgpackMapHeaderSize(int count) { - if (count < 0x10) { - return 1; - } else if (count < 0x10000) { - return 3; - } else { - return 5; - } - } - - protected ByteBuffer msgpackArrayHeader(int count) { - if (count < 0x10) { - return ByteBuffer.allocate(1).put(0, (byte) (FIXARRAY | count)); - } else if (count < 0x10000) { - return ByteBuffer.allocate(3).put(0, ARRAY16).putShort(1, (short) count); - } else { - return ByteBuffer.allocate(5).put(0, ARRAY32).putInt(1, count); - } - } - - protected ByteBuffer msgpackMapHeader(int count) { - if (count < 0x10) { - return ByteBuffer.allocate(1).put(0, (byte) (FIXMAP | count)); - } else if (count < 0x10000) { - return ByteBuffer.allocate(3).put(0, MAP16).putShort((short) count); - } else { - return ByteBuffer.allocate(5).put(0, MAP32).putInt(1, count); - } - } } diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcherImpl.java b/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcherImpl.java deleted file mode 100644 index c410785fa9..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcherImpl.java +++ /dev/null @@ -1,129 +0,0 @@ -package datadog.trace.common.writer; - -import datadog.trace.monitor.Monitoring; -import datadog.trace.monitor.Recording; -import datadog.trace.serialization.ByteBufferConsumer; -import datadog.trace.serialization.FlushingBuffer; -import datadog.trace.serialization.WritableFormatter; -import datadog.trace.serialization.msgpack.MsgPackWriter; -import datadog.trace.core.CoreSpan; -import datadog.trace.core.monitor.HealthMetrics; -import java.nio.ByteBuffer; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import org.jctools.counters.CountersFactory; -import org.jctools.counters.FixedSizeStripedLongCounter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PayloadDispatcherImpl implements ByteBufferConsumer, PayloadDispatcher { - - private static final Logger log = LoggerFactory.getLogger(PayloadDispatcherImpl.class); - - private final RemoteApi api; - private final RemoteMapperDiscovery mapperDiscovery; - private final HealthMetrics healthMetrics; - private final Monitoring monitoring; - - private Recording batchTimer; - private RemoteMapper mapper; - private WritableFormatter packer; - - private final FixedSizeStripedLongCounter droppedSpanCount = - CountersFactory.createFixedSizeStripedCounter(8); - private final FixedSizeStripedLongCounter droppedTraceCount = - CountersFactory.createFixedSizeStripedCounter(8); - - public PayloadDispatcherImpl( - RemoteMapperDiscovery mapperDiscovery, - RemoteApi api, - HealthMetrics healthMetrics, - Monitoring monitoring) { - this.mapperDiscovery = mapperDiscovery; - this.api = api; - this.healthMetrics = healthMetrics; - this.monitoring = monitoring; - } - - @Override - public void flush() { - if (null != packer) { - packer.flush(); - } - } - - @Override - public Collection> getApis() { - return Collections.singleton(api.getClass()); - } - - @Override - public void onDroppedTrace(int spanCount) { - droppedSpanCount.inc(spanCount); - droppedTraceCount.inc(); - } - - @Override - public void addTrace(List> trace) { - selectMapper(); - // the call below is blocking and will trigger IO if a flush is necessary - // there are alternative approaches to avoid blocking here, such as - // introducing an unbound queue and another thread to do the IO - // however, we can't block the application threads from here. - if (null == mapper || !packer.format(trace, mapper)) { - healthMetrics.onFailedPublish( - trace.isEmpty() ? 0 : trace.get(0).samplingPriority(), trace.size()); - } - } - - private void selectMapper() { - if (null == mapper) { - if (mapperDiscovery.getMapper() == null) { - mapperDiscovery.discover(); - } - - mapper = mapperDiscovery.getMapper(); - if (null != mapper && null == packer) { - batchTimer = - monitoring.newTimer("tracer.trace.buffer.fill.time", "endpoint:" + mapper.endpoint()); - packer = new MsgPackWriter(new FlushingBuffer(mapper.messageBufferSize(), this)); - batchTimer.start(); - } - } - } - - Payload newPayload(int messageCount, ByteBuffer buffer) { - return mapper - .newPayload() - .withBody(messageCount, buffer) - .withDroppedSpans(droppedSpanCount.getAndReset()) - .withDroppedTraces(droppedTraceCount.getAndReset()); - } - - @Override - public void accept(int messageCount, ByteBuffer buffer) { - // the packer calls this when the buffer is full, - // or when the packer is flushed at a heartbeat - if (messageCount > 0) { - batchTimer.reset(); - Payload payload = newPayload(messageCount, buffer); - final int sizeInBytes = payload.sizeInBytes(); - healthMetrics.onSerialize(sizeInBytes); - RemoteApi.Response response = api.sendSerializedTraces(payload); - mapper.reset(); - if (response.success()) { - if (log.isDebugEnabled()) { - log.debug("Successfully sent {} traces to the API", messageCount); - } - healthMetrics.onSend(messageCount, sizeInBytes, response); - } else { - if (log.isDebugEnabled()) { - log.debug( - "Failed to send {} traces of size {} bytes to the API", messageCount, sizeInBytes); - } - healthMetrics.onFailedSend(messageCount, sizeInBytes, response); - } - } - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 8be144843c..53484ebe76 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -54,7 +54,6 @@ import datadog.trace.bootstrap.instrumentation.api.ScopeState; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.civisibility.interceptor.CiVisibilityTraceInterceptor; -import datadog.trace.common.GitMetadataTraceInterceptor; import datadog.trace.common.metrics.MetricsAggregator; import datadog.trace.common.metrics.NoOpMetricsAggregator; import datadog.trace.common.sampling.Sampler; @@ -69,9 +68,7 @@ import datadog.trace.core.scopemanager.ContinuableScopeManager; import datadog.trace.core.taginterceptor.RuleFlags; import datadog.trace.core.taginterceptor.TagInterceptor; -import datadog.trace.lambda.LambdaHandler; import datadog.trace.relocate.api.RatelimitedLogger; -import datadog.trace.util.AgentTaskScheduler; import java.io.IOException; import java.lang.ref.WeakReference; @@ -537,8 +534,6 @@ private CoreTracer( // Schedule the metrics aggregator to begin reporting after a random delay of 1 to 10 seconds // (using milliseconds granularity.) This avoids a fleet of traced applications starting at the // same time from sending metrics in sync. - AgentTaskScheduler.INSTANCE.scheduleWithJitter( - MetricsAggregator::start, metricsAggregator, 1, SECONDS); this.dataStreamsMonitoring = new NoOpDataStreamMonitoring(); // Create default extractor from config if not provided and decorate it with DSM extractor @@ -556,10 +551,6 @@ private CoreTracer( addTraceInterceptor(CiVisibilityTraceInterceptor.INSTANCE); } } - if (config.isTraceGitMetadataEnabled()) { - addTraceInterceptor(GitMetadataTraceInterceptor.INSTANCE); - } - this.instrumentationGateway = instrumentationGateway; callbackProviderAppSec = instrumentationGateway.getCallbackProvider(RequestContextSlot.APPSEC); callbackProviderIast = instrumentationGateway.getCallbackProvider(RequestContextSlot.IAST); @@ -765,16 +756,6 @@ public AgentSpan noopSpan() { return AgentTracer.NoopAgentSpan.INSTANCE; } - @Override - public AgentSpan.Context notifyExtensionStart(Object event) { - return LambdaHandler.notifyStartInvocation(event, propagationTagsFactory); - } - - @Override - public void notifyExtensionEnd(AgentSpan span, Object result, boolean isError) { - LambdaHandler.notifyEndInvocation(span, result, isError); - } - @Override public AgentDataStreamsMonitoring getDataStreamsMonitoring() { return dataStreamsMonitoring; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/MsgPackDatastreamsPayloadWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/MsgPackDatastreamsPayloadWriter.java deleted file mode 100644 index f2af129367..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/MsgPackDatastreamsPayloadWriter.java +++ /dev/null @@ -1,169 +0,0 @@ -package datadog.trace.core.datastreams; - -import static java.nio.charset.StandardCharsets.ISO_8859_1; - -import datadog.trace.serialization.GrowableBuffer; -import datadog.trace.serialization.Writable; -import datadog.trace.serialization.WritableFormatter; -import datadog.trace.serialization.msgpack.MsgPackWriter; -import datadog.trace.api.WellKnownTags; -import datadog.trace.common.metrics.Sink; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -public class MsgPackDatastreamsPayloadWriter implements DatastreamsPayloadWriter { - private static final byte[] ENV = "Env".getBytes(ISO_8859_1); - private static final byte[] VERSION = "Version".getBytes(ISO_8859_1); - private static final byte[] PRIMARY_TAG = "PrimaryTag".getBytes(ISO_8859_1); - private static final byte[] LANG = "Lang".getBytes(ISO_8859_1); - private static final byte[] TRACER_VERSION = "TracerVersion".getBytes(ISO_8859_1); - private static final byte[] STATS = "Stats".getBytes(ISO_8859_1); - private static final byte[] START = "Start".getBytes(ISO_8859_1); - private static final byte[] DURATION = "Duration".getBytes(ISO_8859_1); - private static final byte[] PATHWAY_LATENCY = "PathwayLatency".getBytes(ISO_8859_1); - private static final byte[] EDGE_LATENCY = "EdgeLatency".getBytes(ISO_8859_1); - private static final byte[] PAYLOAD_SIZE = "PayloadSize".getBytes(ISO_8859_1); - private static final byte[] SERVICE = "Service".getBytes(ISO_8859_1); - private static final byte[] EDGE_TAGS = "EdgeTags".getBytes(ISO_8859_1); - private static final byte[] BACKLOGS = "Backlogs".getBytes(ISO_8859_1); - private static final byte[] HASH = "Hash".getBytes(ISO_8859_1); - private static final byte[] PARENT_HASH = "ParentHash".getBytes(ISO_8859_1); - private static final byte[] BACKLOG_VALUE = "Value".getBytes(ISO_8859_1); - private static final byte[] BACKLOG_TAGS = "Tags".getBytes(ISO_8859_1); - - private static final int INITIAL_CAPACITY = 512 * 1024; - - private final WritableFormatter writer; - private final Sink sink; - private final GrowableBuffer buffer; - private final WellKnownTags wellKnownTags; - private final byte[] tracerVersionValue; - private final byte[] primaryTagValue; - - public MsgPackDatastreamsPayloadWriter( - Sink sink, WellKnownTags wellKnownTags, String tracerVersion, String primaryTag) { - buffer = new GrowableBuffer(INITIAL_CAPACITY); - writer = new MsgPackWriter(buffer); - this.sink = sink; - this.wellKnownTags = wellKnownTags; - tracerVersionValue = tracerVersion.getBytes(ISO_8859_1); - primaryTagValue = primaryTag == null ? new byte[0] : primaryTag.getBytes(ISO_8859_1); - } - - public void reset() { - buffer.reset(); - } - - @Override - public void writePayload(Collection data) { - writer.startMap(7); - /* 1 */ - writer.writeUTF8(ENV); - writer.writeUTF8(wellKnownTags.getEnv()); - - /* 2 */ - writer.writeUTF8(SERVICE); - writer.writeUTF8(wellKnownTags.getService()); - - /* 3 */ - writer.writeUTF8(LANG); - writer.writeUTF8(wellKnownTags.getLanguage()); - - /* 4 */ - writer.writeUTF8(PRIMARY_TAG); - writer.writeUTF8(primaryTagValue); - - /* 5 */ - writer.writeUTF8(TRACER_VERSION); - writer.writeUTF8(tracerVersionValue); - - /* 6 */ - writer.writeUTF8(VERSION); - writer.writeUTF8(wellKnownTags.getVersion()); - - /* 7 */ - writer.writeUTF8(STATS); - writer.startArray(data.size()); - - for (StatsBucket bucket : data) { - boolean hasBacklogs = !bucket.getBacklogs().isEmpty(); - writer.startMap(3 + (hasBacklogs ? 1 : 0)); - - /* 1 */ - writer.writeUTF8(START); - writer.writeLong(bucket.getStartTimeNanos()); - - /* 2 */ - writer.writeUTF8(DURATION); - writer.writeLong(bucket.getBucketDurationNanos()); - - /* 3 */ - writer.writeUTF8(STATS); - writeBucket(bucket, writer); - - if (hasBacklogs) { - /* 4 */ - writeBacklogs(bucket.getBacklogs(), writer); - } - } - - buffer.mark(); - sink.accept(buffer.messageCount(), buffer.slice()); - buffer.reset(); - } - - private void writeBucket(StatsBucket bucket, Writable packer) { - Collection groups = bucket.getGroups(); - packer.startArray(groups.size()); - for (StatsGroup group : groups) { - boolean firstNode = group.getEdgeTags().isEmpty(); - - packer.startMap(firstNode ? 5 : 6); - - /* 1 */ - packer.writeUTF8(PATHWAY_LATENCY); - packer.writeBinary(group.getPathwayLatency().serialize()); - - /* 2 */ - packer.writeUTF8(EDGE_LATENCY); - packer.writeBinary(group.getEdgeLatency().serialize()); - - /* 3 */ - packer.writeUTF8(PAYLOAD_SIZE); - packer.writeBinary(group.getPayloadSize().serialize()); - - /* 4 */ - packer.writeUTF8(HASH); - packer.writeUnsignedLong(group.getHash()); - - /* 5 */ - packer.writeUTF8(PARENT_HASH); - packer.writeUnsignedLong(group.getParentHash()); - - if (!firstNode) { - /* 6 */ - packer.writeUTF8(EDGE_TAGS); - packer.startArray(group.getEdgeTags().size()); - for (String tag : group.getEdgeTags()) { - packer.writeString(tag, null); - } - } - } - } - - private void writeBacklogs(Collection, Long>> backlogs, Writable packer) { - packer.writeUTF8(BACKLOGS); - packer.startArray(backlogs.size()); - for (Map.Entry, Long> entry : backlogs) { - packer.startMap(2); - packer.writeUTF8(BACKLOG_TAGS); - packer.startArray(entry.getKey().size()); - for (String tag : entry.getKey()) { - packer.writeString(tag, null); - } - packer.writeUTF8(BACKLOG_VALUE); - packer.writeLong(entry.getValue()); - } - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java b/features/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java deleted file mode 100644 index e0e824b3d1..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java +++ /dev/null @@ -1,184 +0,0 @@ -package datadog.trace.lambda; - -import static datadog.trace.api.TracePropagationStyle.DATADOG; -import static java.util.concurrent.TimeUnit.SECONDS; - -import com.squareup.moshi.JsonAdapter; -import com.squareup.moshi.Moshi; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTags; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.core.propagation.ExtractedContext; -import datadog.trace.core.propagation.PropagationTags; -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class communicates with the serverless extension on start invocation and on end invocation. - * The extension is responsible to parse the context and create the invocation span. The tracer will - * also create the span (to be dropped by the extension) so newly created spans will be parenting to - * the right span. - */ -public class LambdaHandler { - - private static final Logger log = LoggerFactory.getLogger(LambdaHandler.class); - - // Note: this header is used to disable tracing for calls to the extension - private static final String DATADOG_META_LANG = "Datadog-Meta-Lang"; - - private static final String DATADOG_TRACE_ID = "x-datadog-trace-id"; - private static final String DATADOG_SPAN_ID = "x-datadog-span-id"; - private static final String DATADOG_SAMPLING_PRIORITY = "x-datadog-sampling-priority"; - private static final String DATADOG_INVOCATION_ERROR = "x-datadog-invocation-error"; - private static final String DATADOG_INVOCATION_ERROR_MSG = "x-datadog-invocation-error-msg"; - private static final String DATADOG_INVOCATION_ERROR_TYPE = "x-datadog-invocation-error-type"; - private static final String DATADOG_INVOCATION_ERROR_STACK = "x-datadog-invocation-error-stack"; - private static final String DATADOG_TAGS_KEY = "x-datadog-tags"; - - private static final String START_INVOCATION = "/lambda/start-invocation"; - private static final String END_INVOCATION = "/lambda/end-invocation"; - - private static final Long REQUEST_TIMEOUT_IN_S = 1L; - - private static OkHttpClient HTTP_CLIENT = - new OkHttpClient.Builder() - .retryOnConnectionFailure(true) - .connectTimeout(REQUEST_TIMEOUT_IN_S, SECONDS) - .writeTimeout(REQUEST_TIMEOUT_IN_S, SECONDS) - .readTimeout(REQUEST_TIMEOUT_IN_S, SECONDS) - .callTimeout(REQUEST_TIMEOUT_IN_S, SECONDS) - .build(); - - private static final MediaType jsonMediaType = MediaType.parse("application/json"); - private static final JsonAdapter adapter = - new Moshi.Builder() - .add(ByteArrayInputStream.class, new ReadFromInputStreamJsonAdapter()) - .add(SkipUnsupportedTypeJsonAdapter.newFactory()) - .build() - .adapter(Object.class); - - private static String EXTENSION_BASE_URL = "http://127.0.0.1:8124"; - - public static AgentSpan.Context notifyStartInvocation( - Object event, PropagationTags.Factory propagationTagsFactory) { - RequestBody body = RequestBody.create(jsonMediaType, writeValueAsString(event)); - try (Response response = - HTTP_CLIENT - .newCall( - new Request.Builder() - .url(EXTENSION_BASE_URL + START_INVOCATION) - .addHeader(DATADOG_META_LANG, "java") - .post(body) - .build()) - .execute()) { - if (response.isSuccessful()) { - final String traceID = response.headers().get(DATADOG_TRACE_ID); - final String priority = response.headers().get(DATADOG_SAMPLING_PRIORITY); - if (null != traceID && null != priority) { - int samplingPriority = PrioritySampling.UNSET; - try { - samplingPriority = Integer.parseInt(priority); - } catch (final NumberFormatException ignored) { - log.warn("could not read the sampling priority, defaulting to UNSET"); - } - log.debug( - "notifyStartInvocation success, found traceID = {} and samplingPriority = {}", - traceID, - samplingPriority); - PropagationTags propagationTags = - propagationTagsFactory.fromHeaderValue( - PropagationTags.HeaderType.DATADOG, response.headers().get(DATADOG_TAGS_KEY)); - return new ExtractedContext( - DDTraceId.from(traceID), - DDSpanId.ZERO, - samplingPriority, - null, - propagationTags, - DATADOG); - } else { - log.debug( - "could not find traceID or sampling priority in notifyStartInvocation, not injecting the context"); - } - } - } catch (Throwable ignored) { - log.error("could not reach the extension"); - } - return null; - } - - public static boolean notifyEndInvocation(AgentSpan span, Object result, boolean isError) { - - if (null == span || null == span.getSamplingPriority()) { - log.error( - "could not notify the extension as the lambda span is null or no sampling priority has been found"); - return false; - } - RequestBody body = RequestBody.create(jsonMediaType, writeValueAsString(result)); - Request.Builder builder = - new Request.Builder() - .url(EXTENSION_BASE_URL + END_INVOCATION) - .addHeader(DATADOG_TRACE_ID, span.getTraceId().toString()) - .addHeader(DATADOG_SPAN_ID, DDSpanId.toString(span.getSpanId())) - .addHeader(DATADOG_SAMPLING_PRIORITY, span.getSamplingPriority().toString()) - .addHeader(DATADOG_META_LANG, "java") - .post(body); - - Object errorMessage = span.getTag(DDTags.ERROR_MSG); - if (errorMessage != null) { - builder.addHeader(DATADOG_INVOCATION_ERROR_MSG, errorMessage.toString()); - } - - Object errorType = span.getTag(DDTags.ERROR_TYPE); - if (errorType != null) { - builder.addHeader(DATADOG_INVOCATION_ERROR_TYPE, errorType.toString()); - } - - Object errorStack = span.getTag(DDTags.ERROR_STACK); - if (errorStack != null) { - String encodedErrStack = - Base64.getEncoder() - .encodeToString(errorStack.toString().getBytes(StandardCharsets.UTF_8)); - builder.addHeader(DATADOG_INVOCATION_ERROR_STACK, encodedErrStack); - } - - if (isError) { - builder.addHeader(DATADOG_INVOCATION_ERROR, "true"); - } - - try (Response response = HTTP_CLIENT.newCall(builder.build()).execute()) { - if (response.isSuccessful()) { - log.debug("notifyEndInvocation success"); - return true; - } - } catch (Exception e) { - log.error("could not reach the extension, not injecting the context", e); - } - return false; - } - - public static String writeValueAsString(Object obj) { - String json = "{}"; - if (null != obj) { - try { - json = adapter.toJson(obj); - } catch (Exception e) { - log.debug("could not write the value into a string", e); - } - } - return json; - } - - public static void setExtensionBaseUrl(String extensionBaseUrl) { - EXTENSION_BASE_URL = extensionBaseUrl; - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/lambda/SkipUnsupportedTypeJsonAdapter.java b/features/dd-trace-core/src/main/java/datadog/trace/lambda/SkipUnsupportedTypeJsonAdapter.java deleted file mode 100644 index 6be76c0522..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/lambda/SkipUnsupportedTypeJsonAdapter.java +++ /dev/null @@ -1,39 +0,0 @@ -package datadog.trace.lambda; - -import com.squareup.moshi.JsonAdapter; -import com.squareup.moshi.JsonReader; -import com.squareup.moshi.JsonWriter; -import com.squareup.moshi.Moshi; -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.Set; - -public final class SkipUnsupportedTypeJsonAdapter extends JsonAdapter { - - @Override - public T fromJson(JsonReader reader) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void toJson(JsonWriter writer, T value) throws IOException { - // nothing to do when we deal with an unsupported type, let's skip it. - writer.beginObject(); - writer.endObject(); - } - - public static Factory newFactory() { - return new Factory() { - @Override - public JsonAdapter create( - Type requestedType, Set annotations, Moshi moshi) { - try { - return moshi.nextAdapter(this, requestedType, annotations); - } catch (IllegalArgumentException e) { - return new SkipUnsupportedTypeJsonAdapter<>(); - } - } - }; - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java b/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java index 7fb8ab5981..8c40ea89f5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java @@ -1,5 +1,7 @@ package datadog.trace.logging; +import java.util.Locale; + /** Log level enum. */ public enum LogLevel { TRACE, @@ -18,7 +20,7 @@ public enum LogLevel { * @return the corresponding {@link LogLevel} enum */ public static LogLevel fromString(String level) { - String upper = level.toUpperCase(); + String upper = level.toUpperCase(Locale.US); try { return Enum.valueOf(LogLevel.class, upper); } catch (Throwable t) { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/Codec.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/Codec.java deleted file mode 100644 index 9a3c38e51d..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/Codec.java +++ /dev/null @@ -1,295 +0,0 @@ -package datadog.trace.serialization; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - -import datadog.trace.serialization.EncodingCache; -import datadog.trace.serialization.ValueWriter; -import datadog.trace.serialization.Writable; - -public final class Codec extends ClassValue> { - - public static final Codec INSTANCE = new Codec(); - - private final Map, ValueWriter> config; - - public Codec(Map, ValueWriter> config) { - this.config = config; - } - - @SuppressWarnings("unchecked") - public Codec() { - this(Collections., ValueWriter>emptyMap()); - } - - @Override - protected ValueWriter computeValue(Class clazz) { - ValueWriter writer = config.get(clazz); - if (null != writer) { - return writer; - } - if (Number.class.isAssignableFrom(clazz)) { - if (Double.class == clazz) { - return new DoubleWriter(); - } - if (Float.class == clazz) { - return new FloatWriter(); - } - if (Integer.class == clazz) { - return new IntWriter(); - } - if (Long.class == clazz) { - return new LongWriter(); - } - if (Short.class == clazz) { - return new ShortWriter(); - } - // This is some other Number type, that will be treated as a metric by the - // serializer, so let's write out its double value to be protocol compatible - return new NumberDoubleWriter(); - } - if (clazz.isArray()) { - if (byte[].class == clazz) { - return new ByteArrayWriter(); - } - if (int[].class == clazz) { - return new IntArrayWriter(); - } - if (long[].class == clazz) { - return new LongArrayWriter(); - } - if (double[].class == clazz) { - return new DoubleArrayWriter(); - } - if (float[].class == clazz) { - return new FloatArrayWriter(); - } - if (short[].class == clazz) { - return new ShortArrayWriter(); - } - if (char[].class == clazz) { - return new CharArrayWriter(); - } - if (boolean[].class == clazz) { - return new BooleanArrayWriter(); - } - return new ObjectArrayWriter(); - } - if (Boolean.class == clazz) { - return new BooleanWriter(); - } - if (CharSequence.class.isAssignableFrom(clazz)) { - return CharSequenceWriter.INSTANCE; - } - if (Map.class.isAssignableFrom(clazz)) { - return new MapWriter(); - } - if (Collection.class.isAssignableFrom(clazz)) { - return new CollectionWriter(); - } - if (ByteBuffer.class.isAssignableFrom(clazz)) { - return new ByteBufferWriter(); - } - return DefaultWriter.INSTANCE; - } - - private static final class IntArrayWriter implements ValueWriter { - - @Override - public void write(int[] value, Writable packer, EncodingCache encodingCache) { - packer.startArray(value.length); - for (int i : value) { - packer.writeInt(i); - } - } - } - - private static final class ShortArrayWriter implements ValueWriter { - - @Override - public void write(short[] value, Writable packer, EncodingCache encodingCache) { - packer.startArray(value.length); - for (short i : value) { - packer.writeInt(i); - } - } - } - - private static final class ByteArrayWriter implements ValueWriter { - - @Override - public void write(byte[] value, Writable packer, EncodingCache encodingCache) { - packer.writeBinary(value, 0, value.length); - } - } - - private static final class ByteBufferWriter implements ValueWriter { - - @Override - public void write(ByteBuffer buffer, Writable packer, EncodingCache encodingCache) { - packer.writeBinary(buffer); - } - } - - private static final class BooleanArrayWriter implements ValueWriter { - - @Override - public void write(boolean[] value, Writable packer, EncodingCache encodingCache) { - packer.startArray(value.length); - for (boolean i : value) { - packer.writeBoolean(i); - } - } - } - - private static final class DoubleArrayWriter implements ValueWriter { - - @Override - public void write(double[] value, Writable packer, EncodingCache encodingCache) { - packer.startArray(value.length); - for (double i : value) { - packer.writeDouble(i); - } - } - } - - private static final class FloatArrayWriter implements ValueWriter { - - @Override - public void write(float[] value, Writable packer, EncodingCache encodingCache) { - packer.startArray(value.length); - for (float i : value) { - packer.writeFloat(i); - } - } - } - - private static final class LongArrayWriter implements ValueWriter { - - @Override - public void write(long[] value, Writable packer, EncodingCache encodingCache) { - packer.startArray(value.length); - for (long i : value) { - packer.writeLong(i); - } - } - } - - private static final class CollectionWriter implements ValueWriter> { - - @Override - public void write(Collection collection, Writable packer, EncodingCache encodingCache) { - packer.startArray(collection.size()); - for (Object value : collection) { - packer.writeObject(value, encodingCache); - } - } - } - - private static final class ObjectArrayWriter implements ValueWriter { - - @Override - public void write(Object[] array, Writable packer, EncodingCache encodingCache) { - packer.startArray(array.length); - for (Object value : array) { - packer.writeObject(value, encodingCache); - } - } - } - - private static final class MapWriter implements ValueWriter> { - - @Override - public void write( - Map value, Writable packer, EncodingCache encodingCache) { - packer.writeMap(value, encodingCache); - } - } - - private static final class DoubleWriter implements ValueWriter { - - @Override - public void write(Double value, Writable packer, EncodingCache encodingCache) { - packer.writeDouble(value); - } - } - - private static final class BooleanWriter implements ValueWriter { - - @Override - public void write(Boolean value, Writable packer, EncodingCache encodingCache) { - packer.writeBoolean(value); - } - } - - private static final class FloatWriter implements ValueWriter { - - @Override - public void write(Float value, Writable packer, EncodingCache encodingCache) { - packer.writeFloat(value); - } - } - - private static final class IntWriter implements ValueWriter { - - @Override - public void write(Integer value, Writable packer, EncodingCache encodingCache) { - packer.writeInt(value); - } - } - - private static final class ShortWriter implements ValueWriter { - - @Override - public void write(Short value, Writable packer, EncodingCache encodingCache) { - packer.writeInt(value); - } - } - - private static final class LongWriter implements ValueWriter { - - @Override - public void write(Long value, Writable packer, EncodingCache encodingCache) { - packer.writeLong(value); - } - } - - private static final class NumberDoubleWriter implements ValueWriter { - - @Override - public void write(Number value, Writable packer, EncodingCache encodingCache) { - packer.writeDouble(value.doubleValue()); - } - } - - private static final class CharSequenceWriter implements ValueWriter { - - public static final CharSequenceWriter INSTANCE = new CharSequenceWriter(); - - @Override - public void write(CharSequence value, Writable packer, EncodingCache encodingCache) { - packer.writeString(value, encodingCache); - } - } - - private static final class CharArrayWriter implements ValueWriter { - - @Override - public void write(char[] value, Writable packer, EncodingCache encodingCache) { - packer.writeString(CharBuffer.wrap(value), null); - } - } - - private static final class DefaultWriter implements ValueWriter { - - public static final DefaultWriter INSTANCE = new DefaultWriter(); - - @Override - public void write(Object value, Writable packer, EncodingCache encodingCache) { - CharSequenceWriter.INSTANCE.write(String.valueOf(value), packer, null); - } - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/msgpack/MsgPackWriter.java b/features/dd-trace-core/src/main/java/datadog/trace/serialization/msgpack/MsgPackWriter.java deleted file mode 100644 index 31cbe8db51..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/msgpack/MsgPackWriter.java +++ /dev/null @@ -1,581 +0,0 @@ -package datadog.trace.serialization.msgpack; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import datadog.trace.serialization.Codec; -import datadog.trace.serialization.EncodingCache; -import datadog.trace.serialization.Mapper; -import datadog.trace.serialization.StreamingBuffer; -import datadog.trace.serialization.ValueWriter; -import datadog.trace.serialization.WritableFormatter; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; -import java.nio.BufferOverflowException; -import java.nio.ByteBuffer; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** Not thread-safe (use one per thread). */ -public class MsgPackWriter implements WritableFormatter { - - private static final Logger log = LoggerFactory.getLogger(MsgPackWriter.class); - - // see https://github.com/msgpack/msgpack/blob/master/spec.md - public static final byte NULL = (byte) 0xC0; - - public static final byte FALSE = (byte) 0xC2; - public static final byte TRUE = (byte) 0xC3; - - public static final byte UINT8 = (byte) 0xCC; - public static final byte UINT16 = (byte) 0xCD; - public static final byte UINT32 = (byte) 0xCE; - public static final byte UINT64 = (byte) 0xCF; - - public static final byte INT8 = (byte) 0xD0; - public static final byte INT16 = (byte) 0xD1; - public static final byte INT32 = (byte) 0xD2; - public static final byte INT64 = (byte) 0xD3; - - public static final byte FLOAT32 = (byte) 0xCA; - public static final byte FLOAT64 = (byte) 0xCB; - - public static final byte STR8 = (byte) 0xD9; - public static final byte STR16 = (byte) 0xDA; - public static final byte STR32 = (byte) 0xDB; - - public static final byte BIN8 = (byte) 0xC4; - public static final byte BIN16 = (byte) 0xC5; - public static final byte BIN32 = (byte) 0xC6; - - public static final byte ARRAY16 = (byte) 0xDC; - public static final byte ARRAY32 = (byte) 0xDD; - - public static final byte MAP16 = (byte) 0xDE; - public static final byte MAP32 = (byte) 0xDF; - - public static final int NEGFIXNUM = 0xE0; - public static final int FIXSTR = 0xA0; - public static final int FIXARRAY = 0x90; - public static final int FIXMAP = 0x80; - - private final Codec codec; - - private final StreamingBuffer buffer; - - public MsgPackWriter(StreamingBuffer buffer) { - this(Codec.INSTANCE, buffer); - } - - public MsgPackWriter(Codec codec, StreamingBuffer buffer) { - this.codec = codec; - this.buffer = buffer; - } - - @Override - public void flush() { - if (buffer.isDirty()) { - buffer.flush(); - } - } - - @Override - public boolean format(T message, Mapper mapper) { - try { - mapper.map(message, this); - buffer.mark(); - return true; - } catch (BufferOverflowException overflow) { - // if the buffer has finite capacity, it will overflow - // if we tried to serialise a message larger than the - // max capacity, then reject the message - if (buffer.flush()) { - try { - mapper.map(message, this); - buffer.mark(); - return true; - } catch (BufferOverflowException fatal) { - log.debug( - "dropping message because its serialized size is too large (> {}MB)", - (buffer.capacity() >>> 20)); - } - } - buffer.reset(); - return false; - } - } - - // NOTE - implementations pulled up to this level should - // not write directly to the buffer - - @Override - public void writeMap(Map map, EncodingCache encodingCache) { - startMap(map.size()); - for (Map.Entry entry : map.entrySet()) { - writeString(entry.getKey(), encodingCache); - writeObject(entry.getValue(), encodingCache); - } - } - - @Override - @SuppressWarnings({"rawtypes", "unchecked"}) - public void writeObject(Object value, EncodingCache encodingCache) { - // unpeel a very common case, but should try to move away from sending - // UTF8BytesString down this codepath at all - if (value instanceof UTF8BytesString) { - writeUTF8((UTF8BytesString) value); - } else if (null == value) { - writeNull(); - } else { - ValueWriter writer = codec.get(value.getClass()); - writer.write(value, this, encodingCache); - } - } - - @Override - @SuppressWarnings({"rawtypes", "unchecked"}) - public void writeObjectString(Object value, EncodingCache encodingCache) { - // unpeel a very common case, but should try to move away from sending - // UTF8BytesString down this codepath at all - if (value instanceof UTF8BytesString) { - writeUTF8((UTF8BytesString) value); - } else if (null == value) { - writeNull(); - } else { - String s = String.valueOf(value); - if (null != encodingCache) { - byte[] utf8 = encodingCache.encode(s); - if (null != utf8) { - writeUTF8(utf8); - return; - } - } - writeUTF8(s.getBytes(UTF_8)); - } - } - - @Override - public void writeNull() { - buffer.put(NULL); - } - - @Override - public void writeBoolean(boolean value) { - buffer.put(value ? TRUE : FALSE); - } - - @Override - public void writeString(CharSequence s, EncodingCache encodingCache) { - if (null == s) { - writeNull(); - } else { - if (null != encodingCache) { - byte[] utf8 = encodingCache.encode(s); - if (null != utf8) { - writeUTF8(utf8); - return; - } - } - if (s instanceof UTF8BytesString) { - writeUTF8((UTF8BytesString) s); - } else { - writeUTF8(String.valueOf(s).getBytes(UTF_8)); - } - } - } - - @Override - public void writeUTF8(byte[] string, int offset, int length) { - writeStringHeader(length); - buffer.put(string, offset, length); - } - - @Override - public void writeUTF8(byte[] string) { - writeUTF8(string, 0, string.length); - } - - @Override - public void writeUTF8(UTF8BytesString string) { - writeStringHeader(string.encodedLength()); - buffer.put(string.getUtf8Bytes()); - } - - @Override - public void writeBinary(byte[] binary) { - writeBinaryHeader(binary.length); - buffer.put(binary); - } - - @Override - public void writeBinary(byte[] binary, int offset, int length) { - writeBinaryHeader(length); - buffer.put(binary, offset, length); - } - - @Override - public void writeBinary(ByteBuffer binary) { - ByteBuffer slice = binary.slice(); - writeBinaryHeader(slice.limit() - slice.position()); - buffer.put(slice); - } - - @Override - public void writeInt(int value) { - if (value < 0) { - switch (Integer.numberOfLeadingZeros(~value)) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - buffer.put(INT32); - buffer.putInt(value); - break; - case 17: - case 18: - case 19: - case 20: - case 21: - case 22: - case 23: - case 24: - buffer.put(INT16); - buffer.putChar((char) value); - break; - case 25: - case 26: - buffer.put(INT8); - buffer.put((byte) value); - break; - case 27: - case 28: - case 29: - case 30: - case 31: - case 32: - default: - buffer.put((byte) (NEGFIXNUM | value)); - } - } else { - switch (Integer.numberOfLeadingZeros(value)) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - buffer.put(UINT32); - buffer.putInt(value); - break; - case 16: - case 17: - case 18: - case 19: - case 20: - case 21: - case 22: - case 23: - buffer.put(UINT16); - buffer.putChar((char) value); - break; - case 24: - buffer.put(UINT8); - buffer.put((byte) value); - break; - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - case 32: - default: - buffer.put((byte) value); - } - } - } - - @Override - public void writeSignedInt(int value) { - writeInt(value); - } - - @Override - public void writeLong(long value) { - writeLongInternal(value, false); - } - - @Override - public void writeUnsignedLong(long value) { - writeLongInternal(value, true); - } - - public void writeLongInternal(long value, boolean forceUnsigned) { - if (value < 0 && !forceUnsigned) { - switch (Long.numberOfLeadingZeros(~value)) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - case 18: - case 19: - case 20: - case 21: - case 22: - case 23: - case 24: - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - case 32: - buffer.put(INT64); - buffer.putLong(value); - break; - case 33: - case 34: - case 35: - case 36: - case 37: - case 38: - case 39: - case 40: - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - case 47: - case 48: - buffer.put(INT32); - buffer.putInt((int) value); - break; - case 49: - case 50: - case 51: - case 52: - case 53: - case 54: - case 55: - case 56: - buffer.put(INT16); - buffer.putChar((char) value); - break; - case 57: - case 58: - buffer.put(INT8); - buffer.put((byte) value); - break; - case 59: - case 60: - case 61: - case 62: - case 63: - case 64: - default: - buffer.put((byte) (NEGFIXNUM | value)); - } - } else { - switch (Long.numberOfLeadingZeros(value)) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - case 18: - case 19: - case 20: - case 21: - case 22: - case 23: - case 24: - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - buffer.put(UINT64); - buffer.putLong(value); - break; - case 32: - case 33: - case 34: - case 35: - case 36: - case 37: - case 38: - case 39: - case 40: - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - case 47: - buffer.put(UINT32); - buffer.putInt((int) value); - break; - case 48: - case 49: - case 50: - case 51: - case 52: - case 53: - case 54: - case 55: - buffer.put(UINT16); - buffer.putChar((char) value); - break; - case 56: - buffer.put(UINT8); - buffer.put((byte) value); - break; - case 57: - case 59: - case 60: - case 61: - case 62: - case 63: - case 64: - default: - buffer.put((byte) value); - } - } - } - - @Override - public void writeSignedLong(long value) { - writeLong(value); - } - - @Override - public void writeFloat(float value) { - // The datadog agent fails to decode FLOAT32 even though the code in read_bytes.go looks like - // it will try to decode FLOAT32 just fine. Even if there will be a fix in a future datadog - // agent release, we need to be backwards compatible here by sending it as a FLOAT64 instead. - buffer.put(FLOAT64); - buffer.putDouble(value); - } - - @Override - public void writeDouble(double value) { - buffer.put(FLOAT64); - buffer.putDouble(value); - } - - @Override - public void startMap(int elementCount) { - if (elementCount < 0x10) { - buffer.put((byte) (FIXMAP | elementCount)); - } else if (elementCount < 0x10000) { - buffer.put(MAP16); - buffer.putShort((short) elementCount); - } else { - buffer.put(MAP32); - buffer.putInt(elementCount); - } - } - - @Override - public void startStruct(int elementCount) { - startArray(elementCount); - } - - @Override - public void startArray(int elementCount) { - if (elementCount < 0x10) { - buffer.put((byte) (FIXARRAY | elementCount)); - } else if (elementCount < 0x10000) { - buffer.put(ARRAY16); - buffer.putShort((short) elementCount); - } else { - buffer.put(ARRAY32); - buffer.putInt(elementCount); - } - } - - void writeStringHeader(int length) { - if (length < 0x10) { - buffer.put((byte) (FIXSTR | length)); - } else if (length < 0x100) { - buffer.put(STR8); - buffer.put((byte) length); - } else if (length < 0x10000) { - buffer.put(STR16); - buffer.putShort((short) length); - } else { - buffer.put(STR32); - buffer.putInt(length); - } - } - - void writeBinaryHeader(int length) { - if (length < 0x100) { - buffer.put(BIN8); - buffer.put((byte) length); - } else if (length < 0x10000) { - buffer.put(BIN16); - buffer.putShort((short) length); - } else { - buffer.put(BIN32); - buffer.putInt(length); - } - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/ClassNameTrie.java b/features/dd-trace-core/src/main/java/datadog/trace/util/ClassNameTrie.java deleted file mode 100644 index 378e85e7a7..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/ClassNameTrie.java +++ /dev/null @@ -1,927 +0,0 @@ -package datadog.trace.util; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Immutable space-efficient trie that captures a mapping of package/class names to numbers. - * - *

    Each node of the trie is represented as a series of {@code char}s using this layout: - * - *

    - * +--------------------------------------+
    - * | number of branches                   |
    - * +--------------------------------------+--------------------------------------+----
    - * | char for branch 0                    | char for branch 1                    | ...
    - * +--------------------------------------+--------------------------------------+----
    - * | segment-length/leaf/bud for branch 0 | segment-length/leaf/bud for branch 1 | ...
    - * +--------------------------------------+--------------------------------------+----
    - * | offset to jump to branch 1           | offset to jump to branch 2           | ...
    - * +--------------------------------------+--------------------------------------+----
    - * 
    - * - * Each node is followed by its child nodes according to branch order, separated by the characters - * expected for that segment of the trie. Segments that represent the end of a name with no further - * branches are followed by a leaf character instead of a child node. - * - *

    Leaves mark a definite end of the match, while buds mark a potential end that could continue - * to a different result if there are more characters to match. A match is a success when either the - * entire key is matched or the match is a glob. - * - *

    The jump for branch 0 is assumed to be 0 and is always omitted, that is any continuation of - * the trie for branch 0 immediately follows the current node. Long jumps that don't fit into a char - * are replaced by an index into a long jump table. - * - *

    For example this mapping: - * - *

    - * 2 akka.stream.*
    - * 0 akka.stream.impl.FanIn$SubInput
    - * 0 akka.stream.impl.FanOut$SubstreamSubscription
    - * 0 akka.stream.impl.fusing.ActorGraphInterpreter$*
    - * 0 akka.stream.stage.GraphStageLogic$*
    - * 0 akka.stream.stage.TimerGraphStageLogic$*
    - * 2 ch.qos.logback.*
    - * 0 ch.qos.logback.classic.Logger
    - * 0 ch.qos.logback.classic.spi.LoggingEvent*
    - * 0 ch.qos.logback.core.AsyncAppenderBase$Worker
    - * 
    - * - * is generated into a string trie with this structure: (formatted for readability) - * - *
    - * | 2 | a | c | length (10) | length (13) | jump (150)
    - * kka.stream | 1 | . | bud+glob (2)
    - *            | 2 | i | s | length (4) | length (5) | jump (83)
    - *            mpl. | 2 | F | f | length (2) | length (28) | jump (44)
    - *                 an | 2 | I | O | length (10) | length (24) | jump (11)
    - *                    n$SubInput | leaf (0)
    - *                    ut$SubstreamSubscription | leaf (0)
    - *                 using.ActorGraphInterpreter$ | leaf+glob (0)
    - *            tage. | 2 | G | T | length (15) | length (20) | jump (16)
    - *                  raphStageLogic$ | leaf+glob (0)
    - *                  imerGraphStageLogic$ | leaf+glob (0)
    - * h.qos.logback | 1 | . | bud+glob (2)
    - *               | 1 | c | length (0)
    - *               | 2 | l | o | length (6) | length (27) | jump (40)
    - *               assic. | 2 | L | s | length (5) | length (14) | jump (6)
    - *                      ogger | leaf (0)
    - *                      pi.LoggingEvent | leaf+glob (0)
    - *               re.AsyncAppenderBase$Worker | leaf(0)
    - * 
    - */ -public final class ClassNameTrie { - - /** Marks a leaf in the trie, where the rest of the bits are the index to be returned. */ - private static final char LEAF_MARKER = 0x8000; - - /** Marks a 'bud' in the trie; the same as a leaf except the trie continues beneath it. */ - private static final char BUD_MARKER = 0x4000; - - /** Marks a glob in the trie, where a match succeeds even if the key has extra characters. */ - private static final char GLOB_MARKER = 0x2000; - - /** Maximum value that can be held in a single node of the trie. */ - private static final char MAX_NODE_VALUE = 0x1FFF; - - /** Marks a long jump that was replaced by an index into the long jump table. */ - private static final char LONG_JUMP_MARKER = 0x8000; - - /** A branch has at most 3 control characters: key, value, and optional jump offset/id. */ - private static final int BRANCH_CONTROL_CHARS = 3; - - /** Constant to account for the fact that the last branch doesn't have a jump offset/id. */ - private static final int NO_END_JUMP = 1; - - private static final int FILE_MAGIC = 0xDD097213; - - /** The compressed trie. */ - private final char[] trieData; - - /** Long jump offsets. */ - private final int[] longJumps; - - public int apply(String key) { - return apply(trieData, longJumps, key); - } - - public static int apply(char[] data, int[] longJumps, String key) { - int keyLength = key.length(); - int keyIndex = 0; - int dataIndex = 0; - int result = -1; - - while (keyIndex < keyLength) { - char c = key.charAt(keyIndex++); - char branchCount = data[dataIndex++]; - - // trie is ordered, so we can use binary search to pick the right branch - int branchIndex = - Arrays.binarySearch(data, dataIndex, dataIndex + branchCount, c == '/' ? '.' : c); - - if (branchIndex < 0) { - return result; // key doesn't match against any future branches - } - - int valueIndex = branchIndex + branchCount; - char value = data[valueIndex]; - int segmentLength = 0; - - if ((value & (LEAF_MARKER | BUD_MARKER)) != 0) { - // update result if we've matched the key, or we're at a glob - if (keyIndex == keyLength || (value & GLOB_MARKER) != 0) { - result = value & MAX_NODE_VALUE; - } - // stop if there's no more characters left in the key, or we've reached a leaf - if (keyIndex == keyLength || (value & LEAF_MARKER) != 0) { - return result; - } - } else { - segmentLength = value; // value is the length of the segment before the next node - } - - // move on to the segment/node for the picked branch... - if (branchIndex > dataIndex) { - int branchJump = data[valueIndex + branchCount - 1]; - if ((branchJump & LONG_JUMP_MARKER) != 0) { - branchJump = longJumps[branchJump & ~LONG_JUMP_MARKER]; - } - dataIndex += branchJump; - } - - // ...always include moving past the current node - dataIndex += (branchCount * BRANCH_CONTROL_CHARS) - NO_END_JUMP; - - // attempt to match any inline segment that precedes the next node - if (segmentLength > 0) { - if (keyLength - keyIndex < segmentLength) { - return result; // not enough characters left in the key - } - int segmentEnd = dataIndex + segmentLength; - while (dataIndex < segmentEnd) { - c = key.charAt(keyIndex++); - if ((c == '/' ? '.' : c) != data[dataIndex++]) { - return result; // segment doesn't match - } - } - // peek ahead - it will either be a node or a leaf - value = data[dataIndex]; - if ((value & LEAF_MARKER) != 0) { - // update result if we've matched the key, or we're at a glob - if (keyIndex == keyLength || (value & GLOB_MARKER) != 0) { - result = value & MAX_NODE_VALUE; - } - return result; // no more characters left to match in the trie - } - } - } - - return result; // no more characters left to match in the key - } - - /** Reads trie content from an external resource. */ - public static ClassNameTrie readFrom(DataInput in) throws IOException { - int magic = in.readInt(); - if (magic != FILE_MAGIC) { - throw new IOException("Unexpected file magic " + magic); - } - int trieLength = in.readInt(); - char[] trieData = new char[trieLength]; - for (int i = 0; i < trieLength; i++) { - byte b = in.readByte(); - char c; - if ((b & 0x80) == 0) { - // read 7-bit non-zero char as 1 byte - c = (char) b; - } else if ((b & 0xE0) == 0xE0) { - // read 16-bit char as 3 bytes (4+6+6) - c = (char) (((b & 0x0F) << 12) | ((in.readByte() & 0x3F) << 6) | (in.readByte() & 0x3F)); - } else { - // read 11-bit char as 2 bytes (5+6) - c = (char) (((b & 0x1F) << 6) | (in.readByte() & 0x3F)); - } - trieData[i] = c; - } - int longJumpCount = in.readInt(); - int[] longJumps; - if (longJumpCount > 0) { - longJumps = new int[longJumpCount]; - for (int i = 0; i < longJumpCount; i++) { - longJumps[i] = in.readInt(); - } - } else { - longJumps = null; - } - return new ClassNameTrie(trieData, longJumps); - } - - ClassNameTrie(char[] trieData, int[] longJumps) { - this.trieData = trieData; - this.longJumps = longJumps; - } - - /** Builds an in-memory trie that represents a mapping of {class-name} to {number}. */ - public static class Builder { - public static final ClassNameTrie EMPTY_TRIE = new ClassNameTrie(new char[] {0x0000}, null); - - private static final Pattern MAPPING_LINE = Pattern.compile("^\\s*(?:([0-9]+)\\s+)?([^\\s#]+)"); - - private char[] trieData; - private int trieLength; - private int[] longJumps; - private int longJumpCount; - - public Builder() {} - - public Builder(ClassNameTrie trie) { - trieData = trie.trieData; - trieLength = trieData.length; - longJumps = trie.longJumps; - longJumpCount = null != longJumps ? longJumps.length : 0; - } - - public boolean isEmpty() { - return trieLength == 0; - } - - /** Allow querying while the class-name trie is being built. */ - public int apply(String key) { - return trieLength > 0 ? ClassNameTrie.apply(trieData, longJumps, key) : -1; - } - - public ClassNameTrie buildTrie() { - if (trieLength == 0) { - return EMPTY_TRIE; - } - // avoid unnecessary allocation when compaction isn't required - if (trieData.length > trieLength) { - trieData = Arrays.copyOfRange(trieData, 0, trieLength); - } - if (null != longJumps && longJumps.length > longJumpCount) { - longJumps = Arrays.copyOfRange(longJumps, 0, longJumpCount); - } - return new ClassNameTrie(trieData, longJumps); - } - - /** Writes trie content to an external resource. */ - public void writeTo(DataOutput out) throws IOException { - out.writeInt(FILE_MAGIC); - out.writeInt(trieLength); - for (int i = 0; i < trieLength; i++) { - char c = trieData[i]; - if (c >= 0x0001 && c <= 0x007F) { - // write 7-bit non-zero char as 1 byte - out.writeByte(c); - } else if (c > 0x07FF) { - // write 16-bit char as 3 bytes (4+6+6) - out.writeByte(0xE0 | ((c >> 12) & 0x0F)); - out.writeByte(0x80 | ((c >> 6) & 0x3F)); - out.writeByte(0x80 | (c & 0x3F)); - } else { - // write 11-bit char as 2 bytes (5+6) - out.writeByte(0xC0 | ((c >> 6) & 0x1F)); - out.writeByte(0x80 | (c & 0x3F)); - } - } - out.writeInt(longJumpCount); - for (int i = 0; i < longJumpCount; i++) { - out.writeInt(longJumps[i]); - } - } - - /** Reads a class-name mapping file into the current builder */ - public void readClassNameMapping(Path triePath) throws IOException { - for (String l : Files.readAllLines(triePath, StandardCharsets.UTF_8)) { - Matcher m = MAPPING_LINE.matcher(l); - if (m.find()) { - put(m.group(2), m.group(1) != null ? Integer.parseInt(m.group(1)) : 1); - } - } - } - - /** Merges a new class-name mapping into the current builder */ - public void put(String className, int number) { - if (null == className || className.isEmpty()) { - throw new IllegalArgumentException("Null or empty class name"); - } - if (number < 0) { - throw new IllegalArgumentException("Number for " + className + " is negative: " + number); - } - if (number > MAX_NODE_VALUE) { - throw new IllegalArgumentException("Number for " + className + " is too big: " + number); - } - - String key; - char value; - // package/class-names ending in '*' are marked as globs - if (className.charAt(className.length() - 1) == '*') { - key = className.substring(0, className.length() - 1); - value = (char) (number | GLOB_MARKER); - } else { - key = className; - value = (char) number; - } - - if (trieLength == 0) { - int keyLength = key.length(); - trieLength = (keyLength > 1 ? 3 : 2) + keyLength; - trieData = new char[8192]; // create table on first mapping - trieData[0] = (char) 1; - trieData[1] = key.charAt(0); - if (keyLength > 1) { - trieData[2] = (char) (keyLength - 1); - key.getChars(1, keyLength, trieData, 3); - } - trieData[trieLength - 1] = (char) (value | LEAF_MARKER); - } else { - insertMapping(key, value); - } - } - - /** Makes a hole in the current trie data to fit a new node/branch, etc. */ - private void makeHole(int start, int length) { - char[] oldData = trieData; - if (trieLength + length > oldData.length) { - trieData = new char[Math.max(trieLength + length, oldData.length + (oldData.length >> 1))]; - System.arraycopy(oldData, 0, trieData, 0, start); - } - System.arraycopy(oldData, start, trieData, start + length, trieLength - start); - trieLength += length; - } - - /** Moves jump values that won't fit into the long-jump table and replaces them with an id. */ - private char setJump(int jump) { - if (jump < LONG_JUMP_MARKER) { - return (char) jump; // jump is small enough to fit into the trie - } - if (longJumpCount == 0) { - longJumps = new int[16]; // create table on first long-jump - } else if (longJumpCount == longJumps.length) { - int[] oldJumps = longJumps; - // expand table by 50% to fit additional long-jumps - longJumps = new int[longJumpCount + (longJumpCount >> 1)]; - System.arraycopy(oldJumps, 0, longJumps, 0, longJumpCount); - } - longJumps[longJumpCount] = jump; - return (char) (longJumpCount++ | LONG_JUMP_MARKER); - } - - /** Restores jump values previously moved into the long-jump table. */ - private int getJump(char jump) { - return (jump & LONG_JUMP_MARKER) == 0 ? jump : longJumps[jump & ~LONG_JUMP_MARKER]; - } - - /** - * Increases jump by the given offset, this may result in it moving into the long-jump table. - */ - private char updateJump(char jump, int offset) { - if (jump < LONG_JUMP_MARKER) { - return setJump(jump + offset); - } - longJumps[jump & ~LONG_JUMP_MARKER] += offset; - return jump; - } - - private void insertMapping(String key, char valueToInsert) { - BitSet jumpsToOffset = new BitSet(); - - int keyLength = key.length(); - int keyIndex = 0; - int dataIndex = 0; - int subTrieEnd = trieLength; - int jumpOffset = 0; - - while (keyIndex < keyLength) { - char c = key.charAt(keyIndex++); - char branchCount = trieData[dataIndex++]; - - // trie is ordered, so we can use binary search to pick the right branch - int branchIndex = Arrays.binarySearch(trieData, dataIndex, dataIndex + branchCount, c); - - if (branchIndex < 0) { - jumpOffset = - insertBranch( - dataIndex, - key, - keyIndex - 1, - valueToInsert, - branchCount, - ~branchIndex - dataIndex, - subTrieEnd); - break; - } - - int valueIndex = branchIndex + branchCount; - char value = trieData[valueIndex]; - - if ((value & (LEAF_MARKER | BUD_MARKER)) != 0 && keyIndex == keyLength) { - // duplicate key: overwrite existing value in the tree with the new value - trieData[valueIndex] = (char) ((value & ~MAX_NODE_VALUE) | valueToInsert); - return; - } - - int branch = branchIndex - dataIndex; - if (branch < branchCount - 1) { - int nextJumpIndex = valueIndex + branchCount; - int nextBranchJump = getJump(trieData[nextJumpIndex]); - - // update subTrieEnd to reflect we've moved down a left/centre branch - subTrieEnd = - dataIndex + (branchCount * BRANCH_CONTROL_CHARS) - NO_END_JUMP + nextBranchJump; - - // remember to update jump offsets on right once we know how much we've added - for (int b = branch + 1; b < branchCount; b++) { - jumpsToOffset.set(nextJumpIndex++); - } - } - - // move on to the segment/node for the picked branch... - if (branch > 0) { - dataIndex += getJump(trieData[valueIndex + branchCount - 1]); - } - - // ...always include moving past the current node - dataIndex += (branchCount * BRANCH_CONTROL_CHARS) - NO_END_JUMP; - - if ((value & LEAF_MARKER) != 0) { - // change leaf branch to a bud and append our new leaf node below it - trieData[valueIndex] = (char) ((value & ~LEAF_MARKER) | BUD_MARKER); - jumpOffset = appendLeaf(dataIndex, key, keyIndex, valueToInsert); - break; - } else if ((value & BUD_MARKER) != 0) { - // ignore bud as we still have more of the key to match - continue; - } else if (keyIndex == keyLength) { - // branch originally led to a segment - record it's now a bud - trieData[valueIndex] = (char) (valueToInsert | BUD_MARKER); - if (value > 0) { - // add the usual node preamble before the old segment - jumpOffset = prependNode(dataIndex, value - 1); - } - break; - } - - // must be a segment - try to match as much as possible before we insert a bud/leaf - if (value > 0) { - int segmentLength = value; - int segmentEnd = dataIndex + segmentLength; - while (keyIndex < keyLength && dataIndex < segmentEnd) { - c = key.charAt(keyIndex); - if (c != trieData[dataIndex]) { - break; - } - keyIndex++; - dataIndex++; - } - if (dataIndex < segmentEnd) { - if (keyIndex == keyLength) { - // key is shorter than segment; add bud at the point the key ends - trieData[valueIndex] -= segmentEnd - (dataIndex - 1); - jumpOffset = insertBud(dataIndex - 1, valueToInsert, segmentEnd); - } else { - // key diverges from segment; add leaf on left/right to capture that - trieData[valueIndex] -= segmentEnd - dataIndex; - if (c < trieData[dataIndex]) { - jumpOffset = insertLeafLeft(dataIndex, key, keyIndex, valueToInsert, segmentEnd); - } else { - jumpOffset = - insertLeafRight( - dataIndex, key, keyIndex, valueToInsert, segmentEnd, subTrieEnd); - } - } - break; // nothing more to add - } - - // peek ahead - it will either be a node or a leaf - value = trieData[dataIndex]; - if ((value & LEAF_MARKER) != 0) { - if (keyIndex < keyLength) { - // key goes past leaf segment, extend old leaf with a bud node and add our new leaf - trieData[valueIndex]--; - jumpOffset = appendLeaf(dataIndex, key, keyIndex, valueToInsert); - break; - } else { - // duplicate key: overwrite existing value in the tree with the new value - trieData[dataIndex] = (char) ((value & ~MAX_NODE_VALUE) | valueToInsert); - return; - } - } else /* segment is followed by a node */ { - if (keyIndex == keyLength) { - // key stops at boundary between segment and node, insert bud node just before this - trieData[valueIndex]--; - jumpOffset = prependNode(dataIndex - 1, valueToInsert | BUD_MARKER); - break; - } - } - } - } - - if (jumpOffset > 0) { - // now we know how much we added, update all jumps that need to jump past our addition - for (int i = jumpsToOffset.nextSetBit(0); i >= 0; i = jumpsToOffset.nextSetBit(i + 1)) { - trieData[i] = updateJump(trieData[i], jumpOffset); - } - } - } - - private int insertBranch( - int dataIndex, - String key, - int keyIndex, - int value, - int branchCount, - int newBranch, - int subTrieEnd) { - - int remainingKeyLength = key.length() - keyIndex; - int insertedCharacters = 3 /* segment-length, jump, value */ + remainingKeyLength; - - // can collapse branch if the key only has a single character left - boolean collapseRight = remainingKeyLength == 1; - if (collapseRight) { - remainingKeyLength = 0; - insertedCharacters = 3; /* branch-key, value, jump */ - } - - int i = dataIndex + newBranch, j = i + insertedCharacters; - - makeHole(i, insertedCharacters); - - // update branch count leading into our branches - trieData[dataIndex - 1] = (char) (branchCount + 1); - - // insert our new branch key - trieData[i++] = key.charAt(keyIndex); - System.arraycopy(trieData, j, trieData, i, branchCount); - i += branchCount; - j += branchCount; - - // insert our new branch value - trieData[i++] = (char) (collapseRight ? value | LEAF_MARKER : remainingKeyLength - 1); - - int subTrieStart = dataIndex + (branchCount * BRANCH_CONTROL_CHARS) - NO_END_JUMP; - - int precedingJump; - if (newBranch < branchCount) { - // adding branch on left/centre - System.arraycopy(trieData, j, trieData, i, branchCount); - i += branchCount; - j += branchCount; - precedingJump = newBranch > 0 ? getJump(trieData[i - 1]) : 0; - // calculate jump for next branch, using previous jump as a reference - trieData[i++] = setJump(precedingJump + remainingKeyLength); - for (int b = newBranch + 1; b < branchCount; b++) { - // update old branch jumps on right to account for added content - trieData[i++] = updateJump(trieData[j++], remainingKeyLength); - } - } else { - // adding branch on right - System.arraycopy(trieData, j, trieData, i, branchCount - 1); - i += branchCount - 1; - j += branchCount - 1; - // calculate jump needed to reach our new branch based on the size of the old sub-trie - precedingJump = subTrieEnd - subTrieStart; - trieData[i++] = setJump(precedingJump); - } - - // now move up the sub-trie content before our new branch - System.arraycopy(trieData, subTrieStart + insertedCharacters, trieData, i, precedingJump); - i += precedingJump; - - if (!collapseRight) { - // lastly add the rest of our key as a leaf segment under our new branch - key.getChars(keyIndex + 1, key.length(), trieData, i); - i += remainingKeyLength - 1; - trieData[i++] = (char) (value | LEAF_MARKER); - } - - return insertedCharacters; - } - - private int prependNode(int dataIndex, int value) { - int insertedCharacters = 2; /* branch count, value */ - - // can collapse branch if it would lead to a leaf segment of zero-length - boolean collapseRight = value == 0 && (trieData[dataIndex + 1] & LEAF_MARKER) != 0; - if (collapseRight) { - insertedCharacters--; - } - - int i = dataIndex, j = i + insertedCharacters; - - makeHole(i, insertedCharacters); - - trieData[i++] = 1; - trieData[i++] = trieData[j]; - if (!collapseRight) { - trieData[i++] = (char) value; - } - - return insertedCharacters; - } - - private int insertBud(int dataIndex, int value, int segmentEnd) { - int insertedCharacters = 4; // branch count (bud), value, branch count (rest), segment-length - int pivot = dataIndex + 2; - - // can collapse right branch if it would lead to a leaf segment of zero-length - boolean collapseRight = pivot == segmentEnd && (trieData[segmentEnd] & LEAF_MARKER) != 0; - if (collapseRight) { - insertedCharacters = 3; - } - - int i = dataIndex, j = i + insertedCharacters; - - makeHole(i, insertedCharacters); - - trieData[i++] = 1; - trieData[i++] = trieData[j]; - trieData[i++] = (char) (value | BUD_MARKER); - trieData[i++] = 1; - trieData[i++] = trieData[j + 1]; - if (!collapseRight) { - trieData[i++] = (char) (segmentEnd - pivot); - } - - return insertedCharacters; - } - - private int insertLeafLeft(int dataIndex, String key, int keyIndex, int value, int segmentEnd) { - int remainingKeyLength = key.length() - keyIndex; - int insertedCharacters = - 5 /* branch count, 2 * segment-length, jump, value */ + remainingKeyLength; - int pivot = dataIndex + 1; - - // can collapse left branch if the key only has a single character left - boolean collapseLeft = remainingKeyLength == 1; - if (collapseLeft) { - insertedCharacters--; - } - // can collapse right branch if it would lead to a leaf segment of zero-length - boolean collapseRight = pivot == segmentEnd && (trieData[segmentEnd] & LEAF_MARKER) != 0; - if (collapseRight) { - insertedCharacters--; - pivot++; - } - - int i = dataIndex, j = i + insertedCharacters; - - makeHole(i, insertedCharacters); - - trieData[i++] = 2; - trieData[i++] = key.charAt(keyIndex); - trieData[i++] = trieData[j]; - trieData[i++] = (char) (collapseLeft ? value | LEAF_MARKER : remainingKeyLength - 1); - trieData[i++] = (char) (collapseRight ? trieData[j + 1] : segmentEnd - pivot); - if (!collapseLeft) { - trieData[i++] = (char) remainingKeyLength; - key.getChars(keyIndex + 1, key.length(), trieData, i); - i += remainingKeyLength - 1; - trieData[i++] = (char) (value | LEAF_MARKER); - } else { - trieData[i++] = 0; - } - - return insertedCharacters; - } - - private int insertLeafRight( - int dataIndex, String key, int keyIndex, int value, int segmentEnd, int subTrieEnd) { - int remainingKeyLength = key.length() - keyIndex; - int insertedCharacters = - 5 /* branch count, 2 * segment-length, jump, value */ + remainingKeyLength; - int pivot = dataIndex + 1; - - // can collapse left branch if it would lead to a leaf segment of zero-length - boolean collapseLeft = pivot == segmentEnd && (trieData[segmentEnd] & LEAF_MARKER) != 0; - if (collapseLeft) { - insertedCharacters--; - pivot++; - } - // can collapse right branch if the key only has a single character left - boolean collapseRight = remainingKeyLength == 1; - if (collapseRight) { - insertedCharacters--; - } - - int i = dataIndex, j = i + insertedCharacters; - - makeHole(i, insertedCharacters); - - trieData[i++] = 2; - trieData[i++] = trieData[j]; - trieData[i++] = key.charAt(keyIndex); - trieData[i++] = (char) (collapseLeft ? trieData[j + 1] : segmentEnd - pivot); - trieData[i++] = (char) (collapseRight ? value | LEAF_MARKER : remainingKeyLength - 1); - trieData[i++] = setJump(subTrieEnd - pivot); - System.arraycopy(trieData, pivot + insertedCharacters, trieData, i, subTrieEnd - pivot); - i += subTrieEnd - pivot; - if (!collapseRight) { - key.getChars(keyIndex + 1, key.length(), trieData, i); - i += remainingKeyLength - 1; - trieData[i++] = (char) (value | LEAF_MARKER); - } - - return insertedCharacters; - } - - private int appendLeaf(int dataIndex, String key, int keyIndex, int value) { - int remainingKeyLength = key.length() - keyIndex; - int insertedCharacters = 3 /* branch count, segment-length, value */ + remainingKeyLength; - - // if we're adding this to a leaf segment then we need to introduce a bud first - boolean insertBud = dataIndex < trieLength && (trieData[dataIndex] & LEAF_MARKER) != 0; - if (insertBud) { - insertedCharacters++; - } - // can collapse right branch if the key only has a single character left - boolean collapseRight = remainingKeyLength == 1; - if (collapseRight) { - insertedCharacters--; - } - - int i = dataIndex, j = i + insertedCharacters; - - makeHole(i, insertedCharacters); - - if (insertBud) { - char c = trieData[i - 1]; - trieData[i - 1] = 1; - trieData[i++] = c; - trieData[i++] = (char) ((trieData[j] & ~LEAF_MARKER) | BUD_MARKER); - } - trieData[i++] = 1; - trieData[i++] = key.charAt(keyIndex); - if (!collapseRight) { - trieData[i++] = (char) (remainingKeyLength - 1); - key.getChars(keyIndex + 1, key.length(), trieData, i); - i += remainingKeyLength - 1; - } - trieData[i++] = (char) (value | LEAF_MARKER); - - return insertedCharacters; - } - } - - /** Generates Java source for a trie described as a series of "{number} {class-name}" lines. */ - public static class JavaGenerator { - public static void main(String[] args) throws IOException { - if (args.length < 2) { - throw new IllegalArgumentException("Expected: trie-dir java-dir [file.trie ...]"); - } - Path trieDir = Paths.get(args[0]).toAbsolutePath().normalize(); - if (!Files.isDirectory(trieDir)) { - throw new IllegalArgumentException("Bad trie directory: " + trieDir); - } - Path javaDir = Paths.get(args[1]).toAbsolutePath().normalize(); - if (!Files.isDirectory(javaDir)) { - throw new IllegalArgumentException("Bad java directory: " + javaDir); - } - for (int i = 2; i < args.length; i++) { - Path triePath = trieDir.resolve(args[i]).normalize(); - String className = toClassName(triePath.getFileName().toString()); - Path pkgPath = trieDir.relativize(triePath.getParent()); - String pkgName = pkgPath.toString().replace(File.separatorChar, '.'); - Path javaPath = javaDir.resolve(pkgPath).resolve(className + ".java"); - generateJavaFile(triePath, javaPath, pkgName, className); - } - } - - /** Converts snake-case trie names to camel-case Java class names. */ - private static String toClassName(String trieName) { - StringBuilder className = new StringBuilder(); - boolean upperNext = true; - for (int i = 0; i < trieName.length(); i++) { - char c = trieName.charAt(i); - if (c == '_' | c == '.') { - upperNext = true; - } else { - className.append(upperNext ? Character.toUpperCase(c) : c); - upperNext = false; - } - } - return className.toString(); - } - - /** Reads a trie file and writes out the equivalent Java file. */ - private static void generateJavaFile( - Path triePath, Path javaPath, String pkgName, String className) throws IOException { - Builder trie = new Builder(); - trie.readClassNameMapping(triePath); - List lines = new ArrayList<>(); - if (!pkgName.isEmpty()) { - lines.add("package " + pkgName + ';'); - } - lines.add(""); - lines.add("import datadog.trace.util.ClassNameTrie;"); - lines.add(""); - lines.add("// Generated from '" + triePath.getFileName() + "' - DO NOT EDIT!"); - lines.add("public final class " + className + " {"); - lines.add(""); - boolean hasLongJumps = generateJavaTrie(lines, "", trie); - lines.add(""); - lines.add(" public static int apply(String key) {"); - if (hasLongJumps) { - lines.add(" return ClassNameTrie.apply(TRIE_DATA, LONG_JUMPS, key);"); - } else { - lines.add(" return ClassNameTrie.apply(TRIE_DATA, null, key);"); - } - lines.add(" }"); - lines.add(""); - lines.add(" private " + className + "() {}"); - lines.add("}"); - Files.write(javaPath, lines, StandardCharsets.UTF_8); - } - - /** Writes the Java form of the trie as a series of lines. */ - public static boolean generateJavaTrie( - List lines, String prefix, Builder trie) { - boolean hasLongJumps = trie.longJumpCount > 0; - int firstLineNumber = lines.size(); - int chunk = 1; - lines.add(" private static final String " + prefix + "TRIE_TEXT_" + chunk + " ="); - int chunkSize = 0; - StringBuilder buf = new StringBuilder(); - buf.append(" \""); - for (int i = 0; i < trie.trieLength; i++) { - char c = trie.trieData[i]; - if (++chunkSize > 10_000) { - chunk++; - chunkSize = 0; - lines.add(buf + "\";"); - lines.add(""); - lines.add(" private static final String " + prefix + "TRIE_TEXT_" + chunk + " ="); - buf.setLength(0); - buf.append(" \""); - } else if (buf.length() > 120) { - lines.add(buf + "\""); - buf.setLength(0); - buf.append(" + \""); - } - if (c <= 0x00FF) { - buf.append(String.format("\\%03o", (int) c)); - } else { - buf.append(String.format("\\u%04x", (int) c)); - } - } - lines.add(buf + "\";"); - lines.add(""); - if (chunk > 1) { - lines.add(" private static final char[] " + prefix + "TRIE_DATA;"); - lines.add(" static {"); - lines.add(" int dataLength = 0;"); - for (int n = 1; n <= chunk; n++) { - lines.add(" dataLength += " + prefix + "TRIE_TEXT_" + n + ".length();"); - } - lines.add(" " + prefix + "TRIE_DATA = new char[dataLength];"); - lines.add(" int dataIndex = 0;"); - lines.add(" String chunk;"); - for (int n = 1; n <= chunk; n++) { - lines.add(" chunk = " + prefix + "TRIE_TEXT_" + n + ";"); - lines.add(" chunk.getChars(0, chunk.length(), " + prefix + "TRIE_DATA, dataIndex);"); - lines.add(" dataIndex += chunk.length();"); - } - lines.add(" }"); - } else { - // only one chunk so can simplify char array creation - lines.set(firstLineNumber, " private static final String " + prefix + "TRIE_TEXT ="); - lines.add( - " private static final char[] " - + prefix - + "TRIE_DATA = " - + prefix - + "TRIE_TEXT.toCharArray();"); - } - if (hasLongJumps) { - lines.add(""); - lines.add(" private static final int[] " + prefix + "LONG_JUMPS = {"); - buf.setLength(0); - buf.append(" "); - for (int i = 0; i < trie.longJumpCount; i++) { - int jump = trie.longJumps[i]; - if (buf.length() > 90) { - lines.add(buf.toString()); - buf.setLength(0); - buf.append(" "); - } - buf.append(' ').append(String.format("0x%06X", jump)).append(','); - } - lines.add(buf.toString()); - lines.add(" };"); - } - return hasLongJumps; - } - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/FileUtils.java b/features/dd-trace-core/src/main/java/datadog/trace/util/FileUtils.java new file mode 100644 index 0000000000..37b3cf5711 --- /dev/null +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/FileUtils.java @@ -0,0 +1,28 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.util; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; + +public class FileUtils { + + public static byte[] readAllBytes(String path) throws IOException { + try (FileInputStream inputStream = new FileInputStream(path)) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + int bytesRead; + byte[] buffer = new byte[1024]; + while ((bytesRead = inputStream.read(buffer, 0, buffer.length)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + outputStream.flush(); + return outputStream.toByteArray(); + } + } + +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/MethodHandles.java b/features/dd-trace-core/src/main/java/datadog/trace/util/MethodHandles.java deleted file mode 100644 index a7e0a2d94f..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/MethodHandles.java +++ /dev/null @@ -1,176 +0,0 @@ -package datadog.trace.util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.invoke.MethodHandle; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Arrays; - -public class MethodHandles { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.class); - - private final java.lang.invoke.MethodHandles.Lookup lookup = - java.lang.invoke.MethodHandles.lookup(); - private final ClassLoader classLoader; - - public MethodHandles(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - public MethodHandle privateFieldGetter(String className, String fieldName) { - Class clazz = loadClass(className); - return clazz != null ? privateFieldGetter(clazz, fieldName) : null; - } - - public MethodHandle privateFieldGetter(Class clazz, String fieldName) { - return AccessController.doPrivileged( - (PrivilegedAction) - () -> { - try { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - String packageName = clazz.getPackage().getName(); - sm.checkPackageAccess(packageName); - } - - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return lookup.unreflectGetter(field); - - } catch (Throwable t) { - log.debug( - "Could not get private field {} getter from class {}", - fieldName, - clazz.getName(), - t); - return null; - } - }); - } - - public MethodHandle privateFieldSetter(String className, String fieldName) { - Class clazz = loadClass(className); - return clazz != null ? privateFieldSetter(clazz, fieldName) : null; - } - - public MethodHandle privateFieldSetter(Class clazz, String fieldName) { - return AccessController.doPrivileged( - (PrivilegedAction) - () -> { - try { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - String packageName = clazz.getPackage().getName(); - sm.checkPackageAccess(packageName); - } - - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return lookup.unreflectSetter(field); - - } catch (Throwable t) { - log.debug( - "Could not get private field {} setter from class {}", - fieldName, - clazz.getName(), - t); - return null; - } - }); - } - - public MethodHandle constructor(String className, Class... parameterTypes) { - Class clazz = loadClass(className); - return clazz != null ? constructor(clazz, parameterTypes) : null; - } - - public MethodHandle constructor(Class clazz, Class... parameterTypes) { - return AccessController.doPrivileged( - (PrivilegedAction) - () -> { - try { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - String packageName = clazz.getPackage().getName(); - sm.checkPackageAccess(packageName); - } - - Constructor constructor = clazz.getDeclaredConstructor(parameterTypes); - constructor.setAccessible(true); - return lookup.unreflectConstructor(constructor); - - } catch (Throwable t) { - log.debug( - "Could not get constructor accepting {} from class {}", - Arrays.toString(parameterTypes), - clazz.getName(), - t); - return null; - } - }); - } - - public MethodHandle method(String className, String methodName, Class... parameterTypes) { - Class clazz = loadClass(className); - return clazz != null ? method(clazz, methodName, parameterTypes) : null; - } - - public MethodHandle method(Class clazz, String methodName, Class... parameterTypes) { - return AccessController.doPrivileged( - (PrivilegedAction) - () -> { - try { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - String packageName = clazz.getPackage().getName(); - sm.checkPackageAccess(packageName); - } - - Method method = clazz.getDeclaredMethod(methodName, parameterTypes); - method.setAccessible(true); - return lookup.unreflect(method); - - } catch (Throwable t) { - log.debug( - "Could not get method {} accepting {} from class {}", - methodName, - Arrays.toString(parameterTypes), - clazz, - t); - return null; - } - }); - } - - private Class loadClass(String className) { - try { - return classLoader.loadClass(className); - } catch (Throwable t) { - log.debug("Could not load class {}", className, t); - return null; - } - } - - @SuppressWarnings("unchecked") - public T invoke(MethodHandle handle, Object... arguments) { - if (handle == null) { - return null; - } - try { - return (T) handle.invokeWithArguments(arguments); - } catch (Throwable t) { - log.error( - "Error while invoking method handle {} with arguments {}", - handle, - Arrays.toString(arguments), - t); - return null; - } - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessSupervisor.java b/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessSupervisor.java deleted file mode 100644 index 738d1b77a5..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessSupervisor.java +++ /dev/null @@ -1,150 +0,0 @@ -package datadog.trace.util; - -import static datadog.trace.util.AgentThreadFactory.AgentThread.PROCESS_SUPERVISOR; -import static datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; -import static datadog.trace.util.ProcessSupervisor.Health.FAULTED; -import static datadog.trace.util.ProcessSupervisor.Health.HEALTHY; -import static datadog.trace.util.ProcessSupervisor.Health.INTERRUPTED; -import static datadog.trace.util.ProcessSupervisor.Health.READY_TO_START; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Closeable; - -/** Starts an external process and restarts the process if it dies */ -public class ProcessSupervisor implements Closeable { - - public enum Health { - NEVER_CHECKED, - READY_TO_START, - INTERRUPTED, - FAULTED, - HEALTHY - } - - @FunctionalInterface - public interface HealthCheck { - Health run(Health previousHealth) throws InterruptedException; - } - - public static final HealthCheck ALWAYS_READY = health -> READY_TO_START; - - private static final Logger log = LoggerFactory.getLogger(ProcessSupervisor.class); - - private static final long HEALTHY_DELAY_MILLIS = 10_000; - private static final long FAULTED_DELAY_MILLIS = 2_000; - private static final int MAX_FAULTS = 5; - - private final String imageName; - private final ProcessBuilder processBuilder; - private final HealthCheck healthCheck; - private final Thread supervisorThread; - - private long nextCheckMillis = 0; - private Health currentHealth = Health.NEVER_CHECKED; - private Process currentProcess; - private int faults; - - private volatile boolean stopping = false; - - /** - * @param imageName For logging purposes - * @param processBuilder Builder to create the process - */ - public ProcessSupervisor(String imageName, ProcessBuilder processBuilder) { - this(imageName, processBuilder, ALWAYS_READY); - } - - public ProcessSupervisor( - String imageName, ProcessBuilder processBuilder, HealthCheck healthCheck) { - this.imageName = imageName; - this.processBuilder = processBuilder; - this.healthCheck = healthCheck; - this.supervisorThread = AgentThreadFactory.newAgentThread(PROCESS_SUPERVISOR, this::mainLoop); - this.supervisorThread.start(); - } - - private void mainLoop() { - try { - while (!stopping) { - if (currentHealth == FAULTED && ++faults >= MAX_FAULTS) { - log.warn("Failed to start process [{}] after {} attempts", imageName, faults); - break; - } - try { - long delayMillis = nextCheckMillis - System.currentTimeMillis(); - if (delayMillis > 0) { - Thread.sleep(delayMillis); - } - currentHealth = healthCheck.run(currentHealth); - if (currentHealth == READY_TO_START) { - startProcessAndWait(); - } - } catch (InterruptedException e) { - currentHealth = INTERRUPTED; - } catch (Throwable e) { - log.warn("Exception starting process: [{}]", imageName, e); - currentHealth = FAULTED; - } - scheduleNextHealthCheck(); - } - } finally { - stopProcess(); - } - } - - private void scheduleNextHealthCheck() { - long now = System.currentTimeMillis(); - if (currentHealth == HEALTHY) { - nextCheckMillis = now + HEALTHY_DELAY_MILLIS; - } else if (currentHealth == FAULTED) { - nextCheckMillis = now + FAULTED_DELAY_MILLIS; - } else { // interrupted - nextCheckMillis = Long.max(nextCheckMillis, now + 100); - } - } - - private void startProcessAndWait() throws Exception { - if (currentProcess == null) { - log.debug("Starting process: [{}]", imageName); - currentProcess = processBuilder.start(); - currentHealth = HEALTHY; - faults = 0; - } - - // Block until the process exits - int code = currentProcess.waitFor(); - log.debug("Process [{}] has exited with code {}", imageName, code); - currentHealth = code == 0 ? INTERRUPTED : FAULTED; - - // Process is dead, no longer needs to be tracked - currentProcess = null; - } - - private void stopProcess() { - if (currentProcess != null) { - log.debug("Stopping process: [{}]", imageName); - currentProcess.destroy(); - if (currentProcess.isAlive()) { - currentProcess.destroyForcibly(); - } - currentProcess = null; - } - } - - @Override - public void close() { - stopping = true; - supervisorThread.interrupt(); - try { - supervisorThread.join(THREAD_JOIN_TIMOUT_MS); - } catch (Throwable ignored) { - } - } - - // Package reachable for testing - Process getCurrentProcess() { - return currentProcess; - } -} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java b/features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java index 3ee4dd0a0c..6a0271770a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java +++ b/features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java @@ -78,7 +78,7 @@ public static String escapeToJson(String string) { } public static String toEnvVar(String string) { - return string.replace('.', '_').replace('-', '_').toUpperCase(); + return string.replace('.', '_').replace('-', '_').toUpperCase(Locale.US); } /** com.foo.Bar -> com/foo/Bar.class */ @@ -190,7 +190,7 @@ public static String propertyNameToEnvironmentVariableName(final String setting) */ @NonNull public static String systemPropertyNameToEnvironmentVariableName(final String setting) { - return setting.replace('.', '_').replace('-', '_').toUpperCase(); + return setting.replace('.', '_').replace('-', '_').toUpperCase(Locale.US); } /** @@ -241,7 +241,7 @@ public static String trim(final String string) { } private static String hex(char ch) { - return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH); + return Integer.toHexString(ch).toUpperCase(Locale.US); } public static String sha256(String input) throws NoSuchAlgorithmException { diff --git a/features/dd-trace-core/src/test/kotlin/datadog/trace/util/FileUtilsTest.kt b/features/dd-trace-core/src/test/kotlin/datadog/trace/util/FileUtilsTest.kt new file mode 100644 index 0000000000..4e9c0f8a96 --- /dev/null +++ b/features/dd-trace-core/src/test/kotlin/datadog/trace/util/FileUtilsTest.kt @@ -0,0 +1,67 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package datadog.trace.util + +import fr.xgouchet.elmyr.Forge +import fr.xgouchet.elmyr.ForgeConfigurator +import fr.xgouchet.elmyr.annotation.StringForgery +import fr.xgouchet.elmyr.junit5.ForgeConfiguration +import fr.xgouchet.elmyr.junit5.ForgeExtension +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatThrownBy +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.junit.jupiter.api.extension.Extensions +import org.junit.jupiter.api.io.TempDir +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.junit.jupiter.MockitoSettings +import org.mockito.quality.Strictness +import java.io.File +import java.io.IOException + +@Extensions( + ExtendWith(MockitoExtension::class), + ExtendWith(ForgeExtension::class) +) +@MockitoSettings(strictness = Strictness.LENIENT) +@ForgeConfiguration(value = ForgeConfigurator.NoOp::class) +internal class FileUtilsTest { + + @TempDir + lateinit var tempDir: File + + @StringForgery + lateinit var fakeFileName: String + + lateinit var fakeFile: File + + @StringForgery + lateinit var fakeFileContent: String + + @BeforeEach + fun `set up`() { + fakeFile = File(tempDir, fakeFileName) + fakeFile.writeText(fakeFileContent) + } + + @Test + fun `M read the file as bytes W readAllBytes`() { + // When + val result = FileUtils.readAllBytes(fakeFile.absolutePath) + + // Then + assertThat(result).isEqualTo(fakeFileContent.toByteArray()) + } + + @Test + fun `M throw IOException W readAllBytes { file does not exist }`(forge: Forge) { + // When + assertThatThrownBy { FileUtils.readAllBytes(forge.anAlphabeticalString()) } + .isInstanceOf(IOException::class.java) + } +} From ee358a081a21d066078dc520b1a046216ac1b88a Mon Sep 17 00:00:00 2001 From: Marius Constantin Date: Thu, 29 Feb 2024 14:02:48 +0100 Subject: [PATCH 03/55] Rename datadog.trace to com.datadog.trace package in dd-trace-core --- features/dd-trace-core/build.gradle.kts | 2 +- .../trace/advice/ActiveRequestContext.java | 2 +- .../trace/advice/RequiresRequestContext.java | 6 +- .../{ => com}/datadog/trace/api/Config.java | 668 +++++++++--------- .../datadog/trace/api/ConfigCollector.java | 2 +- .../datadog/trace/api/ConfigDefaults.java | 8 +- .../datadog/trace/api/ConfigOrigin.java | 2 +- .../datadog/trace/api/ConfigSetting.java | 2 +- .../trace/api/CorrelationIdentifier.java | 2 +- .../datadog/trace/api/DD128bTraceId.java | 4 +- .../datadog/trace/api/DD64bTraceId.java | 4 +- .../{ => com}/datadog/trace/api/DDSpanId.java | 4 +- .../datadog/trace/api/DDSpanTypes.java | 2 +- .../{ => com}/datadog/trace/api/DDTags.java | 2 +- .../datadog/trace/api/DDTraceApiInfo.java | 2 +- .../datadog/trace/api/DDTraceId.java | 4 +- .../datadog/trace/api/DisableTestTrace.java | 2 +- .../datadog/trace/api/DynamicConfig.java | 30 +- .../trace/api/EndpointCheckpointer.java | 4 +- .../trace/api/EndpointCheckpointerHolder.java | 4 +- .../datadog/trace/api/EndpointTracker.java | 4 +- .../datadog/trace/api/EventTracker.java | 6 +- .../datadog/trace/api/Functions.java | 4 +- .../datadog/trace/api/GlobalTracer.java | 6 +- .../trace/api/IdGenerationStrategy.java | 2 +- .../datadog/trace/api/InstrumenterConfig.java | 118 ++-- .../trace/api/MethodFilterConfigParser.java | 2 +- .../datadog/trace/api/NoOpStatsDClient.java | 2 +- .../{ => com}/datadog/trace/api/Pair.java | 2 +- .../{ => com}/datadog/trace/api/Platform.java | 2 +- .../datadog/trace/api/ProductActivation.java | 2 +- .../datadog/trace/api/PropagationStyle.java | 2 +- .../trace/api/ResolverCacheConfig.java | 2 +- .../{ => com}/datadog/trace/api/Stateful.java | 2 +- .../datadog/trace/api/StatsDClient.java | 2 +- .../trace/api/StatsDClientManager.java | 2 +- .../{ => com}/datadog/trace/api/Trace.java | 2 +- .../datadog/trace/api/TraceConfig.java | 6 +- .../trace/api/TracePropagationStyle.java | 2 +- .../{ => com}/datadog/trace/api/Tracer.java | 4 +- .../trace/api/UserEventTrackingMode.java | 2 +- .../datadog/trace/api/WellKnownTags.java | 4 +- .../datadog/trace/api/WithGlobalTracer.java | 4 +- .../datadog/trace/api/cache/CHMCache.java | 2 +- .../datadog/trace/api/cache/DDCache.java | 2 +- .../datadog/trace/api/cache/DDCaches.java | 2 +- .../trace/api/cache/DDPartialKeyCache.java | 2 +- .../trace/api/cache/FixedSizeCache.java | 4 +- .../api/cache/FixedSizePartialKeyCache.java | 6 +- .../api/cache/FixedSizeWeakKeyCache.java | 6 +- .../api/cache/FixedSizeWeightedCache.java | 6 +- .../trace/api/cache/RadixTreeCache.java | 4 +- .../trace/api/civisibility/CIConstants.java | 2 +- .../trace/api/civisibility/DDTest.java | 2 +- .../trace/api/civisibility/DDTestModule.java | 2 +- .../trace/api/civisibility/DDTestSession.java | 2 +- .../trace/api/civisibility/DDTestSuite.java | 2 +- .../civisibility/InstrumentationBridge.java | 6 +- .../civisibility/config/Configurations.java | 2 +- .../config/ModuleExecutionSettings.java | 2 +- .../civisibility/config/TestIdentifier.java | 2 +- .../civisibility/coverage/CoverageBridge.java | 10 +- .../coverage/CoverageDataSupplier.java | 2 +- .../coverage/CoverageProbeStore.java | 2 +- .../api/civisibility/coverage/TestReport.java | 2 +- .../coverage/TestReportFileEntry.java | 2 +- .../coverage/TestReportHolder.java | 2 +- .../events/BuildEventsHandler.java | 4 +- .../events/TestEventsHandler.java | 6 +- .../api/civisibility/noop/NoOpDDTest.java | 4 +- .../civisibility/noop/NoOpDDTestModule.java | 6 +- .../civisibility/noop/NoOpDDTestSession.java | 6 +- .../civisibility/noop/NoOpDDTestSuite.java | 6 +- .../civisibility/retry/TestRetryPolicy.java | 2 +- .../trace/api/config/AppSecConfig.java | 2 +- .../trace/api/config/CiVisibilityConfig.java | 2 +- .../trace/api/config/CrashTrackingConfig.java | 2 +- .../datadog/trace/api/config/CwsConfig.java | 2 +- .../trace/api/config/DebuggerConfig.java | 2 +- .../trace/api/config/GeneralConfig.java | 2 +- .../datadog/trace/api/config/IastConfig.java | 2 +- .../trace/api/config/JmxFetchConfig.java | 2 +- .../trace/api/config/ProfilingConfig.java | 2 +- .../trace/api/config/RemoteConfigConfig.java | 2 +- .../config/TraceInstrumentationConfig.java | 2 +- .../trace/api/config/TracerConfig.java | 2 +- .../datadog/trace/api/config/UsmConfig.java | 2 +- .../trace/api/env/CapturedEnvironment.java | 4 +- .../experimental/DataStreamsCheckpointer.java | 8 +- .../DataStreamsContextCarrier.java | 2 +- .../datadog/trace/api/flare/TracerFlare.java | 2 +- .../trace/api/function/TriConsumer.java | 2 +- .../trace/api/function/TriFunction.java | 2 +- .../api/gateway/BlockResponseFunction.java | 6 +- .../trace/api/gateway/CallbackProvider.java | 2 +- .../datadog/trace/api/gateway/EventType.java | 2 +- .../datadog/trace/api/gateway/Events.java | 10 +- .../datadog/trace/api/gateway/Flow.java | 4 +- .../datadog/trace/api/gateway/IGSpanInfo.java | 6 +- .../api/gateway/InstrumentationGateway.java | 42 +- .../trace/api/gateway/RequestContext.java | 4 +- .../trace/api/gateway/RequestContextSlot.java | 2 +- .../trace/api/gateway/Subscription.java | 2 +- .../api/gateway/SubscriptionService.java | 2 +- .../trace/api/http/StoredBodyFactories.java | 16 +- .../trace/api/http/StoredBodySupplier.java | 2 +- .../trace/api/http/StoredByteBody.java | 6 +- .../trace/api/http/StoredCharBody.java | 10 +- .../datadog/trace/api/iast/IastCallSites.java | 4 +- .../datadog/trace/api/iast/IastContext.java | 10 +- .../trace/api/iast/IastDetectionMode.java | 26 +- .../trace/api/iast/IastEnabledChecks.java | 4 +- .../datadog/trace/api/iast/IastModule.java | 2 +- .../trace/api/iast/InstrumentationBridge.java | 50 +- .../datadog/trace/api/iast/Propagation.java | 2 +- .../datadog/trace/api/iast/Sink.java | 2 +- .../datadog/trace/api/iast/Source.java | 2 +- .../datadog/trace/api/iast/SourceTypes.java | 2 +- .../datadog/trace/api/iast/Taintable.java | 2 +- .../trace/api/iast/VulnerabilityMarks.java | 2 +- .../trace/api/iast/VulnerabilityTypes.java | 2 +- .../api/iast/propagation/CodecModule.java | 4 +- .../iast/propagation/PropagationModule.java | 8 +- .../api/iast/propagation/StringModule.java | 4 +- .../api/iast/sink/ApplicationModule.java | 4 +- .../api/iast/sink/CommandInjectionModule.java | 4 +- .../api/iast/sink/HeaderInjectionModule.java | 4 +- .../iast/sink/HstsMissingHeaderModule.java | 2 +- .../trace/api/iast/sink/HttpCookieModule.java | 6 +- .../api/iast/sink/HttpRequestEndModule.java | 6 +- .../iast/sink/HttpResponseHeaderModule.java | 6 +- .../api/iast/sink/InsecureCookieModule.java | 2 +- .../api/iast/sink/LdapInjectionModule.java | 4 +- .../api/iast/sink/NoHttpOnlyCookieModule.java | 2 +- .../api/iast/sink/NoSameSiteCookieModule.java | 2 +- .../api/iast/sink/PathTraversalModule.java | 4 +- .../api/iast/sink/SqlInjectionModule.java | 4 +- .../trace/api/iast/sink/SsrfModule.java | 4 +- .../api/iast/sink/StacktraceLeakModule.java | 4 +- .../sink/TrustBoundaryViolationModule.java | 4 +- .../iast/sink/UnvalidatedRedirectModule.java | 4 +- .../trace/api/iast/sink/WeakCipherModule.java | 4 +- .../trace/api/iast/sink/WeakHashModule.java | 4 +- .../api/iast/sink/WeakRandomnessModule.java | 4 +- .../api/iast/sink/XContentTypeModule.java | 2 +- .../api/iast/sink/XPathInjectionModule.java | 4 +- .../trace/api/iast/sink/XssModule.java | 4 +- .../trace/api/iast/telemetry/IastMetric.java | 14 +- .../iast/telemetry/IastMetricCollector.java | 18 +- .../trace/api/iast/telemetry/Verbosity.java | 2 +- .../datadog/trace/api/iast/util/Cookie.java | 2 +- .../datadog/trace/api/intake/TrackType.java | 2 +- .../interceptor/AbstractTraceInterceptor.java | 2 +- .../trace/api/interceptor/MutableSpan.java | 4 +- .../api/interceptor/TraceInterceptor.java | 2 +- .../trace/api/internal/InternalTracer.java | 6 +- .../trace/api/internal/TraceSegment.java | 2 +- .../api/internal/util/LongStringUtils.java | 2 +- .../trace/api/metrics/CoreCounter.java | 2 +- .../trace/api/metrics/SpanMetricRegistry.java | 4 +- .../api/metrics/SpanMetricRegistryImpl.java | 2 +- .../trace/api/metrics/SpanMetrics.java | 2 +- .../trace/api/metrics/SpanMetricsImpl.java | 2 +- .../trace/api/naming/NamingSchema.java | 2 +- .../datadog/trace/api/naming/SpanNaming.java | 8 +- .../trace/api/naming/v0/CacheNamingV0.java | 4 +- .../trace/api/naming/v0/ClientNamingV0.java | 4 +- .../trace/api/naming/v0/CloudNamingV0.java | 4 +- .../trace/api/naming/v0/DatabaseNamingV0.java | 4 +- .../api/naming/v0/MessagingNamingV0.java | 6 +- .../trace/api/naming/v0/NamingSchemaV0.java | 8 +- .../api/naming/v0/PeerServiceNamingV0.java | 4 +- .../trace/api/naming/v0/ServerNamingV0.java | 4 +- .../trace/api/naming/v1/CacheNamingV1.java | 4 +- .../trace/api/naming/v1/ClientNamingV1.java | 4 +- .../trace/api/naming/v1/CloudNamingV1.java | 8 +- .../trace/api/naming/v1/DatabaseNamingV1.java | 4 +- .../api/naming/v1/MessagingNamingV1.java | 4 +- .../trace/api/naming/v1/NamingSchemaV1.java | 6 +- .../api/naming/v1/PeerServiceNamingV1.java | 10 +- .../trace/api/naming/v1/ServerNamingV1.java | 4 +- .../trace/api/normalize/AntPathMatcher.java | 2 +- .../AntPatternHttpPathNormalizer.java | 8 +- .../api/normalize/HttpPathNormalizer.java | 2 +- .../api/normalize/HttpResourceNames.java | 16 +- .../trace/api/normalize/SQLNormalizer.java | 4 +- .../normalize/SimpleHttpPathNormalizer.java | 4 +- .../trace/api/profiling/ObservableType.java | 3 + .../trace/api/profiling/Profiling.java | 8 +- .../trace/api/profiling/ProfilingContext.java | 2 +- .../profiling/ProfilingContextAttribute.java | 2 +- .../trace/api/profiling/ProfilingScope.java | 2 +- .../api/profiling/ProfilingSnapshot.java | 2 +- .../trace/api/profiling/QueueTiming.java | 2 +- .../trace/api/profiling/RecordingData.java | 2 +- .../api/profiling/RecordingDataListener.java | 2 +- .../api/profiling/RecordingInputStream.java | 2 +- .../trace/api/profiling/RecordingType.java | 2 +- .../datadog/trace/api/profiling/Timer.java | 2 +- .../datadog/trace/api/profiling/Timing.java | 2 +- .../TransientProfilingContextHolder.java | 2 +- .../trace/api/profiling/package-info.java | 2 +- .../trace/api/sampling/PrioritySampling.java | 2 +- .../datadog/trace/api/sampling/Sampler.java | 2 +- .../trace/api/sampling/SamplingMechanism.java | 10 +- .../trace/api/sampling/SamplingRule.java | 2 +- .../scopemanager/ExtendedScopeListener.java | 6 +- .../trace/api/scopemanager/ScopeListener.java | 2 +- .../api/telemetry/CoreMetricCollector.java | 8 +- .../api/telemetry/IntegrationsCollector.java | 2 +- .../trace/api/telemetry/LogCollector.java | 2 +- .../trace/api/telemetry/MetricCollector.java | 4 +- .../api/telemetry/WafMetricCollector.java | 2 +- .../api/time/ControllableTimeSource.java | 2 +- .../trace/api/time/SystemTimeSource.java | 2 +- .../datadog/trace/api/time/TimeSource.java | 2 +- .../trace/appsec/api/blocking/Blocking.java | 2 +- .../api/blocking/BlockingContentType.java | 2 +- .../appsec/api/blocking/BlockingDetails.java | 2 +- .../api/blocking/BlockingException.java | 2 +- .../appsec/api/blocking/BlockingService.java | 2 +- .../trace/bootstrap/ActiveSubsystems.java | 2 +- .../config/provider/AgentArgsInjector.java | 4 +- .../config/provider/AgentArgsParser.java | 2 +- .../CapturedEnvironmentConfigSource.java | 6 +- .../config/provider/ConfigConverter.java | 4 +- .../config/provider/ConfigProvider.java | 8 +- .../provider/EnvironmentConfigSource.java | 6 +- .../provider/PropertiesConfigSource.java | 6 +- .../SystemPropertiesConfigSource.java | 6 +- .../api/AgentDataStreamsMonitoring.java | 4 +- .../instrumentation/api/AgentHistogram.java | 2 +- .../instrumentation/api/AgentPropagation.java | 4 +- .../instrumentation/api/AgentScope.java | 4 +- .../api/AgentScopeManager.java | 2 +- .../instrumentation/api/AgentSpan.java | 16 +- .../instrumentation/api/AgentSpanLink.java | 4 +- .../instrumentation/api/AgentTrace.java | 2 +- .../instrumentation/api/AgentTracer.java | 50 +- .../api/AttachableWrapper.java | 2 +- .../instrumentation/api/Backlog.java | 2 +- .../instrumentation/api/ErrorPriorities.java | 2 +- .../instrumentation/api/InboxItem.java | 3 + .../api/InstrumentationTags.java | 2 +- .../api/InternalSpanTypes.java | 4 +- .../instrumentation/api/PathwayContext.java | 2 +- .../instrumentation/api/ProfilerContext.java | 2 +- .../api/ProfilingContextIntegration.java | 10 +- .../api/ResourceNamePriorities.java | 2 +- .../instrumentation/api/SamplerConstants.java | 2 +- .../instrumentation/api/ScopeSource.java | 2 +- .../instrumentation/api/ScopeState.java | 2 +- .../instrumentation/api/ScopeStateAware.java | 2 +- .../instrumentation/api/SpanLink.java | 6 +- .../api/SpanLinkAttributes.java | 2 +- .../instrumentation/api/StatsPoint.java | 2 +- .../instrumentation/api/TagContext.java | 14 +- .../bootstrap/instrumentation/api/Tags.java | 2 +- .../instrumentation/api/TaskWrapper.java | 2 +- .../instrumentation/api/URIDataAdapter.java | 2 +- .../api/URIDataAdapterBase.java | 2 +- .../api/URIDefaultDataAdapter.java | 2 +- .../api/URIRawDataAdapter.java | 2 +- .../instrumentation/api/URIUtils.java | 2 +- .../instrumentation/api/UTF8BytesString.java | 2 +- .../api/UnparseableURIDataAdapter.java | 2 +- .../instrumentation/api/WriterConstants.java | 2 +- .../CiVisibilityApmProtocolInterceptor.java | 10 +- .../CiVisibilityTraceInterceptor.java | 18 +- .../trace/common/metrics/AggregateMetric.java | 6 +- .../datadog/trace/common/metrics/Batch.java | 2 +- .../trace/common/metrics/EventListener.java | 2 +- .../trace/common/metrics/InboxItem.java | 4 + .../trace/common/metrics/MetricKey.java | 6 +- .../trace/common/metrics/MetricWriter.java | 2 +- .../common/metrics/MetricsAggregator.java | 4 +- .../common/metrics/NoOpMetricsAggregator.java | 4 +- .../datadog/trace/common/metrics/Sink.java | 8 + .../trace/common/sampling/AllSampler.java | 4 +- .../common/sampling/DeterministicSampler.java | 4 +- .../common/sampling/ForcePrioritySampler.java | 4 +- .../common/sampling/PrioritySampler.java | 4 +- .../common/sampling/PrioritySampling.java | 4 +- .../sampling/RateByServiceTraceSampler.java | 16 +- .../trace/common/sampling/RateSampler.java | 2 +- .../sampling/RuleBasedTraceSampler.java | 22 +- .../trace/common/sampling/Sampler.java | 18 +- .../trace/common/sampling/SamplingRule.java | 12 +- .../common/sampling/SingleSpanSampler.java | 12 +- .../common/sampling/SpanSamplingRules.java | 4 +- .../common/sampling/TraceSamplingRules.java | 4 +- .../writer/CompositePayloadDispatcher.java | 4 +- .../common/writer/DDSpanJsonAdapter.java | 8 +- .../trace/common/writer/ListWriter.java | 8 +- .../trace/common/writer/LoggingWriter.java | 4 +- .../datadog/trace/common/writer/Payload.java | 2 +- .../common/writer/PayloadDispatcher.java | 4 +- .../trace/common/writer/PrintingWriter.java | 4 +- .../trace/common/writer/RemoteApi.java | 4 +- .../trace/common/writer/RemoteMapper.java | 14 +- .../common/writer/RemoteMapperDiscovery.java | 2 +- .../common/writer/RemoteResponseListener.java | 2 +- .../common/writer/SpanSamplingWorker.java | 16 +- .../common/writer/TraceProcessingWorker.java | 26 +- .../common/writer/TraceStructureWriter.java | 10 +- .../datadog/trace/common/writer/Writer.java | 4 +- .../common/writer/ddagent/FlushEvent.java | 2 +- .../common/writer/ddagent/Prioritization.java | 10 +- .../ddagent/PrioritizationStrategy.java | 4 +- .../common/writer/ddagent/TraceMapper.java | 10 +- .../datadog/trace/context/TraceScope.java | 2 +- .../datadog/trace/core/CoreSpan.java | 4 +- .../datadog/trace/core/CoreTracer.java | 134 ++-- .../{ => com}/datadog/trace/core/DDSpan.java | 48 +- .../datadog/trace/core/DDSpanContext.java | 60 +- .../datadog/trace/core/DDSpanLink.java | 18 +- .../datadog/trace/core/DDTraceCoreInfo.java | 2 +- .../trace/core/LongRunningTracesTracker.java | 10 +- .../datadog/trace/core/Metadata.java | 6 +- .../datadog/trace/core/MetadataConsumer.java | 2 +- .../datadog/trace/core/PendingTrace.java | 24 +- .../trace/core/PendingTraceBuffer.java | 14 +- .../datadog/trace/core/StatusLogger.java | 14 +- .../DataStreamContextExtractor.java | 16 +- .../DataStreamContextInjector.java | 12 +- .../DataStreamsContextCarrierAdapter.java | 8 +- .../datastreams/DataStreamsMonitoring.java | 14 +- .../datastreams/DatastreamsPayloadWriter.java | 2 +- .../datastreams/DefaultPathwayContext.java | 16 +- .../datastreams/NoOpDataStreamMonitoring.java | 16 +- .../trace/core/datastreams/SchemaSampler.java | 2 +- .../trace/core/datastreams/StatsBucket.java | 6 +- .../trace/core/datastreams/StatsGroup.java | 6 +- .../trace/core/datastreams/TagsProcessor.java | 6 +- .../trace/core/histogram/Histogram.java | 4 +- .../trace/core/histogram/Histograms.java | 2 +- .../trace/core/monitor/HealthMetrics.java | 6 +- .../trace/core/monitor/MonitoringImpl.java | 14 +- .../trace/core/monitor/StatsDCounter.java | 8 +- .../core/monitor/ThreadLocalRecording.java | 4 +- .../datadog/trace/core/monitor/Timer.java | 12 +- .../datadog/trace/core/monitor/Utils.java | 2 +- .../trace/core/propagation/B3HttpCodec.java | 30 +- .../trace/core/propagation/B3TraceId.java | 6 +- .../core/propagation/ContextInterpreter.java | 60 +- .../core/propagation/CorePropagation.java | 12 +- .../core/propagation/DatadogHttpCodec.java | 32 +- .../core/propagation/ExtractedContext.java | 12 +- .../core/propagation/HaystackHttpCodec.java | 24 +- .../trace/core/propagation/HttpCodec.java | 28 +- .../core/propagation/NoOpCorePropagation.java | 12 +- .../trace/core/propagation/NoneCodec.java | 8 +- .../core/propagation/PropagationTags.java | 8 +- .../core/propagation/TagContextExtractor.java | 8 +- .../trace/core/propagation/W3CHttpCodec.java | 38 +- .../trace/core/propagation/XRayHttpCodec.java | 30 +- .../propagation/ptags/DatadogPTagsCodec.java | 10 +- .../core/propagation/ptags/PTagsCodec.java | 10 +- .../core/propagation/ptags/PTagsFactory.java | 24 +- .../core/propagation/ptags/TagElement.java | 2 +- .../trace/core/propagation/ptags/TagKey.java | 6 +- .../core/propagation/ptags/TagValue.java | 6 +- .../core/propagation/ptags/W3CPTagsCodec.java | 14 +- .../scopemanager/AbstractContinuation.java | 8 +- .../scopemanager/ConcurrentContinuation.java | 6 +- .../core/scopemanager/ContinuableScope.java | 18 +- .../scopemanager/ContinuableScopeManager.java | 36 +- .../core/scopemanager/ContinuingScope.java | 6 +- .../trace/core/scopemanager/ScopeStack.java | 6 +- .../core/scopemanager/SingleContinuation.java | 6 +- .../trace/core/taginterceptor/RuleFlags.java | 4 +- .../core/taginterceptor/TagInterceptor.java | 62 +- .../core/tagprocessor/BaseServiceAdder.java | 8 +- .../tagprocessor/PeerServiceCalculator.java | 12 +- .../core/tagprocessor/PostProcessorChain.java | 4 +- .../core/tagprocessor/QueryObfuscator.java | 8 +- .../core/tagprocessor/TagsPostProcessor.java | 4 +- .../TagsPostProcessorFactory.java | 4 +- .../datadog/trace/core/util/GlobPattern.java | 2 +- .../datadog/trace/core/util/LRUCache.java | 2 +- .../datadog/trace/core/util/Matcher.java | 2 +- .../datadog/trace/core/util/Matchers.java | 2 +- .../core/util/NoneSystemAccessProvider.java | 2 +- .../trace/core/util/SimpleRateLimiter.java | 6 +- .../datadog/trace/core/util/SystemAccess.java | 6 +- .../trace/core/util/SystemAccessProvider.java | 2 +- .../datadog/trace/core/util/TagsMatcher.java | 4 +- .../datadog/trace/ddagent/DroppingPolicy.java | 2 +- .../ReadFromInputStreamJsonAdapter.java | 2 +- .../trace/logging/GlobalLogLevelSwitcher.java | 2 +- .../datadog/trace/logging/LogLevel.java | 2 +- .../trace/logging/LogLevelSwitcher.java | 2 +- .../logging/LoggingSettingsDescription.java | 2 +- .../datadog/trace/monitor/Counter.java | 2 +- .../datadog/trace/monitor/Monitoring.java | 6 +- .../datadog/trace/monitor/NoOpCounter.java | 2 +- .../datadog/trace/monitor/NoOpRecording.java | 2 +- .../datadog/trace/monitor/Recording.java | 2 +- .../datadog/trace/relocate/api/IOLogger.java | 2 +- .../trace/relocate/api/RatelimitedLogger.java | 6 +- .../serialization/ByteBufferConsumer.java | 2 +- .../trace/serialization/EncodingCache.java | 2 +- .../trace/serialization/FlushingBuffer.java | 6 +- .../trace/serialization/GrowableBuffer.java | 4 +- .../datadog/trace/serialization/Mapper.java | 4 +- .../trace/serialization/MessageFormatter.java | 2 +- .../trace/serialization/StreamingBuffer.java | 2 +- .../trace/serialization/ValueWriter.java | 4 +- .../datadog/trace/serialization/Writable.java | 6 +- .../serialization/WritableFormatter.java | 2 +- .../trace/util/AgentProxySelector.java | 4 +- .../trace/util/AgentTaskScheduler.java | 10 +- .../trace/util/AgentThreadFactory.java | 2 +- .../datadog/trace/util/CollectionUtils.java | 2 +- .../datadog/trace/util/FNV64Hash.java | 2 +- .../datadog/trace/util/FileUtils.java | 2 +- .../datadog/trace/util/PidHelper.java | 6 +- .../datadog/trace/util/ProcessUtils.java | 6 +- .../{ => com}/datadog/trace/util/Strings.java | 2 +- .../datadog/trace/util/TagsHelper.java | 2 +- .../datadog/trace/util/TraceUtils.java | 4 +- .../util/stacktrace/AbstractStackWalker.java | 4 +- .../util/stacktrace/DefaultStackWalker.java | 2 +- .../trace/util/stacktrace/StackUtils.java | 2 +- .../trace/util/stacktrace/StackWalker.java | 2 +- .../util/stacktrace/StackWalkerFactory.java | 6 +- .../FatalAgentMisconfigurationError.java | 2 +- .../trace/api/profiling/ObservableType.java | 3 - .../instrumentation/api/InboxItem.java | 3 - .../trace/common/metrics/InboxItem.java | 4 - .../datadog/trace/common/metrics/Sink.java | 8 - .../datadog/trace/util/FileUtilsTest.kt | 2 +- 432 files changed, 1744 insertions(+), 1744 deletions(-) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/advice/ActiveRequestContext.java (88%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/advice/RequiresRequestContext.java (76%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/Config.java (84%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/ConfigCollector.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/ConfigDefaults.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/ConfigOrigin.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/ConfigSetting.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/CorrelationIdentifier.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/DD128bTraceId.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/DD64bTraceId.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/DDSpanId.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/DDSpanTypes.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/DDTags.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/DDTraceApiInfo.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/DDTraceId.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/DisableTestTrace.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/DynamicConfig.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/EndpointCheckpointer.java (84%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/EndpointCheckpointerHolder.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/EndpointTracker.java (76%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/EventTracker.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/Functions.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/GlobalTracer.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/IdGenerationStrategy.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/InstrumenterConfig.java (74%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/MethodFilterConfigParser.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/NoOpStatsDClient.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/Pair.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/Platform.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/ProductActivation.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/PropagationStyle.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/ResolverCacheConfig.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/Stateful.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/StatsDClient.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/StatsDClientManager.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/Trace.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/TraceConfig.java (84%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/TracePropagationStyle.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/Tracer.java (87%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/UserEventTrackingMode.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/WellKnownTags.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/WithGlobalTracer.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/cache/CHMCache.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/cache/DDCache.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/cache/DDCaches.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/cache/DDPartialKeyCache.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/cache/FixedSizeCache.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/cache/FixedSizePartialKeyCache.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/cache/FixedSizeWeakKeyCache.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/cache/FixedSizeWeightedCache.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/cache/RadixTreeCache.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/CIConstants.java (73%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/DDTest.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/DDTestModule.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/DDTestSession.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/DDTestSuite.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/InstrumentationBridge.java (84%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/config/Configurations.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/config/TestIdentifier.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/coverage/CoverageBridge.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java (52%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java (87%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/coverage/TestReport.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/coverage/TestReportHolder.java (68%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/events/BuildEventsHandler.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/events/TestEventsHandler.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/noop/NoOpDDTest.java (80%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java (79%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java (77%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java (79%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/civisibility/retry/TestRetryPolicy.java (67%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/AppSecConfig.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/CiVisibilityConfig.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/CrashTrackingConfig.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/CwsConfig.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/DebuggerConfig.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/GeneralConfig.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/IastConfig.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/JmxFetchConfig.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/ProfilingConfig.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/RemoteConfigConfig.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/TraceInstrumentationConfig.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/TracerConfig.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/config/UsmConfig.java (82%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/env/CapturedEnvironment.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/experimental/DataStreamsCheckpointer.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/experimental/DataStreamsContextCarrier.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/flare/TracerFlare.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/function/TriConsumer.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/function/TriFunction.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/BlockResponseFunction.java (74%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/CallbackProvider.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/EventType.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/Events.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/Flow.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/IGSpanInfo.java (69%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/InstrumentationGateway.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/RequestContext.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/RequestContextSlot.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/Subscription.java (88%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/gateway/SubscriptionService.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/http/StoredBodyFactories.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/http/StoredBodySupplier.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/http/StoredByteBody.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/http/StoredCharBody.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/IastCallSites.java (72%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/IastContext.java (77%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/IastDetectionMode.java (70%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/IastEnabledChecks.java (88%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/IastModule.java (88%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/InstrumentationBridge.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/Propagation.java (88%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/Sink.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/Source.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/SourceTypes.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/Taintable.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/VulnerabilityMarks.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/VulnerabilityTypes.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/propagation/CodecModule.java (85%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/propagation/PropagationModule.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/propagation/StringModule.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/ApplicationModule.java (62%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/CommandInjectionModule.java (80%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/HeaderInjectionModule.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/HttpCookieModule.java (55%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/HttpRequestEndModule.java (87%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java (59%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/InsecureCookieModule.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/LdapInjectionModule.java (74%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/PathTraversalModule.java (84%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/SqlInjectionModule.java (74%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/SsrfModule.java (72%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/StacktraceLeakModule.java (72%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java (65%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java (81%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/WeakCipherModule.java (63%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/WeakHashModule.java (63%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/WeakRandomnessModule.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/XContentTypeModule.java (62%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/XPathInjectionModule.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/sink/XssModule.java (82%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/telemetry/IastMetric.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/telemetry/IastMetricCollector.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/telemetry/Verbosity.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/iast/util/Cookie.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/intake/TrackType.java (62%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/interceptor/AbstractTraceInterceptor.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/interceptor/MutableSpan.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/interceptor/TraceInterceptor.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/internal/InternalTracer.java (82%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/internal/TraceSegment.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/internal/util/LongStringUtils.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/metrics/CoreCounter.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/metrics/SpanMetricRegistry.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/metrics/SpanMetricRegistryImpl.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/metrics/SpanMetrics.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/metrics/SpanMetricsImpl.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/NamingSchema.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/SpanNaming.java (85%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v0/CacheNamingV0.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v0/ClientNamingV0.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v0/CloudNamingV0.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v0/DatabaseNamingV0.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v0/MessagingNamingV0.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v0/NamingSchemaV0.java (88%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v0/PeerServiceNamingV0.java (80%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v0/ServerNamingV0.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v1/CacheNamingV1.java (77%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v1/ClientNamingV1.java (87%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v1/CloudNamingV1.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v1/DatabaseNamingV1.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v1/MessagingNamingV1.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v1/NamingSchemaV1.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v1/PeerServiceNamingV1.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/naming/v1/ServerNamingV1.java (80%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/normalize/AntPathMatcher.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/normalize/HttpPathNormalizer.java (82%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/normalize/HttpResourceNames.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/normalize/SQLNormalizer.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java (97%) create mode 100644 features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ObservableType.java rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/Profiling.java (86%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/ProfilingContext.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/ProfilingContextAttribute.java (80%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/ProfilingScope.java (77%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/ProfilingSnapshot.java (73%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/QueueTiming.java (74%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/RecordingData.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/RecordingDataListener.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/RecordingInputStream.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/RecordingType.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/Timer.java (87%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/Timing.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/TransientProfilingContextHolder.java (56%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/profiling/package-info.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/sampling/PrioritySampling.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/sampling/Sampler.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/sampling/SamplingMechanism.java (84%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/sampling/SamplingRule.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/scopemanager/ExtendedScopeListener.java (67%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/scopemanager/ScopeListener.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/telemetry/CoreMetricCollector.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/telemetry/IntegrationsCollector.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/telemetry/LogCollector.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/telemetry/MetricCollector.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/telemetry/WafMetricCollector.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/time/ControllableTimeSource.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/time/SystemTimeSource.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/api/time/TimeSource.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/appsec/api/blocking/Blocking.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/appsec/api/blocking/BlockingContentType.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/appsec/api/blocking/BlockingDetails.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/appsec/api/blocking/BlockingException.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/appsec/api/blocking/BlockingService.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/ActiveSubsystems.java (69%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/config/provider/AgentArgsParser.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java (76%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/config/provider/ConfigConverter.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/config/provider/ConfigProvider.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java (60%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java (62%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java (85%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/AgentScope.java (82%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java (74%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java (87%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/Backlog.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java (76%) create mode 100644 features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/InboxItem.java rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java (82%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java (73%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java (79%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/ScopeState.java (58%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java (54%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/SpanLink.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/TagContext.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/Tags.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java (86%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/URIUtils.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java (84%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java (80%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/metrics/AggregateMetric.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/metrics/Batch.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/metrics/EventListener.java (79%) create mode 100644 features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/InboxItem.java rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/metrics/MetricKey.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/metrics/MetricWriter.java (82%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/metrics/MetricsAggregator.java (77%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/metrics/NoOpMetricsAggregator.java (94%) create mode 100644 features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/Sink.java rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/AllSampler.java (76%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/DeterministicSampler.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/ForcePrioritySampler.java (88%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/PrioritySampler.java (54%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/PrioritySampling.java (84%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/RateByServiceTraceSampler.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/RateSampler.java (63%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/RuleBasedTraceSampler.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/Sampler.java (87%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/SamplingRule.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/SingleSpanSampler.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/SpanSamplingRules.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/sampling/TraceSamplingRules.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/CompositePayloadDispatcher.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/DDSpanJsonAdapter.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/ListWriter.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/LoggingWriter.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/Payload.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/PayloadDispatcher.java (76%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/PrintingWriter.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/RemoteApi.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/RemoteMapper.java (80%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/RemoteMapperDiscovery.java (69%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/RemoteResponseListener.java (84%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/SpanSamplingWorker.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/TraceProcessingWorker.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/TraceStructureWriter.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/Writer.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/ddagent/FlushEvent.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/ddagent/Prioritization.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java (81%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/common/writer/ddagent/TraceMapper.java (60%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/context/TraceScope.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/CoreSpan.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/CoreTracer.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/DDSpan.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/DDSpanContext.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/DDSpanLink.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/DDTraceCoreInfo.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/LongRunningTracesTracker.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/Metadata.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/MetadataConsumer.java (86%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/PendingTrace.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/PendingTraceBuffer.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/StatusLogger.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/DataStreamContextExtractor.java (82%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/DataStreamContextInjector.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java (74%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/DataStreamsMonitoring.java (67%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java (74%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/DefaultPathwayContext.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java (74%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/SchemaSampler.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/StatsBucket.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/StatsGroup.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/datastreams/TagsProcessor.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/histogram/Histogram.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/histogram/Histograms.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/monitor/HealthMetrics.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/monitor/MonitoringImpl.java (82%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/monitor/StatsDCounter.java (74%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/monitor/ThreadLocalRecording.java (84%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/monitor/Timer.java (88%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/monitor/Utils.java (88%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/B3HttpCodec.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/B3TraceId.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/ContextInterpreter.java (81%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/CorePropagation.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/DatadogHttpCodec.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/ExtractedContext.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/HaystackHttpCodec.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/HttpCodec.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/NoOpCorePropagation.java (80%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/NoneCodec.java (68%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/PropagationTags.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/TagContextExtractor.java (78%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/W3CHttpCodec.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/XRayHttpCodec.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/ptags/PTagsCodec.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/ptags/PTagsFactory.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/ptags/TagElement.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/ptags/TagKey.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/ptags/TagValue.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/scopemanager/AbstractContinuation.java (79%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/scopemanager/ConcurrentContinuation.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/scopemanager/ContinuableScope.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/scopemanager/ContinuableScopeManager.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/scopemanager/ContinuingScope.java (81%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/scopemanager/ScopeStack.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/scopemanager/SingleContinuation.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/taginterceptor/RuleFlags.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/taginterceptor/TagInterceptor.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/tagprocessor/BaseServiceAdder.java (80%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/tagprocessor/PeerServiceCalculator.java (86%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/tagprocessor/PostProcessorChain.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/tagprocessor/QueryObfuscator.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/tagprocessor/TagsPostProcessor.java (76%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/util/GlobPattern.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/util/LRUCache.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/util/Matcher.java (73%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/util/Matchers.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/util/NoneSystemAccessProvider.java (80%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/util/SimpleRateLimiter.java (95%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/util/SystemAccess.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/util/SystemAccessProvider.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/core/util/TagsMatcher.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/ddagent/DroppingPolicy.java (87%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/logging/GlobalLogLevelSwitcher.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/logging/LogLevel.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/logging/LogLevelSwitcher.java (92%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/logging/LoggingSettingsDescription.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/monitor/Counter.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/monitor/Monitoring.java (88%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/monitor/NoOpCounter.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/monitor/NoOpRecording.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/monitor/Recording.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/relocate/api/IOLogger.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/relocate/api/RatelimitedLogger.java (94%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/serialization/ByteBufferConsumer.java (75%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/serialization/EncodingCache.java (70%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/serialization/FlushingBuffer.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/serialization/GrowableBuffer.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/serialization/Mapper.java (52%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/serialization/MessageFormatter.java (72%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/serialization/StreamingBuffer.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/serialization/ValueWriter.java (59%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/serialization/Writable.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/serialization/WritableFormatter.java (64%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/AgentProxySelector.java (93%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/AgentTaskScheduler.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/AgentThreadFactory.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/CollectionUtils.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/FNV64Hash.java (97%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/FileUtils.java (96%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/PidHelper.java (91%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/ProcessUtils.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/Strings.java (99%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/TagsHelper.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/TraceUtils.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/stacktrace/AbstractStackWalker.java (83%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/stacktrace/DefaultStackWalker.java (90%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/stacktrace/StackUtils.java (98%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/stacktrace/StackWalker.java (86%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/stacktrace/StackWalkerFactory.java (89%) rename features/dd-trace-core/src/main/java/{ => com}/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java (92%) delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InboxItem.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java delete mode 100644 features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Sink.java rename features/dd-trace-core/src/test/kotlin/{ => com}/datadog/trace/util/FileUtilsTest.kt (98%) diff --git a/features/dd-trace-core/build.gradle.kts b/features/dd-trace-core/build.gradle.kts index a1cbcce03c..40dd332cdf 100644 --- a/features/dd-trace-core/build.gradle.kts +++ b/features/dd-trace-core/build.gradle.kts @@ -30,7 +30,7 @@ android { compileOptions { isCoreLibraryDesugaringEnabled = true } - namespace = "datadog.trace" + namespace = "com.com.datadog.trace" } dependencies { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/advice/ActiveRequestContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/advice/ActiveRequestContext.java similarity index 88% rename from features/dd-trace-core/src/main/java/datadog/trace/advice/ActiveRequestContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/advice/ActiveRequestContext.java index 6478e5c4ff..98b7f031a9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/advice/ActiveRequestContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/advice/ActiveRequestContext.java @@ -1,4 +1,4 @@ -package datadog.trace.advice; +package com.datadog.trace.advice; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/advice/RequiresRequestContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/advice/RequiresRequestContext.java similarity index 76% rename from features/dd-trace-core/src/main/java/datadog/trace/advice/RequiresRequestContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/advice/RequiresRequestContext.java index 1ac7c06912..b5b5f4a084 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/advice/RequiresRequestContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/advice/RequiresRequestContext.java @@ -1,12 +1,12 @@ -package datadog.trace.advice; +package com.datadog.trace.advice; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import datadog.trace.api.gateway.RequestContext; -import datadog.trace.api.gateway.RequestContextSlot; +import com.datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.gateway.RequestContextSlot; /** * Transforms the enter and exit advice so that the existence of an active {@link RequestContext} is diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Config.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java similarity index 84% rename from features/dd-trace-core/src/main/java/datadog/trace/api/Config.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java index 834582c423..0ad8df9a6f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/Config.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java @@ -1,322 +1,322 @@ -package datadog.trace.api; - -import static datadog.trace.api.ConfigDefaults.*; -import static datadog.trace.api.DDTags.HOST_TAG; -import static datadog.trace.api.DDTags.INTERNAL_HOST_NAME; -import static datadog.trace.api.DDTags.LANGUAGE_TAG_KEY; -import static datadog.trace.api.DDTags.LANGUAGE_TAG_VALUE; -import static datadog.trace.api.DDTags.PID_TAG; -import static datadog.trace.api.DDTags.PROFILING_ENABLED; -import static datadog.trace.api.DDTags.RUNTIME_ID_TAG; -import static datadog.trace.api.DDTags.RUNTIME_VERSION_TAG; -import static datadog.trace.api.DDTags.SCHEMA_VERSION_TAG_KEY; -import static datadog.trace.api.DDTags.SERVICE; -import static datadog.trace.api.DDTags.SERVICE_TAG; -import static datadog.trace.api.UserEventTrackingMode.SAFE; -import static datadog.trace.api.config.AppSecConfig.API_SECURITY_ENABLED; -import static datadog.trace.api.config.AppSecConfig.API_SECURITY_REQUEST_SAMPLE_RATE; -import static datadog.trace.api.config.AppSecConfig.APPSEC_AUTOMATED_USER_EVENTS_TRACKING; -import static datadog.trace.api.config.AppSecConfig.APPSEC_HTTP_BLOCKED_TEMPLATE_HTML; -import static datadog.trace.api.config.AppSecConfig.APPSEC_HTTP_BLOCKED_TEMPLATE_JSON; -import static datadog.trace.api.config.AppSecConfig.APPSEC_IP_ADDR_HEADER; -import static datadog.trace.api.config.AppSecConfig.APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP; -import static datadog.trace.api.config.AppSecConfig.APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP; -import static datadog.trace.api.config.AppSecConfig.APPSEC_REPORTING_INBAND; -import static datadog.trace.api.config.AppSecConfig.APPSEC_REPORT_TIMEOUT_SEC; -import static datadog.trace.api.config.AppSecConfig.APPSEC_RULES_FILE; -import static datadog.trace.api.config.AppSecConfig.APPSEC_TRACE_RATE_LIMIT; -import static datadog.trace.api.config.AppSecConfig.APPSEC_WAF_METRICS; -import static datadog.trace.api.config.AppSecConfig.APPSEC_WAF_TIMEOUT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ADDITIONAL_CHILD_PROCESS_JVM_ARGS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_URL; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENT_JAR_URI; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AUTO_CONFIGURATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CIPROVIDER_INTEGRATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_EXCLUDES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_INCLUDES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_PERCENTAGE_CALCULATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_REPORT_DUMP_DIR; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_ROOT_PACKAGES_LIMIT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_SEGMENTS_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_COMPILER_PLUGIN_VERSION; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_DEBUG_PORT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_COUNT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_REMOTE_NAME; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UNSHALLOW_DEFER; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UNSHALLOW_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UPLOAD_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_INJECTED_TRACER_VERSION; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ITR_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JACOCO_GRADLE_SOURCE_SETS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JACOCO_PLUGIN_VERSION; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JVM_INFO_CACHE_SIZE; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_EXECUTION_SETTINGS_CACHE_SIZE; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_ID; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_NAME; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_REPO_INDEX_SHARING_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_RESOURCE_FOLDER_NAMES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SESSION_ID; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_HOST; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_PORT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SOURCE_DATA_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TRACE_SANITATION_ENABLED; -import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS; -import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS_DEFAULT; -import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_TAGS; -import static datadog.trace.api.config.CwsConfig.CWS_ENABLED; -import static datadog.trace.api.config.CwsConfig.CWS_TLS_REFRESH; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_CAPTURE_TIMEOUT; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_CLASSFILE_DUMP_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_DIAGNOSTICS_INTERVAL; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCLUDE_FILES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_INSTRUMENT_THE_WORLD; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_MAX_PAYLOAD_SIZE; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_METRICS_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_POLL_INTERVAL; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_PROBE_FILE_LOCATION; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTED_IDENTIFIERS; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTED_TYPES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_FLUSH_THRESHOLD; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_FORCE_UPLOAD; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_INCLUDES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_BATCH_SIZE; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_FLUSH_INTERVAL; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_TIMEOUT; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_VERIFY_BYTECODE; -import static datadog.trace.api.config.GeneralConfig.API_KEY; -import static datadog.trace.api.config.GeneralConfig.API_KEY_FILE; -import static datadog.trace.api.config.GeneralConfig.APPLICATION_KEY; -import static datadog.trace.api.config.GeneralConfig.APPLICATION_KEY_FILE; -import static datadog.trace.api.config.GeneralConfig.AZURE_APP_SERVICES; -import static datadog.trace.api.config.GeneralConfig.DATA_STREAMS_BUCKET_DURATION_SECONDS; -import static datadog.trace.api.config.GeneralConfig.DATA_STREAMS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_ARGS; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_HOST; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_NAMED_PIPE; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_PATH; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_PORT; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_START_DELAY; -import static datadog.trace.api.config.GeneralConfig.ENV; -import static datadog.trace.api.config.GeneralConfig.GLOBAL_TAGS; -import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_HOST; -import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_PORT; -import static datadog.trace.api.config.GeneralConfig.PERF_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.PRIMARY_TAG; -import static datadog.trace.api.config.GeneralConfig.RUNTIME_ID_ENABLED; -import static datadog.trace.api.config.GeneralConfig.RUNTIME_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.SERVICE_NAME; -import static datadog.trace.api.config.GeneralConfig.SITE; -import static datadog.trace.api.config.GeneralConfig.STARTUP_LOGS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_QUEUE_SIZE; -import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_SOCKET_BUFFER; -import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_SOCKET_TIMEOUT; -import static datadog.trace.api.config.GeneralConfig.TAGS; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_DEPENDENCY_COLLECTION_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_HEARTBEAT_INTERVAL; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_LOG_COLLECTION_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_METRICS_INTERVAL; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_BUFFERING_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_IGNORED_RESOURCES; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_MAX_AGGREGATES; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_MAX_PENDING; -import static datadog.trace.api.config.GeneralConfig.TRACE_DEBUG; -import static datadog.trace.api.config.GeneralConfig.TRACE_TRIAGE; -import static datadog.trace.api.config.GeneralConfig.VERSION; -import static datadog.trace.api.config.IastConfig.IAST_DEBUG_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_DETECTION_MODE; -import static datadog.trace.api.config.IastConfig.IAST_REDACTION_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_REDACTION_NAME_PATTERN; -import static datadog.trace.api.config.IastConfig.IAST_REDACTION_VALUE_PATTERN; -import static datadog.trace.api.config.IastConfig.IAST_STACKTRACE_LEAK_SUPPRESS; -import static datadog.trace.api.config.IastConfig.IAST_TELEMETRY_VERBOSITY; -import static datadog.trace.api.config.IastConfig.IAST_TRUNCATION_MAX_VALUE_LENGTH; -import static datadog.trace.api.config.IastConfig.IAST_WEAK_CIPHER_ALGORITHMS; -import static datadog.trace.api.config.IastConfig.IAST_WEAK_HASH_ALGORITHMS; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CHECK_PERIOD; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CONFIG; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CONFIG_DIR; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_ENABLED; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_INITIAL_REFRESH_BEANS_PERIOD; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_METRICS_CONFIGS; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_REFRESH_BEANS_PERIOD; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_START_DELAY; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_HOST; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_PORT; -import static datadog.trace.api.config.JmxFetchConfig.JMX_TAGS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_VERY_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_VERY_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_RECORD_MESSAGE; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_RECORD_MESSAGE_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_SAMPLE_LIMIT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_SAMPLE_LIMIT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCLUDE_AGENT_THREADS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_HOST; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PASSWORD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PORT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PORT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_USERNAME; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_DELAY; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_DELAY_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_FORCE_FIRST; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_FORCE_FIRST_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_TAGS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_TEMPLATE_OVERRIDE_FILE; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_COMPRESSION; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_COMPRESSION_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_PERIOD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_PERIOD_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_SUMMARY_ON_413; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_SUMMARY_ON_413_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_TIMEOUT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_TIMEOUT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_URL; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_ENABLED; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_MAX_PAYLOAD_SIZE; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_POLL_INTERVAL_SECONDS; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_TARGETS_KEY; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_TARGETS_KEY_ID; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_URL; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_HOST; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_DBM_PROPAGATION_MODE_MODE; -import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_AND_PARAMS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_PARAMS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.GOOGLE_PUBSUB_IGNORED_GRPC_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_CLIENT_ERROR_STATUSES; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_IGNORED_INBOUND_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_IGNORED_OUTBOUND_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_SERVER_ERROR_STATUSES; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_SERVER_TRIM_PACKAGE_RESOURCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_TAG_HEADERS; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_TAG_QUERY_STRING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_DECODED_RESOURCE_PRESERVE_SPACES; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_QUERY_STRING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_RESOURCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_ROUTE_BASED_NAMING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_TAG_QUERY_STRING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HYSTRIX_MEASURED_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.HYSTRIX_TAGS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.IGNITE_CACHE_INCLUDE_KEYS; -import static datadog.trace.api.config.TraceInstrumentationConfig.INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.JAX_RS_EXCEPTION_AS_ERROR_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_PROPAGATION_DISABLED_QUEUES; -import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_PROPAGATION_DISABLED_TOPICS; -import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_UNACKNOWLEDGED_MAX_AGE; -import static datadog.trace.api.config.TraceInstrumentationConfig.KAFKA_CLIENT_BASE64_DECODING_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS; -import static datadog.trace.api.config.TraceInstrumentationConfig.LOGS_INJECTION_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.MESSAGE_BROKER_SPLIT_BY_DESTINATION; -import static datadog.trace.api.config.TraceInstrumentationConfig.OBFUSCATION_QUERY_STRING_REGEXP; -import static datadog.trace.api.config.TraceInstrumentationConfig.PLAY_REPORT_HTTP_STATUS; -import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_INCLUDE_ROUTINGKEY_IN_RESOURCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_PROPAGATION_DISABLED_EXCHANGES; -import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_PROPAGATION_DISABLED_QUEUES; -import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ASYNC_TIMEOUT_ERROR; -import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_PRINCIPAL_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ROOT_CONTEXT_SERVICE_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.SPARK_TASK_HISTOGRAM_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME; -import static datadog.trace.api.config.TracerConfig.AGENT_HOST; -import static datadog.trace.api.config.TracerConfig.AGENT_NAMED_PIPE; -import static datadog.trace.api.config.TracerConfig.AGENT_PORT_LEGACY; -import static datadog.trace.api.config.TracerConfig.AGENT_TIMEOUT; -import static datadog.trace.api.config.TracerConfig.AGENT_UNIX_DOMAIN_SOCKET; -import static datadog.trace.api.config.TracerConfig.BAGGAGE_MAPPING; -import static datadog.trace.api.config.TracerConfig.CLIENT_IP_ENABLED; -import static datadog.trace.api.config.TracerConfig.CLOCK_SYNC_PERIOD; -import static datadog.trace.api.config.TracerConfig.ENABLE_TRACE_AGENT_V05; -import static datadog.trace.api.config.TracerConfig.HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.HTTP_CLIENT_ERROR_STATUSES; -import static datadog.trace.api.config.TracerConfig.HTTP_SERVER_ERROR_STATUSES; -import static datadog.trace.api.config.TracerConfig.ID_GENERATION_STRATEGY; -import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_ENABLED; -import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_MIN_SPANS; -import static datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING; -import static datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING_FORCE; -import static datadog.trace.api.config.TracerConfig.PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED; -import static datadog.trace.api.config.TracerConfig.PROPAGATION_STYLE_EXTRACT; -import static datadog.trace.api.config.TracerConfig.PROPAGATION_STYLE_INJECT; -import static datadog.trace.api.config.TracerConfig.PROXY_NO_PROXY; -import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS_COMMA_ALLOWED; -import static datadog.trace.api.config.TracerConfig.RESPONSE_HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.SCOPE_DEPTH_LIMIT; -import static datadog.trace.api.config.TracerConfig.SCOPE_INHERIT_ASYNC_PROPAGATION; -import static datadog.trace.api.config.TracerConfig.SCOPE_ITERATION_KEEP_ALIVE; -import static datadog.trace.api.config.TracerConfig.SCOPE_STRICT_MODE; -import static datadog.trace.api.config.TracerConfig.SECURE_RANDOM; -import static datadog.trace.api.config.TracerConfig.SERVICE_MAPPING; -import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES; -import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES_FILE; -import static datadog.trace.api.config.TracerConfig.SPAN_TAGS; -import static datadog.trace.api.config.TracerConfig.SPLIT_BY_TAGS; -import static datadog.trace.api.config.TracerConfig.TRACE_128_BIT_TRACEID_GENERATION_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_ARGS; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_PATH; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_PORT; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_URL; -import static datadog.trace.api.config.TracerConfig.TRACE_ANALYTICS_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_HEADER; -import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_RESOLVER_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_GIT_METADATA_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING; -import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH; -import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING; -import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_COMPONENT_OVERRIDES; -import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_DEFAULTS_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_MAPPING; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_EXTRACT_FIRST; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE_EXTRACT; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE_INJECT; -import static datadog.trace.api.config.TracerConfig.TRACE_RATE_LIMIT; -import static datadog.trace.api.config.TracerConfig.TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_REPORT_HOSTNAME; -import static datadog.trace.api.config.TracerConfig.TRACE_RESOLVER_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLE_RATE; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_OPERATION_RULES; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_RULES; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_SERVICE_RULES; -import static datadog.trace.api.config.TracerConfig.TRACE_SPAN_ATTRIBUTE_SCHEMA; -import static datadog.trace.api.config.TracerConfig.TRACE_STRICT_WRITES_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_X_DATADOG_TAGS_MAX_LENGTH; -import static datadog.trace.api.config.TracerConfig.WRITER_BAGGAGE_INJECT; -import static datadog.trace.api.config.TracerConfig.WRITER_TYPE; -import static datadog.trace.api.iast.IastDetectionMode.DEFAULT; -import static datadog.trace.util.CollectionUtils.tryMakeImmutableList; -import static datadog.trace.util.CollectionUtils.tryMakeImmutableSet; -import static datadog.trace.util.Strings.propertyNameToEnvironmentVariableName; +package com.datadog.trace.api; + +import static com.datadog.trace.api.ConfigDefaults.*; +import static com.datadog.trace.api.DDTags.HOST_TAG; +import static com.datadog.trace.api.DDTags.INTERNAL_HOST_NAME; +import static com.datadog.trace.api.DDTags.LANGUAGE_TAG_KEY; +import static com.datadog.trace.api.DDTags.LANGUAGE_TAG_VALUE; +import static com.datadog.trace.api.DDTags.PID_TAG; +import static com.datadog.trace.api.DDTags.PROFILING_ENABLED; +import static com.datadog.trace.api.DDTags.RUNTIME_ID_TAG; +import static com.datadog.trace.api.DDTags.RUNTIME_VERSION_TAG; +import static com.datadog.trace.api.DDTags.SCHEMA_VERSION_TAG_KEY; +import static com.datadog.trace.api.DDTags.SERVICE; +import static com.datadog.trace.api.DDTags.SERVICE_TAG; +import static com.datadog.trace.api.UserEventTrackingMode.SAFE; +import static com.datadog.trace.api.config.AppSecConfig.API_SECURITY_ENABLED; +import static com.datadog.trace.api.config.AppSecConfig.API_SECURITY_REQUEST_SAMPLE_RATE; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_AUTOMATED_USER_EVENTS_TRACKING; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_HTTP_BLOCKED_TEMPLATE_HTML; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_HTTP_BLOCKED_TEMPLATE_JSON; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_IP_ADDR_HEADER; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_REPORTING_INBAND; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_REPORT_TIMEOUT_SEC; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_RULES_FILE; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_TRACE_RATE_LIMIT; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_WAF_METRICS; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_WAF_TIMEOUT; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ADDITIONAL_CHILD_PROCESS_JVM_ARGS; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_URL; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENT_JAR_URI; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AUTO_CONFIGURATION_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CIPROVIDER_INTEGRATION_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_EXCLUDES; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_INCLUDES; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_PERCENTAGE_CALCULATION_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_REPORT_DUMP_DIR; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_ROOT_PACKAGES_LIMIT; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_SEGMENTS_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_COMPILER_PLUGIN_VERSION; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_DEBUG_PORT; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_COUNT; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_REMOTE_NAME; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UNSHALLOW_DEFER; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UNSHALLOW_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UPLOAD_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_INJECTED_TRACER_VERSION; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ITR_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JACOCO_GRADLE_SOURCE_SETS; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JACOCO_PLUGIN_VERSION; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JVM_INFO_CACHE_SIZE; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_EXECUTION_SETTINGS_CACHE_SIZE; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_ID; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_NAME; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_REPO_INDEX_SHARING_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_RESOURCE_FOLDER_NAMES; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SESSION_ID; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_HOST; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_PORT; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SOURCE_DATA_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SOURCE_DATA_ROOT_CHECK_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TRACE_SANITATION_ENABLED; +import static com.datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS; +import static com.datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS_DEFAULT; +import static com.datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_TAGS; +import static com.datadog.trace.api.config.CwsConfig.CWS_ENABLED; +import static com.datadog.trace.api.config.CwsConfig.CWS_TLS_REFRESH; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_CAPTURE_TIMEOUT; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_CLASSFILE_DUMP_ENABLED; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_DIAGNOSTICS_INTERVAL; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_ENABLED; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCLUDE_FILES; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_INSTRUMENT_THE_WORLD; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_MAX_PAYLOAD_SIZE; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_METRICS_ENABLED; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_POLL_INTERVAL; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_PROBE_FILE_LOCATION; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTED_IDENTIFIERS; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTED_TYPES; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_ENABLED; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_FLUSH_THRESHOLD; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_FORCE_UPLOAD; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_INCLUDES; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_BATCH_SIZE; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_FLUSH_INTERVAL; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_TIMEOUT; +import static com.datadog.trace.api.config.DebuggerConfig.DEBUGGER_VERIFY_BYTECODE; +import static com.datadog.trace.api.config.GeneralConfig.API_KEY; +import static com.datadog.trace.api.config.GeneralConfig.API_KEY_FILE; +import static com.datadog.trace.api.config.GeneralConfig.APPLICATION_KEY; +import static com.datadog.trace.api.config.GeneralConfig.APPLICATION_KEY_FILE; +import static com.datadog.trace.api.config.GeneralConfig.AZURE_APP_SERVICES; +import static com.datadog.trace.api.config.GeneralConfig.DATA_STREAMS_BUCKET_DURATION_SECONDS; +import static com.datadog.trace.api.config.GeneralConfig.DATA_STREAMS_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.DOGSTATSD_ARGS; +import static com.datadog.trace.api.config.GeneralConfig.DOGSTATSD_HOST; +import static com.datadog.trace.api.config.GeneralConfig.DOGSTATSD_NAMED_PIPE; +import static com.datadog.trace.api.config.GeneralConfig.DOGSTATSD_PATH; +import static com.datadog.trace.api.config.GeneralConfig.DOGSTATSD_PORT; +import static com.datadog.trace.api.config.GeneralConfig.DOGSTATSD_START_DELAY; +import static com.datadog.trace.api.config.GeneralConfig.ENV; +import static com.datadog.trace.api.config.GeneralConfig.GLOBAL_TAGS; +import static com.datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_HOST; +import static com.datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_PORT; +import static com.datadog.trace.api.config.GeneralConfig.PERF_METRICS_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.PRIMARY_TAG; +import static com.datadog.trace.api.config.GeneralConfig.RUNTIME_ID_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.RUNTIME_METRICS_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.SERVICE_NAME; +import static com.datadog.trace.api.config.GeneralConfig.SITE; +import static com.datadog.trace.api.config.GeneralConfig.STARTUP_LOGS_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_QUEUE_SIZE; +import static com.datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_SOCKET_BUFFER; +import static com.datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_SOCKET_TIMEOUT; +import static com.datadog.trace.api.config.GeneralConfig.TAGS; +import static com.datadog.trace.api.config.GeneralConfig.TELEMETRY_DEPENDENCY_COLLECTION_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL; +import static com.datadog.trace.api.config.GeneralConfig.TELEMETRY_HEARTBEAT_INTERVAL; +import static com.datadog.trace.api.config.GeneralConfig.TELEMETRY_LOG_COLLECTION_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.TELEMETRY_METRICS_INTERVAL; +import static com.datadog.trace.api.config.GeneralConfig.TRACER_METRICS_BUFFERING_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.TRACER_METRICS_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.TRACER_METRICS_IGNORED_RESOURCES; +import static com.datadog.trace.api.config.GeneralConfig.TRACER_METRICS_MAX_AGGREGATES; +import static com.datadog.trace.api.config.GeneralConfig.TRACER_METRICS_MAX_PENDING; +import static com.datadog.trace.api.config.GeneralConfig.TRACE_DEBUG; +import static com.datadog.trace.api.config.GeneralConfig.TRACE_TRIAGE; +import static com.datadog.trace.api.config.GeneralConfig.VERSION; +import static com.datadog.trace.api.config.IastConfig.IAST_DEBUG_ENABLED; +import static com.datadog.trace.api.config.IastConfig.IAST_DETECTION_MODE; +import static com.datadog.trace.api.config.IastConfig.IAST_REDACTION_ENABLED; +import static com.datadog.trace.api.config.IastConfig.IAST_REDACTION_NAME_PATTERN; +import static com.datadog.trace.api.config.IastConfig.IAST_REDACTION_VALUE_PATTERN; +import static com.datadog.trace.api.config.IastConfig.IAST_STACKTRACE_LEAK_SUPPRESS; +import static com.datadog.trace.api.config.IastConfig.IAST_TELEMETRY_VERBOSITY; +import static com.datadog.trace.api.config.IastConfig.IAST_TRUNCATION_MAX_VALUE_LENGTH; +import static com.datadog.trace.api.config.IastConfig.IAST_WEAK_CIPHER_ALGORITHMS; +import static com.datadog.trace.api.config.IastConfig.IAST_WEAK_HASH_ALGORITHMS; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CHECK_PERIOD; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CONFIG; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CONFIG_DIR; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_ENABLED; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_INITIAL_REFRESH_BEANS_PERIOD; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_METRICS_CONFIGS; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_REFRESH_BEANS_PERIOD; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_START_DELAY; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_HOST; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_PORT; +import static com.datadog.trace.api.config.JmxFetchConfig.JMX_TAGS; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_OLD; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_VERY_OLD; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_OLD; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_VERY_OLD; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_ENABLED; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_RECORD_MESSAGE; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_RECORD_MESSAGE_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_SAMPLE_LIMIT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_SAMPLE_LIMIT_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_EXCLUDE_AGENT_THREADS; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_HOST; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PASSWORD; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PORT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PORT_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_USERNAME; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_START_DELAY; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_START_DELAY_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_START_FORCE_FIRST; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_START_FORCE_FIRST_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_TAGS; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_TEMPLATE_OVERRIDE_FILE; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_COMPRESSION; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_COMPRESSION_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_PERIOD; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_PERIOD_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_SUMMARY_ON_413; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_SUMMARY_ON_413_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_TIMEOUT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_TIMEOUT_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_URL; +import static com.datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_ENABLED; +import static com.datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED; +import static com.datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_MAX_PAYLOAD_SIZE; +import static com.datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_POLL_INTERVAL_SECONDS; +import static com.datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_TARGETS_KEY; +import static com.datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_TARGETS_KEY_ID; +import static com.datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_URL; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_HOST; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.DB_DBM_PROPAGATION_MODE_MODE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_AND_PARAMS_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_PARAMS_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.GOOGLE_PUBSUB_IGNORED_GRPC_METHODS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.GRPC_CLIENT_ERROR_STATUSES; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.GRPC_IGNORED_INBOUND_METHODS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.GRPC_IGNORED_OUTBOUND_METHODS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.GRPC_SERVER_ERROR_STATUSES; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.GRPC_SERVER_TRIM_PACKAGE_RESOURCE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_TAG_HEADERS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_TAG_QUERY_STRING; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_DECODED_RESOURCE_PRESERVE_SPACES; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_QUERY_STRING; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_RESOURCE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_ROUTE_BASED_NAMING; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_TAG_QUERY_STRING; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HYSTRIX_MEASURED_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HYSTRIX_TAGS_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.IGNITE_CACHE_INCLUDE_KEYS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.JAX_RS_EXCEPTION_AS_ERROR_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.JMS_PROPAGATION_DISABLED_QUEUES; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.JMS_PROPAGATION_DISABLED_TOPICS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.JMS_UNACKNOWLEDGED_MAX_AGE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.KAFKA_CLIENT_BASE64_DECODING_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.LOGS_INJECTION_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.MESSAGE_BROKER_SPLIT_BY_DESTINATION; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.OBFUSCATION_QUERY_STRING_REGEXP; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.PLAY_REPORT_HTTP_STATUS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_INCLUDE_ROUTINGKEY_IN_RESOURCE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_PROPAGATION_DISABLED_EXCHANGES; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_PROPAGATION_DISABLED_QUEUES; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ASYNC_TIMEOUT_ERROR; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_PRINCIPAL_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ROOT_CONTEXT_SERVICE_NAME; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.SPARK_TASK_HISTOGRAM_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME; +import static com.datadog.trace.api.config.TracerConfig.AGENT_HOST; +import static com.datadog.trace.api.config.TracerConfig.AGENT_NAMED_PIPE; +import static com.datadog.trace.api.config.TracerConfig.AGENT_PORT_LEGACY; +import static com.datadog.trace.api.config.TracerConfig.AGENT_TIMEOUT; +import static com.datadog.trace.api.config.TracerConfig.AGENT_UNIX_DOMAIN_SOCKET; +import static com.datadog.trace.api.config.TracerConfig.BAGGAGE_MAPPING; +import static com.datadog.trace.api.config.TracerConfig.CLIENT_IP_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.CLOCK_SYNC_PERIOD; +import static com.datadog.trace.api.config.TracerConfig.ENABLE_TRACE_AGENT_V05; +import static com.datadog.trace.api.config.TracerConfig.HEADER_TAGS; +import static com.datadog.trace.api.config.TracerConfig.HTTP_CLIENT_ERROR_STATUSES; +import static com.datadog.trace.api.config.TracerConfig.HTTP_SERVER_ERROR_STATUSES; +import static com.datadog.trace.api.config.TracerConfig.ID_GENERATION_STRATEGY; +import static com.datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_MIN_SPANS; +import static com.datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING; +import static com.datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING_FORCE; +import static com.datadog.trace.api.config.TracerConfig.PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.PROPAGATION_STYLE_EXTRACT; +import static com.datadog.trace.api.config.TracerConfig.PROPAGATION_STYLE_INJECT; +import static com.datadog.trace.api.config.TracerConfig.PROXY_NO_PROXY; +import static com.datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS; +import static com.datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS_COMMA_ALLOWED; +import static com.datadog.trace.api.config.TracerConfig.RESPONSE_HEADER_TAGS; +import static com.datadog.trace.api.config.TracerConfig.SCOPE_DEPTH_LIMIT; +import static com.datadog.trace.api.config.TracerConfig.SCOPE_INHERIT_ASYNC_PROPAGATION; +import static com.datadog.trace.api.config.TracerConfig.SCOPE_ITERATION_KEEP_ALIVE; +import static com.datadog.trace.api.config.TracerConfig.SCOPE_STRICT_MODE; +import static com.datadog.trace.api.config.TracerConfig.SECURE_RANDOM; +import static com.datadog.trace.api.config.TracerConfig.SERVICE_MAPPING; +import static com.datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES; +import static com.datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES_FILE; +import static com.datadog.trace.api.config.TracerConfig.SPAN_TAGS; +import static com.datadog.trace.api.config.TracerConfig.SPLIT_BY_TAGS; +import static com.datadog.trace.api.config.TracerConfig.TRACE_128_BIT_TRACEID_GENERATION_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.TRACE_AGENT_ARGS; +import static com.datadog.trace.api.config.TracerConfig.TRACE_AGENT_PATH; +import static com.datadog.trace.api.config.TracerConfig.TRACE_AGENT_PORT; +import static com.datadog.trace.api.config.TracerConfig.TRACE_AGENT_URL; +import static com.datadog.trace.api.config.TracerConfig.TRACE_ANALYTICS_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_HEADER; +import static com.datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_RESOLVER_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.TRACE_GIT_METADATA_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING; +import static com.datadog.trace.api.config.TracerConfig.TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH; +import static com.datadog.trace.api.config.TracerConfig.TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING; +import static com.datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_COMPONENT_OVERRIDES; +import static com.datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_DEFAULTS_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_MAPPING; +import static com.datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_EXTRACT_FIRST; +import static com.datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE; +import static com.datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE_EXTRACT; +import static com.datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE_INJECT; +import static com.datadog.trace.api.config.TracerConfig.TRACE_RATE_LIMIT; +import static com.datadog.trace.api.config.TracerConfig.TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.TRACE_REPORT_HOSTNAME; +import static com.datadog.trace.api.config.TracerConfig.TRACE_RESOLVER_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.TRACE_SAMPLE_RATE; +import static com.datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_OPERATION_RULES; +import static com.datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_RULES; +import static com.datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_SERVICE_RULES; +import static com.datadog.trace.api.config.TracerConfig.TRACE_SPAN_ATTRIBUTE_SCHEMA; +import static com.datadog.trace.api.config.TracerConfig.TRACE_STRICT_WRITES_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.TRACE_X_DATADOG_TAGS_MAX_LENGTH; +import static com.datadog.trace.api.config.TracerConfig.WRITER_BAGGAGE_INJECT; +import static com.datadog.trace.api.config.TracerConfig.WRITER_TYPE; +import static com.datadog.trace.api.iast.IastDetectionMode.DEFAULT; +import static com.datadog.trace.util.CollectionUtils.tryMakeImmutableList; +import static com.datadog.trace.util.CollectionUtils.tryMakeImmutableSet; +import static com.datadog.trace.util.Strings.propertyNameToEnvironmentVariableName; import android.os.Build; @@ -358,19 +358,19 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import datadog.trace.api.config.GeneralConfig; -import datadog.trace.api.config.ProfilingConfig; -import datadog.trace.api.config.TracerConfig; -import datadog.trace.api.iast.IastDetectionMode; -import datadog.trace.api.iast.telemetry.Verbosity; -import datadog.trace.api.naming.SpanNaming; -import datadog.trace.bootstrap.config.provider.CapturedEnvironmentConfigSource; -import datadog.trace.bootstrap.config.provider.ConfigProvider; -import datadog.trace.bootstrap.config.provider.SystemPropertiesConfigSource; -import datadog.trace.util.FileUtils; -import datadog.trace.util.PidHelper; -import datadog.trace.util.Strings; -import datadog.trace.util.throwable.FatalAgentMisconfigurationError; +import com.datadog.trace.api.config.GeneralConfig; +import com.datadog.trace.api.config.ProfilingConfig; +import com.datadog.trace.api.config.TracerConfig; +import com.datadog.trace.api.iast.IastDetectionMode; +import com.datadog.trace.api.iast.telemetry.Verbosity; +import com.datadog.trace.api.naming.SpanNaming; +import com.datadog.trace.bootstrap.config.provider.CapturedEnvironmentConfigSource; +import com.datadog.trace.bootstrap.config.provider.ConfigProvider; +import com.datadog.trace.bootstrap.config.provider.SystemPropertiesConfigSource; +import com.datadog.trace.util.FileUtils; +import com.datadog.trace.util.PidHelper; +import com.datadog.trace.util.Strings; +import com.datadog.trace.util.throwable.FatalAgentMisconfigurationError; /** * Config reads values with the following priority: @@ -3311,9 +3311,9 @@ private Map getProcessIdTag() { private Map getAzureAppServicesTags() { // These variable names and derivations are copied from the dotnet tracer // See - // https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/src/Datadog.Trace/PlatformHelpers/AzureAppServices.cs + // https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/src/com.datadog.trace/PlatformHelpers/AzureAppServices.cs // and - // https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/src/Datadog.Trace/TraceContext.cs#L207 + // https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/src/com.datadog.trace/TraceContext.cs#L207 Map aasTags = new HashMap<>(); /// The site name of the site instance in Azure where the traced application is running. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigCollector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigCollector.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/ConfigCollector.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigCollector.java index c55f1f309b..6a33d77cf1 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigCollector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigCollector.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.util.Collections; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigDefaults.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigDefaults.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/ConfigDefaults.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigDefaults.java index aae9ba7607..1ab0c9f8a3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigDefaults.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigDefaults.java @@ -1,8 +1,8 @@ -package datadog.trace.api; +package com.datadog.trace.api; import static java.util.Arrays.asList; -import static datadog.trace.api.TracePropagationStyle.DATADOG; -import static datadog.trace.api.TracePropagationStyle.TRACECONTEXT; +import static com.datadog.trace.api.TracePropagationStyle.DATADOG; +import static com.datadog.trace.api.TracePropagationStyle.TRACECONTEXT; import java.util.BitSet; import java.util.HashSet; @@ -133,7 +133,7 @@ public final class ConfigDefaults { static final String DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_VERSION = "0.1.8"; static final String DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_VERSION = "0.8.11"; static final String DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_EXCLUDES = - "datadog.trace.*:org.apache.commons.*:org.mockito.*"; + "com.datadog.trace.*:org.apache.commons.*:org.mockito.*"; static final boolean DEFAULT_CIVISIBILITY_GIT_UPLOAD_ENABLED = true; static final boolean DEFAULT_CIVISIBILITY_GIT_UNSHALLOW_ENABLED = true; static final long DEFAULT_CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS = 30_000; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigOrigin.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigOrigin.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/api/ConfigOrigin.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigOrigin.java index 3f46985758..9f1bed57db 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigOrigin.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigOrigin.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; public enum ConfigOrigin { /** configurations that are set through environment variables */ diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigSetting.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigSetting.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/ConfigSetting.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigSetting.java index ac4471fbae..dbb00b62d5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/ConfigSetting.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ConfigSetting.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.util.Arrays; import java.util.HashSet; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/CorrelationIdentifier.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/CorrelationIdentifier.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/api/CorrelationIdentifier.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/CorrelationIdentifier.java index 2354406d47..99251f27bc 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/CorrelationIdentifier.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/CorrelationIdentifier.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; /** * Utility class to access the active trace and span ids. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DD128bTraceId.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DD128bTraceId.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/DD128bTraceId.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/DD128bTraceId.java index 5c36731a94..58a889c4d3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/DD128bTraceId.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DD128bTraceId.java @@ -1,8 +1,8 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.util.Locale; -import datadog.trace.api.internal.util.LongStringUtils; +import com.datadog.trace.api.internal.util.LongStringUtils; /** * Class encapsulating the unsigned 128-bit id used for TraceIds. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DD64bTraceId.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DD64bTraceId.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/DD64bTraceId.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/DD64bTraceId.java index f40b47a89d..e895982ce8 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/DD64bTraceId.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DD64bTraceId.java @@ -1,6 +1,6 @@ -package datadog.trace.api; +package com.datadog.trace.api; -import datadog.trace.api.internal.util.LongStringUtils; +import com.datadog.trace.api.internal.util.LongStringUtils; /** * Class encapsulating the unsigned 64 bit id used for Traceids. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanId.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DDSpanId.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanId.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/DDSpanId.java index 4925370f43..79f0b9215a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanId.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DDSpanId.java @@ -1,6 +1,6 @@ -package datadog.trace.api; +package com.datadog.trace.api; -import datadog.trace.api.internal.util.LongStringUtils; +import com.datadog.trace.api.internal.util.LongStringUtils; /** Class with methods for working with the unsigned 64 bit id used for Span ids. */ public final class DDSpanId { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanTypes.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DDSpanTypes.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanTypes.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/DDSpanTypes.java index 69366eb146..8c9973f1b0 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/DDSpanTypes.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DDSpanTypes.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; public class DDSpanTypes { public static final String HTTP_CLIENT = "http"; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DDTags.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DDTags.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/DDTags.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/DDTags.java index b53cab5ed3..2c09734c67 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/DDTags.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DDTags.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; public class DDTags { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceApiInfo.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DDTraceApiInfo.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceApiInfo.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/DDTraceApiInfo.java index 4713a4ecfb..5e1d52947d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceApiInfo.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DDTraceApiInfo.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.io.BufferedReader; import java.io.InputStreamReader; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceId.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DDTraceId.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceId.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/DDTraceId.java index cc10e7493e..ea351c27f5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/DDTraceId.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DDTraceId.java @@ -1,6 +1,6 @@ -package datadog.trace.api; +package com.datadog.trace.api; -import datadog.trace.api.internal.util.LongStringUtils; +import com.datadog.trace.api.internal.util.LongStringUtils; /** * Class encapsulating the id used for TraceIds. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DisableTestTrace.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DisableTestTrace.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/api/DisableTestTrace.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/DisableTestTrace.java index 6e472573c9..97c8c96820 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/DisableTestTrace.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DisableTestTrace.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/DynamicConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DynamicConfig.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/api/DynamicConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/DynamicConfig.java index 35690fc56c..f9885ff834 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/DynamicConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DynamicConfig.java @@ -1,15 +1,15 @@ -package datadog.trace.api; - -import static datadog.trace.api.config.GeneralConfig.DATA_STREAMS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.RUNTIME_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TRACE_DEBUG; -import static datadog.trace.api.config.TraceInstrumentationConfig.LOGS_INJECTION_ENABLED; -import static datadog.trace.api.config.TracerConfig.BAGGAGE_MAPPING; -import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.RESPONSE_HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.SERVICE_MAPPING; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLE_RATE; -import static datadog.trace.util.CollectionUtils.tryMakeImmutableMap; +package com.datadog.trace.api; + +import static com.datadog.trace.api.config.GeneralConfig.DATA_STREAMS_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.RUNTIME_METRICS_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.TRACE_DEBUG; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.LOGS_INJECTION_ENABLED; +import static com.datadog.trace.api.config.TracerConfig.BAGGAGE_MAPPING; +import static com.datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS; +import static com.datadog.trace.api.config.TracerConfig.RESPONSE_HEADER_TAGS; +import static com.datadog.trace.api.config.TracerConfig.SERVICE_MAPPING; +import static com.datadog.trace.api.config.TracerConfig.TRACE_SAMPLE_RATE; +import static com.datadog.trace.util.CollectionUtils.tryMakeImmutableMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,9 +23,9 @@ import java.util.function.BiFunction; import java.util.function.Function; -import datadog.trace.api.sampling.SamplingRule.SpanSamplingRule; -import datadog.trace.api.sampling.SamplingRule.TraceSamplingRule; -import datadog.trace.util.Strings; +import com.datadog.trace.api.sampling.SamplingRule.SpanSamplingRule; +import com.datadog.trace.api.sampling.SamplingRule.TraceSamplingRule; +import com.datadog.trace.util.Strings; /** * Config that can be dynamically updated via remote-config diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointCheckpointer.java similarity index 84% rename from features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointCheckpointer.java index 1dd127f398..ea80683add 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointCheckpointer.java @@ -1,6 +1,6 @@ -package datadog.trace.api; +package com.datadog.trace.api; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; public interface EndpointCheckpointer { /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointerHolder.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointCheckpointerHolder.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointerHolder.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointCheckpointerHolder.java index 260a04b6c6..b330eb8004 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointCheckpointerHolder.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointCheckpointerHolder.java @@ -1,11 +1,11 @@ -package datadog.trace.api; +package com.datadog.trace.api; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; public final class EndpointCheckpointerHolder implements EndpointCheckpointer { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointTracker.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointTracker.java similarity index 76% rename from features/dd-trace-core/src/main/java/datadog/trace/api/EndpointTracker.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointTracker.java index 1f1eec82e3..089cf4d979 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/EndpointTracker.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointTracker.java @@ -1,6 +1,6 @@ -package datadog.trace.api; +package com.datadog.trace.api; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; /** A simple listener-like interface for tracking the end-point writes */ public interface EndpointTracker { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/EventTracker.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/EventTracker.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/EventTracker.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/EventTracker.java index f053426a1b..1080abc59a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/EventTracker.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/EventTracker.java @@ -1,9 +1,9 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.util.Map; -import datadog.trace.api.internal.InternalTracer; -import datadog.trace.api.internal.TraceSegment; +import com.datadog.trace.api.internal.InternalTracer; +import com.datadog.trace.api.internal.TraceSegment; public class EventTracker { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Functions.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Functions.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/Functions.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/Functions.java index 24441c9d7e..9985c2bcfe 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/Functions.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Functions.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import static java.util.function.Function.identity; @@ -6,7 +6,7 @@ import java.util.function.BiFunction; import java.util.function.Function; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; public final class Functions { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/GlobalTracer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/GlobalTracer.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/GlobalTracer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/GlobalTracer.java index 610fa1fef0..c8aab4cabb 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/GlobalTracer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/GlobalTracer.java @@ -1,10 +1,10 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.util.ArrayList; import java.util.Collection; -import datadog.trace.api.interceptor.TraceInterceptor; -import datadog.trace.api.internal.InternalTracer; +import com.datadog.trace.api.interceptor.TraceInterceptor; +import com.datadog.trace.api.internal.InternalTracer; /** * A global reference to the registered Datadog tracer. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/IdGenerationStrategy.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/IdGenerationStrategy.java index ab7b347fb3..566b511be4 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/IdGenerationStrategy.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/IdGenerationStrategy.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import static java.lang.Long.MAX_VALUE; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/InstrumenterConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/InstrumenterConfig.java similarity index 74% rename from features/dd-trace-core/src/main/java/datadog/trace/api/InstrumenterConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/InstrumenterConfig.java index 7a910cba2e..e8c1a25bd9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/InstrumenterConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/InstrumenterConfig.java @@ -1,61 +1,61 @@ -package datadog.trace.api; - -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_INTEGRATIONS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_MEASURE_METHODS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_RESOLVER_RESET_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_RUNTIME_CONTEXT_FIELD_INJECTION; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SERIALVERSIONUID_FIELD_INJECTION; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_128_BIT_TRACEID_LOGGING_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ANNOTATIONS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ANNOTATION_ASYNC; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_EXECUTORS_ALL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_METHODS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_OTEL_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_USM_ENABLED; -import static datadog.trace.api.config.AppSecConfig.APPSEC_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ENABLED; -import static datadog.trace.api.config.GeneralConfig.INTERNAL_EXIT_ON_FAILURE; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_ENABLED_DEFAULT; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_URL_CONNECTION_CLASS_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.INTEGRATIONS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.JDBC_CONNECTION_CLASS_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.JDBC_PREPARED_STATEMENT_CLASS_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.LEGACY_INSTALLER_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.MEASURE_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_CACHE_CONFIG; -import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_CACHE_DIR; -import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_NAMES_ARE_UNIQUE; -import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_RESET_INTERVAL; -import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_USE_LOADCLASS; -import static datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_USE_URL_CACHES; -import static datadog.trace.api.config.TraceInstrumentationConfig.RUNTIME_CONTEXT_FIELD_INJECTION; -import static datadog.trace.api.config.TraceInstrumentationConfig.SERIALVERSIONUID_FIELD_INJECTION; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_128_BIT_TRACEID_LOGGING_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ANNOTATIONS; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ANNOTATION_ASYNC; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CLASSES_EXCLUDE; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CLASSES_EXCLUDE_FILE; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CLASSLOADERS_EXCLUDE; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CODESOURCES_EXCLUDE; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_EXECUTORS; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_EXECUTORS_ALL; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_OTEL_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_THREAD_POOL_EXECUTORS_EXCLUDE; -import static datadog.trace.api.config.UsmConfig.USM_ENABLED; -import static datadog.trace.util.CollectionUtils.tryMakeImmutableList; -import static datadog.trace.util.CollectionUtils.tryMakeImmutableSet; +package com.datadog.trace.api; + +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_ENABLED; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_ENABLED; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_IAST_ENABLED; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_INTEGRATIONS_ENABLED; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_MEASURE_METHODS; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_RESOLVER_RESET_INTERVAL; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_RUNTIME_CONTEXT_FIELD_INJECTION; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_SERIALVERSIONUID_FIELD_INJECTION; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_ENABLED; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_128_BIT_TRACEID_LOGGING_ENABLED; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ANNOTATIONS; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ANNOTATION_ASYNC; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ENABLED; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_EXECUTORS_ALL; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_METHODS; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_OTEL_ENABLED; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_USM_ENABLED; +import static com.datadog.trace.api.config.AppSecConfig.APPSEC_ENABLED; +import static com.datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ENABLED; +import static com.datadog.trace.api.config.GeneralConfig.INTERNAL_EXIT_ON_FAILURE; +import static com.datadog.trace.api.config.GeneralConfig.TELEMETRY_ENABLED; +import static com.datadog.trace.api.config.IastConfig.IAST_ENABLED; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_ENABLED; +import static com.datadog.trace.api.config.ProfilingConfig.PROFILING_ENABLED_DEFAULT; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.HTTP_URL_CONNECTION_CLASS_NAME; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.INTEGRATIONS_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.JDBC_CONNECTION_CLASS_NAME; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.JDBC_PREPARED_STATEMENT_CLASS_NAME; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.LEGACY_INSTALLER_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.MEASURE_METHODS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_CACHE_CONFIG; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_CACHE_DIR; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_NAMES_ARE_UNIQUE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_RESET_INTERVAL; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_USE_LOADCLASS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.RESOLVER_USE_URL_CACHES; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.RUNTIME_CONTEXT_FIELD_INJECTION; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.SERIALVERSIONUID_FIELD_INJECTION; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_128_BIT_TRACEID_LOGGING_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ANNOTATIONS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ANNOTATION_ASYNC; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CLASSES_EXCLUDE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CLASSES_EXCLUDE_FILE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CLASSLOADERS_EXCLUDE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_CODESOURCES_EXCLUDE; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_EXECUTORS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_EXECUTORS_ALL; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_METHODS; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_OTEL_ENABLED; +import static com.datadog.trace.api.config.TraceInstrumentationConfig.TRACE_THREAD_POOL_EXECUTORS_EXCLUDE; +import static com.datadog.trace.api.config.UsmConfig.USM_ENABLED; +import static com.datadog.trace.util.CollectionUtils.tryMakeImmutableList; +import static com.datadog.trace.util.CollectionUtils.tryMakeImmutableSet; import java.lang.reflect.Method; import java.util.Arrays; @@ -63,7 +63,7 @@ import java.util.Map; import java.util.Set; -import datadog.trace.bootstrap.config.provider.ConfigProvider; +import com.datadog.trace.bootstrap.config.provider.ConfigProvider; /** * This config is needed before instrumentation is applied diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/MethodFilterConfigParser.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/MethodFilterConfigParser.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/MethodFilterConfigParser.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/MethodFilterConfigParser.java index eb9276bbab..9b4caf4fe5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/MethodFilterConfigParser.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/MethodFilterConfigParser.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/NoOpStatsDClient.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/NoOpStatsDClient.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/NoOpStatsDClient.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/NoOpStatsDClient.java index 83f1955228..63fd3870b0 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/NoOpStatsDClient.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/NoOpStatsDClient.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; final class NoOpStatsDClient implements StatsDClient { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Pair.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Pair.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/Pair.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/Pair.java index 6de16b2f74..2a6000f420 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/Pair.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Pair.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Platform.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/Platform.java index c73148a455..5cbc5227ae 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/Platform.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Platform.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.util.ArrayList; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ProductActivation.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ProductActivation.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/ProductActivation.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/ProductActivation.java index 834afb815c..907650a48d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/ProductActivation.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ProductActivation.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; public enum ProductActivation { /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/PropagationStyle.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/PropagationStyle.java index a7ec2c0958..3d4a562575 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/PropagationStyle.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/PropagationStyle.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.util.Arrays; import java.util.Collections; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/ResolverCacheConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ResolverCacheConfig.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/ResolverCacheConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/ResolverCacheConfig.java index 476b4240f8..98cd1d472f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/ResolverCacheConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/ResolverCacheConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; /** Named presets to help configure various caches inside the type resolver/matcher. */ public enum ResolverCacheConfig { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Stateful.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Stateful.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/api/Stateful.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/Stateful.java index b9532ca6af..6780d4f82f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/Stateful.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Stateful.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; public interface Stateful extends AutoCloseable { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClient.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/StatsDClient.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClient.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/StatsDClient.java index b9cef20ba4..27bbb5c681 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClient.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/StatsDClient.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.io.Closeable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClientManager.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/StatsDClientManager.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClientManager.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/StatsDClientManager.java index a60438da57..4a7b54cddf 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/StatsDClientManager.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/StatsDClientManager.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; public interface StatsDClientManager { default StatsDClient statsDClient( diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Trace.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Trace.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/Trace.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/Trace.java index d558e459e9..499234cd83 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/Trace.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Trace.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/TraceConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/TraceConfig.java similarity index 84% rename from features/dd-trace-core/src/main/java/datadog/trace/api/TraceConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/TraceConfig.java index 52370cf695..722669fba5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/TraceConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/TraceConfig.java @@ -1,10 +1,10 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.util.List; import java.util.Map; -import datadog.trace.api.sampling.SamplingRule.SpanSamplingRule; -import datadog.trace.api.sampling.SamplingRule.TraceSamplingRule; +import com.datadog.trace.api.sampling.SamplingRule.SpanSamplingRule; +import com.datadog.trace.api.sampling.SamplingRule.TraceSamplingRule; /** Snapshot of dynamic configuration; valid for the duration of a trace. */ public interface TraceConfig { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/TracePropagationStyle.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/TracePropagationStyle.java index dd6e4b64ec..460edd40de 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/TracePropagationStyle.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/TracePropagationStyle.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; import java.util.Locale; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/Tracer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Tracer.java similarity index 87% rename from features/dd-trace-core/src/main/java/datadog/trace/api/Tracer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/Tracer.java index d46c89f8cc..f98d989d3e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/Tracer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Tracer.java @@ -1,6 +1,6 @@ -package datadog.trace.api; +package com.datadog.trace.api; -import datadog.trace.api.interceptor.TraceInterceptor; +import com.datadog.trace.api.interceptor.TraceInterceptor; /** A class with Datadog tracer features. */ public interface Tracer { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/UserEventTrackingMode.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/UserEventTrackingMode.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/UserEventTrackingMode.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/UserEventTrackingMode.java index cb21c257e0..0f69c4e2ec 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/UserEventTrackingMode.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/UserEventTrackingMode.java @@ -1,4 +1,4 @@ -package datadog.trace.api; +package com.datadog.trace.api; public enum UserEventTrackingMode { DISABLED, diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/WellKnownTags.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/WellKnownTags.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/WellKnownTags.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/WellKnownTags.java index f01e8d154e..b70f691f46 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/WellKnownTags.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/WellKnownTags.java @@ -1,6 +1,6 @@ -package datadog.trace.api; +package com.datadog.trace.api; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; public class WellKnownTags { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/WithGlobalTracer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/WithGlobalTracer.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/api/WithGlobalTracer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/WithGlobalTracer.java index ae6354d5ee..3f91e2076d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/WithGlobalTracer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/WithGlobalTracer.java @@ -1,9 +1,9 @@ -package datadog.trace.api; +package com.datadog.trace.api; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; /** * Internal API for registering callbacks that will execute as soon as there is a global tracer diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/CHMCache.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/CHMCache.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/cache/CHMCache.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/CHMCache.java index 7ac2dd9875..84d532a09c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/CHMCache.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/CHMCache.java @@ -1,4 +1,4 @@ -package datadog.trace.api.cache; +package com.datadog.trace.api.cache; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCache.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/DDCache.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCache.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/DDCache.java index d1cd802484..ba8ef555a4 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCache.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/DDCache.java @@ -1,4 +1,4 @@ -package datadog.trace.api.cache; +package com.datadog.trace.api.cache; import java.util.function.BiConsumer; import java.util.function.Function; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCaches.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/DDCaches.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCaches.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/DDCaches.java index 65d7b2f697..2a9999adda 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDCaches.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/DDCaches.java @@ -1,4 +1,4 @@ -package datadog.trace.api.cache; +package com.datadog.trace.api.cache; import java.util.function.ToIntFunction; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDPartialKeyCache.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/DDPartialKeyCache.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDPartialKeyCache.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/DDPartialKeyCache.java index 68eb730bb7..5bb74a3642 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/DDPartialKeyCache.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/DDPartialKeyCache.java @@ -1,4 +1,4 @@ -package datadog.trace.api.cache; +package com.datadog.trace.api.cache; /** * Cache that can work on parts of a key to look up a value. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeCache.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizeCache.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeCache.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizeCache.java index 98e0822d83..f5729ea95b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeCache.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizeCache.java @@ -1,10 +1,10 @@ -package datadog.trace.api.cache; +package com.datadog.trace.api.cache; import java.util.Arrays; import java.util.function.BiConsumer; import java.util.function.Function; -import datadog.trace.api.Pair; +import com.datadog.trace.api.Pair; /** * This is a fixed size cache that only has one operation computeIfAbsent, that is used diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizePartialKeyCache.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizePartialKeyCache.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizePartialKeyCache.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizePartialKeyCache.java index d10827d87d..422f67317c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizePartialKeyCache.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizePartialKeyCache.java @@ -1,7 +1,7 @@ -package datadog.trace.api.cache; +package com.datadog.trace.api.cache; -import static datadog.trace.api.cache.FixedSizeCache.calculateSize; -import static datadog.trace.api.cache.FixedSizeCache.rehash; +import static com.datadog.trace.api.cache.FixedSizeCache.calculateSize; +import static com.datadog.trace.api.cache.FixedSizeCache.rehash; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeakKeyCache.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizeWeakKeyCache.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeakKeyCache.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizeWeakKeyCache.java index e9b99d204a..ff85da0415 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeakKeyCache.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizeWeakKeyCache.java @@ -1,7 +1,7 @@ -package datadog.trace.api.cache; +package com.datadog.trace.api.cache; -import static datadog.trace.api.cache.FixedSizeCache.calculateSize; -import static datadog.trace.api.cache.FixedSizeCache.rehash; +import static com.datadog.trace.api.cache.FixedSizeCache.calculateSize; +import static com.datadog.trace.api.cache.FixedSizeCache.rehash; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeightedCache.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizeWeightedCache.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeightedCache.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizeWeightedCache.java index 85295b39bb..1f01a994cb 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/FixedSizeWeightedCache.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/FixedSizeWeightedCache.java @@ -1,7 +1,7 @@ -package datadog.trace.api.cache; +package com.datadog.trace.api.cache; -import static datadog.trace.api.cache.FixedSizeCache.calculateSize; -import static datadog.trace.api.cache.FixedSizeCache.rehash; +import static com.datadog.trace.api.cache.FixedSizeCache.calculateSize; +import static com.datadog.trace.api.cache.FixedSizeCache.rehash; import java.util.Arrays; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/RadixTreeCache.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/RadixTreeCache.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/api/cache/RadixTreeCache.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/RadixTreeCache.java index bb9176b422..5b0d391b18 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/cache/RadixTreeCache.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/cache/RadixTreeCache.java @@ -1,9 +1,9 @@ -package datadog.trace.api.cache; +package com.datadog.trace.api.cache; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.function.IntFunction; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; /** Sparse cache of values associated with a small integer */ public final class RadixTreeCache { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIConstants.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/CIConstants.java similarity index 73% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIConstants.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/CIConstants.java index 76cec93abb..97b4a12cba 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/CIConstants.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/CIConstants.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility; +package com.datadog.trace.api.civisibility; public interface CIConstants { String TEST_PASS = "pass"; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTest.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTest.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTest.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTest.java index 978810d237..092cb17263 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTest.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTest.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility; +package com.datadog.trace.api.civisibility; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTestModule.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTestModule.java index d333924753..82a0879849 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTestModule.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility; +package com.datadog.trace.api.civisibility; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSession.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTestSession.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSession.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTestSession.java index f73960e91a..eb5c49a2b7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSession.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTestSession.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility; +package com.datadog.trace.api.civisibility; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSuite.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTestSuite.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSuite.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTestSuite.java index c309c181c6..74abef132b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/DDTestSuite.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/DDTestSuite.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility; +package com.datadog.trace.api.civisibility; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/InstrumentationBridge.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/InstrumentationBridge.java similarity index 84% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/InstrumentationBridge.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/InstrumentationBridge.java index 79fbbdb282..31b4db9024 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/InstrumentationBridge.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/InstrumentationBridge.java @@ -1,7 +1,7 @@ -package datadog.trace.api.civisibility; +package com.datadog.trace.api.civisibility; -import datadog.trace.api.civisibility.events.BuildEventsHandler; -import datadog.trace.api.civisibility.events.TestEventsHandler; +import com.datadog.trace.api.civisibility.events.BuildEventsHandler; +import com.datadog.trace.api.civisibility.events.TestEventsHandler; public abstract class InstrumentationBridge { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/Configurations.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/config/Configurations.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/Configurations.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/config/Configurations.java index 529598236d..f96c979f89 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/Configurations.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/config/Configurations.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.config; +package com.datadog.trace.api.civisibility.config; import java.util.Map; import java.util.Objects; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java index 31d8a2a095..68c8c413ec 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/config/ModuleExecutionSettings.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.config; +package com.datadog.trace.api.civisibility.config; import java.util.Collection; import java.util.Collections; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/TestIdentifier.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/config/TestIdentifier.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/TestIdentifier.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/config/TestIdentifier.java index 678e13998d..7711c801fd 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/config/TestIdentifier.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/config/TestIdentifier.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.config; +package com.datadog.trace.api.civisibility.config; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageBridge.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/CoverageBridge.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageBridge.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/CoverageBridge.java index 49b28ab2fc..9a50744d8c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageBridge.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/CoverageBridge.java @@ -1,10 +1,10 @@ -package datadog.trace.api.civisibility.coverage; +package com.datadog.trace.api.civisibility.coverage; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan; +import static com.datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan; -import datadog.trace.api.gateway.RequestContext; -import datadog.trace.api.gateway.RequestContextSlot; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.gateway.RequestContextSlot; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; public abstract class CoverageBridge { /* diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java similarity index 52% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java index a3909674ee..d78d9c4be9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/CoverageDataSupplier.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.coverage; +package com.datadog.trace.api.civisibility.coverage; public interface CoverageDataSupplier { byte[] get(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java similarity index 87% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java index bc181d62a7..60a7a6d9e1 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/CoverageProbeStore.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.coverage; +package com.datadog.trace.api.civisibility.coverage; public interface CoverageProbeStore extends TestReportHolder { void record(Class clazz); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReport.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/TestReport.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReport.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/TestReport.java index cbe187f2bc..8e58a71db5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReport.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/TestReport.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.coverage; +package com.datadog.trace.api.civisibility.coverage; import java.util.Collection; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java index 3f2002d8a4..a108054980 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/TestReportFileEntry.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.coverage; +package com.datadog.trace.api.civisibility.coverage; import java.util.Collection; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportHolder.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/TestReportHolder.java similarity index 68% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportHolder.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/TestReportHolder.java index 489d594b79..d9996d6f32 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/coverage/TestReportHolder.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/coverage/TestReportHolder.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.coverage; +package com.datadog.trace.api.civisibility.coverage; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/BuildEventsHandler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/events/BuildEventsHandler.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/BuildEventsHandler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/events/BuildEventsHandler.java index 46a0287f6a..eb2e92d394 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/BuildEventsHandler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/events/BuildEventsHandler.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.events; +package com.datadog.trace.api.civisibility.events; import androidx.annotation.Nullable; @@ -7,7 +7,7 @@ import java.util.Collection; import java.util.Map; -import datadog.trace.api.civisibility.config.ModuleExecutionSettings; +import com.datadog.trace.api.civisibility.config.ModuleExecutionSettings; public interface BuildEventsHandler { void onTestSessionStart( diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/TestEventsHandler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/events/TestEventsHandler.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/TestEventsHandler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/events/TestEventsHandler.java index 01c62411de..441aaba28c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/events/TestEventsHandler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/events/TestEventsHandler.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.events; +package com.datadog.trace.api.civisibility.events; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -7,8 +7,8 @@ import java.lang.reflect.Method; import java.util.Collection; -import datadog.trace.api.civisibility.config.TestIdentifier; -import datadog.trace.api.civisibility.retry.TestRetryPolicy; +import com.datadog.trace.api.civisibility.config.TestIdentifier; +import com.datadog.trace.api.civisibility.retry.TestRetryPolicy; public interface TestEventsHandler extends Closeable { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTest.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTest.java similarity index 80% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTest.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTest.java index 97bc6ef428..08cab2c856 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTest.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTest.java @@ -1,8 +1,8 @@ -package datadog.trace.api.civisibility.noop; +package com.datadog.trace.api.civisibility.noop; import androidx.annotation.Nullable; -import datadog.trace.api.civisibility.DDTest; +import com.datadog.trace.api.civisibility.DDTest; public class NoOpDDTest implements DDTest { static final DDTest INSTANCE = new NoOpDDTest(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java similarity index 79% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java index f5f98b635b..0c19eb453b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTestModule.java @@ -1,9 +1,9 @@ -package datadog.trace.api.civisibility.noop; +package com.datadog.trace.api.civisibility.noop; import androidx.annotation.Nullable; -import datadog.trace.api.civisibility.DDTestModule; -import datadog.trace.api.civisibility.DDTestSuite; +import com.datadog.trace.api.civisibility.DDTestModule; +import com.datadog.trace.api.civisibility.DDTestSuite; public class NoOpDDTestModule implements DDTestModule { static final DDTestModule INSTANCE = new NoOpDDTestModule(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java similarity index 77% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java index b2f85f969f..e0e100ddb0 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTestSession.java @@ -1,9 +1,9 @@ -package datadog.trace.api.civisibility.noop; +package com.datadog.trace.api.civisibility.noop; import androidx.annotation.Nullable; -import datadog.trace.api.civisibility.DDTestModule; -import datadog.trace.api.civisibility.DDTestSession; +import com.datadog.trace.api.civisibility.DDTestModule; +import com.datadog.trace.api.civisibility.DDTestSession; public class NoOpDDTestSession implements DDTestSession { public static final DDTestSession INSTANCE = new NoOpDDTestSession(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java similarity index 79% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java index 7d87e5d17c..5a46f4da75 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/noop/NoOpDDTestSuite.java @@ -1,11 +1,11 @@ -package datadog.trace.api.civisibility.noop; +package com.datadog.trace.api.civisibility.noop; import androidx.annotation.Nullable; import java.lang.reflect.Method; -import datadog.trace.api.civisibility.DDTest; -import datadog.trace.api.civisibility.DDTestSuite; +import com.datadog.trace.api.civisibility.DDTest; +import com.datadog.trace.api.civisibility.DDTestSuite; public class NoOpDDTestSuite implements DDTestSuite { static final DDTestSuite INSTANCE = new NoOpDDTestSuite(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/retry/TestRetryPolicy.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/retry/TestRetryPolicy.java similarity index 67% rename from features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/retry/TestRetryPolicy.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/retry/TestRetryPolicy.java index 465cae3891..32e2318050 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/civisibility/retry/TestRetryPolicy.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/civisibility/retry/TestRetryPolicy.java @@ -1,4 +1,4 @@ -package datadog.trace.api.civisibility.retry; +package com.datadog.trace.api.civisibility.retry; public interface TestRetryPolicy { boolean retryPossible(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/AppSecConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/AppSecConfig.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/AppSecConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/AppSecConfig.java index c68380f613..f7253c855b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/AppSecConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/AppSecConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; /** Constant with names of configuration options for appsec. */ public final class AppSecConfig { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/CiVisibilityConfig.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/CiVisibilityConfig.java index 3982885359..ddc2c31c22 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/CiVisibilityConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; /** Constant with names of configuration options for CI visibility. */ public final class CiVisibilityConfig { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/CrashTrackingConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/CrashTrackingConfig.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/CrashTrackingConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/CrashTrackingConfig.java index 85b593c0c8..03f86f5d27 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/CrashTrackingConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/CrashTrackingConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; /** * These config options will only work with dd-java-agent, not with dd-trace-ot. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/CwsConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/CwsConfig.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/CwsConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/CwsConfig.java index d65db69252..cb06cb54bc 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/CwsConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/CwsConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; public final class CwsConfig { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/DebuggerConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/DebuggerConfig.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/DebuggerConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/DebuggerConfig.java index 4d81b8c5f7..9ab0559ef5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/DebuggerConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/DebuggerConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; public final class DebuggerConfig { public static final String DEBUGGER_ENABLED = "dynamic.instrumentation.enabled"; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/GeneralConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/GeneralConfig.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/GeneralConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/GeneralConfig.java index d53b41fdb1..ff486c36a7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/GeneralConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/GeneralConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; /** * A list of keys to be used in a Properties instance with dd-trace-ot's DDTracer as follows: diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/IastConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/IastConfig.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/IastConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/IastConfig.java index e70a42becc..4b2e81c0f3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/IastConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/IastConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; /** Constant with names of configuration options for IAST. */ public final class IastConfig { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/JmxFetchConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/JmxFetchConfig.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/JmxFetchConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/JmxFetchConfig.java index 6d2642f6db..4472531b9a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/JmxFetchConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/JmxFetchConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; /** * These config options will only work with dd-java-agent, not with dd-trace-ot. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/ProfilingConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/ProfilingConfig.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/ProfilingConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/ProfilingConfig.java index ca1dd823d5..960f78d64a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/ProfilingConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/ProfilingConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; /** * These config options will only work with dd-java-agent, not with dd-trace-ot. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/RemoteConfigConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/RemoteConfigConfig.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/RemoteConfigConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/RemoteConfigConfig.java index 32c9251831..1ba8aa60c2 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/RemoteConfigConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/RemoteConfigConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; public class RemoteConfigConfig { public static final String REMOTE_CONFIG_ENABLED = "remote_config.enabled"; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/TraceInstrumentationConfig.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/TraceInstrumentationConfig.java index 3833509a78..bc9cec0ef2 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/TraceInstrumentationConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; /** * These config options will only work with dd-java-agent, not with dd-trace-ot. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/TracerConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/TracerConfig.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/TracerConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/TracerConfig.java index d48178d857..0e0b7b0e53 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/TracerConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/TracerConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; /** * A list of keys to be used in a Properties instance with dd-trace-ot's DDTracer as follows: diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/config/UsmConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/UsmConfig.java similarity index 82% rename from features/dd-trace-core/src/main/java/datadog/trace/api/config/UsmConfig.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/config/UsmConfig.java index c84b832a1f..f46a062d56 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/config/UsmConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/config/UsmConfig.java @@ -1,4 +1,4 @@ -package datadog.trace.api.config; +package com.datadog.trace.api.config; /** Constant with names of configuration options for USM. */ public final class UsmConfig { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/env/CapturedEnvironment.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/env/CapturedEnvironment.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/env/CapturedEnvironment.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/env/CapturedEnvironment.java index d1f3fc7694..1638415831 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/env/CapturedEnvironment.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/env/CapturedEnvironment.java @@ -1,10 +1,10 @@ -package datadog.trace.api.env; +package com.datadog.trace.api.env; import java.io.File; import java.util.HashMap; import java.util.Map; -import datadog.trace.api.config.GeneralConfig; +import com.datadog.trace.api.config.GeneralConfig; /** * The {@code CapturedEnvironment} instance keeps those {@code Config} values which are platform diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsCheckpointer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/experimental/DataStreamsCheckpointer.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsCheckpointer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/experimental/DataStreamsCheckpointer.java index 574b9fdb2a..b6a06a2299 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsCheckpointer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/experimental/DataStreamsCheckpointer.java @@ -1,8 +1,8 @@ -package datadog.trace.api.experimental; +package com.datadog.trace.api.experimental; -import datadog.trace.api.GlobalTracer; -import datadog.trace.api.Tracer; -import datadog.trace.api.internal.InternalTracer; +import com.datadog.trace.api.GlobalTracer; +import com.datadog.trace.api.Tracer; +import com.datadog.trace.api.internal.InternalTracer; /** An interface to Data Streams checkpointer, allowing passing the context manually. */ public interface DataStreamsCheckpointer { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsContextCarrier.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/experimental/DataStreamsContextCarrier.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsContextCarrier.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/experimental/DataStreamsContextCarrier.java index 2d83b071a5..2111843b4a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/experimental/DataStreamsContextCarrier.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/experimental/DataStreamsContextCarrier.java @@ -1,4 +1,4 @@ -package datadog.trace.api.experimental; +package com.datadog.trace.api.experimental; import java.util.Collections; import java.util.Map.Entry; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/flare/TracerFlare.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/flare/TracerFlare.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/flare/TracerFlare.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/flare/TracerFlare.java index f2ba39041a..e53c3818bf 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/flare/TracerFlare.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/flare/TracerFlare.java @@ -1,4 +1,4 @@ -package datadog.trace.api.flare; +package com.datadog.trace.api.flare; import static java.nio.charset.StandardCharsets.UTF_8; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/function/TriConsumer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/function/TriConsumer.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/api/function/TriConsumer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/function/TriConsumer.java index 10abca7b64..3719f4d941 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/function/TriConsumer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/function/TriConsumer.java @@ -1,4 +1,4 @@ -package datadog.trace.api.function; +package com.datadog.trace.api.function; public interface TriConsumer { void accept(S s, T t, U u); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/function/TriFunction.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/function/TriFunction.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/api/function/TriFunction.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/function/TriFunction.java index 438793e712..5d25bc5ec7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/function/TriFunction.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/function/TriFunction.java @@ -1,4 +1,4 @@ -package datadog.trace.api.function; +package com.datadog.trace.api.function; public interface TriFunction { R apply(T t, U u, V v); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/BlockResponseFunction.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/BlockResponseFunction.java similarity index 74% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/BlockResponseFunction.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/BlockResponseFunction.java index f3b8f7875c..a01d54a3f0 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/BlockResponseFunction.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/BlockResponseFunction.java @@ -1,9 +1,9 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; import java.util.Map; -import datadog.trace.appsec.api.blocking.BlockingContentType; -import datadog.trace.api.internal.TraceSegment; +import com.datadog.trace.appsec.api.blocking.BlockingContentType; +import com.datadog.trace.api.internal.TraceSegment; public interface BlockResponseFunction { /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/CallbackProvider.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/CallbackProvider.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/CallbackProvider.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/CallbackProvider.java index e4f07f963d..e8767f8b44 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/CallbackProvider.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/CallbackProvider.java @@ -1,4 +1,4 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; /** The API used by the producers to retrieve callbacks. */ public interface CallbackProvider { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/EventType.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/EventType.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/EventType.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/EventType.java index a14d2b5616..e8f1e5e9a9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/EventType.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/EventType.java @@ -1,4 +1,4 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; /** * The {@code EventType} is a unique identifier for an event. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Events.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/Events.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Events.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/Events.java index 13c32706d1..5ce8892012 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Events.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/Events.java @@ -1,4 +1,4 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -6,10 +6,10 @@ import java.util.function.Function; import java.util.function.Supplier; -import datadog.trace.api.function.TriConsumer; -import datadog.trace.api.function.TriFunction; -import datadog.trace.api.http.StoredBodySupplier; -import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; +import com.datadog.trace.api.function.TriConsumer; +import com.datadog.trace.api.function.TriFunction; +import com.datadog.trace.api.http.StoredBodySupplier; +import com.datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; /** All known {@code EventType} that the {@code InstrumentationGateway} can handle. */ public final class Events { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Flow.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/Flow.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Flow.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/Flow.java index 6286dd6852..443ca1ab48 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Flow.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/Flow.java @@ -1,9 +1,9 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; import java.util.Collections; import java.util.Map; -import datadog.trace.appsec.api.blocking.BlockingContentType; +import com.datadog.trace.appsec.api.blocking.BlockingContentType; /** * The result of sending an event to a callback. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/IGSpanInfo.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/IGSpanInfo.java similarity index 69% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/IGSpanInfo.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/IGSpanInfo.java index fdfe55d6f8..dd9cf46076 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/IGSpanInfo.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/IGSpanInfo.java @@ -1,9 +1,9 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; import java.util.Map; -import datadog.trace.api.DDTraceId; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; public interface IGSpanInfo { DDTraceId getTraceId(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/InstrumentationGateway.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/InstrumentationGateway.java index 6df40dd685..507b0e15de 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/InstrumentationGateway.java @@ -1,21 +1,21 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; -import static datadog.trace.api.gateway.Events.GRPC_SERVER_REQUEST_MESSAGE_ID; -import static datadog.trace.api.gateway.Events.MAX_EVENTS; -import static datadog.trace.api.gateway.Events.REQUEST_BODY_CONVERTED_ID; -import static datadog.trace.api.gateway.Events.REQUEST_BODY_DONE_ID; -import static datadog.trace.api.gateway.Events.REQUEST_BODY_START_ID; -import static datadog.trace.api.gateway.Events.REQUEST_CLIENT_SOCKET_ADDRESS_ID; -import static datadog.trace.api.gateway.Events.REQUEST_ENDED_ID; -import static datadog.trace.api.gateway.Events.REQUEST_HEADER_DONE_ID; -import static datadog.trace.api.gateway.Events.REQUEST_HEADER_ID; -import static datadog.trace.api.gateway.Events.REQUEST_INFERRED_CLIENT_ADDRESS_ID; -import static datadog.trace.api.gateway.Events.REQUEST_METHOD_URI_RAW_ID; -import static datadog.trace.api.gateway.Events.REQUEST_PATH_PARAMS_ID; -import static datadog.trace.api.gateway.Events.REQUEST_STARTED_ID; -import static datadog.trace.api.gateway.Events.RESPONSE_HEADER_DONE_ID; -import static datadog.trace.api.gateway.Events.RESPONSE_HEADER_ID; -import static datadog.trace.api.gateway.Events.RESPONSE_STARTED_ID; +import static com.datadog.trace.api.gateway.Events.GRPC_SERVER_REQUEST_MESSAGE_ID; +import static com.datadog.trace.api.gateway.Events.MAX_EVENTS; +import static com.datadog.trace.api.gateway.Events.REQUEST_BODY_CONVERTED_ID; +import static com.datadog.trace.api.gateway.Events.REQUEST_BODY_DONE_ID; +import static com.datadog.trace.api.gateway.Events.REQUEST_BODY_START_ID; +import static com.datadog.trace.api.gateway.Events.REQUEST_CLIENT_SOCKET_ADDRESS_ID; +import static com.datadog.trace.api.gateway.Events.REQUEST_ENDED_ID; +import static com.datadog.trace.api.gateway.Events.REQUEST_HEADER_DONE_ID; +import static com.datadog.trace.api.gateway.Events.REQUEST_HEADER_ID; +import static com.datadog.trace.api.gateway.Events.REQUEST_INFERRED_CLIENT_ADDRESS_ID; +import static com.datadog.trace.api.gateway.Events.REQUEST_METHOD_URI_RAW_ID; +import static com.datadog.trace.api.gateway.Events.REQUEST_PATH_PARAMS_ID; +import static com.datadog.trace.api.gateway.Events.REQUEST_STARTED_ID; +import static com.datadog.trace.api.gateway.Events.RESPONSE_HEADER_DONE_ID; +import static com.datadog.trace.api.gateway.Events.RESPONSE_HEADER_ID; +import static com.datadog.trace.api.gateway.Events.RESPONSE_STARTED_ID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,10 +26,10 @@ import java.util.function.Function; import java.util.function.Supplier; -import datadog.trace.api.function.TriConsumer; -import datadog.trace.api.function.TriFunction; -import datadog.trace.api.http.StoredBodySupplier; -import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; +import com.datadog.trace.api.function.TriConsumer; +import com.datadog.trace.api.function.TriFunction; +import com.datadog.trace.api.http.StoredBodySupplier; +import com.datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; /** The implementation of the {@code CallbackProvider} and {@code SubscriptionService}. */ public class InstrumentationGateway { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/RequestContext.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/RequestContext.java index eaa442ed9c..3d4ca1f075 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/RequestContext.java @@ -1,9 +1,9 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; import java.io.Closeable; import java.io.IOException; -import datadog.trace.api.internal.TraceSegment; +import com.datadog.trace.api.internal.TraceSegment; /** * This is the context that will travel along with the request and be presented to the diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContextSlot.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/RequestContextSlot.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContextSlot.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/RequestContextSlot.java index 9b1ebbf106..b2f8e40e37 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/RequestContextSlot.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/RequestContextSlot.java @@ -1,4 +1,4 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; public enum RequestContextSlot { APPSEC, diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Subscription.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/Subscription.java similarity index 88% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Subscription.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/Subscription.java index dae58bf74d..a18a28094d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/Subscription.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/Subscription.java @@ -1,4 +1,4 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; /** A handle to the started subscription of an event. */ public interface Subscription { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/SubscriptionService.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/SubscriptionService.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/api/gateway/SubscriptionService.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/SubscriptionService.java index 48448135af..05c9daf71a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/gateway/SubscriptionService.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/SubscriptionService.java @@ -1,4 +1,4 @@ -package datadog.trace.api.gateway; +package com.datadog.trace.api.gateway; /** The API used by the consumers to register callbacks. */ public interface SubscriptionService { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodyFactories.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredBodyFactories.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodyFactories.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredBodyFactories.java index 5163373b16..a9208a7e27 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodyFactories.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredBodyFactories.java @@ -1,17 +1,17 @@ -package datadog.trace.api.http; +package com.datadog.trace.api.http; -import static datadog.trace.api.gateway.Events.EVENTS; +import static com.datadog.trace.api.gateway.Events.EVENTS; import java.nio.charset.Charset; import java.util.function.BiFunction; import java.util.function.Supplier; -import datadog.trace.api.gateway.CallbackProvider; -import datadog.trace.api.gateway.Flow; -import datadog.trace.api.gateway.RequestContext; -import datadog.trace.api.gateway.RequestContextSlot; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import com.datadog.trace.api.gateway.CallbackProvider; +import com.datadog.trace.api.gateway.Flow; +import com.datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.gateway.RequestContextSlot; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer; public class StoredBodyFactories { private StoredBodyFactories() {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodySupplier.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredBodySupplier.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodySupplier.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredBodySupplier.java index 52d3ee6fbc..9b36690032 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredBodySupplier.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredBodySupplier.java @@ -1,4 +1,4 @@ -package datadog.trace.api.http; +package com.datadog.trace.api.http; import androidx.annotation.NonNull; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredByteBody.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredByteBody.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredByteBody.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredByteBody.java index 7ac0e09ca1..642e5b0c3e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredByteBody.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredByteBody.java @@ -1,4 +1,4 @@ -package datadog.trace.api.http; +package com.datadog.trace.api.http; import androidx.annotation.Nullable; @@ -17,8 +17,8 @@ import java.nio.charset.StandardCharsets; import java.util.function.BiFunction; -import datadog.trace.api.gateway.Flow; -import datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.gateway.Flow; +import com.datadog.trace.api.gateway.RequestContext; /** @see StoredCharBody */ public class StoredByteBody implements StoredBodySupplier { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredCharBody.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredCharBody.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredCharBody.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredCharBody.java index c89b0f802e..1dbae3019f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/http/StoredCharBody.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredCharBody.java @@ -1,4 +1,4 @@ -package datadog.trace.api.http; +package com.datadog.trace.api.http; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -7,10 +7,10 @@ import java.util.Arrays; import java.util.function.BiFunction; -import datadog.trace.appsec.api.blocking.BlockingException; -import datadog.trace.api.gateway.BlockResponseFunction; -import datadog.trace.api.gateway.Flow; -import datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.appsec.api.blocking.BlockingException; +import com.datadog.trace.api.gateway.BlockResponseFunction; +import com.datadog.trace.api.gateway.Flow; +import com.datadog.trace.api.gateway.RequestContext; /** Analogous to {@link StoredByteBody}, but Java doesn't support generics with scalar types. */ public class StoredCharBody implements StoredBodySupplier { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastCallSites.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastCallSites.java similarity index 72% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastCallSites.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastCallSites.java index 322e3cfb51..47ca91092f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastCallSites.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastCallSites.java @@ -1,6 +1,6 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; -import datadog.trace.api.iast.telemetry.Verbosity; +import com.datadog.trace.api.iast.telemetry.Verbosity; /** * Interface used to mark advice implementations using @CallSite so they are instrumented by diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastContext.java similarity index 77% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastContext.java index a360a07acb..26cc0806af 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastContext.java @@ -1,11 +1,11 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; import androidx.annotation.Nullable; -import datadog.trace.api.gateway.RequestContext; -import datadog.trace.api.gateway.RequestContextSlot; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import com.datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.gateway.RequestContextSlot; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer; /** * Initial encapsulation of the IAST context to be able to isolate it from the request. Ideally we diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastDetectionMode.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastDetectionMode.java similarity index 70% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastDetectionMode.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastDetectionMode.java index 570f0320dd..cbe1cd9679 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastDetectionMode.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastDetectionMode.java @@ -1,19 +1,19 @@ -package datadog.trace.api.iast; - -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_DEDUPLICATION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_MAX_CONCURRENT_REQUESTS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_MAX_RANGE_COUNT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_REQUEST_SAMPLING; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_VULNERABILITIES_PER_REQUEST; -import static datadog.trace.api.config.IastConfig.IAST_DEDUPLICATION_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_MAX_CONCURRENT_REQUESTS; -import static datadog.trace.api.config.IastConfig.IAST_MAX_RANGE_COUNT; -import static datadog.trace.api.config.IastConfig.IAST_REQUEST_SAMPLING; -import static datadog.trace.api.config.IastConfig.IAST_VULNERABILITIES_PER_REQUEST; +package com.datadog.trace.api.iast; + +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_IAST_DEDUPLICATION_ENABLED; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_IAST_MAX_CONCURRENT_REQUESTS; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_IAST_MAX_RANGE_COUNT; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_IAST_REQUEST_SAMPLING; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_IAST_VULNERABILITIES_PER_REQUEST; +import static com.datadog.trace.api.config.IastConfig.IAST_DEDUPLICATION_ENABLED; +import static com.datadog.trace.api.config.IastConfig.IAST_MAX_CONCURRENT_REQUESTS; +import static com.datadog.trace.api.config.IastConfig.IAST_MAX_RANGE_COUNT; +import static com.datadog.trace.api.config.IastConfig.IAST_REQUEST_SAMPLING; +import static com.datadog.trace.api.config.IastConfig.IAST_VULNERABILITIES_PER_REQUEST; import androidx.annotation.NonNull; -import datadog.trace.bootstrap.config.provider.ConfigProvider; +import com.datadog.trace.bootstrap.config.provider.ConfigProvider; public enum IastDetectionMode { FULL { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastEnabledChecks.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastEnabledChecks.java similarity index 88% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastEnabledChecks.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastEnabledChecks.java index 5a6daab420..1a30fc911c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastEnabledChecks.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastEnabledChecks.java @@ -1,9 +1,9 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import datadog.trace.api.Platform; +import com.datadog.trace.api.Platform; public abstract class IastEnabledChecks { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastModule.java similarity index 88% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastModule.java index 33d014b963..baa63cb531 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/IastModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastModule.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/InstrumentationBridge.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/InstrumentationBridge.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/InstrumentationBridge.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/InstrumentationBridge.java index 78a9bade1e..1cb363550c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/InstrumentationBridge.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/InstrumentationBridge.java @@ -1,29 +1,29 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; -import datadog.trace.api.iast.propagation.CodecModule; -import datadog.trace.api.iast.propagation.PropagationModule; -import datadog.trace.api.iast.propagation.StringModule; -import datadog.trace.api.iast.sink.ApplicationModule; -import datadog.trace.api.iast.sink.CommandInjectionModule; -import datadog.trace.api.iast.sink.HeaderInjectionModule; -import datadog.trace.api.iast.sink.HstsMissingHeaderModule; -import datadog.trace.api.iast.sink.HttpResponseHeaderModule; -import datadog.trace.api.iast.sink.InsecureCookieModule; -import datadog.trace.api.iast.sink.LdapInjectionModule; -import datadog.trace.api.iast.sink.NoHttpOnlyCookieModule; -import datadog.trace.api.iast.sink.NoSameSiteCookieModule; -import datadog.trace.api.iast.sink.PathTraversalModule; -import datadog.trace.api.iast.sink.SqlInjectionModule; -import datadog.trace.api.iast.sink.SsrfModule; -import datadog.trace.api.iast.sink.StacktraceLeakModule; -import datadog.trace.api.iast.sink.TrustBoundaryViolationModule; -import datadog.trace.api.iast.sink.UnvalidatedRedirectModule; -import datadog.trace.api.iast.sink.WeakCipherModule; -import datadog.trace.api.iast.sink.WeakHashModule; -import datadog.trace.api.iast.sink.WeakRandomnessModule; -import datadog.trace.api.iast.sink.XContentTypeModule; -import datadog.trace.api.iast.sink.XPathInjectionModule; -import datadog.trace.api.iast.sink.XssModule; +import com.datadog.trace.api.iast.propagation.CodecModule; +import com.datadog.trace.api.iast.propagation.PropagationModule; +import com.datadog.trace.api.iast.propagation.StringModule; +import com.datadog.trace.api.iast.sink.ApplicationModule; +import com.datadog.trace.api.iast.sink.CommandInjectionModule; +import com.datadog.trace.api.iast.sink.HeaderInjectionModule; +import com.datadog.trace.api.iast.sink.HstsMissingHeaderModule; +import com.datadog.trace.api.iast.sink.HttpResponseHeaderModule; +import com.datadog.trace.api.iast.sink.InsecureCookieModule; +import com.datadog.trace.api.iast.sink.LdapInjectionModule; +import com.datadog.trace.api.iast.sink.NoHttpOnlyCookieModule; +import com.datadog.trace.api.iast.sink.NoSameSiteCookieModule; +import com.datadog.trace.api.iast.sink.PathTraversalModule; +import com.datadog.trace.api.iast.sink.SqlInjectionModule; +import com.datadog.trace.api.iast.sink.SsrfModule; +import com.datadog.trace.api.iast.sink.StacktraceLeakModule; +import com.datadog.trace.api.iast.sink.TrustBoundaryViolationModule; +import com.datadog.trace.api.iast.sink.UnvalidatedRedirectModule; +import com.datadog.trace.api.iast.sink.WeakCipherModule; +import com.datadog.trace.api.iast.sink.WeakHashModule; +import com.datadog.trace.api.iast.sink.WeakRandomnessModule; +import com.datadog.trace.api.iast.sink.XContentTypeModule; +import com.datadog.trace.api.iast.sink.XPathInjectionModule; +import com.datadog.trace.api.iast.sink.XssModule; /** Bridge between instrumentations and {@link IastModule} instances. */ public abstract class InstrumentationBridge { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Propagation.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Propagation.java similarity index 88% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/Propagation.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Propagation.java index 8ca392f76a..4fc935971a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Propagation.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Propagation.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Sink.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Sink.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/Sink.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Sink.java index c7e53d20e8..a40d8bf63f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Sink.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Sink.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Source.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Source.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/Source.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Source.java index 0cf222b59e..7015f10fa5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Source.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Source.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/SourceTypes.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/SourceTypes.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/SourceTypes.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/SourceTypes.java index cd6f9a0d05..6b782220b9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/SourceTypes.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/SourceTypes.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; public abstract class SourceTypes { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Taintable.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Taintable.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/Taintable.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Taintable.java index c42b8ddd90..7583a0b1b6 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/Taintable.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Taintable.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityMarks.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/VulnerabilityMarks.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityMarks.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/VulnerabilityMarks.java index ab39b1f429..1075d4e807 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityMarks.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/VulnerabilityMarks.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; public class VulnerabilityMarks { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityTypes.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/VulnerabilityTypes.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityTypes.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/VulnerabilityTypes.java index af2d67d86b..bb7b182afa 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/VulnerabilityTypes.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/VulnerabilityTypes.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast; +package com.datadog.trace.api.iast; public abstract class VulnerabilityTypes { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/CodecModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/propagation/CodecModule.java similarity index 85% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/CodecModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/propagation/CodecModule.java index 07c637a5e4..661ed17275 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/CodecModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/propagation/CodecModule.java @@ -1,9 +1,9 @@ -package datadog.trace.api.iast.propagation; +package com.datadog.trace.api.iast.propagation; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface CodecModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/PropagationModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/propagation/PropagationModule.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/PropagationModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/propagation/PropagationModule.java index 7ad06418af..c6476deeb7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/PropagationModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/propagation/PropagationModule.java @@ -1,12 +1,12 @@ -package datadog.trace.api.iast.propagation; +package com.datadog.trace.api.iast.propagation; import androidx.annotation.Nullable; import java.util.function.Predicate; -import datadog.trace.api.iast.IastContext; -import datadog.trace.api.iast.IastModule; -import datadog.trace.api.iast.Taintable.Source; +import com.datadog.trace.api.iast.IastContext; +import com.datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.Taintable.Source; /** Main API for propagation of tainted values, */ @SuppressWarnings("unused") diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/StringModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/propagation/StringModule.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/StringModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/propagation/StringModule.java index 34b35f7923..93f3b60b8c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/propagation/StringModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/propagation/StringModule.java @@ -1,11 +1,11 @@ -package datadog.trace.api.iast.propagation; +package com.datadog.trace.api.iast.propagation; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.util.Locale; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface StringModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/ApplicationModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/ApplicationModule.java similarity index 62% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/ApplicationModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/ApplicationModule.java index f52917cbc1..a1947e40bf 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/ApplicationModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/ApplicationModule.java @@ -1,8 +1,8 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.Nullable; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface ApplicationModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/CommandInjectionModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/CommandInjectionModule.java similarity index 80% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/CommandInjectionModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/CommandInjectionModule.java index cd7ca150bc..0e6dfe24af 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/CommandInjectionModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/CommandInjectionModule.java @@ -1,11 +1,11 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.util.List; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface CommandInjectionModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HeaderInjectionModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HeaderInjectionModule.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HeaderInjectionModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HeaderInjectionModule.java index e4a0bc5372..54a0b6ac7a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HeaderInjectionModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HeaderInjectionModule.java @@ -1,8 +1,8 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface HeaderInjectionModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java index bdd1e17bfb..a637716af1 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HstsMissingHeaderModule.java @@ -1,3 +1,3 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; public interface HstsMissingHeaderModule extends HttpRequestEndModule {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpCookieModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HttpCookieModule.java similarity index 55% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpCookieModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HttpCookieModule.java index 6783ae36a1..800459a0db 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpCookieModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HttpCookieModule.java @@ -1,9 +1,9 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; -import datadog.trace.api.iast.IastModule; -import datadog.trace.api.iast.util.Cookie; +import com.datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.util.Cookie; public interface HttpCookieModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpRequestEndModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HttpRequestEndModule.java similarity index 87% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpRequestEndModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HttpRequestEndModule.java index f6cc6415f2..0be4823886 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpRequestEndModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HttpRequestEndModule.java @@ -1,10 +1,10 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import java.net.HttpURLConnection; import java.util.Locale; -import datadog.trace.api.gateway.IGSpanInfo; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.gateway.IGSpanInfo; +import com.datadog.trace.api.iast.IastModule; public interface HttpRequestEndModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java similarity index 59% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java index 0a8a0b46bf..1e11ef4af3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/HttpResponseHeaderModule.java @@ -1,9 +1,9 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; -import datadog.trace.api.iast.IastModule; -import datadog.trace.api.iast.util.Cookie; +import com.datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.util.Cookie; public interface HttpResponseHeaderModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/InsecureCookieModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/InsecureCookieModule.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/InsecureCookieModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/InsecureCookieModule.java index ed95b38451..90d1c8dd21 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/InsecureCookieModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/InsecureCookieModule.java @@ -1,3 +1,3 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; public interface InsecureCookieModule extends HttpCookieModule {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/LdapInjectionModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/LdapInjectionModule.java similarity index 74% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/LdapInjectionModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/LdapInjectionModule.java index b7b671fc97..72119bea3f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/LdapInjectionModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/LdapInjectionModule.java @@ -1,9 +1,9 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface LdapInjectionModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java index c05e81c45d..433ba4c993 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/NoHttpOnlyCookieModule.java @@ -1,3 +1,3 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; public interface NoHttpOnlyCookieModule extends HttpCookieModule {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java index 25c2b4d34f..aaa288e9af 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/NoSameSiteCookieModule.java @@ -1,3 +1,3 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; public interface NoSameSiteCookieModule extends HttpCookieModule {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/PathTraversalModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/PathTraversalModule.java similarity index 84% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/PathTraversalModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/PathTraversalModule.java index 211e379f2b..11a6f8b636 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/PathTraversalModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/PathTraversalModule.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -6,7 +6,7 @@ import java.io.File; import java.net.URI; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface PathTraversalModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SqlInjectionModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/SqlInjectionModule.java similarity index 74% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SqlInjectionModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/SqlInjectionModule.java index 2dd7f9c11d..b93ee72a40 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SqlInjectionModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/SqlInjectionModule.java @@ -1,8 +1,8 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.Nullable; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface SqlInjectionModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SsrfModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/SsrfModule.java similarity index 72% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SsrfModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/SsrfModule.java index 827afad1ff..8a7be090be 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/SsrfModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/SsrfModule.java @@ -1,8 +1,8 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.Nullable; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface SsrfModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/StacktraceLeakModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/StacktraceLeakModule.java similarity index 72% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/StacktraceLeakModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/StacktraceLeakModule.java index 65a86225ab..60352e5b34 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/StacktraceLeakModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/StacktraceLeakModule.java @@ -1,8 +1,8 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.Nullable; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface StacktraceLeakModule extends IastModule { void onStacktraceLeak( diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java similarity index 65% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java index 0a494eeb1d..6897805022 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/TrustBoundaryViolationModule.java @@ -1,8 +1,8 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface TrustBoundaryViolationModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java similarity index 81% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java index acdaec6a40..739400ac63 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/UnvalidatedRedirectModule.java @@ -1,11 +1,11 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.net.URI; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface UnvalidatedRedirectModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakCipherModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/WeakCipherModule.java similarity index 63% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakCipherModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/WeakCipherModule.java index 23d629a3c7..2a83677bd5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakCipherModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/WeakCipherModule.java @@ -1,8 +1,8 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface WeakCipherModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakHashModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/WeakHashModule.java similarity index 63% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakHashModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/WeakHashModule.java index de3c1b89a2..b80e0cf46f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakHashModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/WeakHashModule.java @@ -1,8 +1,8 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface WeakHashModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakRandomnessModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/WeakRandomnessModule.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakRandomnessModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/WeakRandomnessModule.java index 383cdc1e9b..dc64199f05 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/WeakRandomnessModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/WeakRandomnessModule.java @@ -1,8 +1,8 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface WeakRandomnessModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XContentTypeModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/XContentTypeModule.java similarity index 62% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XContentTypeModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/XContentTypeModule.java index 525ab7af8b..1e0d155cca 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XContentTypeModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/XContentTypeModule.java @@ -1,3 +1,3 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; public interface XContentTypeModule extends HttpRequestEndModule {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XPathInjectionModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/XPathInjectionModule.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XPathInjectionModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/XPathInjectionModule.java index 3a7f321091..2a01950fe8 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XPathInjectionModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/XPathInjectionModule.java @@ -1,8 +1,8 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.Nullable; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface XPathInjectionModule extends IastModule { void onExpression(@Nullable final String expression); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XssModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/XssModule.java similarity index 82% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XssModule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/XssModule.java index 81315d4a9f..42318b87df 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/sink/XssModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/sink/XssModule.java @@ -1,9 +1,9 @@ -package datadog.trace.api.iast.sink; +package com.datadog.trace.api.iast.sink; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import datadog.trace.api.iast.IastModule; +import com.datadog.trace.api.iast.IastModule; public interface XssModule extends IastModule { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetric.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/IastMetric.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetric.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/IastMetric.java index 3faf3b4574..00f14f1d39 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetric.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/IastMetric.java @@ -1,16 +1,16 @@ -package datadog.trace.api.iast.telemetry; +package com.datadog.trace.api.iast.telemetry; -import static datadog.trace.api.iast.VulnerabilityTypes.RESPONSE_HEADER; -import static datadog.trace.api.iast.VulnerabilityTypes.RESPONSE_HEADER_TYPES; -import static datadog.trace.api.iast.VulnerabilityTypes.SPRING_RESPONSE; -import static datadog.trace.api.iast.VulnerabilityTypes.SPRING_RESPONSE_TYPES; +import static com.datadog.trace.api.iast.VulnerabilityTypes.RESPONSE_HEADER; +import static com.datadog.trace.api.iast.VulnerabilityTypes.RESPONSE_HEADER_TYPES; +import static com.datadog.trace.api.iast.VulnerabilityTypes.SPRING_RESPONSE; +import static com.datadog.trace.api.iast.VulnerabilityTypes.SPRING_RESPONSE_TYPES; import androidx.annotation.NonNull; import java.util.function.Function; -import datadog.trace.api.iast.SourceTypes; -import datadog.trace.api.iast.VulnerabilityTypes; +import com.datadog.trace.api.iast.SourceTypes; +import com.datadog.trace.api.iast.VulnerabilityTypes; public enum IastMetric { INSTRUMENTED_PROPAGATION("instrumented.propagation", true, Scope.GLOBAL, Verbosity.MANDATORY), diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/IastMetricCollector.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/IastMetricCollector.java index d06027d30c..0bd7512942 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/IastMetricCollector.java @@ -1,6 +1,6 @@ -package datadog.trace.api.iast.telemetry; +package com.datadog.trace.api.iast.telemetry; -import static datadog.trace.api.iast.telemetry.IastMetric.Scope.REQUEST; +import static com.datadog.trace.api.iast.telemetry.IastMetric.Scope.REQUEST; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -17,13 +17,13 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.atomic.AtomicLongArray; -import datadog.trace.api.Config; -import datadog.trace.api.gateway.RequestContext; -import datadog.trace.api.gateway.RequestContextSlot; -import datadog.trace.api.iast.telemetry.IastMetric.Tag; -import datadog.trace.api.telemetry.MetricCollector; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.gateway.RequestContextSlot; +import com.datadog.trace.api.iast.telemetry.IastMetric.Tag; +import com.datadog.trace.api.telemetry.MetricCollector; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer; @SuppressWarnings("resource") public class IastMetricCollector implements MetricCollector { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/Verbosity.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/Verbosity.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/Verbosity.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/Verbosity.java index c6965aca24..6fad7557c2 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/telemetry/Verbosity.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/Verbosity.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast.telemetry; +package com.datadog.trace.api.iast.telemetry; public enum Verbosity { OFF, diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/util/Cookie.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/util/Cookie.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/iast/util/Cookie.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/util/Cookie.java index c743932add..baa416a660 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/iast/util/Cookie.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/util/Cookie.java @@ -1,4 +1,4 @@ -package datadog.trace.api.iast.util; +package com.datadog.trace.api.iast.util; public class Cookie { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/intake/TrackType.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/intake/TrackType.java similarity index 62% rename from features/dd-trace-core/src/main/java/datadog/trace/api/intake/TrackType.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/intake/TrackType.java index 6af32af4c2..ccef711fdb 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/intake/TrackType.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/intake/TrackType.java @@ -1,4 +1,4 @@ -package datadog.trace.api.intake; +package com.datadog.trace.api.intake; public enum TrackType { CITESTCYCLE, diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/AbstractTraceInterceptor.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/interceptor/AbstractTraceInterceptor.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/AbstractTraceInterceptor.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/interceptor/AbstractTraceInterceptor.java index c40bffc83d..426d2ac6a1 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/AbstractTraceInterceptor.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/interceptor/AbstractTraceInterceptor.java @@ -1,4 +1,4 @@ -package datadog.trace.api.interceptor; +package com.datadog.trace.api.interceptor; public abstract class AbstractTraceInterceptor implements TraceInterceptor { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/MutableSpan.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/interceptor/MutableSpan.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/MutableSpan.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/interceptor/MutableSpan.java index 4856a5ae58..a04ce6cb38 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/MutableSpan.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/interceptor/MutableSpan.java @@ -1,8 +1,8 @@ -package datadog.trace.api.interceptor; +package com.datadog.trace.api.interceptor; import java.util.Map; -import datadog.trace.api.DDTags; +import com.datadog.trace.api.DDTags; public interface MutableSpan { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/TraceInterceptor.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/interceptor/TraceInterceptor.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/TraceInterceptor.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/interceptor/TraceInterceptor.java index 822e0b9fd6..bfb1bdaab2 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/interceptor/TraceInterceptor.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/interceptor/TraceInterceptor.java @@ -1,4 +1,4 @@ -package datadog.trace.api.interceptor; +package com.datadog.trace.api.interceptor; import java.util.Collection; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/internal/InternalTracer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/internal/InternalTracer.java similarity index 82% rename from features/dd-trace-core/src/main/java/datadog/trace/api/internal/InternalTracer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/internal/InternalTracer.java index 73a825ea32..d690206c70 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/internal/InternalTracer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/internal/InternalTracer.java @@ -1,7 +1,7 @@ -package datadog.trace.api.internal; +package com.datadog.trace.api.internal; -import datadog.trace.api.experimental.DataStreamsCheckpointer; -import datadog.trace.api.profiling.Profiling; +import com.datadog.trace.api.experimental.DataStreamsCheckpointer; +import com.datadog.trace.api.profiling.Profiling; /** * Tracer internal features. Those features are not part of public API and can change or be removed diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/internal/TraceSegment.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/internal/TraceSegment.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/internal/TraceSegment.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/internal/TraceSegment.java index 0e2adb22ff..128e1df153 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/internal/TraceSegment.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/internal/TraceSegment.java @@ -1,4 +1,4 @@ -package datadog.trace.api.internal; +package com.datadog.trace.api.internal; /** * A {@code TraceSegment} represents the local, i.e. in the scope of this {@code Tracer}, part of a diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/internal/util/LongStringUtils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/internal/util/LongStringUtils.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/internal/util/LongStringUtils.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/internal/util/LongStringUtils.java index aa55b8943f..ec9aae2441 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/internal/util/LongStringUtils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/internal/util/LongStringUtils.java @@ -1,4 +1,4 @@ -package datadog.trace.api.internal.util; +package com.datadog.trace.api.internal.util; import static java.nio.charset.StandardCharsets.US_ASCII; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/CoreCounter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/CoreCounter.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/metrics/CoreCounter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/CoreCounter.java index c5d9abedce..d9be6ee007 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/CoreCounter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/CoreCounter.java @@ -1,4 +1,4 @@ -package datadog.trace.api.metrics; +package com.datadog.trace.api.metrics; /** This interface describes a core counter metric. */ public interface CoreCounter { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistry.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetricRegistry.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistry.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetricRegistry.java index 20c9c26442..b93b990a65 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistry.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetricRegistry.java @@ -1,6 +1,6 @@ -package datadog.trace.api.metrics; +package com.datadog.trace.api.metrics; -import datadog.trace.api.InstrumenterConfig; +import com.datadog.trace.api.InstrumenterConfig; /** This class holds the {@link SpanMetrics} instances. */ @FunctionalInterface diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistryImpl.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetricRegistryImpl.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistryImpl.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetricRegistryImpl.java index be2123c3ae..60d4f35bae 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricRegistryImpl.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetricRegistryImpl.java @@ -1,4 +1,4 @@ -package datadog.trace.api.metrics; +package com.datadog.trace.api.metrics; import java.util.Collection; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetrics.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetrics.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetrics.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetrics.java index fa4462316c..b2ce58ff42 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetrics.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetrics.java @@ -1,4 +1,4 @@ -package datadog.trace.api.metrics; +package com.datadog.trace.api.metrics; /** The core metrics related to a span./ */ public interface SpanMetrics { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricsImpl.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetricsImpl.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricsImpl.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetricsImpl.java index b0781008e2..4207447159 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/metrics/SpanMetricsImpl.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/metrics/SpanMetricsImpl.java @@ -1,4 +1,4 @@ -package datadog.trace.api.metrics; +package com.datadog.trace.api.metrics; import java.util.ArrayList; import java.util.Collection; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/NamingSchema.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/NamingSchema.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/NamingSchema.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/NamingSchema.java index 55d8e54ca8..5a6e3a078c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/NamingSchema.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/NamingSchema.java @@ -1,4 +1,4 @@ -package datadog.trace.api.naming; +package com.datadog.trace.api.naming; import androidx.annotation.NonNull; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/SpanNaming.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/SpanNaming.java similarity index 85% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/SpanNaming.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/SpanNaming.java index adbc318103..a6376b7ecd 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/SpanNaming.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/SpanNaming.java @@ -1,10 +1,10 @@ -package datadog.trace.api.naming; +package com.datadog.trace.api.naming; import androidx.annotation.NonNull; -import datadog.trace.api.Config; -import datadog.trace.api.naming.v0.NamingSchemaV0; -import datadog.trace.api.naming.v1.NamingSchemaV1; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.naming.v0.NamingSchemaV0; +import com.datadog.trace.api.naming.v1.NamingSchemaV1; /** This is the main entry point to drive span naming decisions. */ public class SpanNaming { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CacheNamingV0.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/CacheNamingV0.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CacheNamingV0.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/CacheNamingV0.java index 3f858684ca..8527816a84 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CacheNamingV0.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/CacheNamingV0.java @@ -1,8 +1,8 @@ -package datadog.trace.api.naming.v0; +package com.datadog.trace.api.naming.v0; import androidx.annotation.NonNull; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class CacheNamingV0 implements NamingSchema.ForCache { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ClientNamingV0.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/ClientNamingV0.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ClientNamingV0.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/ClientNamingV0.java index f7b310868d..8498118fd7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ClientNamingV0.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/ClientNamingV0.java @@ -1,8 +1,8 @@ -package datadog.trace.api.naming.v0; +package com.datadog.trace.api.naming.v0; import androidx.annotation.NonNull; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class ClientNamingV0 implements NamingSchema.ForClient { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CloudNamingV0.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/CloudNamingV0.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CloudNamingV0.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/CloudNamingV0.java index e83c947bca..db4f2f8819 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/CloudNamingV0.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/CloudNamingV0.java @@ -1,9 +1,9 @@ -package datadog.trace.api.naming.v0; +package com.datadog.trace.api.naming.v0; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class CloudNamingV0 implements NamingSchema.ForCloud { private final boolean allowInferredServices; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/DatabaseNamingV0.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/DatabaseNamingV0.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/DatabaseNamingV0.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/DatabaseNamingV0.java index 2eb7f5571b..3522086891 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/DatabaseNamingV0.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/DatabaseNamingV0.java @@ -1,8 +1,8 @@ -package datadog.trace.api.naming.v0; +package com.datadog.trace.api.naming.v0; import androidx.annotation.NonNull; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class DatabaseNamingV0 implements NamingSchema.ForDatabase { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/MessagingNamingV0.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/MessagingNamingV0.java index 666735c7d6..a3ca010a5e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/MessagingNamingV0.java @@ -1,9 +1,9 @@ -package datadog.trace.api.naming.v0; +package com.datadog.trace.api.naming.v0; import androidx.annotation.NonNull; -import datadog.trace.api.Config; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.naming.NamingSchema; public class MessagingNamingV0 implements NamingSchema.ForMessaging { private final boolean allowInferredServices; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/NamingSchemaV0.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/NamingSchemaV0.java similarity index 88% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/NamingSchemaV0.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/NamingSchemaV0.java index f36966115c..97aa16c7cc 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/NamingSchemaV0.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/NamingSchemaV0.java @@ -1,8 +1,8 @@ -package datadog.trace.api.naming.v0; +package com.datadog.trace.api.naming.v0; -import datadog.trace.api.Config; -import datadog.trace.api.naming.NamingSchema; -import datadog.trace.api.naming.v1.PeerServiceNamingV1; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.v1.PeerServiceNamingV1; public class NamingSchemaV0 implements NamingSchema { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/PeerServiceNamingV0.java similarity index 80% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/PeerServiceNamingV0.java index 6120d713eb..980dfee762 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/PeerServiceNamingV0.java @@ -1,11 +1,11 @@ -package datadog.trace.api.naming.v0; +package com.datadog.trace.api.naming.v0; import androidx.annotation.NonNull; import java.util.Collections; import java.util.Map; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class PeerServiceNamingV0 implements NamingSchema.ForPeerService { @Override diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ServerNamingV0.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/ServerNamingV0.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ServerNamingV0.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/ServerNamingV0.java index f5f09b3405..ec3b26345e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v0/ServerNamingV0.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v0/ServerNamingV0.java @@ -1,8 +1,8 @@ -package datadog.trace.api.naming.v0; +package com.datadog.trace.api.naming.v0; import androidx.annotation.NonNull; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class ServerNamingV0 implements NamingSchema.ForServer { @NonNull diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CacheNamingV1.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/CacheNamingV1.java similarity index 77% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CacheNamingV1.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/CacheNamingV1.java index 48286d25d1..60652003b3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CacheNamingV1.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/CacheNamingV1.java @@ -1,8 +1,8 @@ -package datadog.trace.api.naming.v1; +package com.datadog.trace.api.naming.v1; import androidx.annotation.NonNull; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class CacheNamingV1 implements NamingSchema.ForCache { @NonNull diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ClientNamingV1.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/ClientNamingV1.java similarity index 87% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ClientNamingV1.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/ClientNamingV1.java index 0617873e63..d6c657cddd 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ClientNamingV1.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/ClientNamingV1.java @@ -1,8 +1,8 @@ -package datadog.trace.api.naming.v1; +package com.datadog.trace.api.naming.v1; import androidx.annotation.NonNull; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class ClientNamingV1 implements NamingSchema.ForClient { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CloudNamingV1.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/CloudNamingV1.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CloudNamingV1.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/CloudNamingV1.java index 179a2c47ec..776efcce44 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/CloudNamingV1.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/CloudNamingV1.java @@ -1,13 +1,13 @@ -package datadog.trace.api.naming.v1; +package com.datadog.trace.api.naming.v1; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.util.Locale; -import datadog.trace.api.naming.NamingSchema; -import datadog.trace.api.naming.SpanNaming; -import datadog.trace.util.Strings; +import com.datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.SpanNaming; +import com.datadog.trace.util.Strings; public class CloudNamingV1 implements NamingSchema.ForCloud { @NonNull diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/DatabaseNamingV1.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/DatabaseNamingV1.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/DatabaseNamingV1.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/DatabaseNamingV1.java index c4591ffb15..1f32cc3bba 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/DatabaseNamingV1.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/DatabaseNamingV1.java @@ -1,8 +1,8 @@ -package datadog.trace.api.naming.v1; +package com.datadog.trace.api.naming.v1; import androidx.annotation.NonNull; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class DatabaseNamingV1 implements NamingSchema.ForDatabase { @Override diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/MessagingNamingV1.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/MessagingNamingV1.java index ff6ae39b80..6cccd4144a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/MessagingNamingV1.java @@ -1,8 +1,8 @@ -package datadog.trace.api.naming.v1; +package com.datadog.trace.api.naming.v1; import androidx.annotation.NonNull; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class MessagingNamingV1 implements NamingSchema.ForMessaging { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/NamingSchemaV1.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/NamingSchemaV1.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/NamingSchemaV1.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/NamingSchemaV1.java index 9c961f60e4..046408ea4a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/NamingSchemaV1.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/NamingSchemaV1.java @@ -1,7 +1,7 @@ -package datadog.trace.api.naming.v1; +package com.datadog.trace.api.naming.v1; -import datadog.trace.api.Config; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.naming.NamingSchema; public class NamingSchemaV1 implements NamingSchema { private final ForCache cacheNaming = new CacheNamingV1(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/PeerServiceNamingV1.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/PeerServiceNamingV1.java index 5cd70f369c..d605fa8a9a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/PeerServiceNamingV1.java @@ -1,4 +1,4 @@ -package datadog.trace.api.naming.v1; +package com.datadog.trace.api.naming.v1; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -6,10 +6,10 @@ import java.util.HashMap; import java.util.Map; -import datadog.trace.api.DDTags; -import datadog.trace.api.naming.NamingSchema; -import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags; -import datadog.trace.bootstrap.instrumentation.api.Tags; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.bootstrap.instrumentation.api.InstrumentationTags; +import com.datadog.trace.bootstrap.instrumentation.api.Tags; public class PeerServiceNamingV1 implements NamingSchema.ForPeerService { private static final Map SPECIFIC_PRECURSORS_BY_COMPONENT = diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ServerNamingV1.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/ServerNamingV1.java similarity index 80% rename from features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ServerNamingV1.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/ServerNamingV1.java index 3084be1f6e..2ae132cf04 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/naming/v1/ServerNamingV1.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/naming/v1/ServerNamingV1.java @@ -1,8 +1,8 @@ -package datadog.trace.api.naming.v1; +package com.datadog.trace.api.naming.v1; import androidx.annotation.NonNull; -import datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.NamingSchema; public class ServerNamingV1 implements NamingSchema.ForServer { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPathMatcher.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/AntPathMatcher.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPathMatcher.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/AntPathMatcher.java index f50dd62f30..384bea231a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPathMatcher.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/AntPathMatcher.java @@ -1,4 +1,4 @@ -package datadog.trace.api.normalize; +package com.datadog.trace.api.normalize; import java.util.ArrayList; import java.util.Collection; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java index 436ce5c4ca..25ca1c7a68 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java @@ -1,4 +1,4 @@ -package datadog.trace.api.normalize; +package com.datadog.trace.api.normalize; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -8,9 +8,9 @@ import java.util.Map; import java.util.function.Function; -import datadog.trace.api.cache.DDCache; -import datadog.trace.api.cache.DDCaches; -import datadog.trace.bootstrap.instrumentation.api.URIUtils; +import com.datadog.trace.api.cache.DDCache; +import com.datadog.trace.api.cache.DDCaches; +import com.datadog.trace.bootstrap.instrumentation.api.URIUtils; final class AntPatternHttpPathNormalizer extends HttpPathNormalizer { private static final Logger log = LoggerFactory.getLogger(AntPatternHttpPathNormalizer.class); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpPathNormalizer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/HttpPathNormalizer.java similarity index 82% rename from features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpPathNormalizer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/HttpPathNormalizer.java index 4496607d61..42079ac2df 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpPathNormalizer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/HttpPathNormalizer.java @@ -1,4 +1,4 @@ -package datadog.trace.api.normalize; +package com.datadog.trace.api.normalize; abstract class HttpPathNormalizer { public final String normalize(String path) { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpResourceNames.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/HttpResourceNames.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpResourceNames.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/HttpResourceNames.java index 597a810a78..265556a72a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/HttpResourceNames.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/HttpResourceNames.java @@ -1,14 +1,14 @@ -package datadog.trace.api.normalize; +package com.datadog.trace.api.normalize; import java.util.function.Function; -import datadog.trace.api.Config; -import datadog.trace.api.Pair; -import datadog.trace.api.cache.DDCache; -import datadog.trace.api.cache.DDCaches; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.Pair; +import com.datadog.trace.api.cache.DDCache; +import com.datadog.trace.api.cache.DDCaches; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; public class HttpResourceNames { public static final UTF8BytesString DEFAULT_RESOURCE_NAME = UTF8BytesString.create("/"); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SQLNormalizer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/SQLNormalizer.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SQLNormalizer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/SQLNormalizer.java index a9e71e8292..15b7dceccd 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SQLNormalizer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/SQLNormalizer.java @@ -1,4 +1,4 @@ -package datadog.trace.api.normalize; +package com.datadog.trace.api.normalize; import static java.nio.charset.StandardCharsets.UTF_8; @@ -8,7 +8,7 @@ import java.util.Arrays; import java.util.BitSet; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; /** * This class removes numbers and SQL literals from strings on a best-effort basis, producing UTF-8 diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java index d4857986eb..6a4ef27f27 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/SimpleHttpPathNormalizer.java @@ -1,6 +1,6 @@ -package datadog.trace.api.normalize; +package com.datadog.trace.api.normalize; -import datadog.trace.api.Config; +import com.datadog.trace.api.Config; // public because this is used in the testing module but groovy accesses it through Class.forName // which is banned diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ObservableType.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ObservableType.java new file mode 100644 index 0000000000..2bd8c1c397 --- /dev/null +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ObservableType.java @@ -0,0 +1,3 @@ +package com.datadog.trace.api.profiling; + +public interface ObservableType {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Profiling.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/Profiling.java similarity index 86% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Profiling.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/Profiling.java index f4ee47c4b2..bc36e9eda6 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Profiling.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/Profiling.java @@ -1,8 +1,8 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; -import datadog.trace.api.GlobalTracer; -import datadog.trace.api.Tracer; -import datadog.trace.api.internal.InternalTracer; +import com.datadog.trace.api.GlobalTracer; +import com.datadog.trace.api.Tracer; +import com.datadog.trace.api.internal.InternalTracer; public interface Profiling { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingContext.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingContext.java index 2d1f72b9a4..4b5075306f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingContext.java @@ -1,4 +1,4 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; public interface ProfilingContext { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContextAttribute.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingContextAttribute.java similarity index 80% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContextAttribute.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingContextAttribute.java index 9dcf909e48..ca7dd0974b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingContextAttribute.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingContextAttribute.java @@ -1,4 +1,4 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; public interface ProfilingContextAttribute { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingScope.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingScope.java similarity index 77% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingScope.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingScope.java index 182cbe09ec..14ce456bee 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingScope.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingScope.java @@ -1,4 +1,4 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; public interface ProfilingScope extends AutoCloseable, ProfilingContext { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingSnapshot.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingSnapshot.java similarity index 73% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingSnapshot.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingSnapshot.java index 21eca45267..acfe8deaad 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ProfilingSnapshot.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/ProfilingSnapshot.java @@ -1,4 +1,4 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; public interface ProfilingSnapshot extends ObservableType { enum Kind { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/QueueTiming.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/QueueTiming.java similarity index 74% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/QueueTiming.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/QueueTiming.java index 082f5a8be9..c47c75ab0d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/QueueTiming.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/QueueTiming.java @@ -1,4 +1,4 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; public interface QueueTiming extends Timing { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingData.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingData.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingData.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingData.java index cce87e03b9..eec86abba8 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingData.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingData.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; import androidx.annotation.NonNull; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingDataListener.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingDataListener.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingDataListener.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingDataListener.java index 29a5e4951b..90e3511b91 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingDataListener.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingDataListener.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; /** Listener for getting notified when new recording data is becoming available. */ public interface RecordingDataListener { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingInputStream.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingInputStream.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingInputStream.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingInputStream.java index 0549635a02..af23ac9681 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingInputStream.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingInputStream.java @@ -1,4 +1,4 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; import java.io.BufferedInputStream; import java.io.IOException; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingType.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingType.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingType.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingType.java index 639ccc3955..326e4913cd 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/RecordingType.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/RecordingType.java @@ -1,4 +1,4 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; public enum RecordingType { CONTINUOUS("continuous"); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/Timer.java similarity index 87% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/Timer.java index 991fc832e7..3c9bc8da9d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/Timer.java @@ -1,4 +1,4 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; public interface Timer { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timing.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/Timing.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timing.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/Timing.java index 99aa1913db..273555dc08 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/Timing.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/Timing.java @@ -1,4 +1,4 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; public interface Timing extends AutoCloseable { @Override diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/TransientProfilingContextHolder.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/TransientProfilingContextHolder.java similarity index 56% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/TransientProfilingContextHolder.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/TransientProfilingContextHolder.java index ad24b678c0..ffbf5e3384 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/TransientProfilingContextHolder.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/TransientProfilingContextHolder.java @@ -1,3 +1,3 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; public interface TransientProfilingContextHolder {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/package-info.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/package-info.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/api/profiling/package-info.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/package-info.java index 75028b334f..30e3b1c316 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/package-info.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/profiling/package-info.java @@ -1,4 +1,4 @@ -package datadog.trace.api.profiling; +package com.datadog.trace.api.profiling; /** * This is the communication point between the tracer and profiler. The classes from this package diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/PrioritySampling.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/PrioritySampling.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/sampling/PrioritySampling.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/PrioritySampling.java index 4aeda33362..60050cb691 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/PrioritySampling.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/PrioritySampling.java @@ -1,4 +1,4 @@ -package datadog.trace.api.sampling; +package com.datadog.trace.api.sampling; public class PrioritySampling { /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/Sampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/Sampler.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/sampling/Sampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/Sampler.java index 032f545402..f45644578d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/Sampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/Sampler.java @@ -1,4 +1,4 @@ -package datadog.trace.api.sampling; +package com.datadog.trace.api.sampling; public interface Sampler { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingMechanism.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/SamplingMechanism.java similarity index 84% rename from features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingMechanism.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/SamplingMechanism.java index 93cb32307d..3053e10f6a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingMechanism.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/SamplingMechanism.java @@ -1,9 +1,9 @@ -package datadog.trace.api.sampling; +package com.datadog.trace.api.sampling; -import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; -import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; -import static datadog.trace.api.sampling.PrioritySampling.USER_DROP; -import static datadog.trace.api.sampling.PrioritySampling.USER_KEEP; +import static com.datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static com.datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; +import static com.datadog.trace.api.sampling.PrioritySampling.USER_DROP; +import static com.datadog.trace.api.sampling.PrioritySampling.USER_KEEP; public class SamplingMechanism { /** Not encouraged to use */ diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingRule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/SamplingRule.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingRule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/SamplingRule.java index 3bb8ba2d9a..30ea8fb567 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/sampling/SamplingRule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/sampling/SamplingRule.java @@ -1,4 +1,4 @@ -package datadog.trace.api.sampling; +package com.datadog.trace.api.sampling; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ExtendedScopeListener.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/scopemanager/ExtendedScopeListener.java similarity index 67% rename from features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ExtendedScopeListener.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/scopemanager/ExtendedScopeListener.java index 239fc4eba7..d14d32455b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ExtendedScopeListener.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/scopemanager/ExtendedScopeListener.java @@ -1,7 +1,7 @@ -package datadog.trace.api.scopemanager; +package com.datadog.trace.api.scopemanager; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; public interface ExtendedScopeListener extends ScopeListener { void afterScopeActivated( diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ScopeListener.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/scopemanager/ScopeListener.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ScopeListener.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/scopemanager/ScopeListener.java index 3c55c67ef3..d057510c40 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/scopemanager/ScopeListener.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/scopemanager/ScopeListener.java @@ -1,4 +1,4 @@ -package datadog.trace.api.scopemanager; +package com.datadog.trace.api.scopemanager; /** Hooks for scope activation */ public interface ScopeListener { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/CoreMetricCollector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/CoreMetricCollector.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/CoreMetricCollector.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/CoreMetricCollector.java index 91633d215c..d194b7ef5c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/CoreMetricCollector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/CoreMetricCollector.java @@ -1,4 +1,4 @@ -package datadog.trace.api.telemetry; +package com.datadog.trace.api.telemetry; import java.util.ArrayList; import java.util.Collection; @@ -7,9 +7,9 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; -import datadog.trace.api.metrics.CoreCounter; -import datadog.trace.api.metrics.SpanMetricRegistryImpl; -import datadog.trace.api.metrics.SpanMetricsImpl; +import com.datadog.trace.api.metrics.CoreCounter; +import com.datadog.trace.api.metrics.SpanMetricRegistryImpl; +import com.datadog.trace.api.metrics.SpanMetricsImpl; /** This class is in charge of draining core metrics for telemetry. */ public class CoreMetricCollector implements MetricCollector { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/IntegrationsCollector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/IntegrationsCollector.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/IntegrationsCollector.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/IntegrationsCollector.java index 2b85a444e6..312e073092 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/IntegrationsCollector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/IntegrationsCollector.java @@ -1,4 +1,4 @@ -package datadog.trace.api.telemetry; +package com.datadog.trace.api.telemetry; import java.util.Collections; import java.util.LinkedHashMap; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/LogCollector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/LogCollector.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/LogCollector.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/LogCollector.java index 0a99d1365f..40f629aba8 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/LogCollector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/LogCollector.java @@ -1,4 +1,4 @@ -package datadog.trace.api.telemetry; +package com.datadog.trace.api.telemetry; import org.slf4j.Marker; import org.slf4j.MarkerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/MetricCollector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/MetricCollector.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/MetricCollector.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/MetricCollector.java index ee8347b61a..4c38c70767 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/MetricCollector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/MetricCollector.java @@ -1,8 +1,8 @@ -package datadog.trace.api.telemetry; +package com.datadog.trace.api.telemetry; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; -import static datadog.trace.api.telemetry.MetricCollector.Metric; +import static com.datadog.trace.api.telemetry.MetricCollector.Metric; import java.util.Arrays; import java.util.Collection; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/WafMetricCollector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/WafMetricCollector.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/WafMetricCollector.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/WafMetricCollector.java index bec43b3824..79b877eb39 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/telemetry/WafMetricCollector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/WafMetricCollector.java @@ -1,4 +1,4 @@ -package datadog.trace.api.telemetry; +package com.datadog.trace.api.telemetry; import java.util.Collection; import java.util.Collections; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/time/ControllableTimeSource.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/time/ControllableTimeSource.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/time/ControllableTimeSource.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/time/ControllableTimeSource.java index 833314da88..8d2f7734c2 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/time/ControllableTimeSource.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/time/ControllableTimeSource.java @@ -1,4 +1,4 @@ -package datadog.trace.api.time; +package com.datadog.trace.api.time; import java.util.concurrent.TimeUnit; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/time/SystemTimeSource.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/time/SystemTimeSource.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/time/SystemTimeSource.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/time/SystemTimeSource.java index dfa5139056..3bb5c0630c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/time/SystemTimeSource.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/time/SystemTimeSource.java @@ -1,4 +1,4 @@ -package datadog.trace.api.time; +package com.datadog.trace.api.time; import static java.util.concurrent.TimeUnit.MILLISECONDS; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/time/TimeSource.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/time/TimeSource.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/api/time/TimeSource.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/api/time/TimeSource.java index dc785661fb..a806ce204e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/time/TimeSource.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/time/TimeSource.java @@ -1,4 +1,4 @@ -package datadog.trace.api.time; +package com.datadog.trace.api.time; /** * Interface to retrieve various time primitives. Limited by the granularity of the underlying diff --git a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/Blocking.java b/features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/Blocking.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/Blocking.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/Blocking.java index 0b8d1894d2..857dfab7e9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/Blocking.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/Blocking.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.appsec.api.blocking; +package com.datadog.trace.appsec.api.blocking; import java.util.Collections; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingContentType.java b/features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingContentType.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingContentType.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingContentType.java index c42fef949e..17f3c6d9f8 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingContentType.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingContentType.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.appsec.api.blocking; +package com.datadog.trace.appsec.api.blocking; public enum BlockingContentType { /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingDetails.java b/features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingDetails.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingDetails.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingDetails.java index d452627b03..3acddb86ab 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingDetails.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingDetails.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.appsec.api.blocking; +package com.datadog.trace.appsec.api.blocking; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingException.java b/features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingException.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingException.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingException.java index 3e66084309..3d517076cd 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingException.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingException.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.appsec.api.blocking; +package com.datadog.trace.appsec.api.blocking; public class BlockingException extends RuntimeException { public BlockingException() {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingService.java b/features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingService.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingService.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingService.java index 50bf5dff48..03be28f8f8 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/appsec/api/blocking/BlockingService.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/appsec/api/blocking/BlockingService.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.appsec.api.blocking; +package com.datadog.trace.appsec.api.blocking; import androidx.annotation.NonNull; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/ActiveSubsystems.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/ActiveSubsystems.java similarity index 69% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/ActiveSubsystems.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/ActiveSubsystems.java index 2a43c32c3f..0f3471cfb7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/ActiveSubsystems.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/ActiveSubsystems.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap; +package com.datadog.trace.bootstrap; public class ActiveSubsystems { public static volatile boolean APPSEC_ACTIVE; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java index 690a82584f..7d12c60374 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/AgentArgsInjector.java @@ -1,8 +1,8 @@ -package datadog.trace.bootstrap.config.provider; +package com.datadog.trace.bootstrap.config.provider; import java.util.Map; -import datadog.trace.util.Strings; +import com.datadog.trace.util.Strings; public class AgentArgsInjector { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsParser.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/AgentArgsParser.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsParser.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/AgentArgsParser.java index b8a7480f8d..d7c5843c5e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/AgentArgsParser.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/AgentArgsParser.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.config.provider; +package com.datadog.trace.bootstrap.config.provider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java similarity index 76% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java index 56bfb0ad54..01f7ec25e8 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/CapturedEnvironmentConfigSource.java @@ -1,7 +1,7 @@ -package datadog.trace.bootstrap.config.provider; +package com.datadog.trace.bootstrap.config.provider; -import datadog.trace.api.ConfigOrigin; -import datadog.trace.api.env.CapturedEnvironment; +import com.datadog.trace.api.ConfigOrigin; +import com.datadog.trace.api.env.CapturedEnvironment; public final class CapturedEnvironmentConfigSource extends ConfigProvider.Source { private final CapturedEnvironment env; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigConverter.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigConverter.java index 4ef4e3b4b5..70701e8de2 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigConverter.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.config.provider; +package com.datadog.trace.bootstrap.config.provider; import androidx.annotation.NonNull; @@ -17,7 +17,7 @@ import java.util.Map; import java.util.Objects; -import datadog.trace.util.Strings; +import com.datadog.trace.util.Strings; final class ConfigConverter { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigProvider.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigProvider.java index d9dbaf221a..cb1bf35c46 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigProvider.java @@ -1,6 +1,6 @@ -package datadog.trace.bootstrap.config.provider; +package com.datadog.trace.bootstrap.config.provider; -import static datadog.trace.api.config.GeneralConfig.CONFIGURATION_FILE; +import static com.datadog.trace.api.config.GeneralConfig.CONFIGURATION_FILE; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,8 +18,8 @@ import java.util.Properties; import java.util.Set; -import datadog.trace.api.ConfigCollector; -import datadog.trace.api.ConfigOrigin; +import com.datadog.trace.api.ConfigCollector; +import com.datadog.trace.api.ConfigOrigin; public final class ConfigProvider { private static final class Singleton { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java similarity index 60% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java index 6719693fd8..2b9784414a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java @@ -1,8 +1,8 @@ -package datadog.trace.bootstrap.config.provider; +package com.datadog.trace.bootstrap.config.provider; -import static datadog.trace.util.Strings.propertyNameToEnvironmentVariableName; +import static com.datadog.trace.util.Strings.propertyNameToEnvironmentVariableName; -import datadog.trace.api.ConfigOrigin; +import com.datadog.trace.api.ConfigOrigin; final class EnvironmentConfigSource extends ConfigProvider.Source { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java index 76ad7c4709..3e30931f47 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/PropertiesConfigSource.java @@ -1,10 +1,10 @@ -package datadog.trace.bootstrap.config.provider; +package com.datadog.trace.bootstrap.config.provider; -import static datadog.trace.util.Strings.propertyNameToSystemPropertyName; +import static com.datadog.trace.util.Strings.propertyNameToSystemPropertyName; import java.util.Properties; -import datadog.trace.api.ConfigOrigin; +import com.datadog.trace.api.ConfigOrigin; final class PropertiesConfigSource extends ConfigProvider.Source { // start key with underscore, so it isn't visible using the public 'get' method diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java similarity index 62% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java index 08aaf48702..c4e7c10a20 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java @@ -1,8 +1,8 @@ -package datadog.trace.bootstrap.config.provider; +package com.datadog.trace.bootstrap.config.provider; -import static datadog.trace.util.Strings.propertyNameToSystemPropertyName; +import static com.datadog.trace.util.Strings.propertyNameToSystemPropertyName; -import datadog.trace.api.ConfigOrigin; +import com.datadog.trace.api.ConfigOrigin; public final class SystemPropertiesConfigSource extends ConfigProvider.Source { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java index 3f04dd292a..5b4c7f9cfc 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentDataStreamsMonitoring.java @@ -1,8 +1,8 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.util.LinkedHashMap; -import datadog.trace.api.experimental.DataStreamsCheckpointer; +import com.datadog.trace.api.experimental.DataStreamsCheckpointer; public interface AgentDataStreamsMonitoring extends DataStreamsCheckpointer { void trackBacklog(LinkedHashMap sortedTags, long value); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java similarity index 85% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java index f36e08ac81..96e2b09f13 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentHistogram.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.nio.ByteBuffer; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java index e4ba4281e4..a31a7f7616 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java @@ -1,8 +1,8 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.util.LinkedHashMap; -import datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.api.TracePropagationStyle; public interface AgentPropagation { void inject(AgentSpan span, C carrier, Setter setter); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentScope.java similarity index 82% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentScope.java index 8075c76b26..87f73f0f76 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentScope.java @@ -1,8 +1,8 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.io.Closeable; -import datadog.trace.context.TraceScope; +import com.datadog.trace.context.TraceScope; public interface AgentScope extends TraceScope, Closeable { AgentSpan span(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java index 9337c33ab4..514179f3b4 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentScopeManager.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; /** * Allows custom scope managers. See OTScopeManager, CustomScopeManager, and ContextualScopeManager diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java index f534827d5e..3cdec62239 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java @@ -1,14 +1,14 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.util.List; import java.util.Map; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.gateway.IGSpanInfo; -import datadog.trace.api.gateway.RequestContext; -import datadog.trace.api.interceptor.MutableSpan; -import datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.gateway.IGSpanInfo; +import com.datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.interceptor.MutableSpan; +import com.datadog.trace.api.sampling.PrioritySampling; public interface AgentSpan extends MutableSpan, IGSpanInfo { @@ -153,7 +153,7 @@ interface Context { /** * Gets the SpanId. * - * @return The span identifier, or {@link datadog.trace.api.DDSpanId#ZERO} if not set. + * @return The span identifier, or {@link com.datadog.trace.api.DDSpanId#ZERO} if not set. */ long getSpanId(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java index 3e10df0212..aba0563893 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentSpanLink.java @@ -1,8 +1,8 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.util.Map; -import datadog.trace.api.DDTraceId; +import com.datadog.trace.api.DDTraceId; /** * This interface describes a link to another span. The linked span could be part of the same trace diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java similarity index 74% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java index abb4fe9d30..6e026f112e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentTrace.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public interface AgentTrace { void registerContinuation(AgentScope.Continuation continuation); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java index f7b33a668d..aa974df352 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java @@ -1,7 +1,7 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import static java.util.Collections.emptyList; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; import java.nio.ByteBuffer; import java.util.Collections; @@ -10,27 +10,27 @@ import java.util.Map; import java.util.function.Consumer; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.EndpointCheckpointer; -import datadog.trace.api.EndpointTracker; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.experimental.DataStreamsCheckpointer; -import datadog.trace.api.experimental.DataStreamsContextCarrier; -import datadog.trace.api.gateway.CallbackProvider; -import datadog.trace.api.gateway.Flow; -import datadog.trace.api.gateway.RequestContext; -import datadog.trace.api.gateway.RequestContextSlot; -import datadog.trace.api.gateway.SubscriptionService; -import datadog.trace.api.interceptor.TraceInterceptor; -import datadog.trace.api.internal.InternalTracer; -import datadog.trace.api.internal.TraceSegment; -import datadog.trace.api.profiling.Timer; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.sampling.SamplingRule; -import datadog.trace.api.scopemanager.ScopeListener; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan.Context; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.EndpointCheckpointer; +import com.datadog.trace.api.EndpointTracker; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.api.experimental.DataStreamsCheckpointer; +import com.datadog.trace.api.experimental.DataStreamsContextCarrier; +import com.datadog.trace.api.gateway.CallbackProvider; +import com.datadog.trace.api.gateway.Flow; +import com.datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.gateway.RequestContextSlot; +import com.datadog.trace.api.gateway.SubscriptionService; +import com.datadog.trace.api.interceptor.TraceInterceptor; +import com.datadog.trace.api.internal.InternalTracer; +import com.datadog.trace.api.internal.TraceSegment; +import com.datadog.trace.api.profiling.Timer; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.sampling.SamplingRule; +import com.datadog.trace.api.scopemanager.ScopeListener; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan.Context; public class AgentTracer { private static final String DEFAULT_INSTRUMENTATION_NAME = "datadog"; @@ -115,7 +115,7 @@ public static void closePrevious(final boolean finishSpan) { /** * Activates a new iteration scope; closes automatically after a fixed period. * - * @see datadog.trace.api.config.TracerConfig#SCOPE_ITERATION_KEEP_ALIVE + * @see com.datadog.trace.api.config.TracerConfig#SCOPE_ITERATION_KEEP_ALIVE */ public static AgentScope activateNext(final AgentSpan span) { return get().activateNext(span); @@ -176,7 +176,7 @@ public static TracerAPI get() { private AgentTracer() {} public interface TracerAPI - extends datadog.trace.api.Tracer, InternalTracer, EndpointCheckpointer, ScopeStateAware { + extends com.datadog.trace.api.Tracer, InternalTracer, EndpointCheckpointer, ScopeStateAware { /** * Create and start a new span. diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java similarity index 87% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java index 685562807d..def0c4b676 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import androidx.annotation.NonNull; import androidx.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Backlog.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/Backlog.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Backlog.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/Backlog.java index 333a43f6e8..d9653258dc 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Backlog.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/Backlog.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java similarity index 76% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java index 3e48582a1c..4aa6f513e5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ErrorPriorities.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public class ErrorPriorities { public static final byte UNSET = Byte.MIN_VALUE; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/InboxItem.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/InboxItem.java new file mode 100644 index 0000000000..de3d1a45fc --- /dev/null +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/InboxItem.java @@ -0,0 +1,3 @@ +package com.datadog.trace.bootstrap.instrumentation.api; + +public interface InboxItem {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java index 5a2f96fd7c..9e4ecf1d34 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/InstrumentationTags.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public class InstrumentationTags { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java index 918f9bd759..7d6b163d7e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java @@ -1,6 +1,6 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; -import datadog.trace.api.DDSpanTypes; +import com.datadog.trace.api.DDSpanTypes; public class InternalSpanTypes { public static final CharSequence HTTP_CLIENT = UTF8BytesString.create(DDSpanTypes.HTTP_CLIENT); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java index b9cd729fc1..54798937bb 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/PathwayContext.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.io.IOException; import java.util.LinkedHashMap; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java index 1001b1c0a8..bbe067cf9e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ProfilerContext.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public interface ProfilerContext { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java similarity index 82% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java index 303411289c..96687e21d2 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ProfilingContextIntegration.java @@ -1,9 +1,9 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; -import datadog.trace.api.Stateful; -import datadog.trace.api.profiling.Profiling; -import datadog.trace.api.profiling.ProfilingContextAttribute; -import datadog.trace.api.profiling.ProfilingScope; +import com.datadog.trace.api.Stateful; +import com.datadog.trace.api.profiling.Profiling; +import com.datadog.trace.api.profiling.ProfilingContextAttribute; +import com.datadog.trace.api.profiling.ProfilingScope; public interface ProfilingContextIntegration extends Profiling { /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java index dddeabaf0e..d5d1cea0a7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ResourceNamePriorities.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public class ResourceNamePriorities { public static final byte DEFAULT = 0; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java similarity index 73% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java index eae61cdc31..c9e09e8654 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/SamplerConstants.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public class SamplerConstants { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java similarity index 79% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java index b801c83273..174af4dde0 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public enum ScopeSource { INSTRUMENTATION((byte) 0), diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeState.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ScopeState.java similarity index 58% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeState.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ScopeState.java index 5e715cc354..41d08fc787 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeState.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ScopeState.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public interface ScopeState { void activate(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java similarity index 54% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java index 977afc1184..1555c04b4c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/ScopeStateAware.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public interface ScopeStateAware { ScopeState newScopeState(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLink.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/SpanLink.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLink.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/SpanLink.java index 4a0e28b272..3eb94763ea 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLink.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/SpanLink.java @@ -1,8 +1,8 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; -import static datadog.trace.bootstrap.instrumentation.api.SpanLinkAttributes.EMPTY; +import static com.datadog.trace.bootstrap.instrumentation.api.SpanLinkAttributes.EMPTY; -import datadog.trace.api.DDTraceId; +import com.datadog.trace.api.DDTraceId; /** This class is a base implementation of {@link AgentSpanLink}. */ public class SpanLink implements AgentSpanLink { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java index 87a2ce05f6..1686817ba8 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/SpanLinkAttributes.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import static java.util.Objects.requireNonNull; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java index caa6540699..f92fbd2fda 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/StatsPoint.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TagContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/TagContext.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TagContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/TagContext.java index c76475a085..2e6f009a21 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TagContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/TagContext.java @@ -1,18 +1,18 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import static java.util.Collections.emptyList; -import static datadog.trace.api.TracePropagationStyle.NONE; +import static com.datadog.trace.api.TracePropagationStyle.NONE; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.api.sampling.PrioritySampling; /** * When calling extract, we allow for grabbing other configured headers as tags. Those tags are diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/Tags.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/Tags.java index cfe43ff6df..763700574b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/Tags.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; // standard tag names (and span kind values) from OpenTracing (see io.opentracing.tag.Tags) public class Tags { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java similarity index 86% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java index 3315ab3e8b..fa10783eae 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/TaskWrapper.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public interface TaskWrapper { static Class getUnwrappedType(Object task) { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java index 6536401f62..4f4a535190 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIDataAdapter.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public interface URIDataAdapter { /** The scheme of this URI. Can never be encoded. */ diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java index 87545a9aa6..7570f22dc3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIDataAdapterBase.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.net.URI; import java.util.function.Function; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java index 6392aad2d4..9526448fd4 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIDefaultDataAdapter.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import java.net.URI; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java index d02af4ead1..9db29e9a81 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIRawDataAdapter.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public abstract class URIRawDataAdapter extends URIDataAdapterBase { private String decodedPath = UNINITIALIZED; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIUtils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIUtils.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIUtils.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIUtils.java index b44573f58f..8ce4dcd820 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/URIUtils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIUtils.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java index ce60056fd9..aa581fba84 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import static java.nio.charset.StandardCharsets.UTF_8; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java index 7a3b4f1daa..2c511c481f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/UnparseableURIDataAdapter.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; import androidx.annotation.NonNull; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java index 0c283d129f..4f0e124f1d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/WriterConstants.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.instrumentation.api; +package com.datadog.trace.bootstrap.instrumentation.api; public final class WriterConstants { public static final String DD_AGENT_WRITER_TYPE = "DDAgentWriter"; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java b/features/dd-trace-core/src/main/java/com/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java similarity index 84% rename from features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java index 589fba522d..1fb58f78e9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/civisibility/interceptor/CiVisibilityApmProtocolInterceptor.java @@ -1,9 +1,9 @@ -package datadog.trace.civisibility.interceptor; +package com.datadog.trace.civisibility.interceptor; -import datadog.trace.api.DDSpanTypes; -import datadog.trace.api.interceptor.AbstractTraceInterceptor; -import datadog.trace.api.interceptor.MutableSpan; -import datadog.trace.bootstrap.instrumentation.api.Tags; +import com.datadog.trace.api.DDSpanTypes; +import com.datadog.trace.api.interceptor.AbstractTraceInterceptor; +import com.datadog.trace.api.interceptor.MutableSpan; +import com.datadog.trace.bootstrap.instrumentation.api.Tags; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java b/features/dd-trace-core/src/main/java/com/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java similarity index 80% rename from features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java index bec1bdcd64..db89638473 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java @@ -1,12 +1,12 @@ -package datadog.trace.civisibility.interceptor; - -import datadog.trace.api.DDSpanTypes; -import datadog.trace.api.DDTags; -import datadog.trace.api.interceptor.AbstractTraceInterceptor; -import datadog.trace.api.interceptor.MutableSpan; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; -import datadog.trace.core.DDSpan; -import datadog.trace.core.DDTraceCoreInfo; +package com.datadog.trace.civisibility.interceptor; + +import com.datadog.trace.api.DDSpanTypes; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.api.interceptor.AbstractTraceInterceptor; +import com.datadog.trace.api.interceptor.MutableSpan; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.core.DDSpan; +import com.datadog.trace.core.DDTraceCoreInfo; import java.util.Collection; import java.util.Collections; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/AggregateMetric.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/AggregateMetric.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/common/metrics/AggregateMetric.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/AggregateMetric.java index c81015b52f..ac87f0e00b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/AggregateMetric.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/AggregateMetric.java @@ -1,7 +1,7 @@ -package datadog.trace.common.metrics; +package com.datadog.trace.common.metrics; -import datadog.trace.core.histogram.Histogram; -import datadog.trace.core.histogram.Histograms; +import com.datadog.trace.core.histogram.Histogram; +import com.datadog.trace.core.histogram.Histograms; import java.util.concurrent.atomic.AtomicLongArray; /** Not thread-safe. Accumulates counts and durations. */ diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Batch.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/Batch.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Batch.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/Batch.java index f3c7ea4d46..d99c11b13a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Batch.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/Batch.java @@ -1,4 +1,4 @@ -package datadog.trace.common.metrics; +package com.datadog.trace.common.metrics; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicLongArray; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/EventListener.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/EventListener.java similarity index 79% rename from features/dd-trace-core/src/main/java/datadog/trace/common/metrics/EventListener.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/EventListener.java index ae5f910b0a..9acf2191c3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/EventListener.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/EventListener.java @@ -1,4 +1,4 @@ -package datadog.trace.common.metrics; +package com.datadog.trace.common.metrics; public interface EventListener { enum EventType { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/InboxItem.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/InboxItem.java new file mode 100644 index 0000000000..f69334ecdc --- /dev/null +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/InboxItem.java @@ -0,0 +1,4 @@ +package com.datadog.trace.common.metrics; + +interface InboxItem {} + diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricKey.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/MetricKey.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricKey.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/MetricKey.java index 4ba23db6d5..0f2a099f3e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricKey.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/MetricKey.java @@ -1,8 +1,8 @@ -package datadog.trace.common.metrics; +package com.datadog.trace.common.metrics; -import static datadog.trace.bootstrap.instrumentation.api.UTF8BytesString.EMPTY; +import static com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString.EMPTY; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; /** The aggregation key for tracked metrics. */ public final class MetricKey { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricWriter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/MetricWriter.java similarity index 82% rename from features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricWriter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/MetricWriter.java index fa26ed2e5d..d2fe567ab6 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricWriter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/MetricWriter.java @@ -1,4 +1,4 @@ -package datadog.trace.common.metrics; +package com.datadog.trace.common.metrics; public interface MetricWriter { void startBucket(int metricCount, long start, long duration); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricsAggregator.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/MetricsAggregator.java similarity index 77% rename from features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricsAggregator.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/MetricsAggregator.java index 3ea6df9c58..a686023679 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricsAggregator.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/MetricsAggregator.java @@ -1,6 +1,6 @@ -package datadog.trace.common.metrics; +package com.datadog.trace.common.metrics; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.core.CoreSpan; import java.util.List; import java.util.concurrent.Future; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/NoOpMetricsAggregator.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/NoOpMetricsAggregator.java index ae34266f26..52c6a21cfa 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/NoOpMetricsAggregator.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/NoOpMetricsAggregator.java @@ -1,8 +1,8 @@ -package datadog.trace.common.metrics; +package com.datadog.trace.common.metrics; import static java.lang.Boolean.FALSE; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.core.CoreSpan; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/Sink.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/Sink.java new file mode 100644 index 0000000000..a5d9d4529f --- /dev/null +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/metrics/Sink.java @@ -0,0 +1,8 @@ +package com.datadog.trace.common.metrics; + +import com.datadog.trace.serialization.ByteBufferConsumer; + +public interface Sink extends ByteBufferConsumer { + + void register(EventListener listener); +} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/AllSampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/AllSampler.java similarity index 76% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/AllSampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/AllSampler.java index 1e381a9d94..398ede76ec 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/AllSampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/AllSampler.java @@ -1,6 +1,6 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.core.CoreSpan; /** Sampler that always says yes... */ public class AllSampler implements Sampler { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/DeterministicSampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/DeterministicSampler.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/DeterministicSampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/DeterministicSampler.java index 350e27a5ee..69722def93 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/DeterministicSampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/DeterministicSampler.java @@ -1,6 +1,6 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.core.CoreSpan; /** * This implements the deterministic sampling algorithm used by the Datadog Agent as well as the diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/ForcePrioritySampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/ForcePrioritySampler.java similarity index 88% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/ForcePrioritySampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/ForcePrioritySampler.java index 69aa8bf36d..f104f4874e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/ForcePrioritySampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/ForcePrioritySampler.java @@ -1,6 +1,6 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.core.CoreSpan; /** A sampler which forces the sampling priority */ public class ForcePrioritySampler implements Sampler, PrioritySampler { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/PrioritySampler.java similarity index 54% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/PrioritySampler.java index 474617de1b..bdf6fdf5bc 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/PrioritySampler.java @@ -1,6 +1,6 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.core.CoreSpan; public interface PrioritySampler { > void setSamplingPriority(T span); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampling.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/PrioritySampling.java similarity index 84% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampling.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/PrioritySampling.java index 18446bcdfe..6772c408f9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/PrioritySampling.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/PrioritySampling.java @@ -1,6 +1,6 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; -/** @deprecated Replaced by {@link datadog.trace.api.sampling.PrioritySampling} . */ +/** @deprecated Replaced by {@link com.datadog.trace.api.sampling.PrioritySampling} . */ @Deprecated public class PrioritySampling { /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateByServiceTraceSampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RateByServiceTraceSampler.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateByServiceTraceSampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RateByServiceTraceSampler.java index 3434b0681c..295dca2f8d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateByServiceTraceSampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RateByServiceTraceSampler.java @@ -1,11 +1,11 @@ -package datadog.trace.common.sampling; - -import datadog.trace.api.cache.DDCache; -import datadog.trace.api.cache.DDCaches; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.sampling.SamplingMechanism; -import datadog.trace.common.writer.RemoteResponseListener; -import datadog.trace.core.CoreSpan; +package com.datadog.trace.common.sampling; + +import com.datadog.trace.api.cache.DDCache; +import com.datadog.trace.api.cache.DDCaches; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.sampling.SamplingMechanism; +import com.datadog.trace.common.writer.RemoteResponseListener; +import com.datadog.trace.core.CoreSpan; import java.util.HashMap; import java.util.Map; import java.util.function.Function; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateSampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RateSampler.java similarity index 63% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateSampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RateSampler.java index d8691a6642..3ee4526b7c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RateSampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RateSampler.java @@ -1,4 +1,4 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; public interface RateSampler extends Sampler { double getSampleRate(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RuleBasedTraceSampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RuleBasedTraceSampler.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RuleBasedTraceSampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RuleBasedTraceSampler.java index c02a5daaab..9cf2784f33 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/RuleBasedTraceSampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RuleBasedTraceSampler.java @@ -1,14 +1,14 @@ -package datadog.trace.common.sampling; - -import datadog.trace.api.config.TracerConfig; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.sampling.SamplingMechanism; -import datadog.trace.common.sampling.SamplingRule.AlwaysMatchesSamplingRule; -import datadog.trace.common.sampling.SamplingRule.OperationSamplingRule; -import datadog.trace.common.sampling.SamplingRule.ServiceSamplingRule; -import datadog.trace.common.sampling.SamplingRule.TraceSamplingRule; -import datadog.trace.core.CoreSpan; -import datadog.trace.core.util.SimpleRateLimiter; +package com.datadog.trace.common.sampling; + +import com.datadog.trace.api.config.TracerConfig; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.sampling.SamplingMechanism; +import com.datadog.trace.common.sampling.SamplingRule.AlwaysMatchesSamplingRule; +import com.datadog.trace.common.sampling.SamplingRule.OperationSamplingRule; +import com.datadog.trace.common.sampling.SamplingRule.ServiceSamplingRule; +import com.datadog.trace.common.sampling.SamplingRule.TraceSamplingRule; +import com.datadog.trace.core.CoreSpan; +import com.datadog.trace.core.util.SimpleRateLimiter; import java.util.ArrayList; import java.util.List; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/Sampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/Sampler.java similarity index 87% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/Sampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/Sampler.java index 63309af2b9..a70a1d877d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/Sampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/Sampler.java @@ -1,14 +1,14 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; -import static datadog.trace.bootstrap.instrumentation.api.SamplerConstants.DROP; -import static datadog.trace.bootstrap.instrumentation.api.SamplerConstants.KEEP; +import static com.datadog.trace.bootstrap.instrumentation.api.SamplerConstants.DROP; +import static com.datadog.trace.bootstrap.instrumentation.api.SamplerConstants.KEEP; -import datadog.trace.api.Config; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.config.TracerConfig; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.sampling.SamplingMechanism; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.config.TracerConfig; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.sampling.SamplingMechanism; +import com.datadog.trace.core.CoreSpan; import java.util.Map; import java.util.Properties; import org.slf4j.Logger; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SamplingRule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SamplingRule.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SamplingRule.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SamplingRule.java index c2aded26b4..26c3b80e3b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SamplingRule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SamplingRule.java @@ -1,10 +1,10 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; -import datadog.trace.core.CoreSpan; -import datadog.trace.core.util.Matcher; -import datadog.trace.core.util.Matchers; -import datadog.trace.core.util.SimpleRateLimiter; -import datadog.trace.core.util.TagsMatcher; +import com.datadog.trace.core.CoreSpan; +import com.datadog.trace.core.util.Matcher; +import com.datadog.trace.core.util.Matchers; +import com.datadog.trace.core.util.SimpleRateLimiter; +import com.datadog.trace.core.util.TagsMatcher; import java.util.Map; import java.util.regex.Pattern; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SingleSpanSampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SingleSpanSampler.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SingleSpanSampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SingleSpanSampler.java index 2d01192465..78a708b96c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SingleSpanSampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SingleSpanSampler.java @@ -1,11 +1,11 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; -import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES; -import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES_FILE; +import static com.datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES; +import static com.datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES_FILE; -import datadog.trace.api.Config; -import datadog.trace.core.CoreSpan; -import datadog.trace.core.util.SimpleRateLimiter; +import com.datadog.trace.api.Config; +import com.datadog.trace.core.CoreSpan; +import com.datadog.trace.core.util.SimpleRateLimiter; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SpanSamplingRules.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SpanSamplingRules.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SpanSamplingRules.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SpanSamplingRules.java index 954ded5480..c060664941 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/SpanSamplingRules.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SpanSamplingRules.java @@ -1,11 +1,11 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; import com.squareup.moshi.FromJson; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.JsonReader; import com.squareup.moshi.Moshi; import com.squareup.moshi.Types; -import datadog.trace.api.sampling.SamplingRule; +import com.datadog.trace.api.sampling.SamplingRule; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/TraceSamplingRules.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/TraceSamplingRules.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/common/sampling/TraceSamplingRules.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/TraceSamplingRules.java index d97e1a4081..93c9cc0db0 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/sampling/TraceSamplingRules.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/TraceSamplingRules.java @@ -1,10 +1,10 @@ -package datadog.trace.common.sampling; +package com.datadog.trace.common.sampling; import com.squareup.moshi.FromJson; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.Moshi; import com.squareup.moshi.Types; -import datadog.trace.api.sampling.SamplingRule; +import com.datadog.trace.api.sampling.SamplingRule; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Collections; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/CompositePayloadDispatcher.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/CompositePayloadDispatcher.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/CompositePayloadDispatcher.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/CompositePayloadDispatcher.java index 3822d62160..9a6b62ae3b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/CompositePayloadDispatcher.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/CompositePayloadDispatcher.java @@ -1,6 +1,6 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.core.CoreSpan; import java.util.ArrayList; import java.util.Collection; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/DDSpanJsonAdapter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/DDSpanJsonAdapter.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/DDSpanJsonAdapter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/DDSpanJsonAdapter.java index 93c6995d4e..49392b6281 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/DDSpanJsonAdapter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/DDSpanJsonAdapter.java @@ -1,12 +1,12 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.JsonReader; import com.squareup.moshi.Moshi; import com.squareup.moshi.Types; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTraceId; -import datadog.trace.core.DDSpan; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.core.DDSpan; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Type; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ListWriter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ListWriter.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/ListWriter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ListWriter.java index 6393547c6e..9cec2d0d79 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ListWriter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ListWriter.java @@ -1,8 +1,8 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; -import datadog.trace.core.DDSpan; -import datadog.trace.core.MetadataConsumer; -import datadog.trace.core.tagprocessor.PeerServiceCalculator; +import com.datadog.trace.core.DDSpan; +import com.datadog.trace.core.MetadataConsumer; +import com.datadog.trace.core.tagprocessor.PeerServiceCalculator; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/LoggingWriter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/LoggingWriter.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/LoggingWriter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/LoggingWriter.java index 24a6361db3..b280b2bcc9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/LoggingWriter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/LoggingWriter.java @@ -1,9 +1,9 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.Moshi; import com.squareup.moshi.Types; -import datadog.trace.core.DDSpan; +import com.datadog.trace.core.DDSpan; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/Payload.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/Payload.java index 24ec61b608..3e7d03d6ff 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Payload.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/Payload.java @@ -1,4 +1,4 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; import java.nio.ByteBuffer; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcher.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/PayloadDispatcher.java similarity index 76% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcher.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/PayloadDispatcher.java index ee39606822..5c4527c484 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PayloadDispatcher.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/PayloadDispatcher.java @@ -1,6 +1,6 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.core.CoreSpan; import java.util.Collection; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PrintingWriter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/PrintingWriter.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/PrintingWriter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/PrintingWriter.java index e882abcd5e..763c4773ff 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/PrintingWriter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/PrintingWriter.java @@ -1,9 +1,9 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.Moshi; import com.squareup.moshi.Types; -import datadog.trace.core.DDSpan; +import com.datadog.trace.core.DDSpan; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteApi.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteApi.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java index 232f5a8d2f..8796758eca 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteApi.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java @@ -1,6 +1,6 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; -import datadog.trace.relocate.api.IOLogger; +import com.datadog.trace.relocate.api.IOLogger; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import org.slf4j.Logger; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapper.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteMapper.java similarity index 80% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapper.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteMapper.java index 48b64de1be..63a7ca8e4d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapper.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteMapper.java @@ -1,13 +1,13 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; import static java.nio.charset.StandardCharsets.UTF_8; -import datadog.trace.serialization.Mapper; -import datadog.trace.serialization.Writable; -import datadog.trace.api.DDTags; -import datadog.trace.bootstrap.instrumentation.api.Tags; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.serialization.Mapper; +import com.datadog.trace.serialization.Writable; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.bootstrap.instrumentation.api.Tags; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.core.CoreSpan; import java.util.List; public interface RemoteMapper extends Mapper>> { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapperDiscovery.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteMapperDiscovery.java similarity index 69% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapperDiscovery.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteMapperDiscovery.java index a09674282f..e12b27871a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteMapperDiscovery.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteMapperDiscovery.java @@ -1,4 +1,4 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; public interface RemoteMapperDiscovery { void discover(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteResponseListener.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteResponseListener.java similarity index 84% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteResponseListener.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteResponseListener.java index d51440a087..3aa83a6fee 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/RemoteResponseListener.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteResponseListener.java @@ -1,4 +1,4 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/SpanSamplingWorker.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/SpanSamplingWorker.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/SpanSamplingWorker.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/SpanSamplingWorker.java index fb1b4ec9e2..d3181f0cc6 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/SpanSamplingWorker.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/SpanSamplingWorker.java @@ -1,14 +1,14 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; -import static datadog.trace.util.AgentThreadFactory.AgentThread.SPAN_SAMPLING_PROCESSOR; -import static datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; -import static datadog.trace.util.AgentThreadFactory.newAgentThread; +import static com.datadog.trace.util.AgentThreadFactory.AgentThread.SPAN_SAMPLING_PROCESSOR; +import static com.datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; +import static com.datadog.trace.util.AgentThreadFactory.newAgentThread; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import datadog.trace.ddagent.DroppingPolicy; -import datadog.trace.common.sampling.SingleSpanSampler; -import datadog.trace.core.DDSpan; -import datadog.trace.core.monitor.HealthMetrics; +import com.datadog.trace.ddagent.DroppingPolicy; +import com.datadog.trace.common.sampling.SingleSpanSampler; +import com.datadog.trace.core.DDSpan; +import com.datadog.trace.core.monitor.HealthMetrics; import java.util.ArrayList; import java.util.List; import java.util.Queue; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceProcessingWorker.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceProcessingWorker.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceProcessingWorker.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceProcessingWorker.java index 227c53f42b..b13448aba0 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceProcessingWorker.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceProcessingWorker.java @@ -1,19 +1,19 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; -import static datadog.trace.util.AgentThreadFactory.AgentThread.TRACE_PROCESSOR; -import static datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; -import static datadog.trace.util.AgentThreadFactory.newAgentThread; +import static com.datadog.trace.util.AgentThreadFactory.AgentThread.TRACE_PROCESSOR; +import static com.datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; +import static com.datadog.trace.util.AgentThreadFactory.newAgentThread; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import datadog.trace.ddagent.DroppingPolicy; -import datadog.trace.api.Config; -import datadog.trace.common.sampling.SingleSpanSampler; -import datadog.trace.common.writer.ddagent.FlushEvent; -import datadog.trace.common.writer.ddagent.Prioritization; -import datadog.trace.common.writer.ddagent.PrioritizationStrategy; -import datadog.trace.core.CoreSpan; -import datadog.trace.core.DDSpan; -import datadog.trace.core.monitor.HealthMetrics; +import com.datadog.trace.ddagent.DroppingPolicy; +import com.datadog.trace.api.Config; +import com.datadog.trace.common.sampling.SingleSpanSampler; +import com.datadog.trace.common.writer.ddagent.FlushEvent; +import com.datadog.trace.common.writer.ddagent.Prioritization; +import com.datadog.trace.common.writer.ddagent.PrioritizationStrategy; +import com.datadog.trace.core.CoreSpan; +import com.datadog.trace.core.DDSpan; +import com.datadog.trace.core.monitor.HealthMetrics; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceStructureWriter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceStructureWriter.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceStructureWriter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceStructureWriter.java index 9c2cefd23d..6b7998709b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/TraceStructureWriter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceStructureWriter.java @@ -1,9 +1,9 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.Platform; -import datadog.trace.core.DDSpan; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.Platform; +import com.datadog.trace.core.DDSpan; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Writer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/Writer.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/Writer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/Writer.java index cd4ccf70bf..ce72466649 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/Writer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/Writer.java @@ -1,6 +1,6 @@ -package datadog.trace.common.writer; +package com.datadog.trace.common.writer; -import datadog.trace.core.DDSpan; +import com.datadog.trace.core.DDSpan; import java.io.Closeable; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/FlushEvent.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/FlushEvent.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/FlushEvent.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/FlushEvent.java index edb2aa1528..64ee528f74 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/FlushEvent.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/FlushEvent.java @@ -1,4 +1,4 @@ -package datadog.trace.common.writer.ddagent; +package com.datadog.trace.common.writer.ddagent; import java.util.concurrent.CountDownLatch; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/Prioritization.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/Prioritization.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/Prioritization.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/Prioritization.java index ab78164a94..2db2dc2189 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/Prioritization.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/Prioritization.java @@ -1,10 +1,10 @@ -package datadog.trace.common.writer.ddagent; +package com.datadog.trace.common.writer.ddagent; -import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; -import static datadog.trace.api.sampling.PrioritySampling.USER_DROP; +import static com.datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static com.datadog.trace.api.sampling.PrioritySampling.USER_DROP; -import datadog.trace.ddagent.DroppingPolicy; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.ddagent.DroppingPolicy; +import com.datadog.trace.core.CoreSpan; import java.util.List; import java.util.Queue; import java.util.concurrent.CountDownLatch; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java similarity index 81% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java index 5918015e3a..f6af92cb59 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/PrioritizationStrategy.java @@ -1,6 +1,6 @@ -package datadog.trace.common.writer.ddagent; +package com.datadog.trace.common.writer.ddagent; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.core.CoreSpan; import java.util.List; import java.util.concurrent.TimeUnit; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapper.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/TraceMapper.java similarity index 60% rename from features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapper.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/TraceMapper.java index 3866a056b5..bc2819d226 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapper.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ddagent/TraceMapper.java @@ -1,9 +1,9 @@ -package datadog.trace.common.writer.ddagent; +package com.datadog.trace.common.writer.ddagent; -import datadog.trace.api.DDTags; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; -import datadog.trace.common.writer.RemoteMapper; -import datadog.trace.core.DDSpanContext; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.common.writer.RemoteMapper; +import com.datadog.trace.core.DDSpanContext; public interface TraceMapper extends RemoteMapper { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/context/TraceScope.java b/features/dd-trace-core/src/main/java/com/datadog/trace/context/TraceScope.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/context/TraceScope.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/context/TraceScope.java index effa5a5758..ff683b1931 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/context/TraceScope.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/context/TraceScope.java @@ -1,4 +1,4 @@ -package datadog.trace.context; +package com.datadog.trace.context; import java.io.Closeable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/CoreSpan.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/CoreSpan.java index ca2bbd44ab..e834f7e53d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/CoreSpan.java @@ -1,6 +1,6 @@ -package datadog.trace.core; +package com.datadog.trace.core; -import datadog.trace.api.DDTraceId; +import com.datadog.trace.api.DDTraceId; public interface CoreSpan> { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/CoreTracer.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/CoreTracer.java index 53484ebe76..f48965f416 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/CoreTracer.java @@ -1,74 +1,74 @@ -package datadog.trace.core; +package com.datadog.trace.core; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; -import static datadog.trace.api.DDTags.PROFILING_CONTEXT_ENGINE; -import static datadog.trace.util.AgentThreadFactory.AGENT_THREAD_GROUP; -import static datadog.trace.util.CollectionUtils.tryMakeImmutableMap; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; +import static com.datadog.trace.api.DDTags.PROFILING_CONTEXT_ENGINE; +import static com.datadog.trace.util.AgentThreadFactory.AGENT_THREAD_GROUP; +import static com.datadog.trace.util.CollectionUtils.tryMakeImmutableMap; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; -import datadog.trace.monitor.Monitoring; -import datadog.trace.monitor.Recording; -import datadog.trace.monitor.NoOpRecording; -import datadog.trace.api.Config; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.DynamicConfig; -import datadog.trace.api.EndpointCheckpointer; -import datadog.trace.api.EndpointCheckpointerHolder; -import datadog.trace.api.EndpointTracker; -import datadog.trace.api.IdGenerationStrategy; -import datadog.trace.api.InstrumenterConfig; -import datadog.trace.api.StatsDClient; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.config.GeneralConfig; -import datadog.trace.api.experimental.DataStreamsCheckpointer; -import datadog.trace.api.flare.TracerFlare; -import datadog.trace.api.gateway.CallbackProvider; -import datadog.trace.api.gateway.InstrumentationGateway; -import datadog.trace.api.gateway.RequestContext; -import datadog.trace.api.gateway.RequestContextSlot; -import datadog.trace.api.gateway.SubscriptionService; -import datadog.trace.api.interceptor.MutableSpan; -import datadog.trace.api.interceptor.TraceInterceptor; -import datadog.trace.api.internal.TraceSegment; -import datadog.trace.api.metrics.SpanMetricRegistry; -import datadog.trace.api.naming.SpanNaming; -import datadog.trace.api.profiling.Timer; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.scopemanager.ScopeListener; -import datadog.trace.api.time.SystemTimeSource; -import datadog.trace.api.time.TimeSource; -import datadog.trace.bootstrap.instrumentation.api.AgentDataStreamsMonitoring; -import datadog.trace.bootstrap.instrumentation.api.AgentHistogram; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.AgentScope; -import datadog.trace.bootstrap.instrumentation.api.AgentScopeManager; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; -import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.PathwayContext; -import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; -import datadog.trace.bootstrap.instrumentation.api.ScopeState; -import datadog.trace.bootstrap.instrumentation.api.TagContext; -import datadog.trace.civisibility.interceptor.CiVisibilityTraceInterceptor; -import datadog.trace.common.metrics.MetricsAggregator; -import datadog.trace.common.metrics.NoOpMetricsAggregator; -import datadog.trace.common.sampling.Sampler; -import datadog.trace.common.sampling.SpanSamplingRules; -import datadog.trace.common.sampling.TraceSamplingRules; -import datadog.trace.common.writer.Writer; -import datadog.trace.core.datastreams.DataStreamsMonitoring; -import datadog.trace.core.datastreams.NoOpDataStreamMonitoring; -import datadog.trace.core.histogram.Histograms; -import datadog.trace.core.monitor.HealthMetrics; -import datadog.trace.core.propagation.*; -import datadog.trace.core.scopemanager.ContinuableScopeManager; -import datadog.trace.core.taginterceptor.RuleFlags; -import datadog.trace.core.taginterceptor.TagInterceptor; -import datadog.trace.relocate.api.RatelimitedLogger; +import com.datadog.trace.monitor.Monitoring; +import com.datadog.trace.monitor.Recording; +import com.datadog.trace.monitor.NoOpRecording; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.DynamicConfig; +import com.datadog.trace.api.EndpointCheckpointer; +import com.datadog.trace.api.EndpointCheckpointerHolder; +import com.datadog.trace.api.EndpointTracker; +import com.datadog.trace.api.IdGenerationStrategy; +import com.datadog.trace.api.InstrumenterConfig; +import com.datadog.trace.api.StatsDClient; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.api.config.GeneralConfig; +import com.datadog.trace.api.experimental.DataStreamsCheckpointer; +import com.datadog.trace.api.flare.TracerFlare; +import com.datadog.trace.api.gateway.CallbackProvider; +import com.datadog.trace.api.gateway.InstrumentationGateway; +import com.datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.gateway.RequestContextSlot; +import com.datadog.trace.api.gateway.SubscriptionService; +import com.datadog.trace.api.interceptor.MutableSpan; +import com.datadog.trace.api.interceptor.TraceInterceptor; +import com.datadog.trace.api.internal.TraceSegment; +import com.datadog.trace.api.metrics.SpanMetricRegistry; +import com.datadog.trace.api.naming.SpanNaming; +import com.datadog.trace.api.profiling.Timer; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.scopemanager.ScopeListener; +import com.datadog.trace.api.time.SystemTimeSource; +import com.datadog.trace.api.time.TimeSource; +import com.datadog.trace.bootstrap.instrumentation.api.AgentDataStreamsMonitoring; +import com.datadog.trace.bootstrap.instrumentation.api.AgentHistogram; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.AgentScope; +import com.datadog.trace.bootstrap.instrumentation.api.AgentScopeManager; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import com.datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import com.datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; +import com.datadog.trace.bootstrap.instrumentation.api.ScopeSource; +import com.datadog.trace.bootstrap.instrumentation.api.ScopeState; +import com.datadog.trace.bootstrap.instrumentation.api.TagContext; +import com.datadog.trace.civisibility.interceptor.CiVisibilityTraceInterceptor; +import com.datadog.trace.common.metrics.MetricsAggregator; +import com.datadog.trace.common.metrics.NoOpMetricsAggregator; +import com.datadog.trace.common.sampling.Sampler; +import com.datadog.trace.common.sampling.SpanSamplingRules; +import com.datadog.trace.common.sampling.TraceSamplingRules; +import com.datadog.trace.common.writer.Writer; +import com.datadog.trace.core.datastreams.DataStreamsMonitoring; +import com.datadog.trace.core.datastreams.NoOpDataStreamMonitoring; +import com.datadog.trace.core.histogram.Histograms; +import com.datadog.trace.core.monitor.HealthMetrics; +import com.datadog.trace.core.propagation.*; +import com.datadog.trace.core.scopemanager.ContinuableScopeManager; +import com.datadog.trace.core.taginterceptor.RuleFlags; +import com.datadog.trace.core.taginterceptor.TagInterceptor; +import com.datadog.trace.relocate.api.RatelimitedLogger; import java.io.IOException; import java.lang.ref.WeakReference; @@ -96,7 +96,7 @@ /** * Main entrypoint into the tracer implementation. In addition to implementing - * datadog.trace.api.Tracer and TracerAPI, it coordinates many functions necessary creating, + * com.datadog.trace.api.Tracer and TracerAPI, it coordinates many functions necessary creating, * reporting, and propagating traces */ public class CoreTracer implements AgentTracer.TracerAPI { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java index dfa76bf097..dfde7a025a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java @@ -1,32 +1,32 @@ -package datadog.trace.core; +package com.datadog.trace.core; -import static datadog.trace.api.DDTags.TRACE_START_TIME; -import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; -import static datadog.trace.api.sampling.PrioritySampling.USER_DROP; -import static datadog.trace.bootstrap.instrumentation.api.InstrumentationTags.RECORD_END_TO_END_DURATION_MS; -import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_STATUS; +import static com.datadog.trace.api.DDTags.TRACE_START_TIME; +import static com.datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static com.datadog.trace.api.sampling.PrioritySampling.USER_DROP; +import static com.datadog.trace.bootstrap.instrumentation.api.InstrumentationTags.RECORD_END_TO_END_DURATION_MS; +import static com.datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_STATUS; import static java.util.concurrent.TimeUnit.MICROSECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import datadog.trace.api.Config; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTags; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.EndpointTracker; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.gateway.Flow; -import datadog.trace.api.gateway.RequestContext; -import datadog.trace.api.metrics.SpanMetricRegistry; -import datadog.trace.api.metrics.SpanMetrics; -import datadog.trace.api.profiling.TransientProfilingContextHolder; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.sampling.SamplingMechanism; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; -import datadog.trace.bootstrap.instrumentation.api.AttachableWrapper; -import datadog.trace.bootstrap.instrumentation.api.ErrorPriorities; -import datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.EndpointTracker; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.gateway.Flow; +import com.datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.metrics.SpanMetricRegistry; +import com.datadog.trace.api.metrics.SpanMetrics; +import com.datadog.trace.api.profiling.TransientProfilingContextHolder; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.sampling.SamplingMechanism; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; +import com.datadog.trace.bootstrap.instrumentation.api.AttachableWrapper; +import com.datadog.trace.bootstrap.instrumentation.api.ErrorPriorities; +import com.datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Collections; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanContext.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanContext.java index c7763468e2..0520f93348 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanContext.java @@ -1,33 +1,33 @@ -package datadog.trace.core; - -import static datadog.trace.api.DDTags.SPAN_LINKS; -import static datadog.trace.api.cache.RadixTreeCache.HTTP_STATUSES; -import static datadog.trace.bootstrap.instrumentation.api.ErrorPriorities.UNSET; - -import datadog.trace.api.DDTags; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.Functions; -import datadog.trace.api.cache.DDCache; -import datadog.trace.api.cache.DDCaches; -import datadog.trace.api.config.TracerConfig; -import datadog.trace.api.gateway.BlockResponseFunction; -import datadog.trace.api.gateway.RequestContext; -import datadog.trace.api.gateway.RequestContextSlot; -import datadog.trace.api.internal.TraceSegment; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.sampling.SamplingMechanism; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; -import datadog.trace.bootstrap.instrumentation.api.PathwayContext; -import datadog.trace.bootstrap.instrumentation.api.ProfilerContext; -import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; -import datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; -import datadog.trace.bootstrap.instrumentation.api.Tags; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; -import datadog.trace.core.propagation.PropagationTags; -import datadog.trace.core.taginterceptor.TagInterceptor; -import datadog.trace.core.tagprocessor.TagsPostProcessorFactory; -import datadog.trace.util.TagsHelper; +package com.datadog.trace.core; + +import static com.datadog.trace.api.DDTags.SPAN_LINKS; +import static com.datadog.trace.api.cache.RadixTreeCache.HTTP_STATUSES; +import static com.datadog.trace.bootstrap.instrumentation.api.ErrorPriorities.UNSET; + +import com.datadog.trace.api.DDTags; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.Functions; +import com.datadog.trace.api.cache.DDCache; +import com.datadog.trace.api.cache.DDCaches; +import com.datadog.trace.api.config.TracerConfig; +import com.datadog.trace.api.gateway.BlockResponseFunction; +import com.datadog.trace.api.gateway.RequestContext; +import com.datadog.trace.api.gateway.RequestContextSlot; +import com.datadog.trace.api.internal.TraceSegment; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.sampling.SamplingMechanism; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; +import com.datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import com.datadog.trace.bootstrap.instrumentation.api.ProfilerContext; +import com.datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; +import com.datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; +import com.datadog.trace.bootstrap.instrumentation.api.Tags; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.core.propagation.PropagationTags; +import com.datadog.trace.core.taginterceptor.TagInterceptor; +import com.datadog.trace.core.tagprocessor.TagsPostProcessorFactory; +import com.datadog.trace.util.TagsHelper; import java.io.Closeable; import java.io.IOException; import java.util.Collections; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanLink.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanLink.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanLink.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanLink.java index 69f0659c08..060b6824a1 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/DDSpanLink.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanLink.java @@ -1,18 +1,18 @@ -package datadog.trace.core; +package com.datadog.trace.core; -import static datadog.trace.bootstrap.instrumentation.api.SpanLinkAttributes.EMPTY; +import static com.datadog.trace.bootstrap.instrumentation.api.SpanLinkAttributes.EMPTY; import com.squareup.moshi.FromJson; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.Moshi; import com.squareup.moshi.ToJson; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTraceId; -import datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; -import datadog.trace.bootstrap.instrumentation.api.SpanLink; -import datadog.trace.bootstrap.instrumentation.api.SpanLinkAttributes; -import datadog.trace.core.propagation.ExtractedContext; -import datadog.trace.core.propagation.PropagationTags; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; +import com.datadog.trace.bootstrap.instrumentation.api.SpanLink; +import com.datadog.trace.bootstrap.instrumentation.api.SpanLinkAttributes; +import com.datadog.trace.core.propagation.ExtractedContext; +import com.datadog.trace.core.propagation.PropagationTags; import java.util.List; import java.util.Map; import org.slf4j.Logger; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/DDTraceCoreInfo.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDTraceCoreInfo.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/core/DDTraceCoreInfo.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/DDTraceCoreInfo.java index 4f689e1b75..f524a9d965 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/DDTraceCoreInfo.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDTraceCoreInfo.java @@ -1,4 +1,4 @@ -package datadog.trace.core; +package com.datadog.trace.core; import java.io.BufferedReader; import java.io.InputStreamReader; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/LongRunningTracesTracker.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/LongRunningTracesTracker.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/LongRunningTracesTracker.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/LongRunningTracesTracker.java index 11fdbf57f2..5f40c11b49 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/LongRunningTracesTracker.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/LongRunningTracesTracker.java @@ -1,9 +1,9 @@ -package datadog.trace.core; +package com.datadog.trace.core; -//import datadog.trace.ddagent.DDAgentFeaturesDiscovery; -//import datadog.trace.ddagent.SharedCommunicationObjects; -import datadog.trace.api.Config; -import datadog.trace.core.monitor.HealthMetrics; +//import com.datadog.trace.ddagent.DDAgentFeaturesDiscovery; +//import com.datadog.trace.ddagent.SharedCommunicationObjects; +import com.datadog.trace.api.Config; +import com.datadog.trace.core.monitor.HealthMetrics; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/Metadata.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/Metadata.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/core/Metadata.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/Metadata.java index f1f7945416..55b5a84e6c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/Metadata.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/Metadata.java @@ -1,8 +1,8 @@ -package datadog.trace.core; +package com.datadog.trace.core; -import static datadog.trace.api.sampling.PrioritySampling.UNSET; +import static com.datadog.trace.api.sampling.PrioritySampling.UNSET; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import java.util.Map; public final class Metadata { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/MetadataConsumer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/MetadataConsumer.java similarity index 86% rename from features/dd-trace-core/src/main/java/datadog/trace/core/MetadataConsumer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/MetadataConsumer.java index 0166348bc0..b0a42cf2aa 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/MetadataConsumer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/MetadataConsumer.java @@ -1,4 +1,4 @@ -package datadog.trace.core; +package com.datadog.trace.core; import java.util.function.Consumer; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/PendingTrace.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/core/PendingTrace.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java index cb6d33f44a..26c866cd9e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/PendingTrace.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java @@ -1,15 +1,15 @@ -package datadog.trace.core; - -import datadog.trace.monitor.Recording; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.time.TimeSource; -import datadog.trace.bootstrap.instrumentation.api.AgentScope; -import datadog.trace.bootstrap.instrumentation.api.AgentTrace; -import datadog.trace.common.sampling.PrioritySampler; -import datadog.trace.core.CoreTracer.ConfigSnapshot; -import datadog.trace.core.monitor.HealthMetrics; +package com.datadog.trace.core; + +import com.datadog.trace.monitor.Recording; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.time.TimeSource; +import com.datadog.trace.bootstrap.instrumentation.api.AgentScope; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTrace; +import com.datadog.trace.common.sampling.PrioritySampler; +import com.datadog.trace.core.CoreTracer.ConfigSnapshot; +import com.datadog.trace.core.monitor.HealthMetrics; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentLinkedDeque; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/PendingTraceBuffer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTraceBuffer.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/core/PendingTraceBuffer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTraceBuffer.java index e735f1ce4a..07b192706e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/PendingTraceBuffer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTraceBuffer.java @@ -1,12 +1,12 @@ -package datadog.trace.core; +package com.datadog.trace.core; -import static datadog.trace.util.AgentThreadFactory.AgentThread.TRACE_MONITOR; -import static datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; -import static datadog.trace.util.AgentThreadFactory.newAgentThread; +import static com.datadog.trace.util.AgentThreadFactory.AgentThread.TRACE_MONITOR; +import static com.datadog.trace.util.AgentThreadFactory.THREAD_JOIN_TIMOUT_MS; +import static com.datadog.trace.util.AgentThreadFactory.newAgentThread; -import datadog.trace.api.Config; -import datadog.trace.api.time.TimeSource; -import datadog.trace.core.monitor.HealthMetrics; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.time.TimeSource; +import com.datadog.trace.core.monitor.HealthMetrics; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.jctools.queues.MessagePassingQueue; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/StatusLogger.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/StatusLogger.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/StatusLogger.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/StatusLogger.java index cf9609cb1c..f44e1c9de6 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/StatusLogger.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/StatusLogger.java @@ -1,17 +1,17 @@ -package datadog.trace.core; +package com.datadog.trace.core; -import static datadog.trace.api.Config.isDatadogProfilerEnablementOverridden; -import static datadog.trace.api.Config.isDatadogProfilerSafeInCurrentEnvironment; +import static com.datadog.trace.api.Config.isDatadogProfilerEnablementOverridden; +import static com.datadog.trace.api.Config.isDatadogProfilerSafeInCurrentEnvironment; import static java.util.concurrent.TimeUnit.MILLISECONDS; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.JsonReader; import com.squareup.moshi.JsonWriter; import com.squareup.moshi.Moshi; -import datadog.trace.api.Config; -import datadog.trace.api.ProductActivation; -import datadog.trace.logging.LoggingSettingsDescription; -import datadog.trace.util.AgentTaskScheduler; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.ProductActivation; +import com.datadog.trace.logging.LoggingSettingsDescription; +import com.datadog.trace.util.AgentTaskScheduler; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Type; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextExtractor.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamContextExtractor.java similarity index 82% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextExtractor.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamContextExtractor.java index e51ec15803..4218100ded 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextExtractor.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamContextExtractor.java @@ -1,11 +1,11 @@ -package datadog.trace.core.datastreams; - -import datadog.trace.api.TraceConfig; -import datadog.trace.api.WellKnownTags; -import datadog.trace.api.time.TimeSource; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.TagContext; -import datadog.trace.core.propagation.HttpCodec; +package com.datadog.trace.core.datastreams; + +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.WellKnownTags; +import com.datadog.trace.api.time.TimeSource; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.TagContext; +import com.datadog.trace.core.propagation.HttpCodec; import java.util.function.Supplier; public class DataStreamContextExtractor implements HttpCodec.Extractor { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextInjector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamContextInjector.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextInjector.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamContextInjector.java index d354a72c45..26494f7d4d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamContextInjector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamContextInjector.java @@ -1,11 +1,11 @@ -package datadog.trace.core.datastreams; +package com.datadog.trace.core.datastreams; -import static datadog.trace.api.DDTags.PATHWAY_HASH; -import static datadog.trace.bootstrap.instrumentation.api.PathwayContext.PROPAGATION_KEY_BASE64; +import static com.datadog.trace.api.DDTags.PATHWAY_HASH; +import static com.datadog.trace.bootstrap.instrumentation.api.PathwayContext.PROPAGATION_KEY_BASE64; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.PathwayContext; import java.io.IOException; import java.util.LinkedHashMap; import org.slf4j.Logger; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java similarity index 74% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java index a9460bae22..e666b4bf53 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamsContextCarrierAdapter.java @@ -1,8 +1,8 @@ -package datadog.trace.core.datastreams; +package com.datadog.trace.core.datastreams; -import datadog.trace.api.experimental.DataStreamsContextCarrier; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation.KeyClassifier; +import com.datadog.trace.api.experimental.DataStreamsContextCarrier; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation.KeyClassifier; import java.util.Map; public class DataStreamsContextCarrierAdapter diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamsMonitoring.java similarity index 67% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamsMonitoring.java index d6df69cc8e..e30c765f21 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamsMonitoring.java @@ -1,11 +1,11 @@ -package datadog.trace.core.datastreams; +package com.datadog.trace.core.datastreams; -import datadog.trace.api.experimental.DataStreamsContextCarrier; -import datadog.trace.bootstrap.instrumentation.api.AgentDataStreamsMonitoring; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan.Context; -import datadog.trace.bootstrap.instrumentation.api.PathwayContext; -import datadog.trace.core.propagation.HttpCodec; +import com.datadog.trace.api.experimental.DataStreamsContextCarrier; +import com.datadog.trace.bootstrap.instrumentation.api.AgentDataStreamsMonitoring; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan.Context; +import com.datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import com.datadog.trace.core.propagation.HttpCodec; public interface DataStreamsMonitoring extends AgentDataStreamsMonitoring, AutoCloseable { void start(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java similarity index 74% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java index 07d040dd9a..09d89b390c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DatastreamsPayloadWriter.java @@ -1,4 +1,4 @@ -package datadog.trace.core.datastreams; +package com.datadog.trace.core.datastreams; import java.util.Collection; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DefaultPathwayContext.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DefaultPathwayContext.java index 340af2c559..5827bbe14c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DefaultPathwayContext.java @@ -1,4 +1,4 @@ -package datadog.trace.core.datastreams; +package com.datadog.trace.core.datastreams; import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.UTF_8; @@ -7,13 +7,13 @@ import com.datadoghq.sketch.ddsketch.encoding.ByteArrayInput; import com.datadoghq.sketch.ddsketch.encoding.GrowingByteArrayOutput; import com.datadoghq.sketch.ddsketch.encoding.VarEncodingHelper; -import datadog.trace.api.Config; -import datadog.trace.api.WellKnownTags; -import datadog.trace.api.time.TimeSource; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.PathwayContext; -import datadog.trace.bootstrap.instrumentation.api.StatsPoint; -import datadog.trace.util.FNV64Hash; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.WellKnownTags; +import com.datadog.trace.api.time.TimeSource; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import com.datadog.trace.bootstrap.instrumentation.api.StatsPoint; +import com.datadog.trace.util.FNV64Hash; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java similarity index 74% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java index 957f48894c..3ccf9c42c3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/NoOpDataStreamMonitoring.java @@ -1,11 +1,11 @@ -package datadog.trace.core.datastreams; - -import datadog.trace.api.experimental.DataStreamsContextCarrier; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.PathwayContext; -import datadog.trace.bootstrap.instrumentation.api.StatsPoint; -import datadog.trace.core.propagation.HttpCodec; +package com.datadog.trace.core.datastreams; + +import com.datadog.trace.api.experimental.DataStreamsContextCarrier; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import com.datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import com.datadog.trace.bootstrap.instrumentation.api.StatsPoint; +import com.datadog.trace.core.propagation.HttpCodec; import java.util.LinkedHashMap; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/SchemaSampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/SchemaSampler.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/SchemaSampler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/SchemaSampler.java index 07af84b758..5ab95d9551 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/SchemaSampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/SchemaSampler.java @@ -1,4 +1,4 @@ -package datadog.trace.core.datastreams; +package com.datadog.trace.core.datastreams; import java.util.concurrent.atomic.AtomicInteger; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsBucket.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/StatsBucket.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsBucket.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/StatsBucket.java index de58e3cccf..30867e9871 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsBucket.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/StatsBucket.java @@ -1,7 +1,7 @@ -package datadog.trace.core.datastreams; +package com.datadog.trace.core.datastreams; -import datadog.trace.bootstrap.instrumentation.api.Backlog; -import datadog.trace.bootstrap.instrumentation.api.StatsPoint; +import com.datadog.trace.bootstrap.instrumentation.api.Backlog; +import com.datadog.trace.bootstrap.instrumentation.api.StatsPoint; import java.util.Collection; import java.util.HashMap; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsGroup.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/StatsGroup.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsGroup.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/StatsGroup.java index bbdb7dcc4e..e9c67b14bb 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/StatsGroup.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/StatsGroup.java @@ -1,7 +1,7 @@ -package datadog.trace.core.datastreams; +package com.datadog.trace.core.datastreams; -import datadog.trace.core.histogram.Histogram; -import datadog.trace.core.histogram.Histograms; +import com.datadog.trace.core.histogram.Histogram; +import com.datadog.trace.core.histogram.Histograms; import java.util.List; public class StatsGroup { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/TagsProcessor.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/TagsProcessor.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/TagsProcessor.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/TagsProcessor.java index 287be4daeb..d318382468 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/datastreams/TagsProcessor.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/TagsProcessor.java @@ -1,7 +1,7 @@ -package datadog.trace.core.datastreams; +package com.datadog.trace.core.datastreams; -import datadog.trace.api.cache.DDCache; -import datadog.trace.api.cache.DDCaches; +import com.datadog.trace.api.cache.DDCache; +import com.datadog.trace.api.cache.DDCaches; import java.util.HashMap; import java.util.Map; import java.util.function.Function; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histogram.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/histogram/Histogram.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histogram.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/histogram/Histogram.java index 556177d424..0ccb34728c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histogram.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/histogram/Histogram.java @@ -1,7 +1,7 @@ -package datadog.trace.core.histogram; +package com.datadog.trace.core.histogram; import com.datadoghq.sketch.ddsketch.DDSketch; -import datadog.trace.bootstrap.instrumentation.api.AgentHistogram; +import com.datadog.trace.bootstrap.instrumentation.api.AgentHistogram; import java.nio.ByteBuffer; /** Wrapper around the DDSketch library so that it can be used in an instrumentation */ diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histograms.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/histogram/Histograms.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histograms.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/histogram/Histograms.java index 4dca763458..9fd4604f9b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/histogram/Histograms.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/histogram/Histograms.java @@ -1,4 +1,4 @@ -package datadog.trace.core.histogram; +package com.datadog.trace.core.histogram; import com.datadoghq.sketch.ddsketch.DDSketch; import com.datadoghq.sketch.ddsketch.DDSketches; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/HealthMetrics.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/HealthMetrics.java index f0dd6cc885..1d1ec851f4 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/HealthMetrics.java @@ -1,7 +1,7 @@ -package datadog.trace.core.monitor; +package com.datadog.trace.core.monitor; -import datadog.trace.common.writer.RemoteApi; -import datadog.trace.core.DDSpan; +import com.datadog.trace.common.writer.RemoteApi; +import com.datadog.trace.core.DDSpan; import java.util.List; /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/MonitoringImpl.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/MonitoringImpl.java similarity index 82% rename from features/dd-trace-core/src/main/java/datadog/trace/core/monitor/MonitoringImpl.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/MonitoringImpl.java index 275067a96c..1750d8357b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/MonitoringImpl.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/MonitoringImpl.java @@ -1,11 +1,11 @@ -package datadog.trace.core.monitor; +package com.datadog.trace.core.monitor; -import datadog.trace.monitor.Counter; -import datadog.trace.monitor.Monitoring; -import datadog.trace.monitor.NoOpCounter; -import datadog.trace.monitor.NoOpRecording; -import datadog.trace.monitor.Recording; -import datadog.trace.api.StatsDClient; +import com.datadog.trace.monitor.Counter; +import com.datadog.trace.monitor.Monitoring; +import com.datadog.trace.monitor.NoOpCounter; +import com.datadog.trace.monitor.NoOpRecording; +import com.datadog.trace.monitor.Recording; +import com.datadog.trace.api.StatsDClient; import java.util.concurrent.TimeUnit; public final class MonitoringImpl implements Monitoring { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/StatsDCounter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/StatsDCounter.java similarity index 74% rename from features/dd-trace-core/src/main/java/datadog/trace/core/monitor/StatsDCounter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/StatsDCounter.java index 221ee55712..01726ff50d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/StatsDCounter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/StatsDCounter.java @@ -1,9 +1,9 @@ -package datadog.trace.core.monitor; +package com.datadog.trace.core.monitor; -import static datadog.trace.core.monitor.Utils.mergeTags; +import static com.datadog.trace.core.monitor.Utils.mergeTags; -import datadog.trace.monitor.Counter; -import datadog.trace.api.StatsDClient; +import com.datadog.trace.monitor.Counter; +import com.datadog.trace.api.StatsDClient; public final class StatsDCounter implements Counter { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/ThreadLocalRecording.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/ThreadLocalRecording.java similarity index 84% rename from features/dd-trace-core/src/main/java/datadog/trace/core/monitor/ThreadLocalRecording.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/ThreadLocalRecording.java index 546f5183e0..ed78dbea60 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/ThreadLocalRecording.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/ThreadLocalRecording.java @@ -1,6 +1,6 @@ -package datadog.trace.core.monitor; +package com.datadog.trace.core.monitor; -import datadog.trace.monitor.Recording; +import com.datadog.trace.monitor.Recording; public class ThreadLocalRecording extends Recording { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Timer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/Timer.java similarity index 88% rename from features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Timer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/Timer.java index 8fe4c7685b..207a00c296 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Timer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/Timer.java @@ -1,13 +1,13 @@ -package datadog.trace.core.monitor; +package com.datadog.trace.core.monitor; -import static datadog.trace.core.monitor.Utils.mergeTags; +import static com.datadog.trace.core.monitor.Utils.mergeTags; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; -import datadog.trace.monitor.Recording; -import datadog.trace.api.StatsDClient; -import datadog.trace.core.histogram.Histogram; -import datadog.trace.core.histogram.Histograms; +import com.datadog.trace.monitor.Recording; +import com.datadog.trace.api.StatsDClient; +import com.datadog.trace.core.histogram.Histogram; +import com.datadog.trace.core.histogram.Histograms; /** * A timer which records times in a histogram, and flushes stats from the histogram after a diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Utils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/Utils.java similarity index 88% rename from features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Utils.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/Utils.java index c69de28ec6..26b16a8c99 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/monitor/Utils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/monitor/Utils.java @@ -1,4 +1,4 @@ -package datadog.trace.core.monitor; +package com.datadog.trace.core.monitor; import java.util.Arrays; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/B3HttpCodec.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/B3HttpCodec.java index e39f074585..d35074de68 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/B3HttpCodec.java @@ -1,18 +1,18 @@ -package datadog.trace.core.propagation; - -import static datadog.trace.api.TracePropagationStyle.B3MULTI; -import static datadog.trace.api.TracePropagationStyle.B3SINGLE; -import static datadog.trace.core.propagation.HttpCodec.firstHeaderValue; - -import datadog.trace.api.Config; -import datadog.trace.api.DD128bTraceId; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.core.DDSpanContext; +package com.datadog.trace.core.propagation; + +import static com.datadog.trace.api.TracePropagationStyle.B3MULTI; +import static com.datadog.trace.api.TracePropagationStyle.B3SINGLE; +import static com.datadog.trace.core.propagation.HttpCodec.firstHeaderValue; + +import com.datadog.trace.api.Config; +import com.datadog.trace.api.DD128bTraceId; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.core.DDSpanContext; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/B3TraceId.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/B3TraceId.java index a9376cd659..ed8468b601 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/B3TraceId.java @@ -1,7 +1,7 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import datadog.trace.api.DD128bTraceId; -import datadog.trace.api.DDTraceId; +import com.datadog.trace.api.DD128bTraceId; +import com.datadog.trace.api.DDTraceId; /** A B3 {@link DDTraceId} along with its original {@link String} representation. */ public class B3TraceId extends DDTraceId { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ContextInterpreter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ContextInterpreter.java similarity index 81% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ContextInterpreter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ContextInterpreter.java index 01488d3d93..b15d262013 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ContextInterpreter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ContextInterpreter.java @@ -1,33 +1,33 @@ -package datadog.trace.core.propagation; - -import static datadog.trace.core.propagation.HttpCodec.CF_CONNECTING_IP_KEY; -import static datadog.trace.core.propagation.HttpCodec.CF_CONNECTING_IP_V6_KEY; -import static datadog.trace.core.propagation.HttpCodec.FASTLY_CLIENT_IP_KEY; -import static datadog.trace.core.propagation.HttpCodec.FORWARDED_FOR_KEY; -import static datadog.trace.core.propagation.HttpCodec.FORWARDED_KEY; -import static datadog.trace.core.propagation.HttpCodec.TRUE_CLIENT_IP_KEY; -import static datadog.trace.core.propagation.HttpCodec.USER_AGENT_KEY; -import static datadog.trace.core.propagation.HttpCodec.X_CLIENT_IP_KEY; -import static datadog.trace.core.propagation.HttpCodec.X_CLUSTER_CLIENT_IP_KEY; -import static datadog.trace.core.propagation.HttpCodec.X_FORWARDED_FOR_KEY; -import static datadog.trace.core.propagation.HttpCodec.X_FORWARDED_HOST_KEY; -import static datadog.trace.core.propagation.HttpCodec.X_FORWARDED_KEY; -import static datadog.trace.core.propagation.HttpCodec.X_FORWARDED_PORT_KEY; -import static datadog.trace.core.propagation.HttpCodec.X_FORWARDED_PROTO_KEY; -import static datadog.trace.core.propagation.HttpCodec.X_REAL_IP_KEY; - -import datadog.trace.api.Config; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.Functions; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.cache.DDCache; -import datadog.trace.api.cache.DDCaches; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.bootstrap.ActiveSubsystems; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.TagContext; +package com.datadog.trace.core.propagation; + +import static com.datadog.trace.core.propagation.HttpCodec.CF_CONNECTING_IP_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.CF_CONNECTING_IP_V6_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.FASTLY_CLIENT_IP_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.FORWARDED_FOR_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.FORWARDED_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.TRUE_CLIENT_IP_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.USER_AGENT_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.X_CLIENT_IP_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.X_CLUSTER_CLIENT_IP_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.X_FORWARDED_FOR_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.X_FORWARDED_HOST_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.X_FORWARDED_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.X_FORWARDED_PORT_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.X_FORWARDED_PROTO_KEY; +import static com.datadog.trace.core.propagation.HttpCodec.X_REAL_IP_KEY; + +import com.datadog.trace.api.Config; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.Functions; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.api.cache.DDCache; +import com.datadog.trace.api.cache.DDCaches; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.bootstrap.ActiveSubsystems; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.TagContext; import java.util.Collections; import java.util.Map; import java.util.TreeMap; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/CorePropagation.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/CorePropagation.java index 135fff0327..5066638106 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/CorePropagation.java @@ -1,10 +1,10 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.core.DDSpanContext; -import datadog.trace.core.datastreams.DataStreamContextInjector; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.core.DDSpanContext; +import com.datadog.trace.core.datastreams.DataStreamContextInjector; import java.util.LinkedHashMap; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/DatadogHttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/DatadogHttpCodec.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/DatadogHttpCodec.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/DatadogHttpCodec.java index 9624a54a50..1e98911c13 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/DatadogHttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/DatadogHttpCodec.java @@ -1,23 +1,23 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import static datadog.trace.api.TracePropagationStyle.DATADOG; -import static datadog.trace.core.propagation.HttpCodec.firstHeaderValue; -import static datadog.trace.core.propagation.XRayHttpCodec.XRayContextInterpreter.handleXRayTraceHeader; -import static datadog.trace.core.propagation.XRayHttpCodec.X_AMZN_TRACE_ID; +import static com.datadog.trace.api.TracePropagationStyle.DATADOG; +import static com.datadog.trace.core.propagation.HttpCodec.firstHeaderValue; +import static com.datadog.trace.core.propagation.XRayHttpCodec.XRayContextInterpreter.handleXRayTraceHeader; +import static com.datadog.trace.core.propagation.XRayHttpCodec.X_AMZN_TRACE_ID; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import datadog.trace.api.Config; -import datadog.trace.api.DD128bTraceId; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTags; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.TagContext; -import datadog.trace.core.DDSpanContext; -import datadog.trace.core.propagation.PropagationTags.HeaderType; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.DD128bTraceId; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.TagContext; +import com.datadog.trace.core.DDSpanContext; +import com.datadog.trace.core.propagation.PropagationTags.HeaderType; import java.util.Map; import java.util.TreeMap; import java.util.function.Supplier; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ExtractedContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ExtractedContext.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ExtractedContext.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ExtractedContext.java index d164eec30b..2454138cc4 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ExtractedContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ExtractedContext.java @@ -1,10 +1,10 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.bootstrap.instrumentation.api.TagContext; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.bootstrap.instrumentation.api.TagContext; import java.util.Map; /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HaystackHttpCodec.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HaystackHttpCodec.java index e272bac6d9..fa2ad45a88 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HaystackHttpCodec.java @@ -1,17 +1,17 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import static datadog.trace.api.TracePropagationStyle.HAYSTACK; -import static datadog.trace.core.propagation.HttpCodec.firstHeaderValue; +import static com.datadog.trace.api.TracePropagationStyle.HAYSTACK; +import static com.datadog.trace.core.propagation.HttpCodec.firstHeaderValue; -import datadog.trace.api.Config; -import datadog.trace.api.DD64bTraceId; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.core.DDSpanContext; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.DD64bTraceId; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.core.DDSpanContext; import java.util.Map; import java.util.TreeMap; import java.util.function.Supplier; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HttpCodec.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HttpCodec.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HttpCodec.java index c1e8df5c46..7cd50af483 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/HttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HttpCodec.java @@ -1,17 +1,17 @@ -package datadog.trace.core.propagation; - -import static datadog.trace.api.TracePropagationStyle.TRACECONTEXT; - -import datadog.trace.api.Config; -import datadog.trace.api.DD128bTraceId; -import datadog.trace.api.DD64bTraceId; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.TagContext; -import datadog.trace.core.DDSpanContext; -import datadog.trace.core.DDSpanLink; +package com.datadog.trace.core.propagation; + +import static com.datadog.trace.api.TracePropagationStyle.TRACECONTEXT; + +import com.datadog.trace.api.Config; +import com.datadog.trace.api.DD128bTraceId; +import com.datadog.trace.api.DD64bTraceId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.TagContext; +import com.datadog.trace.core.DDSpanContext; +import com.datadog.trace.core.DDSpanLink; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoOpCorePropagation.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/NoOpCorePropagation.java similarity index 80% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoOpCorePropagation.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/NoOpCorePropagation.java index fad468a5f7..dd1cf2c706 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoOpCorePropagation.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/NoOpCorePropagation.java @@ -1,10 +1,10 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.core.DDSpanContext; -import datadog.trace.core.datastreams.DataStreamContextInjector; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.core.DDSpanContext; +import com.datadog.trace.core.datastreams.DataStreamContextInjector; import java.util.LinkedHashMap; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoneCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/NoneCodec.java similarity index 68% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoneCodec.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/NoneCodec.java index 377062667a..849f0c962c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/NoneCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/NoneCodec.java @@ -1,8 +1,8 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.TagContext; -import datadog.trace.core.DDSpanContext; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.TagContext; +import com.datadog.trace.core.DDSpanContext; public class NoneCodec { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/PropagationTags.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/PropagationTags.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/PropagationTags.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/PropagationTags.java index 00ed3d0f53..5bc82ebb40 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/PropagationTags.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/PropagationTags.java @@ -1,9 +1,9 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH; -import datadog.trace.api.Config; -import datadog.trace.core.propagation.ptags.PTagsFactory; +import com.datadog.trace.api.Config; +import com.datadog.trace.core.propagation.ptags.PTagsFactory; import java.util.HashMap; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/TagContextExtractor.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/TagContextExtractor.java similarity index 78% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/TagContextExtractor.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/TagContextExtractor.java index cb22ef0c08..0d21045d5a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/TagContextExtractor.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/TagContextExtractor.java @@ -1,8 +1,8 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import datadog.trace.api.TraceConfig; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.TagContext; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.TagContext; import java.util.function.Supplier; public class TagContextExtractor implements HttpCodec.Extractor { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/W3CHttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/W3CHttpCodec.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/W3CHttpCodec.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/W3CHttpCodec.java index 76ca949e22..c47530c4e7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/W3CHttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/W3CHttpCodec.java @@ -1,26 +1,26 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import static datadog.trace.api.TracePropagationStyle.TRACECONTEXT; -import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; -import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; -import static datadog.trace.core.propagation.HttpCodec.firstHeaderValue; -import static datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; +import static com.datadog.trace.api.TracePropagationStyle.TRACECONTEXT; +import static com.datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static com.datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; +import static com.datadog.trace.core.propagation.HttpCodec.firstHeaderValue; +import static com.datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import datadog.trace.api.Config; -import datadog.trace.api.DD128bTraceId; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTags; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.internal.util.LongStringUtils; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.sampling.SamplingMechanism; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.bootstrap.instrumentation.api.TagContext; -import datadog.trace.core.DDSpanContext; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.DD128bTraceId; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.api.internal.util.LongStringUtils; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.sampling.SamplingMechanism; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.bootstrap.instrumentation.api.TagContext; +import com.datadog.trace.core.DDSpanContext; import java.util.Map; import java.util.TreeMap; import java.util.function.Supplier; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/XRayHttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/XRayHttpCodec.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/XRayHttpCodec.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/XRayHttpCodec.java index 15e7d54e47..25f644906b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/XRayHttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/XRayHttpCodec.java @@ -1,22 +1,22 @@ -package datadog.trace.core.propagation; +package com.datadog.trace.core.propagation; -import static datadog.trace.api.DDTags.ORIGIN_KEY; -import static datadog.trace.api.TracePropagationStyle.XRAY; -import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; -import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; +import static com.datadog.trace.api.DDTags.ORIGIN_KEY; +import static com.datadog.trace.api.TracePropagationStyle.XRAY; +import static com.datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static com.datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import datadog.trace.api.Config; -import datadog.trace.api.DD64bTraceId; -import datadog.trace.api.DDSpanId; -import datadog.trace.api.DDTags; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; -import datadog.trace.core.DDSpanContext; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.DD64bTraceId; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.TraceConfig; +import com.datadog.trace.api.TracePropagationStyle; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import com.datadog.trace.core.DDSpanContext; import java.util.Map; import java.util.TreeMap; import java.util.function.Supplier; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java index 12bd59738a..ec2bc2ddac 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java @@ -1,9 +1,9 @@ -package datadog.trace.core.propagation.ptags; +package com.datadog.trace.core.propagation.ptags; -import datadog.trace.core.propagation.PropagationTags; -import datadog.trace.core.propagation.ptags.PTagsFactory.PTags; -import datadog.trace.core.propagation.ptags.TagElement.Encoding; -import datadog.trace.relocate.api.RatelimitedLogger; +import com.datadog.trace.core.propagation.PropagationTags; +import com.datadog.trace.core.propagation.ptags.PTagsFactory.PTags; +import com.datadog.trace.core.propagation.ptags.TagElement.Encoding; +import com.datadog.trace.relocate.api.RatelimitedLogger; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/PTagsCodec.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsCodec.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/PTagsCodec.java index 2379c39d36..2a7c229726 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/PTagsCodec.java @@ -1,10 +1,10 @@ -package datadog.trace.core.propagation.ptags; +package com.datadog.trace.core.propagation.ptags; -import static datadog.trace.core.propagation.ptags.PTagsFactory.PROPAGATION_ERROR_TAG_KEY; +import static com.datadog.trace.core.propagation.ptags.PTagsFactory.PROPAGATION_ERROR_TAG_KEY; -import datadog.trace.core.propagation.PropagationTags; -import datadog.trace.core.propagation.ptags.PTagsFactory.PTags; -import datadog.trace.core.propagation.ptags.TagElement.Encoding; +import com.datadog.trace.core.propagation.PropagationTags; +import com.datadog.trace.core.propagation.ptags.PTagsFactory.PTags; +import com.datadog.trace.core.propagation.ptags.TagElement.Encoding; import java.util.Iterator; import java.util.List; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsFactory.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/PTagsFactory.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsFactory.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/PTagsFactory.java index 21ab986a16..04b3a466fa 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/PTagsFactory.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/PTagsFactory.java @@ -1,15 +1,15 @@ -package datadog.trace.core.propagation.ptags; - -import static datadog.trace.core.propagation.PropagationTags.HeaderType.DATADOG; -import static datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; -import static datadog.trace.core.propagation.ptags.PTagsCodec.DECISION_MAKER_TAG; -import static datadog.trace.core.propagation.ptags.PTagsCodec.TRACE_ID_TAG; - -import datadog.trace.api.internal.util.LongStringUtils; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.sampling.SamplingMechanism; -import datadog.trace.core.propagation.PropagationTags; -import datadog.trace.core.propagation.PropagationTags.HeaderType; +package com.datadog.trace.core.propagation.ptags; + +import static com.datadog.trace.core.propagation.PropagationTags.HeaderType.DATADOG; +import static com.datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; +import static com.datadog.trace.core.propagation.ptags.PTagsCodec.DECISION_MAKER_TAG; +import static com.datadog.trace.core.propagation.ptags.PTagsCodec.TRACE_ID_TAG; + +import com.datadog.trace.api.internal.util.LongStringUtils; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.api.sampling.SamplingMechanism; +import com.datadog.trace.core.propagation.PropagationTags; +import com.datadog.trace.core.propagation.PropagationTags.HeaderType; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.Collections; import java.util.EnumMap; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagElement.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagElement.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagElement.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagElement.java index 8805e86d04..3710ba1ace 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagElement.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagElement.java @@ -1,4 +1,4 @@ -package datadog.trace.core.propagation.ptags; +package com.datadog.trace.core.propagation.ptags; abstract class TagElement implements CharSequence { public enum Encoding { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagKey.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagKey.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagKey.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagKey.java index 75b5276fdd..4d175fe51e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagKey.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagKey.java @@ -1,7 +1,7 @@ -package datadog.trace.core.propagation.ptags; +package com.datadog.trace.core.propagation.ptags; -import datadog.trace.api.cache.DDCaches; -import datadog.trace.api.cache.DDPartialKeyCache; +import com.datadog.trace.api.cache.DDCaches; +import com.datadog.trace.api.cache.DDPartialKeyCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagValue.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagValue.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagValue.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagValue.java index 8c1d6412fe..ea946e57fa 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/TagValue.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagValue.java @@ -1,7 +1,7 @@ -package datadog.trace.core.propagation.ptags; +package com.datadog.trace.core.propagation.ptags; -import datadog.trace.api.cache.DDCaches; -import datadog.trace.api.cache.DDPartialKeyCache; +import com.datadog.trace.api.cache.DDCaches; +import com.datadog.trace.api.cache.DDPartialKeyCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java index f3fd57efcc..f2ef7b9e4e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java @@ -1,12 +1,12 @@ -package datadog.trace.core.propagation.ptags; +package com.datadog.trace.core.propagation.ptags; -import static datadog.trace.api.internal.util.LongStringUtils.toHexStringPadded; +import static com.datadog.trace.api.internal.util.LongStringUtils.toHexStringPadded; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.core.propagation.PropagationTags; -import datadog.trace.core.propagation.ptags.PTagsFactory.PTags; -import datadog.trace.core.propagation.ptags.TagElement.Encoding; -import datadog.trace.relocate.api.RatelimitedLogger; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.core.propagation.PropagationTags; +import com.datadog.trace.core.propagation.ptags.PTagsFactory.PTags; +import com.datadog.trace.core.propagation.ptags.TagElement.Encoding; +import com.datadog.trace.relocate.api.RatelimitedLogger; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/AbstractContinuation.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/AbstractContinuation.java similarity index 79% rename from features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/AbstractContinuation.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/AbstractContinuation.java index 094c8feb59..0d93e528e4 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/AbstractContinuation.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/AbstractContinuation.java @@ -1,8 +1,8 @@ -package datadog.trace.core.scopemanager; +package com.datadog.trace.core.scopemanager; -import datadog.trace.bootstrap.instrumentation.api.AgentScope; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentTrace; +import com.datadog.trace.bootstrap.instrumentation.api.AgentScope; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTrace; /** * This class must not be a nested class of ContinuableScope to avoid an unconstrained chain of diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ConcurrentContinuation.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ConcurrentContinuation.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ConcurrentContinuation.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ConcurrentContinuation.java index fe5a5986a9..1a4922bd02 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ConcurrentContinuation.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ConcurrentContinuation.java @@ -1,7 +1,7 @@ -package datadog.trace.core.scopemanager; +package com.datadog.trace.core.scopemanager; -import datadog.trace.bootstrap.instrumentation.api.AgentScope; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentScope; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScope.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScope.java index 86667d5a24..51cb29c79a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScope.java @@ -1,12 +1,12 @@ -package datadog.trace.core.scopemanager; - -import datadog.trace.api.Stateful; -import datadog.trace.api.scopemanager.ExtendedScopeListener; -import datadog.trace.api.scopemanager.ScopeListener; -import datadog.trace.bootstrap.instrumentation.api.AgentScope; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AttachableWrapper; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; +package com.datadog.trace.core.scopemanager; + +import com.datadog.trace.api.Stateful; +import com.datadog.trace.api.scopemanager.ExtendedScopeListener; +import com.datadog.trace.api.scopemanager.ScopeListener; +import com.datadog.trace.bootstrap.instrumentation.api.AgentScope; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AttachableWrapper; +import com.datadog.trace.bootstrap.instrumentation.api.ScopeSource; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import javax.annotation.Nonnull; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScopeManager.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScopeManager.java index 217c33699e..cac32e99b9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScopeManager.java @@ -1,26 +1,26 @@ -package datadog.trace.core.scopemanager; +package com.datadog.trace.core.scopemanager; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.NoopAgentSpan; +import static com.datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; +import static com.datadog.trace.bootstrap.instrumentation.api.AgentTracer.NoopAgentSpan; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; -import datadog.trace.api.Config; -import datadog.trace.api.Stateful; -import datadog.trace.api.scopemanager.ExtendedScopeListener; -import datadog.trace.api.scopemanager.ScopeListener; -import datadog.trace.bootstrap.instrumentation.api.AgentScope; -import datadog.trace.bootstrap.instrumentation.api.AgentScopeManager; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ProfilerContext; -import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; -import datadog.trace.bootstrap.instrumentation.api.ScopeState; -import datadog.trace.core.monitor.HealthMetrics; -import datadog.trace.relocate.api.RatelimitedLogger; -import datadog.trace.util.AgentTaskScheduler; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.Stateful; +import com.datadog.trace.api.scopemanager.ExtendedScopeListener; +import com.datadog.trace.api.scopemanager.ScopeListener; +import com.datadog.trace.bootstrap.instrumentation.api.AgentScope; +import com.datadog.trace.bootstrap.instrumentation.api.AgentScopeManager; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import com.datadog.trace.bootstrap.instrumentation.api.ProfilerContext; +import com.datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; +import com.datadog.trace.bootstrap.instrumentation.api.ScopeSource; +import com.datadog.trace.bootstrap.instrumentation.api.ScopeState; +import com.datadog.trace.core.monitor.HealthMetrics; +import com.datadog.trace.relocate.api.RatelimitedLogger; +import com.datadog.trace.util.AgentTaskScheduler; import java.util.Iterator; import java.util.List; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuingScope.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuingScope.java similarity index 81% rename from features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuingScope.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuingScope.java index f929fdb5df..44443c0535 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuingScope.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuingScope.java @@ -1,7 +1,7 @@ -package datadog.trace.core.scopemanager; +package com.datadog.trace.core.scopemanager; -import datadog.trace.api.Stateful; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.api.Stateful; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; final class ContinuingScope extends ContinuableScope { /** Continuation that created this scope. */ diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ScopeStack.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ScopeStack.java index 78ea56d7d8..539e28f0b7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ScopeStack.java @@ -1,7 +1,7 @@ -package datadog.trace.core.scopemanager; +package com.datadog.trace.core.scopemanager; -import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; +import com.datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; +import com.datadog.trace.bootstrap.instrumentation.api.ScopeSource; import java.util.ArrayDeque; /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/SingleContinuation.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/SingleContinuation.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/SingleContinuation.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/SingleContinuation.java index 06aae99c35..f881d2b281 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/SingleContinuation.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/SingleContinuation.java @@ -1,7 +1,7 @@ -package datadog.trace.core.scopemanager; +package com.datadog.trace.core.scopemanager; -import datadog.trace.bootstrap.instrumentation.api.AgentScope; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentScope; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; /** diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/RuleFlags.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/taginterceptor/RuleFlags.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/RuleFlags.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/taginterceptor/RuleFlags.java index 3ebcfdd488..fd828a8638 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/RuleFlags.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/taginterceptor/RuleFlags.java @@ -1,6 +1,6 @@ -package datadog.trace.core.taginterceptor; +package com.datadog.trace.core.taginterceptor; -import datadog.trace.api.Config; +import com.datadog.trace.api.Config; public class RuleFlags { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/TagInterceptor.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/taginterceptor/TagInterceptor.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/TagInterceptor.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/taginterceptor/TagInterceptor.java index 475f1d1448..31b8648062 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/taginterceptor/TagInterceptor.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/taginterceptor/TagInterceptor.java @@ -1,36 +1,36 @@ -package datadog.trace.core.taginterceptor; +package com.datadog.trace.core.taginterceptor; -import static datadog.trace.api.DDTags.ANALYTICS_SAMPLE_RATE; -import static datadog.trace.api.DDTags.MEASURED; -import static datadog.trace.api.DDTags.ORIGIN_KEY; -import static datadog.trace.api.DDTags.SPAN_TYPE; -import static datadog.trace.api.sampling.PrioritySampling.USER_DROP; -import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_METHOD; -import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_STATUS; -import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_URL; -import static datadog.trace.core.taginterceptor.RuleFlags.Feature.FORCE_MANUAL_DROP; -import static datadog.trace.core.taginterceptor.RuleFlags.Feature.PEER_SERVICE; -import static datadog.trace.core.taginterceptor.RuleFlags.Feature.RESOURCE_NAME; -import static datadog.trace.core.taginterceptor.RuleFlags.Feature.SERVICE_NAME; -import static datadog.trace.core.taginterceptor.RuleFlags.Feature.STATUS_404; -import static datadog.trace.core.taginterceptor.RuleFlags.Feature.STATUS_404_DECORATOR; -import static datadog.trace.core.taginterceptor.RuleFlags.Feature.URL_AS_RESOURCE_NAME; +import static com.datadog.trace.api.DDTags.ANALYTICS_SAMPLE_RATE; +import static com.datadog.trace.api.DDTags.MEASURED; +import static com.datadog.trace.api.DDTags.ORIGIN_KEY; +import static com.datadog.trace.api.DDTags.SPAN_TYPE; +import static com.datadog.trace.api.sampling.PrioritySampling.USER_DROP; +import static com.datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_METHOD; +import static com.datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_STATUS; +import static com.datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_URL; +import static com.datadog.trace.core.taginterceptor.RuleFlags.Feature.FORCE_MANUAL_DROP; +import static com.datadog.trace.core.taginterceptor.RuleFlags.Feature.PEER_SERVICE; +import static com.datadog.trace.core.taginterceptor.RuleFlags.Feature.RESOURCE_NAME; +import static com.datadog.trace.core.taginterceptor.RuleFlags.Feature.SERVICE_NAME; +import static com.datadog.trace.core.taginterceptor.RuleFlags.Feature.STATUS_404; +import static com.datadog.trace.core.taginterceptor.RuleFlags.Feature.STATUS_404_DECORATOR; +import static com.datadog.trace.core.taginterceptor.RuleFlags.Feature.URL_AS_RESOURCE_NAME; -import datadog.trace.api.Config; -import datadog.trace.api.ConfigDefaults; -import datadog.trace.api.DDTags; -import datadog.trace.api.Pair; -import datadog.trace.api.config.GeneralConfig; -import datadog.trace.api.env.CapturedEnvironment; -import datadog.trace.api.normalize.HttpResourceNames; -import datadog.trace.api.sampling.SamplingMechanism; -import datadog.trace.bootstrap.instrumentation.api.ErrorPriorities; -import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags; -import datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; -import datadog.trace.bootstrap.instrumentation.api.Tags; -import datadog.trace.bootstrap.instrumentation.api.URIUtils; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; -import datadog.trace.core.DDSpanContext; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.ConfigDefaults; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.api.Pair; +import com.datadog.trace.api.config.GeneralConfig; +import com.datadog.trace.api.env.CapturedEnvironment; +import com.datadog.trace.api.normalize.HttpResourceNames; +import com.datadog.trace.api.sampling.SamplingMechanism; +import com.datadog.trace.bootstrap.instrumentation.api.ErrorPriorities; +import com.datadog.trace.bootstrap.instrumentation.api.InstrumentationTags; +import com.datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities; +import com.datadog.trace.bootstrap.instrumentation.api.Tags; +import com.datadog.trace.bootstrap.instrumentation.api.URIUtils; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.core.DDSpanContext; import java.net.URI; import java.util.Set; import javax.annotation.Nonnull; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/BaseServiceAdder.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/BaseServiceAdder.java similarity index 80% rename from features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/BaseServiceAdder.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/BaseServiceAdder.java index 4081460663..4a401cfa60 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/BaseServiceAdder.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/BaseServiceAdder.java @@ -1,8 +1,8 @@ -package datadog.trace.core.tagprocessor; +package com.datadog.trace.core.tagprocessor; -import datadog.trace.api.DDTags; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; -import datadog.trace.core.DDSpanContext; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.core.DDSpanContext; import java.util.Map; import javax.annotation.Nullable; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PeerServiceCalculator.java similarity index 86% rename from features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PeerServiceCalculator.java index 7c473d8d0a..45f21324e6 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PeerServiceCalculator.java @@ -1,10 +1,10 @@ -package datadog.trace.core.tagprocessor; +package com.datadog.trace.core.tagprocessor; -import datadog.trace.api.Config; -import datadog.trace.api.DDTags; -import datadog.trace.api.naming.NamingSchema; -import datadog.trace.api.naming.SpanNaming; -import datadog.trace.bootstrap.instrumentation.api.Tags; +import com.datadog.trace.api.Config; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.api.naming.NamingSchema; +import com.datadog.trace.api.naming.SpanNaming; +import com.datadog.trace.bootstrap.instrumentation.api.Tags; import java.util.Map; import javax.annotation.Nonnull; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PostProcessorChain.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PostProcessorChain.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PostProcessorChain.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PostProcessorChain.java index ffadb33671..48ce52b881 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PostProcessorChain.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PostProcessorChain.java @@ -1,6 +1,6 @@ -package datadog.trace.core.tagprocessor; +package com.datadog.trace.core.tagprocessor; -import datadog.trace.core.DDSpanContext; +import com.datadog.trace.core.DDSpanContext; import java.util.Map; import java.util.Objects; import javax.annotation.Nonnull; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/QueryObfuscator.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/QueryObfuscator.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/QueryObfuscator.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/QueryObfuscator.java index 07e4a03db7..aea6ea83f4 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/QueryObfuscator.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/QueryObfuscator.java @@ -1,11 +1,11 @@ -package datadog.trace.core.tagprocessor; +package com.datadog.trace.core.tagprocessor; import com.google.re2j.Matcher; import com.google.re2j.Pattern; import com.google.re2j.PatternSyntaxException; -import datadog.trace.api.DDTags; -import datadog.trace.bootstrap.instrumentation.api.Tags; -import datadog.trace.util.Strings; +import com.datadog.trace.api.DDTags; +import com.datadog.trace.bootstrap.instrumentation.api.Tags; +import com.datadog.trace.util.Strings; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessor.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/TagsPostProcessor.java similarity index 76% rename from features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessor.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/TagsPostProcessor.java index 55baaa2d4a..6d0a72b725 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessor.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/TagsPostProcessor.java @@ -1,6 +1,6 @@ -package datadog.trace.core.tagprocessor; +package com.datadog.trace.core.tagprocessor; -import datadog.trace.core.DDSpanContext; +import com.datadog.trace.core.DDSpanContext; import java.util.Map; public interface TagsPostProcessor { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java index 74aa721562..8ca34ddf06 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java @@ -1,6 +1,6 @@ -package datadog.trace.core.tagprocessor; +package com.datadog.trace.core.tagprocessor; -import datadog.trace.api.Config; +import com.datadog.trace.api.Config; import java.util.ArrayList; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/GlobPattern.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/GlobPattern.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/core/util/GlobPattern.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/util/GlobPattern.java index c0fd0499b9..adaf0621b5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/util/GlobPattern.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/GlobPattern.java @@ -1,4 +1,4 @@ -package datadog.trace.core.util; +package com.datadog.trace.core.util; import java.util.regex.Pattern; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/LRUCache.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/LRUCache.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/core/util/LRUCache.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/util/LRUCache.java index b8d993ec04..66361b9b90 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/util/LRUCache.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/LRUCache.java @@ -1,4 +1,4 @@ -package datadog.trace.core.util; +package com.datadog.trace.core.util; import java.util.LinkedHashMap; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/Matcher.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/Matcher.java similarity index 73% rename from features/dd-trace-core/src/main/java/datadog/trace/core/util/Matcher.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/util/Matcher.java index 972954e5eb..849f5e6e5b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/util/Matcher.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/Matcher.java @@ -1,4 +1,4 @@ -package datadog.trace.core.util; +package com.datadog.trace.core.util; public interface Matcher { boolean matches(String str); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/Matchers.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/Matchers.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/core/util/Matchers.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/util/Matchers.java index 4ea92fecbe..ce32cc7c06 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/util/Matchers.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/Matchers.java @@ -1,4 +1,4 @@ -package datadog.trace.core.util; +package com.datadog.trace.core.util; import java.util.regex.Pattern; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/NoneSystemAccessProvider.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/NoneSystemAccessProvider.java similarity index 80% rename from features/dd-trace-core/src/main/java/datadog/trace/core/util/NoneSystemAccessProvider.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/util/NoneSystemAccessProvider.java index 1f1a9cd3ef..c5a91ade5c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/util/NoneSystemAccessProvider.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/NoneSystemAccessProvider.java @@ -1,4 +1,4 @@ -package datadog.trace.core.util; +package com.datadog.trace.core.util; final class NoneSystemAccessProvider implements SystemAccessProvider { @Override diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/SimpleRateLimiter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SimpleRateLimiter.java similarity index 95% rename from features/dd-trace-core/src/main/java/datadog/trace/core/util/SimpleRateLimiter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SimpleRateLimiter.java index a011c61f61..3e25927377 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/util/SimpleRateLimiter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SimpleRateLimiter.java @@ -1,7 +1,7 @@ -package datadog.trace.core.util; +package com.datadog.trace.core.util; -import datadog.trace.api.time.SystemTimeSource; -import datadog.trace.api.time.TimeSource; +import com.datadog.trace.api.time.SystemTimeSource; +import com.datadog.trace.api.time.TimeSource; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccess.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SystemAccess.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccess.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SystemAccess.java index da82cf7162..6612012ae7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccess.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SystemAccess.java @@ -1,6 +1,6 @@ -package datadog.trace.core.util; +package com.datadog.trace.core.util; -import datadog.trace.api.Config; +import com.datadog.trace.api.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +37,7 @@ public static void enableJmx() { systemAccessProvider = (SystemAccessProvider) Class.forName( - "datadog.trace.core.util.JmxSystemAccessProvider", + "com.datadog.trace.core.util.JmxSystemAccessProvider", false, SystemAccess.class.getClassLoader()) .getField("INSTANCE") diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccessProvider.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SystemAccessProvider.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccessProvider.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SystemAccessProvider.java index b7eb198a29..82764cba1b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/util/SystemAccessProvider.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SystemAccessProvider.java @@ -1,4 +1,4 @@ -package datadog.trace.core.util; +package com.datadog.trace.core.util; /** * A pluggable system provider used by {@linkplain SystemAccess}. {@linkplain SystemAccess} may not diff --git a/features/dd-trace-core/src/main/java/datadog/trace/core/util/TagsMatcher.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/TagsMatcher.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/core/util/TagsMatcher.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/core/util/TagsMatcher.java index ef680e5b07..5f8cdc1352 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/core/util/TagsMatcher.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/TagsMatcher.java @@ -1,6 +1,6 @@ -package datadog.trace.core.util; +package com.datadog.trace.core.util; -import datadog.trace.core.CoreSpan; +import com.datadog.trace.core.CoreSpan; import java.util.Map; import java.util.regex.Pattern; import java.util.stream.Collectors; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/ddagent/DroppingPolicy.java b/features/dd-trace-core/src/main/java/com/datadog/trace/ddagent/DroppingPolicy.java similarity index 87% rename from features/dd-trace-core/src/main/java/datadog/trace/ddagent/DroppingPolicy.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/ddagent/DroppingPolicy.java index 1b8f9de805..c6be47bd6c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/ddagent/DroppingPolicy.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/ddagent/DroppingPolicy.java @@ -1,4 +1,4 @@ -package datadog.trace.ddagent; +package com.datadog.trace.ddagent; public interface DroppingPolicy { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java index 76b6081d24..3f47b7b65c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/lambda/ReadFromInputStreamJsonAdapter.java @@ -1,4 +1,4 @@ -package datadog.trace.lambda; +package com.datadog.trace.lambda; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.JsonReader; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/logging/GlobalLogLevelSwitcher.java b/features/dd-trace-core/src/main/java/com/datadog/trace/logging/GlobalLogLevelSwitcher.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/logging/GlobalLogLevelSwitcher.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/logging/GlobalLogLevelSwitcher.java index 400772b7f2..6b95b9044f 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/logging/GlobalLogLevelSwitcher.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/logging/GlobalLogLevelSwitcher.java @@ -1,4 +1,4 @@ -package datadog.trace.logging; +package com.datadog.trace.logging; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java b/features/dd-trace-core/src/main/java/com/datadog/trace/logging/LogLevel.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/logging/LogLevel.java index 8c40ea89f5..42ce35aaea 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevel.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/logging/LogLevel.java @@ -1,4 +1,4 @@ -package datadog.trace.logging; +package com.datadog.trace.logging; import java.util.Locale; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevelSwitcher.java b/features/dd-trace-core/src/main/java/com/datadog/trace/logging/LogLevelSwitcher.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevelSwitcher.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/logging/LogLevelSwitcher.java index 3e1adfe12f..7595231b05 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/logging/LogLevelSwitcher.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/logging/LogLevelSwitcher.java @@ -1,4 +1,4 @@ -package datadog.trace.logging; +package com.datadog.trace.logging; /** Enables temporary runtime switching of LogLevel. */ public interface LogLevelSwitcher { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/logging/LoggingSettingsDescription.java b/features/dd-trace-core/src/main/java/com/datadog/trace/logging/LoggingSettingsDescription.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/logging/LoggingSettingsDescription.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/logging/LoggingSettingsDescription.java index 90924168ae..770f4285f9 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/logging/LoggingSettingsDescription.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/logging/LoggingSettingsDescription.java @@ -1,4 +1,4 @@ -package datadog.trace.logging; +package com.datadog.trace.logging; import java.util.Collections; import java.util.HashMap; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/monitor/Counter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/monitor/Counter.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/monitor/Counter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/monitor/Counter.java index c7d01ccd12..f8592d0fdc 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/monitor/Counter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/monitor/Counter.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.monitor; +package com.datadog.trace.monitor; public interface Counter { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/monitor/Monitoring.java b/features/dd-trace-core/src/main/java/com/datadog/trace/monitor/Monitoring.java similarity index 88% rename from features/dd-trace-core/src/main/java/datadog/trace/monitor/Monitoring.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/monitor/Monitoring.java index 6a75d6b304..0ea2b93cf5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/monitor/Monitoring.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/monitor/Monitoring.java @@ -4,10 +4,10 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.monitor; +package com.datadog.trace.monitor; -import datadog.trace.monitor.NoOpCounter; -import datadog.trace.monitor.NoOpRecording; +import com.datadog.trace.monitor.NoOpCounter; +import com.datadog.trace.monitor.NoOpRecording; public interface Monitoring { Monitoring DISABLED = new DisabledMonitoring(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpCounter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/monitor/NoOpCounter.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpCounter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/monitor/NoOpCounter.java index e2a78e0605..785505bb90 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpCounter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/monitor/NoOpCounter.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.monitor; +package com.datadog.trace.monitor; public final class NoOpCounter implements Counter { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpRecording.java b/features/dd-trace-core/src/main/java/com/datadog/trace/monitor/NoOpRecording.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpRecording.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/monitor/NoOpRecording.java index 8f1c05ffa6..26b474088c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/monitor/NoOpRecording.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/monitor/NoOpRecording.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.monitor; +package com.datadog.trace.monitor; public class NoOpRecording extends Recording { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/monitor/Recording.java b/features/dd-trace-core/src/main/java/com/datadog/trace/monitor/Recording.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/monitor/Recording.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/monitor/Recording.java index 501f553850..6ceae20652 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/monitor/Recording.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/monitor/Recording.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.monitor; +package com.datadog.trace.monitor; public abstract class Recording implements AutoCloseable { @Override diff --git a/features/dd-trace-core/src/main/java/datadog/trace/relocate/api/IOLogger.java b/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/IOLogger.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/relocate/api/IOLogger.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/IOLogger.java index a43ff21390..0116aba1bd 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/relocate/api/IOLogger.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/IOLogger.java @@ -1,4 +1,4 @@ -package datadog.trace.relocate.api; +package com.datadog.trace.relocate.api; import org.slf4j.Logger; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/relocate/api/RatelimitedLogger.java b/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/RatelimitedLogger.java similarity index 94% rename from features/dd-trace-core/src/main/java/datadog/trace/relocate/api/RatelimitedLogger.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/RatelimitedLogger.java index fe0273a0f4..c9582b23fc 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/relocate/api/RatelimitedLogger.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/RatelimitedLogger.java @@ -1,4 +1,4 @@ -package datadog.trace.relocate.api; +package com.datadog.trace.relocate.api; import org.slf4j.Logger; @@ -6,8 +6,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -import datadog.trace.api.time.SystemTimeSource; -import datadog.trace.api.time.TimeSource; +import com.datadog.trace.api.time.SystemTimeSource; +import com.datadog.trace.api.time.TimeSource; /** * Logger that logs message once per given delay if debugging is disabled. If debugging is enabled diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/ByteBufferConsumer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/ByteBufferConsumer.java similarity index 75% rename from features/dd-trace-core/src/main/java/datadog/trace/serialization/ByteBufferConsumer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/serialization/ByteBufferConsumer.java index ba6201e884..22715ee8a3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/ByteBufferConsumer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/ByteBufferConsumer.java @@ -1,4 +1,4 @@ -package datadog.trace.serialization; +package com.datadog.trace.serialization; import java.nio.ByteBuffer; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/EncodingCache.java b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/EncodingCache.java similarity index 70% rename from features/dd-trace-core/src/main/java/datadog/trace/serialization/EncodingCache.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/serialization/EncodingCache.java index 9bcb163279..65e02a2488 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/EncodingCache.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/EncodingCache.java @@ -1,4 +1,4 @@ -package datadog.trace.serialization; +package com.datadog.trace.serialization; // TODO @FunctionalInterface public interface EncodingCache { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/FlushingBuffer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/FlushingBuffer.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/serialization/FlushingBuffer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/serialization/FlushingBuffer.java index a062207a7b..9a1439a25c 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/FlushingBuffer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/FlushingBuffer.java @@ -1,9 +1,9 @@ -package datadog.trace.serialization; +package com.datadog.trace.serialization; import java.nio.ByteBuffer; -import datadog.trace.serialization.ByteBufferConsumer; -import datadog.trace.serialization.StreamingBuffer; +import com.datadog.trace.serialization.ByteBufferConsumer; +import com.datadog.trace.serialization.StreamingBuffer; public final class FlushingBuffer implements StreamingBuffer { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/GrowableBuffer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/GrowableBuffer.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/serialization/GrowableBuffer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/serialization/GrowableBuffer.java index 87575bdcc2..281c21f91a 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/GrowableBuffer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/GrowableBuffer.java @@ -1,8 +1,8 @@ -package datadog.trace.serialization; +package com.datadog.trace.serialization; import java.nio.ByteBuffer; -import datadog.trace.serialization.StreamingBuffer; +import com.datadog.trace.serialization.StreamingBuffer; /** * This buffer doesn't have a bounded length, and grows linearly. Don't use it except when diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/Mapper.java b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/Mapper.java similarity index 52% rename from features/dd-trace-core/src/main/java/datadog/trace/serialization/Mapper.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/serialization/Mapper.java index 7218d97f9d..cf7f3ed1e5 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/Mapper.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/Mapper.java @@ -1,6 +1,6 @@ -package datadog.trace.serialization; +package com.datadog.trace.serialization; -import datadog.trace.serialization.Writable; +import com.datadog.trace.serialization.Writable; // TODO @FunctionalInterface public interface Mapper { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/MessageFormatter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/MessageFormatter.java similarity index 72% rename from features/dd-trace-core/src/main/java/datadog/trace/serialization/MessageFormatter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/serialization/MessageFormatter.java index a8461baaee..77a17a8060 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/MessageFormatter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/MessageFormatter.java @@ -1,4 +1,4 @@ -package datadog.trace.serialization; +package com.datadog.trace.serialization; public interface MessageFormatter { boolean format(T message, Mapper mapper); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/StreamingBuffer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/StreamingBuffer.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/serialization/StreamingBuffer.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/serialization/StreamingBuffer.java index 01b81c80d0..f2ec347fbc 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/StreamingBuffer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/StreamingBuffer.java @@ -1,4 +1,4 @@ -package datadog.trace.serialization; +package com.datadog.trace.serialization; import java.nio.ByteBuffer; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/ValueWriter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/ValueWriter.java similarity index 59% rename from features/dd-trace-core/src/main/java/datadog/trace/serialization/ValueWriter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/serialization/ValueWriter.java index 73c947bfae..b5f1149565 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/ValueWriter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/ValueWriter.java @@ -1,6 +1,6 @@ -package datadog.trace.serialization; +package com.datadog.trace.serialization; -import datadog.trace.serialization.EncodingCache; +import com.datadog.trace.serialization.EncodingCache; // TODO @FunctionalInterface public interface ValueWriter { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/Writable.java b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/Writable.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/serialization/Writable.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/serialization/Writable.java index 8476b13f83..2f7dad0454 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/Writable.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/Writable.java @@ -1,7 +1,7 @@ -package datadog.trace.serialization; +package com.datadog.trace.serialization; -import datadog.trace.serialization.EncodingCache; -import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import com.datadog.trace.serialization.EncodingCache; +import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import java.nio.ByteBuffer; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/serialization/WritableFormatter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/WritableFormatter.java similarity index 64% rename from features/dd-trace-core/src/main/java/datadog/trace/serialization/WritableFormatter.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/serialization/WritableFormatter.java index 856f09666b..4bc8b9852d 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/serialization/WritableFormatter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/serialization/WritableFormatter.java @@ -1,3 +1,3 @@ -package datadog.trace.serialization; +package com.datadog.trace.serialization; public interface WritableFormatter extends Writable, MessageFormatter {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/AgentProxySelector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentProxySelector.java similarity index 93% rename from features/dd-trace-core/src/main/java/datadog/trace/util/AgentProxySelector.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentProxySelector.java index 7bbb171ad1..d2851555e3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/AgentProxySelector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentProxySelector.java @@ -1,4 +1,4 @@ -package datadog.trace.util; +package com.datadog.trace.util; import java.io.IOException; import java.net.Proxy; @@ -9,7 +9,7 @@ import java.util.List; import java.util.Set; -import datadog.trace.api.Config; +import com.datadog.trace.api.Config; public final class AgentProxySelector extends ProxySelector { public static final ProxySelector INSTANCE = new AgentProxySelector(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/AgentTaskScheduler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentTaskScheduler.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/util/AgentTaskScheduler.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentTaskScheduler.java index e7a0821c64..accc46b4fd 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/AgentTaskScheduler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentTaskScheduler.java @@ -1,11 +1,11 @@ -package datadog.trace.util; +package com.datadog.trace.util; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; -import static datadog.trace.util.AgentThreadFactory.AGENT_THREAD_GROUP; -import static datadog.trace.util.AgentThreadFactory.AgentThread.TASK_SCHEDULER; -import static datadog.trace.util.AgentThreadFactory.newAgentThread; +import static com.datadog.trace.util.AgentThreadFactory.AGENT_THREAD_GROUP; +import static com.datadog.trace.util.AgentThreadFactory.AgentThread.TASK_SCHEDULER; +import static com.datadog.trace.util.AgentThreadFactory.newAgentThread; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,7 +18,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import datadog.trace.util.AgentThreadFactory.AgentThread; +import com.datadog.trace.util.AgentThreadFactory.AgentThread; public class AgentTaskScheduler implements Executor { private static final Logger log = LoggerFactory.getLogger(AgentTaskScheduler.class); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/AgentThreadFactory.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentThreadFactory.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/util/AgentThreadFactory.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentThreadFactory.java index 9602db255e..6175eee643 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/AgentThreadFactory.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentThreadFactory.java @@ -1,4 +1,4 @@ -package datadog.trace.util; +package com.datadog.trace.util; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/CollectionUtils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/CollectionUtils.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/util/CollectionUtils.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/CollectionUtils.java index 9b7c19bc95..7a7e610484 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/CollectionUtils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/CollectionUtils.java @@ -1,4 +1,4 @@ -package datadog.trace.util; +package com.datadog.trace.util; import java.util.ArrayList; import java.util.Collection; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/FNV64Hash.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/FNV64Hash.java similarity index 97% rename from features/dd-trace-core/src/main/java/datadog/trace/util/FNV64Hash.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/FNV64Hash.java index 8c91e4accc..6cf06aaf62 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/FNV64Hash.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/FNV64Hash.java @@ -1,4 +1,4 @@ -package datadog.trace.util; +package com.datadog.trace.util; /** * Calculates the FNV 64 bit hash. Longs should be treated as though they were unsigned diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/FileUtils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/FileUtils.java similarity index 96% rename from features/dd-trace-core/src/main/java/datadog/trace/util/FileUtils.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/FileUtils.java index 37b3cf5711..57e5cd26e3 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/FileUtils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/FileUtils.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.util; +package com.datadog.trace.util; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/PidHelper.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/PidHelper.java similarity index 91% rename from features/dd-trace-core/src/main/java/datadog/trace/util/PidHelper.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/PidHelper.java index 45219d8976..1eb19b2625 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/PidHelper.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/PidHelper.java @@ -1,11 +1,11 @@ -package datadog.trace.util; +package com.datadog.trace.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.function.Supplier; -import datadog.trace.api.Platform; +import com.datadog.trace.api.Platform; /** Get PID in reasonably cross-platform way. */ public final class PidHelper { @@ -31,7 +31,7 @@ private static String findPid() { pid = Strings.trim( ((Supplier) - Class.forName("datadog.trace.util.JDK9PidSupplier") + Class.forName("com.datadog.trace.util.JDK9PidSupplier") .getDeclaredConstructor() .newInstance()) .get()); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessUtils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/ProcessUtils.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/util/ProcessUtils.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/ProcessUtils.java index 8b7ba1f2f5..5cee610490 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/ProcessUtils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/ProcessUtils.java @@ -1,4 +1,4 @@ -package datadog.trace.util; +package com.datadog.trace.util; import androidx.annotation.Nullable; @@ -7,7 +7,7 @@ import java.util.function.Supplier; -import datadog.trace.api.Platform; +import com.datadog.trace.api.Platform; public abstract class ProcessUtils { @@ -34,7 +34,7 @@ public static String getCurrentJvmPath() { try { Supplier jdk9Supplier = (Supplier) - Class.forName("datadog.trace.util.JDK9ExecutableSupplier") + Class.forName("com.datadog.trace.util.JDK9ExecutableSupplier") .getDeclaredConstructor() .newInstance(); return jdk9Supplier.get(); diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/Strings.java similarity index 99% rename from features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/Strings.java index 6a0271770a..9940a18b2e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/Strings.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/Strings.java @@ -1,4 +1,4 @@ -package datadog.trace.util; +package com.datadog.trace.util; import androidx.annotation.NonNull; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/TagsHelper.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/TagsHelper.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/util/TagsHelper.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/TagsHelper.java index e0f2da7fab..5f525a139e 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/TagsHelper.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/TagsHelper.java @@ -1,4 +1,4 @@ -package datadog.trace.util; +package com.datadog.trace.util; import java.util.Locale; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/TraceUtils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/TraceUtils.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/util/TraceUtils.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/TraceUtils.java index b5c1a1b76a..e95f979e62 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/TraceUtils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/TraceUtils.java @@ -1,6 +1,6 @@ -package datadog.trace.util; +package com.datadog.trace.util; -import static datadog.trace.util.Strings.truncate; +import static com.datadog.trace.util.Strings.truncate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/AbstractStackWalker.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/AbstractStackWalker.java similarity index 83% rename from features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/AbstractStackWalker.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/AbstractStackWalker.java index 17c90ae02a..3bd25f756b 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/AbstractStackWalker.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/AbstractStackWalker.java @@ -1,4 +1,4 @@ -package datadog.trace.util.stacktrace; +package com.datadog.trace.util.stacktrace; import java.util.function.Function; import java.util.stream.Stream; @@ -18,6 +18,6 @@ final Stream doFilterStack(Stream stream) static boolean isNotDatadogTraceStackElement(final StackTraceElement el) { final String clazz = el.getClassName(); - return !clazz.startsWith("datadog.trace.") && !clazz.startsWith("com.datadog.iast."); + return !clazz.startsWith("com.datadog.trace.") && !clazz.startsWith("com.datadog.iast."); } } diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/DefaultStackWalker.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/DefaultStackWalker.java similarity index 90% rename from features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/DefaultStackWalker.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/DefaultStackWalker.java index a19d0b702b..b8d2341d66 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/DefaultStackWalker.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/DefaultStackWalker.java @@ -1,4 +1,4 @@ -package datadog.trace.util.stacktrace; +package com.datadog.trace.util.stacktrace; import java.util.Arrays; import java.util.function.Function; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackUtils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackUtils.java similarity index 98% rename from features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackUtils.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackUtils.java index 5f3cc6a22c..3e98ec1a20 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackUtils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackUtils.java @@ -1,4 +1,4 @@ -package datadog.trace.util.stacktrace; +package com.datadog.trace.util.stacktrace; import java.util.Arrays; import java.util.function.Function; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalker.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackWalker.java similarity index 86% rename from features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalker.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackWalker.java index 9364fb306a..b76740c9a7 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalker.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackWalker.java @@ -1,4 +1,4 @@ -package datadog.trace.util.stacktrace; +package com.datadog.trace.util.stacktrace; import java.util.function.Function; import java.util.stream.Stream; diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalkerFactory.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackWalkerFactory.java similarity index 89% rename from features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalkerFactory.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackWalkerFactory.java index ec93321e9a..9146a387ea 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/stacktrace/StackWalkerFactory.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackWalkerFactory.java @@ -1,4 +1,4 @@ -package datadog.trace.util.stacktrace; +package com.datadog.trace.util.stacktrace; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -7,7 +7,7 @@ import java.util.function.Supplier; import java.util.stream.Stream; -import datadog.trace.api.Platform; +import com.datadog.trace.api.Platform; public class StackWalkerFactory { @@ -51,7 +51,7 @@ private static Supplier jdk9() { } try { return (StackWalker) - Class.forName("datadog.trace.util.stacktrace.JDK9StackWalker") + Class.forName("com.datadog.trace.util.stacktrace.JDK9StackWalker") .getDeclaredConstructor() .newInstance(); } catch (Throwable e) { diff --git a/features/dd-trace-core/src/main/java/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java similarity index 92% rename from features/dd-trace-core/src/main/java/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java rename to features/dd-trace-core/src/main/java/com/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java index 5feb71d160..db610a4c67 100644 --- a/features/dd-trace-core/src/main/java/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/throwable/FatalAgentMisconfigurationError.java @@ -1,4 +1,4 @@ -package datadog.trace.util.throwable; +package com.datadog.trace.util.throwable; /** * This error represents a critical agent configuration issue that needs to be signalled to the diff --git a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java b/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java deleted file mode 100644 index fc2749fd5d..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/api/profiling/ObservableType.java +++ /dev/null @@ -1,3 +0,0 @@ -package datadog.trace.api.profiling; - -public interface ObservableType {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InboxItem.java b/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InboxItem.java deleted file mode 100644 index 1f56183e41..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/bootstrap/instrumentation/api/InboxItem.java +++ /dev/null @@ -1,3 +0,0 @@ -package datadog.trace.bootstrap.instrumentation.api; - -public interface InboxItem {} diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java deleted file mode 100644 index f6297f126f..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/InboxItem.java +++ /dev/null @@ -1,4 +0,0 @@ -package datadog.trace.common.metrics; - -interface InboxItem {} - diff --git a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Sink.java b/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Sink.java deleted file mode 100644 index 7328caaedd..0000000000 --- a/features/dd-trace-core/src/main/java/datadog/trace/common/metrics/Sink.java +++ /dev/null @@ -1,8 +0,0 @@ -package datadog.trace.common.metrics; - -import datadog.trace.serialization.ByteBufferConsumer; - -public interface Sink extends ByteBufferConsumer { - - void register(EventListener listener); -} diff --git a/features/dd-trace-core/src/test/kotlin/datadog/trace/util/FileUtilsTest.kt b/features/dd-trace-core/src/test/kotlin/com/datadog/trace/util/FileUtilsTest.kt similarity index 98% rename from features/dd-trace-core/src/test/kotlin/datadog/trace/util/FileUtilsTest.kt rename to features/dd-trace-core/src/test/kotlin/com/datadog/trace/util/FileUtilsTest.kt index 4e9c0f8a96..ec9e7cfc50 100644 --- a/features/dd-trace-core/src/test/kotlin/datadog/trace/util/FileUtilsTest.kt +++ b/features/dd-trace-core/src/test/kotlin/com/datadog/trace/util/FileUtilsTest.kt @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package datadog.trace.util +package com.datadog.trace.util import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.ForgeConfigurator From eddf6d89cc06d7b5e5c6912278d3815a99c10de3 Mon Sep 17 00:00:00 2001 From: Marius Constantin Date: Thu, 29 Feb 2024 14:07:46 +0100 Subject: [PATCH 04/55] Switch to com.legacy.trace package into the dd-sdk-android-trace module --- .../api/dd-sdk-android-trace.api | 1266 ++++++++--------- .../{ => legacy}/trace/api/Config.java | 2 +- .../{ => legacy}/trace/api/DDSpanTypes.java | 2 +- .../{ => legacy}/trace/api/DDTags.java | 2 +- .../trace/api/DDTraceApiInfo.java | 2 +- .../datadog/{ => legacy}/trace/api/Trace.java | 2 +- .../{ => legacy}/trace/api/Tracer.java | 6 +- .../trace/api/interceptor/MutableSpan.java | 6 +- .../api/interceptor/TraceInterceptor.java | 4 +- .../trace/api/sampling/PrioritySampling.java | 2 +- .../common/sampling/AbstractSampler.java | 3 +- .../trace/common/sampling/AllSampler.java | 2 +- .../common/sampling/DeterministicSampler.java | 2 +- .../common/sampling/PrioritySampler.java | 2 +- .../common/sampling/PrioritySampling.java | 4 +- .../common/sampling/RateByServiceSampler.java | 8 +- .../trace/common/sampling/RateSampler.java | 2 +- .../trace/common/sampling/Sampler.java | 6 +- .../trace/common/sampling/SamplingRule.java | 15 +- .../{ => legacy}/trace/common/util/Clock.java | 2 +- .../trace/common/writer/LoggingWriter.java | 2 +- .../trace/common/writer/Writer.java | 2 +- .../trace/context/ScopeListener.java | 2 +- .../trace/context/TraceScope.java | 2 +- .../java/com/datadog/opentracing/DDSpan.java | 8 +- .../datadog/opentracing/DDSpanContext.java | 4 +- .../com/datadog/opentracing/DDTracer.java | 20 +- .../opentracing/DefaultLogHandler.java | 2 +- .../com/datadog/opentracing/PendingTrace.java | 2 +- .../decorators/DBTypeDecorator.java | 4 +- .../decorators/DDDecoratorsFactory.java | 2 +- .../decorators/ForceManualDropDecorator.java | 4 +- .../decorators/ForceManualKeepDecorator.java | 4 +- .../decorators/ServiceNameDecorator.java | 2 +- .../decorators/ServletContextDecorator.java | 2 +- .../opentracing/propagation/B3HttpCodec.java | 2 +- .../opentracing/propagation/B3MHttpCodec.java | 2 +- .../propagation/DatadogHttpCodec.java | 2 +- .../propagation/HaystackHttpCodec.java | 2 +- .../opentracing/propagation/HttpCodec.java | 2 +- .../opentracing/propagation/W3CHttpCodec.java | 2 +- .../scopemanager/ContextualScopeManager.java | 2 +- .../scopemanager/ContinuableScope.java | 4 +- .../opentracing/scopemanager/SimpleScope.java | 2 +- .../datadog/android/trace/AndroidTracer.kt | 6 +- .../android/trace/internal/TracingFeature.kt | 2 +- .../android/trace/internal/data/NoOpWriter.kt | 2 +- .../trace/internal/data/TraceWriter.kt | 2 +- .../handlers/AndroidSpanLogsHandler.kt | 2 +- .../android/trace/AndroidTracerTest.kt | 4 +- .../trace/assertj/TracerConfigAssert.kt | 2 +- .../handlers/AndroidSpanLogsHandlerTest.kt | 2 +- .../android/utils/forge/SpanForgeryFactory.kt | 2 +- .../datadog/opentracing/DDSpanContextTest.kt | 4 +- .../datadog/opentracing/PendingTraceTest.kt | 2 +- .../transitiveDependencies | 17 +- .../okhttp/trace/TracingInterceptor.kt | 6 +- .../DatadogInterceptorWithoutTracesTest.kt | 2 +- ...nterceptorNonDdTracerNotSendingSpanTest.kt | 4 +- .../TracingInterceptorNonDdTracerTest.kt | 4 +- .../TracingInterceptorNotSendingSpanTest.kt | 4 +- .../okhttp/trace/TracingInterceptorTest.kt | 4 +- 62 files changed, 740 insertions(+), 753 deletions(-) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/api/Config.java (99%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/api/DDSpanTypes.java (96%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/api/DDTags.java (97%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/api/DDTraceApiInfo.java (96%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/api/Trace.java (95%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/api/Tracer.java (86%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/api/interceptor/MutableSpan.java (92%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/api/interceptor/TraceInterceptor.java (83%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/api/sampling/PrioritySampling.java (95%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/sampling/AbstractSampler.java (96%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/sampling/AllSampler.java (91%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/sampling/DeterministicSampler.java (96%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/sampling/PrioritySampler.java (88%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/sampling/PrioritySampling.java (86%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/sampling/RateByServiceSampler.java (91%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/sampling/RateSampler.java (86%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/sampling/Sampler.java (87%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/sampling/SamplingRule.java (73%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/util/Clock.java (97%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/writer/LoggingWriter.java (93%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/common/writer/Writer.java (95%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/context/ScopeListener.java (93%) rename features/dd-sdk-android-trace/src/main/java/com/datadog/{ => legacy}/trace/context/TraceScope.java (97%) diff --git a/features/dd-sdk-android-trace/api/dd-sdk-android-trace.api b/features/dd-sdk-android-trace/api/dd-sdk-android-trace.api index a6636c15d7..e186e94864 100644 --- a/features/dd-sdk-android-trace/api/dd-sdk-android-trace.api +++ b/features/dd-sdk-android-trace/api/dd-sdk-android-trace.api @@ -413,7 +413,423 @@ public final class com/datadog/exec/DaemonThreadFactory : java/util/concurrent/T public fun newThread (Ljava/lang/Runnable;)Ljava/lang/Thread; } -public class com/datadog/opentracing/DDSpan : com/datadog/trace/api/interceptor/MutableSpan, io/opentracing/Span { +public class com/datadog/legacy/trace/api/Config { + public static final field AGENT_HOST Ljava/lang/String; + public static final field AGENT_PORT_LEGACY Ljava/lang/String; + public static final field AGENT_UNIX_DOMAIN_SOCKET Ljava/lang/String; + public static final field API_KEY Ljava/lang/String; + public static final field API_KEY_FILE Ljava/lang/String; + public static final field CONFIGURATION_FILE Ljava/lang/String; + public static final field DB_CLIENT_HOST_SPLIT_BY_INSTANCE Ljava/lang/String; + public static final field DD_AGENT_WRITER_TYPE Ljava/lang/String; + public static final field DEFAULT_AGENT_HOST Ljava/lang/String; + public static final field DEFAULT_AGENT_UNIX_DOMAIN_SOCKET Ljava/lang/String; + public static final field DEFAULT_ANALYTICS_SAMPLE_RATE F + public static final field DEFAULT_INTEGRATIONS_ENABLED Z + public static final field DEFAULT_JMX_FETCH_STATSD_PORT I + public static final field DEFAULT_LOGS_INJECTION_ENABLED Z + public static final field DEFAULT_METRICS_ENABLED Z + public static final field DEFAULT_PROFILING_ENABLED Z + public static final field DEFAULT_PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE I + public static final field DEFAULT_PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS I + public static final field DEFAULT_PROFILING_EXCEPTION_SAMPLE_LIMIT I + public static final field DEFAULT_PROFILING_PROXY_PORT I + public static final field DEFAULT_PROFILING_START_DELAY I + public static final field DEFAULT_PROFILING_START_FORCE_FIRST Z + public static final field DEFAULT_PROFILING_UPLOAD_COMPRESSION Ljava/lang/String; + public static final field DEFAULT_PROFILING_UPLOAD_PERIOD I + public static final field DEFAULT_PROFILING_UPLOAD_TIMEOUT I + public static final field DEFAULT_SERVICE_NAME Ljava/lang/String; + public static final field DEFAULT_SITE Ljava/lang/String; + public static final field DEFAULT_TRACE_AGENT_PORT I + public static final field DEFAULT_TRACE_ANALYTICS_ENABLED Z + public static final field DEFAULT_TRACE_RATE_LIMIT D + public static final field GLOBAL_TAGS Ljava/lang/String; + public static final field HEADER_TAGS Ljava/lang/String; + public static final field HEALTH_METRICS_ENABLED Ljava/lang/String; + public static final field HEALTH_METRICS_STATSD_HOST Ljava/lang/String; + public static final field HEALTH_METRICS_STATSD_PORT Ljava/lang/String; + public static final field HOST_TAG Ljava/lang/String; + public static final field HTTP_CLIENT_ERROR_STATUSES Ljava/lang/String; + public static final field HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN Ljava/lang/String; + public static final field HTTP_CLIENT_TAG_QUERY_STRING Ljava/lang/String; + public static final field HTTP_SERVER_ERROR_STATUSES Ljava/lang/String; + public static final field HTTP_SERVER_TAG_QUERY_STRING Ljava/lang/String; + public static final field INTEGRATIONS_ENABLED Ljava/lang/String; + public static final field JMX_FETCH_CHECK_PERIOD Ljava/lang/String; + public static final field JMX_FETCH_CONFIG Ljava/lang/String; + public static final field JMX_FETCH_CONFIG_DIR Ljava/lang/String; + public static final field JMX_FETCH_ENABLED Ljava/lang/String; + public static final field JMX_FETCH_METRICS_CONFIGS Ljava/lang/String; + public static final field JMX_FETCH_REFRESH_BEANS_PERIOD Ljava/lang/String; + public static final field JMX_FETCH_STATSD_HOST Ljava/lang/String; + public static final field JMX_FETCH_STATSD_PORT Ljava/lang/String; + public static final field JMX_TAGS Ljava/lang/String; + public static final field LANGUAGE_TAG_KEY Ljava/lang/String; + public static final field LANGUAGE_TAG_VALUE Ljava/lang/String; + public static final field LOGGING_WRITER_TYPE Ljava/lang/String; + public static final field LOGS_INJECTION_ENABLED Ljava/lang/String; + public static final field PARTIAL_FLUSH_MIN_SPANS Ljava/lang/String; + public static final field PRIORITY_SAMPLING Ljava/lang/String; + public static final field PROFILING_API_KEY_FILE_OLD Ljava/lang/String; + public static final field PROFILING_API_KEY_FILE_VERY_OLD Ljava/lang/String; + public static final field PROFILING_API_KEY_OLD Ljava/lang/String; + public static final field PROFILING_API_KEY_VERY_OLD Ljava/lang/String; + public static final field PROFILING_ENABLED Ljava/lang/String; + public static final field PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE Ljava/lang/String; + public static final field PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS Ljava/lang/String; + public static final field PROFILING_EXCEPTION_SAMPLE_LIMIT Ljava/lang/String; + public static final field PROFILING_PROXY_HOST Ljava/lang/String; + public static final field PROFILING_PROXY_PASSWORD Ljava/lang/String; + public static final field PROFILING_PROXY_PORT Ljava/lang/String; + public static final field PROFILING_PROXY_USERNAME Ljava/lang/String; + public static final field PROFILING_START_DELAY Ljava/lang/String; + public static final field PROFILING_START_FORCE_FIRST Ljava/lang/String; + public static final field PROFILING_TAGS Ljava/lang/String; + public static final field PROFILING_TEMPLATE_OVERRIDE_FILE Ljava/lang/String; + public static final field PROFILING_UPLOAD_COMPRESSION Ljava/lang/String; + public static final field PROFILING_UPLOAD_PERIOD Ljava/lang/String; + public static final field PROFILING_UPLOAD_TIMEOUT Ljava/lang/String; + public static final field PROFILING_URL Ljava/lang/String; + public static final field PROFILING_URL_TEMPLATE Ljava/lang/String; + public static final field PROPAGATION_STYLE_EXTRACT Ljava/lang/String; + public static final field PROPAGATION_STYLE_INJECT Ljava/lang/String; + public static final field RUNTIME_CONTEXT_FIELD_INJECTION Ljava/lang/String; + public static final field RUNTIME_ID_TAG Ljava/lang/String; + public static final field SCOPE_DEPTH_LIMIT Ljava/lang/String; + public static final field SERVICE Ljava/lang/String; + public static final field SERVICE_MAPPING Ljava/lang/String; + public static final field SERVICE_NAME Ljava/lang/String; + public static final field SERVICE_TAG Ljava/lang/String; + public static final field SITE Ljava/lang/String; + public static final field SPAN_TAGS Ljava/lang/String; + public static final field SPLIT_BY_TAGS Ljava/lang/String; + public static final field TAGS Ljava/lang/String; + public static final field TRACE_AGENT_PORT Ljava/lang/String; + public static final field TRACE_ANALYTICS_ENABLED Ljava/lang/String; + public static final field TRACE_ANNOTATIONS Ljava/lang/String; + public static final field TRACE_CLASSES_EXCLUDE Ljava/lang/String; + public static final field TRACE_ENABLED Ljava/lang/String; + public static final field TRACE_EXECUTORS Ljava/lang/String; + public static final field TRACE_EXECUTORS_ALL Ljava/lang/String; + public static final field TRACE_METHODS Ljava/lang/String; + public static final field TRACE_RATE_LIMIT Ljava/lang/String; + public static final field TRACE_REPORT_HOSTNAME Ljava/lang/String; + public static final field TRACE_RESOLVER_ENABLED Ljava/lang/String; + public static final field TRACE_SAMPLE_RATE Ljava/lang/String; + public static final field TRACE_SAMPLING_OPERATION_RULES Ljava/lang/String; + public static final field TRACE_SAMPLING_SERVICE_RULES Ljava/lang/String; + public static final field WRITER_TYPE Ljava/lang/String; + public static fun get ()Lcom/datadog/legacy/trace/api/Config; + public static fun get (Ljava/util/Properties;)Lcom/datadog/legacy/trace/api/Config; + public fun getAgentHost ()Ljava/lang/String; + public fun getAgentPort ()I + public fun getAgentUnixDomainSocket ()Ljava/lang/String; + public static fun getBooleanSettingFromEnvironment (Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/Boolean; + public fun getExcludedClasses ()Ljava/util/List; + public fun getFinalProfilingUrl ()Ljava/lang/String; + public static fun getFloatSettingFromEnvironment (Ljava/lang/String;Ljava/lang/Float;)Ljava/lang/Float; + public fun getHeaderTags ()Ljava/util/Map; + public fun getHealthMetricsStatsdHost ()Ljava/lang/String; + public fun getHealthMetricsStatsdPort ()Ljava/lang/Integer; + public fun getHttpClientErrorStatuses ()Ljava/util/Set; + public fun getHttpServerErrorStatuses ()Ljava/util/Set; + public fun getInstrumentationAnalyticsSampleRate ([Ljava/lang/String;)F + public fun getJmxFetchCheckPeriod ()Ljava/lang/Integer; + public fun getJmxFetchConfigDir ()Ljava/lang/String; + public fun getJmxFetchConfigs ()Ljava/util/List; + public fun getJmxFetchMetricsConfigs ()Ljava/util/List; + public fun getJmxFetchRefreshBeansPeriod ()Ljava/lang/Integer; + public fun getJmxFetchStatsdHost ()Ljava/lang/String; + public fun getJmxFetchStatsdPort ()Ljava/lang/Integer; + public fun getLocalRootSpanTags ()Ljava/util/Map; + public fun getMergedJmxTags ()Ljava/util/Map; + public fun getMergedProfilingTags ()Ljava/util/Map; + public fun getMergedSpanTags ()Ljava/util/Map; + public fun getPartialFlushMinSpans ()Ljava/lang/Integer; + public fun getProfilingExceptionHistogramMaxCollectionSize ()I + public fun getProfilingExceptionHistogramTopItems ()I + public fun getProfilingExceptionSampleLimit ()I + public fun getProfilingProxyHost ()Ljava/lang/String; + public fun getProfilingProxyPassword ()Ljava/lang/String; + public fun getProfilingProxyPort ()I + public fun getProfilingProxyUsername ()Ljava/lang/String; + public fun getProfilingStartDelay ()I + public fun getProfilingTemplateOverrideFile ()Ljava/lang/String; + public fun getProfilingUploadCompression ()Ljava/lang/String; + public fun getProfilingUploadPeriod ()I + public fun getProfilingUploadTimeout ()I + public fun getPropagationStylesToExtract ()Ljava/util/Set; + public fun getPropagationStylesToInject ()Ljava/util/Set; + public fun getRuntimeId ()Ljava/lang/String; + public fun getScopeDepthLimit ()Ljava/lang/Integer; + public fun getServiceMapping ()Ljava/util/Map; + public fun getServiceName ()Ljava/lang/String; + public static fun getSettingFromEnvironment (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + public fun getSite ()Ljava/lang/String; + public fun getSplitByTags ()Ljava/util/Set; + public fun getTraceAnnotations ()Ljava/lang/String; + public fun getTraceExecutors ()Ljava/util/List; + public fun getTraceMethods ()Ljava/lang/String; + public fun getTraceRateLimit ()Ljava/lang/Double; + public fun getTraceSampleRate ()Ljava/lang/Double; + public fun getTraceSamplingOperationRules ()Ljava/util/Map; + public fun getTraceSamplingServiceRules ()Ljava/util/Map; + public fun getWriterType ()Ljava/lang/String; + public fun isDbClientSplitByInstance ()Z + public fun isHealthMetricsEnabled ()Z + public fun isHttpClientSplitByDomain ()Z + public fun isHttpClientTagQueryString ()Z + public fun isHttpServerTagQueryString ()Z + public fun isIntegrationEnabled (Ljava/util/SortedSet;Z)Z + public fun isIntegrationsEnabled ()Z + public fun isJmxFetchEnabled ()Z + public fun isJmxFetchIntegrationEnabled (Ljava/util/SortedSet;Z)Z + public fun isLogsInjectionEnabled ()Z + public fun isPrioritySamplingEnabled ()Z + public fun isProfilingEnabled ()Z + public fun isProfilingStartForceFirst ()Z + public fun isReportHostName ()Z + public fun isRuleEnabled (Ljava/lang/String;)Z + public fun isRuntimeContextFieldInjection ()Z + public fun isTraceAnalyticsEnabled ()Z + public fun isTraceAnalyticsIntegrationEnabled (Ljava/util/SortedSet;Z)Z + public fun isTraceEnabled ()Z + public fun isTraceExecutorsAll ()Z + public fun isTraceResolverEnabled ()Z + public static fun jmxFetchIntegrationEnabled (Ljava/util/SortedSet;Z)Z + public fun toString ()Ljava/lang/String; + public static fun traceAnalyticsIntegrationEnabled (Ljava/util/SortedSet;Z)Z +} + +public final class com/datadog/legacy/trace/api/Config$PropagationStyle : java/lang/Enum { + public static final field B3 Lcom/datadog/legacy/trace/api/Config$PropagationStyle; + public static final field B3MULTI Lcom/datadog/legacy/trace/api/Config$PropagationStyle; + public static final field DATADOG Lcom/datadog/legacy/trace/api/Config$PropagationStyle; + public static final field HAYSTACK Lcom/datadog/legacy/trace/api/Config$PropagationStyle; + public static final field TRACECONTEXT Lcom/datadog/legacy/trace/api/Config$PropagationStyle; + public static fun valueOf (Ljava/lang/String;)Lcom/datadog/legacy/trace/api/Config$PropagationStyle; + public static fun values ()[Lcom/datadog/legacy/trace/api/Config$PropagationStyle; +} + +public class com/datadog/legacy/trace/api/DDSpanTypes { + public static final field CACHE Ljava/lang/String; + public static final field CASSANDRA Ljava/lang/String; + public static final field COUCHBASE Ljava/lang/String; + public static final field ELASTICSEARCH Ljava/lang/String; + public static final field HIBERNATE Ljava/lang/String; + public static final field HTTP_CLIENT Ljava/lang/String; + public static final field HTTP_SERVER Ljava/lang/String; + public static final field MEMCACHED Ljava/lang/String; + public static final field MESSAGE_CLIENT Ljava/lang/String; + public static final field MESSAGE_CONSUMER Ljava/lang/String; + public static final field MESSAGE_PRODUCER Ljava/lang/String; + public static final field MONGO Ljava/lang/String; + public static final field REDIS Ljava/lang/String; + public static final field RPC Ljava/lang/String; + public static final field SQL Ljava/lang/String; + public static final field WEB_SERVLET Ljava/lang/String; + public fun ()V +} + +public class com/datadog/legacy/trace/api/DDTags { + public static final field ANALYTICS_SAMPLE_RATE Ljava/lang/String; + public static final field DB_STATEMENT Ljava/lang/String; + public static final field ERROR_MSG Ljava/lang/String; + public static final field ERROR_STACK Ljava/lang/String; + public static final field ERROR_TYPE Ljava/lang/String; + public static final field EVENT_SAMPLE_RATE Ljava/lang/String; + public static final field HTTP_FRAGMENT Ljava/lang/String; + public static final field HTTP_QUERY Ljava/lang/String; + public static final field MANUAL_DROP Ljava/lang/String; + public static final field MANUAL_KEEP Ljava/lang/String; + public static final field RESOURCE_NAME Ljava/lang/String; + public static final field SERVICE_NAME Ljava/lang/String; + public static final field SPAN_TYPE Ljava/lang/String; + public static final field THREAD_ID Ljava/lang/String; + public static final field THREAD_NAME Ljava/lang/String; + public static final field USER_NAME Ljava/lang/String; + public fun ()V +} + +public class com/datadog/legacy/trace/api/DDTraceApiInfo { + public static final field VERSION Ljava/lang/String; + public fun ()V + public static fun main ([Ljava/lang/String;)V +} + +public abstract interface annotation class com/datadog/legacy/trace/api/Trace : java/lang/annotation/Annotation { + public abstract fun operationName ()Ljava/lang/String; + public abstract fun resourceName ()Ljava/lang/String; +} + +public abstract interface class com/datadog/legacy/trace/api/Tracer { + public abstract fun addScopeListener (Lcom/datadog/legacy/trace/context/ScopeListener;)V + public abstract fun addTraceInterceptor (Lcom/datadog/legacy/trace/api/interceptor/TraceInterceptor;)Z + public abstract fun getSpanId ()Ljava/lang/String; + public abstract fun getTraceId ()Ljava/lang/String; +} + +public abstract interface class com/datadog/legacy/trace/api/interceptor/MutableSpan { + public abstract fun drop ()V + public abstract fun getDurationNano ()J + public abstract fun getLocalRootSpan ()Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; + public abstract fun getOperationName ()Ljava/lang/String; + public abstract fun getResourceName ()Ljava/lang/String; + public abstract fun getRootSpan ()Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; + public abstract fun getSamplingPriority ()Ljava/lang/Integer; + public abstract fun getServiceName ()Ljava/lang/String; + public abstract fun getSpanType ()Ljava/lang/String; + public abstract fun getStartTime ()J + public abstract fun getTags ()Ljava/util/Map; + public abstract fun isError ()Ljava/lang/Boolean; + public abstract fun setError (Z)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; + public abstract fun setOperationName (Ljava/lang/String;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; + public abstract fun setResourceName (Ljava/lang/String;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; + public abstract fun setSamplingPriority (I)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; + public abstract fun setServiceName (Ljava/lang/String;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; + public abstract fun setSpanType (Ljava/lang/String;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/Number;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; + public abstract fun setTag (Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; + public abstract fun setTag (Ljava/lang/String;Z)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; +} + +public abstract interface class com/datadog/legacy/trace/api/interceptor/TraceInterceptor { + public abstract fun onTraceComplete (Ljava/util/Collection;)Ljava/util/Collection; + public abstract fun priority ()I +} + +public class com/datadog/legacy/trace/api/sampling/PrioritySampling { + public static final field SAMPLER_DROP I + public static final field SAMPLER_KEEP I + public static final field UNSET I + public static final field USER_DROP I + public static final field USER_KEEP I +} + +public abstract class com/datadog/legacy/trace/common/sampling/AbstractSampler : com/datadog/legacy/trace/common/sampling/Sampler { + protected field skipTagsPatterns Ljava/util/Map; + public fun ()V + public fun addSkipTagPattern (Ljava/lang/String;Ljava/util/regex/Pattern;)V + protected abstract fun doSample (Lcom/datadog/opentracing/DDSpan;)Z + public fun sample (Lcom/datadog/opentracing/DDSpan;)Z +} + +public class com/datadog/legacy/trace/common/sampling/AllSampler : com/datadog/legacy/trace/common/sampling/AbstractSampler { + public fun ()V + public fun doSample (Lcom/datadog/opentracing/DDSpan;)Z + public fun toString ()Ljava/lang/String; +} + +public class com/datadog/legacy/trace/common/sampling/DeterministicSampler : com/datadog/legacy/trace/common/sampling/RateSampler { + public fun (D)V + public fun getSampleRate ()D + public fun sample (Lcom/datadog/opentracing/DDSpan;)Z +} + +public abstract interface class com/datadog/legacy/trace/common/sampling/PrioritySampler { + public abstract fun setSamplingPriority (Lcom/datadog/opentracing/DDSpan;)V +} + +public class com/datadog/legacy/trace/common/sampling/PrioritySampling { + public static final field SAMPLER_DROP I + public static final field SAMPLER_KEEP I + public static final field UNSET I + public static final field USER_DROP I + public static final field USER_KEEP I +} + +public class com/datadog/legacy/trace/common/sampling/RateByServiceSampler : com/datadog/legacy/trace/common/sampling/PrioritySampler, com/datadog/legacy/trace/common/sampling/Sampler { + public static final field SAMPLING_AGENT_RATE Ljava/lang/String; + public fun ()V + public fun (Ljava/lang/Double;)V + public fun sample (Lcom/datadog/opentracing/DDSpan;)Z + public fun setSamplingPriority (Lcom/datadog/opentracing/DDSpan;)V +} + +public abstract interface class com/datadog/legacy/trace/common/sampling/RateSampler : com/datadog/legacy/trace/common/sampling/Sampler { + public abstract fun getSampleRate ()D +} + +public abstract interface class com/datadog/legacy/trace/common/sampling/Sampler { + public abstract fun sample (Lcom/datadog/opentracing/DDSpan;)Z +} + +public final class com/datadog/legacy/trace/common/sampling/Sampler$Builder { + public static fun forConfig (Lcom/datadog/legacy/trace/api/Config;)Lcom/datadog/legacy/trace/common/sampling/Sampler; + public static fun forConfig (Ljava/util/Properties;)Lcom/datadog/legacy/trace/common/sampling/Sampler; +} + +public abstract class com/datadog/legacy/trace/common/sampling/SamplingRule { + public fun (Lcom/datadog/legacy/trace/common/sampling/RateSampler;)V + public fun getSampler ()Lcom/datadog/legacy/trace/common/sampling/RateSampler; + public abstract fun matches (Lcom/datadog/opentracing/DDSpan;)Z + public fun sample (Lcom/datadog/opentracing/DDSpan;)Z +} + +public class com/datadog/legacy/trace/common/sampling/SamplingRule$AlwaysMatchesSamplingRule : com/datadog/legacy/trace/common/sampling/SamplingRule { + public fun (Lcom/datadog/legacy/trace/common/sampling/RateSampler;)V + public fun matches (Lcom/datadog/opentracing/DDSpan;)Z +} + +public class com/datadog/legacy/trace/common/sampling/SamplingRule$OperationSamplingRule : com/datadog/legacy/trace/common/sampling/SamplingRule$PatternMatchSamplingRule { + public fun (Ljava/lang/String;Lcom/datadog/legacy/trace/common/sampling/RateSampler;)V + protected fun getRelevantString (Lcom/datadog/opentracing/DDSpan;)Ljava/lang/String; +} + +public abstract class com/datadog/legacy/trace/common/sampling/SamplingRule$PatternMatchSamplingRule : com/datadog/legacy/trace/common/sampling/SamplingRule { + public fun (Ljava/lang/String;Lcom/datadog/legacy/trace/common/sampling/RateSampler;)V + protected abstract fun getRelevantString (Lcom/datadog/opentracing/DDSpan;)Ljava/lang/String; + public fun matches (Lcom/datadog/opentracing/DDSpan;)Z +} + +public class com/datadog/legacy/trace/common/sampling/SamplingRule$ServiceSamplingRule : com/datadog/legacy/trace/common/sampling/SamplingRule$PatternMatchSamplingRule { + public fun (Ljava/lang/String;Lcom/datadog/legacy/trace/common/sampling/RateSampler;)V + protected fun getRelevantString (Lcom/datadog/opentracing/DDSpan;)Ljava/lang/String; +} + +public class com/datadog/legacy/trace/common/util/Clock { + public fun ()V + public static fun currentMicroTime ()J + public static fun currentNanoTicks ()J + public static fun currentNanoTime ()J +} + +public class com/datadog/legacy/trace/common/writer/LoggingWriter : com/datadog/legacy/trace/common/writer/Writer { + public fun ()V + public fun close ()V + public fun incrementTraceCount ()V + public fun start ()V + public fun toString ()Ljava/lang/String; + public fun write (Ljava/util/List;)V +} + +public abstract interface class com/datadog/legacy/trace/common/writer/Writer : java/io/Closeable { + public abstract fun close ()V + public abstract fun incrementTraceCount ()V + public abstract fun start ()V + public abstract fun write (Ljava/util/List;)V +} + +public abstract interface class com/datadog/legacy/trace/context/ScopeListener { + public abstract fun afterScopeActivated ()V + public abstract fun afterScopeClosed ()V +} + +public abstract interface class com/datadog/legacy/trace/context/TraceScope : java/io/Closeable { + public abstract fun capture ()Lcom/datadog/legacy/trace/context/TraceScope$Continuation; + public abstract fun close ()V + public abstract fun isAsyncPropagating ()Z + public abstract fun setAsyncPropagation (Z)V +} + +public abstract interface class com/datadog/legacy/trace/context/TraceScope$Continuation { + public abstract fun activate ()Lcom/datadog/legacy/trace/context/TraceScope; + public abstract fun close ()V + public abstract fun close (Z)V +} + +public class com/datadog/opentracing/DDSpan : com/datadog/legacy/trace/api/interceptor/MutableSpan, io/opentracing/Span { public final fun context ()Lcom/datadog/opentracing/DDSpanContext; public synthetic fun context ()Lio/opentracing/SpanContext; public final fun drop ()V @@ -422,13 +838,13 @@ public class com/datadog/opentracing/DDSpan : com/datadog/trace/api/interceptor/ public final fun getBaggageItem (Ljava/lang/String;)Ljava/lang/String; public fun getDurationNano ()J public fun getError ()I - public fun getLocalRootSpan ()Lcom/datadog/trace/api/interceptor/MutableSpan; + public fun getLocalRootSpan ()Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public fun getMeta ()Ljava/util/Map; public fun getMetrics ()Ljava/util/Map; public fun getOperationName ()Ljava/lang/String; public fun getParentId ()Ljava/math/BigInteger; public fun getResourceName ()Ljava/lang/String; - public fun getRootSpan ()Lcom/datadog/trace/api/interceptor/MutableSpan; + public fun getRootSpan ()Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public fun getSamplingPriority ()Ljava/lang/Integer; public fun getServiceName ()Ljava/lang/String; public fun getSpanId ()Ljava/math/BigInteger; @@ -450,29 +866,29 @@ public class com/datadog/opentracing/DDSpan : com/datadog/trace/api/interceptor/ public synthetic fun log (Ljava/util/Map;)Lio/opentracing/Span; public final fun setBaggageItem (Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/opentracing/DDSpan; public synthetic fun setBaggageItem (Ljava/lang/String;Ljava/lang/String;)Lio/opentracing/Span; + public synthetic fun setError (Z)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public fun setError (Z)Lcom/datadog/opentracing/DDSpan; - public synthetic fun setError (Z)Lcom/datadog/trace/api/interceptor/MutableSpan; public fun setErrorMeta (Ljava/lang/Throwable;)V + public synthetic fun setOperationName (Ljava/lang/String;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public final fun setOperationName (Ljava/lang/String;)Lcom/datadog/opentracing/DDSpan; - public synthetic fun setOperationName (Ljava/lang/String;)Lcom/datadog/trace/api/interceptor/MutableSpan; public synthetic fun setOperationName (Ljava/lang/String;)Lio/opentracing/Span; + public synthetic fun setResourceName (Ljava/lang/String;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public final fun setResourceName (Ljava/lang/String;)Lcom/datadog/opentracing/DDSpan; - public synthetic fun setResourceName (Ljava/lang/String;)Lcom/datadog/trace/api/interceptor/MutableSpan; + public synthetic fun setSamplingPriority (I)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public final fun setSamplingPriority (I)Lcom/datadog/opentracing/DDSpan; - public synthetic fun setSamplingPriority (I)Lcom/datadog/trace/api/interceptor/MutableSpan; + public synthetic fun setServiceName (Ljava/lang/String;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public final fun setServiceName (Ljava/lang/String;)Lcom/datadog/opentracing/DDSpan; - public synthetic fun setServiceName (Ljava/lang/String;)Lcom/datadog/trace/api/interceptor/MutableSpan; + public synthetic fun setSpanType (Ljava/lang/String;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public final fun setSpanType (Ljava/lang/String;)Lcom/datadog/opentracing/DDSpan; - public synthetic fun setSpanType (Ljava/lang/String;)Lcom/datadog/trace/api/interceptor/MutableSpan; public fun setTag (Lio/opentracing/tag/Tag;Ljava/lang/Object;)Lio/opentracing/Span; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/Number;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public final fun setTag (Ljava/lang/String;Ljava/lang/Number;)Lcom/datadog/opentracing/DDSpan; - public synthetic fun setTag (Ljava/lang/String;Ljava/lang/Number;)Lcom/datadog/trace/api/interceptor/MutableSpan; public synthetic fun setTag (Ljava/lang/String;Ljava/lang/Number;)Lio/opentracing/Span; + public synthetic fun setTag (Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public final fun setTag (Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/opentracing/DDSpan; - public synthetic fun setTag (Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/trace/api/interceptor/MutableSpan; public synthetic fun setTag (Ljava/lang/String;Ljava/lang/String;)Lio/opentracing/Span; + public synthetic fun setTag (Ljava/lang/String;Z)Lcom/datadog/legacy/trace/api/interceptor/MutableSpan; public final fun setTag (Ljava/lang/String;Z)Lcom/datadog/opentracing/DDSpan; - public synthetic fun setTag (Ljava/lang/String;Z)Lcom/datadog/trace/api/interceptor/MutableSpan; public synthetic fun setTag (Ljava/lang/String;Z)Lio/opentracing/Span; public fun toString ()Ljava/lang/String; } @@ -509,698 +925,282 @@ public class com/datadog/opentracing/DDSpanContext : io/opentracing/SpanContext public fun setResourceName (Ljava/lang/String;)V public fun setSamplingPriority (I)Z public fun setServiceName (Ljava/lang/String;)V - public fun setSpanType (Ljava/lang/String;)V - public fun setTag (Ljava/lang/String;Ljava/lang/Object;)V - public fun toSpanId ()Ljava/lang/String; - public fun toString ()Ljava/lang/String; - public fun toTraceId ()Ljava/lang/String; -} - -public class com/datadog/opentracing/DDTraceOTInfo { - public static final field JAVA_VERSION Ljava/lang/String; - public static final field JAVA_VM_NAME Ljava/lang/String; - public static final field JAVA_VM_VENDOR Ljava/lang/String; - public static final field VERSION Ljava/lang/String; - public fun ()V - public static fun main ([Ljava/lang/String;)V -} - -public class com/datadog/opentracing/DDTracer : com/datadog/trace/api/Tracer, io/opentracing/Tracer, java/io/Closeable { - public static final field TRACE_ID_MAX Ljava/math/BigInteger; - public static final field TRACE_ID_MIN Ljava/math/BigInteger; - protected fun (Lcom/datadog/trace/api/Config;Lcom/datadog/trace/common/writer/Writer;Ljava/util/Random;)V - public fun activateSpan (Lio/opentracing/Span;)Lio/opentracing/Scope; - public fun activeSpan ()Lio/opentracing/Span; - public fun addDecorator (Lcom/datadog/opentracing/decorators/AbstractDecorator;)V - public fun addScopeContext (Lcom/datadog/opentracing/scopemanager/ScopeContext;)V - public fun addScopeListener (Lcom/datadog/trace/context/ScopeListener;)V - public fun addTraceInterceptor (Lcom/datadog/trace/api/interceptor/TraceInterceptor;)Z - public fun buildSpan (Ljava/lang/String;)Lio/opentracing/Tracer$SpanBuilder; - public fun close ()V - public fun extract (Lio/opentracing/propagation/Format;Ljava/lang/Object;)Lio/opentracing/SpanContext; - public fun finalize ()V - public fun getPartialFlushMinSpans ()I - public fun getSpanContextDecorators (Ljava/lang/String;)Ljava/util/List; - public fun getSpanId ()Ljava/lang/String; - public fun getTraceId ()Ljava/lang/String; - public fun inject (Lio/opentracing/SpanContext;Lio/opentracing/propagation/Format;Ljava/lang/Object;)V - public fun registerClassLoader (Ljava/lang/ClassLoader;)V - public fun scopeManager ()Lio/opentracing/ScopeManager; - public fun toString ()Ljava/lang/String; -} - -public class com/datadog/opentracing/DDTracer$DDSpanBuilder : io/opentracing/Tracer$SpanBuilder { - public fun (Lcom/datadog/opentracing/DDTracer;Ljava/lang/String;Lio/opentracing/ScopeManager;)V - public fun addReference (Ljava/lang/String;Lio/opentracing/SpanContext;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public synthetic fun addReference (Ljava/lang/String;Lio/opentracing/SpanContext;)Lio/opentracing/Tracer$SpanBuilder; - public fun asChildOf (Lio/opentracing/Span;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public synthetic fun asChildOf (Lio/opentracing/Span;)Lio/opentracing/Tracer$SpanBuilder; - public fun asChildOf (Lio/opentracing/SpanContext;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public synthetic fun asChildOf (Lio/opentracing/SpanContext;)Lio/opentracing/Tracer$SpanBuilder; - public fun baggageItems ()Ljava/lang/Iterable; - public fun ignoreActiveSpan ()Lio/opentracing/Tracer$SpanBuilder; - public fun start ()Lio/opentracing/Span; - public fun startActive (Z)Lio/opentracing/Scope; - public fun startManual ()Lio/opentracing/Span; - public fun withErrorFlag ()Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public fun withLogHandler (Lcom/datadog/opentracing/LogHandler;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public fun withOrigin (Ljava/lang/String;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public fun withResourceName (Ljava/lang/String;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public fun withServiceName (Ljava/lang/String;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public fun withSpanType (Ljava/lang/String;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public fun withStartTimestamp (J)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public synthetic fun withStartTimestamp (J)Lio/opentracing/Tracer$SpanBuilder; - public fun withTag (Lio/opentracing/tag/Tag;Ljava/lang/Object;)Lio/opentracing/Tracer$SpanBuilder; - public fun withTag (Ljava/lang/String;Ljava/lang/Number;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public synthetic fun withTag (Ljava/lang/String;Ljava/lang/Number;)Lio/opentracing/Tracer$SpanBuilder; - public fun withTag (Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public synthetic fun withTag (Ljava/lang/String;Ljava/lang/String;)Lio/opentracing/Tracer$SpanBuilder; - public fun withTag (Ljava/lang/String;Z)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; - public synthetic fun withTag (Ljava/lang/String;Z)Lio/opentracing/Tracer$SpanBuilder; -} - -public class com/datadog/opentracing/DefaultLogHandler : com/datadog/opentracing/LogHandler { - public fun ()V - public fun log (JLjava/lang/String;Lcom/datadog/opentracing/DDSpan;)V - public fun log (JLjava/util/Map;Lcom/datadog/opentracing/DDSpan;)V - public fun log (Ljava/lang/String;Lcom/datadog/opentracing/DDSpan;)V - public fun log (Ljava/util/Map;Lcom/datadog/opentracing/DDSpan;)V -} - -public abstract interface class com/datadog/opentracing/LogHandler { - public abstract fun log (JLjava/lang/String;Lcom/datadog/opentracing/DDSpan;)V - public abstract fun log (JLjava/util/Map;Lcom/datadog/opentracing/DDSpan;)V - public abstract fun log (Ljava/lang/String;Lcom/datadog/opentracing/DDSpan;)V - public abstract fun log (Ljava/util/Map;Lcom/datadog/opentracing/DDSpan;)V -} - -public class com/datadog/opentracing/PendingTrace : java/util/LinkedList { - public fun addFirst (Lcom/datadog/opentracing/DDSpan;)V - public synthetic fun addFirst (Ljava/lang/Object;)V - public fun addSpan (Lcom/datadog/opentracing/DDSpan;)V - public fun cancelContinuation (Lcom/datadog/opentracing/scopemanager/ContinuableScope$Continuation;)V - public fun clean ()Z - public fun dropSpan (Lcom/datadog/opentracing/DDSpan;)V - public fun getCurrentTimeNano ()J - public fun getRootSpan ()Lcom/datadog/opentracing/DDSpan; - public fun registerContinuation (Lcom/datadog/opentracing/scopemanager/ContinuableScope$Continuation;)V - public fun registerSpan (Lcom/datadog/opentracing/DDSpan;)V - public fun size ()I -} - -public class com/datadog/opentracing/StringCachingBigInteger : java/math/BigInteger { - public fun (IILjava/util/Random;)V - public fun (ILjava/util/Random;)V - public fun (I[B)V - public fun (Ljava/lang/String;)V - public fun (Ljava/lang/String;I)V - public fun ([B)V - public fun equals (Ljava/lang/Object;)Z - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public abstract class com/datadog/opentracing/decorators/AbstractDecorator { - public fun ()V - public fun getMatchingTag ()Ljava/lang/String; - public fun getMatchingValue ()Ljava/lang/Object; - public fun getReplacementTag ()Ljava/lang/String; - public fun getReplacementValue ()Ljava/lang/String; - public fun setMatchingTag (Ljava/lang/String;)V - public fun setMatchingValue (Ljava/lang/Object;)V - public fun setReplacementTag (Ljava/lang/String;)V - public fun setReplacementValue (Ljava/lang/String;)V - public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z -} - -public class com/datadog/opentracing/decorators/DBTypeDecorator : com/datadog/opentracing/decorators/AbstractDecorator { - public fun ()V - public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z -} - -public class com/datadog/opentracing/decorators/DDDecoratorsFactory { - public fun ()V - public static fun createBuiltinDecorators ()Ljava/util/List; -} - -public class com/datadog/opentracing/decorators/ForceManualDropDecorator : com/datadog/opentracing/decorators/AbstractDecorator { - public fun ()V - public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z -} - -public class com/datadog/opentracing/decorators/ForceManualKeepDecorator : com/datadog/opentracing/decorators/AbstractDecorator { - public fun ()V - public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z -} - -public class com/datadog/opentracing/decorators/PeerServiceDecorator : com/datadog/opentracing/decorators/AbstractDecorator { - public fun ()V - public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z -} - -public class com/datadog/opentracing/decorators/ServiceNameDecorator : com/datadog/opentracing/decorators/AbstractDecorator { - public fun ()V - public fun (Ljava/lang/String;Z)V - public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z -} - -public class com/datadog/opentracing/decorators/ServletContextDecorator : com/datadog/opentracing/decorators/AbstractDecorator { - public fun ()V - public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z -} - -public final class com/datadog/opentracing/jfr/DDNoopScopeEvent : com/datadog/opentracing/jfr/DDScopeEvent { - public static final field INSTANCE Lcom/datadog/opentracing/jfr/DDNoopScopeEvent; - public fun ()V - public fun finish ()V - public fun start ()V -} - -public final class com/datadog/opentracing/jfr/DDNoopScopeEventFactory : com/datadog/opentracing/jfr/DDScopeEventFactory { - public fun ()V - public fun create (Lcom/datadog/opentracing/DDSpanContext;)Lcom/datadog/opentracing/jfr/DDScopeEvent; -} - -public abstract interface class com/datadog/opentracing/jfr/DDScopeEvent { - public abstract fun finish ()V - public abstract fun start ()V -} - -public abstract interface class com/datadog/opentracing/jfr/DDScopeEventFactory { - public abstract fun create (Lcom/datadog/opentracing/DDSpanContext;)Lcom/datadog/opentracing/jfr/DDScopeEvent; -} - -public class com/datadog/opentracing/propagation/ExtractedContext : com/datadog/opentracing/propagation/TagContext { - public fun (Ljava/math/BigInteger;Ljava/math/BigInteger;ILjava/lang/String;Ljava/util/Map;Ljava/util/Map;)V - public fun baggageItems ()Ljava/lang/Iterable; - public fun getBaggage ()Ljava/util/Map; - public fun getSamplingPriority ()I - public fun getSamplingPriorityLocked ()Z - public fun getSpanId ()Ljava/math/BigInteger; - public fun getTraceId ()Ljava/math/BigInteger; - public fun lockSamplingPriority ()V -} - -public class com/datadog/opentracing/propagation/HaystackHttpCodec { -} - -public class com/datadog/opentracing/propagation/HaystackHttpCodec$Extractor : com/datadog/opentracing/propagation/HttpCodec$Extractor { - public fun (Ljava/util/Map;)V - public fun extract (Lio/opentracing/propagation/TextMapExtract;)Lio/opentracing/SpanContext; -} - -public class com/datadog/opentracing/propagation/HaystackHttpCodec$Injector : com/datadog/opentracing/propagation/HttpCodec$Injector { - public fun ()V - public fun inject (Lcom/datadog/opentracing/DDSpanContext;Lio/opentracing/propagation/TextMapInject;)V -} - -public class com/datadog/opentracing/propagation/HttpCodec { - public fun ()V - public static fun createExtractor (Lcom/datadog/trace/api/Config;Ljava/util/Map;)Lcom/datadog/opentracing/propagation/HttpCodec$Extractor; - public static fun createInjector (Lcom/datadog/trace/api/Config;)Lcom/datadog/opentracing/propagation/HttpCodec$Injector; -} - -public class com/datadog/opentracing/propagation/HttpCodec$CompoundExtractor : com/datadog/opentracing/propagation/HttpCodec$Extractor { - public fun (Ljava/util/List;)V - public fun extract (Lio/opentracing/propagation/TextMapExtract;)Lio/opentracing/SpanContext; -} - -public class com/datadog/opentracing/propagation/HttpCodec$CompoundInjector : com/datadog/opentracing/propagation/HttpCodec$Injector { - public fun (Ljava/util/List;)V - public fun inject (Lcom/datadog/opentracing/DDSpanContext;Lio/opentracing/propagation/TextMapInject;)V -} - -public abstract interface class com/datadog/opentracing/propagation/HttpCodec$Extractor { - public abstract fun extract (Lio/opentracing/propagation/TextMapExtract;)Lio/opentracing/SpanContext; -} - -public abstract interface class com/datadog/opentracing/propagation/HttpCodec$Injector { - public abstract fun inject (Lcom/datadog/opentracing/DDSpanContext;Lio/opentracing/propagation/TextMapInject;)V -} - -public class com/datadog/opentracing/propagation/TagContext : io/opentracing/SpanContext { - public fun (Ljava/lang/String;Ljava/util/Map;)V - public fun baggageItems ()Ljava/lang/Iterable; - public fun getOrigin ()Ljava/lang/String; - public fun getTags ()Ljava/util/Map; + public fun setSpanType (Ljava/lang/String;)V + public fun setTag (Ljava/lang/String;Ljava/lang/Object;)V public fun toSpanId ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; public fun toTraceId ()Ljava/lang/String; } -public class com/datadog/opentracing/scopemanager/ContextualScopeManager : io/opentracing/ScopeManager { - public fun (ILcom/datadog/opentracing/jfr/DDScopeEventFactory;)V - public fun activate (Lio/opentracing/Span;)Lio/opentracing/Scope; - public fun activate (Lio/opentracing/Span;Z)Lio/opentracing/Scope; - public fun active ()Lio/opentracing/Scope; - public fun activeSpan ()Lio/opentracing/Span; - public fun addScopeContext (Lcom/datadog/opentracing/scopemanager/ScopeContext;)V - public fun addScopeListener (Lcom/datadog/trace/context/ScopeListener;)V +public class com/datadog/opentracing/DDTraceOTInfo { + public static final field JAVA_VERSION Ljava/lang/String; + public static final field JAVA_VM_NAME Ljava/lang/String; + public static final field JAVA_VM_VENDOR Ljava/lang/String; + public static final field VERSION Ljava/lang/String; + public fun ()V + public static fun main ([Ljava/lang/String;)V } -public class com/datadog/opentracing/scopemanager/ContinuableScope : com/datadog/opentracing/scopemanager/DDScope, com/datadog/trace/context/TraceScope { - public fun capture ()Lcom/datadog/opentracing/scopemanager/ContinuableScope$Continuation; - public synthetic fun capture ()Lcom/datadog/trace/context/TraceScope$Continuation; +public class com/datadog/opentracing/DDTracer : com/datadog/legacy/trace/api/Tracer, io/opentracing/Tracer, java/io/Closeable { + public static final field TRACE_ID_MAX Ljava/math/BigInteger; + public static final field TRACE_ID_MIN Ljava/math/BigInteger; + protected fun (Lcom/datadog/legacy/trace/api/Config;Lcom/datadog/legacy/trace/common/writer/Writer;Ljava/util/Random;)V + public fun activateSpan (Lio/opentracing/Span;)Lio/opentracing/Scope; + public fun activeSpan ()Lio/opentracing/Span; + public fun addDecorator (Lcom/datadog/opentracing/decorators/AbstractDecorator;)V + public fun addScopeContext (Lcom/datadog/opentracing/scopemanager/ScopeContext;)V + public fun addScopeListener (Lcom/datadog/legacy/trace/context/ScopeListener;)V + public fun addTraceInterceptor (Lcom/datadog/legacy/trace/api/interceptor/TraceInterceptor;)Z + public fun buildSpan (Ljava/lang/String;)Lio/opentracing/Tracer$SpanBuilder; public fun close ()V - public fun depth ()I - public fun isAsyncPropagating ()Z - public fun setAsyncPropagation (Z)V - public fun span ()Lcom/datadog/opentracing/DDSpan; - public synthetic fun span ()Lio/opentracing/Span; + public fun extract (Lio/opentracing/propagation/Format;Ljava/lang/Object;)Lio/opentracing/SpanContext; + public fun finalize ()V + public fun getPartialFlushMinSpans ()I + public fun getSpanContextDecorators (Ljava/lang/String;)Ljava/util/List; + public fun getSpanId ()Ljava/lang/String; + public fun getTraceId ()Ljava/lang/String; + public fun inject (Lio/opentracing/SpanContext;Lio/opentracing/propagation/Format;Ljava/lang/Object;)V + public fun registerClassLoader (Ljava/lang/ClassLoader;)V + public fun scopeManager ()Lio/opentracing/ScopeManager; public fun toString ()Ljava/lang/String; } -public class com/datadog/opentracing/scopemanager/ContinuableScope$Continuation : com/datadog/trace/context/TraceScope$Continuation, java/io/Closeable { - public field ref Ljava/lang/ref/WeakReference; - public fun activate ()Lcom/datadog/opentracing/scopemanager/ContinuableScope; - public synthetic fun activate ()Lcom/datadog/trace/context/TraceScope; - public fun close ()V - public fun close (Z)V -} - -public abstract interface class com/datadog/opentracing/scopemanager/ScopeContext : io/opentracing/ScopeManager { - public abstract fun inContext ()Z -} - -public class com/datadog/opentracing/scopemanager/SimpleScope : com/datadog/opentracing/scopemanager/DDScope { - public fun (Lcom/datadog/opentracing/scopemanager/ContextualScopeManager;Lio/opentracing/Span;Z)V - public fun close ()V - public fun depth ()I - public fun span ()Lio/opentracing/Span; -} - -public class com/datadog/trace/api/Config { - public static final field AGENT_HOST Ljava/lang/String; - public static final field AGENT_PORT_LEGACY Ljava/lang/String; - public static final field AGENT_UNIX_DOMAIN_SOCKET Ljava/lang/String; - public static final field API_KEY Ljava/lang/String; - public static final field API_KEY_FILE Ljava/lang/String; - public static final field CONFIGURATION_FILE Ljava/lang/String; - public static final field DB_CLIENT_HOST_SPLIT_BY_INSTANCE Ljava/lang/String; - public static final field DD_AGENT_WRITER_TYPE Ljava/lang/String; - public static final field DEFAULT_AGENT_HOST Ljava/lang/String; - public static final field DEFAULT_AGENT_UNIX_DOMAIN_SOCKET Ljava/lang/String; - public static final field DEFAULT_ANALYTICS_SAMPLE_RATE F - public static final field DEFAULT_INTEGRATIONS_ENABLED Z - public static final field DEFAULT_JMX_FETCH_STATSD_PORT I - public static final field DEFAULT_LOGS_INJECTION_ENABLED Z - public static final field DEFAULT_METRICS_ENABLED Z - public static final field DEFAULT_PROFILING_ENABLED Z - public static final field DEFAULT_PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE I - public static final field DEFAULT_PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS I - public static final field DEFAULT_PROFILING_EXCEPTION_SAMPLE_LIMIT I - public static final field DEFAULT_PROFILING_PROXY_PORT I - public static final field DEFAULT_PROFILING_START_DELAY I - public static final field DEFAULT_PROFILING_START_FORCE_FIRST Z - public static final field DEFAULT_PROFILING_UPLOAD_COMPRESSION Ljava/lang/String; - public static final field DEFAULT_PROFILING_UPLOAD_PERIOD I - public static final field DEFAULT_PROFILING_UPLOAD_TIMEOUT I - public static final field DEFAULT_SERVICE_NAME Ljava/lang/String; - public static final field DEFAULT_SITE Ljava/lang/String; - public static final field DEFAULT_TRACE_AGENT_PORT I - public static final field DEFAULT_TRACE_ANALYTICS_ENABLED Z - public static final field DEFAULT_TRACE_RATE_LIMIT D - public static final field GLOBAL_TAGS Ljava/lang/String; - public static final field HEADER_TAGS Ljava/lang/String; - public static final field HEALTH_METRICS_ENABLED Ljava/lang/String; - public static final field HEALTH_METRICS_STATSD_HOST Ljava/lang/String; - public static final field HEALTH_METRICS_STATSD_PORT Ljava/lang/String; - public static final field HOST_TAG Ljava/lang/String; - public static final field HTTP_CLIENT_ERROR_STATUSES Ljava/lang/String; - public static final field HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN Ljava/lang/String; - public static final field HTTP_CLIENT_TAG_QUERY_STRING Ljava/lang/String; - public static final field HTTP_SERVER_ERROR_STATUSES Ljava/lang/String; - public static final field HTTP_SERVER_TAG_QUERY_STRING Ljava/lang/String; - public static final field INTEGRATIONS_ENABLED Ljava/lang/String; - public static final field JMX_FETCH_CHECK_PERIOD Ljava/lang/String; - public static final field JMX_FETCH_CONFIG Ljava/lang/String; - public static final field JMX_FETCH_CONFIG_DIR Ljava/lang/String; - public static final field JMX_FETCH_ENABLED Ljava/lang/String; - public static final field JMX_FETCH_METRICS_CONFIGS Ljava/lang/String; - public static final field JMX_FETCH_REFRESH_BEANS_PERIOD Ljava/lang/String; - public static final field JMX_FETCH_STATSD_HOST Ljava/lang/String; - public static final field JMX_FETCH_STATSD_PORT Ljava/lang/String; - public static final field JMX_TAGS Ljava/lang/String; - public static final field LANGUAGE_TAG_KEY Ljava/lang/String; - public static final field LANGUAGE_TAG_VALUE Ljava/lang/String; - public static final field LOGGING_WRITER_TYPE Ljava/lang/String; - public static final field LOGS_INJECTION_ENABLED Ljava/lang/String; - public static final field PARTIAL_FLUSH_MIN_SPANS Ljava/lang/String; - public static final field PRIORITY_SAMPLING Ljava/lang/String; - public static final field PROFILING_API_KEY_FILE_OLD Ljava/lang/String; - public static final field PROFILING_API_KEY_FILE_VERY_OLD Ljava/lang/String; - public static final field PROFILING_API_KEY_OLD Ljava/lang/String; - public static final field PROFILING_API_KEY_VERY_OLD Ljava/lang/String; - public static final field PROFILING_ENABLED Ljava/lang/String; - public static final field PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE Ljava/lang/String; - public static final field PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS Ljava/lang/String; - public static final field PROFILING_EXCEPTION_SAMPLE_LIMIT Ljava/lang/String; - public static final field PROFILING_PROXY_HOST Ljava/lang/String; - public static final field PROFILING_PROXY_PASSWORD Ljava/lang/String; - public static final field PROFILING_PROXY_PORT Ljava/lang/String; - public static final field PROFILING_PROXY_USERNAME Ljava/lang/String; - public static final field PROFILING_START_DELAY Ljava/lang/String; - public static final field PROFILING_START_FORCE_FIRST Ljava/lang/String; - public static final field PROFILING_TAGS Ljava/lang/String; - public static final field PROFILING_TEMPLATE_OVERRIDE_FILE Ljava/lang/String; - public static final field PROFILING_UPLOAD_COMPRESSION Ljava/lang/String; - public static final field PROFILING_UPLOAD_PERIOD Ljava/lang/String; - public static final field PROFILING_UPLOAD_TIMEOUT Ljava/lang/String; - public static final field PROFILING_URL Ljava/lang/String; - public static final field PROFILING_URL_TEMPLATE Ljava/lang/String; - public static final field PROPAGATION_STYLE_EXTRACT Ljava/lang/String; - public static final field PROPAGATION_STYLE_INJECT Ljava/lang/String; - public static final field RUNTIME_CONTEXT_FIELD_INJECTION Ljava/lang/String; - public static final field RUNTIME_ID_TAG Ljava/lang/String; - public static final field SCOPE_DEPTH_LIMIT Ljava/lang/String; - public static final field SERVICE Ljava/lang/String; - public static final field SERVICE_MAPPING Ljava/lang/String; - public static final field SERVICE_NAME Ljava/lang/String; - public static final field SERVICE_TAG Ljava/lang/String; - public static final field SITE Ljava/lang/String; - public static final field SPAN_TAGS Ljava/lang/String; - public static final field SPLIT_BY_TAGS Ljava/lang/String; - public static final field TAGS Ljava/lang/String; - public static final field TRACE_AGENT_PORT Ljava/lang/String; - public static final field TRACE_ANALYTICS_ENABLED Ljava/lang/String; - public static final field TRACE_ANNOTATIONS Ljava/lang/String; - public static final field TRACE_CLASSES_EXCLUDE Ljava/lang/String; - public static final field TRACE_ENABLED Ljava/lang/String; - public static final field TRACE_EXECUTORS Ljava/lang/String; - public static final field TRACE_EXECUTORS_ALL Ljava/lang/String; - public static final field TRACE_METHODS Ljava/lang/String; - public static final field TRACE_RATE_LIMIT Ljava/lang/String; - public static final field TRACE_REPORT_HOSTNAME Ljava/lang/String; - public static final field TRACE_RESOLVER_ENABLED Ljava/lang/String; - public static final field TRACE_SAMPLE_RATE Ljava/lang/String; - public static final field TRACE_SAMPLING_OPERATION_RULES Ljava/lang/String; - public static final field TRACE_SAMPLING_SERVICE_RULES Ljava/lang/String; - public static final field WRITER_TYPE Ljava/lang/String; - public static fun get ()Lcom/datadog/trace/api/Config; - public static fun get (Ljava/util/Properties;)Lcom/datadog/trace/api/Config; - public fun getAgentHost ()Ljava/lang/String; - public fun getAgentPort ()I - public fun getAgentUnixDomainSocket ()Ljava/lang/String; - public static fun getBooleanSettingFromEnvironment (Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/Boolean; - public fun getExcludedClasses ()Ljava/util/List; - public fun getFinalProfilingUrl ()Ljava/lang/String; - public static fun getFloatSettingFromEnvironment (Ljava/lang/String;Ljava/lang/Float;)Ljava/lang/Float; - public fun getHeaderTags ()Ljava/util/Map; - public fun getHealthMetricsStatsdHost ()Ljava/lang/String; - public fun getHealthMetricsStatsdPort ()Ljava/lang/Integer; - public fun getHttpClientErrorStatuses ()Ljava/util/Set; - public fun getHttpServerErrorStatuses ()Ljava/util/Set; - public fun getInstrumentationAnalyticsSampleRate ([Ljava/lang/String;)F - public fun getJmxFetchCheckPeriod ()Ljava/lang/Integer; - public fun getJmxFetchConfigDir ()Ljava/lang/String; - public fun getJmxFetchConfigs ()Ljava/util/List; - public fun getJmxFetchMetricsConfigs ()Ljava/util/List; - public fun getJmxFetchRefreshBeansPeriod ()Ljava/lang/Integer; - public fun getJmxFetchStatsdHost ()Ljava/lang/String; - public fun getJmxFetchStatsdPort ()Ljava/lang/Integer; - public fun getLocalRootSpanTags ()Ljava/util/Map; - public fun getMergedJmxTags ()Ljava/util/Map; - public fun getMergedProfilingTags ()Ljava/util/Map; - public fun getMergedSpanTags ()Ljava/util/Map; - public fun getPartialFlushMinSpans ()Ljava/lang/Integer; - public fun getProfilingExceptionHistogramMaxCollectionSize ()I - public fun getProfilingExceptionHistogramTopItems ()I - public fun getProfilingExceptionSampleLimit ()I - public fun getProfilingProxyHost ()Ljava/lang/String; - public fun getProfilingProxyPassword ()Ljava/lang/String; - public fun getProfilingProxyPort ()I - public fun getProfilingProxyUsername ()Ljava/lang/String; - public fun getProfilingStartDelay ()I - public fun getProfilingTemplateOverrideFile ()Ljava/lang/String; - public fun getProfilingUploadCompression ()Ljava/lang/String; - public fun getProfilingUploadPeriod ()I - public fun getProfilingUploadTimeout ()I - public fun getPropagationStylesToExtract ()Ljava/util/Set; - public fun getPropagationStylesToInject ()Ljava/util/Set; - public fun getRuntimeId ()Ljava/lang/String; - public fun getScopeDepthLimit ()Ljava/lang/Integer; - public fun getServiceMapping ()Ljava/util/Map; - public fun getServiceName ()Ljava/lang/String; - public static fun getSettingFromEnvironment (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; - public fun getSite ()Ljava/lang/String; - public fun getSplitByTags ()Ljava/util/Set; - public fun getTraceAnnotations ()Ljava/lang/String; - public fun getTraceExecutors ()Ljava/util/List; - public fun getTraceMethods ()Ljava/lang/String; - public fun getTraceRateLimit ()Ljava/lang/Double; - public fun getTraceSampleRate ()Ljava/lang/Double; - public fun getTraceSamplingOperationRules ()Ljava/util/Map; - public fun getTraceSamplingServiceRules ()Ljava/util/Map; - public fun getWriterType ()Ljava/lang/String; - public fun isDbClientSplitByInstance ()Z - public fun isHealthMetricsEnabled ()Z - public fun isHttpClientSplitByDomain ()Z - public fun isHttpClientTagQueryString ()Z - public fun isHttpServerTagQueryString ()Z - public fun isIntegrationEnabled (Ljava/util/SortedSet;Z)Z - public fun isIntegrationsEnabled ()Z - public fun isJmxFetchEnabled ()Z - public fun isJmxFetchIntegrationEnabled (Ljava/util/SortedSet;Z)Z - public fun isLogsInjectionEnabled ()Z - public fun isPrioritySamplingEnabled ()Z - public fun isProfilingEnabled ()Z - public fun isProfilingStartForceFirst ()Z - public fun isReportHostName ()Z - public fun isRuleEnabled (Ljava/lang/String;)Z - public fun isRuntimeContextFieldInjection ()Z - public fun isTraceAnalyticsEnabled ()Z - public fun isTraceAnalyticsIntegrationEnabled (Ljava/util/SortedSet;Z)Z - public fun isTraceEnabled ()Z - public fun isTraceExecutorsAll ()Z - public fun isTraceResolverEnabled ()Z - public static fun jmxFetchIntegrationEnabled (Ljava/util/SortedSet;Z)Z +public class com/datadog/opentracing/DDTracer$DDSpanBuilder : io/opentracing/Tracer$SpanBuilder { + public fun (Lcom/datadog/opentracing/DDTracer;Ljava/lang/String;Lio/opentracing/ScopeManager;)V + public fun addReference (Ljava/lang/String;Lio/opentracing/SpanContext;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public synthetic fun addReference (Ljava/lang/String;Lio/opentracing/SpanContext;)Lio/opentracing/Tracer$SpanBuilder; + public fun asChildOf (Lio/opentracing/Span;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public synthetic fun asChildOf (Lio/opentracing/Span;)Lio/opentracing/Tracer$SpanBuilder; + public fun asChildOf (Lio/opentracing/SpanContext;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public synthetic fun asChildOf (Lio/opentracing/SpanContext;)Lio/opentracing/Tracer$SpanBuilder; + public fun baggageItems ()Ljava/lang/Iterable; + public fun ignoreActiveSpan ()Lio/opentracing/Tracer$SpanBuilder; + public fun start ()Lio/opentracing/Span; + public fun startActive (Z)Lio/opentracing/Scope; + public fun startManual ()Lio/opentracing/Span; + public fun withErrorFlag ()Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public fun withLogHandler (Lcom/datadog/opentracing/LogHandler;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public fun withOrigin (Ljava/lang/String;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public fun withResourceName (Ljava/lang/String;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public fun withServiceName (Ljava/lang/String;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public fun withSpanType (Ljava/lang/String;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public fun withStartTimestamp (J)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public synthetic fun withStartTimestamp (J)Lio/opentracing/Tracer$SpanBuilder; + public fun withTag (Lio/opentracing/tag/Tag;Ljava/lang/Object;)Lio/opentracing/Tracer$SpanBuilder; + public fun withTag (Ljava/lang/String;Ljava/lang/Number;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public synthetic fun withTag (Ljava/lang/String;Ljava/lang/Number;)Lio/opentracing/Tracer$SpanBuilder; + public fun withTag (Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public synthetic fun withTag (Ljava/lang/String;Ljava/lang/String;)Lio/opentracing/Tracer$SpanBuilder; + public fun withTag (Ljava/lang/String;Z)Lcom/datadog/opentracing/DDTracer$DDSpanBuilder; + public synthetic fun withTag (Ljava/lang/String;Z)Lio/opentracing/Tracer$SpanBuilder; +} + +public class com/datadog/opentracing/DefaultLogHandler : com/datadog/opentracing/LogHandler { + public fun ()V + public fun log (JLjava/lang/String;Lcom/datadog/opentracing/DDSpan;)V + public fun log (JLjava/util/Map;Lcom/datadog/opentracing/DDSpan;)V + public fun log (Ljava/lang/String;Lcom/datadog/opentracing/DDSpan;)V + public fun log (Ljava/util/Map;Lcom/datadog/opentracing/DDSpan;)V +} + +public abstract interface class com/datadog/opentracing/LogHandler { + public abstract fun log (JLjava/lang/String;Lcom/datadog/opentracing/DDSpan;)V + public abstract fun log (JLjava/util/Map;Lcom/datadog/opentracing/DDSpan;)V + public abstract fun log (Ljava/lang/String;Lcom/datadog/opentracing/DDSpan;)V + public abstract fun log (Ljava/util/Map;Lcom/datadog/opentracing/DDSpan;)V +} + +public class com/datadog/opentracing/PendingTrace : java/util/LinkedList { + public fun addFirst (Lcom/datadog/opentracing/DDSpan;)V + public synthetic fun addFirst (Ljava/lang/Object;)V + public fun addSpan (Lcom/datadog/opentracing/DDSpan;)V + public fun cancelContinuation (Lcom/datadog/opentracing/scopemanager/ContinuableScope$Continuation;)V + public fun clean ()Z + public fun dropSpan (Lcom/datadog/opentracing/DDSpan;)V + public fun getCurrentTimeNano ()J + public fun getRootSpan ()Lcom/datadog/opentracing/DDSpan; + public fun registerContinuation (Lcom/datadog/opentracing/scopemanager/ContinuableScope$Continuation;)V + public fun registerSpan (Lcom/datadog/opentracing/DDSpan;)V + public fun size ()I +} + +public class com/datadog/opentracing/StringCachingBigInteger : java/math/BigInteger { + public fun (IILjava/util/Random;)V + public fun (ILjava/util/Random;)V + public fun (I[B)V + public fun (Ljava/lang/String;)V + public fun (Ljava/lang/String;I)V + public fun ([B)V + public fun equals (Ljava/lang/Object;)Z + public fun hashCode ()I public fun toString ()Ljava/lang/String; - public static fun traceAnalyticsIntegrationEnabled (Ljava/util/SortedSet;Z)Z } -public final class com/datadog/trace/api/Config$PropagationStyle : java/lang/Enum { - public static final field B3 Lcom/datadog/trace/api/Config$PropagationStyle; - public static final field B3MULTI Lcom/datadog/trace/api/Config$PropagationStyle; - public static final field DATADOG Lcom/datadog/trace/api/Config$PropagationStyle; - public static final field HAYSTACK Lcom/datadog/trace/api/Config$PropagationStyle; - public static final field TRACECONTEXT Lcom/datadog/trace/api/Config$PropagationStyle; - public static fun valueOf (Ljava/lang/String;)Lcom/datadog/trace/api/Config$PropagationStyle; - public static fun values ()[Lcom/datadog/trace/api/Config$PropagationStyle; +public abstract class com/datadog/opentracing/decorators/AbstractDecorator { + public fun ()V + public fun getMatchingTag ()Ljava/lang/String; + public fun getMatchingValue ()Ljava/lang/Object; + public fun getReplacementTag ()Ljava/lang/String; + public fun getReplacementValue ()Ljava/lang/String; + public fun setMatchingTag (Ljava/lang/String;)V + public fun setMatchingValue (Ljava/lang/Object;)V + public fun setReplacementTag (Ljava/lang/String;)V + public fun setReplacementValue (Ljava/lang/String;)V + public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z } -public class com/datadog/trace/api/DDSpanTypes { - public static final field CACHE Ljava/lang/String; - public static final field CASSANDRA Ljava/lang/String; - public static final field COUCHBASE Ljava/lang/String; - public static final field ELASTICSEARCH Ljava/lang/String; - public static final field HIBERNATE Ljava/lang/String; - public static final field HTTP_CLIENT Ljava/lang/String; - public static final field HTTP_SERVER Ljava/lang/String; - public static final field MEMCACHED Ljava/lang/String; - public static final field MESSAGE_CLIENT Ljava/lang/String; - public static final field MESSAGE_CONSUMER Ljava/lang/String; - public static final field MESSAGE_PRODUCER Ljava/lang/String; - public static final field MONGO Ljava/lang/String; - public static final field REDIS Ljava/lang/String; - public static final field RPC Ljava/lang/String; - public static final field SQL Ljava/lang/String; - public static final field WEB_SERVLET Ljava/lang/String; +public class com/datadog/opentracing/decorators/DBTypeDecorator : com/datadog/opentracing/decorators/AbstractDecorator { public fun ()V + public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z } -public class com/datadog/trace/api/DDTags { - public static final field ANALYTICS_SAMPLE_RATE Ljava/lang/String; - public static final field DB_STATEMENT Ljava/lang/String; - public static final field ERROR_MSG Ljava/lang/String; - public static final field ERROR_STACK Ljava/lang/String; - public static final field ERROR_TYPE Ljava/lang/String; - public static final field EVENT_SAMPLE_RATE Ljava/lang/String; - public static final field HTTP_FRAGMENT Ljava/lang/String; - public static final field HTTP_QUERY Ljava/lang/String; - public static final field MANUAL_DROP Ljava/lang/String; - public static final field MANUAL_KEEP Ljava/lang/String; - public static final field RESOURCE_NAME Ljava/lang/String; - public static final field SERVICE_NAME Ljava/lang/String; - public static final field SPAN_TYPE Ljava/lang/String; - public static final field THREAD_ID Ljava/lang/String; - public static final field THREAD_NAME Ljava/lang/String; - public static final field USER_NAME Ljava/lang/String; +public class com/datadog/opentracing/decorators/DDDecoratorsFactory { public fun ()V + public static fun createBuiltinDecorators ()Ljava/util/List; } -public class com/datadog/trace/api/DDTraceApiInfo { - public static final field VERSION Ljava/lang/String; +public class com/datadog/opentracing/decorators/ForceManualDropDecorator : com/datadog/opentracing/decorators/AbstractDecorator { public fun ()V - public static fun main ([Ljava/lang/String;)V + public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z } -public abstract interface annotation class com/datadog/trace/api/Trace : java/lang/annotation/Annotation { - public abstract fun operationName ()Ljava/lang/String; - public abstract fun resourceName ()Ljava/lang/String; +public class com/datadog/opentracing/decorators/ForceManualKeepDecorator : com/datadog/opentracing/decorators/AbstractDecorator { + public fun ()V + public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z } -public abstract interface class com/datadog/trace/api/Tracer { - public abstract fun addScopeListener (Lcom/datadog/trace/context/ScopeListener;)V - public abstract fun addTraceInterceptor (Lcom/datadog/trace/api/interceptor/TraceInterceptor;)Z - public abstract fun getSpanId ()Ljava/lang/String; - public abstract fun getTraceId ()Ljava/lang/String; +public class com/datadog/opentracing/decorators/PeerServiceDecorator : com/datadog/opentracing/decorators/AbstractDecorator { + public fun ()V + public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z } -public abstract interface class com/datadog/trace/api/interceptor/MutableSpan { - public abstract fun drop ()V - public abstract fun getDurationNano ()J - public abstract fun getLocalRootSpan ()Lcom/datadog/trace/api/interceptor/MutableSpan; - public abstract fun getOperationName ()Ljava/lang/String; - public abstract fun getResourceName ()Ljava/lang/String; - public abstract fun getRootSpan ()Lcom/datadog/trace/api/interceptor/MutableSpan; - public abstract fun getSamplingPriority ()Ljava/lang/Integer; - public abstract fun getServiceName ()Ljava/lang/String; - public abstract fun getSpanType ()Ljava/lang/String; - public abstract fun getStartTime ()J - public abstract fun getTags ()Ljava/util/Map; - public abstract fun isError ()Ljava/lang/Boolean; - public abstract fun setError (Z)Lcom/datadog/trace/api/interceptor/MutableSpan; - public abstract fun setOperationName (Ljava/lang/String;)Lcom/datadog/trace/api/interceptor/MutableSpan; - public abstract fun setResourceName (Ljava/lang/String;)Lcom/datadog/trace/api/interceptor/MutableSpan; - public abstract fun setSamplingPriority (I)Lcom/datadog/trace/api/interceptor/MutableSpan; - public abstract fun setServiceName (Ljava/lang/String;)Lcom/datadog/trace/api/interceptor/MutableSpan; - public abstract fun setSpanType (Ljava/lang/String;)Lcom/datadog/trace/api/interceptor/MutableSpan; - public abstract fun setTag (Ljava/lang/String;Ljava/lang/Number;)Lcom/datadog/trace/api/interceptor/MutableSpan; - public abstract fun setTag (Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/trace/api/interceptor/MutableSpan; - public abstract fun setTag (Ljava/lang/String;Z)Lcom/datadog/trace/api/interceptor/MutableSpan; -} - -public abstract interface class com/datadog/trace/api/interceptor/TraceInterceptor { - public abstract fun onTraceComplete (Ljava/util/Collection;)Ljava/util/Collection; - public abstract fun priority ()I +public class com/datadog/opentracing/decorators/ServiceNameDecorator : com/datadog/opentracing/decorators/AbstractDecorator { + public fun ()V + public fun (Ljava/lang/String;Z)V + public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z } -public class com/datadog/trace/api/sampling/PrioritySampling { - public static final field SAMPLER_DROP I - public static final field SAMPLER_KEEP I - public static final field UNSET I - public static final field USER_DROP I - public static final field USER_KEEP I +public class com/datadog/opentracing/decorators/ServletContextDecorator : com/datadog/opentracing/decorators/AbstractDecorator { + public fun ()V + public fun shouldSetTag (Lcom/datadog/opentracing/DDSpanContext;Ljava/lang/String;Ljava/lang/Object;)Z } -public abstract class com/datadog/trace/common/sampling/AbstractSampler : com/datadog/trace/common/sampling/Sampler { - protected field skipTagsPatterns Ljava/util/Map; +public final class com/datadog/opentracing/jfr/DDNoopScopeEvent : com/datadog/opentracing/jfr/DDScopeEvent { + public static final field INSTANCE Lcom/datadog/opentracing/jfr/DDNoopScopeEvent; public fun ()V - public fun addSkipTagPattern (Ljava/lang/String;Ljava/util/regex/Pattern;)V - protected abstract fun doSample (Lcom/datadog/opentracing/DDSpan;)Z - public fun sample (Lcom/datadog/opentracing/DDSpan;)Z + public fun finish ()V + public fun start ()V } -public class com/datadog/trace/common/sampling/AllSampler : com/datadog/trace/common/sampling/AbstractSampler { +public final class com/datadog/opentracing/jfr/DDNoopScopeEventFactory : com/datadog/opentracing/jfr/DDScopeEventFactory { public fun ()V - public fun doSample (Lcom/datadog/opentracing/DDSpan;)Z - public fun toString ()Ljava/lang/String; + public fun create (Lcom/datadog/opentracing/DDSpanContext;)Lcom/datadog/opentracing/jfr/DDScopeEvent; } -public class com/datadog/trace/common/sampling/DeterministicSampler : com/datadog/trace/common/sampling/RateSampler { - public fun (D)V - public fun getSampleRate ()D - public fun sample (Lcom/datadog/opentracing/DDSpan;)Z +public abstract interface class com/datadog/opentracing/jfr/DDScopeEvent { + public abstract fun finish ()V + public abstract fun start ()V } -public abstract interface class com/datadog/trace/common/sampling/PrioritySampler { - public abstract fun setSamplingPriority (Lcom/datadog/opentracing/DDSpan;)V +public abstract interface class com/datadog/opentracing/jfr/DDScopeEventFactory { + public abstract fun create (Lcom/datadog/opentracing/DDSpanContext;)Lcom/datadog/opentracing/jfr/DDScopeEvent; } -public class com/datadog/trace/common/sampling/PrioritySampling { - public static final field SAMPLER_DROP I - public static final field SAMPLER_KEEP I - public static final field UNSET I - public static final field USER_DROP I - public static final field USER_KEEP I +public class com/datadog/opentracing/propagation/ExtractedContext : com/datadog/opentracing/propagation/TagContext { + public fun (Ljava/math/BigInteger;Ljava/math/BigInteger;ILjava/lang/String;Ljava/util/Map;Ljava/util/Map;)V + public fun baggageItems ()Ljava/lang/Iterable; + public fun getBaggage ()Ljava/util/Map; + public fun getSamplingPriority ()I + public fun getSamplingPriorityLocked ()Z + public fun getSpanId ()Ljava/math/BigInteger; + public fun getTraceId ()Ljava/math/BigInteger; + public fun lockSamplingPriority ()V } -public class com/datadog/trace/common/sampling/RateByServiceSampler : com/datadog/trace/common/sampling/PrioritySampler, com/datadog/trace/common/sampling/Sampler { - public static final field SAMPLING_AGENT_RATE Ljava/lang/String; - public fun ()V - public fun (Ljava/lang/Double;)V - public fun sample (Lcom/datadog/opentracing/DDSpan;)Z - public fun setSamplingPriority (Lcom/datadog/opentracing/DDSpan;)V +public class com/datadog/opentracing/propagation/HaystackHttpCodec { } -public abstract interface class com/datadog/trace/common/sampling/RateSampler : com/datadog/trace/common/sampling/Sampler { - public abstract fun getSampleRate ()D +public class com/datadog/opentracing/propagation/HaystackHttpCodec$Extractor : com/datadog/opentracing/propagation/HttpCodec$Extractor { + public fun (Ljava/util/Map;)V + public fun extract (Lio/opentracing/propagation/TextMapExtract;)Lio/opentracing/SpanContext; } -public abstract interface class com/datadog/trace/common/sampling/Sampler { - public abstract fun sample (Lcom/datadog/opentracing/DDSpan;)Z +public class com/datadog/opentracing/propagation/HaystackHttpCodec$Injector : com/datadog/opentracing/propagation/HttpCodec$Injector { + public fun ()V + public fun inject (Lcom/datadog/opentracing/DDSpanContext;Lio/opentracing/propagation/TextMapInject;)V } -public final class com/datadog/trace/common/sampling/Sampler$Builder { - public static fun forConfig (Lcom/datadog/trace/api/Config;)Lcom/datadog/trace/common/sampling/Sampler; - public static fun forConfig (Ljava/util/Properties;)Lcom/datadog/trace/common/sampling/Sampler; +public class com/datadog/opentracing/propagation/HttpCodec { + public fun ()V + public static fun createExtractor (Lcom/datadog/legacy/trace/api/Config;Ljava/util/Map;)Lcom/datadog/opentracing/propagation/HttpCodec$Extractor; + public static fun createInjector (Lcom/datadog/legacy/trace/api/Config;)Lcom/datadog/opentracing/propagation/HttpCodec$Injector; } -public abstract class com/datadog/trace/common/sampling/SamplingRule { - public fun (Lcom/datadog/trace/common/sampling/RateSampler;)V - public fun getSampler ()Lcom/datadog/trace/common/sampling/RateSampler; - public abstract fun matches (Lcom/datadog/opentracing/DDSpan;)Z - public fun sample (Lcom/datadog/opentracing/DDSpan;)Z +public class com/datadog/opentracing/propagation/HttpCodec$CompoundExtractor : com/datadog/opentracing/propagation/HttpCodec$Extractor { + public fun (Ljava/util/List;)V + public fun extract (Lio/opentracing/propagation/TextMapExtract;)Lio/opentracing/SpanContext; } -public class com/datadog/trace/common/sampling/SamplingRule$AlwaysMatchesSamplingRule : com/datadog/trace/common/sampling/SamplingRule { - public fun (Lcom/datadog/trace/common/sampling/RateSampler;)V - public fun matches (Lcom/datadog/opentracing/DDSpan;)Z +public class com/datadog/opentracing/propagation/HttpCodec$CompoundInjector : com/datadog/opentracing/propagation/HttpCodec$Injector { + public fun (Ljava/util/List;)V + public fun inject (Lcom/datadog/opentracing/DDSpanContext;Lio/opentracing/propagation/TextMapInject;)V } -public class com/datadog/trace/common/sampling/SamplingRule$OperationSamplingRule : com/datadog/trace/common/sampling/SamplingRule$PatternMatchSamplingRule { - public fun (Ljava/lang/String;Lcom/datadog/trace/common/sampling/RateSampler;)V - protected fun getRelevantString (Lcom/datadog/opentracing/DDSpan;)Ljava/lang/String; +public abstract interface class com/datadog/opentracing/propagation/HttpCodec$Extractor { + public abstract fun extract (Lio/opentracing/propagation/TextMapExtract;)Lio/opentracing/SpanContext; } -public abstract class com/datadog/trace/common/sampling/SamplingRule$PatternMatchSamplingRule : com/datadog/trace/common/sampling/SamplingRule { - public fun (Ljava/lang/String;Lcom/datadog/trace/common/sampling/RateSampler;)V - protected abstract fun getRelevantString (Lcom/datadog/opentracing/DDSpan;)Ljava/lang/String; - public fun matches (Lcom/datadog/opentracing/DDSpan;)Z +public abstract interface class com/datadog/opentracing/propagation/HttpCodec$Injector { + public abstract fun inject (Lcom/datadog/opentracing/DDSpanContext;Lio/opentracing/propagation/TextMapInject;)V } -public class com/datadog/trace/common/sampling/SamplingRule$ServiceSamplingRule : com/datadog/trace/common/sampling/SamplingRule$PatternMatchSamplingRule { - public fun (Ljava/lang/String;Lcom/datadog/trace/common/sampling/RateSampler;)V - protected fun getRelevantString (Lcom/datadog/opentracing/DDSpan;)Ljava/lang/String; +public class com/datadog/opentracing/propagation/TagContext : io/opentracing/SpanContext { + public fun (Ljava/lang/String;Ljava/util/Map;)V + public fun baggageItems ()Ljava/lang/Iterable; + public fun getOrigin ()Ljava/lang/String; + public fun getTags ()Ljava/util/Map; + public fun toSpanId ()Ljava/lang/String; + public fun toTraceId ()Ljava/lang/String; } -public class com/datadog/trace/common/util/Clock { - public fun ()V - public static fun currentMicroTime ()J - public static fun currentNanoTicks ()J - public static fun currentNanoTime ()J +public class com/datadog/opentracing/scopemanager/ContextualScopeManager : io/opentracing/ScopeManager { + public fun (ILcom/datadog/opentracing/jfr/DDScopeEventFactory;)V + public fun activate (Lio/opentracing/Span;)Lio/opentracing/Scope; + public fun activate (Lio/opentracing/Span;Z)Lio/opentracing/Scope; + public fun active ()Lio/opentracing/Scope; + public fun activeSpan ()Lio/opentracing/Span; + public fun addScopeContext (Lcom/datadog/opentracing/scopemanager/ScopeContext;)V + public fun addScopeListener (Lcom/datadog/legacy/trace/context/ScopeListener;)V } -public class com/datadog/trace/common/writer/LoggingWriter : com/datadog/trace/common/writer/Writer { - public fun ()V +public class com/datadog/opentracing/scopemanager/ContinuableScope : com/datadog/legacy/trace/context/TraceScope, com/datadog/opentracing/scopemanager/DDScope { + public synthetic fun capture ()Lcom/datadog/legacy/trace/context/TraceScope$Continuation; + public fun capture ()Lcom/datadog/opentracing/scopemanager/ContinuableScope$Continuation; public fun close ()V - public fun incrementTraceCount ()V - public fun start ()V + public fun depth ()I + public fun isAsyncPropagating ()Z + public fun setAsyncPropagation (Z)V + public fun span ()Lcom/datadog/opentracing/DDSpan; + public synthetic fun span ()Lio/opentracing/Span; public fun toString ()Ljava/lang/String; - public fun write (Ljava/util/List;)V } -public abstract interface class com/datadog/trace/common/writer/Writer : java/io/Closeable { - public abstract fun close ()V - public abstract fun incrementTraceCount ()V - public abstract fun start ()V - public abstract fun write (Ljava/util/List;)V -} - -public abstract interface class com/datadog/trace/context/ScopeListener { - public abstract fun afterScopeActivated ()V - public abstract fun afterScopeClosed ()V +public class com/datadog/opentracing/scopemanager/ContinuableScope$Continuation : com/datadog/legacy/trace/context/TraceScope$Continuation, java/io/Closeable { + public field ref Ljava/lang/ref/WeakReference; + public synthetic fun activate ()Lcom/datadog/legacy/trace/context/TraceScope; + public fun activate ()Lcom/datadog/opentracing/scopemanager/ContinuableScope; + public fun close ()V + public fun close (Z)V } -public abstract interface class com/datadog/trace/context/TraceScope : java/io/Closeable { - public abstract fun capture ()Lcom/datadog/trace/context/TraceScope$Continuation; - public abstract fun close ()V - public abstract fun isAsyncPropagating ()Z - public abstract fun setAsyncPropagation (Z)V +public abstract interface class com/datadog/opentracing/scopemanager/ScopeContext : io/opentracing/ScopeManager { + public abstract fun inContext ()Z } -public abstract interface class com/datadog/trace/context/TraceScope$Continuation { - public abstract fun activate ()Lcom/datadog/trace/context/TraceScope; - public abstract fun close ()V - public abstract fun close (Z)V +public class com/datadog/opentracing/scopemanager/SimpleScope : com/datadog/opentracing/scopemanager/DDScope { + public fun (Lcom/datadog/opentracing/scopemanager/ContextualScopeManager;Lio/opentracing/Span;Z)V + public fun close ()V + public fun depth ()I + public fun span ()Lio/opentracing/Span; } diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/Config.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/Config.java similarity index 99% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/Config.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/Config.java index 6789b4182c..1b7e422479 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/Config.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/Config.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.api; +package com.datadog.legacy.trace.api; import java.io.BufferedReader; import java.io.File; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/DDSpanTypes.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/DDSpanTypes.java similarity index 96% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/DDSpanTypes.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/DDSpanTypes.java index d4689fc07a..a3fbf6de36 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/DDSpanTypes.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/DDSpanTypes.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.api; +package com.datadog.legacy.trace.api; public class DDSpanTypes { public static final String HTTP_CLIENT = "http"; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/DDTags.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/DDTags.java similarity index 97% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/DDTags.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/DDTags.java index 7732f16aa7..9a53bcdc70 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/DDTags.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/DDTags.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.api; +package com.datadog.legacy.trace.api; public class DDTags { public static final String SPAN_TYPE = "span.type"; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/DDTraceApiInfo.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/DDTraceApiInfo.java similarity index 96% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/DDTraceApiInfo.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/DDTraceApiInfo.java index 8814f708fa..94332b75c7 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/DDTraceApiInfo.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/DDTraceApiInfo.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.api; +package com.datadog.legacy.trace.api; import java.io.BufferedReader; import java.io.InputStreamReader; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/Trace.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/Trace.java similarity index 95% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/Trace.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/Trace.java index bcfbcd29c9..ca4b91026a 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/Trace.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/Trace.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.api; +package com.datadog.legacy.trace.api; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/Tracer.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/Tracer.java similarity index 86% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/Tracer.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/Tracer.java index d8254b23e6..10b7f63947 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/Tracer.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/Tracer.java @@ -4,10 +4,10 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.api; +package com.datadog.legacy.trace.api; -import com.datadog.trace.api.interceptor.TraceInterceptor; -import com.datadog.trace.context.ScopeListener; +import com.datadog.legacy.trace.api.interceptor.TraceInterceptor; +import com.datadog.legacy.trace.context.ScopeListener; /** A class with Datadog tracer features. */ public interface Tracer { diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/interceptor/MutableSpan.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/interceptor/MutableSpan.java similarity index 92% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/interceptor/MutableSpan.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/interceptor/MutableSpan.java index 70c0e1fd79..5f13bd12eb 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/interceptor/MutableSpan.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/interceptor/MutableSpan.java @@ -4,9 +4,9 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.api.interceptor; +package com.datadog.legacy.trace.api.interceptor; -import com.datadog.trace.api.DDTags; +import com.datadog.legacy.trace.api.DDTags; import java.util.Map; @@ -34,7 +34,7 @@ public interface MutableSpan { /** * @deprecated Use {@link io.opentracing.Span#setTag(String, boolean)} instead using either tag - * names {@link DDTags#MANUAL_KEEP} or {@link + * names {@link com.datadog.legacy.trace.api.DDTags#MANUAL_KEEP} or {@link * DDTags#MANUAL_DROP}. * @param newPriority * @return diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/interceptor/TraceInterceptor.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/interceptor/TraceInterceptor.java similarity index 83% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/interceptor/TraceInterceptor.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/interceptor/TraceInterceptor.java index 122fdab98e..9bc29ca88e 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/interceptor/TraceInterceptor.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/interceptor/TraceInterceptor.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.api.interceptor; +package com.datadog.legacy.trace.api.interceptor; import java.util.Collection; @@ -18,7 +18,7 @@ public interface TraceInterceptor { * of spans should not be relied upon. * @return A potentially modified or replaced collection of spans. Must not be null. */ - Collection onTraceComplete(Collection trace); + Collection onTraceComplete(Collection trace); /** * @return A unique priority for sorting relative to other TraceInterceptors. Unique because diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/sampling/PrioritySampling.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/sampling/PrioritySampling.java similarity index 95% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/sampling/PrioritySampling.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/sampling/PrioritySampling.java index 22c681bf89..d4addbf5b8 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/api/sampling/PrioritySampling.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/api/sampling/PrioritySampling.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.api.sampling; +package com.datadog.legacy.trace.api.sampling; public class PrioritySampling { /** diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/AbstractSampler.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/AbstractSampler.java similarity index 96% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/AbstractSampler.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/AbstractSampler.java index cfffa4b2f1..7234793ab0 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/AbstractSampler.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/AbstractSampler.java @@ -4,9 +4,10 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.sampling; +package com.datadog.legacy.trace.common.sampling; import com.datadog.opentracing.DDSpan; + import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/AllSampler.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/AllSampler.java similarity index 91% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/AllSampler.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/AllSampler.java index 4cb35158cc..5900d158c9 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/AllSampler.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/AllSampler.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.sampling; +package com.datadog.legacy.trace.common.sampling; import com.datadog.opentracing.DDSpan; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/DeterministicSampler.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/DeterministicSampler.java similarity index 96% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/DeterministicSampler.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/DeterministicSampler.java index ab6568213d..6a034e2ca0 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/DeterministicSampler.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/DeterministicSampler.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.sampling; +package com.datadog.legacy.trace.common.sampling; import com.datadog.opentracing.DDSpan; import com.datadog.opentracing.DDTracer; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/PrioritySampler.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/PrioritySampler.java similarity index 88% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/PrioritySampler.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/PrioritySampler.java index 1e99fb0432..ff893c9d7c 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/PrioritySampler.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/PrioritySampler.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.sampling; +package com.datadog.legacy.trace.common.sampling; import com.datadog.opentracing.DDSpan; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/PrioritySampling.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/PrioritySampling.java similarity index 86% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/PrioritySampling.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/PrioritySampling.java index a2068ebbe1..5336432c5c 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/PrioritySampling.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/PrioritySampling.java @@ -4,9 +4,9 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.sampling; +package com.datadog.legacy.trace.common.sampling; -/** @deprecated Replaced by {@link com.datadog.trace.api.sampling.PrioritySampling} . */ +/** @deprecated Replaced by {@link com.datadog.legacy.trace.api.sampling.PrioritySampling} . */ @Deprecated public class PrioritySampling { /** diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/RateByServiceSampler.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/RateByServiceSampler.java similarity index 91% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/RateByServiceSampler.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/RateByServiceSampler.java index ad8a818614..578a6872a7 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/RateByServiceSampler.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/RateByServiceSampler.java @@ -4,13 +4,13 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.sampling; +package com.datadog.legacy.trace.common.sampling; import static java.util.Collections.singletonMap; -import static java.util.Collections.unmodifiableMap; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; import com.datadog.opentracing.DDSpan; -import com.datadog.trace.api.sampling.PrioritySampling; + import java.util.Map; /** @@ -59,7 +59,7 @@ public void setSamplingPriority(final DDSpan span) { final boolean priorityWasSet; if (sampler.sample(span)) { - priorityWasSet = span.context().setSamplingPriority(PrioritySampling.SAMPLER_KEEP); + priorityWasSet = span.context().setSamplingPriority(com.datadog.legacy.trace.api.sampling.PrioritySampling.SAMPLER_KEEP); } else { priorityWasSet = span.context().setSamplingPriority(PrioritySampling.SAMPLER_DROP); } diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/RateSampler.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/RateSampler.java similarity index 86% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/RateSampler.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/RateSampler.java index 44659ff5c2..bbea484c82 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/RateSampler.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/RateSampler.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.sampling; +package com.datadog.legacy.trace.common.sampling; public interface RateSampler extends Sampler { double getSampleRate(); diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/Sampler.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/Sampler.java similarity index 87% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/Sampler.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/Sampler.java index 7a0dca8a46..01a7c934e5 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/Sampler.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/Sampler.java @@ -4,10 +4,10 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.sampling; +package com.datadog.legacy.trace.common.sampling; +import com.datadog.legacy.trace.api.Config; import com.datadog.opentracing.DDSpan; -import com.datadog.trace.api.Config; import java.util.Properties; @@ -23,7 +23,7 @@ public interface Sampler { boolean sample(DDSpan span); final class Builder { - public static Sampler forConfig(final Config config) { + public static Sampler forConfig(final com.datadog.legacy.trace.api.Config config) { Sampler sampler; if (config != null) { if (config.isPrioritySamplingEnabled()) { diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/SamplingRule.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/SamplingRule.java similarity index 73% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/SamplingRule.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/SamplingRule.java index 356f18259c..5d1f24f712 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/sampling/SamplingRule.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/sampling/SamplingRule.java @@ -4,15 +4,16 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.sampling; +package com.datadog.legacy.trace.common.sampling; import com.datadog.opentracing.DDSpan; + import java.util.regex.Pattern; public abstract class SamplingRule { - private final RateSampler sampler; + private final com.datadog.legacy.trace.common.sampling.RateSampler sampler; - public SamplingRule(final RateSampler sampler) { + public SamplingRule(final com.datadog.legacy.trace.common.sampling.RateSampler sampler) { this.sampler = sampler; } @@ -22,13 +23,13 @@ public boolean sample(final DDSpan span) { return sampler.sample(span); } - public RateSampler getSampler() { + public com.datadog.legacy.trace.common.sampling.RateSampler getSampler() { return sampler; } public static class AlwaysMatchesSamplingRule extends SamplingRule { - public AlwaysMatchesSamplingRule(final RateSampler sampler) { + public AlwaysMatchesSamplingRule(final com.datadog.legacy.trace.common.sampling.RateSampler sampler) { super(sampler); } @@ -41,7 +42,7 @@ public boolean matches(final DDSpan span) { public abstract static class PatternMatchSamplingRule extends SamplingRule { private final Pattern pattern; - public PatternMatchSamplingRule(final String regex, final RateSampler sampler) { + public PatternMatchSamplingRule(final String regex, final com.datadog.legacy.trace.common.sampling.RateSampler sampler) { super(sampler); this.pattern = Pattern.compile(regex); } @@ -56,7 +57,7 @@ public boolean matches(final DDSpan span) { } public static class ServiceSamplingRule extends PatternMatchSamplingRule { - public ServiceSamplingRule(final String regex, final RateSampler sampler) { + public ServiceSamplingRule(final String regex, final com.datadog.legacy.trace.common.sampling.RateSampler sampler) { super(regex, sampler); } diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/util/Clock.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/util/Clock.java similarity index 97% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/util/Clock.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/util/Clock.java index c1bae860cb..6780148d31 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/util/Clock.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/util/Clock.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.util; +package com.datadog.legacy.trace.common.util; import java.util.concurrent.TimeUnit; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/writer/LoggingWriter.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/writer/LoggingWriter.java similarity index 93% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/writer/LoggingWriter.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/writer/LoggingWriter.java index 93cc49cd15..e73120372e 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/writer/LoggingWriter.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/writer/LoggingWriter.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.writer; +package com.datadog.legacy.trace.common.writer; import com.datadog.opentracing.DDSpan; import java.util.List; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/writer/Writer.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/writer/Writer.java similarity index 95% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/writer/Writer.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/writer/Writer.java index 2d458a9780..5063de1baa 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/common/writer/Writer.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/common/writer/Writer.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.common.writer; +package com.datadog.legacy.trace.common.writer; import com.datadog.opentracing.DDSpan; import java.io.Closeable; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/context/ScopeListener.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/context/ScopeListener.java similarity index 93% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/context/ScopeListener.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/context/ScopeListener.java index 40c95c609c..b62b061d34 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/context/ScopeListener.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/context/ScopeListener.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.context; +package com.datadog.legacy.trace.context; /** Hooks for scope activation */ public interface ScopeListener { diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/context/TraceScope.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/context/TraceScope.java similarity index 97% rename from features/dd-sdk-android-trace/src/main/java/com/datadog/trace/context/TraceScope.java rename to features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/context/TraceScope.java index 1a254a7e1c..e4aea21daf 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/trace/context/TraceScope.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/legacy/trace/context/TraceScope.java @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.trace.context; +package com.datadog.legacy.trace.context; import java.io.Closeable; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDSpan.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDSpan.java index eebf346238..a32805892c 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDSpan.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDSpan.java @@ -6,10 +6,10 @@ package com.datadog.opentracing; -import com.datadog.trace.api.DDTags; -import com.datadog.trace.api.interceptor.MutableSpan; -import com.datadog.trace.api.sampling.PrioritySampling; -import com.datadog.trace.common.util.Clock; +import com.datadog.legacy.trace.api.DDTags; +import com.datadog.legacy.trace.api.interceptor.MutableSpan; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; +import com.datadog.legacy.trace.common.util.Clock; import io.opentracing.Span; import io.opentracing.tag.Tag; import java.io.PrintWriter; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDSpanContext.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDSpanContext.java index e63ae382c7..b7c6876e25 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDSpanContext.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDSpanContext.java @@ -7,8 +7,8 @@ package com.datadog.opentracing; import com.datadog.opentracing.decorators.AbstractDecorator; -import com.datadog.trace.api.DDTags; -import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.legacy.trace.api.DDTags; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; import java.math.BigInteger; import java.util.Collections; import java.util.List; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDTracer.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDTracer.java index 30d5b75438..5498ed4c18 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDTracer.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DDTracer.java @@ -17,16 +17,16 @@ import com.datadog.opentracing.propagation.TagContext; import com.datadog.opentracing.scopemanager.ContextualScopeManager; import com.datadog.opentracing.scopemanager.ScopeContext; -import com.datadog.trace.api.Config; -import com.datadog.trace.api.Tracer; -import com.datadog.trace.api.interceptor.MutableSpan; -import com.datadog.trace.api.interceptor.TraceInterceptor; -import com.datadog.trace.api.sampling.PrioritySampling; -import com.datadog.trace.common.sampling.PrioritySampler; -import com.datadog.trace.common.sampling.Sampler; -import com.datadog.trace.common.writer.LoggingWriter; -import com.datadog.trace.common.writer.Writer; -import com.datadog.trace.context.ScopeListener; +import com.datadog.legacy.trace.api.Config; +import com.datadog.legacy.trace.api.Tracer; +import com.datadog.legacy.trace.api.interceptor.MutableSpan; +import com.datadog.legacy.trace.api.interceptor.TraceInterceptor; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; +import com.datadog.legacy.trace.common.sampling.PrioritySampler; +import com.datadog.legacy.trace.common.sampling.Sampler; +import com.datadog.legacy.trace.common.writer.LoggingWriter; +import com.datadog.legacy.trace.common.writer.Writer; +import com.datadog.legacy.trace.context.ScopeListener; import io.opentracing.References; import io.opentracing.Scope; import io.opentracing.ScopeManager; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DefaultLogHandler.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DefaultLogHandler.java index 0222ecd329..0ba850f158 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DefaultLogHandler.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/DefaultLogHandler.java @@ -9,7 +9,7 @@ import static io.opentracing.log.Fields.ERROR_OBJECT; import static io.opentracing.log.Fields.MESSAGE; -import com.datadog.trace.api.DDTags; +import com.datadog.legacy.trace.api.DDTags; import java.util.Map; /** The default implementation of the LogHandler. */ diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/PendingTrace.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/PendingTrace.java index b7667a0087..2cdaae09b5 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/PendingTrace.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/PendingTrace.java @@ -9,7 +9,7 @@ import com.datadog.exec.CommonTaskExecutor; import com.datadog.exec.CommonTaskExecutor.Task; import com.datadog.opentracing.scopemanager.ContinuableScope; -import com.datadog.trace.common.util.Clock; +import com.datadog.legacy.trace.common.util.Clock; import java.io.Closeable; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/DBTypeDecorator.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/DBTypeDecorator.java index f9bfef6fda..5b4126f47d 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/DBTypeDecorator.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/DBTypeDecorator.java @@ -7,8 +7,8 @@ package com.datadog.opentracing.decorators; import com.datadog.opentracing.DDSpanContext; -import com.datadog.trace.api.DDSpanTypes; -import com.datadog.trace.api.DDTags; +import com.datadog.legacy.trace.api.DDSpanTypes; +import com.datadog.legacy.trace.api.DDTags; import io.opentracing.tag.Tags; /** diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/DDDecoratorsFactory.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/DDDecoratorsFactory.java index ffe7507436..90805c106e 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/DDDecoratorsFactory.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/DDDecoratorsFactory.java @@ -6,7 +6,7 @@ package com.datadog.opentracing.decorators; -import com.datadog.trace.api.Config; +import com.datadog.legacy.trace.api.Config; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ForceManualDropDecorator.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ForceManualDropDecorator.java index 21fa2ab6a4..cd46c766de 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ForceManualDropDecorator.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ForceManualDropDecorator.java @@ -7,8 +7,8 @@ package com.datadog.opentracing.decorators; import com.datadog.opentracing.DDSpanContext; -import com.datadog.trace.api.DDTags; -import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.legacy.trace.api.DDTags; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; /** * Tag decorator to replace tag 'manual.drop: true' with the appropriate priority sampling value. diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ForceManualKeepDecorator.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ForceManualKeepDecorator.java index 150d1c3967..a701d9dcea 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ForceManualKeepDecorator.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ForceManualKeepDecorator.java @@ -7,8 +7,8 @@ package com.datadog.opentracing.decorators; import com.datadog.opentracing.DDSpanContext; -import com.datadog.trace.api.DDTags; -import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.legacy.trace.api.DDTags; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; /** * Tag decorator to replace tag 'manual.keep: true' with the appropriate priority sampling value. diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ServiceNameDecorator.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ServiceNameDecorator.java index faad513899..b067281bec 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ServiceNameDecorator.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ServiceNameDecorator.java @@ -7,7 +7,7 @@ package com.datadog.opentracing.decorators; import com.datadog.opentracing.DDSpanContext; -import com.datadog.trace.api.DDTags; +import com.datadog.legacy.trace.api.DDTags; public class ServiceNameDecorator extends AbstractDecorator { diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ServletContextDecorator.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ServletContextDecorator.java index ec6b3ebb61..053c83688e 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ServletContextDecorator.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/decorators/ServletContextDecorator.java @@ -7,7 +7,7 @@ package com.datadog.opentracing.decorators; import com.datadog.opentracing.DDSpanContext; -import com.datadog.trace.api.Config; +import com.datadog.legacy.trace.api.Config; public class ServletContextDecorator extends AbstractDecorator { diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/B3HttpCodec.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/B3HttpCodec.java index 34a7b3aea6..838fcd672a 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/B3HttpCodec.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/B3HttpCodec.java @@ -9,7 +9,7 @@ import static com.datadog.opentracing.propagation.HttpCodec.validateUInt64BitsID; import com.datadog.opentracing.DDSpanContext; -import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; import java.math.BigInteger; import java.util.Collections; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/B3MHttpCodec.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/B3MHttpCodec.java index 0ae9a4c751..45e2d01cc8 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/B3MHttpCodec.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/B3MHttpCodec.java @@ -9,7 +9,7 @@ import static com.datadog.opentracing.propagation.HttpCodec.validateUInt64BitsID; import com.datadog.opentracing.DDSpanContext; -import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; import io.opentracing.SpanContext; import io.opentracing.propagation.TextMapExtract; import io.opentracing.propagation.TextMapInject; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/DatadogHttpCodec.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/DatadogHttpCodec.java index 48350e99d8..1ae298d060 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/DatadogHttpCodec.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/DatadogHttpCodec.java @@ -9,7 +9,7 @@ import static com.datadog.opentracing.propagation.HttpCodec.validateUInt64BitsID; import com.datadog.opentracing.DDSpanContext; -import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; import io.opentracing.SpanContext; import io.opentracing.propagation.TextMapExtract; import io.opentracing.propagation.TextMapInject; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/HaystackHttpCodec.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/HaystackHttpCodec.java index 709eafa17b..d0b23f2af3 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/HaystackHttpCodec.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/HaystackHttpCodec.java @@ -9,7 +9,7 @@ import static com.datadog.opentracing.propagation.HttpCodec.validateUInt64BitsID; import com.datadog.opentracing.DDSpanContext; -import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; import io.opentracing.SpanContext; import io.opentracing.propagation.TextMapExtract; import io.opentracing.propagation.TextMapInject; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/HttpCodec.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/HttpCodec.java index f90c752291..2bfd6fe845 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/HttpCodec.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/HttpCodec.java @@ -9,7 +9,7 @@ import com.datadog.opentracing.DDSpanContext; import com.datadog.opentracing.DDTracer; import com.datadog.opentracing.StringCachingBigInteger; -import com.datadog.trace.api.Config; +import com.datadog.legacy.trace.api.Config; import io.opentracing.SpanContext; import io.opentracing.propagation.TextMapExtract; import io.opentracing.propagation.TextMapInject; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/W3CHttpCodec.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/W3CHttpCodec.java index 3ff895c3f5..086cced7c8 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/W3CHttpCodec.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/propagation/W3CHttpCodec.java @@ -9,7 +9,7 @@ import static com.datadog.opentracing.propagation.HttpCodec.validateUInt64BitsID; import com.datadog.opentracing.DDSpanContext; -import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.legacy.trace.api.sampling.PrioritySampling; import java.math.BigInteger; import java.util.Collections; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/ContextualScopeManager.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/ContextualScopeManager.java index b4e4da76f1..c49a3da8db 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/ContextualScopeManager.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/ContextualScopeManager.java @@ -8,7 +8,7 @@ import com.datadog.opentracing.DDSpan; import com.datadog.opentracing.jfr.DDScopeEventFactory; -import com.datadog.trace.context.ScopeListener; +import com.datadog.legacy.trace.context.ScopeListener; import io.opentracing.Scope; import io.opentracing.ScopeManager; import io.opentracing.Span; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/ContinuableScope.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/ContinuableScope.java index e95418f8c0..bc27c742c5 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/ContinuableScope.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/ContinuableScope.java @@ -11,8 +11,8 @@ import com.datadog.opentracing.PendingTrace; import com.datadog.opentracing.jfr.DDScopeEvent; import com.datadog.opentracing.jfr.DDScopeEventFactory; -import com.datadog.trace.context.ScopeListener; -import com.datadog.trace.context.TraceScope; +import com.datadog.legacy.trace.context.ScopeListener; +import com.datadog.legacy.trace.context.TraceScope; import java.io.Closeable; import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/SimpleScope.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/SimpleScope.java index 66043749a6..26c60b8d26 100644 --- a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/SimpleScope.java +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/scopemanager/SimpleScope.java @@ -6,7 +6,7 @@ package com.datadog.opentracing.scopemanager; -import com.datadog.trace.context.ScopeListener; +import com.datadog.legacy.trace.context.ScopeListener; import io.opentracing.Span; /** Simple scope implementation which does not propagate across threads. */ diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/AndroidTracer.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/AndroidTracer.kt index 270d8f3c26..2150319d9c 100644 --- a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/AndroidTracer.kt +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/AndroidTracer.kt @@ -16,11 +16,11 @@ import com.datadog.android.log.LogAttributes import com.datadog.android.trace.internal.TracingFeature import com.datadog.android.trace.internal.data.NoOpWriter import com.datadog.android.trace.internal.handlers.AndroidSpanLogsHandler +import com.datadog.legacy.trace.api.Config +import com.datadog.legacy.trace.common.writer.Writer +import com.datadog.legacy.trace.context.ScopeListener import com.datadog.opentracing.DDTracer import com.datadog.opentracing.LogHandler -import com.datadog.trace.api.Config -import com.datadog.trace.common.writer.Writer -import com.datadog.trace.context.ScopeListener import io.opentracing.Span import io.opentracing.log.Fields import java.security.SecureRandom diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/TracingFeature.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/TracingFeature.kt index 2bdab204ff..ddcb93c521 100644 --- a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/TracingFeature.kt +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/TracingFeature.kt @@ -19,7 +19,7 @@ import com.datadog.android.trace.internal.domain.event.DdSpanToSpanEventMapper import com.datadog.android.trace.internal.domain.event.SpanEventMapperWrapper import com.datadog.android.trace.internal.domain.event.SpanEventSerializer import com.datadog.android.trace.internal.net.TracesRequestFactory -import com.datadog.trace.common.writer.Writer +import com.datadog.legacy.trace.common.writer.Writer import java.util.concurrent.atomic.AtomicBoolean /** diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/NoOpWriter.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/NoOpWriter.kt index 26451e92ca..7e144f8d7e 100644 --- a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/NoOpWriter.kt +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/NoOpWriter.kt @@ -6,8 +6,8 @@ package com.datadog.android.trace.internal.data +import com.datadog.legacy.trace.common.writer.Writer import com.datadog.opentracing.DDSpan -import com.datadog.trace.common.writer.Writer internal class NoOpWriter : Writer { override fun close() { diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/TraceWriter.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/TraceWriter.kt index e52d50220a..5801d8ed38 100644 --- a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/TraceWriter.kt +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/TraceWriter.kt @@ -17,8 +17,8 @@ import com.datadog.android.event.EventMapper import com.datadog.android.trace.internal.domain.event.ContextAwareMapper import com.datadog.android.trace.internal.storage.ContextAwareSerializer import com.datadog.android.trace.model.SpanEvent +import com.datadog.legacy.trace.common.writer.Writer import com.datadog.opentracing.DDSpan -import com.datadog.trace.common.writer.Writer import java.util.Locale internal class TraceWriter( diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/handlers/AndroidSpanLogsHandler.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/handlers/AndroidSpanLogsHandler.kt index fa53575752..c4810c6522 100644 --- a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/handlers/AndroidSpanLogsHandler.kt +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/handlers/AndroidSpanLogsHandler.kt @@ -11,9 +11,9 @@ import com.datadog.android.api.feature.Feature import com.datadog.android.api.feature.FeatureSdkCore import com.datadog.android.core.internal.utils.loggableStackTrace import com.datadog.android.log.LogAttributes +import com.datadog.legacy.trace.api.DDTags import com.datadog.opentracing.DDSpan import com.datadog.opentracing.LogHandler -import com.datadog.trace.api.DDTags import io.opentracing.log.Fields import java.util.concurrent.TimeUnit diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/AndroidTracerTest.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/AndroidTracerTest.kt index 3ab69b296e..2e41d28c00 100644 --- a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/AndroidTracerTest.kt +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/AndroidTracerTest.kt @@ -14,11 +14,11 @@ import com.datadog.android.log.LogAttributes import com.datadog.android.trace.internal.TracingFeature import com.datadog.android.trace.utils.verifyLog import com.datadog.android.utils.forge.Configurator +import com.datadog.legacy.trace.api.Config +import com.datadog.legacy.trace.common.writer.Writer import com.datadog.opentracing.DDSpan import com.datadog.opentracing.LogHandler import com.datadog.opentracing.scopemanager.ScopeTestHelper -import com.datadog.trace.api.Config -import com.datadog.trace.common.writer.Writer import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.annotation.DoubleForgery import fr.xgouchet.elmyr.annotation.Forgery diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/assertj/TracerConfigAssert.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/assertj/TracerConfigAssert.kt index 0f25ca845d..a202510a00 100644 --- a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/assertj/TracerConfigAssert.kt +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/assertj/TracerConfigAssert.kt @@ -6,7 +6,7 @@ package com.datadog.android.trace.assertj -import com.datadog.trace.api.Config +import com.datadog.legacy.trace.api.Config import org.assertj.core.api.AbstractObjectAssert import org.assertj.core.api.Assertions.assertThat diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/handlers/AndroidSpanLogsHandlerTest.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/handlers/AndroidSpanLogsHandlerTest.kt index a108f4668f..0e9a5e1b94 100644 --- a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/handlers/AndroidSpanLogsHandlerTest.kt +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/handlers/AndroidSpanLogsHandlerTest.kt @@ -14,8 +14,8 @@ import com.datadog.android.core.internal.utils.loggableStackTrace import com.datadog.android.log.LogAttributes import com.datadog.android.trace.utils.verifyLog import com.datadog.android.utils.forge.Configurator +import com.datadog.legacy.trace.api.DDTags import com.datadog.opentracing.DDSpan -import com.datadog.trace.api.DDTags import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.annotation.Forgery import fr.xgouchet.elmyr.annotation.LongForgery diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/SpanForgeryFactory.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/SpanForgeryFactory.kt index 34f3c65122..91f7f0ea74 100644 --- a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/SpanForgeryFactory.kt +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/SpanForgeryFactory.kt @@ -6,10 +6,10 @@ package com.datadog.android.utils.forge +import com.datadog.legacy.trace.api.Config import com.datadog.opentracing.DDSpan import com.datadog.opentracing.DDTracer import com.datadog.opentracing.DDTracer.DDSpanBuilder -import com.datadog.trace.api.Config import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.ForgeryFactory import org.mockito.kotlin.mock diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/opentracing/DDSpanContextTest.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/opentracing/DDSpanContextTest.kt index 68061a55ff..0f5e997b2d 100644 --- a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/opentracing/DDSpanContextTest.kt +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/opentracing/DDSpanContextTest.kt @@ -7,10 +7,10 @@ package com.datadog.opentracing import com.datadog.android.utils.forge.Configurator +import com.datadog.legacy.trace.api.DDTags +import com.datadog.legacy.trace.api.sampling.PrioritySampling import com.datadog.opentracing.assertj.DDSpanContextAssert.Companion.assertThat import com.datadog.opentracing.decorators.AbstractDecorator -import com.datadog.trace.api.DDTags -import com.datadog.trace.api.sampling.PrioritySampling import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.annotation.BoolForgery import fr.xgouchet.elmyr.annotation.Forgery diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/opentracing/PendingTraceTest.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/opentracing/PendingTraceTest.kt index acd76bc22e..5c32877a71 100644 --- a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/opentracing/PendingTraceTest.kt +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/opentracing/PendingTraceTest.kt @@ -7,7 +7,7 @@ package com.datadog.opentracing import com.datadog.android.utils.forge.Configurator -import com.datadog.trace.api.sampling.PrioritySampling +import com.datadog.legacy.trace.api.sampling.PrioritySampling import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.junit5.ForgeConfiguration import fr.xgouchet.elmyr.junit5.ForgeExtension diff --git a/features/dd-sdk-android-trace/transitiveDependencies b/features/dd-sdk-android-trace/transitiveDependencies index cd26cca254..9e6270370a 100644 --- a/features/dd-sdk-android-trace/transitiveDependencies +++ b/features/dd-sdk-android-trace/transitiveDependencies @@ -1,28 +1,13 @@ Dependencies List androidx.annotation:annotation:1.3.0 : 30 Kb -com.github.spotbugs:spotbugs-annotations:4.2.0 : 14 Kb -com.github.spotbugs:spotbugs:4.2.0 : 3 Mb -com.google.code.findbugs:jsr305:3.0.2 : 19 Kb com.google.code.gson:gson:2.10.1 : 276 Kb io.opentracing:opentracing-api:0.32.0 : 18 Kb io.opentracing:opentracing-noop:0.32.0 : 10 Kb io.opentracing:opentracing-util:0.32.0 : 10 Kb -net.jcip:jcip-annotations:1.0 : 2 Kb -org.apache.bcel:bcel:6.5.0 : 678 Kb -org.apache.commons:commons-lang3:3.11 : 564 Kb -org.apache.commons:commons-text:1.9 : 211 Kb -org.dom4j:dom4j:2.1.3 : 316 Kb org.jetbrains.kotlin:kotlin-stdlib-common:1.8.10 : 212 Kb org.jetbrains.kotlin:kotlin-stdlib:1.8.10 : 1598 Kb org.jetbrains:annotations:13.0 : 17 Kb -org.json:json:20200518 : 64 Kb -org.ow2.asm:asm-analysis:9.0 : 32 Kb -org.ow2.asm:asm-commons:9.0 : 69 Kb -org.ow2.asm:asm-tree:9.0 : 51 Kb -org.ow2.asm:asm-util:9.0 : 82 Kb -org.ow2.asm:asm:9.0 : 118 Kb -org.slf4j:slf4j-api:1.7.30 : 40 Kb -Total transitive dependencies size : 7 Mb +Total transitive dependencies size : 2 Mb diff --git a/integrations/dd-sdk-android-okhttp/src/main/kotlin/com/datadog/android/okhttp/trace/TracingInterceptor.kt b/integrations/dd-sdk-android-okhttp/src/main/kotlin/com/datadog/android/okhttp/trace/TracingInterceptor.kt index d5bf71114f..41aa791a70 100644 --- a/integrations/dd-sdk-android-okhttp/src/main/kotlin/com/datadog/android/okhttp/trace/TracingInterceptor.kt +++ b/integrations/dd-sdk-android-okhttp/src/main/kotlin/com/datadog/android/okhttp/trace/TracingInterceptor.kt @@ -20,10 +20,10 @@ import com.datadog.android.core.sampling.RateBasedSampler import com.datadog.android.core.sampling.Sampler import com.datadog.android.trace.AndroidTracer import com.datadog.android.trace.TracingHeaderType +import com.datadog.legacy.trace.api.DDTags +import com.datadog.legacy.trace.api.interceptor.MutableSpan +import com.datadog.legacy.trace.api.sampling.PrioritySampling import com.datadog.opentracing.DDTracer -import com.datadog.trace.api.DDTags -import com.datadog.trace.api.interceptor.MutableSpan -import com.datadog.trace.api.sampling.PrioritySampling import io.opentracing.Span import io.opentracing.SpanContext import io.opentracing.Tracer diff --git a/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/DatadogInterceptorWithoutTracesTest.kt b/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/DatadogInterceptorWithoutTracesTest.kt index 163784ac1f..3f27c2bd0f 100644 --- a/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/DatadogInterceptorWithoutTracesTest.kt +++ b/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/DatadogInterceptorWithoutTracesTest.kt @@ -21,6 +21,7 @@ import com.datadog.android.rum.RumErrorSource import com.datadog.android.rum.RumResourceAttributesProvider import com.datadog.android.rum.RumResourceKind import com.datadog.android.rum.RumResourceMethod +import com.datadog.legacy.trace.api.interceptor.MutableSpan import com.datadog.opentracing.DDSpan import com.datadog.opentracing.DDSpanContext import com.datadog.opentracing.DDTracer @@ -29,7 +30,6 @@ import com.datadog.tools.unit.extensions.TestConfigurationExtension import com.datadog.tools.unit.extensions.config.TestConfiguration import com.datadog.tools.unit.forge.BaseConfigurator import com.datadog.tools.unit.forge.exhaustiveAttributes -import com.datadog.trace.api.interceptor.MutableSpan import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.annotation.Forgery import fr.xgouchet.elmyr.annotation.IntForgery diff --git a/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNonDdTracerNotSendingSpanTest.kt b/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNonDdTracerNotSendingSpanTest.kt index 43e7cf7700..76fc1958c0 100644 --- a/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNonDdTracerNotSendingSpanTest.kt +++ b/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNonDdTracerNotSendingSpanTest.kt @@ -16,14 +16,14 @@ import com.datadog.android.okhttp.utils.assertj.HeadersAssert.Companion.assertTh import com.datadog.android.okhttp.utils.config.DatadogSingletonTestConfiguration import com.datadog.android.okhttp.utils.verifyLog import com.datadog.android.trace.TracingHeaderType +import com.datadog.legacy.trace.api.interceptor.MutableSpan +import com.datadog.legacy.trace.api.sampling.PrioritySampling import com.datadog.opentracing.DDTracer import com.datadog.tools.unit.annotations.TestConfigurationsProvider import com.datadog.tools.unit.extensions.TestConfigurationExtension import com.datadog.tools.unit.extensions.config.TestConfiguration import com.datadog.tools.unit.forge.BaseConfigurator import com.datadog.tools.unit.setStaticValue -import com.datadog.trace.api.interceptor.MutableSpan -import com.datadog.trace.api.sampling.PrioritySampling import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.annotation.Forgery import fr.xgouchet.elmyr.annotation.IntForgery diff --git a/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNonDdTracerTest.kt b/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNonDdTracerTest.kt index ee8556e0dd..9f24b8d22a 100644 --- a/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNonDdTracerTest.kt +++ b/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNonDdTracerTest.kt @@ -17,14 +17,14 @@ import com.datadog.android.okhttp.utils.assertj.HeadersAssert.Companion.assertTh import com.datadog.android.okhttp.utils.config.DatadogSingletonTestConfiguration import com.datadog.android.okhttp.utils.verifyLog import com.datadog.android.trace.TracingHeaderType +import com.datadog.legacy.trace.api.interceptor.MutableSpan +import com.datadog.legacy.trace.api.sampling.PrioritySampling import com.datadog.opentracing.DDTracer import com.datadog.tools.unit.annotations.TestConfigurationsProvider import com.datadog.tools.unit.extensions.TestConfigurationExtension import com.datadog.tools.unit.extensions.config.TestConfiguration import com.datadog.tools.unit.forge.BaseConfigurator import com.datadog.tools.unit.setStaticValue -import com.datadog.trace.api.interceptor.MutableSpan -import com.datadog.trace.api.sampling.PrioritySampling import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.annotation.Forgery import fr.xgouchet.elmyr.annotation.IntForgery diff --git a/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNotSendingSpanTest.kt b/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNotSendingSpanTest.kt index 2036df3f89..baa4ad6c11 100644 --- a/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNotSendingSpanTest.kt +++ b/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorNotSendingSpanTest.kt @@ -18,6 +18,8 @@ import com.datadog.android.okhttp.utils.config.GlobalRumMonitorTestConfiguration import com.datadog.android.okhttp.utils.verifyLog import com.datadog.android.rum.RumResourceMethod import com.datadog.android.trace.TracingHeaderType +import com.datadog.legacy.trace.api.interceptor.MutableSpan +import com.datadog.legacy.trace.api.sampling.PrioritySampling import com.datadog.opentracing.DDSpanContext import com.datadog.opentracing.DDTracer import com.datadog.tools.unit.annotations.TestConfigurationsProvider @@ -25,8 +27,6 @@ import com.datadog.tools.unit.extensions.TestConfigurationExtension import com.datadog.tools.unit.extensions.config.TestConfiguration import com.datadog.tools.unit.forge.BaseConfigurator import com.datadog.tools.unit.setStaticValue -import com.datadog.trace.api.interceptor.MutableSpan -import com.datadog.trace.api.sampling.PrioritySampling import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.annotation.Forgery import fr.xgouchet.elmyr.annotation.IntForgery diff --git a/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorTest.kt b/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorTest.kt index 0a87cf1232..2273f405dd 100644 --- a/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorTest.kt +++ b/integrations/dd-sdk-android-okhttp/src/test/kotlin/com/datadog/android/okhttp/trace/TracingInterceptorTest.kt @@ -18,6 +18,8 @@ import com.datadog.android.okhttp.utils.config.DatadogSingletonTestConfiguration import com.datadog.android.okhttp.utils.config.GlobalRumMonitorTestConfiguration import com.datadog.android.okhttp.utils.verifyLog import com.datadog.android.trace.TracingHeaderType +import com.datadog.legacy.trace.api.interceptor.MutableSpan +import com.datadog.legacy.trace.api.sampling.PrioritySampling import com.datadog.opentracing.DDSpanContext import com.datadog.opentracing.DDTracer import com.datadog.tools.unit.annotations.TestConfigurationsProvider @@ -25,8 +27,6 @@ import com.datadog.tools.unit.extensions.TestConfigurationExtension import com.datadog.tools.unit.extensions.config.TestConfiguration import com.datadog.tools.unit.forge.BaseConfigurator import com.datadog.tools.unit.setStaticValue -import com.datadog.trace.api.interceptor.MutableSpan -import com.datadog.trace.api.sampling.PrioritySampling import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.annotation.Forgery import fr.xgouchet.elmyr.annotation.IntForgery From 4b35b3cec2db018dca0a42762e9848b2e6677f28 Mon Sep 17 00:00:00 2001 From: Marius Constantin Date: Fri, 1 Mar 2024 16:46:55 +0100 Subject: [PATCH 05/55] RUM-3247 Port the Otel Java implementation and provide OtelTracerProvider Builder --- LICENSE-3rdparty.csv | 1 + build.gradle.kts | 2 +- detekt_custom.yml | 5 + features/dd-sdk-android-trace/api/apiSurface | 15 + .../api/dd-sdk-android-trace.api | 109 +++++ .../dd-sdk-android-trace/build.gradle.kts | 1 + .../context/propagation/TraceStateHelper.java | 63 +++ .../opentelemetry/trace/OtelConventions.java | 222 ++++++++++ .../trace/OtelExtractedContext.java | 89 ++++ .../datadog/opentelemetry/trace/OtelSpan.java | 230 ++++++++++ .../opentelemetry/trace/OtelSpanBuilder.java | 188 ++++++++ .../opentelemetry/trace/OtelSpanContext.java | 94 ++++ .../opentelemetry/trace/OtelSpanLink.java | 72 +++ .../opentelemetry/trace/OtelTracer.java | 40 ++ .../trace/OtelTracerBuilder.java | 53 +++ .../android/trace/OtelTracerProvider.kt | 241 ++++++++++ .../trace/internal/data/NoOpOtelWriter.kt | 27 ++ .../trace/OtelTracerBuilderProviderTest.kt | 415 ++++++++++++++++++ .../java/com/datadog/trace/api/Config.java | 4 +- 19 files changed, 1869 insertions(+), 2 deletions(-) create mode 100644 features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/context/propagation/TraceStateHelper.java create mode 100644 features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelConventions.java create mode 100644 features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelExtractedContext.java create mode 100644 features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpan.java create mode 100644 features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanBuilder.java create mode 100644 features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanContext.java create mode 100644 features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanLink.java create mode 100644 features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelTracer.java create mode 100644 features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelTracerBuilder.java create mode 100644 features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/OtelTracerProvider.kt create mode 100644 features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/NoOpOtelWriter.kt create mode 100644 features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/OtelTracerBuilderProviderTest.kt diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index bc77e471f2..b5c32de93e 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -57,6 +57,7 @@ import,com.squareup.sqldelight,Apache-2.0,"Copyright 2016 Square, Inc" import,com.fasterxml.jackson,Apache-2.0,"Copyright 2020 Datadog, Inc." import,com.datadoghq,Apache-2.0,"Copyright 2017 Datadog, Inc" import,io.coil-kt,Apache-2.0,Copyright 2021 Coil Contributors +import,io.opentelemetry,Apache-2.0,Copyright 2019 The OpenTelemetry Authors import,io.opentracing,Apache-2.0,Copyright 2016-2017 The OpenTracing Authors import,io.opentracing.contrib,Apache-2.0,Copyright 2016-2017 The OpenTracing Authors import,io.reactivex.rxjava3,Apache-2.0,"Copyright (c) 2016-present, RxJava Contributors" diff --git a/build.gradle.kts b/build.gradle.kts index 798a66f332..6d88117a1d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -131,7 +131,7 @@ tasks.register("buildNdkIntegrationTestsArtifacts") { dependsOn(":instrumented:integration:assembleDebug") } -nightlyTestsCoverageConfig(threshold = 0.85f) +nightlyTestsCoverageConfig(threshold = 0.81f) tasks.register("printSdkDebugRuntimeClasspath") { val fileTreeClassPathCollector = UnionFileTree( diff --git a/detekt_custom.yml b/detekt_custom.yml index 91f34ac942..7b22716fbb 100644 --- a/detekt_custom.yml +++ b/detekt_custom.yml @@ -1059,6 +1059,7 @@ datadog: - "kotlin.math.max(kotlin.Long, kotlin.Long)" - "kotlin.math.min(kotlin.Double, kotlin.Double)" - "kotlin.math.sqrt(kotlin.Double)" + - "kotlin.String.trim(kotlin.Function1)" # endregion # region Kotlin Tuples - "kotlin.Pair.constructor(com.datadog.android.sessionreplay.internal.utils.SessionReplayRumContext, com.google.gson.JsonArray)" @@ -1241,6 +1242,10 @@ datadog: - "io.opentracing.util.GlobalTracer.get()" - "io.opentracing.util.GlobalTracer.isRegistered()" # endregion + # region Opentelemetry + - "io.opentelemetry.api.trace.TracerBuilder.build()" + - "io.opentelemetry.api.trace.TracerBuilder.setInstrumentationVersion(kotlin.String?)" + # endregion # region RxJava - "io.reactivex.rxjava3.core.Completable.doOnError(io.reactivex.rxjava3.functions.Consumer?)" - "io.reactivex.rxjava3.core.Flowable.doOnError(io.reactivex.rxjava3.functions.Consumer?)" diff --git a/features/dd-sdk-android-trace/api/apiSurface b/features/dd-sdk-android-trace/api/apiSurface index b190f744b8..57a580faeb 100644 --- a/features/dd-sdk-android-trace/api/apiSurface +++ b/features/dd-sdk-android-trace/api/apiSurface @@ -14,6 +14,21 @@ class com.datadog.android.trace.AndroidTracer : com.datadog.opentracing.DDTracer companion object fun logThrowable(io.opentracing.Span, Throwable) fun logErrorMessage(io.opentracing.Span, String) +class com.datadog.android.trace.OtelTracerProvider : io.opentelemetry.api.trace.TracerProvider + constructor(com.datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI, com.datadog.android.api.InternalLogger) + override fun get(String): io.opentelemetry.api.trace.Tracer + override fun get(String, String): io.opentelemetry.api.trace.Tracer + override fun tracerBuilder(String): io.opentelemetry.api.trace.TracerBuilder + class Builder + constructor(com.datadog.android.api.SdkCore = Datadog.getInstance()) + fun build(): OtelTracerProvider + fun setTracingHeaderTypes(Set): Builder + fun setService(String): Builder + fun setPartialFlushThreshold(Int): Builder + fun addTag(String, String): Builder + fun setSampleRate(Double): Builder + override fun toString(): String + companion object fun io.opentracing.Span.setError(Throwable) fun io.opentracing.Span.setError(String) fun withinSpan(String, io.opentracing.Span? = null, Boolean = true, io.opentracing.Span.() -> T): T diff --git a/features/dd-sdk-android-trace/api/dd-sdk-android-trace.api b/features/dd-sdk-android-trace/api/dd-sdk-android-trace.api index e186e94864..8d719adac9 100644 --- a/features/dd-sdk-android-trace/api/dd-sdk-android-trace.api +++ b/features/dd-sdk-android-trace/api/dd-sdk-android-trace.api @@ -26,6 +26,30 @@ public final class com/datadog/android/trace/AndroidTracer$Companion { public final fun logThrowable (Lio/opentracing/Span;Ljava/lang/Throwable;)V } +public final class com/datadog/android/trace/OtelTracerProvider : io/opentelemetry/api/trace/TracerProvider { + public static final field Companion Lcom/datadog/android/trace/OtelTracerProvider$Companion; + public fun (Lcom/datadog/trace/bootstrap/instrumentation/api/AgentTracer$TracerAPI;Lcom/datadog/android/api/InternalLogger;)V + public fun get (Ljava/lang/String;)Lio/opentelemetry/api/trace/Tracer; + public fun get (Ljava/lang/String;Ljava/lang/String;)Lio/opentelemetry/api/trace/Tracer; + public fun toString ()Ljava/lang/String; + public fun tracerBuilder (Ljava/lang/String;)Lio/opentelemetry/api/trace/TracerBuilder; +} + +public final class com/datadog/android/trace/OtelTracerProvider$Builder { + public fun ()V + public fun (Lcom/datadog/android/api/SdkCore;)V + public synthetic fun (Lcom/datadog/android/api/SdkCore;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun addTag (Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/android/trace/OtelTracerProvider$Builder; + public final fun build ()Lcom/datadog/android/trace/OtelTracerProvider; + public final fun setPartialFlushThreshold (I)Lcom/datadog/android/trace/OtelTracerProvider$Builder; + public final fun setSampleRate (D)Lcom/datadog/android/trace/OtelTracerProvider$Builder; + public final fun setService (Ljava/lang/String;)Lcom/datadog/android/trace/OtelTracerProvider$Builder; + public final fun setTracingHeaderTypes (Ljava/util/Set;)Lcom/datadog/android/trace/OtelTracerProvider$Builder; +} + +public final class com/datadog/android/trace/OtelTracerProvider$Companion { +} + public final class com/datadog/android/trace/SpanExtKt { public static final fun setError (Lio/opentracing/Span;Ljava/lang/String;)V public static final fun setError (Lio/opentracing/Span;Ljava/lang/Throwable;)V @@ -829,6 +853,91 @@ public abstract interface class com/datadog/legacy/trace/context/TraceScope$Cont public abstract fun close (Z)V } +public final class com/datadog/opentelemetry/context/propagation/TraceStateHelper { + public static fun decodeHeader (Ljava/lang/String;)Lio/opentelemetry/api/trace/TraceState; + public static fun encodeHeader (Lio/opentelemetry/api/trace/TraceState;)Ljava/lang/String; +} + +public final class com/datadog/opentelemetry/trace/OtelConventions { + public static fun applyNamingConvention (Lcom/datadog/trace/bootstrap/instrumentation/api/AgentSpan;)V + public static fun applyReservedAttribute (Lcom/datadog/trace/bootstrap/instrumentation/api/AgentSpan;Lio/opentelemetry/api/common/AttributeKey;Ljava/lang/Object;)Z + public static fun toOtelSpanKind (Ljava/lang/String;)Lio/opentelemetry/api/trace/SpanKind; + public static fun toSpanKindTagValue (Lio/opentelemetry/api/trace/SpanKind;)Ljava/lang/String; +} + +public class com/datadog/opentelemetry/trace/OtelExtractedContext : com/datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context { + public fun baggageItems ()Ljava/lang/Iterable; + public static fun extract (Lio/opentelemetry/context/Context;Lcom/datadog/android/api/InternalLogger;)Lcom/datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; + public fun getPathwayContext ()Lcom/datadog/trace/bootstrap/instrumentation/api/PathwayContext; + public fun getSamplingPriority ()I + public fun getSpanId ()J + public fun getTrace ()Lcom/datadog/trace/bootstrap/instrumentation/api/AgentTrace; + public fun getTraceId ()Lcom/datadog/trace/api/DDTraceId; +} + +public class com/datadog/opentelemetry/trace/OtelSpan : io/opentelemetry/api/trace/Span { + public fun (Lcom/datadog/trace/bootstrap/instrumentation/api/AgentSpan;)V + public fun activate ()Lcom/datadog/trace/bootstrap/instrumentation/api/AgentScope; + public fun addEvent (Ljava/lang/String;Lio/opentelemetry/api/common/Attributes;)Lio/opentelemetry/api/trace/Span; + public fun addEvent (Ljava/lang/String;Lio/opentelemetry/api/common/Attributes;JLjava/util/concurrent/TimeUnit;)Lio/opentelemetry/api/trace/Span; + public fun end ()V + public fun end (JLjava/util/concurrent/TimeUnit;)V + public fun getAgentSpanContext ()Lcom/datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; + public fun getSpanContext ()Lio/opentelemetry/api/trace/SpanContext; + public static fun invalid ()Lio/opentelemetry/api/trace/Span; + public fun isRecording ()Z + public fun recordException (Ljava/lang/Throwable;Lio/opentelemetry/api/common/Attributes;)Lio/opentelemetry/api/trace/Span; + public fun setAttribute (Lio/opentelemetry/api/common/AttributeKey;Ljava/lang/Object;)Lio/opentelemetry/api/trace/Span; + public fun setStatus (Lio/opentelemetry/api/trace/StatusCode;Ljava/lang/String;)Lio/opentelemetry/api/trace/Span; + public fun updateName (Ljava/lang/String;)Lio/opentelemetry/api/trace/Span; +} + +public class com/datadog/opentelemetry/trace/OtelSpanBuilder : io/opentelemetry/api/trace/SpanBuilder { + public fun (Lcom/datadog/trace/bootstrap/instrumentation/api/AgentTracer$SpanBuilder;Lcom/datadog/android/api/InternalLogger;)V + public fun addLink (Lio/opentelemetry/api/trace/SpanContext;)Lio/opentelemetry/api/trace/SpanBuilder; + public fun addLink (Lio/opentelemetry/api/trace/SpanContext;Lio/opentelemetry/api/common/Attributes;)Lio/opentelemetry/api/trace/SpanBuilder; + public fun setAttribute (Lio/opentelemetry/api/common/AttributeKey;Ljava/lang/Object;)Lio/opentelemetry/api/trace/SpanBuilder; + public fun setAttribute (Ljava/lang/String;D)Lio/opentelemetry/api/trace/SpanBuilder; + public fun setAttribute (Ljava/lang/String;J)Lio/opentelemetry/api/trace/SpanBuilder; + public fun setAttribute (Ljava/lang/String;Ljava/lang/String;)Lio/opentelemetry/api/trace/SpanBuilder; + public fun setAttribute (Ljava/lang/String;Z)Lio/opentelemetry/api/trace/SpanBuilder; + public fun setNoParent ()Lio/opentelemetry/api/trace/SpanBuilder; + public fun setParent (Lio/opentelemetry/context/Context;)Lio/opentelemetry/api/trace/SpanBuilder; + public fun setSpanKind (Lio/opentelemetry/api/trace/SpanKind;)Lio/opentelemetry/api/trace/SpanBuilder; + public fun setStartTimestamp (JLjava/util/concurrent/TimeUnit;)Lio/opentelemetry/api/trace/SpanBuilder; + public fun startSpan ()Lio/opentelemetry/api/trace/Span; +} + +public class com/datadog/opentelemetry/trace/OtelSpanContext : io/opentelemetry/api/trace/SpanContext { + public fun (Lcom/datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;ZZLio/opentelemetry/api/trace/TraceState;)V + public static fun fromLocalSpan (Lcom/datadog/trace/bootstrap/instrumentation/api/AgentSpan;)Lio/opentelemetry/api/trace/SpanContext; + public static fun fromRemote (Lcom/datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context;Lio/opentelemetry/api/trace/TraceState;)Lio/opentelemetry/api/trace/SpanContext; + public fun getDelegate ()Lcom/datadog/trace/bootstrap/instrumentation/api/AgentSpan$Context; + public fun getSpanId ()Ljava/lang/String; + public fun getTraceFlags ()Lio/opentelemetry/api/trace/TraceFlags; + public fun getTraceId ()Ljava/lang/String; + public fun getTraceState ()Lio/opentelemetry/api/trace/TraceState; + public fun isRemote ()Z + public fun toString ()Ljava/lang/String; +} + +public class com/datadog/opentelemetry/trace/OtelSpanLink : com/datadog/trace/bootstrap/instrumentation/api/SpanLink { + public fun (Lio/opentelemetry/api/trace/SpanContext;)V + public fun (Lio/opentelemetry/api/trace/SpanContext;Lio/opentelemetry/api/common/Attributes;)V +} + +public class com/datadog/opentelemetry/trace/OtelTracer : io/opentelemetry/api/trace/Tracer { + public fun (Ljava/lang/String;Lcom/datadog/trace/bootstrap/instrumentation/api/AgentTracer$TracerAPI;Lcom/datadog/android/api/InternalLogger;)V + public fun spanBuilder (Ljava/lang/String;)Lio/opentelemetry/api/trace/SpanBuilder; +} + +public class com/datadog/opentelemetry/trace/OtelTracerBuilder : io/opentelemetry/api/trace/TracerBuilder { + public fun (Ljava/lang/String;Lcom/datadog/trace/bootstrap/instrumentation/api/AgentTracer$TracerAPI;Lcom/datadog/android/api/InternalLogger;)V + public fun build ()Lio/opentelemetry/api/trace/Tracer; + public fun setInstrumentationVersion (Ljava/lang/String;)Lio/opentelemetry/api/trace/TracerBuilder; + public fun setSchemaUrl (Ljava/lang/String;)Lio/opentelemetry/api/trace/TracerBuilder; +} + public class com/datadog/opentracing/DDSpan : com/datadog/legacy/trace/api/interceptor/MutableSpan, io/opentracing/Span { public final fun context ()Lcom/datadog/opentracing/DDSpanContext; public synthetic fun context ()Lio/opentracing/SpanContext; diff --git a/features/dd-sdk-android-trace/build.gradle.kts b/features/dd-sdk-android-trace/build.gradle.kts index e85de819d3..a48dcfe05d 100644 --- a/features/dd-sdk-android-trace/build.gradle.kts +++ b/features/dd-sdk-android-trace/build.gradle.kts @@ -55,6 +55,7 @@ dependencies { implementation(libs.kotlin) implementation(libs.gson) implementation(libs.androidXAnnotation) + implementation(libs.openTelemetry) // Generate NoOp implementations ksp(project(":tools:noopfactory")) diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/context/propagation/TraceStateHelper.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/context/propagation/TraceStateHelper.java new file mode 100644 index 0000000000..0973a844a1 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/context/propagation/TraceStateHelper.java @@ -0,0 +1,63 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.opentelemetry.context.propagation; + +import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.api.trace.TraceStateBuilder; +import java.util.regex.Pattern; + +/** This class helps to decode W3C tracestate header into a {@link TraceState} instance. */ +public final class TraceStateHelper { + private static final int TRACESTATE_MAX_SIZE = 512; + private static final char TRACESTATE_ENTRY_DELIMITER = ','; + private static final char TRACESTATE_KEY_VALUE_DELIMITER = '='; + private static final Pattern TRACESTATE_ENTRY_DELIMITER_SPLIT_PATTERN = + Pattern.compile("[ \t]*,[ \t]*"); + + private TraceStateHelper() {} + + // Inspired from W3CTraceContextEncoding.decodeTraceState only available in API later versions. + public static TraceState decodeHeader(String header) { + TraceStateBuilder traceStateBuilder = TraceState.builder(); + String[] listMembers = TRACESTATE_ENTRY_DELIMITER_SPLIT_PATTERN.split(header); + if (listMembers.length > 32) { + return TraceState.getDefault(); + } + + for (int i = listMembers.length - 1; i >= 0; --i) { + String listMember = listMembers[i]; + int index = listMember.indexOf(61); + if (index == -1) { + return TraceState.getDefault(); + } + traceStateBuilder.put(listMember.substring(0, index), listMember.substring(index + 1)); + } + + TraceState traceState = traceStateBuilder.build(); + if (traceState.size() != listMembers.length) { + return TraceState.getDefault(); + } else { + return traceState; + } + } + + // Inspired from W3CTraceContextEncoding.encodeTraceState only available in API later versions. + public static String encodeHeader(TraceState traceState) { + if (traceState.isEmpty()) { + return ""; + } + StringBuilder builder = new StringBuilder(TRACESTATE_MAX_SIZE); + traceState.forEach( + (key, value) -> { + if (builder.length() != 0) { + builder.append(TRACESTATE_ENTRY_DELIMITER); + } + builder.append(key).append(TRACESTATE_KEY_VALUE_DELIMITER).append(value); + }); + return builder.toString(); + } +} diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelConventions.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelConventions.java new file mode 100644 index 0000000000..3718641f84 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelConventions.java @@ -0,0 +1,222 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.opentelemetry.trace; + +import static com.datadog.trace.api.DDTags.ANALYTICS_SAMPLE_RATE; +import static com.datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND; +import static com.datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_CLIENT; +import static com.datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_CONSUMER; +import static com.datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_PRODUCER; +import static com.datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_SERVER; +import static io.opentelemetry.api.trace.SpanKind.CLIENT; +import static io.opentelemetry.api.trace.SpanKind.CONSUMER; +import static io.opentelemetry.api.trace.SpanKind.INTERNAL; +import static io.opentelemetry.api.trace.SpanKind.PRODUCER; +import static io.opentelemetry.api.trace.SpanKind.SERVER; +import static java.lang.Boolean.parseBoolean; +import static java.util.Locale.ROOT; + +import androidx.annotation.Nullable; + +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.Tags; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.trace.SpanKind; + +public final class OtelConventions { + static final String SPAN_KIND_INTERNAL = "internal"; + static final String OPERATION_NAME_SPECIFIC_ATTRIBUTE = "operation.name"; + static final String ANALYTICS_EVENT_SPECIFIC_ATTRIBUTES = "analytics.event"; + private OtelConventions() {} + + /** + * Convert OpenTelemetry {@link SpanKind} to {@link Tags#SPAN_KIND} value. + * + * @param spanKind The OpenTelemetry span kind to convert. + * @return The {@link Tags#SPAN_KIND} value. + */ + public static String toSpanKindTagValue(SpanKind spanKind) { + switch (spanKind) { + case CLIENT: + return SPAN_KIND_CLIENT; + case SERVER: + return SPAN_KIND_SERVER; + case PRODUCER: + return SPAN_KIND_PRODUCER; + case CONSUMER: + return SPAN_KIND_CONSUMER; + case INTERNAL: + return SPAN_KIND_INTERNAL; + default: + return spanKind.toString().toLowerCase(ROOT); + } + } + + /** + * Convert {@link Tags#SPAN_KIND} value to OpenTelemetry {@link SpanKind}. + * + * @param spanKind The {@link Tags#SPAN_KIND} value to convert. + * @return The related OpenTelemetry {@link SpanKind}. + */ + public static SpanKind toOtelSpanKind(String spanKind) { + if (spanKind == null) { + return INTERNAL; + } + switch (spanKind) { + case SPAN_KIND_CLIENT: + return CLIENT; + case SPAN_KIND_SERVER: + return SERVER; + case SPAN_KIND_PRODUCER: + return PRODUCER; + case SPAN_KIND_CONSUMER: + return CONSUMER; + default: + return INTERNAL; + } + } + + /** + * Applies the reserved span attributes. Only OpenTelemetry specific span attributes are handled + * here, the default ones are handled by tag interceptor while setting span attributes. + * + * @param span The span to apply the attributes. + * @param key The attribute key. + * @param value The attribute value. + * @param The attribute type. + * @return {@code true} if the attributes is a reserved attribute applied to the span, {@code + * false} otherwise. + */ + public static boolean applyReservedAttribute(AgentSpan span, AttributeKey key, T value) { + String name = key.getKey(); + switch (key.getType()) { + case STRING: + if (OPERATION_NAME_SPECIFIC_ATTRIBUTE.equals(name) && value instanceof String) { + span.setOperationName(((String) value).toLowerCase(ROOT)); + return true; + } else if (ANALYTICS_EVENT_SPECIFIC_ATTRIBUTES.equals(name) && value instanceof String) { + span.setMetric(ANALYTICS_SAMPLE_RATE, parseBoolean((String) value) ? 1 : 0); + return true; + } + case BOOLEAN: + if (ANALYTICS_EVENT_SPECIFIC_ATTRIBUTES.equals(name) && value instanceof Boolean) { + span.setMetric(ANALYTICS_SAMPLE_RATE, ((Boolean) value) ? 1 : 0); + return true; + } + } + return false; + } + + public static void applyNamingConvention(AgentSpan span) { + // Check if span operation name is unchanged from its default value + if (span.getOperationName() == SPAN_KIND_INTERNAL) { + span.setOperationName(computeOperationName(span).toLowerCase(ROOT)); + } + } + + private static String computeOperationName(AgentSpan span) { + Object spanKingTag = span.getTag(SPAN_KIND); + SpanKind spanKind = + spanKingTag instanceof String ? toOtelSpanKind((String) spanKingTag) : INTERNAL; + /* + * HTTP convention: https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/http/ + */ + String httpRequestMethod = getStringAttribute(span, "http.request.method"); + if (spanKind == SERVER && httpRequestMethod != null) { + return "http.server.request"; + } + if (spanKind == CLIENT && httpRequestMethod != null) { + return "http.client.request"; + } + /* + * Database convention: https://opentelemetry.io/docs/specs/semconv/database/database-spans/ + */ + String dbSystem = getStringAttribute(span, "db.system"); + if (spanKind == CLIENT && dbSystem != null) { + return dbSystem + ".query"; + } + /* + * Messaging: https://opentelemetry.io/docs/specs/semconv/messaging/messaging-spans/ + */ + String messagingSystem = getStringAttribute(span, "messaging.system"); + String messagingOperation = getStringAttribute(span, "messaging.operation"); + if ((spanKind == CONSUMER || spanKind == PRODUCER || spanKind == CLIENT || spanKind == SERVER) + && messagingSystem != null + && messagingOperation != null) { + return messagingSystem + "." + messagingOperation; + } + /* + * AWS: https://opentelemetry.io/docs/specs/semconv/cloud-providers/aws-sdk/ + */ + String rpcSystem = getStringAttribute(span, "rpc.system"); + if (spanKind == CLIENT && "aws-api".equals(rpcSystem)) { + String service = getStringAttribute(span, "rpc.service"); + if (service == null) { + return "aws.client.request"; + } else { + return "aws." + service + ".request"; + } + } + /* + * RPC: https://opentelemetry.io/docs/specs/semconv/rpc/rpc-spans/ + */ + if (spanKind == CLIENT && rpcSystem != null) { + return rpcSystem + ".client.request"; + } + if (spanKind == SERVER && rpcSystem != null) { + return rpcSystem + ".server.request"; + } + /* + * FaaS: + * https://opentelemetry.io/docs/specs/semconv/faas/faas-spans/#incoming-faas-span-attributes + * https://opentelemetry.io/docs/specs/semconv/faas/faas-spans/#outgoing-invocations + */ + String faasInvokedProvider = getStringAttribute(span, "faas.invoked_provider"); + String faasInvokedName = getStringAttribute(span, "faas.invoked_name"); + if (spanKind == CLIENT && faasInvokedProvider != null && faasInvokedName != null) { + return faasInvokedProvider + "." + faasInvokedName + ".invoke"; + } + String faasTrigger = getStringAttribute(span, "faas.trigger"); + if (spanKind == SERVER && faasTrigger != null) { + return faasTrigger + ".invoke"; + } + /* + * GraphQL: https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/instrumentation/graphql/ + */ + String graphqlOperationType = getStringAttribute(span, "graphql.operation.type"); + if (graphqlOperationType != null) { + return "graphql.server.request"; + } + /* + * Generic server / client: https://opentelemetry.io/docs/specs/semconv/http/http-spans/ + */ + String networkProtocolName = getStringAttribute(span, "network.protocol.name"); + if (spanKind == SERVER) { + return networkProtocolName == null + ? "server.request" + : networkProtocolName + ".server.request"; + } + if (spanKind == CLIENT) { + return networkProtocolName == null + ? "client.request" + : networkProtocolName + ".client.request"; + } + // Fallback if no convention match + return spanKind.name(); + } + + @Nullable + private static String getStringAttribute(AgentSpan span, String key) { + Object tag = span.getTag(key); + if (tag == null) { + return null; + } else if (!(tag instanceof String)) { + return key; + } + return (String) tag; + } +} diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelExtractedContext.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelExtractedContext.java new file mode 100644 index 0000000000..b68535f329 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelExtractedContext.java @@ -0,0 +1,89 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.opentelemetry.trace; + +import com.datadog.android.api.InternalLogger; +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.api.sampling.PrioritySampling; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTrace; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import com.datadog.trace.bootstrap.instrumentation.api.PathwayContext; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.context.Context; + +import java.util.Locale; +import java.util.Map; + +public class OtelExtractedContext implements AgentSpan.Context { + private final DDTraceId traceId; + private final long spanId; + private final int prioritySampling; + + private OtelExtractedContext(SpanContext context) { + this.traceId = DDTraceId.fromHex(context.getTraceId()); + this.spanId = DDSpanId.fromHex(context.getSpanId()); + this.prioritySampling = + context.isSampled() ? PrioritySampling.SAMPLER_KEEP : PrioritySampling.UNSET; + } + + public static AgentSpan.Context extract(Context context, InternalLogger logger) { + Span span = Span.fromContext(context); + SpanContext spanContext = span.getSpanContext(); + if (spanContext instanceof OtelSpanContext) { + return ((OtelSpanContext) spanContext).delegate; + } else if (spanContext.isValid()) { + try { + return new OtelExtractedContext(spanContext); + } catch (NumberFormatException e) { + logger.log( + InternalLogger.Level.DEBUG, + InternalLogger.Target.MAINTAINER, + () -> String.format(Locale.US, "Failed to convert span context with trace id = " + + "{%1s} and span id = {%2s}", spanContext.getSpanId(), spanContext.getTraceId()), + null, + false, + null); + + } + } + return null; + } + + @Override + public DDTraceId getTraceId() { + return this.traceId; + } + + @Override + public long getSpanId() { + return this.spanId; + } + + @Override + public AgentTrace getTrace() { + return AgentTracer.NoopAgentTrace.INSTANCE; + } + + @Override + public int getSamplingPriority() { + return this.prioritySampling; + } + + @Override + public Iterable> baggageItems() { + return null; + } + + @Override + public PathwayContext getPathwayContext() { + return null; + } +} diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpan.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpan.java new file mode 100644 index 0000000000..e94f7033f4 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpan.java @@ -0,0 +1,230 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.opentelemetry.trace; + +import static com.datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; +import static com.datadog.opentelemetry.trace.OtelConventions.applyNamingConvention; +import static com.datadog.opentelemetry.trace.OtelConventions.applyReservedAttribute; +import static io.opentelemetry.api.trace.StatusCode.ERROR; +import static io.opentelemetry.api.trace.StatusCode.OK; +import static io.opentelemetry.api.trace.StatusCode.UNSET; + +import com.datadog.trace.bootstrap.instrumentation.api.AgentScope; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AttachableWrapper; +import com.datadog.trace.bootstrap.instrumentation.api.ErrorPriorities; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class OtelSpan implements Span { + private final AgentSpan delegate; + private StatusCode statusCode; + private boolean recording; + + public OtelSpan(AgentSpan delegate) { + this.delegate = delegate; + if (delegate instanceof AttachableWrapper) { + ((AttachableWrapper) delegate).attachWrapper(this); + } + this.statusCode = UNSET; + this.recording = true; + } + + public static Span invalid() { + return NoopSpan.INSTANCE; + } + + @Override + public Span setAttribute(AttributeKey key, T value) { + if (this.recording && !applyReservedAttribute(this.delegate, key, value)) { + switch (key.getType()) { + case STRING_ARRAY: + case BOOLEAN_ARRAY: + case LONG_ARRAY: + case DOUBLE_ARRAY: + if (value instanceof List) { + List valueList = (List) value; + if (valueList.isEmpty()) { + // Store as object to prevent delegate to remove tag when value is empty + this.delegate.setTag(key.getKey(), (Object) ""); + } else { + for (int index = 0; index < valueList.size(); index++) { + this.delegate.setTag(key.getKey() + "." + index, valueList.get(index)); + } + } + } + break; + default: + this.delegate.setTag(key.getKey(), value); + break; + } + } + return this; + } + + @Override + public Span addEvent(String name, Attributes attributes) { + // Not supported + return this; + } + + @Override + public Span addEvent(String name, Attributes attributes, long timestamp, TimeUnit unit) { + // Not supported + return this; + } + + @Override + public Span setStatus(StatusCode statusCode, String description) { + if (this.recording) { + if (this.statusCode == UNSET) { + this.statusCode = statusCode; + this.delegate.setError(statusCode == ERROR); + this.delegate.setErrorMessage(statusCode == ERROR ? description : null); + } else if (this.statusCode == ERROR && statusCode == OK) { + this.delegate.setError(false); + this.delegate.setErrorMessage(null); + } + } + return this; + } + + @Override + public Span recordException(Throwable exception, Attributes additionalAttributes) { + if (this.recording) { + // Store exception as span tags as span events are not supported yet + this.delegate.addThrowable(exception, ErrorPriorities.UNSET); + } + return this; + } + + @Override + public Span updateName(String name) { + if (this.recording) { + this.delegate.setResourceName(name); + } + return this; + } + + @Override + public void end() { + this.recording = false; + applyNamingConvention(this.delegate); + this.delegate.finish(); + } + + @Override + public void end(long timestamp, TimeUnit unit) { + this.recording = false; + applyNamingConvention(this.delegate); + this.delegate.finish(unit.toMicros(timestamp)); + } + + @Override + public SpanContext getSpanContext() { + return OtelSpanContext.fromLocalSpan(this.delegate); + } + + @Override + public boolean isRecording() { + return this.recording; + } + + public AgentScope activate() { + return activateSpan(this.delegate); + } + + public AgentSpan.Context getAgentSpanContext() { + return this.delegate.context(); + } + + private static class NoopSpan implements Span { + private static final Span INSTANCE = new NoopSpan(); + + @Override + public Span setAttribute(AttributeKey key, T value) { + return this; + } + + @Override + public Span addEvent(String name, Attributes attributes) { + return this; + } + + @Override + public Span addEvent(String name, Attributes attributes, long timestamp, TimeUnit unit) { + return this; + } + + @Override + public Span setStatus(StatusCode statusCode, String description) { + return this; + } + + @Override + public Span recordException(Throwable exception, Attributes additionalAttributes) { + return this; + } + + @Override + public Span updateName(String name) { + return this; + } + + @Override + public void end() {} + + @Override + public void end(long timestamp, TimeUnit unit) {} + + @Override + public SpanContext getSpanContext() { + return NoopSpanContext.INSTANCE; + } + + @Override + public boolean isRecording() { + return false; + } + } + + private static class NoopSpanContext implements SpanContext { + private static final SpanContext INSTANCE = new NoopSpanContext(); + + @Override + public String getTraceId() { + return "00000000000000000000000000000000"; + } + + @Override + public String getSpanId() { + return "0000000000000000"; + } + + @Override + public TraceFlags getTraceFlags() { + return TraceFlags.getDefault(); + } + + @Override + public TraceState getTraceState() { + return TraceState.getDefault(); + } + + @Override + public boolean isRemote() { + return false; + } + } +} diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanBuilder.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanBuilder.java new file mode 100644 index 0000000000..0fc776ef11 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanBuilder.java @@ -0,0 +1,188 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.opentelemetry.trace; + +import static com.datadog.trace.api.DDTags.ANALYTICS_SAMPLE_RATE; +import static com.datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND; +import static com.datadog.opentelemetry.trace.OtelConventions.ANALYTICS_EVENT_SPECIFIC_ATTRIBUTES; +import static com.datadog.opentelemetry.trace.OtelConventions.OPERATION_NAME_SPECIFIC_ATTRIBUTE; +import static com.datadog.opentelemetry.trace.OtelConventions.toSpanKindTagValue; +import static com.datadog.opentelemetry.trace.OtelExtractedContext.extract; +import static io.opentelemetry.api.trace.SpanKind.INTERNAL; +import static java.lang.Boolean.parseBoolean; +import static java.util.Locale.ROOT; + +import androidx.annotation.NonNull; + +import com.datadog.android.api.InternalLogger; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.context.Context; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +public class OtelSpanBuilder implements SpanBuilder { + private final AgentTracer.SpanBuilder delegate; + private boolean spanKindSet; + /** + * Operation name overridden value by {@link OtelConventions#OPERATION_NAME_SPECIFIC_ATTRIBUTE} + * reserved attribute ({@code null} if not set). + */ + private String overriddenOperationName; + /** + * Analytics sample rate metric value from {@link + * OtelConventions#ANALYTICS_EVENT_SPECIFIC_ATTRIBUTES} reserved attribute ({@code -1} if not + * set). + */ + private int overriddenAnalyticsSampleRate; + + @NonNull + private final InternalLogger logger; + + public OtelSpanBuilder(AgentTracer.SpanBuilder delegate, @NonNull InternalLogger logger) { + this.delegate = delegate; + this.spanKindSet = false; + this.overriddenOperationName = null; + this.overriddenAnalyticsSampleRate = -1; + this.logger = logger; + } + + @Override + public SpanBuilder setParent(Context context) { + AgentSpan.Context extractedContext = extract(context, logger); + if (extractedContext != null) { + this.delegate.asChildOf(extractedContext); + } + return this; + } + + @Override + public SpanBuilder setNoParent() { + this.delegate.asChildOf(null); + this.delegate.ignoreActiveSpan(); + return this; + } + + @Override + public SpanBuilder addLink(SpanContext spanContext) { + if (spanContext.isValid()) { + this.delegate.withLink(new OtelSpanLink(spanContext)); + } + return this; + } + + @Override + public SpanBuilder addLink(SpanContext spanContext, Attributes attributes) { + if (spanContext.isValid()) { + this.delegate.withLink(new OtelSpanLink(spanContext, attributes)); + } + return this; + } + + @Override + public SpanBuilder setAttribute(String key, String value) { + // Check reserved attributes + if (OPERATION_NAME_SPECIFIC_ATTRIBUTE.equals(key) && value != null) { + this.overriddenOperationName = value.toLowerCase(ROOT); + return this; + } else if (ANALYTICS_EVENT_SPECIFIC_ATTRIBUTES.equals(key) && value != null) { + this.overriddenAnalyticsSampleRate = parseBoolean(value) ? 1 : 0; + return this; + } + // Store as object to prevent delegate to remove tag when value is empty + this.delegate.withTag(key, (Object) value); + return this; + } + + @Override + public SpanBuilder setAttribute(String key, long value) { + this.delegate.withTag(key, value); + return this; + } + + @Override + public SpanBuilder setAttribute(String key, double value) { + this.delegate.withTag(key, value); + return this; + } + + @Override + public SpanBuilder setAttribute(String key, boolean value) { + // Check reserved attributes + if (ANALYTICS_EVENT_SPECIFIC_ATTRIBUTES.equals(key)) { + this.overriddenAnalyticsSampleRate = value ? 1 : 0; + return this; + } + this.delegate.withTag(key, value); + return this; + } + + @Override + public SpanBuilder setAttribute(AttributeKey key, T value) { + switch (key.getType()) { + case STRING_ARRAY: + case BOOLEAN_ARRAY: + case LONG_ARRAY: + case DOUBLE_ARRAY: + if (value instanceof List) { + List valueList = (List) value; + if (valueList.isEmpty()) { + // Store as object to prevent delegate to remove tag when value is empty + this.delegate.withTag(key.getKey(), (Object) ""); + } else { + for (int index = 0; index < valueList.size(); index++) { + this.delegate.withTag(key.getKey() + "." + index, valueList.get(index)); + } + } + } + break; + default: + this.delegate.withTag(key.getKey(), value); + break; + } + return this; + } + + @Override + public SpanBuilder setSpanKind(SpanKind spanKind) { + if (spanKind != null) { + this.delegate.withTag(SPAN_KIND, toSpanKindTagValue(spanKind)); + this.spanKindSet = true; + } + return this; + } + + @Override + public SpanBuilder setStartTimestamp(long startTimestamp, TimeUnit unit) { + this.delegate.withStartTimestamp(unit.toMicros(startTimestamp)); + return this; + } + + @Override + public Span startSpan() { + // Ensure the span kind is set + if (!this.spanKindSet) { + setSpanKind(INTERNAL); + } + AgentSpan delegate = this.delegate.start(); + // Apply overrides + if (this.overriddenOperationName != null) { + delegate.setOperationName(this.overriddenOperationName); + } + if (this.overriddenAnalyticsSampleRate != -1) { + delegate.setMetric(ANALYTICS_SAMPLE_RATE, this.overriddenAnalyticsSampleRate); + } + return new OtelSpan(delegate); + } +} diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanContext.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanContext.java new file mode 100644 index 0000000000..8ed0e0a7ad --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanContext.java @@ -0,0 +1,94 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.opentelemetry.trace; + +import androidx.annotation.VisibleForTesting; + +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; + +public class OtelSpanContext implements SpanContext { + final AgentSpan.Context delegate; + private final boolean sampled; + private final boolean remote; + private final TraceState traceState; + private String traceId; + private String spanId; + + public OtelSpanContext( + AgentSpan.Context delegate, boolean sampled, boolean remote, TraceState traceState) { + this.delegate = delegate; + this.sampled = sampled; + this.remote = remote; + this.traceState = traceState; + } + + public static SpanContext fromLocalSpan(AgentSpan span) { + AgentSpan.Context delegate = span.context(); + AgentSpan localRootSpan = span.getLocalRootSpan(); + Integer samplingPriority = localRootSpan.getSamplingPriority(); + boolean sampled = samplingPriority != null && samplingPriority > 0; + return new OtelSpanContext(delegate, sampled, false, TraceState.getDefault()); + } + + public static SpanContext fromRemote(AgentSpan.Context extracted, TraceState traceState) { + return new OtelSpanContext(extracted, extracted.getSamplingPriority() > 0, true, traceState); + } + + @Override + public String getTraceId() { + if (this.traceId == null) { + this.traceId = this.delegate.getTraceId().toHexString(); + } + return this.traceId; + } + + @Override + public String getSpanId() { + if (this.spanId == null) { + this.spanId = DDSpanId.toHexStringPadded(this.delegate.getSpanId()); + } + return this.spanId; + } + + @VisibleForTesting + public AgentSpan.Context getDelegate() { + return delegate; + } + + @Override + public TraceFlags getTraceFlags() { + return this.sampled ? TraceFlags.getSampled() : TraceFlags.getDefault(); + } + + @Override + public TraceState getTraceState() { + return this.traceState; + } + + @Override + public boolean isRemote() { + return this.remote; + } + + @Override + public String toString() { + return "OtelSpanContext{" + + "traceId='" + + getTraceId() + + "', spanId='" + + getSpanId() + + "', sampled=" + + this.sampled + + ", remote=" + + this.remote + + '}'; + } +} diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanLink.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanLink.java new file mode 100644 index 0000000000..d09a3b61aa --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelSpanLink.java @@ -0,0 +1,72 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.opentelemetry.trace; + +import com.datadog.trace.api.DDSpanId; +import com.datadog.trace.api.DDTraceId; +import com.datadog.trace.bootstrap.instrumentation.api.SpanLink; +import com.datadog.trace.bootstrap.instrumentation.api.SpanLinkAttributes; +import com.datadog.opentelemetry.context.propagation.TraceStateHelper; +import io.opentelemetry.api.trace.SpanContext; +import java.util.List; + +public class OtelSpanLink extends SpanLink { + public OtelSpanLink(SpanContext spanContext) { + this(spanContext, io.opentelemetry.api.common.Attributes.empty()); + } + + public OtelSpanLink(SpanContext spanContext, io.opentelemetry.api.common.Attributes attributes) { + super( + DDTraceId.fromHex(spanContext.getTraceId()), + DDSpanId.fromHex(spanContext.getSpanId()), + spanContext.isSampled() ? SAMPLED_FLAG : DEFAULT_FLAGS, + TraceStateHelper.encodeHeader(spanContext.getTraceState()), + convertAttributes(attributes)); + } + + private static Attributes convertAttributes(io.opentelemetry.api.common.Attributes attributes) { + if (attributes.isEmpty()) { + return SpanLinkAttributes.EMPTY; + } + SpanLinkAttributes.Builder builder = SpanLinkAttributes.builder(); + attributes.forEach( + (attributeKey, value) -> { + String key = attributeKey.getKey(); + switch (attributeKey.getType()) { + case STRING: + builder.put(key, (String) value); + break; + case BOOLEAN: + builder.put(key, (boolean) value); + break; + case LONG: + builder.put(key, (long) value); + break; + case DOUBLE: + builder.put(key, (double) value); + break; + case STRING_ARRAY: + //noinspection unchecked + builder.putStringArray(key, (List) value); + break; + case BOOLEAN_ARRAY: + //noinspection unchecked + builder.putBooleanArray(key, (List) value); + break; + case LONG_ARRAY: + //noinspection unchecked + builder.putLongArray(key, (List) value); + break; + case DOUBLE_ARRAY: + //noinspection unchecked + builder.putDoubleArray(key, (List) value); + break; + } + }); + return builder.build(); + } +} diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelTracer.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelTracer.java new file mode 100644 index 0000000000..8c1e686674 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelTracer.java @@ -0,0 +1,40 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.opentelemetry.trace; + +import androidx.annotation.NonNull; + +import com.datadog.android.api.InternalLogger; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer; + +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.Tracer; + +public class OtelTracer implements Tracer { + @NonNull + private final AgentTracer.TracerAPI tracer; + @NonNull + private final String instrumentationScopeName; + @NonNull + private final InternalLogger logger; + + public OtelTracer( + @NonNull String instrumentationScopeName, + @NonNull AgentTracer.TracerAPI tracer, + @NonNull InternalLogger logger) { + this.instrumentationScopeName = instrumentationScopeName; + this.tracer = tracer; + this.logger = logger; + } + + @Override + public SpanBuilder spanBuilder(String spanName) { + AgentTracer.SpanBuilder delegate = + this.tracer.buildSpan(instrumentationScopeName, OtelConventions.SPAN_KIND_INTERNAL).withResourceName(spanName); + return new OtelSpanBuilder(delegate, logger); + } +} diff --git a/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelTracerBuilder.java b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelTracerBuilder.java new file mode 100644 index 0000000000..a1c3768fe5 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/java/com/datadog/opentelemetry/trace/OtelTracerBuilder.java @@ -0,0 +1,53 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.opentelemetry.trace; + + +import androidx.annotation.NonNull; + +import com.datadog.android.api.InternalLogger; +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer; + +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.api.trace.TracerBuilder; + +public class OtelTracerBuilder implements TracerBuilder { + @NonNull + private final String instrumentationScopeName; + + @NonNull + private final AgentTracer.TracerAPI coreTracer; + + @NonNull + private final InternalLogger logger; + + public OtelTracerBuilder( + @NonNull String instrumentationScopeName, + @NonNull AgentTracer.TracerAPI coreTracer, + @NonNull InternalLogger logger) { + this.coreTracer = coreTracer; + this.instrumentationScopeName = instrumentationScopeName; + this.logger = logger; + } + + @Override + public TracerBuilder setSchemaUrl(String schemaUrl) { + // Not supported + return this; + } + + @Override + public TracerBuilder setInstrumentationVersion(String instrumentationScopeVersion) { + // Not supported + return this; + } + + @Override + public Tracer build() { + return new OtelTracer(this.instrumentationScopeName, this.coreTracer, this.logger); + } +} \ No newline at end of file diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/OtelTracerProvider.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/OtelTracerProvider.kt new file mode 100644 index 0000000000..16c3284d69 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/OtelTracerProvider.kt @@ -0,0 +1,241 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.trace + +import androidx.annotation.FloatRange +import com.datadog.android.Datadog +import com.datadog.android.api.InternalLogger +import com.datadog.android.api.SdkCore +import com.datadog.android.api.feature.Feature +import com.datadog.android.api.feature.FeatureSdkCore +import com.datadog.android.trace.internal.TracingFeature +import com.datadog.android.trace.internal.data.NoOpOtelWriter +import com.datadog.opentelemetry.trace.OtelTracerBuilder +import com.datadog.trace.api.IdGenerationStrategy +import com.datadog.trace.api.config.TracerConfig +import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer +import com.datadog.trace.core.CoreTracer +import io.opentelemetry.api.trace.Tracer +import io.opentelemetry.api.trace.TracerBuilder +import io.opentelemetry.api.trace.TracerProvider +import java.util.Locale +import java.util.Properties + +/** + * A class enabling Datadog OpenTelemetry features. + * + * It allows you to create [TracerProvider]. + * + * You can have multiple [TracerProvider]s configured in your application, each with their own settings. + * + */ +class OtelTracerProvider( + private val coreTracer: AgentTracer.TracerAPI, + private val internalLogger: InternalLogger +) : TracerProvider { + + private val tracers: MutableMap = mutableMapOf() + override fun get(instrumentationName: String): Tracer { + val tracer = tracers[instrumentationName] + return if (tracer == null) { + val newTracer = tracerBuilder(instrumentationName).build() + tracers[instrumentationName] = newTracer + newTracer + } else { + internalLogger.log( + InternalLogger.Level.DEBUG, + InternalLogger.Target.USER, + { TRACER_ALREADY_EXISTS_WARNING_MESSAGE.format(Locale.US, instrumentationName) } + ) + tracer + } + } + + override fun get(instrumentationName: String, instrumentationVersion: String): Tracer { + val tracer = tracers[instrumentationName] + return if (tracer == null) { + val newTracer = tracerBuilder(instrumentationName) + .setInstrumentationVersion(instrumentationVersion) + .build() + tracers[instrumentationName] = newTracer + newTracer + } else { + internalLogger.log( + InternalLogger.Level.DEBUG, + InternalLogger.Target.USER, + { TRACER_ALREADY_EXISTS_WARNING_MESSAGE.format(Locale.US, instrumentationName) } + ) + tracer + } + } + + /** @inheritDoc */ + override fun tracerBuilder(instrumentationScopeName: String): TracerBuilder { + val resolvedInstrumentationScopeName = resolveInstrumentationScopeName(instrumentationScopeName) + return OtelTracerBuilder(resolvedInstrumentationScopeName, coreTracer, internalLogger) + } + + private fun resolveInstrumentationScopeName(instrumentationScopeName: String): String { + return if (instrumentationScopeName.trim { it <= ' ' }.isEmpty()) { + DEFAULT_TRACER_NAME + } else { + instrumentationScopeName + } + } + + /** + * A builder for creating [TracerProvider] instances. + */ + class Builder internal constructor( + private val sdkCore: FeatureSdkCore + ) { + private var tracingHeaderTypes: Set = + setOf(TracingHeaderType.DATADOG, TracingHeaderType.TRACECONTEXT) + private var sampleRate: Double = DEFAULT_SAMPLE_RATE + private var serviceName: String = "" + get() { + return field.ifEmpty { + val service = sdkCore.service + if (service.isEmpty()) { + sdkCore.internalLogger.log( + InternalLogger.Level.ERROR, + InternalLogger.Target.USER, + { DEFAULT_SERVICE_NAME_IS_MISSING_ERROR_MESSAGE } + ) + } + service + } + } + private var partialFlushThreshold = DEFAULT_PARTIAL_MIN_FLUSH + private val globalTags: MutableMap = mutableMapOf() + + /** + * @param sdkCore SDK instance to bind to. If not provided, default instance will be used. + */ + @JvmOverloads + constructor(sdkCore: SdkCore = Datadog.getInstance()) : this(sdkCore as FeatureSdkCore) + + // region Public API + + /** + * Builds a [TracerProvider] based on the current state of this Builder. + */ + fun build(): OtelTracerProvider { + val tracingFeature = sdkCore.getFeature(Feature.TRACING_FEATURE_NAME) + ?.unwrap() + if (tracingFeature == null) { + sdkCore.internalLogger.log( + InternalLogger.Level.ERROR, + InternalLogger.Target.USER, + { TRACING_NOT_ENABLED_ERROR_MESSAGE } + ) + } + // TODO: RUM-0000 Add a logs handler here maybe + val coreTracer = CoreTracer.CoreTracerBuilder() + .withProperties(properties()) + .serviceName(serviceName) + .writer(NoOpOtelWriter()) + .partialFlushMinSpans(partialFlushThreshold) + .idGenerationStrategy(IdGenerationStrategy.fromName("SECURE_RANDOM", false)) + .build() + return OtelTracerProvider(coreTracer, sdkCore.internalLogger) + } + + /** + * Sets the tracing header styles that may be injected by this tracer. + * @param headerTypes the list of header types injected (default = datadog style headers) + */ + fun setTracingHeaderTypes(headerTypes: Set): Builder { + this.tracingHeaderTypes = headerTypes + return this + } + + /** + * Sets the service name that will appear in your traces. + * @param service the service name (default = application package name) + */ + fun setService(service: String): Builder { + this.serviceName = service + return this + } + + /** + * Sets the partial flush threshold. When this threshold is reached (you have a specific + * amount of spans closed waiting) the flush mechanism will be triggered and all the pending + * closed spans will be processed in order to be sent to the intake. + * @param threshold the threshold value (default = 5) + */ + fun setPartialFlushThreshold(threshold: Int): Builder { + this.partialFlushThreshold = threshold + return this + } + + /** + * Adds a global tag which will be appended to all spans created with the built tracer. + * @param key the tag key + * @param value the tag value + */ + fun addTag(key: String, value: String): Builder { + this.globalTags[key] = value + return this + } + + /** + * Sets the sample rate of spans. + * @param sampleRate the sample rate as a percentage between 0 and 100 (default is 100%) + */ + fun setSampleRate( + @FloatRange(from = 0.0, to = 100.0) sampleRate: Double + ): Builder { + this.sampleRate = sampleRate + return this + } + + internal fun properties(): Properties { + val properties = Properties() + properties.setProperty( + TracerConfig.SPAN_TAGS, + globalTags.map { "${it.key}:${it.value}" }.joinToString(",") + ) + properties.setProperty( + TracerConfig.TRACE_SAMPLE_RATE, + (sampleRate / DEFAULT_SAMPLE_RATE).toString() + ) + + val propagationStyles = tracingHeaderTypes.joinToString(",") + properties.setProperty(TracerConfig.PROPAGATION_STYLE_EXTRACT, propagationStyles) + properties.setProperty(TracerConfig.PROPAGATION_STYLE_INJECT, propagationStyles) + + return properties + } + + // endregion + } + + override fun toString(): String { + return "OtelTracerProvider/${super.toString()}" + } + + companion object { + internal const val TRACER_ALREADY_EXISTS_WARNING_MESSAGE = + "Tracer for %s already exists. Returning existing instance." + internal const val DEFAULT_TRACER_NAME = "android" + internal const val DEFAULT_SAMPLE_RATE = 100.0 + + internal const val TRACING_NOT_ENABLED_ERROR_MESSAGE = + "You're trying to create an OtelTracerProvider instance, " + + "but either the SDK was not initialized or the Tracing feature was " + + "disabled in your Configuration. No tracing data will be sent." + internal const val DEFAULT_SERVICE_NAME_IS_MISSING_ERROR_MESSAGE = + "Default service name is missing during" + + " OtelTracerProvider creation, did you initialize SDK?" + + // the minimum closed spans required for triggering a flush and deliver + // everything to the writer + internal const val DEFAULT_PARTIAL_MIN_FLUSH = 5 + } +} diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/NoOpOtelWriter.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/NoOpOtelWriter.kt new file mode 100644 index 0000000000..b6956bfdf3 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/NoOpOtelWriter.kt @@ -0,0 +1,27 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.trace.internal.data + +import com.datadog.trace.common.writer.Writer + +internal class NoOpOtelWriter : Writer { + override fun close() { + } + + override fun write(p0: MutableList?) { + } + + override fun start() { + } + + override fun flush(): Boolean { + return true + } + + override fun incrementDropCounts(p0: Int) { + } +} diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/OtelTracerBuilderProviderTest.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/OtelTracerBuilderProviderTest.kt new file mode 100644 index 0000000000..717f031e7d --- /dev/null +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/OtelTracerBuilderProviderTest.kt @@ -0,0 +1,415 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.trace + +import com.datadog.android.api.InternalLogger +import com.datadog.android.api.feature.Feature +import com.datadog.android.api.feature.FeatureScope +import com.datadog.android.api.feature.FeatureSdkCore +import com.datadog.android.trace.internal.TracingFeature +import com.datadog.android.trace.utils.verifyLog +import com.datadog.android.utils.forge.Configurator +import com.datadog.opentelemetry.trace.OtelSpan +import com.datadog.opentelemetry.trace.OtelSpanContext +import com.datadog.tools.unit.getFieldValue +import com.datadog.trace.api.Config +import com.datadog.trace.api.config.TracerConfig +import com.datadog.trace.core.CoreTracer +import com.datadog.trace.core.DDSpanContext +import fr.xgouchet.elmyr.Forge +import fr.xgouchet.elmyr.annotation.DoubleForgery +import fr.xgouchet.elmyr.annotation.IntForgery +import fr.xgouchet.elmyr.annotation.StringForgery +import fr.xgouchet.elmyr.annotation.StringForgeryType +import fr.xgouchet.elmyr.junit5.ForgeConfiguration +import fr.xgouchet.elmyr.junit5.ForgeExtension +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.offset +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.junit.jupiter.api.extension.Extensions +import org.mockito.Mock +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.junit.jupiter.MockitoSettings +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.times +import org.mockito.kotlin.verifyNoInteractions +import org.mockito.kotlin.whenever +import org.mockito.quality.Strictness +import java.util.Locale + +@Extensions( + ExtendWith(MockitoExtension::class), + ExtendWith(ForgeExtension::class) +) +@MockitoSettings(strictness = Strictness.LENIENT) +@ForgeConfiguration(Configurator::class) +internal class OtelTracerBuilderProviderTest { + + lateinit var testedOtelTracerProviderBuilder: OtelTracerProvider.Builder + lateinit var fakeServiceName: String + + @Mock + lateinit var mockTracingFeatureScope: FeatureScope + + @Mock + lateinit var mockTracingFeature: TracingFeature + + @Mock + lateinit var mockSdkCore: FeatureSdkCore + + @Mock + lateinit var mockInternalLogger: InternalLogger + + @StringForgery + lateinit var fakeInstrumentationName: String + + @BeforeEach + fun `set up`(forge: Forge) { + fakeServiceName = forge.anAlphabeticalString() + whenever( + mockSdkCore.getFeature(Feature.TRACING_FEATURE_NAME) + ) doReturn mockTracingFeatureScope + whenever(mockTracingFeatureScope.unwrap()) doReturn mockTracingFeature + whenever(mockSdkCore.getFeature(Feature.RUM_FEATURE_NAME)) doReturn mock() + whenever(mockSdkCore.service) doReturn fakeServiceName + whenever(mockSdkCore.internalLogger) doReturn mockInternalLogger + testedOtelTracerProviderBuilder = OtelTracerProvider.Builder(mockSdkCore) + } + + // region feature checks + + @Test + fun `M log a user error W build { TracingFeature not enabled }`() { + // GIVEN + whenever(mockSdkCore.getFeature(Feature.TRACING_FEATURE_NAME)) doReturn null + + // WHEN + testedOtelTracerProviderBuilder.build() + + // THEN + mockInternalLogger.verifyLog( + InternalLogger.Level.ERROR, + InternalLogger.Target.USER, + OtelTracerProvider.TRACING_NOT_ENABLED_ERROR_MESSAGE + ) + } + + @Test + fun `M log a user error W build { default service name not available }`() { + // GIVEN + whenever(mockSdkCore.service) doReturn "" + + // WHEN + testedOtelTracerProviderBuilder.build() + + // THEN + mockInternalLogger.verifyLog( + InternalLogger.Level.ERROR, + InternalLogger.Target.USER, + OtelTracerProvider.DEFAULT_SERVICE_NAME_IS_MISSING_ERROR_MESSAGE + ) + } + + // endregion + + // region ID generation + + @Test + fun `M build tracers which generate Spans with 64 bits long ids W build`( + @StringForgery(type = StringForgeryType.ALPHA_NUMERICAL) spanName: String + ) { + // Given + val tracerProvider = testedOtelTracerProviderBuilder + .build() + + // When + val span = tracerProvider + .tracerBuilder(fakeInstrumentationName) + .build() + .spanBuilder(spanName) + .startSpan() + + // Then + assertThat(span.spanContext.spanIdBytes.size).isEqualTo(8) + } + + @Test + fun `M build tracers which generate Spans with 128 bits long trace ids W build`( + @StringForgery(type = StringForgeryType.ALPHA_NUMERICAL) spanName: String + ) { + // Given + val tracerProvider = testedOtelTracerProviderBuilder.build() + + // When + val span = tracerProvider + .tracerBuilder(fakeInstrumentationName) + .build() + .spanBuilder(spanName) + .startSpan() + val traceId = span.spanContext.traceId + + // Then + assertThat(traceId.substring(0, 16)).isEqualTo("0000000000000000") + assertThat(span.spanContext.traceIdBytes.size).isEqualTo(16) + } + + // endregion + + // region Tracer creation + + @Test + fun `M create a single tracer for same instrumentation name W get`(forge: Forge) { + // Given + val tracerProvider = testedOtelTracerProviderBuilder.build() + val tracer = tracerProvider.get(fakeInstrumentationName) + + // Then + val times = forge.aTinyInt() + repeat(times) { + val newTracer = tracerProvider.get(fakeInstrumentationName) + assertThat(newTracer).isSameAs(tracer) + } + mockInternalLogger.verifyLog( + InternalLogger.Level.DEBUG, + InternalLogger.Target.USER, + OtelTracerProvider.TRACER_ALREADY_EXISTS_WARNING_MESSAGE.format(Locale.US, fakeInstrumentationName), + mode = times(times) + ) + } + + @Test + fun `M create different tracers for different instrumentation name W get`(forge: Forge) { + // Given + val tracerProvider = testedOtelTracerProviderBuilder.build() + val tracer = tracerProvider.get(fakeInstrumentationName) + + // Then + val times = forge.aTinyInt() + repeat(times) { + val newTracer = tracerProvider.get(forge.anAlphabeticalString()) + assertThat(newTracer).isNotSameAs(tracer) + } + verifyNoInteractions(mockInternalLogger) + } + + @Test + fun `M create a single tracer for same instrumentation name W get { same instrumentationVersion }`( + @StringForgery(type = StringForgeryType.ALPHA_NUMERICAL) instrumentationVersion: String, + forge: Forge + ) { + // Given + val tracerProvider = testedOtelTracerProviderBuilder.build() + val tracer = tracerProvider.get(fakeInstrumentationName, instrumentationVersion) + + // Then + val times = forge.aTinyInt() + repeat(times) { + val newTracer = tracerProvider.get(fakeInstrumentationName, instrumentationVersion) + assertThat(newTracer).isSameAs(tracer) + } + mockInternalLogger.verifyLog( + InternalLogger.Level.DEBUG, + InternalLogger.Target.USER, + OtelTracerProvider.TRACER_ALREADY_EXISTS_WARNING_MESSAGE.format(Locale.US, fakeInstrumentationName), + mode = times(times) + ) + } + + @Test + fun `M use the spanName as resourceName W creating a span`( + @StringForgery(type = StringForgeryType.ALPHA_NUMERICAL) spanName: String + ) { + // Given + val tracerProvider = testedOtelTracerProviderBuilder.build() + + // When + val span = tracerProvider + .tracerBuilder(fakeInstrumentationName) + .build() + .spanBuilder(spanName) + .startSpan() + span.end() + + // Then + val agentContext = (span.spanContext as OtelSpanContext).delegate as DDSpanContext + assertThat(agentContext.resourceName).isEqualTo(spanName) + } + + @Test + fun `M use the default serviceName W creating a tracer`( + @StringForgery(type = StringForgeryType.ALPHA_NUMERICAL) spanName: String + ) { + // Given + val tracerProvider = testedOtelTracerProviderBuilder.build() + + // When + val span = tracerProvider + .tracerBuilder(fakeInstrumentationName) + .build() + .spanBuilder(spanName) + .startSpan() + span.end() + + // Then + val agentContext = (span.spanContext as OtelSpanContext).delegate as DDSpanContext + assertThat(agentContext.serviceName).isEqualTo(fakeServiceName) + } + + @Test + fun `M use the provided serviceName W setServiceName`( + @StringForgery(type = StringForgeryType.ALPHA_NUMERICAL) spanName: String, + @StringForgery(type = StringForgeryType.ALPHABETICAL) fakeCustomServiceName: String + ) { + // Given + val tracerProvider = testedOtelTracerProviderBuilder.setService(fakeCustomServiceName).build() + + // When + val span = tracerProvider + .tracerBuilder(fakeInstrumentationName) + .build() + .spanBuilder(spanName) + .startSpan() + span.end() + + // Then + val agentContext = (span.spanContext as OtelSpanContext).delegate as DDSpanContext + assertThat(agentContext.serviceName).isEqualTo(fakeCustomServiceName) + } + + @Test + fun `M use the default threshold value W creating a tracer`() { + // Given + val tracer = testedOtelTracerProviderBuilder.build() + .tracerBuilder(fakeInstrumentationName).build() + + // When + val coreTracer: CoreTracer = tracer.getFieldValue("tracer") + + // Then + assertThat(coreTracer.partialFlushMinSpans).isEqualTo(OtelTracerProvider.DEFAULT_PARTIAL_MIN_FLUSH) + } + + @Test + fun `M use the provided flush threshold value W setPartialFlushThreshold`(@IntForgery threshold: Int) { + // Given + val tracer = testedOtelTracerProviderBuilder.setPartialFlushThreshold(threshold).build() + .tracerBuilder(fakeInstrumentationName).build() + + // When + val coreTracer: CoreTracer = tracer.getFieldValue("tracer") + + // Then + assertThat(coreTracer.partialFlushMinSpans).isEqualTo(threshold) + } + + @Test + fun `M use the default sample rate W creating a tracer`() { + // Given + val expectedNormalizedSampleRate = OtelTracerProvider.DEFAULT_SAMPLE_RATE / 100.0 + val tracer = testedOtelTracerProviderBuilder.build() + .tracerBuilder(fakeInstrumentationName).build() + + // When + val coreTracer: CoreTracer = tracer.getFieldValue("tracer") + + // Then + val config: Config = coreTracer.getFieldValue("initialConfig") + assertThat(config.traceSampleRate).isCloseTo(expectedNormalizedSampleRate, offset(0.005)) + } + + @Test + fun `M use the sample rate W setSampleRate`(@DoubleForgery(min = 0.0, max = 100.0) sampleRate: Double) { + // Given + val expectedNormalizedSampleRate = sampleRate / 100.0 + val tracer = testedOtelTracerProviderBuilder.setSampleRate(sampleRate).build() + .tracerBuilder(fakeInstrumentationName).build() + + // When + val coreTracer: CoreTracer = tracer.getFieldValue("tracer") + + // Then + val config: Config = coreTracer.getFieldValue("initialConfig") + assertThat(config.traceSampleRate).isCloseTo(expectedNormalizedSampleRate, offset(0.005)) + } + + @Test + fun `M set correct propagating style W setting tracing header types`(forge: Forge) { + // Given + val tracingHeaderStyles = forge.aList { aValueFrom(TracingHeaderType::class.java) }.toSet() + val tracerProvider = testedOtelTracerProviderBuilder + .setTracingHeaderTypes(tracingHeaderStyles) + .build() + + // Then + tracerProvider.tracerBuilder(fakeInstrumentationName).build() + val properties = testedOtelTracerProviderBuilder.properties() + + val injectionStyles = properties + .getProperty(TracerConfig.PROPAGATION_STYLE_INJECT) + .toString() + .split(",") + .toSet() + val extractionStyles = properties + .getProperty(TracerConfig.PROPAGATION_STYLE_EXTRACT) + .toString() + .split(",") + .toSet() + + assertThat(injectionStyles).isEqualTo(tracingHeaderStyles.map { it.headerType }.toSet()) + assertThat(extractionStyles).isEqualTo(tracingHeaderStyles.map { it.headerType }.toSet()) + } + + @Test + fun `M use default propagating style W build`() { + // Given + val expectedDefaultPropagationStyles = setOf(TracingHeaderType.DATADOG, TracingHeaderType.TRACECONTEXT) + val tracerProvider = testedOtelTracerProviderBuilder + .build() + + // Then + tracerProvider.tracerBuilder(fakeInstrumentationName).build() + val properties = testedOtelTracerProviderBuilder.properties() + + val injectionStyles = properties + .getProperty(TracerConfig.PROPAGATION_STYLE_INJECT) + .toString() + .split(",") + .toSet() + val extractionStyles = properties + .getProperty(TracerConfig.PROPAGATION_STYLE_EXTRACT) + .toString() + .split(",") + .toSet() + + assertThat(injectionStyles).isEqualTo(expectedDefaultPropagationStyles.map { it.headerType }.toSet()) + assertThat(extractionStyles).isEqualTo(expectedDefaultPropagationStyles.map { it.headerType }.toSet()) + } + + @Test + fun `M build a valid Tracer with tags W addTag`( + @StringForgery operation: String, + @StringForgery key: String, + @StringForgery(type = StringForgeryType.HEXADECIMAL) value: String + ) { + // When + val tracerProvider = testedOtelTracerProviderBuilder + .addTag(key, value) + .build() + val tracer = tracerProvider.tracerBuilder(fakeInstrumentationName).build() + + // Then + assertThat(tracer).isNotNull() + val span = tracer.spanBuilder(operation).startSpan() as OtelSpan + val agentSpanContext = span.agentSpanContext as DDSpanContext + assertThat(agentSpanContext.tags).containsEntry(key, value) + } + + // endregion +} diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java index 0ad8df9a6f..5194d00860 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java @@ -1317,7 +1317,7 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins new String( Files.readAllBytes(Paths.get(oldProfilingApiKeyFile)), StandardCharsets.UTF_8) .trim(); - }else{ + } else { tmpApiKey = new String(FileUtils.readAllBytes(oldProfilingApiKeyFile), StandardCharsets.UTF_8) .trim(); } @@ -3467,6 +3467,7 @@ public boolean isRuleEnabled(final String name, boolean defaultEnabled) { * @deprecated This method should only be used internally. Use the instance getter instead {@link * #isJmxFetchIntegrationEnabled(Iterable, boolean)}. */ + @Deprecated public static boolean jmxFetchIntegrationEnabled( final SortedSet integrationNames, final boolean defaultEnabled) { return Config.get().isJmxFetchIntegrationEnabled(integrationNames, defaultEnabled); @@ -3571,6 +3572,7 @@ public > T getEnumValue( * @deprecated This method should only be used internally. Use the instance getter instead {@link * #isTraceAnalyticsIntegrationEnabled(SortedSet, boolean)}. */ + @Deprecated public static boolean traceAnalyticsIntegrationEnabled( final SortedSet integrationNames, final boolean defaultEnabled) { return Config.get().isTraceAnalyticsIntegrationEnabled(integrationNames, defaultEnabled); From 169dfbb3df86aa833f90966222f32c5ce93769d8 Mon Sep 17 00:00:00 2001 From: Marius Constantin Date: Mon, 4 Mar 2024 14:09:06 +0100 Subject: [PATCH 06/55] Remove spotbugs depdendency --- features/dd-trace-core/build.gradle.kts | 1 - features/dd-trace-core/lint.xml | 6 ------ .../datadog/trace/common/writer/RemoteApi.java | 2 -- .../main/java/com/datadog/trace/core/DDSpan.java | 14 +++++++------- .../com/datadog/trace/core/PendingTrace.java | 14 +++++++------- .../core/propagation/ptags/PTagsFactory.java | 8 +++----- .../core/scopemanager/ContinuableScope.java | 4 ++-- .../core/taginterceptor/TagInterceptor.java | 6 +++--- .../core/tagprocessor/BaseServiceAdder.java | 2 +- .../core/tagprocessor/PeerServiceCalculator.java | 6 +++--- .../core/tagprocessor/PostProcessorChain.java | 4 ++-- features/dd-trace-core/transitiveDependencies | 16 +--------------- gradle/libs.versions.toml | 2 -- 13 files changed, 29 insertions(+), 56 deletions(-) delete mode 100644 features/dd-trace-core/lint.xml diff --git a/features/dd-trace-core/build.gradle.kts b/features/dd-trace-core/build.gradle.kts index 40dd332cdf..8065c53e31 100644 --- a/features/dd-trace-core/build.gradle.kts +++ b/features/dd-trace-core/build.gradle.kts @@ -43,7 +43,6 @@ dependencies { implementation(libs.androidXAnnotation) implementation(libs.datadogSketchesJava) implementation(libs.re2j) - compileOnly(libs.spotbugs) // TODO: RUM-3268 Port and enable the groovy unit tests diff --git a/features/dd-trace-core/lint.xml b/features/dd-trace-core/lint.xml deleted file mode 100644 index 9253c42b22..0000000000 --- a/features/dd-trace-core/lint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java index 8796758eca..2726d9e683 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java @@ -1,7 +1,6 @@ package com.datadog.trace.common.writer; import com.datadog.trace.relocate.api.IOLogger; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import org.slf4j.Logger; @@ -65,7 +64,6 @@ protected String createSendLogMessage( + "."; } - @SuppressFBWarnings("DCN_NULLPOINTER_EXCEPTION") protected static String getResponseBody(okhttp3.Response response) { if (response != null) { try { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java index dfde7a025a..f1073f7270 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java @@ -35,8 +35,8 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,7 +55,7 @@ public class DDSpan static DDSpan create( final String instrumentationName, final long timestampMicro, - @Nonnull DDSpanContext context, + @NonNull DDSpanContext context, final List links) { final DDSpan span = new DDSpan(instrumentationName, timestampMicro, context, links); log.debug("Started span: {}", span); @@ -121,9 +121,9 @@ static DDSpan create( * @param context the context used for the span */ private DDSpan( - @Nonnull String instrumentationName, + @NonNull String instrumentationName, final long timestampMicro, - @Nonnull DDSpanContext context, + @NonNull DDSpanContext context, final List links) { this.context = context; this.metrics = SpanMetricRegistry.getInstance().get(instrumentationName); @@ -484,7 +484,7 @@ public Object getTag(final String tag) { } @Override - @Nonnull + @NonNull public final DDSpanContext context() { return context; } @@ -760,7 +760,7 @@ public EndpointTracker getEndpointTracker() { * * @param endpointTracker the end-point tracker instance */ - public void setEndpointTracker(@Nonnull EndpointTracker endpointTracker) { + public void setEndpointTracker(@NonNull EndpointTracker endpointTracker) { DDSpan localRootSpan = getLocalRootSpan(); if (localRootSpan == null) { log.warn("Span {} has no associated local root span", this); diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java index 26c866cd9e..b285969c2c 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java @@ -17,7 +17,7 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -import javax.annotation.Nonnull; +import androidx.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,11 +68,11 @@ static class Factory { } /** Used by tests and benchmarks. */ - PendingTrace create(@Nonnull DDTraceId traceId) { + PendingTrace create(@NonNull DDTraceId traceId) { return create(traceId, null); } - PendingTrace create(@Nonnull DDTraceId traceId, ConfigSnapshot traceConfig) { + PendingTrace create(@NonNull DDTraceId traceId, ConfigSnapshot traceConfig) { return new PendingTrace( tracer, traceId, @@ -145,10 +145,10 @@ PendingTrace create(@Nonnull DDTraceId traceId, ConfigSnapshot traceConfig) { AtomicLongFieldUpdater.newUpdater(PendingTrace.class, "endToEndStartTime"); private PendingTrace( - @Nonnull CoreTracer tracer, - @Nonnull DDTraceId traceId, - @Nonnull PendingTraceBuffer pendingTraceBuffer, - @Nonnull TimeSource timeSource, + @NonNull CoreTracer tracer, + @NonNull DDTraceId traceId, + @NonNull PendingTraceBuffer pendingTraceBuffer, + @NonNull TimeSource timeSource, ConfigSnapshot traceConfig, boolean strictTraceWrites, HealthMetrics healthMetrics) { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/PTagsFactory.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/PTagsFactory.java index 04b3a466fa..c5483c4b4a 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/PTagsFactory.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/PTagsFactory.java @@ -10,13 +10,12 @@ import com.datadog.trace.api.sampling.SamplingMechanism; import com.datadog.trace.core.propagation.PropagationTags; import com.datadog.trace.core.propagation.PropagationTags.HeaderType; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.Collections; import java.util.EnumMap; import java.util.List; import java.util.Map; import java.util.Objects; -import javax.annotation.Nonnull; +import androidx.annotation.NonNull; public class PTagsFactory implements PropagationTags.Factory { static final String PROPAGATION_ERROR_TAG_KEY = "_dd.propagation_error"; @@ -39,7 +38,7 @@ int getxDatadogTagsLimit() { return xDatadogTagsLimit; } - PTagsCodec getDecoderEncoder(@Nonnull HeaderType headerType) { + PTagsCodec getDecoderEncoder(@NonNull HeaderType headerType) { return DEC_ENC_MAP.get(headerType); } @@ -49,7 +48,7 @@ public final PropagationTags empty() { } @Override - public final PropagationTags fromHeaderValue(@Nonnull HeaderType headerType, String value) { + public final PropagationTags fromHeaderValue(@NonNull HeaderType headerType, String value) { return DEC_ENC_MAP.get(headerType).fromHeaderValue(this, value); } @@ -215,7 +214,6 @@ public void updateTraceIdHighOrderBits(long highOrderBits) { @Override @SuppressWarnings("StringEquality") - @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ") public String headerValue(HeaderType headerType) { String header = getCachedHeader(headerType); if (header == null) { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScope.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScope.java index 51cb29c79a..dafb05566b 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScope.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScope.java @@ -8,7 +8,7 @@ import com.datadog.trace.bootstrap.instrumentation.api.AttachableWrapper; import com.datadog.trace.bootstrap.instrumentation.api.ScopeSource; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -import javax.annotation.Nonnull; +import androidx.annotation.NonNull; class ContinuableScope implements AgentScope, AttachableWrapper { private final ContinuableScopeManager scopeManager; @@ -196,7 +196,7 @@ public byte source() { } @Override - public void attachWrapper(@Nonnull Object wrapper) { + public void attachWrapper(@NonNull Object wrapper) { WRAPPER_FIELD_UPDATER.set(this, wrapper); } diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/taginterceptor/TagInterceptor.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/taginterceptor/TagInterceptor.java index 31b8648062..fb54c59113 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/taginterceptor/TagInterceptor.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/taginterceptor/TagInterceptor.java @@ -33,8 +33,8 @@ import com.datadog.trace.core.DDSpanContext; import java.net.URI; import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; public class TagInterceptor { @@ -136,7 +136,7 @@ private boolean interceptUrlResourceAsNameRule(DDSpanContext span, String tag, O } private static void setResourceFromUrl( - @Nonnull final DDSpanContext span, @Nullable final String method, @Nonnull final Object url) { + @NonNull final DDSpanContext span, @Nullable final String method, @NonNull final Object url) { final String path; if (url instanceof URIUtils.LazyUrl) { path = ((URIUtils.LazyUrl) url).path(); diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/BaseServiceAdder.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/BaseServiceAdder.java index 4a401cfa60..18fdd9a2fb 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/BaseServiceAdder.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/BaseServiceAdder.java @@ -4,7 +4,7 @@ import com.datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import com.datadog.trace.core.DDSpanContext; import java.util.Map; -import javax.annotation.Nullable; +import androidx.annotation.Nullable; public class BaseServiceAdder implements TagsPostProcessor { private final UTF8BytesString ddService; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PeerServiceCalculator.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PeerServiceCalculator.java index 45f21324e6..989368ae03 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PeerServiceCalculator.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PeerServiceCalculator.java @@ -6,7 +6,7 @@ import com.datadog.trace.api.naming.SpanNaming; import com.datadog.trace.bootstrap.instrumentation.api.Tags; import java.util.Map; -import javax.annotation.Nonnull; +import androidx.annotation.NonNull; public class PeerServiceCalculator implements TagsPostProcessor { private final NamingSchema.ForPeerService peerServiceNaming; @@ -21,8 +21,8 @@ public PeerServiceCalculator() { // Visible for testing PeerServiceCalculator( - @Nonnull final NamingSchema.ForPeerService peerServiceNaming, - @Nonnull final Map peerServiceMapping) { + @NonNull final NamingSchema.ForPeerService peerServiceNaming, + @NonNull final Map peerServiceMapping) { this.peerServiceNaming = peerServiceNaming; this.peerServiceMapping = peerServiceMapping; this.canRemap = !peerServiceMapping.isEmpty(); diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PostProcessorChain.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PostProcessorChain.java index 48ce52b881..7138debe45 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PostProcessorChain.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/PostProcessorChain.java @@ -3,12 +3,12 @@ import com.datadog.trace.core.DDSpanContext; import java.util.Map; import java.util.Objects; -import javax.annotation.Nonnull; +import androidx.annotation.NonNull; public class PostProcessorChain implements TagsPostProcessor { private final TagsPostProcessor[] chain; - public PostProcessorChain(@Nonnull final TagsPostProcessor... processors) { + public PostProcessorChain(@NonNull final TagsPostProcessor... processors) { chain = Objects.requireNonNull(processors); } diff --git a/features/dd-trace-core/transitiveDependencies b/features/dd-trace-core/transitiveDependencies index 72288f83cd..f7e3ae6ea6 100644 --- a/features/dd-trace-core/transitiveDependencies +++ b/features/dd-trace-core/transitiveDependencies @@ -2,31 +2,17 @@ Dependencies List androidx.annotation:annotation:1.1.0 : 27 Kb com.datadoghq:sketches-java:0.8.2 : 125 Kb -com.github.spotbugs:spotbugs-annotations:4.2.0 : 14 Kb -com.github.spotbugs:spotbugs:4.2.0 : 3 Mb -com.google.code.findbugs:jsr305:3.0.2 : 19 Kb com.google.re2j:re2j:1.7 : 111 Kb com.squareup.moshi:moshi:1.11.0 : 148 Kb com.squareup.okhttp3:okhttp:4.11.0 : 768 Kb com.squareup.okio:okio-jvm:3.2.0 : 337 Kb -net.jcip:jcip-annotations:1.0 : 2 Kb -org.apache.bcel:bcel:6.5.0 : 678 Kb -org.apache.commons:commons-lang3:3.11 : 564 Kb -org.apache.commons:commons-text:1.9 : 211 Kb -org.dom4j:dom4j:2.1.3 : 316 Kb org.jctools:jctools-core:3.3.0 : 328 Kb org.jetbrains.kotlin:kotlin-stdlib-common:1.8.10 : 212 Kb org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.10 : 963 b org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10 : 969 b org.jetbrains.kotlin:kotlin-stdlib:1.8.10 : 1598 Kb org.jetbrains:annotations:13.0 : 17 Kb -org.json:json:20200518 : 64 Kb -org.ow2.asm:asm-analysis:9.0 : 32 Kb -org.ow2.asm:asm-commons:9.0 : 69 Kb -org.ow2.asm:asm-tree:9.0 : 51 Kb -org.ow2.asm:asm-util:9.0 : 82 Kb -org.ow2.asm:asm:9.0 : 118 Kb org.slf4j:slf4j-api:1.7.30 : 40 Kb -Total transitive dependencies size : 9 Mb +Total transitive dependencies size : 3 Mb diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e5cfc17417..9ea7443b64 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -91,7 +91,6 @@ openTelemetry = "1.4.0" desugarJdk = "2.0.4" datatadogSketchesJava = "0.8.2" re2j = "1.7" -spotbugs = "4.2.0" [libraries] @@ -236,7 +235,6 @@ openTelemetry = { module = "io.opentelemetry:opentelemetry-api", version.ref = " desugarJdk = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugarJdk" } datadogSketchesJava = { module = "com.datadoghq:sketches-java", version.ref = "datatadogSketchesJava" } re2j = { module = "com.google.re2j:re2j", version.ref = "re2j" } -spotbugs = { module = "com.github.spotbugs:spotbugs", version.ref = "spotbugs" } [bundles] From fd1ee87fe5067057528064bf8841f9dd3ae63be6 Mon Sep 17 00:00:00 2001 From: Marius Constantin Date: Mon, 4 Mar 2024 15:29:44 +0100 Subject: [PATCH 07/55] Switch from slf4j logger to our internal implementation --- .../dd-sdk-android-trace/build.gradle.kts | 2 +- .../transitiveDependencies | 2 + features/dd-trace-core/build.gradle.kts | 4 - features/dd-trace-core/consumer-rules.pro | 4 - .../java/com/datadog/trace/api/Config.java | 4 +- .../com/datadog/trace/api/DynamicConfig.java | 4 +- .../trace/api/EndpointCheckpointerHolder.java | 4 +- .../trace/api/MethodFilterConfigParser.java | 4 +- .../datadog/trace/api/WithGlobalTracer.java | 4 +- .../api/gateway/InstrumentationGateway.java | 4 +- .../trace/api/http/StoredByteBody.java | 4 +- .../trace/api/http/StoredCharBody.java | 4 +- .../trace/api/iast/IastEnabledChecks.java | 4 +- .../datadog/trace/api/iast/IastModule.java | 4 +- .../com/datadog/trace/api/iast/Taintable.java | 4 +- .../iast/telemetry/IastMetricCollector.java | 4 +- .../AntPatternHttpPathNormalizer.java | 4 +- .../trace/api/normalize/SQLNormalizer.java | 4 +- .../trace/api/telemetry/LogCollector.java | 4 - .../config/provider/AgentArgsParser.java | 4 +- .../config/provider/ConfigConverter.java | 7 +- .../config/provider/ConfigProvider.java | 4 +- .../instrumentation/api/URIUtils.java | 4 +- .../sampling/RateByServiceTraceSampler.java | 4 +- .../sampling/RuleBasedTraceSampler.java | 4 +- .../trace/common/sampling/Sampler.java | 4 +- .../common/sampling/SingleSpanSampler.java | 4 +- .../common/sampling/SpanSamplingRules.java | 4 +- .../common/sampling/TraceSamplingRules.java | 4 +- .../trace/common/writer/ListWriter.java | 4 +- .../trace/common/writer/LoggingWriter.java | 4 +- .../trace/common/writer/RemoteApi.java | 2 +- .../common/writer/SpanSamplingWorker.java | 4 +- .../common/writer/TraceProcessingWorker.java | 4 +- .../common/writer/TraceStructureWriter.java | 4 +- .../com/datadog/trace/core/CoreTracer.java | 4 +- .../java/com/datadog/trace/core/DDSpan.java | 4 +- .../com/datadog/trace/core/DDSpanContext.java | 4 +- .../com/datadog/trace/core/DDSpanLink.java | 4 +- .../com/datadog/trace/core/PendingTrace.java | 4 +- .../trace/core/PendingTraceBuffer.java | 4 +- .../com/datadog/trace/core/StatusLogger.java | 4 +- .../DataStreamContextInjector.java | 4 +- .../datastreams/DefaultPathwayContext.java | 4 +- .../trace/core/propagation/B3HttpCodec.java | 4 +- .../core/propagation/DatadogHttpCodec.java | 4 +- .../core/propagation/HaystackHttpCodec.java | 4 +- .../trace/core/propagation/HttpCodec.java | 4 +- .../trace/core/propagation/W3CHttpCodec.java | 4 +- .../trace/core/propagation/XRayHttpCodec.java | 4 +- .../propagation/ptags/DatadogPTagsCodec.java | 2 +- .../trace/core/propagation/ptags/TagKey.java | 4 +- .../core/propagation/ptags/TagValue.java | 4 +- .../core/propagation/ptags/W3CPTagsCodec.java | 2 +- .../scopemanager/ContinuableScopeManager.java | 4 +- .../core/tagprocessor/QueryObfuscator.java | 4 +- .../datadog/trace/core/util/SystemAccess.java | 4 +- .../datadog/trace/logger/ILoggerFactory.java | 12 ++ .../java/com/datadog/trace/logger/Logger.java | 42 +++++ .../datadog/trace/logger/LoggerFactory.java | 27 +++ .../com/datadog/trace/logger/NoOpLogger.java | 167 ++++++++++++++++++ .../trace/logging/GlobalLogLevelSwitcher.java | 6 +- .../datadog/trace/relocate/api/IOLogger.java | 2 +- .../trace/relocate/api/RatelimitedLogger.java | 2 +- .../trace/util/AgentTaskScheduler.java | 4 +- .../trace/util/AgentThreadFactory.java | 2 +- .../com/datadog/trace/util/PidHelper.java | 4 +- .../com/datadog/trace/util/ProcessUtils.java | 4 +- .../com/datadog/trace/util/TraceUtils.java | 4 +- .../util/stacktrace/StackWalkerFactory.java | 4 +- features/dd-trace-core/transitiveDependencies | 1 - gradle/libs.versions.toml | 4 +- instrumented/integration/proguard-rules.pro | 3 + 73 files changed, 372 insertions(+), 137 deletions(-) delete mode 100644 features/dd-trace-core/consumer-rules.pro create mode 100644 features/dd-trace-core/src/main/java/com/datadog/trace/logger/ILoggerFactory.java create mode 100644 features/dd-trace-core/src/main/java/com/datadog/trace/logger/Logger.java create mode 100644 features/dd-trace-core/src/main/java/com/datadog/trace/logger/LoggerFactory.java create mode 100644 features/dd-trace-core/src/main/java/com/datadog/trace/logger/NoOpLogger.java diff --git a/features/dd-sdk-android-trace/build.gradle.kts b/features/dd-sdk-android-trace/build.gradle.kts index a48dcfe05d..149a4a15da 100644 --- a/features/dd-sdk-android-trace/build.gradle.kts +++ b/features/dd-sdk-android-trace/build.gradle.kts @@ -51,11 +51,11 @@ android { dependencies { api(project(":dd-sdk-android-core")) + api(libs.openTelemetryApi) implementation(project(":features:dd-trace-core")) implementation(libs.kotlin) implementation(libs.gson) implementation(libs.androidXAnnotation) - implementation(libs.openTelemetry) // Generate NoOp implementations ksp(project(":tools:noopfactory")) diff --git a/features/dd-sdk-android-trace/transitiveDependencies b/features/dd-sdk-android-trace/transitiveDependencies index 9e6270370a..164b39abe3 100644 --- a/features/dd-sdk-android-trace/transitiveDependencies +++ b/features/dd-sdk-android-trace/transitiveDependencies @@ -2,6 +2,8 @@ Dependencies List androidx.annotation:annotation:1.3.0 : 30 Kb com.google.code.gson:gson:2.10.1 : 276 Kb +io.opentelemetry:opentelemetry-api:1.4.0 : 78 Kb +io.opentelemetry:opentelemetry-context:1.4.0 : 42 Kb io.opentracing:opentracing-api:0.32.0 : 18 Kb io.opentracing:opentracing-noop:0.32.0 : 10 Kb io.opentracing:opentracing-util:0.32.0 : 10 Kb diff --git a/features/dd-trace-core/build.gradle.kts b/features/dd-trace-core/build.gradle.kts index 8065c53e31..ed1534ac63 100644 --- a/features/dd-trace-core/build.gradle.kts +++ b/features/dd-trace-core/build.gradle.kts @@ -24,9 +24,6 @@ plugins { } android { - defaultConfig { - consumerProguardFiles("consumer-rules.pro") - } compileOptions { isCoreLibraryDesugaringEnabled = true } @@ -35,7 +32,6 @@ android { dependencies { coreLibraryDesugaring(libs.desugarJdk) - implementation(libs.slf4j) implementation(libs.moshi) implementation(libs.jctools) implementation(libs.kotlin) diff --git a/features/dd-trace-core/consumer-rules.pro b/features/dd-trace-core/consumer-rules.pro deleted file mode 100644 index 8de36b2ecf..0000000000 --- a/features/dd-trace-core/consumer-rules.pro +++ /dev/null @@ -1,4 +0,0 @@ -# Do not warn about missing classes required only at compile time by dependencies --dontwarn org.slf4j.** --dontwarn com.google.protobuf.** --dontwarn edu.umd.cs.findbugs.** diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java index 5194d00860..9963f97d04 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/Config.java @@ -322,8 +322,8 @@ import androidx.annotation.NonNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.io.BufferedReader; import java.io.File; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/DynamicConfig.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DynamicConfig.java index f9885ff834..3b85d2eec0 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/DynamicConfig.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/DynamicConfig.java @@ -11,8 +11,8 @@ import static com.datadog.trace.api.config.TracerConfig.TRACE_SAMPLE_RATE; import static com.datadog.trace.util.CollectionUtils.tryMakeImmutableMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.Collection; import java.util.Collections; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointCheckpointerHolder.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointCheckpointerHolder.java index b330eb8004..ae5f087ba1 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointCheckpointerHolder.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/EndpointCheckpointerHolder.java @@ -1,7 +1,7 @@ package com.datadog.trace.api; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/MethodFilterConfigParser.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/MethodFilterConfigParser.java index 9b4caf4fe5..0c01b83d26 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/MethodFilterConfigParser.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/MethodFilterConfigParser.java @@ -1,7 +1,7 @@ package com.datadog.trace.api; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.Collections; import java.util.HashMap; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/WithGlobalTracer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/WithGlobalTracer.java index 3f91e2076d..bfb3d04aea 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/WithGlobalTracer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/WithGlobalTracer.java @@ -1,7 +1,7 @@ package com.datadog.trace.api; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import com.datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/InstrumentationGateway.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/InstrumentationGateway.java index 507b0e15de..62c1f5443c 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/InstrumentationGateway.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/gateway/InstrumentationGateway.java @@ -17,8 +17,8 @@ import static com.datadog.trace.api.gateway.Events.RESPONSE_HEADER_ID; import static com.datadog.trace.api.gateway.Events.RESPONSE_STARTED_ID; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.Map; import java.util.concurrent.atomic.AtomicReferenceArray; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredByteBody.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredByteBody.java index 642e5b0c3e..de3008b525 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredByteBody.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredByteBody.java @@ -2,8 +2,8 @@ import androidx.annotation.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.lang.reflect.UndeclaredThrowableException; import java.nio.ByteBuffer; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredCharBody.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredCharBody.java index 1dbae3019f..c109117591 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredCharBody.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/http/StoredCharBody.java @@ -1,7 +1,7 @@ package com.datadog.trace.api.http; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.nio.CharBuffer; import java.util.Arrays; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastEnabledChecks.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastEnabledChecks.java index 1a30fc911c..5b95c01ffe 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastEnabledChecks.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastEnabledChecks.java @@ -1,7 +1,7 @@ package com.datadog.trace.api.iast; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import com.datadog.trace.api.Platform; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastModule.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastModule.java index baa63cb531..601cd9350c 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastModule.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/IastModule.java @@ -1,7 +1,7 @@ package com.datadog.trace.api.iast; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public interface IastModule { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Taintable.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Taintable.java index 7583a0b1b6..e4517b6778 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Taintable.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/Taintable.java @@ -1,7 +1,7 @@ package com.datadog.trace.api.iast; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/IastMetricCollector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/IastMetricCollector.java index 0bd7512942..8a6d0df0d5 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/IastMetricCollector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/iast/telemetry/IastMetricCollector.java @@ -5,8 +5,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.Collection; import java.util.Collections; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java index 25ca1c7a68..2dcb4156c1 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/AntPatternHttpPathNormalizer.java @@ -1,7 +1,7 @@ package com.datadog.trace.api.normalize; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.ArrayList; import java.util.List; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/SQLNormalizer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/SQLNormalizer.java index 15b7dceccd..3d5ca2bc76 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/SQLNormalizer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/normalize/SQLNormalizer.java @@ -2,8 +2,8 @@ import static java.nio.charset.StandardCharsets.UTF_8; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.Arrays; import java.util.BitSet; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/LogCollector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/LogCollector.java index 40f629aba8..8163957141 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/LogCollector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/api/telemetry/LogCollector.java @@ -1,8 +1,5 @@ package com.datadog.trace.api.telemetry; -import org.slf4j.Marker; -import org.slf4j.MarkerFactory; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -14,7 +11,6 @@ import java.util.concurrent.atomic.AtomicInteger; public class LogCollector { - public static final Marker SEND_TELEMETRY = MarkerFactory.getMarker("SEND_TELEMETRY"); private static final int DEFAULT_MAX_CAPACITY = 1024; private static final LogCollector INSTANCE = new LogCollector(); private final Map rawLogMessages; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/AgentArgsParser.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/AgentArgsParser.java index d7c5843c5e..18157a5609 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/AgentArgsParser.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/AgentArgsParser.java @@ -1,7 +1,7 @@ package com.datadog.trace.bootstrap.config.provider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.HashMap; import java.util.Map; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigConverter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigConverter.java index 70701e8de2..214083712c 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigConverter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigConverter.java @@ -2,12 +2,9 @@ import androidx.annotation.NonNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; import java.util.Arrays; import java.util.BitSet; import java.util.Collections; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigProvider.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigProvider.java index cb1bf35c46..9ace803d0a 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigProvider.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/config/provider/ConfigProvider.java @@ -2,8 +2,8 @@ import static com.datadog.trace.api.config.GeneralConfig.CONFIGURATION_FILE; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.io.File; import java.io.FileNotFoundException; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIUtils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIUtils.java index 8ce4dcd820..a50754cace 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIUtils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/bootstrap/instrumentation/api/URIUtils.java @@ -1,7 +1,7 @@ package com.datadog.trace.bootstrap.instrumentation.api; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.net.MalformedURLException; import java.net.URI; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RateByServiceTraceSampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RateByServiceTraceSampler.java index 295dca2f8d..ad21b3862b 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RateByServiceTraceSampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RateByServiceTraceSampler.java @@ -9,8 +9,8 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Function; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** * A rate sampler which maintains different sample rates per service+env name. diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RuleBasedTraceSampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RuleBasedTraceSampler.java index 9cf2784f33..70468663e5 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RuleBasedTraceSampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/RuleBasedTraceSampler.java @@ -13,8 +13,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public class RuleBasedTraceSampler> implements Sampler, PrioritySampler { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/Sampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/Sampler.java index a70a1d877d..11edd24f07 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/Sampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/Sampler.java @@ -11,8 +11,8 @@ import com.datadog.trace.core.CoreSpan; import java.util.Map; import java.util.Properties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** Main interface to sample a collection of traces. */ public interface Sampler { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SingleSpanSampler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SingleSpanSampler.java index 78a708b96c..37561e7d3b 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SingleSpanSampler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SingleSpanSampler.java @@ -8,8 +8,8 @@ import com.datadog.trace.core.util.SimpleRateLimiter; import java.util.ArrayList; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public interface SingleSpanSampler { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SpanSamplingRules.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SpanSamplingRules.java index c060664941..ba9ec88d8a 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SpanSamplingRules.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/SpanSamplingRules.java @@ -15,8 +15,8 @@ import java.util.List; import java.util.Map; import okio.Okio; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** Represents list of Span Sampling Rules read from JSON. See SPAN_SAMPLING_RULES */ public class SpanSamplingRules { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/TraceSamplingRules.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/TraceSamplingRules.java index 93c9cc0db0..de8d18572b 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/TraceSamplingRules.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/sampling/TraceSamplingRules.java @@ -10,8 +10,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** Represents list of Trace Sampling Rules read from JSON. See TRACE_SAMPLING_RULES */ public class TraceSamplingRules { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ListWriter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ListWriter.java index 9cec2d0d79..3de81bfb83 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ListWriter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/ListWriter.java @@ -10,8 +10,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** List writer used by tests mostly */ public class ListWriter extends CopyOnWriteArrayList> implements Writer { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/LoggingWriter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/LoggingWriter.java index b280b2bcc9..81d99af202 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/LoggingWriter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/LoggingWriter.java @@ -5,8 +5,8 @@ import com.squareup.moshi.Types; import com.datadog.trace.core.DDSpan; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public class LoggingWriter implements Writer { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java index 2726d9e683..2fe422ac3d 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/RemoteApi.java @@ -2,7 +2,7 @@ import com.datadog.trace.relocate.api.IOLogger; import java.io.IOException; -import org.slf4j.Logger; +import com.datadog.trace.logger.Logger; public abstract class RemoteApi { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/SpanSamplingWorker.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/SpanSamplingWorker.java index d3181f0cc6..d6e53ca04f 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/SpanSamplingWorker.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/SpanSamplingWorker.java @@ -14,8 +14,8 @@ import java.util.Queue; import org.jctools.queues.MessagePassingQueue; import org.jctools.queues.MpscBlockingConsumerArrayQueue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public interface SpanSamplingWorker extends AutoCloseable { static SpanSamplingWorker build( diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceProcessingWorker.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceProcessingWorker.java index b13448aba0..dc93720363 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceProcessingWorker.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceProcessingWorker.java @@ -19,8 +19,8 @@ import java.util.concurrent.TimeUnit; import org.jctools.queues.MessagePassingQueue; import org.jctools.queues.MpscBlockingConsumerArrayQueue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** * Worker which applies rules to traces and serializes the results. Upon completion, the serialized diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceStructureWriter.java b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceStructureWriter.java index 6b7998709b..74ee4c0b23 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceStructureWriter.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/common/writer/TraceStructureWriter.java @@ -13,8 +13,8 @@ import java.util.Locale; import java.util.Map; import java.util.regex.Pattern; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public class TraceStructureWriter implements Writer { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/CoreTracer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/CoreTracer.java index f48965f416..93a7b16827 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/CoreTracer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/CoreTracer.java @@ -91,8 +91,8 @@ import java.util.concurrent.TimeoutException; import java.util.zip.ZipOutputStream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** * Main entrypoint into the tracer implementation. In addition to implementing diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java index f1073f7270..560a02de9e 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpan.java @@ -37,8 +37,8 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** * Represents a period of time. Associated information is stored in the SpanContext. diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanContext.java index 0520f93348..2a5d5b5941 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanContext.java @@ -38,8 +38,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** * SpanContext represents Span state that must propagate to descendant Spans and across process diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanLink.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanLink.java index 060b6824a1..ec2775629c 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanLink.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/DDSpanLink.java @@ -15,8 +15,8 @@ import com.datadog.trace.core.propagation.PropagationTags; import java.util.List; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** This class holds helper methods to encode span links into span context. */ public class DDSpanLink extends SpanLink { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java index b285969c2c..70db988cf1 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTrace.java @@ -18,8 +18,8 @@ import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import androidx.annotation.NonNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** * This class implements the following data flow rules when a Span is finished: diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTraceBuffer.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTraceBuffer.java index 07b192706e..a9aec30a2a 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTraceBuffer.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/PendingTraceBuffer.java @@ -11,8 +11,8 @@ import java.util.concurrent.atomic.AtomicInteger; import org.jctools.queues.MessagePassingQueue; import org.jctools.queues.MpscBlockingConsumerArrayQueue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public abstract class PendingTraceBuffer implements AutoCloseable { private static final int BUFFER_SIZE = 1 << 12; // 4096 diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/StatusLogger.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/StatusLogger.java index f44e1c9de6..d715958476 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/StatusLogger.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/StatusLogger.java @@ -19,8 +19,8 @@ import java.net.Socket; import java.util.Map; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public final class StatusLogger extends JsonAdapter implements AgentTaskScheduler.Task, JsonAdapter.Factory { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamContextInjector.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamContextInjector.java index 26494f7d4d..659e66128b 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamContextInjector.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DataStreamContextInjector.java @@ -8,8 +8,8 @@ import com.datadog.trace.bootstrap.instrumentation.api.PathwayContext; import java.io.IOException; import java.util.LinkedHashMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public class DataStreamContextInjector { private static final Logger LOGGER = LoggerFactory.getLogger(DataStreamContextInjector.class); diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DefaultPathwayContext.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DefaultPathwayContext.java index 5827bbe14c..650b08afc8 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DefaultPathwayContext.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/datastreams/DefaultPathwayContext.java @@ -27,8 +27,8 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public class DefaultPathwayContext implements PathwayContext { private static final Logger log = LoggerFactory.getLogger(DefaultPathwayContext.class); diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/B3HttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/B3HttpCodec.java index d35074de68..b3260a6304 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/B3HttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/B3HttpCodec.java @@ -18,8 +18,8 @@ import java.util.List; import java.util.TreeMap; import java.util.function.Supplier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** A codec designed for HTTP transport via headers using B3 headers */ class B3HttpCodec { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/DatadogHttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/DatadogHttpCodec.java index 1e98911c13..bbe85076f1 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/DatadogHttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/DatadogHttpCodec.java @@ -21,8 +21,8 @@ import java.util.Map; import java.util.TreeMap; import java.util.function.Supplier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** A codec designed for HTTP transport via headers using Datadog headers */ class DatadogHttpCodec { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HaystackHttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HaystackHttpCodec.java index fa2ad45a88..56566eb526 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HaystackHttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HaystackHttpCodec.java @@ -15,8 +15,8 @@ import java.util.Map; import java.util.TreeMap; import java.util.function.Supplier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** * A codec designed for HTTP transport via headers using Haystack headers. diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HttpCodec.java index 7cd50af483..0bdb0f3024 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/HttpCodec.java @@ -22,8 +22,8 @@ import java.util.Map; import java.util.Set; import java.util.function.Supplier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public class HttpCodec { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/W3CHttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/W3CHttpCodec.java index c47530c4e7..bb43a08887 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/W3CHttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/W3CHttpCodec.java @@ -24,8 +24,8 @@ import java.util.Map; import java.util.TreeMap; import java.util.function.Supplier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** A codec designed for HTTP transport via headers using W3C traceparent and tracestate headers */ class W3CHttpCodec { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/XRayHttpCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/XRayHttpCodec.java index 25f644906b..0dadacfd38 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/XRayHttpCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/XRayHttpCodec.java @@ -20,8 +20,8 @@ import java.util.Map; import java.util.TreeMap; import java.util.function.Supplier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** * A codec designed for AWS requests using the {@code X-Amzn-Trace-Id} tracing header. diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java index ec2bc2ddac..a8b1271d02 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/DatadogPTagsCodec.java @@ -8,7 +8,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.IntPredicate; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.LoggerFactory; /** Captures configuration required for PropagationTags logic */ final class DatadogPTagsCodec extends PTagsCodec { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagKey.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagKey.java index 4d175fe51e..808c3388ea 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagKey.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagKey.java @@ -2,8 +2,8 @@ import com.datadog.trace.api.cache.DDCaches; import com.datadog.trace.api.cache.DDPartialKeyCache; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; final class TagKey extends TagElement { private static final Logger log = LoggerFactory.getLogger(TagKey.class); diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagValue.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagValue.java index ea946e57fa..48dda0b093 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagValue.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/TagValue.java @@ -2,8 +2,8 @@ import com.datadog.trace.api.cache.DDCaches; import com.datadog.trace.api.cache.DDPartialKeyCache; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; final class TagValue extends TagElement { private static final Logger log = LoggerFactory.getLogger(TagValue.class); diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java index f2ef7b9e4e..8e6d2cba8d 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java @@ -11,7 +11,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.IntPredicate; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.LoggerFactory; public class W3CPTagsCodec extends PTagsCodec { private static final RatelimitedLogger log = diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScopeManager.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScopeManager.java index cac32e99b9..4bbf2f7f34 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScopeManager.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/scopemanager/ContinuableScopeManager.java @@ -28,8 +28,8 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** * The primary ScopeManager. This class has ownership of the core ThreadLocal containing the diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/QueryObfuscator.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/QueryObfuscator.java index aea6ea83f4..94bb7aecf5 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/QueryObfuscator.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/tagprocessor/QueryObfuscator.java @@ -7,8 +7,8 @@ import com.datadog.trace.bootstrap.instrumentation.api.Tags; import com.datadog.trace.util.Strings; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public class QueryObfuscator implements TagsPostProcessor { diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SystemAccess.java b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SystemAccess.java index 6612012ae7..ecdb5bf709 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SystemAccess.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/core/util/SystemAccess.java @@ -1,8 +1,8 @@ package com.datadog.trace.core.util; import com.datadog.trace.api.Config; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public final class SystemAccess { private static final Logger log = LoggerFactory.getLogger(SystemAccess.class); diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/logger/ILoggerFactory.java b/features/dd-trace-core/src/main/java/com/datadog/trace/logger/ILoggerFactory.java new file mode 100644 index 0000000000..e072222e28 --- /dev/null +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/logger/ILoggerFactory.java @@ -0,0 +1,12 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.trace.logger; + +public interface ILoggerFactory { + + Logger getLogger(String name); +} diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/logger/Logger.java b/features/dd-trace-core/src/main/java/com/datadog/trace/logger/Logger.java new file mode 100644 index 0000000000..8fa40ae562 --- /dev/null +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/logger/Logger.java @@ -0,0 +1,42 @@ + +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.trace.logger; +public interface Logger { + public static String ROOT_LOGGER_NAME = "ROOT"; + public String getName(); + public void trace(String msg); + public void trace(String format, Object arg); + public void trace(String format, Object arg1, Object arg2); + public void trace(String format, Object... argArray); + public void trace(String msg, Throwable t); + public boolean isTraceEnabled(); + public boolean isInfoEnabled(); + public boolean isWarnEnabled(); + public boolean isErrorEnabled(); + public boolean isDebugEnabled(); + public void debug(String msg); + public void debug(String format, Object arg); + public void debug(String format, Object arg1, Object arg2); + public void debug(String format, Object... arguments); + public void debug(String msg, Throwable t); + public void info(String msg); + public void info(String format, Object arg); + public void info(String format, Object arg1, Object arg2); + public void info(String format, Object... arguments); + public void info(String msg, Throwable t); + public void warn(String msg); + public void warn(String format, Object arg); + public void warn(String format, Object arg1, Object arg2); + public void warn(String format, Object... arguments); + public void warn(String msg, Throwable t); + public void error(String msg); + public void error(String format, Object arg); + public void error(String format, Object arg1, Object arg2); + public void error(String format, Object... arguments); + public void error(String msg, Throwable t); +} diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/logger/LoggerFactory.java b/features/dd-trace-core/src/main/java/com/datadog/trace/logger/LoggerFactory.java new file mode 100644 index 0000000000..97e17f3e69 --- /dev/null +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/logger/LoggerFactory.java @@ -0,0 +1,27 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.trace.logger; + +public final class LoggerFactory { + + public static Logger getLogger(String name) { + return new NoOpLogger(); + } + + public static Logger getLogger(Class clazz) { + return new NoOpLogger(); + } + + public static ILoggerFactory getILoggerFactory() { + return new ILoggerFactory() { + @Override + public Logger getLogger(String name) { + return new NoOpLogger(); + } + }; + } +} diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/logger/NoOpLogger.java b/features/dd-trace-core/src/main/java/com/datadog/trace/logger/NoOpLogger.java new file mode 100644 index 0000000000..73f9454c4b --- /dev/null +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/logger/NoOpLogger.java @@ -0,0 +1,167 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.trace.logger; + + +// TODO: 04/03/2024 https://datadoghq.atlassian.net/browse/RUM-3405 Add a proper implementation here +public class NoOpLogger implements Logger { + + @Override + public boolean isDebugEnabled() { + return false; + } + + @Override + public String getName() { + return ""; + } + + @Override + public boolean isTraceEnabled() { + return false; + } + + @Override + public void trace(String msg) { + + } + + @Override + public void trace(String format, Object arg) { + + } + + @Override + public void trace(String format, Object arg1, Object arg2) { + + } + + @Override + public void trace(String format, Object... argArray) { + + } + + @Override + public void trace(String msg, Throwable t) { + + } + + @Override + public void debug(String msg) { + + } + + @Override + public void debug(String format, Object arg) { + + } + + @Override + public void debug(String format, Object arg1, Object arg2) { + + } + + @Override + public void debug(String format, Object... arguments) { + + } + + @Override + public void debug(String msg, Throwable t) { + + } + + @Override + public boolean isInfoEnabled() { + return false; + } + + @Override + public void info(String msg) { + + } + + @Override + public void info(String format, Object arg) { + + } + + @Override + public void info(String format, Object arg1, Object arg2) { + + } + + @Override + public void info(String format, Object... arguments) { + + } + + @Override + public void info(String msg, Throwable t) { + + } + + @Override + public boolean isWarnEnabled() { + return false; + } + + @Override + public void warn(String msg) { + + } + + @Override + public void warn(String format, Object arg) { + + } + + @Override + public void warn(String format, Object arg1, Object arg2) { + + } + + @Override + public void warn(String format, Object... arguments) { + + } + + @Override + public void warn(String msg, Throwable t) { + + } + + @Override + public boolean isErrorEnabled() { + return false; + } + + @Override + public void error(String msg) { + + } + + @Override + public void error(String format, Object arg) { + + } + + @Override + public void error(String format, Object arg1, Object arg2) { + + } + + @Override + public void error(String format, Object... arguments) { + + } + + @Override + public void error(String msg, Throwable t) { + + } +} diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/logging/GlobalLogLevelSwitcher.java b/features/dd-trace-core/src/main/java/com/datadog/trace/logging/GlobalLogLevelSwitcher.java index 6b95b9044f..707b763177 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/logging/GlobalLogLevelSwitcher.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/logging/GlobalLogLevelSwitcher.java @@ -1,8 +1,8 @@ package com.datadog.trace.logging; -import org.slf4j.ILoggerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.ILoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; public class GlobalLogLevelSwitcher implements LogLevelSwitcher { private static volatile LogLevelSwitcher INSTANCE = null; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/IOLogger.java b/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/IOLogger.java index 0116aba1bd..e070bd635d 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/IOLogger.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/IOLogger.java @@ -1,6 +1,6 @@ package com.datadog.trace.relocate.api; -import org.slf4j.Logger; +import com.datadog.trace.logger.Logger; import java.util.concurrent.TimeUnit; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/RatelimitedLogger.java b/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/RatelimitedLogger.java index c9582b23fc..bf4c032c29 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/RatelimitedLogger.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/relocate/api/RatelimitedLogger.java @@ -1,6 +1,6 @@ package com.datadog.trace.relocate.api; -import org.slf4j.Logger; +import com.datadog.trace.logger.Logger; import java.util.Locale; import java.util.concurrent.TimeUnit; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentTaskScheduler.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentTaskScheduler.java index accc46b4fd..eb663a4e64 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentTaskScheduler.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentTaskScheduler.java @@ -7,8 +7,8 @@ import static com.datadog.trace.util.AgentThreadFactory.AgentThread.TASK_SCHEDULER; import static com.datadog.trace.util.AgentThreadFactory.newAgentThread; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.lang.ref.WeakReference; import java.util.concurrent.DelayQueue; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentThreadFactory.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentThreadFactory.java index 6175eee643..8339a6432a 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentThreadFactory.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/AgentThreadFactory.java @@ -1,6 +1,6 @@ package com.datadog.trace.util; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.LoggerFactory; import java.util.concurrent.ThreadFactory; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/util/PidHelper.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/PidHelper.java index 1eb19b2625..4a32973360 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/util/PidHelper.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/PidHelper.java @@ -1,7 +1,7 @@ package com.datadog.trace.util; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.function.Supplier; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/util/ProcessUtils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/ProcessUtils.java index 5cee610490..0b1dd2aea9 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/util/ProcessUtils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/ProcessUtils.java @@ -2,8 +2,8 @@ import androidx.annotation.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.function.Supplier; diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/util/TraceUtils.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/TraceUtils.java index e95f979e62..b97e3b3477 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/util/TraceUtils.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/TraceUtils.java @@ -2,8 +2,8 @@ import static com.datadog.trace.util.Strings.truncate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; /** * Utility methods to normalize trace data. This normalization is recommended if the trace is sent diff --git a/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackWalkerFactory.java b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackWalkerFactory.java index 9146a387ea..932a89477d 100644 --- a/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackWalkerFactory.java +++ b/features/dd-trace-core/src/main/java/com/datadog/trace/util/stacktrace/StackWalkerFactory.java @@ -1,7 +1,7 @@ package com.datadog.trace.util.stacktrace; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.datadog.trace.logger.Logger; +import com.datadog.trace.logger.LoggerFactory; import java.util.Objects; import java.util.function.Supplier; diff --git a/features/dd-trace-core/transitiveDependencies b/features/dd-trace-core/transitiveDependencies index f7e3ae6ea6..9bd2e89457 100644 --- a/features/dd-trace-core/transitiveDependencies +++ b/features/dd-trace-core/transitiveDependencies @@ -12,7 +12,6 @@ org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.10 : 963 b org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10 : 969 b org.jetbrains.kotlin:kotlin-stdlib:1.8.10 : 1598 Kb org.jetbrains:annotations:13.0 : 17 Kb -org.slf4j:slf4j-api:1.7.30 : 40 Kb Total transitive dependencies size : 3 Mb diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9ea7443b64..348d16cb40 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -84,7 +84,6 @@ coroutines = "1.4.2" ktor = "1.6.0" # Otel -slf4j = "1.7.30" moshi = "1.11.0" jctools = "3.3.0" openTelemetry = "1.4.0" @@ -228,10 +227,9 @@ ktorNetty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" } ktorGson = { module = "io.ktor:ktor-gson", version.ref = "ktor" } # Otel -slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" } jctools = { module = "org.jctools:jctools-core", version.ref = "jctools" } -openTelemetry = { module = "io.opentelemetry:opentelemetry-api", version.ref = "openTelemetry" } +openTelemetryApi = { module = "io.opentelemetry:opentelemetry-api", version.ref = "openTelemetry" } desugarJdk = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugarJdk" } datadogSketchesJava = { module = "com.datadoghq:sketches-java", version.ref = "datatadogSketchesJava" } re2j = { module = "com.google.re2j:re2j", version.ref = "re2j" } diff --git a/instrumented/integration/proguard-rules.pro b/instrumented/integration/proguard-rules.pro index cfd2255066..4e37e4b66d 100644 --- a/instrumented/integration/proguard-rules.pro +++ b/instrumented/integration/proguard-rules.pro @@ -33,3 +33,6 @@ -dontwarn kotlin.Experimental$Level -dontwarn kotlin.Experimental +# Required because we are compiling the `dd-sdk-android-trace` module which depends on "io.opentelemetry.api" which +# uses google autovalue annotations +-dontwarn com.google.** From 195783bdd7cd8a72de5cbe499a14ee30ba6274b7 Mon Sep 17 00:00:00 2001 From: Nikita Ogorodnikov Date: Tue, 5 Mar 2024 15:45:57 +0100 Subject: [PATCH 08/55] Update ProGuard configuration --- sample/kotlin/build.gradle.kts | 4 ++++ sample/kotlin/proguard-rules.pro | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 sample/kotlin/proguard-rules.pro diff --git a/sample/kotlin/build.gradle.kts b/sample/kotlin/build.gradle.kts index 6138942810..3c378a46d7 100644 --- a/sample/kotlin/build.gradle.kts +++ b/sample/kotlin/build.gradle.kts @@ -131,6 +131,10 @@ android { } getByName("release") { + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) isMinifyEnabled = false if (e2ePassword != null) { signingConfig = signingConfigs.getByName("release") diff --git a/sample/kotlin/proguard-rules.pro b/sample/kotlin/proguard-rules.pro new file mode 100644 index 0000000000..d8ee6a9419 --- /dev/null +++ b/sample/kotlin/proguard-rules.pro @@ -0,0 +1,27 @@ +# This is generated automatically by the Android Gradle plugin. +-dontwarn io.netty.internal.tcnative.Buffer +-dontwarn io.netty.internal.tcnative.CertificateCallback +-dontwarn io.netty.internal.tcnative.CertificateVerifier +-dontwarn io.netty.internal.tcnative.Library +-dontwarn io.netty.internal.tcnative.SSL +-dontwarn io.netty.internal.tcnative.SSLContext +-dontwarn io.netty.internal.tcnative.SSLPrivateKeyMethod +-dontwarn io.netty.internal.tcnative.SSLSessionCache +-dontwarn io.netty.internal.tcnative.SessionTicketKey +-dontwarn io.netty.internal.tcnative.SniHostNameMatcher +-dontwarn org.apache.log4j.Level +-dontwarn org.apache.log4j.Logger +-dontwarn org.apache.log4j.Priority +-dontwarn org.apache.logging.log4j.Level +-dontwarn org.apache.logging.log4j.LogManager +-dontwarn org.apache.logging.log4j.Logger +-dontwarn org.apache.logging.log4j.message.MessageFactory +-dontwarn org.apache.logging.log4j.spi.ExtendedLogger +-dontwarn org.apache.logging.log4j.spi.ExtendedLoggerWrapper +-dontwarn org.eclipse.jetty.npn.NextProtoNego$ClientProvider +-dontwarn org.eclipse.jetty.npn.NextProtoNego$Provider +-dontwarn org.eclipse.jetty.npn.NextProtoNego$ServerProvider +-dontwarn org.eclipse.jetty.npn.NextProtoNego +-dontwarn org.slf4j.impl.StaticLoggerBinder +-dontwarn org.slf4j.impl.StaticMDCBinder +-dontwarn reactor.blockhound.integration.BlockHoundIntegration From 87e17bd16f568466f43c8f67bdd42aa3d27470be Mon Sep 17 00:00:00 2001 From: Marius Constantin Date: Tue, 5 Mar 2024 16:39:08 +0100 Subject: [PATCH 09/55] RUM-3394 Provide the OtelDataWriter to be used in the OtelTracer --- .../android/trace/OtelTracerProvider.kt | 2 +- .../android/trace/internal/TracingFeature.kt | 20 +- .../trace/internal/data/OtelTraceWriter.kt | 92 ++++++ .../trace/internal/data/TraceWriter.kt | 4 +- .../event/OtelDdSpanToSpanEventMapper.kt | 130 +++++++++ .../trace/OtelTracerBuilderProviderTest.kt | 36 ++- .../trace/internal/TracingFeatureTest.kt | 40 ++- .../internal/data/OtelTraceWriterTest.kt | 272 ++++++++++++++++++ .../trace/internal/data/TraceWriterTest.kt | 2 +- .../event/OtelDdSpanToSpanEventMapperTest.kt | 232 +++++++++++++++ .../android/utils/forge/Configurator.kt | 1 + .../utils/forge/CoreDDSpanForgeryFactory.kt | 81 ++++++ 12 files changed, 901 insertions(+), 11 deletions(-) create mode 100644 features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/OtelTraceWriter.kt create mode 100644 features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/domain/event/OtelDdSpanToSpanEventMapper.kt create mode 100644 features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/data/OtelTraceWriterTest.kt create mode 100644 features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/domain/event/OtelDdSpanToSpanEventMapperTest.kt create mode 100644 features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/CoreDDSpanForgeryFactory.kt diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/OtelTracerProvider.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/OtelTracerProvider.kt index 16c3284d69..70f6b6a7e9 100644 --- a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/OtelTracerProvider.kt +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/OtelTracerProvider.kt @@ -138,7 +138,7 @@ class OtelTracerProvider( val coreTracer = CoreTracer.CoreTracerBuilder() .withProperties(properties()) .serviceName(serviceName) - .writer(NoOpOtelWriter()) + .writer(tracingFeature?.otelDataWriter ?: NoOpOtelWriter()) .partialFlushMinSpans(partialFlushThreshold) .idGenerationStrategy(IdGenerationStrategy.fromName("SECURE_RANDOM", false)) .build() diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/TracingFeature.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/TracingFeature.kt index ddcb93c521..f756a51031 100644 --- a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/TracingFeature.kt +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/TracingFeature.kt @@ -13,9 +13,12 @@ import com.datadog.android.api.feature.StorageBackedFeature import com.datadog.android.api.net.RequestFactory import com.datadog.android.api.storage.FeatureStorageConfiguration import com.datadog.android.trace.event.SpanEventMapper +import com.datadog.android.trace.internal.data.NoOpOtelWriter import com.datadog.android.trace.internal.data.NoOpWriter +import com.datadog.android.trace.internal.data.OtelTraceWriter import com.datadog.android.trace.internal.data.TraceWriter import com.datadog.android.trace.internal.domain.event.DdSpanToSpanEventMapper +import com.datadog.android.trace.internal.domain.event.OtelDdSpanToSpanEventMapper import com.datadog.android.trace.internal.domain.event.SpanEventMapperWrapper import com.datadog.android.trace.internal.domain.event.SpanEventSerializer import com.datadog.android.trace.internal.net.TracesRequestFactory @@ -33,6 +36,7 @@ internal class TracingFeature constructor( ) : StorageBackedFeature { internal var dataWriter: Writer = NoOpWriter() + internal var otelDataWriter: com.datadog.trace.common.writer.Writer = NoOpOtelWriter() internal val initialized = AtomicBoolean(false) // region Feature @@ -41,6 +45,7 @@ internal class TracingFeature constructor( override fun onInitialize(appContext: Context) { dataWriter = createDataWriter(sdkCore) + otelDataWriter = createOtelDataWriter(sdkCore) initialized.set(true) } @@ -67,7 +72,20 @@ internal class TracingFeature constructor( val internalLogger = sdkCore.internalLogger return TraceWriter( sdkCore, - legacyMapper = DdSpanToSpanEventMapper(networkInfoEnabled), + ddSpanToSpanEventMapper = DdSpanToSpanEventMapper(networkInfoEnabled), + eventMapper = SpanEventMapperWrapper(spanEventMapper, internalLogger), + serializer = SpanEventSerializer(internalLogger), + internalLogger = internalLogger + ) + } + + private fun createOtelDataWriter( + sdkCore: FeatureSdkCore + ): com.datadog.trace.common.writer.Writer { + val internalLogger = sdkCore.internalLogger + return OtelTraceWriter( + sdkCore, + ddSpanToSpanEventMapper = OtelDdSpanToSpanEventMapper(networkInfoEnabled), eventMapper = SpanEventMapperWrapper(spanEventMapper, internalLogger), serializer = SpanEventSerializer(internalLogger), internalLogger = internalLogger diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/OtelTraceWriter.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/OtelTraceWriter.kt new file mode 100644 index 0000000000..72d680c863 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/OtelTraceWriter.kt @@ -0,0 +1,92 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.trace.internal.data + +import androidx.annotation.WorkerThread +import com.datadog.android.api.InternalLogger +import com.datadog.android.api.context.DatadogContext +import com.datadog.android.api.feature.Feature +import com.datadog.android.api.feature.FeatureSdkCore +import com.datadog.android.api.storage.EventBatchWriter +import com.datadog.android.api.storage.RawBatchEvent +import com.datadog.android.event.EventMapper +import com.datadog.android.event.NoOpEventMapper +import com.datadog.android.trace.internal.domain.event.ContextAwareMapper +import com.datadog.android.trace.internal.storage.ContextAwareSerializer +import com.datadog.android.trace.model.SpanEvent +import com.datadog.trace.common.writer.Writer +import com.datadog.trace.core.DDSpan +import java.util.Locale + +internal class OtelTraceWriter( + private val sdkCore: FeatureSdkCore, + internal val ddSpanToSpanEventMapper: ContextAwareMapper, + internal val eventMapper: EventMapper = NoOpEventMapper(), + private val serializer: ContextAwareSerializer, + private val internalLogger: InternalLogger +) : Writer { + + // region Writer + override fun start() { + // NO - OP + } + + override fun write(trace: MutableList?) { + if (trace == null) return + sdkCore.getFeature(Feature.TRACING_FEATURE_NAME) + ?.withWriteContext { datadogContext, eventBatchWriter -> + trace.forEach { span -> + @Suppress("ThreadSafety") // called in the worker context + writeSpan(datadogContext, eventBatchWriter, span) + } + } + } + + override fun flush(): Boolean { + // NO - OP + return true + } + + override fun incrementDropCounts(p0: Int) { + // NO - OP + } + + override fun close() { + // NO - OP + } + + // endregion + + @WorkerThread + private fun writeSpan( + datadogContext: DatadogContext, + writer: EventBatchWriter, + span: DDSpan + ) { + val spanEvent = ddSpanToSpanEventMapper.map(datadogContext, span) + val mapped = eventMapper.map(spanEvent) ?: return + try { + val serialized = serializer + .serialize(datadogContext, mapped) + ?.toByteArray(Charsets.UTF_8) ?: return + synchronized(this) { + writer.write(RawBatchEvent(data = serialized), batchMetadata = null) + } + } catch (@Suppress("TooGenericExceptionCaught") e: Throwable) { + internalLogger.log( + InternalLogger.Level.ERROR, + listOf(InternalLogger.Target.USER, InternalLogger.Target.TELEMETRY), + { ERROR_SERIALIZING.format(Locale.US, mapped.javaClass.simpleName) }, + e + ) + } + } + + companion object { + internal const val ERROR_SERIALIZING = "Error serializing %s model" + } +} diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/TraceWriter.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/TraceWriter.kt index 5801d8ed38..de65026a55 100644 --- a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/TraceWriter.kt +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/data/TraceWriter.kt @@ -23,7 +23,7 @@ import java.util.Locale internal class TraceWriter( private val sdkCore: FeatureSdkCore, - internal val legacyMapper: ContextAwareMapper, + internal val ddSpanToSpanEventMapper: ContextAwareMapper, internal val eventMapper: EventMapper, private val serializer: ContextAwareSerializer, private val internalLogger: InternalLogger @@ -61,7 +61,7 @@ internal class TraceWriter( writer: EventBatchWriter, span: DDSpan ) { - val spanEvent = legacyMapper.map(datadogContext, span) + val spanEvent = ddSpanToSpanEventMapper.map(datadogContext, span) val mapped = eventMapper.map(spanEvent) ?: return try { val serialized = serializer diff --git a/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/domain/event/OtelDdSpanToSpanEventMapper.kt b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/domain/event/OtelDdSpanToSpanEventMapper.kt new file mode 100644 index 0000000000..615dd4e8b8 --- /dev/null +++ b/features/dd-sdk-android-trace/src/main/kotlin/com/datadog/android/trace/internal/domain/event/OtelDdSpanToSpanEventMapper.kt @@ -0,0 +1,130 @@ +/* +* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +* This product includes software developed at Datadog (https://www.datadoghq.com/). +* Copyright 2016-Present Datadog, Inc. +*/ + +package com.datadog.android.trace.internal.domain.event + +import com.datadog.android.api.context.DatadogContext +import com.datadog.android.api.context.NetworkInfo +import com.datadog.android.core.internal.utils.toHexString +import com.datadog.android.log.LogAttributes +import com.datadog.android.trace.model.SpanEvent +import com.datadog.trace.core.DDSpan + +internal class OtelDdSpanToSpanEventMapper( + internal val networkInfoEnabled: Boolean +) : ContextAwareMapper { + + // region Mapper + + override fun map(datadogContext: DatadogContext, model: DDSpan): SpanEvent { + val serverOffset = datadogContext.time.serverTimeOffsetNs + val metrics = resolveMetrics(model) + val metadata = resolveMeta(datadogContext, model) + return SpanEvent( + // we remove the first part as we specifically set an IdGeneratorStrategy with + // 64bits length. Our current endpoint does not accept trace ids longer than 64bits + traceId = resolveTraceId(model), + spanId = model.spanId.toHexString(), + parentId = model.parentId.toHexString(), + resource = model.resourceName.toString(), // + name = model.operationName.toString(), // GET, POST, etc + service = model.serviceName, + duration = model.durationNano, + start = model.startTime + serverOffset, + error = model.error.toLong(), + meta = metadata, + metrics = metrics + ) + } + + // endregion + + // region internal + + private fun resolveTraceId(model: DDSpan): String { + // the argument will never be negative + @Suppress("UnsafeThirdPartyFunctionCall") + return model.traceId.toHexString().takeLast(RUM_ENDPOINT_REQUIRED_TRACE_ID_LENGTH) + } + + private fun resolveMetrics(event: DDSpan): SpanEvent.Metrics { + val metrics = resolveMetricsFromSpanContext(event).apply { + this["_dd.agent_psr"] = 1.0f + this["_sampling_priority_v1"] = 1 + } + return SpanEvent.Metrics( + topLevel = if (event.parentId == 0L) 1 else null, + additionalProperties = metrics + ) + } + + private fun resolveMeta(datadogContext: DatadogContext, event: DDSpan): SpanEvent.Meta { + val networkInfoMeta = if (networkInfoEnabled) { + val networkInfo = datadogContext.networkInfo + val simCarrier = resolveSimCarrier(networkInfo) + val networkInfoClient = SpanEvent.Client( + simCarrier = simCarrier, + signalStrength = networkInfo.strength?.toString(), + downlinkKbps = networkInfo.downKbps?.toString(), + uplinkKbps = networkInfo.upKbps?.toString(), + connectivity = networkInfo.connectivity.toString() + ) + SpanEvent.Network(networkInfoClient) + } else { + null + } + val userInfo = datadogContext.userInfo + val usrMeta = SpanEvent.Usr( + id = userInfo.id, + name = userInfo.name, + email = userInfo.email, + additionalProperties = userInfo.additionalProperties.toMutableMap() + ) + val dd = SpanEvent.Dd( + source = datadogContext.source, + application = event.tags[LogAttributes.RUM_APPLICATION_ID]?.let { SpanEvent.Application(it as? String) }, + session = event.tags[LogAttributes.RUM_SESSION_ID]?.let { SpanEvent.Session(it as? String) }, + view = event.tags[LogAttributes.RUM_VIEW_ID]?.let { SpanEvent.View(it as? String) } + ) + val tags = event.tags.mapValues { it.value.toString() } + val meta = (event.baggage + tags).toMutableMap() + return SpanEvent.Meta( + version = datadogContext.version, + dd = dd, + span = SpanEvent.Span(), + tracer = SpanEvent.Tracer( + version = datadogContext.sdkVersion + ), + usr = usrMeta, + network = networkInfoMeta, + additionalProperties = meta + ) + } + + private fun resolveSimCarrier(networkInfo: NetworkInfo): SpanEvent.SimCarrier? { + return if (networkInfo.carrierId != null || networkInfo.carrierName != null) { + SpanEvent.SimCarrier( + id = networkInfo.carrierId?.toString(), + name = networkInfo.carrierName + ) + } else { + null + } + } + + private fun resolveMetricsFromSpanContext(span: DDSpan): MutableMap { + return span.tags + .filterValues { it is Number } + .mapValues { it.value as Number } + .toMutableMap() + } + + // endregion + + companion object { + internal const val RUM_ENDPOINT_REQUIRED_TRACE_ID_LENGTH = 16 + } +} diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/OtelTracerBuilderProviderTest.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/OtelTracerBuilderProviderTest.kt index 717f031e7d..2bf8c83207 100644 --- a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/OtelTracerBuilderProviderTest.kt +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/OtelTracerBuilderProviderTest.kt @@ -11,6 +11,7 @@ import com.datadog.android.api.feature.Feature import com.datadog.android.api.feature.FeatureScope import com.datadog.android.api.feature.FeatureSdkCore import com.datadog.android.trace.internal.TracingFeature +import com.datadog.android.trace.internal.data.NoOpOtelWriter import com.datadog.android.trace.utils.verifyLog import com.datadog.android.utils.forge.Configurator import com.datadog.opentelemetry.trace.OtelSpan @@ -18,6 +19,7 @@ import com.datadog.opentelemetry.trace.OtelSpanContext import com.datadog.tools.unit.getFieldValue import com.datadog.trace.api.Config import com.datadog.trace.api.config.TracerConfig +import com.datadog.trace.common.writer.Writer import com.datadog.trace.core.CoreTracer import com.datadog.trace.core.DDSpanContext import fr.xgouchet.elmyr.Forge @@ -70,6 +72,9 @@ internal class OtelTracerBuilderProviderTest { @StringForgery lateinit var fakeInstrumentationName: String + @Mock + lateinit var mockTraceWriter: Writer + @BeforeEach fun `set up`(forge: Forge) { fakeServiceName = forge.anAlphabeticalString() @@ -80,6 +85,7 @@ internal class OtelTracerBuilderProviderTest { whenever(mockSdkCore.getFeature(Feature.RUM_FEATURE_NAME)) doReturn mock() whenever(mockSdkCore.service) doReturn fakeServiceName whenever(mockSdkCore.internalLogger) doReturn mockInternalLogger + whenever(mockTracingFeature.otelDataWriter) doReturn mockTraceWriter testedOtelTracerProviderBuilder = OtelTracerProvider.Builder(mockSdkCore) } @@ -91,9 +97,10 @@ internal class OtelTracerBuilderProviderTest { whenever(mockSdkCore.getFeature(Feature.TRACING_FEATURE_NAME)) doReturn null // WHEN - testedOtelTracerProviderBuilder.build() + val tracer = testedOtelTracerProviderBuilder.build() // THEN + assertThat(tracer).isNotNull mockInternalLogger.verifyLog( InternalLogger.Level.ERROR, InternalLogger.Target.USER, @@ -101,6 +108,33 @@ internal class OtelTracerBuilderProviderTest { ) } + @Test + fun `M use a NoOpOtelWriter W build { TracingFeature not enabled }`() { + // GIVEN + whenever(mockSdkCore.getFeature(Feature.TRACING_FEATURE_NAME)) doReturn null + + // WHEN + val tracer = testedOtelTracerProviderBuilder.build() + + // THEN + assertThat(tracer).isNotNull + val coreTracer: CoreTracer = tracer.getFieldValue("coreTracer") + val writer: Writer = coreTracer.getFieldValue("writer") + assertThat(writer).isInstanceOf(NoOpOtelWriter::class.java) + } + + @Test + fun `M use the feature writer W build { TracingFeature enabled }`() { + // WHEN + val tracer = testedOtelTracerProviderBuilder.build() + + // THEN + assertThat(tracer).isNotNull + val coreTracer: CoreTracer = tracer.getFieldValue("coreTracer") + val writer: Writer = coreTracer.getFieldValue("writer") + assertThat(writer).isSameAs(mockTraceWriter) + } + @Test fun `M log a user error W build { default service name not available }`() { // GIVEN diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/TracingFeatureTest.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/TracingFeatureTest.kt index cbe0b60f89..da42399225 100644 --- a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/TracingFeatureTest.kt +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/TracingFeatureTest.kt @@ -11,8 +11,10 @@ import com.datadog.android.api.feature.Feature import com.datadog.android.api.feature.FeatureSdkCore import com.datadog.android.api.storage.FeatureStorageConfiguration import com.datadog.android.trace.event.SpanEventMapper +import com.datadog.android.trace.internal.data.OtelTraceWriter import com.datadog.android.trace.internal.data.TraceWriter import com.datadog.android.trace.internal.domain.event.DdSpanToSpanEventMapper +import com.datadog.android.trace.internal.domain.event.OtelDdSpanToSpanEventMapper import com.datadog.android.trace.internal.domain.event.SpanEventMapperWrapper import com.datadog.android.trace.internal.net.TracesRequestFactory import com.datadog.android.utils.forge.Configurator @@ -71,7 +73,7 @@ internal class TracingFeatureTest { } @Test - fun `𝕄 initialize writer 𝕎 initialize()`() { + fun `𝕄 initialize opentracing writer 𝕎 initialize()`() { // When testedFeature.onInitialize(mock()) @@ -79,13 +81,29 @@ internal class TracingFeatureTest { assertThat(testedFeature.dataWriter) .isInstanceOf(TraceWriter::class.java) val traceWriter = testedFeature.dataWriter as TraceWriter - val legacyMapper = traceWriter.legacyMapper - assertThat(legacyMapper).isInstanceOf(DdSpanToSpanEventMapper::class.java) - assertThat((legacyMapper as DdSpanToSpanEventMapper).networkInfoEnabled).isEqualTo(fakeNetworkInfoEnabled) + val ddSpanToSpanEventMapper = traceWriter.ddSpanToSpanEventMapper + assertThat(ddSpanToSpanEventMapper).isInstanceOf(DdSpanToSpanEventMapper::class.java) + assertThat((ddSpanToSpanEventMapper as DdSpanToSpanEventMapper).networkInfoEnabled) + .isEqualTo(fakeNetworkInfoEnabled) } @Test - fun `𝕄 use the eventMapper 𝕎 initialize()`() { + fun `𝕄 initialize otel writer 𝕎 initialize()`() { + // When + testedFeature.onInitialize(mock()) + + // Then + assertThat(testedFeature.dataWriter) + .isInstanceOf(TraceWriter::class.java) + val traceWriter = testedFeature.otelDataWriter as OtelTraceWriter + val ddSpanToSpanEventMapper = traceWriter.ddSpanToSpanEventMapper + assertThat(ddSpanToSpanEventMapper).isInstanceOf(OtelDdSpanToSpanEventMapper::class.java) + assertThat((ddSpanToSpanEventMapper as OtelDdSpanToSpanEventMapper).networkInfoEnabled) + .isEqualTo(fakeNetworkInfoEnabled) + } + + @Test + fun `𝕄 use the eventMapper for opentracing writer 𝕎 initialize()`() { // When testedFeature.onInitialize(mock()) @@ -96,6 +114,18 @@ internal class TracingFeatureTest { assertThat(spanEventMapper).isSameAs(mockSpanEventMapper) } + @Test + fun `𝕄 use the eventMapper for otel writer 𝕎 initialize()`() { + // When + testedFeature.onInitialize(mock()) + + // Then + val dataWriter = testedFeature.otelDataWriter as? OtelTraceWriter + val spanEventMapperWrapper = dataWriter?.eventMapper as? SpanEventMapperWrapper + val spanEventMapper = spanEventMapperWrapper?.wrappedEventMapper + assertThat(spanEventMapper).isSameAs(mockSpanEventMapper) + } + @Test fun `𝕄 provide tracing feature name 𝕎 name()`() { // When+Then diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/data/OtelTraceWriterTest.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/data/OtelTraceWriterTest.kt new file mode 100644 index 0000000000..d40231e321 --- /dev/null +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/data/OtelTraceWriterTest.kt @@ -0,0 +1,272 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.trace.internal.data + +import com.datadog.android.api.InternalLogger +import com.datadog.android.api.context.DatadogContext +import com.datadog.android.api.feature.Feature +import com.datadog.android.api.feature.FeatureScope +import com.datadog.android.api.feature.FeatureSdkCore +import com.datadog.android.api.storage.EventBatchWriter +import com.datadog.android.api.storage.RawBatchEvent +import com.datadog.android.event.EventMapper +import com.datadog.android.trace.internal.domain.event.ContextAwareMapper +import com.datadog.android.trace.internal.storage.ContextAwareSerializer +import com.datadog.android.trace.model.SpanEvent +import com.datadog.android.trace.utils.verifyLog +import com.datadog.android.utils.forge.Configurator +import com.datadog.tools.unit.forge.aThrowable +import com.datadog.trace.core.DDSpan +import fr.xgouchet.elmyr.Forge +import fr.xgouchet.elmyr.annotation.Forgery +import fr.xgouchet.elmyr.junit5.ForgeConfiguration +import fr.xgouchet.elmyr.junit5.ForgeExtension +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.junit.jupiter.api.extension.Extensions +import org.mockito.Mock +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.junit.jupiter.MockitoSettings +import org.mockito.kotlin.any +import org.mockito.kotlin.doAnswer +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.doThrow +import org.mockito.kotlin.times +import org.mockito.kotlin.verify +import org.mockito.kotlin.verifyNoInteractions +import org.mockito.kotlin.verifyNoMoreInteractions +import org.mockito.kotlin.whenever +import org.mockito.quality.Strictness +import java.util.Locale + +@Extensions( + ExtendWith(MockitoExtension::class), + ExtendWith(ForgeExtension::class) +) +@MockitoSettings(strictness = Strictness.LENIENT) +@ForgeConfiguration(Configurator::class) +internal class OtelTraceWriterTest { + + private lateinit var testedWriter: OtelTraceWriter + + @Mock + lateinit var mockSdkCore: FeatureSdkCore + + @Mock + lateinit var mockLegacyMapper: ContextAwareMapper + + @Mock + lateinit var mockEventMapper: EventMapper + + @Mock + lateinit var mockSerializer: ContextAwareSerializer + + @Mock + lateinit var mockInternalLogger: InternalLogger + + @Mock + lateinit var mockTracingFeatureScope: FeatureScope + + @Mock + lateinit var mockEventBatchWriter: EventBatchWriter + + @Forgery + lateinit var fakeDatadogContext: DatadogContext + + // region Unit Tests + + @BeforeEach + fun `set up`() { + whenever( + mockSdkCore.getFeature(Feature.TRACING_FEATURE_NAME) + ) doReturn mockTracingFeatureScope + + whenever(mockTracingFeatureScope.withWriteContext(any(), any())) doAnswer { + val callback = it.getArgument<(DatadogContext, EventBatchWriter) -> Unit>(1) + callback.invoke(fakeDatadogContext, mockEventBatchWriter) + } + + whenever(mockEventMapper.map(any())) doAnswer { it.getArgument(0) } + + testedWriter = OtelTraceWriter( + sdkCore = mockSdkCore, + ddSpanToSpanEventMapper = mockLegacyMapper, + eventMapper = mockEventMapper, + serializer = mockSerializer, + internalLogger = mockInternalLogger + ) + } + + @Test + fun `M write spans W write()`(forge: Forge) { + // GIVEN + val ddSpans = forge.aList { getForgery() }.toMutableList() + val spanEvents = ddSpans.map { forge.getForgery() } + val serializedSpans = ddSpans.map { forge.aString() } + + ddSpans.forEachIndexed { index, ddSpan -> + whenever(mockLegacyMapper.map(fakeDatadogContext, ddSpan)) doReturn spanEvents[index] + } + + spanEvents.forEachIndexed { index, spanEvent -> + whenever( + mockSerializer.serialize(fakeDatadogContext, spanEvent) + ) doReturn serializedSpans[index] + } + + // WHEN + testedWriter.write(ddSpans) + + // THEN + serializedSpans.forEach { + verify(mockEventBatchWriter).write(RawBatchEvent(data = it.toByteArray()), null) + } + verifyNoMoreInteractions(mockEventBatchWriter) + } + + @Test + fun `M not write non-mapped spans W write()`(forge: Forge) { + // GIVEN + val ddSpans = forge.aList { getForgery() }.toMutableList() + val spanEvents = ddSpans.map { forge.getForgery() } + val mappedEvents = spanEvents.map { forge.aNullable { it } } + + val serializedSpans = mappedEvents.filterNotNull().map { forge.aString() } + + ddSpans.forEachIndexed { index, ddSpan -> + whenever(mockLegacyMapper.map(fakeDatadogContext, ddSpan)) doReturn spanEvents[index] + } + + spanEvents.forEachIndexed { index, event -> + whenever(mockEventMapper.map(event)) doReturn mappedEvents[index] + } + + mappedEvents.filterNotNull().forEachIndexed { index, spanEvent -> + whenever( + mockSerializer.serialize(fakeDatadogContext, spanEvent) + ) doReturn serializedSpans[index] + } + + // WHEN + testedWriter.write(ddSpans) + + // THEN + serializedSpans.forEach { + verify(mockEventBatchWriter).write(RawBatchEvent(data = it.toByteArray()), null) + } + verifyNoMoreInteractions(mockEventBatchWriter) + } + + @Test + fun `M not write non-serialized spans W write()`(forge: Forge) { + // GIVEN + val ddSpans = forge.aList { getForgery() }.toMutableList() + val spanEvents = ddSpans.map { forge.getForgery() } + + val serializedSpans = spanEvents.map { forge.aNullable { aString() } } + + ddSpans.forEachIndexed { index, ddSpan -> + whenever(mockLegacyMapper.map(fakeDatadogContext, ddSpan)) doReturn spanEvents[index] + } + + spanEvents.forEachIndexed { index, spanEvent -> + whenever( + mockSerializer.serialize(fakeDatadogContext, spanEvent) + ) doReturn serializedSpans[index] + } + + // WHEN + testedWriter.write(ddSpans) + + // THEN + serializedSpans.filterNotNull().forEach { + verify(mockEventBatchWriter).write(RawBatchEvent(data = it.toByteArray()), null) + } + verifyNoMoreInteractions(mockEventBatchWriter) + } + + @Test + fun `M do nothing W write() { null trace }`() { + // WHEN + testedWriter.write(null) + + // THEN + verifyNoInteractions( + mockEventBatchWriter, + mockEventMapper, + mockSerializer, + mockSdkCore, + mockLegacyMapper, + mockInternalLogger + ) + } + + @Test + fun `M log error and proceed W write() { serialization failed }`(forge: Forge) { + // GIVEN + val ddSpans = forge.aList { getForgery() }.toMutableList() + val spanEvents = ddSpans.map { forge.getForgery() } + val serializedSpans = ddSpans.map { forge.aString() } + + ddSpans.forEachIndexed { index, ddSpan -> + whenever(mockLegacyMapper.map(fakeDatadogContext, ddSpan)) doReturn spanEvents[index] + } + + val faultySpanIndex = forge.anInt(min = 0, max = spanEvents.size) + val fakeThrowable = forge.aThrowable() + spanEvents.forEachIndexed { index, spanEvent -> + if (index == faultySpanIndex) { + whenever( + mockSerializer.serialize( + fakeDatadogContext, + spanEvent + ) + ) doThrow fakeThrowable + } else { + whenever( + mockSerializer.serialize(fakeDatadogContext, spanEvent) + ) doReturn serializedSpans[index] + } + } + + // WHEN + testedWriter.write(ddSpans) + + // THEN + serializedSpans.forEachIndexed { index, serializedSpan -> + if (index != faultySpanIndex) { + verify(mockEventBatchWriter).write(RawBatchEvent(data = serializedSpan.toByteArray()), null) + } + } + verifyNoMoreInteractions(mockEventBatchWriter) + + mockInternalLogger.verifyLog( + InternalLogger.Level.ERROR, + listOf(InternalLogger.Target.USER, InternalLogger.Target.TELEMETRY), + TraceWriter.ERROR_SERIALIZING.format(Locale.US, SpanEvent::class.java.simpleName), + fakeThrowable + ) + } + + @Test + fun `M request event write context once W write()`(forge: Forge) { + // GIVEN + val ddSpans = forge.aList { getForgery() }.toMutableList() + + // WHEN + testedWriter.write(ddSpans) + + // THEN + verify(mockSdkCore, times(1)).getFeature(Feature.TRACING_FEATURE_NAME) + verify(mockTracingFeatureScope, times(1)).withWriteContext(any(), any()) + + verifyNoMoreInteractions(mockSdkCore, mockTracingFeatureScope) + } + + // endregion +} diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/data/TraceWriterTest.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/data/TraceWriterTest.kt index 45eb82da5e..96f7678fab 100644 --- a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/data/TraceWriterTest.kt +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/data/TraceWriterTest.kt @@ -95,7 +95,7 @@ internal class TraceWriterTest { testedWriter = TraceWriter( sdkCore = mockSdkCore, - legacyMapper = mockLegacyMapper, + ddSpanToSpanEventMapper = mockLegacyMapper, eventMapper = mockEventMapper, serializer = mockSerializer, internalLogger = mockInternalLogger diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/domain/event/OtelDdSpanToSpanEventMapperTest.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/domain/event/OtelDdSpanToSpanEventMapperTest.kt new file mode 100644 index 0000000000..4df50869ec --- /dev/null +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/trace/internal/domain/event/OtelDdSpanToSpanEventMapperTest.kt @@ -0,0 +1,232 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.trace.internal.domain.event + +import com.datadog.android.api.context.DatadogContext +import com.datadog.android.core.internal.utils.toHexString +import com.datadog.android.log.LogAttributes +import com.datadog.android.trace.assertj.SpanEventAssert.Companion.assertThat +import com.datadog.android.utils.forge.Configurator +import com.datadog.trace.api.DD128bTraceId +import com.datadog.trace.core.DDSpan +import fr.xgouchet.elmyr.Forge +import fr.xgouchet.elmyr.annotation.BoolForgery +import fr.xgouchet.elmyr.annotation.Forgery +import fr.xgouchet.elmyr.annotation.StringForgery +import fr.xgouchet.elmyr.junit5.ForgeConfiguration +import fr.xgouchet.elmyr.junit5.ForgeExtension +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.junit.jupiter.api.extension.Extensions +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.junit.jupiter.MockitoSettings +import org.mockito.kotlin.whenever +import org.mockito.quality.Strictness + +@Extensions( + ExtendWith(MockitoExtension::class), ExtendWith(ForgeExtension::class) +) +@MockitoSettings(strictness = Strictness.LENIENT) +@ForgeConfiguration(Configurator::class) +internal class OtelDdSpanToSpanEventMapperTest { + + lateinit var testedMapper: OtelDdSpanToSpanEventMapper + + @Forgery + lateinit var fakeDatadogContext: DatadogContext + + @BoolForgery + var fakeNetworkInfoEnabled: Boolean = false + + // region Tests + + @BeforeEach + fun `set up`() { + testedMapper = OtelDdSpanToSpanEventMapper(fakeNetworkInfoEnabled) + } + + @Test + fun `M map a DdSpan to a SpanEvent W map()`( + @Forgery fakeSpan: DDSpan + ) { + // Given + val expectedMeta = fakeSpan.baggage + fakeSpan.tags.map { + it.key to it.value.toString() + } + val expectedMetrics = fakeSpan.expectedMetrics() + + // When + val event = testedMapper.map(fakeDatadogContext, fakeSpan) + + // Then + assertThat(event).hasSpanId(fakeSpan.spanId.toHexString()) + .hasTraceId(fakeSpan.traceId.toHexString().substring(16)) + .hasParentId(fakeSpan.parentId.toHexString()) + .hasServiceName(fakeSpan.serviceName) + .hasOperationName(fakeSpan.operationName.toString()) + .hasResourceName(fakeSpan.resourceName.toString()) + .hasSpanType("custom") + .hasSpanSource(fakeDatadogContext.source) + .hasApplicationId(null) + .hasSessionId(null) + .hasViewId(null) + .hasErrorFlag(fakeSpan.error.toLong()) + .hasSpanStartTime(fakeSpan.startTime + fakeDatadogContext.time.serverTimeOffsetNs) + .hasSpanDuration(fakeSpan.durationNano) + .hasTracerVersion(fakeDatadogContext.sdkVersion) + .hasClientPackageVersion(fakeDatadogContext.version).apply { + if (fakeNetworkInfoEnabled) { + hasNetworkInfo(fakeDatadogContext.networkInfo) + } else { + doesntHaveNetworkInfo() + } + } + .hasUserInfo(fakeDatadogContext.userInfo) + .hasMeta(expectedMeta) + .hasMetrics(expectedMetrics) + } + + @Test + fun `M make sure the traceId is always a 16 characters length hexa W map()`( + @Forgery fakeSpan: DDSpan, + forge: Forge + ) { + // Given + // we will generate a traceId with a length of 128 bits + val fakeTraceId = DD128bTraceId.from((forge.aLong() + 1), (forge.aLong() + 1)) + val expectedMeta = fakeSpan.baggage + fakeSpan.tags.map { + it.key to it.value.toString() + } + whenever(fakeSpan.traceId).thenReturn(fakeTraceId) + val expectedMetrics = fakeSpan.expectedMetrics() + + // When + val event = testedMapper.map(fakeDatadogContext, fakeSpan) + + // Then + assertThat(event) + .hasSpanId(fakeSpan.spanId.toHexString()) + .hasTraceId(fakeSpan.traceId.toHexString().substring(16)) + .hasParentId(fakeSpan.parentId.toHexString()) + .hasServiceName(fakeSpan.serviceName) + .hasOperationName(fakeSpan.operationName.toString()) + .hasResourceName(fakeSpan.resourceName.toString()) + .hasSpanType("custom") + .hasSpanSource(fakeDatadogContext.source) + .hasApplicationId(null) + .hasSessionId(null) + .hasViewId(null) + .hasErrorFlag(fakeSpan.error.toLong()) + .hasSpanStartTime(fakeSpan.startTime + fakeDatadogContext.time.serverTimeOffsetNs) + .hasSpanDuration(fakeSpan.durationNano) + .hasTracerVersion(fakeDatadogContext.sdkVersion) + .hasClientPackageVersion(fakeDatadogContext.version).apply { + if (fakeNetworkInfoEnabled) { + hasNetworkInfo(fakeDatadogContext.networkInfo) + } else { + doesntHaveNetworkInfo() + } + } + .hasUserInfo(fakeDatadogContext.userInfo) + .hasMeta(expectedMeta) + .hasMetrics(expectedMetrics) + } + + @Test + fun `M map a DdSpan to a SpanEvent with RUM info W map() {RUM info present}`( + @Forgery fakeSpan: DDSpan, + @StringForgery fakeApplicationId: String, + @StringForgery fakeSessionId: String, + @StringForgery fakeViewId: String + ) { + // Given + val tags = fakeSpan.tags.toMutableMap().apply { + this[LogAttributes.RUM_APPLICATION_ID] = fakeApplicationId + this[LogAttributes.RUM_SESSION_ID] = fakeSessionId + this[LogAttributes.RUM_VIEW_ID] = fakeViewId + } + whenever(fakeSpan.tags).thenReturn(tags) + whenever(fakeSpan.context().tags).thenReturn(tags) + + // Given + val expectedMeta = fakeSpan.baggage + fakeSpan.tags.map { + it.key to it.value.toString() + } + val expectedMetrics = fakeSpan.expectedMetrics() + + // When + val event = testedMapper.map(fakeDatadogContext, fakeSpan) + + // Then + assertThat(event).hasSpanId(fakeSpan.spanId.toHexString()) + .hasTraceId(fakeSpan.traceId.toHexString().substring(16)) + .hasParentId(fakeSpan.parentId.toHexString()) + .hasServiceName(fakeSpan.serviceName) + .hasOperationName(fakeSpan.operationName.toString()) + .hasResourceName(fakeSpan.resourceName.toString()) + .hasSpanType("custom") + .hasSpanSource(fakeDatadogContext.source) + .hasApplicationId(fakeApplicationId) + .hasSessionId(fakeSessionId) + .hasViewId(fakeViewId) + .hasErrorFlag(fakeSpan.error.toLong()) + .hasSpanStartTime(fakeSpan.startTime + fakeDatadogContext.time.serverTimeOffsetNs) + .hasSpanDuration(fakeSpan.durationNano) + .hasTracerVersion(fakeDatadogContext.sdkVersion) + .hasClientPackageVersion(fakeDatadogContext.version).apply { + if (fakeNetworkInfoEnabled) { + hasNetworkInfo(fakeDatadogContext.networkInfo) + } else { + doesntHaveNetworkInfo() + } + }.hasUserInfo(fakeDatadogContext.userInfo) + .hasMeta(expectedMeta) + .hasMetrics(expectedMetrics) + } + + @Test + fun `M mark the SpanEvent as top span W map() { parentId is 0 }`( + @Forgery fakeSpan: DDSpan + ) { + // Given + whenever(fakeSpan.parentId).thenReturn(0L) + + // When + val event = testedMapper.map(fakeDatadogContext, fakeSpan) + + // Then + assertThat(event).isTopSpan() + } + + @Test + fun `M not mark the SpanEvent as top span W map() { parentId is different than 0 }`( + forge: Forge, @Forgery fakeSpan: DDSpan + ) { + // Given + whenever(fakeSpan.parentId).thenReturn(forge.aLong(min = 1)) + + // When + val event = testedMapper.map(fakeDatadogContext, fakeSpan) + + // Then + assertThat(event).isNotTopSpan() + } + + // endregion + + // region Internal + + private fun DDSpan.expectedMetrics(): Map { + return tags.filterValues { it is Number }.mapValues { it.value as Number }.toMutableMap().apply { + this["_dd.agent_psr"] = 1.0f + this["_sampling_priority_v1"] = 1 + } + } + + // endregion +} diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/Configurator.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/Configurator.kt index bd722164f0..46841a0d06 100644 --- a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/Configurator.kt +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/Configurator.kt @@ -22,6 +22,7 @@ internal class Configurator : BaseConfigurator() { forge.addFactory(SpanForgeryFactory()) forge.addFactory(SpanEventForgeryFactory()) forge.addFactory(TraceConfigurationForgeryFactory()) + forge.addFactory(CoreDDSpanForgeryFactory()) // MISC forge.addFactory(BigIntegerFactory()) diff --git a/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/CoreDDSpanForgeryFactory.kt b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/CoreDDSpanForgeryFactory.kt new file mode 100644 index 0000000000..cfed4fd31a --- /dev/null +++ b/features/dd-sdk-android-trace/src/test/kotlin/com/datadog/android/utils/forge/CoreDDSpanForgeryFactory.kt @@ -0,0 +1,81 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.utils.forge + +import com.datadog.trace.api.DDTraceId +import com.datadog.trace.core.DDSpan +import com.datadog.trace.core.DDSpanContext +import fr.xgouchet.elmyr.Forge +import fr.xgouchet.elmyr.ForgeryFactory +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever + +internal class CoreDDSpanForgeryFactory : ForgeryFactory { + + override fun getForgery(forge: Forge): DDSpan { + val baggageItems = forge.exhaustiveMeta() + val tags = forge.exhaustiveTraceTags() + val metrics = forge.exhaustiveMetrics() + val operationName = forge.anAlphabeticalString() + val resourceName = forge.anAlphabeticalString() + val serviceName = forge.anAlphabeticalString() + val spanType = forge.anAlphabeticalString() + val spanStartTime = forge.aPositiveLong() + val spanDuration = forge.aPositiveLong() + val traceId = forge.aLong(min = 1) + val spanId = forge.aLong(min = 1) + val parentId = forge.aLong(min = 1) + val tagsAndMetrics = tags + metrics + val mockSpanContext: DDSpanContext = mock { + whenever(it.baggageItems).thenReturn(baggageItems) + whenever(it.tags).thenReturn(tagsAndMetrics) + } + val mockDDSpan: DDSpan = mock { + whenever(it.context()).thenReturn(mockSpanContext) + whenever(it.serviceName).thenReturn(serviceName) + whenever(it.operationName).thenReturn(operationName) + whenever(it.resourceName).thenReturn(resourceName) + whenever(it.spanType).thenReturn(spanType) + whenever(it.error).thenReturn(forge.anInt()) + whenever(it.startTime).thenReturn(spanStartTime) + whenever(it.durationNano).thenReturn(spanDuration) + whenever(it.spanId).thenReturn(spanId) + whenever(it.traceId).thenReturn(DDTraceId.from(traceId)) + whenever(it.parentId).thenReturn(parentId) + whenever(it.baggage).thenReturn(baggageItems) + whenever(it.tags).thenReturn(tagsAndMetrics) + } + return mockDDSpan + } + + private fun Forge.exhaustiveTraceTags(): Map { + return listOf( + aBool(), + anInt(), + aLong(), + aFloat(), + aDouble(), + anAsciiString() + ).map { anAlphabeticalString() to it } + .toMap() + } + + private fun Forge.exhaustiveMetrics(): Map { + return listOf( + aLong(), + anInt(), + aFloat(), + aDouble() + ).associate { anAlphabeticalString() to it as Number } + } + + private fun Forge.exhaustiveMeta(): Map { + return listOf( + aString() + ).associateBy { anAlphabeticalString() } + } +} From f18d5275db7737ab821e366f36b74f29d98edab3 Mon Sep 17 00:00:00 2001 From: Marius Constantin Date: Wed, 6 Mar 2024 17:41:57 +0100 Subject: [PATCH 10/55] RUM-3415 Sample app - add AsyncTask Otel trace use case --- .../android/sample/SampleApplication.kt | 16 +++ .../android/sample/ViewModelFactory.kt | 4 + .../android/sample/home/HomeFragment.kt | 1 + .../sample/traces/OtelTracesFragment.kt | 72 +++++++++++ .../sample/traces/OtelTracesViewModel.kt | 114 ++++++++++++++++++ .../baseline_radio_button_unchecked_24.xml | 11 ++ .../src/main/res/layout/fragment_home.xml | 13 +- .../main/res/layout/fragment_otel_traces.xml | 51 ++++++++ .../src/main/res/navigation/nav_graph.xml | 4 + sample/kotlin/src/main/res/values/strings.xml | 3 +- 10 files changed, 287 insertions(+), 2 deletions(-) create mode 100644 sample/kotlin/src/main/kotlin/com/datadog/android/sample/traces/OtelTracesFragment.kt create mode 100644 sample/kotlin/src/main/kotlin/com/datadog/android/sample/traces/OtelTracesViewModel.kt create mode 100644 sample/kotlin/src/main/res/drawable/baseline_radio_button_unchecked_24.xml create mode 100644 sample/kotlin/src/main/res/layout/fragment_otel_traces.xml diff --git a/sample/kotlin/src/main/kotlin/com/datadog/android/sample/SampleApplication.kt b/sample/kotlin/src/main/kotlin/com/datadog/android/sample/SampleApplication.kt index ab2880a323..4bac205868 100644 --- a/sample/kotlin/src/main/kotlin/com/datadog/android/sample/SampleApplication.kt +++ b/sample/kotlin/src/main/kotlin/com/datadog/android/sample/SampleApplication.kt @@ -46,6 +46,7 @@ import com.datadog.android.sessionreplay.SessionReplayConfiguration import com.datadog.android.sessionreplay.material.MaterialExtensionSupport import com.datadog.android.timber.DatadogTree import com.datadog.android.trace.AndroidTracer +import com.datadog.android.trace.OtelTracerProvider import com.datadog.android.trace.Trace import com.datadog.android.trace.TraceConfiguration import com.datadog.android.vendor.sample.LocalServer @@ -53,6 +54,9 @@ import com.facebook.stetho.Stetho import com.google.gson.GsonBuilder import com.google.gson.JsonArray import com.google.gson.JsonObject +import io.opentelemetry.api.GlobalOpenTelemetry +import io.opentelemetry.api.OpenTelemetry +import io.opentelemetry.context.propagation.ContextPropagators import io.opentracing.rxjava3.TracingRxJava3Utils import io.opentracing.util.GlobalTracer import okhttp3.OkHttpClient @@ -181,6 +185,17 @@ class SampleApplication : Application() { .setService(BuildConfig.APPLICATION_ID) .build() ) + GlobalOpenTelemetry.set(object : OpenTelemetry { + override fun getTracerProvider(): OtelTracerProvider { + return OtelTracerProvider.Builder() + .setService(BuildConfig.APPLICATION_ID) + .build() + } + + override fun getPropagators(): ContextPropagators { + return ContextPropagators.noop() + } + }) GlobalRumMonitor.get().debug = true TracingRxJava3Utils.enableTracing(GlobalTracer.get()) } @@ -285,6 +300,7 @@ class SampleApplication : Application() { companion object { private const val SAMPLE_IN_ALL_SESSIONS = 100f + init { System.loadLibrary("datadog-native-sample-lib") } diff --git a/sample/kotlin/src/main/kotlin/com/datadog/android/sample/ViewModelFactory.kt b/sample/kotlin/src/main/kotlin/com/datadog/android/sample/ViewModelFactory.kt index bd615580c5..165fb02b6a 100644 --- a/sample/kotlin/src/main/kotlin/com/datadog/android/sample/ViewModelFactory.kt +++ b/sample/kotlin/src/main/kotlin/com/datadog/android/sample/ViewModelFactory.kt @@ -12,6 +12,7 @@ import com.datadog.android.sample.data.DataRepository import com.datadog.android.sample.data.db.LocalDataSource import com.datadog.android.sample.data.remote.RemoteDataSource import com.datadog.android.sample.datalist.DataListViewModel +import com.datadog.android.sample.traces.OtelTracesViewModel import com.datadog.android.sample.traces.TracesViewModel import com.datadog.android.sample.webview.WebViewModel import com.datadog.android.vendor.sample.LocalServer @@ -39,6 +40,9 @@ internal class ViewModelFactory( WebViewModel::class.java -> { WebViewModel(localServer) as T } + OtelTracesViewModel::class.java -> { + OtelTracesViewModel() as T + } else -> { modelClass.newInstance() } diff --git a/sample/kotlin/src/main/kotlin/com/datadog/android/sample/home/HomeFragment.kt b/sample/kotlin/src/main/kotlin/com/datadog/android/sample/home/HomeFragment.kt index fb596b2dcb..bf4cb1fc84 100644 --- a/sample/kotlin/src/main/kotlin/com/datadog/android/sample/home/HomeFragment.kt +++ b/sample/kotlin/src/main/kotlin/com/datadog/android/sample/home/HomeFragment.kt @@ -57,6 +57,7 @@ internal class HomeFragment : R.id.navigation_logs -> R.id.fragment_logs R.id.navigation_crash -> R.id.fragment_crash R.id.navigation_traces -> R.id.fragment_trace + R.id.navigation_otel_traces -> R.id.fragment_otel_traces R.id.navigation_vitals -> R.id.fragment_vitals R.id.navigation_webview -> R.id.fragment_webview R.id.navigation_data_list -> R.id.fragment_data_list diff --git a/sample/kotlin/src/main/kotlin/com/datadog/android/sample/traces/OtelTracesFragment.kt b/sample/kotlin/src/main/kotlin/com/datadog/android/sample/traces/OtelTracesFragment.kt new file mode 100644 index 0000000000..8bda10a48f --- /dev/null +++ b/sample/kotlin/src/main/kotlin/com/datadog/android/sample/traces/OtelTracesFragment.kt @@ -0,0 +1,72 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.sample.traces + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.ProgressBar +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProviders +import com.datadog.android.sample.R +import com.datadog.android.sample.SampleApplication + +internal class OtelTracesFragment : Fragment(), View.OnClickListener { + + lateinit var viewModel: OtelTracesViewModel + lateinit var progressBarAsync: ProgressBar + + // region Fragment + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val rootView = inflater.inflate(R.layout.fragment_otel_traces, container, false) + rootView.findViewById