From 378d44211949117eef2eb7f1b00ba2ff8e46841e Mon Sep 17 00:00:00 2001 From: Nayeem Kamal Date: Tue, 29 Jul 2025 14:38:33 -0400 Subject: [PATCH 1/7] added apm openai instrumentation --- .../instrumentation/openai/build.gradle | 29 + .../instrumentation/openai/gradle.lockfile | 4 + .../ChatCompletionServiceInstrumentation.java | 83 +++ .../CompletionServiceInstrumentation.java | 80 +++ .../EmbeddingServiceInstrumentation.java | 71 +++ .../openai/OpenAIClientDecorator.java | 303 ++++++++++ .../openai/OpenAIClientInfo.java | 88 +++ .../openai/OpenAIClientInstrumentation.java | 74 +++ settings.gradle | 565 ++++++++++++++++++ 9 files changed, 1297 insertions(+) create mode 100644 dd-java-agent/instrumentation/openai/build.gradle create mode 100644 dd-java-agent/instrumentation/openai/gradle.lockfile create mode 100644 dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java create mode 100644 dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java create mode 100644 dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java create mode 100644 dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java create mode 100644 dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java create mode 100644 dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java create mode 100644 settings.gradle diff --git a/dd-java-agent/instrumentation/openai/build.gradle b/dd-java-agent/instrumentation/openai/build.gradle new file mode 100644 index 00000000000..ebc49e827ea --- /dev/null +++ b/dd-java-agent/instrumentation/openai/build.gradle @@ -0,0 +1,29 @@ +muzzle { + pass { + group = "com.openai" + module = "openai-java" + versions = "[2.8.0,)" + assertInverse = true + } +} + +// Instrumentation is currently in preview. Additional testing will be implemented before enabling this by default. +//minimumBranchCoverage = 0.0 +//minimumInstructionCoverage = 0.0 + +apply from: "$rootDir/gradle/java.gradle" + +addTestSuiteForDir('latestDepTest', 'test') + +dependencies { + compileOnly(group: 'com.openai', name: 'openai-java', version: '2.8.1') + + testImplementation(group: 'com.openai', name: 'openai-java') { + version { + strictly '[2.8.0,)' + } + } + + latestDepTestImplementation group: 'com.openai', name: 'openai-java', version: '+' + +} diff --git a/dd-java-agent/instrumentation/openai/gradle.lockfile b/dd-java-agent/instrumentation/openai/gradle.lockfile new file mode 100644 index 00000000000..09cf7528a00 --- /dev/null +++ b/dd-java-agent/instrumentation/openai/gradle.lockfile @@ -0,0 +1,4 @@ +# This is a Gradle generated file for dependency locking. +# This file is expected to be part of source control. +# Manual entries are allowed. +empty= \ No newline at end of file diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java new file mode 100644 index 00000000000..1fb2bffe8cd --- /dev/null +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java @@ -0,0 +1,83 @@ +package datadog.trace.instrumentation.openai; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface; +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.*; +import static net.bytebuddy.matcher.ElementMatchers.isPublic; + +import com.openai.models.chat.completions.ChatCompletionCreateParams; +import com.openai.services.blocking.CompletionService; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.InstrumentationContext; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import java.util.HashMap; +import java.util.Map; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class ChatCompletionServiceInstrumentation extends InstrumenterModule.Tracing + implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice { + public ChatCompletionServiceInstrumentation() { + super("openai-client"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + packageName + ".OpenAIClientInfo", + }; + } + + @Override + public Map contextStore() { + Map contextStores = new HashMap<>(1); + contextStores.put( + "com.openai.services.blocking.CompletionService", OpenAIClientInfo.class.getName()); + return contextStores; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isMethod() + .and(isPublic()) + .and(named("create")) + .and( + takesArgument( + 0, named("com.openai.models.completions.ChatCompletionCreateParams"))), + getClass().getName() + "$CompletionServiceAdvice"); + } + + @Override + public String hierarchyMarkerType() { + return "com.openai.services.blocking.chat.ChatCompletionService"; + } + + @Override + public ElementMatcher hierarchyMatcher() { + return implementsInterface(named(hierarchyMarkerType())); + } + + public static class CompletionServiceAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static AgentScope methodEnter( + @Advice.Argument(0) final ChatCompletionCreateParams params) { + + return OpenAIClientDecorator.DECORATE.startChatCompletionSpan(params); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void methodExit( + @Advice.Enter final AgentScope span, + @Advice.This final CompletionService completionService, + @Advice.Return final Object result, + @Advice.Thrown final Throwable throwable) { + OpenAIClientInfo info = + InstrumentationContext.get(CompletionService.class, OpenAIClientInfo.class) + .get(completionService); + OpenAIClientDecorator.DECORATE.finishSpan(span, result, throwable); + } + } +} diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java new file mode 100644 index 00000000000..72ea7014a29 --- /dev/null +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java @@ -0,0 +1,80 @@ +package datadog.trace.instrumentation.openai; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface; +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.*; +import static net.bytebuddy.matcher.ElementMatchers.isPublic; + +import com.openai.models.completions.CompletionCreateParams; +import com.openai.services.blocking.CompletionService; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.InstrumentationContext; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import java.util.HashMap; +import java.util.Map; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class CompletionServiceInstrumentation extends InstrumenterModule.Tracing + implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice { + public CompletionServiceInstrumentation() { + super("openai-client"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + packageName + ".OpenAIClientInfo", + }; + } + + @Override + public Map contextStore() { + Map contextStores = new HashMap<>(1); + contextStores.put( + "com.openai.services.blocking.CompletionService", OpenAIClientInfo.class.getName()); + return contextStores; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isMethod() + .and(isPublic()) + .and(named("create")) + .and(takesArgument(0, named("com.openai.models.completions.CompletionCreateParams"))), + getClass().getName() + "$CompletionServiceAdvice"); + } + + @Override + public String hierarchyMarkerType() { + return "com.openai.services.blocking.CompletionService"; + } + + @Override + public ElementMatcher hierarchyMatcher() { + return implementsInterface(named(hierarchyMarkerType())); + } + + public static class CompletionServiceAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static AgentScope methodEnter(@Advice.Argument(0) final CompletionCreateParams params) { + + return OpenAIClientDecorator.DECORATE.startCompletionSpan(params); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void methodExit( + @Advice.Enter final AgentScope span, + @Advice.This final CompletionService completionService, + @Advice.Return final Object result, + @Advice.Thrown final Throwable throwable) { + OpenAIClientInfo info = + InstrumentationContext.get(CompletionService.class, OpenAIClientInfo.class) + .get(completionService); + OpenAIClientDecorator.DECORATE.finishSpan(span, result, throwable); + } + } +} diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java new file mode 100644 index 00000000000..afe8cc34db0 --- /dev/null +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java @@ -0,0 +1,71 @@ +package datadog.trace.instrumentation.openai; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface; +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.isPublic; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import com.google.auto.service.AutoService; +import com.openai.models.embeddings.EmbeddingCreateParams; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +@AutoService(InstrumenterModule.class) +public class EmbeddingServiceInstrumentation extends InstrumenterModule.Tracing + implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice { + + public EmbeddingServiceInstrumentation() { + super("openai", "openai-java"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + packageName + ".OpenAIDecorator", + }; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + // Instrument embedding creation methods + transformer.applyAdvice( + isMethod() + .and(named("create")) + .and(isPublic()) + .and(takesArgument(0, named("com.openai.models.embeddings.EmbeddingCreateParams"))), + EmbeddingServiceInstrumentation.class.getName() + "$EmbeddingAdvice"); + } + + @Override + public String hierarchyMarkerType() { + return "com.openai.services.embedding.EmbeddingService"; + } + + @Override + public ElementMatcher hierarchyMatcher() { + return implementsInterface(named(hierarchyMarkerType())); + } + + public static class EmbeddingAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static AgentScope onEnter( + @Advice.Argument(0) final EmbeddingCreateParams embeddingParams) { + + return OpenAIClientDecorator.DECORATE.startEmbeddingSpan(embeddingParams); + } + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onExit( + @Advice.Enter final AgentScope span, + @Advice.Return final Object result, + @Advice.Thrown final Throwable throwable) { + + OpenAIClientDecorator.DECORATE.finishSpan(span, result, throwable); + } + } +} diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java new file mode 100644 index 00000000000..b23739c29ea --- /dev/null +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java @@ -0,0 +1,303 @@ +package datadog.trace.instrumentation.openai; + +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan; + +import com.openai.models.chat.completions.*; +import com.openai.models.completions.Completion; +import com.openai.models.completions.CompletionChoice; +import com.openai.models.completions.CompletionCreateParams; +import com.openai.models.embeddings.CreateEmbeddingResponse; +import com.openai.models.embeddings.Embedding; +import com.openai.models.embeddings.EmbeddingCreateParams; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.InternalSpanTypes; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.bootstrap.instrumentation.decorator.ClientDecorator; +import java.util.List; +import java.util.Optional; + +public class OpenAIClientDecorator extends ClientDecorator { + private static final String COMPONENT_NAME = "openai"; + private static final UTF8BytesString OPENAI_REQUEST = UTF8BytesString.create("openai.request"); + + public static final OpenAIClientDecorator DECORATE = new OpenAIClientDecorator(); + + @Override + protected String[] instrumentationNames() { + return new String[] {"openai"}; + } + + @Override + protected CharSequence component() { + return UTF8BytesString.create(COMPONENT_NAME); + } + + @Override + protected CharSequence spanType() { + return InternalSpanTypes.HTTP_CLIENT; + } + + @Override + protected String service() { + return null; // Use default service name + } + + public AgentScope startChatCompletionSpan(ChatCompletionCreateParams params) { + AgentSpan span = startSpan(OPENAI_REQUEST); + span.setTag("openai.request.endpoint", "/chat/completions"); + span.setResourceName("chat.completions.create"); + span.setTag("openai.provider", "openai"); + extractChatCompletionRequestData(span, params); + afterStart(span); + return activateSpan(span); + } + + public AgentScope startLLMChatCompletionSpan(ChatCompletionCreateParams params) { + AgentSpan span = startSpan(OPENAI_REQUEST); + span.setTag("openai.request.endpoint", "/chat/completions"); + span.setResourceName("chat.completions.create"); + span.setTag("openai.provider", "openai"); + extractChatCompletionRequestData(span, params); + afterStart(span); + return activateSpan(span); + } + + public AgentScope startCompletionSpan(CompletionCreateParams params) { + AgentSpan span = startSpan(OPENAI_REQUEST); + span.setTag(Tags.COMPONENT, COMPONENT_NAME); + span.setTag("openai.request.endpoint", "/completions"); + span.setResourceName("completions.create"); + span.setTag("ai.provider", "openai"); + + extractCompletionRequestData(span, params); + afterStart(span); + return activateSpan(span); + } + + public AgentScope startEmbeddingSpan(EmbeddingCreateParams params) { + AgentSpan span = startSpan(OPENAI_REQUEST); + span.setTag("openai.request.endpoint", "/embeddings"); + span.setResourceName("embeddings.create"); + span.setTag("ai.provider", "openai"); + + extractEmbeddingRequestData(span, params); + afterStart(span); + return activateSpan(span); + } + + public void finishSpan(AgentScope scope, Object result, Throwable throwable) { + + AgentSpan span = scope.span(); + + try { + if (throwable != null) { + onError(span, throwable); + } else if (result != null) { + extractResponseData(span, result); + } + beforeFinish(span); + } finally { + scope.close(); + span.finish(); + } + } + + private void extractChatCompletionRequestData(AgentSpan span, ChatCompletionCreateParams params) { + + // Extract model + + span.setTag("openai.model.name", params.model().toString()); + + // Extract messages + List messages = params.messages(); + for (int i = 0; i < messages.size(); i++) { + ChatCompletionMessageParam messageParam = messages.get(i); + extractMessageData(span, messageParam, i); + } + + // Extract request parameters + extractChatCompletionParameters(span, params); + } + + private void extractCompletionRequestData( + AgentSpan span, CompletionCreateParams completionParams) { + // Extract model + CompletionCreateParams.Model model = completionParams.model(); + if (model != null) { + span.setTag("openai.model.name", model.toString()); + } + + // Extract prompt + Optional prompt = completionParams.prompt(); + prompt.ifPresent( + promptValue -> { + if (promptValue.isArrayOfStrings()) { + List promptArray = promptValue.asArrayOfStrings(); + int promptIndex = 0; + for (String currentPrompt : promptArray) { + span.setTag("openai.request.prompt." + promptIndex, currentPrompt); + promptIndex++; + } + } else if (promptValue.isString()) { + // Setting the index as 0 since there is only one prompt string + span.setTag("openai.request.prompt.0", promptValue.asString()); + + } else if (promptValue.isArrayOfTokenArrays() || promptValue.isArrayOfTokens()) { + // Setting the token array as the value of the prompt tag + span.setTag("openai.request.prompt.0", promptValue.asArrayOfTokens()); + } + }); + // Extract request parameters + extractCompletionParameters(span, completionParams); + } + + private void extractEmbeddingRequestData(AgentSpan span, EmbeddingCreateParams embeddingParams) { + + // Extract model + Object model = embeddingParams.model(); + if (model != null) { + span.setTag("openai.model.name", model.toString()); + } + + // Extract input + EmbeddingCreateParams.Input input = embeddingParams.input(); + int inputIndex = 0; + List inputStrings = input.asArrayOfStrings(); + for (String inputItem : inputStrings) { + span.setTag("openai.request.input." + inputIndex, input.asString()); + inputIndex++; + } + } + + private void extractMessageData( + AgentSpan span, ChatCompletionMessageParam messageParam, int index) { + // Handle different message parameter types + if (messageParam.isUser()) { + span.setTag("openai.request.messages." + index + ".role", "user"); + span.setTag( + "openai.request.messages." + index + ".content", + messageParam.asUser().content().toString()); + } else if (messageParam.isAssistant()) { + span.setTag("openai.request.messages." + index + ".role", "assistant"); + span.setTag( + "openai.request.messages." + index + ".content", + messageParam.asAssistant().content().toString()); + } else if (messageParam.isDeveloper()) { + span.setTag("openai.request.messages." + index + ".role", "developer"); + span.setTag( + "openai.request.messages." + index + ".content", + messageParam.asDeveloper().content().toString()); + } else if (messageParam.isSystem()) { + span.setTag("openai.request.messages." + index + ".role", "system"); + span.setTag( + "openai.request.messages." + index + ".content", + messageParam.asSystem().content().toString()); + } else if (messageParam.isTool()) { + span.setTag("openai.request.messages." + index + ".role", "tool"); + span.setTag( + "openai.request.messages." + index + ".content", + messageParam.asTool().content().toString()); + } + } + + private void extractChatCompletionParameters(AgentSpan span, ChatCompletionCreateParams params) { + // Extract max_tokens + Optional maxTokens = params.maxTokens(); + maxTokens.ifPresent(tokens -> span.setTag("openai.request.max_tokens", tokens)); + + // Extract temperature + Optional temperature = params.temperature(); + temperature.ifPresent(temp -> span.setTag("openai.request.temperature", temp)); + } + + private void extractCompletionParameters(AgentSpan span, CompletionCreateParams params) { + // Extract max_tokens + if (params.maxTokens().isPresent()) { + span.setTag("openai.request.max_tokens", params.maxTokens().get()); + } + + // Extract temperature + Optional temperature = params.temperature(); + if (temperature.isPresent()) { + span.setTag("openai.request.temperature", temperature.get()); + } + } + + private void extractResponseData(AgentSpan span, Object result) { + if (result instanceof ChatCompletion) { + extractChatCompletionResponseData(span, (ChatCompletion) result); + } else if (result instanceof Completion) { + extractCompletionResponseData(span, (Completion) result); + } else if (result instanceof CreateEmbeddingResponse) { + extractEmbeddingResponseData(span, (CreateEmbeddingResponse) result); + } + } + + private void extractChatCompletionResponseData(AgentSpan span, ChatCompletion response) { + // Extract choices + List choices = response.choices(); + int choiceIndex = 0; + if (!choices.isEmpty()) { + for (ChatCompletion.Choice curChoice : choices) { + ChatCompletionMessage curMessage = curChoice.message(); + // Extract content + Optional content = curMessage.content(); + content.ifPresent( + s -> span.setTag("openai.response.choices." + choiceIndex + ".message.content", s)); + span.setTag( + "openai.response.choices." + choiceIndex + ".message.role", + curMessage._role().toString()); + Optional> toolCalls = curMessage.toolCalls(); + if (toolCalls.isPresent() && !toolCalls.get().isEmpty()) { + // Extract tool calls if present + int callIndex = 0; + for (ChatCompletionMessageToolCall call : toolCalls.get()) { + span.setTag( + "openai.response.choices." + + choiceIndex + + ".message.tool_calls." + + callIndex + + ".name", + call.id()); + span.setTag( + "openai.response.choices." + + choiceIndex + + ".message.tool_calls." + + callIndex + + ".arguments", + call.function().arguments()); + + callIndex++; + } + } + } + } + } + + private void extractCompletionResponseData(AgentSpan span, Completion response) { + // Extract choices + List choices = response.choices(); + for (CompletionChoice choice : choices) { + span.setTag("openai.response.choices." + choice.index() + ".text", choice.text()); + } + } + + private void extractEmbeddingResponseData(AgentSpan span, CreateEmbeddingResponse response) { + // Extract data (embeddings) + List data = response.data(); + span.setTag("openai.response.embeddings_count", data.size()); + int embeddingIndex = 0; + if (!data.isEmpty()) { + for (Embedding curEmbedding : data) { + // Extract embedding array + List embedding = curEmbedding.embedding(); + span.setTag( + "openai.response.embedding." + embeddingIndex + ".embedding_length", embedding.size()); + embeddingIndex++; + } + } + } +} diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java new file mode 100644 index 00000000000..ba8280620d4 --- /dev/null +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java @@ -0,0 +1,88 @@ +package datadog.trace.instrumentation.openai; + +import com.openai.azure.credential.AzureApiKeyCredential; +import com.openai.core.ClientOptions; +import com.openai.credential.BearerTokenCredential; + +public class OpenAIClientInfo { + private String baseURL; + private String organizationID; + private String projectID; + private String apiKey; + + /** + * Creates an OpenAIClientInfo instance populated with relevant information from ClientOptions for + * use in span tags during tests and instrumentation + */ + public static OpenAIClientInfo fromClientOptions(ClientOptions options) { + if (options == null) { + return null; + } + + OpenAIClientInfo info = new OpenAIClientInfo(); + + try { + // Extract base URL + info.setBaseURL(options.baseUrl()); + + // Extract organization ID if available + if (options.organization().isPresent()) { + info.setOrganizationID(options.organization().get()); + } + + // Extract project ID if available + if (options.project().isPresent()) { + info.setProjectID(options.project().get()); + } + + if (options.credential() instanceof BearerTokenCredential) { + info.setApiKey(((BearerTokenCredential) options.credential()).token()); + } else if (options.credential() instanceof AzureApiKeyCredential) { + info.setApiKey(((AzureApiKeyCredential) options.credential()).apiKey()); + } else info.setApiKey(null); + + } catch (Exception e) { + // TODO: returns empty info for now + return info; + } + + return info; + } + + private OpenAIClientInfo() { + // Used by fromClientOptions method + } + + public String getBaseURL() { + return baseURL; + } + + public String getOrganizationID() { + return organizationID; + } + + public String getProjectID() { + return projectID; + } + + public String getApiKey() { + return apiKey; + } + + // Private setter methods (write properties) + private void setBaseURL(String baseURL) { + this.baseURL = baseURL; + } + + private void setOrganizationID(String organizationID) { + this.organizationID = organizationID; + } + + private void setProjectID(String projectID) { + this.projectID = projectID; + } + + private void setApiKey(String apiKey) { + this.apiKey = apiKey; + } +} diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java new file mode 100644 index 00000000000..f20c1eb7ca2 --- /dev/null +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java @@ -0,0 +1,74 @@ +package datadog.trace.instrumentation.openai; + +import static net.bytebuddy.matcher.ElementMatchers.isConstructor; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import com.openai.client.OpenAIClientImpl; +import com.openai.core.ClientOptions; +import com.openai.services.blocking.CompletionService; +import com.openai.services.blocking.EmbeddingService; +import com.openai.services.blocking.chat.ChatCompletionService; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.InstrumentationContext; +import java.util.HashMap; +import java.util.Map; +import net.bytebuddy.asm.Advice; + +public class OpenAIClientInstrumentation extends InstrumenterModule.Tracing + implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { + public OpenAIClientInstrumentation() { + super("openai-client"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + packageName + ".OpenAIClientInfo", + }; + } + + @Override + public String instrumentedType() { + return "com.openai.client.OpenAIClientImpl"; + } + + @Override + public Map contextStore() { + Map contextStores = new HashMap<>(3); + contextStores.put( + "com.openai.services.blocking.chat.ChatCompletionService", + OpenAIClientInfo.class.getName()); + contextStores.put( + "com.openai.services.blocking.CompletionService", OpenAIClientInfo.class.getName()); + contextStores.put( + "com.openai.services.blocking.EmbeddingService", OpenAIClientInfo.class.getName()); + return contextStores; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isConstructor().and(takesArgument(0, ClientOptions.class)), + getClass().getName() + "$OpenAIClientAdvice"); + } + + public static class OpenAIClientAdvice { + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void methodExit( + @Advice.This final OpenAIClientImpl client, + @Advice.Argument(0) final ClientOptions options, + @Advice.Thrown final Throwable throwable) { + OpenAIClientInfo info = OpenAIClientInfo.fromClientOptions(options); + if (info != null) { + InstrumentationContext.get(CompletionService.class, OpenAIClientInfo.class) + .put(client.completions(), info); + InstrumentationContext.get(EmbeddingService.class, OpenAIClientInfo.class) + .put(client.embeddings(), info); + InstrumentationContext.get(ChatCompletionService.class, OpenAIClientInfo.class) + .put(client.chat().completions(), info); + } + } + } +} diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000000..28697f423a9 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,565 @@ +pluginManagement { + repositories { + mavenLocal() + if (settings.hasProperty("gradlePluginProxy")) { + maven { + url settings["gradlePluginProxy"] + allowInsecureProtocol true + } + } + if (settings.hasProperty("mavenRepositoryProxy")) { + maven { + url settings["mavenRepositoryProxy"] + allowInsecureProtocol true + } + } + gradlePluginPortal() + mavenCentral() + } +} + +plugins { + id 'com.gradle.develocity' version '3.19.2' +} + +def isCI = System.getenv("CI") != null +def skipBuildscan = Boolean.valueOf(System.getenv("SKIP_BUILDSCAN")) +develocity { + buildScan { + termsOfUseUrl = 'https://gradle.com/help/legal-terms-of-use' + termsOfUseAgree = 'yes' + + publishing.onlyIf { isCI && !skipBuildscan } + } +} + +// Don't pollute the dependency cache with the build cache +if (isCI) { + buildCache { + local { + directory = "$rootDir/workspace/build-cache" + } + } +} + +rootProject.name = 'dd-trace-java' + +// external apis +include ':dd-trace-api' +include ':dd-trace-ot' +include ':dd-trace-ot:correlation-id-injection' + +// agent projects +include ':internal-api' +include ':internal-api:internal-api-9' +include ':dd-trace-core' +include ':dd-java-agent' +include ':dd-java-agent:agent-bootstrap' +include ':dd-java-agent:agent-builder' +include ':dd-java-agent:agent-tooling' +include ':dd-java-agent:agent-jmxfetch' +include ':dd-java-agent:agent-logging' +include ':dd-java-agent:agent-logs-intake' +include ':dd-java-agent:load-generator' + +// profiling +include ':dd-java-agent:agent-profiling' +include ':dd-java-agent:agent-profiling:profiling-ddprof' +include ':dd-java-agent:agent-profiling:profiling-controller' +include ':dd-java-agent:agent-profiling:profiling-controller-jfr' +include ':dd-java-agent:agent-profiling:profiling-controller-jfr:implementation' +include ':dd-java-agent:agent-profiling:profiling-controller-ddprof' +include ':dd-java-agent:agent-profiling:profiling-controller-openjdk' +include ':dd-java-agent:agent-profiling:profiling-controller-oracle' +include ':dd-java-agent:agent-profiling:profiling-testing' +include ':dd-java-agent:agent-profiling:profiling-uploader' +include ':dd-java-agent:agent-profiling:profiling-utils' + +include ':dd-java-agent:agent-debugger:debugger-bootstrap' +include ':dd-java-agent:agent-debugger:debugger-test-scala' +include ':dd-java-agent:agent-debugger:debugger-el' + +include ':dd-java-agent:agent-crashtracking' + +include ':dd-java-agent:agent-otel:otel-bootstrap' +include ':dd-java-agent:agent-otel:otel-shim' +include ':dd-java-agent:agent-otel:otel-tooling' + +include ':communication' +include ':components:cli' +include ':components:context' +include ':components:json' +include ':components:yaml' +include ':telemetry' +include ':remote-config:remote-config-api' +include ':remote-config:remote-config-core' + +include ':dd-java-agent:appsec' + +// ci-visibility +include ':dd-java-agent:agent-ci-visibility' + +// iast +include ':dd-java-agent:agent-iast' + +include ':dd-java-agent:cws-tls' + +// misc +include ':dd-java-agent:testing' +include ':utils:container-utils' +include ':utils:socket-utils' +include ':utils:test-agent-utils:decoder' +include ':utils:test-utils' +include ':utils:time-utils' +include ':utils:version-utils' + +// smoke tests +include ':dd-smoke-tests:apm-tracing-disabled' +include ':dd-smoke-tests:armeria-grpc' +include ':dd-smoke-tests:backend-mock' +include ':dd-smoke-tests:cli' +include ':dd-smoke-tests:concurrent:java-8' +include ':dd-smoke-tests:concurrent:java-21' +include ':dd-smoke-tests:crashtracking' +include ':dd-smoke-tests:custom-systemloader' +include ':dd-smoke-tests:dynamic-config' +include ':dd-smoke-tests:field-injection' +include ':dd-smoke-tests:gradle' +include ':dd-smoke-tests:grpc-1.5' +include ':dd-smoke-tests:java9-modules' +include ':dd-smoke-tests:jersey' +include ':dd-smoke-tests:jersey-2' +include ':dd-smoke-tests:jersey-3' +include ':dd-smoke-tests:jboss-modules' +include ':dd-smoke-tests:kafka-2' +include ':dd-smoke-tests:kafka-3' +include ':dd-smoke-tests:lib-injection' +include ':dd-smoke-tests:log-injection' +include ':dd-smoke-tests:maven' +include ':dd-smoke-tests:opentracing' +include ':dd-smoke-tests:opentelemetry' +include ':dd-smoke-tests:osgi' +include ':dd-smoke-tests:play-2.4' +include ':dd-smoke-tests:play-2.5' +include ':dd-smoke-tests:play-2.6' +include ':dd-smoke-tests:play-2.7' +include ':dd-smoke-tests:play-2.8' +include ':dd-smoke-tests:play-2.8-otel' +include ':dd-smoke-tests:play-2.8-split-routes' +include ':dd-smoke-tests:profiling-integration-tests' +include ':dd-smoke-tests:quarkus' +include ':dd-smoke-tests:quarkus-native' +include ':dd-smoke-tests:sample-trace' +include ':dd-smoke-tests:resteasy' +include ':dd-smoke-tests:spring-boot-3.0-native' +include ':dd-smoke-tests:spring-boot-2.4-webflux' +include ':dd-smoke-tests:spring-boot-2.5-webflux' +include ':dd-smoke-tests:spring-boot-2.6-webflux' +include ':dd-smoke-tests:spring-boot-2.7-webflux' +include ':dd-smoke-tests:spring-boot-3.0-webflux' +include ':dd-smoke-tests:spring-boot-2.3-webmvc-jetty' +include ':dd-smoke-tests:spring-boot-2.6-webmvc' +include ':dd-smoke-tests:spring-boot-3.0-webmvc' +include ':dd-smoke-tests:spring-boot-3.3-webmvc' +include ':dd-smoke-tests:spring-boot-rabbit' +include ':dd-smoke-tests:spring-security' +include ':dd-smoke-tests:springboot' +include ':dd-smoke-tests:springboot-freemarker' +include ':dd-smoke-tests:springboot-grpc' +include ':dd-smoke-tests:springboot-java-11' +include ':dd-smoke-tests:springboot-java-17' +include ':dd-smoke-tests:springboot-jetty-jsp' +include ':dd-smoke-tests:springboot-jpa' +include ':dd-smoke-tests:springboot-mongo' +include ':dd-smoke-tests:springboot-openliberty-20' +include ':dd-smoke-tests:springboot-openliberty-23' +include ':dd-smoke-tests:springboot-thymeleaf' +include ':dd-smoke-tests:springboot-tomcat' +include ':dd-smoke-tests:springboot-tomcat-jsp' +include ':dd-smoke-tests:springboot-velocity' +include ':dd-smoke-tests:vertx-3.4' +include ':dd-smoke-tests:vertx-3.9' +include ':dd-smoke-tests:vertx-3.9-resteasy' +include ':dd-smoke-tests:vertx-4.2' +include ':dd-smoke-tests:wildfly' +include ':dd-smoke-tests:appsec' +include ':dd-smoke-tests:appsec:spring-tomcat7' +include ':dd-smoke-tests:appsec:springboot' +include ':dd-smoke-tests:appsec:springboot-grpc' +include ':dd-smoke-tests:appsec:springboot-graphql' +include ':dd-smoke-tests:appsec:springboot-security' +include ':dd-smoke-tests:debugger-integration-tests' +include ':dd-smoke-tests:datastreams:kafkaschemaregistry' +include ':dd-smoke-tests:iast-propagation' +include ':dd-smoke-tests:iast-util' +include ':dd-smoke-tests:iast-util:iast-util-11' +include ':dd-smoke-tests:iast-util:iast-util-17' +// TODO this fails too often with a jgit failure, so disable until fixed +//include ':dd-smoke-tests:debugger-integration-tests:latest-jdk-app' + +// annotation processor for checking instrumentation advice +include ':dd-java-agent:instrumentation-annotation-processor' + +// instrumentation: +include ':dd-java-agent:instrumentation:aerospike-4' +include ':dd-java-agent:instrumentation:akka-concurrent' +include ':dd-java-agent:instrumentation:akka-http' +include ':dd-java-agent:instrumentation:akka-http:akka-http-10.0' +include ':dd-java-agent:instrumentation:akka-http:akka-http-10.2-iast' +include ':dd-java-agent:instrumentation:akka-http:akka-http-10.6' +include ':dd-java-agent:instrumentation:akka-init' +include ':dd-java-agent:instrumentation:apache-httpasyncclient-4' +include ':dd-java-agent:instrumentation:apache-httpclient-4' +include ':dd-java-agent:instrumentation:apache-httpclient-5' +include ':dd-java-agent:instrumentation:apache-httpcore-4' +include ':dd-java-agent:instrumentation:apache-httpcore-5' +include ':dd-java-agent:instrumentation:armeria-grpc' +include ':dd-java-agent:instrumentation:armeria-jetty' +include ':dd-java-agent:instrumentation:avro' +include ':dd-java-agent:instrumentation:aws-common' +include ':dd-java-agent:instrumentation:aws-java-dynamodb-2.0' +include ':dd-java-agent:instrumentation:aws-java-eventbridge-2.0' +include ':dd-java-agent:instrumentation:aws-java-sdk-1.11.0' +include ':dd-java-agent:instrumentation:aws-java-sdk-2.2' +include ':dd-java-agent:instrumentation:aws-java-sfn-2.0' +include ':dd-java-agent:instrumentation:aws-java-sns-1.0' +include ':dd-java-agent:instrumentation:aws-java-sns-2.0' +include ':dd-java-agent:instrumentation:aws-java-sqs-1.0' +include ':dd-java-agent:instrumentation:aws-java-sqs-2.0' +include ':dd-java-agent:instrumentation:aws-java-s3-2.0' +include ':dd-java-agent:instrumentation:aws-lambda-handler' +include ':dd-java-agent:instrumentation:axis-2' +include ':dd-java-agent:instrumentation:axway-api' +include ':dd-java-agent:instrumentation:azure-functions' +include ':dd-java-agent:instrumentation:caffeine' +include ':dd-java-agent:instrumentation:cdi-1.2' +include ':dd-java-agent:instrumentation:classloading' +include ':dd-java-agent:instrumentation:classloading:jboss-testing' +include ':dd-java-agent:instrumentation:classloading:jsr14-testing' +include ':dd-java-agent:instrumentation:classloading:osgi-testing' +include ':dd-java-agent:instrumentation:classloading:tomcat-testing' +include ':dd-java-agent:instrumentation:commons-codec-1' +include ':dd-java-agent:instrumentation:commons-fileupload' +include ':dd-java-agent:instrumentation:commons-httpclient-2' +include ':dd-java-agent:instrumentation:commons-lang-2' +include ':dd-java-agent:instrumentation:commons-lang-3' +include ':dd-java-agent:instrumentation:commons-text' +include ':dd-java-agent:instrumentation:couchbase' +include ':dd-java-agent:instrumentation:couchbase:couchbase-2.0' +include ':dd-java-agent:instrumentation:couchbase:couchbase-2.6' +include ':dd-java-agent:instrumentation:couchbase:couchbase-3.1' +include ':dd-java-agent:instrumentation:couchbase:couchbase-3.2' +include ':dd-java-agent:instrumentation:cucumber' +include ':dd-java-agent:instrumentation:cxf-2.1' +include ':dd-java-agent:instrumentation:datanucleus-4' +include ':dd-java-agent:instrumentation:datastax-cassandra-3' +include ':dd-java-agent:instrumentation:datastax-cassandra-3.8' +include ':dd-java-agent:instrumentation:datastax-cassandra-4' +include ':dd-java-agent:instrumentation:dropwizard' +include ':dd-java-agent:instrumentation:dropwizard:dropwizard-views' +include ':dd-java-agent:instrumentation:elasticsearch' +include ':dd-java-agent:instrumentation:elasticsearch:rest-5' +include ':dd-java-agent:instrumentation:elasticsearch:rest-6.4' +include ':dd-java-agent:instrumentation:elasticsearch:rest-7' +include ':dd-java-agent:instrumentation:elasticsearch:transport' +include ':dd-java-agent:instrumentation:elasticsearch:transport-2' +include ':dd-java-agent:instrumentation:elasticsearch:transport-5' +include ':dd-java-agent:instrumentation:elasticsearch:transport-5.3' +include ':dd-java-agent:instrumentation:elasticsearch:transport-6' +include ':dd-java-agent:instrumentation:elasticsearch:transport-7.3' +include ':dd-java-agent:instrumentation:enable-wallclock-profiling' +include ':dd-java-agent:instrumentation:exception-profiling' +include ':dd-java-agent:instrumentation:finatra-2.9' +include ':dd-java-agent:instrumentation:freemarker' +include ':dd-java-agent:instrumentation:freemarker:freemarker-2.3.9' +include ':dd-java-agent:instrumentation:freemarker:freemarker-2.3.24' +include ':dd-java-agent:instrumentation:glassfish' +include ':dd-java-agent:instrumentation:google-http-client' +include ':dd-java-agent:instrumentation:google-pubsub' +include ':dd-java-agent:instrumentation:graal:native-image' +include ':dd-java-agent:instrumentation:gradle-3.0' +include ':dd-java-agent:instrumentation:gradle-8.3' +include ':dd-java-agent:instrumentation:gradle-testing' +include ':dd-java-agent:instrumentation:graphql-java' +include ':dd-java-agent:instrumentation:graphql-java:graphql-java-14.0' +include ':dd-java-agent:instrumentation:graphql-java:graphql-java-20.0' +include ':dd-java-agent:instrumentation:graphql-java:graphql-java-common' +include ':dd-java-agent:instrumentation:grizzly-2' +include ':dd-java-agent:instrumentation:grizzly-client-1.9' +include ':dd-java-agent:instrumentation:grizzly-http-2.3.20' +include ':dd-java-agent:instrumentation:grpc-1.5' +include ':dd-java-agent:instrumentation:gson-1.6' +include ':dd-java-agent:instrumentation:guava-10' +include ':dd-java-agent:instrumentation:hazelcast-3.6' +include ':dd-java-agent:instrumentation:hazelcast-3.9' +include ':dd-java-agent:instrumentation:hazelcast-4.0' +include ':dd-java-agent:instrumentation:hibernate' +include ':dd-java-agent:instrumentation:hibernate:core-3.3' +include ':dd-java-agent:instrumentation:hibernate:core-4.0' +include ':dd-java-agent:instrumentation:hibernate:core-4.3' +include ':dd-java-agent:instrumentation:http-url-connection' +include ':dd-java-agent:instrumentation:hystrix-1.4' +include ':dd-java-agent:instrumentation:iast-instrumenter' +include ':dd-java-agent:instrumentation:ignite-2.0' +include ':dd-java-agent:instrumentation:jackson-core' +include ':dd-java-agent:instrumentation:jackson-core:jackson-core-1' +include ':dd-java-agent:instrumentation:jackson-core:jackson-core-2' +include ':dd-java-agent:instrumentation:jackson-core:jackson-core-2.6' +include ':dd-java-agent:instrumentation:jackson-core:jackson-core-2.8' +include ':dd-java-agent:instrumentation:jackson-core:jackson-core-2.12' +include ':dd-java-agent:instrumentation:jackson-core:jackson-core-2.16' +include ':dd-java-agent:instrumentation:jacoco' +include ':dd-java-agent:instrumentation:jakarta-jms' +include ':dd-java-agent:instrumentation:jakarta-mail' +include ':dd-java-agent:instrumentation:jakarta-rs-annotations-3' +include ':dd-java-agent:instrumentation:jakarta-ws-annotations' +include ':dd-java-agent:instrumentation:java-concurrent' +include ':dd-java-agent:instrumentation:java-concurrent:java-completablefuture' +include ':dd-java-agent:instrumentation:java-concurrent:java-concurrent-21' +include ':dd-java-agent:instrumentation:java-concurrent:lambda-testing' +include ':dd-java-agent:instrumentation:java-directbytebuffer' +include ':dd-java-agent:instrumentation:java-http-client' +include ':dd-java-agent:instrumentation:java-io' +include ':dd-java-agent:instrumentation:java-lang' +include ':dd-java-agent:instrumentation:java-lang:java-lang-9' +include ':dd-java-agent:instrumentation:java-lang:java-lang-11' +include ':dd-java-agent:instrumentation:java-lang:java-lang-15' +include ':dd-java-agent:instrumentation:java-lang:java-lang-17' +include ':dd-java-agent:instrumentation:java-net' +include ':dd-java-agent:instrumentation:java-security' +include ':dd-java-agent:instrumentation:java-util' +include ':dd-java-agent:instrumentation:javax-naming' +include ':dd-java-agent:instrumentation:javax-xml' +include ':dd-java-agent:instrumentation:javax-mail' +include ':dd-java-agent:instrumentation:jax-rs-annotations-1' +include ':dd-java-agent:instrumentation:jax-rs-annotations-2' +include ':dd-java-agent:instrumentation:jax-rs-annotations-2:filter-jersey' +include ':dd-java-agent:instrumentation:jax-rs-annotations-2:filter-resteasy-3.0' +include ':dd-java-agent:instrumentation:jax-rs-annotations-2:filter-resteasy-3.1' +include ':dd-java-agent:instrumentation:jax-rs-client-1.1' +include ':dd-java-agent:instrumentation:jax-rs-client-2.0' +include ':dd-java-agent:instrumentation:jax-rs-client-2.0:connection-error-handling-jersey' +include ':dd-java-agent:instrumentation:jax-rs-client-2.0:connection-error-handling-resteasy' +include ':dd-java-agent:instrumentation:jax-ws-annotations-1' +include ':dd-java-agent:instrumentation:jax-ws-annotations-2' +include ':dd-java-agent:instrumentation:jboss-logmanager' +include ':dd-java-agent:instrumentation:jboss-modules' +include ':dd-java-agent:instrumentation:jdbc' +include ':dd-java-agent:instrumentation:jdbc:scalikejdbc' +include ':dd-java-agent:instrumentation:jedis-1.4' +include ':dd-java-agent:instrumentation:jedis-3.0' +include ':dd-java-agent:instrumentation:jedis-4.0' +include ':dd-java-agent:instrumentation:jersey' +include ':dd-java-agent:instrumentation:jersey-2-appsec' +include ':dd-java-agent:instrumentation:jersey-3-appsec' +include ':dd-java-agent:instrumentation:jetty-7.0' +include ':dd-java-agent:instrumentation:jetty-7.6' +include ':dd-java-agent:instrumentation:jetty-9' +include ':dd-java-agent:instrumentation:jetty-11' +include ':dd-java-agent:instrumentation:jetty-12' +include ':dd-java-agent:instrumentation:jetty-appsec-7' +include ':dd-java-agent:instrumentation:jetty-appsec-8.1.3' +include ':dd-java-agent:instrumentation:jetty-appsec-9.2' +include ':dd-java-agent:instrumentation:jetty-appsec-9.3' +include ':dd-java-agent:instrumentation:jetty-client:jetty-client-common' +include ':dd-java-agent:instrumentation:jetty-client:jetty-client-9.1' +include ':dd-java-agent:instrumentation:jetty-client:jetty-client-10.0' +include ':dd-java-agent:instrumentation:jetty-client:jetty-client-12.0' +include ':dd-java-agent:instrumentation:jetty-common' +include ':dd-java-agent:instrumentation:jetty-util' +include ':dd-java-agent:instrumentation:jms' +include ':dd-java-agent:instrumentation:jose-jwt' +include ':dd-java-agent:instrumentation:org-json' +include ':dd-java-agent:instrumentation:jsp-2.3' +include ':dd-java-agent:instrumentation:junit-4.10' +include ':dd-java-agent:instrumentation:junit-4.10:cucumber-junit-4' +include ':dd-java-agent:instrumentation:junit-4.10:junit-4.13' +include ':dd-java-agent:instrumentation:junit-4.10:munit-junit-4' +include ':dd-java-agent:instrumentation:junit-5.3' +include ':dd-java-agent:instrumentation:junit-5.3:junit-5.8' +include ':dd-java-agent:instrumentation:junit-5.3:cucumber-junit-5' +include ':dd-java-agent:instrumentation:junit-5.3:spock-junit-5' +include ':dd-java-agent:instrumentation:kafka-clients-0.11' +include ':dd-java-agent:instrumentation:kafka-clients-3.8' +include ':dd-java-agent:instrumentation:kafka-common' +include ':dd-java-agent:instrumentation:kafka-connect-0.11' +include ':dd-java-agent:instrumentation:kafka-streams-0.11' +include ':dd-java-agent:instrumentation:kafka-streams-1.0' +include ':dd-java-agent:instrumentation:karate' +include ':dd-java-agent:instrumentation:kotlin-coroutines' +include ':dd-java-agent:instrumentation:lettuce-4' +include ':dd-java-agent:instrumentation:lettuce-5' +include ':dd-java-agent:instrumentation:liberty-20' +include ':dd-java-agent:instrumentation:liberty-23' +include ':dd-java-agent:instrumentation:log4j-2.7' +include ':dd-java-agent:instrumentation:log4j1' +include ':dd-java-agent:instrumentation:log4j2' +include ':dd-java-agent:instrumentation:log4j2:logs-intake' +include ':dd-java-agent:instrumentation:logback-1' +include ':dd-java-agent:instrumentation:maven-3.2.1' +include ':dd-java-agent:instrumentation:maven-surefire' +include ':dd-java-agent:instrumentation:micronaut' +include ':dd-java-agent:instrumentation:micronaut:http-server-netty-2.0' +include ':dd-java-agent:instrumentation:micronaut:http-server-netty-3.0' +include ':dd-java-agent:instrumentation:micronaut:http-server-netty-4.0' +include ':dd-java-agent:instrumentation:mongo' +include ':dd-java-agent:instrumentation:mongo:common' +include ':dd-java-agent:instrumentation:mongo:bson-document' +include ':dd-java-agent:instrumentation:mongo:driver-3.1' +include ':dd-java-agent:instrumentation:mongo:driver-3.4' +include ':dd-java-agent:instrumentation:mongo:driver-3.1-core-test' +include ':dd-java-agent:instrumentation:mongo:driver-3.7-core-test' +include ':dd-java-agent:instrumentation:mongo:driver-4.0' +include ':dd-java-agent:instrumentation:mongo:driver-3.3-async-test' +include ':dd-java-agent:instrumentation:mongo:driver-3.10-sync-test' +include ':dd-java-agent:instrumentation:mule-4' +include ':dd-java-agent:instrumentation:netty-3.8' +include ':dd-java-agent:instrumentation:netty-4.0' +include ':dd-java-agent:instrumentation:netty-4.1-shared' +include ':dd-java-agent:instrumentation:netty-4.1' +include ':dd-java-agent:instrumentation:netty-buffer-4' +include ':dd-java-agent:instrumentation:netty-concurrent-4' +include ':dd-java-agent:instrumentation:netty-promise-4' +include ':dd-java-agent:instrumentation:okhttp-2' +include ':dd-java-agent:instrumentation:okhttp-3' +include ':dd-java-agent:instrumentation:ognl-appsec' +include ':dd-java-agent:instrumentation:opensearch' +include ':dd-java-agent:instrumentation:opensearch:rest' +include ':dd-java-agent:instrumentation:opensearch:transport' +include ':dd-java-agent:instrumentation:openai' +include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-0.3' +include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-1.4' +include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-annotations-1.20' +include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-annotations-1.26' +include ':dd-java-agent:instrumentation:opentracing' +include ':dd-java-agent:instrumentation:opentracing:api-0.31' +include ':dd-java-agent:instrumentation:opentracing:api-0.32' +include ':dd-java-agent:instrumentation:osgi-4.3' +include ':dd-java-agent:instrumentation:owasp-esapi-2' +include ':dd-java-agent:instrumentation:pekko-concurrent' +include ':dd-java-agent:instrumentation:pekko-http-1.0' +include ':dd-java-agent:instrumentation:play-2.3' +include ':dd-java-agent:instrumentation:play-2.4' +include ':dd-java-agent:instrumentation:play-2.6' +include ':dd-java-agent:instrumentation:play-ws' +include ':dd-java-agent:instrumentation:play-ws-1' +include ':dd-java-agent:instrumentation:play-ws-2' +include ':dd-java-agent:instrumentation:play-ws-2.1' +include ':dd-java-agent:instrumentation:protobuf' +include ':dd-java-agent:instrumentation:quartz-2' +include ':dd-java-agent:instrumentation:rabbitmq-amqp-2.7' +include ':dd-java-agent:instrumentation:ratpack-1.5' +include ':dd-java-agent:instrumentation:reactive-streams' +include ':dd-java-agent:instrumentation:reactor-core-3.1' +include ':dd-java-agent:instrumentation:reactor-netty-1' +include ':dd-java-agent:instrumentation:rediscala-1.8.0' +include ':dd-java-agent:instrumentation:renaissance' +include ':dd-java-agent:instrumentation:resteasy-appsec' +include ':dd-java-agent:instrumentation:restlet-2.2' +include ':dd-java-agent:instrumentation:rmi' +include ':dd-java-agent:instrumentation:rxjava-1' +include ':dd-java-agent:instrumentation:rxjava-2' +include ':dd-java-agent:instrumentation:scala' +include ':dd-java-agent:instrumentation:scala-concurrent' +include ':dd-java-agent:instrumentation:scala-promise' +include ':dd-java-agent:instrumentation:scala-promise:scala-promise-2.10' +include ':dd-java-agent:instrumentation:scala-promise:scala-promise-2.13' +include ':dd-java-agent:instrumentation:scalatest' +include ':dd-java-agent:instrumentation:selenium' +include ':dd-java-agent:instrumentation:servicetalk' +include ':dd-java-agent:instrumentation:servicetalk:servicetalk-0.42.0' +include ':dd-java-agent:instrumentation:servicetalk:servicetalk-0.42.56' +include ':dd-java-agent:instrumentation:servlet' +include ':dd-java-agent:instrumentation:servlet-common' +include ':dd-java-agent:instrumentation:servlet:request-2' +include ':dd-java-agent:instrumentation:servlet:request-3' +include ':dd-java-agent:instrumentation:servlet:request-5' +include ':dd-java-agent:instrumentation:shutdown' +include ':dd-java-agent:instrumentation:slick' +include ':dd-java-agent:instrumentation:snakeyaml' +include ':dd-java-agent:instrumentation:span-origin' +include ':dd-java-agent:instrumentation:spark' +include ':dd-java-agent:instrumentation:spark:spark_2.12' +include ':dd-java-agent:instrumentation:spark:spark_2.13' +include ':dd-java-agent:instrumentation:spark-executor' +include ':dd-java-agent:instrumentation:sparkjava-2.3' +include ':dd-java-agent:instrumentation:spray-1.3' +include ':dd-java-agent:instrumentation:spring-beans' +include ':dd-java-agent:instrumentation:spring-boot' +include ':dd-java-agent:instrumentation:spring-cloud-zuul-2' +include ':dd-java-agent:instrumentation:spring-core' +include ':dd-java-agent:instrumentation:spring-data-1.8' +include ':dd-java-agent:instrumentation:spring-jms-3.1' +include ':dd-java-agent:instrumentation:spring-messaging-4' +include ':dd-java-agent:instrumentation:spring-rabbit' +include ':dd-java-agent:instrumentation:spring-scheduling-3.1' +include ':dd-java-agent:instrumentation:spring-security-5' +include ':dd-java-agent:instrumentation:spring-security-6' +include ':dd-java-agent:instrumentation:spring-webflux-5' +include ':dd-java-agent:instrumentation:spring-webflux-6' +include ':dd-java-agent:instrumentation:spring-webmvc-3.1' +include ':dd-java-agent:instrumentation:spring-webmvc-5.3' +include ':dd-java-agent:instrumentation:spring-webmvc-6.0' +include ':dd-java-agent:instrumentation:spring-ws-2' +include ':dd-java-agent:instrumentation:spymemcached-2.10' +include ':dd-java-agent:instrumentation:sslsocket' +include ':dd-java-agent:instrumentation:synapse-3' +include ':dd-java-agent:instrumentation:testng' +include ':dd-java-agent:instrumentation:testng:testng-6' +include ':dd-java-agent:instrumentation:testng:testng-7' +include ':dd-java-agent:instrumentation:thymeleaf' +include ':dd-java-agent:instrumentation:tinylog-2' +include ':dd-java-agent:instrumentation:tibco-businessworks' +include ':dd-java-agent:instrumentation:tibco-businessworks:tibcobw-stubs' +include ':dd-java-agent:instrumentation:tibco-businessworks:tibcobw-5' +include ':dd-java-agent:instrumentation:tibco-businessworks:tibcobw-6' +include ':dd-java-agent:instrumentation:tomcat-5.5' +include ':dd-java-agent:instrumentation:tomcat-5.5-common' +include ':dd-java-agent:instrumentation:tomcat-appsec-5.5' +include ':dd-java-agent:instrumentation:tomcat-appsec-6' +include ':dd-java-agent:instrumentation:tomcat-appsec-7' +include ':dd-java-agent:instrumentation:tomcat-classloading-9' +include ':dd-java-agent:instrumentation:trace-annotation' +include ':dd-java-agent:instrumentation:twilio' +include ':dd-java-agent:instrumentation:unbescape' +include ':dd-java-agent:instrumentation:undertow' +include ':dd-java-agent:instrumentation:undertow:undertow-2.0' +include ':dd-java-agent:instrumentation:undertow:undertow-2.2' +include ':dd-java-agent:instrumentation:valkey-java' +include ':dd-java-agent:instrumentation:velocity' +include ':dd-java-agent:instrumentation:vertx-mysql-client-3.9' +include ':dd-java-agent:instrumentation:vertx-mysql-client-4.0' +include ':dd-java-agent:instrumentation:vertx-mysql-client-4.4.2' +include ':dd-java-agent:instrumentation:vertx-pg-client-4.0' +include ':dd-java-agent:instrumentation:vertx-pg-client-4.4.2' +include ':dd-java-agent:instrumentation:vertx-redis-client-3.9' +include ':dd-java-agent:instrumentation:vertx-redis-client-3.9:stubs' +include ':dd-java-agent:instrumentation:vertx-rx-3.5' +include ':dd-java-agent:instrumentation:vertx-sql-client-3.9' +include ':dd-java-agent:instrumentation:vertx-web-3.4' +include ':dd-java-agent:instrumentation:vertx-web-3.5' +include ':dd-java-agent:instrumentation:vertx-web-3.9' +include ':dd-java-agent:instrumentation:vertx-web-4.0' +include ':dd-java-agent:instrumentation:vertx-web-5.0' +include ':dd-java-agent:instrumentation:redisson' +include ':dd-java-agent:instrumentation:redisson:redisson-2.0.0' +include ':dd-java-agent:instrumentation:redisson:redisson-2.3.0' +include ':dd-java-agent:instrumentation:redisson:redisson-3.10.3' +include ':dd-java-agent:instrumentation:weaver' +include ':dd-java-agent:instrumentation:websocket' +include ':dd-java-agent:instrumentation:websocket:jakarta-websocket-2.0' +include ':dd-java-agent:instrumentation:websocket:javax-websocket-1.0' +include ':dd-java-agent:instrumentation:websocket:jetty-websocket' +include ':dd-java-agent:instrumentation:websocket:jetty-websocket:jetty-websocket-10' +include ':dd-java-agent:instrumentation:websocket:jetty-websocket:jetty-websocket-11' +include ':dd-java-agent:instrumentation:websocket:jetty-websocket:jetty-websocket-12' +include ':dd-java-agent:instrumentation:websphere-jmx' +include ':dd-java-agent:instrumentation:wildfly-9' +include ':dd-java-agent:instrumentation:zio' +include ':dd-java-agent:instrumentation:zio:zio-2.0' + +// benchmark +include ':dd-java-agent:benchmark' +include ':dd-java-agent:benchmark-integration' +include ':dd-java-agent:benchmark-integration:jetty-perftest' +include ':dd-java-agent:benchmark-integration:play-perftest' From 42784e2de93eeb4987e2e117ef52ee96dbe27592 Mon Sep 17 00:00:00 2001 From: Nayeem Kamal Date: Mon, 4 Aug 2025 05:40:19 -0400 Subject: [PATCH 2/7] added chatcompletion llmobs spans --- .../datadog/trace/llmobs/LLMObsSystem.java | 4 +- .../instrumentation/openai/build.gradle | 2 - .../ChatCompletionServiceInstrumentation.java | 38 ++++- .../CompletionServiceInstrumentation.java | 7 + .../EmbeddingServiceInstrumentation.java | 7 + .../openai/OpenAIClientDecorator.java | 155 ++++++++++++++---- .../openai/OpenAIClientInfo.java | 8 +- .../openai/OpenAIClientInstrumentation.java | 8 + dd-trace-core/build.gradle | 2 + .../java/datadog/trace/core/CoreTracer.java | 5 + 10 files changed, 188 insertions(+), 48 deletions(-) diff --git a/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java b/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java index e184a645f71..42404944c2b 100644 --- a/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java +++ b/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java @@ -12,7 +12,7 @@ import java.lang.instrument.Instrumentation; import java.util.Map; import java.util.concurrent.TimeUnit; -import org.jetbrains.annotations.Nullable; +import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,7 +22,7 @@ public class LLMObsSystem { private static final String CUSTOM_MODEL_VAL = "custom"; - public static void start(Instrumentation inst, SharedCommunicationObjects sco) { + public static void start(@Nullable Instrumentation inst, SharedCommunicationObjects sco) { Config config = Config.get(); if (!config.isLlmObsEnabled()) { LOGGER.debug("LLM Observability is disabled"); diff --git a/dd-java-agent/instrumentation/openai/build.gradle b/dd-java-agent/instrumentation/openai/build.gradle index ebc49e827ea..d70243ef320 100644 --- a/dd-java-agent/instrumentation/openai/build.gradle +++ b/dd-java-agent/instrumentation/openai/build.gradle @@ -8,8 +8,6 @@ muzzle { } // Instrumentation is currently in preview. Additional testing will be implemented before enabling this by default. -//minimumBranchCoverage = 0.0 -//minimumInstructionCoverage = 0.0 apply from: "$rootDir/gradle/java.gradle" diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java index 1fb2bffe8cd..43fdccf0d0e 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java @@ -5,12 +5,16 @@ import static net.bytebuddy.matcher.ElementMatchers.*; import static net.bytebuddy.matcher.ElementMatchers.isPublic; +import com.openai.models.chat.completions.ChatCompletion; import com.openai.models.chat.completions.ChatCompletionCreateParams; import com.openai.services.blocking.CompletionService; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.api.InstrumenterConfig; +import datadog.trace.api.llmobs.LLMObsSpan; import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -23,6 +27,11 @@ public ChatCompletionServiceInstrumentation() { super("openai-client"); } + @Override + protected boolean defaultEnabled() { + return InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); + } + @Override public String[] helperClassNames() { return new String[] { @@ -34,7 +43,7 @@ public String[] helperClassNames() { public Map contextStore() { Map contextStores = new HashMap<>(1); contextStores.put( - "com.openai.services.blocking.CompletionService", OpenAIClientInfo.class.getName()); + "com.openai.services.blocking.ChatCompletionService", OpenAIClientInfo.class.getName()); return contextStores; } @@ -47,7 +56,7 @@ public void methodAdvice(MethodTransformer transformer) { .and( takesArgument( 0, named("com.openai.models.completions.ChatCompletionCreateParams"))), - getClass().getName() + "$CompletionServiceAdvice"); + getClass().getName() + "$ChatCompletionServiceAdvice"); } @Override @@ -60,24 +69,37 @@ public ElementMatcher hierarchyMatcher() { return implementsInterface(named(hierarchyMarkerType())); } - public static class CompletionServiceAdvice { + public static class ChatCompletionServiceAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static AgentScope methodEnter( + public static Map methodEnter( @Advice.Argument(0) final ChatCompletionCreateParams params) { - - return OpenAIClientDecorator.DECORATE.startChatCompletionSpan(params); + Map spans = new HashMap<>(); + spans.put( + "datadog.trace.api.llmobs.LLMObsSpan", + OpenAIClientDecorator.DECORATE.startLLMObsChatCompletionSpan(params)); + spans.put( + "datadog.trace.bootstrap.instrumentation.api.AgentScope", + OpenAIClientDecorator.DECORATE.startChatCompletionSpan(params)); + return spans; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void methodExit( - @Advice.Enter final AgentScope span, + @Advice.Enter final Map spans, @Advice.This final CompletionService completionService, @Advice.Return final Object result, @Advice.Thrown final Throwable throwable) { OpenAIClientInfo info = InstrumentationContext.get(CompletionService.class, OpenAIClientInfo.class) .get(completionService); - OpenAIClientDecorator.DECORATE.finishSpan(span, result, throwable); + OpenAIClientDecorator.DECORATE.finishLLMObsChatCompletionSpan( + (LLMObsSpan) spans.get("datadog.trace.api.llmobs.LLMObsSpan"), + (ChatCompletion) result, + throwable); + OpenAIClientDecorator.DECORATE.finishSpan( + (AgentScope) spans.get("datadog.trace.bootstrap.instrumentation.api.AgentScope"), + result, + throwable); } } } diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java index 72ea7014a29..e70bfbe29d0 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java @@ -9,8 +9,10 @@ import com.openai.services.blocking.CompletionService; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.api.InstrumenterConfig; import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -23,6 +25,11 @@ public CompletionServiceInstrumentation() { super("openai-client"); } + @Override + protected boolean defaultEnabled() { + return InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); + } + @Override public String[] helperClassNames() { return new String[] { diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java index afe8cc34db0..722a685909d 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java @@ -10,7 +10,9 @@ import com.openai.models.embeddings.EmbeddingCreateParams; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.api.InstrumenterConfig; import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import java.util.Collections; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -23,6 +25,11 @@ public EmbeddingServiceInstrumentation() { super("openai", "openai-java"); } + @Override + protected boolean defaultEnabled() { + return InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); + } + @Override public String[] helperClassNames() { return new String[] { diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java index b23739c29ea..a8a04e1f3e8 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java @@ -10,6 +10,9 @@ import com.openai.models.embeddings.CreateEmbeddingResponse; import com.openai.models.embeddings.Embedding; import com.openai.models.embeddings.EmbeddingCreateParams; +import datadog.trace.api.Config; +import datadog.trace.api.llmobs.LLMObs; +import datadog.trace.api.llmobs.LLMObsSpan; import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.InternalSpanTypes; @@ -20,6 +23,8 @@ import java.util.Optional; public class OpenAIClientDecorator extends ClientDecorator { + private static final String mlApp = Config.get().getLlmObsMlApp(); + private static final String mlProvider = "openai"; private static final String COMPONENT_NAME = "openai"; private static final UTF8BytesString OPENAI_REQUEST = UTF8BytesString.create("openai.request"); @@ -42,14 +47,14 @@ protected CharSequence spanType() { @Override protected String service() { - return null; // Use default service name + return null; } public AgentScope startChatCompletionSpan(ChatCompletionCreateParams params) { AgentSpan span = startSpan(OPENAI_REQUEST); span.setTag("openai.request.endpoint", "/chat/completions"); span.setResourceName("chat.completions.create"); - span.setTag("openai.provider", "openai"); + span.setTag("openai.request.provider", "openai"); extractChatCompletionRequestData(span, params); afterStart(span); return activateSpan(span); @@ -59,7 +64,7 @@ public AgentScope startLLMChatCompletionSpan(ChatCompletionCreateParams params) AgentSpan span = startSpan(OPENAI_REQUEST); span.setTag("openai.request.endpoint", "/chat/completions"); span.setResourceName("chat.completions.create"); - span.setTag("openai.provider", "openai"); + span.setTag("openai.request.provider", "openai"); extractChatCompletionRequestData(span, params); afterStart(span); return activateSpan(span); @@ -88,6 +93,115 @@ public AgentScope startEmbeddingSpan(EmbeddingCreateParams params) { return activateSpan(span); } + public LLMObsSpan startLLMObsChatCompletionSpan(ChatCompletionCreateParams params) { + String modelName = params.model().toString(); + + LLMObsSpan llmObsSpan = + LLMObs.startLLMSpan("chat_completion", modelName, mlProvider, mlApp, null); + + // Extract and set input data from chat completion params + // May need to be reformatted + StringBuilder inputData = new StringBuilder(); + List messages = params.messages(); + for (int i = 0; i < messages.size(); i++) { + ChatCompletionMessageParam messageParam = messages.get(i); + if (i > 0) { + inputData.append(" | "); + } + + if (messageParam.isUser()) { + inputData.append("User: ").append(messageParam.asUser().content()); + } else if (messageParam.isAssistant()) { + inputData.append("Assistant: ").append(messageParam.asAssistant().content()); + } else if (messageParam.isDeveloper()) { + inputData.append("Developer: ").append(messageParam.asDeveloper().content()); + } else if (messageParam.isSystem()) { + inputData.append("System: ").append(messageParam.asSystem().content()); + } else if (messageParam.isTool()) { + inputData.append("Tool: ").append(messageParam.asTool().content()); + } + } + + if (inputData.length() > 0) { + llmObsSpan.annotateIO(inputData.toString(), null); // No output yet, will be set in response + } + + java.util.Map metadata = new java.util.HashMap<>(); + metadata.put("endpoint", "/chat/completions"); + metadata.put("provider", "openai"); + metadata.put("model", modelName); + + params.maxTokens().ifPresent(tokens -> metadata.put("max_tokens", tokens)); + params.temperature().ifPresent(temp -> metadata.put("temperature", temp)); + + llmObsSpan.setMetadata(metadata); + + return llmObsSpan; + } + + public void finishLLMObsChatCompletionSpan( + LLMObsSpan llmObsSpan, ChatCompletion response, Throwable throwable) { + try { + if (throwable != null) { + // Set error information + java.util.Map errorMetadata = new java.util.HashMap<>(); + errorMetadata.put("error.type", throwable.getClass().getSimpleName()); + errorMetadata.put("error.message", throwable.getMessage()); + llmObsSpan.setMetadata(errorMetadata); + } else if (response != null) { + StringBuilder outputData = new StringBuilder(); + List choices = response.choices(); + + for (int i = 0; i < choices.size(); i++) { + ChatCompletion.Choice choice = choices.get(i); + ChatCompletionMessage message = choice.message(); + + if (i > 0) { + outputData.append(" | "); + } + + // Extract content + Optional content = message.content(); + content.ifPresent(s -> outputData.append("Assistant: ").append(s)); + + // Extract tool calls if present + Optional> toolCalls = message.toolCalls(); + if (toolCalls.isPresent() && !toolCalls.get().isEmpty()) { + content.ifPresent(s -> outputData.append(" | ")); + outputData.append("Tool calls: "); + for (int j = 0; j < toolCalls.get().size(); j++) { + ChatCompletionMessageToolCall call = toolCalls.get().get(j); + if (j > 0) { + outputData.append(", "); + } + outputData + .append(call.function().name()) + .append("(") + .append(call.function().arguments()) + .append(")"); + } + } + } + + if (outputData.length() > 0) { + llmObsSpan.annotateIO(null, outputData.toString()); + } + java.util.Map responseMetadata = new java.util.HashMap<>(); + responseMetadata.put("response.choices_count", choices.size()); + + llmObsSpan.setMetadata(responseMetadata); + } + } catch (Exception e) { + java.util.Map errorMetadata = new java.util.HashMap<>(); + errorMetadata.put("error.type", "ResponseProcessingError"); + errorMetadata.put("error.message", "Failed to process response: " + e.getMessage()); + llmObsSpan.setMetadata(errorMetadata); + } finally { + // Always finish the span + llmObsSpan.finish(); + } + } + public void finishSpan(AgentScope scope, Object result, Throwable throwable) { AgentSpan span = scope.span(); @@ -107,8 +221,6 @@ public void finishSpan(AgentScope scope, Object result, Throwable throwable) { private void extractChatCompletionRequestData(AgentSpan span, ChatCompletionCreateParams params) { - // Extract model - span.setTag("openai.model.name", params.model().toString()); // Extract messages @@ -124,11 +236,7 @@ private void extractChatCompletionRequestData(AgentSpan span, ChatCompletionCrea private void extractCompletionRequestData( AgentSpan span, CompletionCreateParams completionParams) { - // Extract model - CompletionCreateParams.Model model = completionParams.model(); - if (model != null) { - span.setTag("openai.model.name", model.toString()); - } + span.setTag("openai.model.name", completionParams.model().toString()); // Extract prompt Optional prompt = completionParams.prompt(); @@ -156,18 +264,13 @@ private void extractCompletionRequestData( private void extractEmbeddingRequestData(AgentSpan span, EmbeddingCreateParams embeddingParams) { - // Extract model - Object model = embeddingParams.model(); - if (model != null) { - span.setTag("openai.model.name", model.toString()); - } - + span.setTag("openai.model.name", embeddingParams.model().toString()); // Extract input EmbeddingCreateParams.Input input = embeddingParams.input(); int inputIndex = 0; List inputStrings = input.asArrayOfStrings(); for (String inputItem : inputStrings) { - span.setTag("openai.request.input." + inputIndex, input.asString()); + span.setTag("openai.request.input." + inputIndex, inputItem); inputIndex++; } } @@ -205,25 +308,19 @@ private void extractMessageData( private void extractChatCompletionParameters(AgentSpan span, ChatCompletionCreateParams params) { // Extract max_tokens - Optional maxTokens = params.maxTokens(); - maxTokens.ifPresent(tokens -> span.setTag("openai.request.max_tokens", tokens)); + params + .maxCompletionTokens() + .ifPresent(tokens -> span.setTag("openai.request.max_tokens", tokens)); // Extract temperature - Optional temperature = params.temperature(); - temperature.ifPresent(temp -> span.setTag("openai.request.temperature", temp)); + params.temperature().ifPresent(temp -> span.setTag("openai.request.temperature", temp)); } private void extractCompletionParameters(AgentSpan span, CompletionCreateParams params) { // Extract max_tokens - if (params.maxTokens().isPresent()) { - span.setTag("openai.request.max_tokens", params.maxTokens().get()); - } - + params.maxTokens().ifPresent(tokens -> span.setTag("openai.request.max_tokens", tokens)); // Extract temperature - Optional temperature = params.temperature(); - if (temperature.isPresent()) { - span.setTag("openai.request.temperature", temperature.get()); - } + params.temperature().ifPresent(temp -> span.setTag("openai.request.temperature", temp)); } private void extractResponseData(AgentSpan span, Object result) { diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java index ba8280620d4..945736c0d27 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java @@ -10,10 +10,7 @@ public class OpenAIClientInfo { private String projectID; private String apiKey; - /** - * Creates an OpenAIClientInfo instance populated with relevant information from ClientOptions for - * use in span tags during tests and instrumentation - */ + // This information will be used later to populate future LLMObs spans public static OpenAIClientInfo fromClientOptions(ClientOptions options) { if (options == null) { return null; @@ -22,15 +19,12 @@ public static OpenAIClientInfo fromClientOptions(ClientOptions options) { OpenAIClientInfo info = new OpenAIClientInfo(); try { - // Extract base URL info.setBaseURL(options.baseUrl()); - // Extract organization ID if available if (options.organization().isPresent()) { info.setOrganizationID(options.organization().get()); } - // Extract project ID if available if (options.project().isPresent()) { info.setProjectID(options.project().get()); } diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java index f20c1eb7ca2..f50eea3d912 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java +++ b/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java @@ -10,7 +10,9 @@ import com.openai.services.blocking.chat.ChatCompletionService; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.api.InstrumenterConfig; import datadog.trace.bootstrap.InstrumentationContext; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -21,6 +23,11 @@ public OpenAIClientInstrumentation() { super("openai-client"); } + @Override + protected boolean defaultEnabled() { + return InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); + } + @Override public String[] helperClassNames() { return new String[] { @@ -60,6 +67,7 @@ public static void methodExit( @Advice.This final OpenAIClientImpl client, @Advice.Argument(0) final ClientOptions options, @Advice.Thrown final Throwable throwable) { + // This information will be used later to populate future LLMObs spans OpenAIClientInfo info = OpenAIClientInfo.fromClientOptions(options); if (info != null) { InstrumentationContext.get(CompletionService.class, OpenAIClientInfo.class) diff --git a/dd-trace-core/build.gradle b/dd-trace-core/build.gradle index d415949e629..98b63012548 100644 --- a/dd-trace-core/build.gradle +++ b/dd-trace-core/build.gradle @@ -72,6 +72,8 @@ dependencies { implementation project(':utils:socket-utils') // for span exception debugging compileOnly project(':dd-java-agent:agent-debugger:debugger-bootstrap') + // for llmobs + compileOnly project(':dd-java-agent:agent-llmobs') implementation libs.slf4j implementation libs.moshi diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 6b5ea0b5f10..2bd0fa4fa2d 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -97,6 +97,7 @@ import datadog.trace.core.taginterceptor.TagInterceptor; import datadog.trace.core.traceinterceptor.LatencyTraceInterceptor; import datadog.trace.lambda.LambdaHandler; +import datadog.trace.llmobs.LLMObsSystem; import datadog.trace.relocate.api.RatelimitedLogger; import datadog.trace.util.AgentTaskScheduler; import java.io.IOException; @@ -789,6 +790,10 @@ private CoreTracer( sharedCommunicationObjects.whenReady(this.dataStreamsMonitoring::start); + if (config.isLlmObsEnabled()) { + LLMObsSystem.start(null, sharedCommunicationObjects); + } + // Register context propagators HttpCodec.Extractor tracingExtractor = extractor == null ? HttpCodec.createExtractor(config, this::captureTraceConfig) : extractor; From f620b66781a0874a9293054a1f85caf9fbe5fc93 Mon Sep 17 00:00:00 2001 From: Nayeem Kamal Date: Mon, 4 Aug 2025 06:10:18 -0400 Subject: [PATCH 3/7] address PR comments --- .../instrumentation/{openai => openai-client}/build.gradle | 2 +- .../{openai => openai-client}/gradle.lockfile | 0 .../ChatCompletionServiceInstrumentation.java | 4 ++-- .../openaiclient}/CompletionServiceInstrumentation.java | 4 ++-- .../openaiclient}/EmbeddingServiceInstrumentation.java | 4 ++-- .../openaiclient}/OpenAIClientDecorator.java | 2 +- .../instrumentation/openaiclient}/OpenAIClientInfo.java | 7 ++++--- .../openaiclient}/OpenAIClientInstrumentation.java | 4 ++-- settings.gradle | 2 +- 9 files changed, 15 insertions(+), 14 deletions(-) rename dd-java-agent/instrumentation/{openai => openai-client}/build.gradle (98%) rename dd-java-agent/instrumentation/{openai => openai-client}/gradle.lockfile (100%) rename dd-java-agent/instrumentation/{openai/src/main/java/datadog/trace/instrumentation/openai => openai-client/src/main/java/datadog/trace/instrumentation/openaiclient}/ChatCompletionServiceInstrumentation.java (97%) rename dd-java-agent/instrumentation/{openai/src/main/java/datadog/trace/instrumentation/openai => openai-client/src/main/java/datadog/trace/instrumentation/openaiclient}/CompletionServiceInstrumentation.java (96%) rename dd-java-agent/instrumentation/{openai/src/main/java/datadog/trace/instrumentation/openai => openai-client/src/main/java/datadog/trace/instrumentation/openaiclient}/EmbeddingServiceInstrumentation.java (96%) rename dd-java-agent/instrumentation/{openai/src/main/java/datadog/trace/instrumentation/openai => openai-client/src/main/java/datadog/trace/instrumentation/openaiclient}/OpenAIClientDecorator.java (99%) rename dd-java-agent/instrumentation/{openai/src/main/java/datadog/trace/instrumentation/openai => openai-client/src/main/java/datadog/trace/instrumentation/openaiclient}/OpenAIClientInfo.java (93%) rename dd-java-agent/instrumentation/{openai/src/main/java/datadog/trace/instrumentation/openai => openai-client/src/main/java/datadog/trace/instrumentation/openaiclient}/OpenAIClientInstrumentation.java (96%) diff --git a/dd-java-agent/instrumentation/openai/build.gradle b/dd-java-agent/instrumentation/openai-client/build.gradle similarity index 98% rename from dd-java-agent/instrumentation/openai/build.gradle rename to dd-java-agent/instrumentation/openai-client/build.gradle index d70243ef320..ab67cf1d288 100644 --- a/dd-java-agent/instrumentation/openai/build.gradle +++ b/dd-java-agent/instrumentation/openai-client/build.gradle @@ -14,7 +14,7 @@ apply from: "$rootDir/gradle/java.gradle" addTestSuiteForDir('latestDepTest', 'test') dependencies { - compileOnly(group: 'com.openai', name: 'openai-java', version: '2.8.1') + compileOnly(group: 'com.openai', name: 'openai-java', version: '2.8.0') testImplementation(group: 'com.openai', name: 'openai-java') { version { diff --git a/dd-java-agent/instrumentation/openai/gradle.lockfile b/dd-java-agent/instrumentation/openai-client/gradle.lockfile similarity index 100% rename from dd-java-agent/instrumentation/openai/gradle.lockfile rename to dd-java-agent/instrumentation/openai-client/gradle.lockfile diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/ChatCompletionServiceInstrumentation.java similarity index 97% rename from dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java rename to dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/ChatCompletionServiceInstrumentation.java index 43fdccf0d0e..e2890778007 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/ChatCompletionServiceInstrumentation.java +++ b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/ChatCompletionServiceInstrumentation.java @@ -1,4 +1,4 @@ -package datadog.trace.instrumentation.openai; +package datadog.trace.instrumentation.openaiclient; import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface; import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; @@ -24,7 +24,7 @@ public class ChatCompletionServiceInstrumentation extends InstrumenterModule.Tracing implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice { public ChatCompletionServiceInstrumentation() { - super("openai-client"); + super("openai-client", "openai-java", "openai-2.8"); } @Override diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/CompletionServiceInstrumentation.java similarity index 96% rename from dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java rename to dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/CompletionServiceInstrumentation.java index e70bfbe29d0..11842ecdd48 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/CompletionServiceInstrumentation.java +++ b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/CompletionServiceInstrumentation.java @@ -1,4 +1,4 @@ -package datadog.trace.instrumentation.openai; +package datadog.trace.instrumentation.openaiclient; import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface; import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; @@ -22,7 +22,7 @@ public class CompletionServiceInstrumentation extends InstrumenterModule.Tracing implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice { public CompletionServiceInstrumentation() { - super("openai-client"); + super("openai-client", "openai-java", "openai-2.8"); } @Override diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/EmbeddingServiceInstrumentation.java similarity index 96% rename from dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java rename to dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/EmbeddingServiceInstrumentation.java index 722a685909d..ccb659d6030 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/EmbeddingServiceInstrumentation.java +++ b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/EmbeddingServiceInstrumentation.java @@ -1,4 +1,4 @@ -package datadog.trace.instrumentation.openai; +package datadog.trace.instrumentation.openaiclient; import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface; import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; @@ -22,7 +22,7 @@ public class EmbeddingServiceInstrumentation extends InstrumenterModule.Tracing implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice { public EmbeddingServiceInstrumentation() { - super("openai", "openai-java"); + super("openai", "openai-java", "openai-2.8"); } @Override diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java similarity index 99% rename from dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java rename to dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java index a8a04e1f3e8..213026d70f0 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientDecorator.java +++ b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java @@ -1,4 +1,4 @@ -package datadog.trace.instrumentation.openai; +package datadog.trace.instrumentation.openaiclient; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan; diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInfo.java similarity index 93% rename from dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java rename to dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInfo.java index 945736c0d27..6a2854d8aaf 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInfo.java +++ b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInfo.java @@ -1,4 +1,4 @@ -package datadog.trace.instrumentation.openai; +package datadog.trace.instrumentation.openaiclient; import com.openai.azure.credential.AzureApiKeyCredential; import com.openai.core.ClientOptions; @@ -33,10 +33,11 @@ public static OpenAIClientInfo fromClientOptions(ClientOptions options) { info.setApiKey(((BearerTokenCredential) options.credential()).token()); } else if (options.credential() instanceof AzureApiKeyCredential) { info.setApiKey(((AzureApiKeyCredential) options.credential()).apiKey()); - } else info.setApiKey(null); + } else { + info.setApiKey(null); + } } catch (Exception e) { - // TODO: returns empty info for now return info; } diff --git a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInstrumentation.java similarity index 96% rename from dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java rename to dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInstrumentation.java index f50eea3d912..5c512f12020 100644 --- a/dd-java-agent/instrumentation/openai/src/main/java/datadog/trace/instrumentation/openai/OpenAIClientInstrumentation.java +++ b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInstrumentation.java @@ -1,4 +1,4 @@ -package datadog.trace.instrumentation.openai; +package datadog.trace.instrumentation.openaiclient; import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; @@ -20,7 +20,7 @@ public class OpenAIClientInstrumentation extends InstrumenterModule.Tracing implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { public OpenAIClientInstrumentation() { - super("openai-client"); + super("openai-client", "openai-java", "openai-2.8"); } @Override diff --git a/settings.gradle b/settings.gradle index 28697f423a9..be05dcbb171 100644 --- a/settings.gradle +++ b/settings.gradle @@ -426,7 +426,7 @@ include ':dd-java-agent:instrumentation:ognl-appsec' include ':dd-java-agent:instrumentation:opensearch' include ':dd-java-agent:instrumentation:opensearch:rest' include ':dd-java-agent:instrumentation:opensearch:transport' -include ':dd-java-agent:instrumentation:openai' +include ':dd-java-agent:instrumentation:openai-client' include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-0.3' include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-1.4' include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-annotations-1.20' From 93a22fe2409acad53be88eb8f9b3053b704df9fd Mon Sep 17 00:00:00 2001 From: Nayeem Kamal Date: Mon, 4 Aug 2025 07:14:19 -0400 Subject: [PATCH 4/7] resolve settings merge conflict --- settings.gradle | 565 -------------------------------------------- settings.gradle.kts | 1 + 2 files changed, 1 insertion(+), 565 deletions(-) delete mode 100644 settings.gradle diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index be05dcbb171..00000000000 --- a/settings.gradle +++ /dev/null @@ -1,565 +0,0 @@ -pluginManagement { - repositories { - mavenLocal() - if (settings.hasProperty("gradlePluginProxy")) { - maven { - url settings["gradlePluginProxy"] - allowInsecureProtocol true - } - } - if (settings.hasProperty("mavenRepositoryProxy")) { - maven { - url settings["mavenRepositoryProxy"] - allowInsecureProtocol true - } - } - gradlePluginPortal() - mavenCentral() - } -} - -plugins { - id 'com.gradle.develocity' version '3.19.2' -} - -def isCI = System.getenv("CI") != null -def skipBuildscan = Boolean.valueOf(System.getenv("SKIP_BUILDSCAN")) -develocity { - buildScan { - termsOfUseUrl = 'https://gradle.com/help/legal-terms-of-use' - termsOfUseAgree = 'yes' - - publishing.onlyIf { isCI && !skipBuildscan } - } -} - -// Don't pollute the dependency cache with the build cache -if (isCI) { - buildCache { - local { - directory = "$rootDir/workspace/build-cache" - } - } -} - -rootProject.name = 'dd-trace-java' - -// external apis -include ':dd-trace-api' -include ':dd-trace-ot' -include ':dd-trace-ot:correlation-id-injection' - -// agent projects -include ':internal-api' -include ':internal-api:internal-api-9' -include ':dd-trace-core' -include ':dd-java-agent' -include ':dd-java-agent:agent-bootstrap' -include ':dd-java-agent:agent-builder' -include ':dd-java-agent:agent-tooling' -include ':dd-java-agent:agent-jmxfetch' -include ':dd-java-agent:agent-logging' -include ':dd-java-agent:agent-logs-intake' -include ':dd-java-agent:load-generator' - -// profiling -include ':dd-java-agent:agent-profiling' -include ':dd-java-agent:agent-profiling:profiling-ddprof' -include ':dd-java-agent:agent-profiling:profiling-controller' -include ':dd-java-agent:agent-profiling:profiling-controller-jfr' -include ':dd-java-agent:agent-profiling:profiling-controller-jfr:implementation' -include ':dd-java-agent:agent-profiling:profiling-controller-ddprof' -include ':dd-java-agent:agent-profiling:profiling-controller-openjdk' -include ':dd-java-agent:agent-profiling:profiling-controller-oracle' -include ':dd-java-agent:agent-profiling:profiling-testing' -include ':dd-java-agent:agent-profiling:profiling-uploader' -include ':dd-java-agent:agent-profiling:profiling-utils' - -include ':dd-java-agent:agent-debugger:debugger-bootstrap' -include ':dd-java-agent:agent-debugger:debugger-test-scala' -include ':dd-java-agent:agent-debugger:debugger-el' - -include ':dd-java-agent:agent-crashtracking' - -include ':dd-java-agent:agent-otel:otel-bootstrap' -include ':dd-java-agent:agent-otel:otel-shim' -include ':dd-java-agent:agent-otel:otel-tooling' - -include ':communication' -include ':components:cli' -include ':components:context' -include ':components:json' -include ':components:yaml' -include ':telemetry' -include ':remote-config:remote-config-api' -include ':remote-config:remote-config-core' - -include ':dd-java-agent:appsec' - -// ci-visibility -include ':dd-java-agent:agent-ci-visibility' - -// iast -include ':dd-java-agent:agent-iast' - -include ':dd-java-agent:cws-tls' - -// misc -include ':dd-java-agent:testing' -include ':utils:container-utils' -include ':utils:socket-utils' -include ':utils:test-agent-utils:decoder' -include ':utils:test-utils' -include ':utils:time-utils' -include ':utils:version-utils' - -// smoke tests -include ':dd-smoke-tests:apm-tracing-disabled' -include ':dd-smoke-tests:armeria-grpc' -include ':dd-smoke-tests:backend-mock' -include ':dd-smoke-tests:cli' -include ':dd-smoke-tests:concurrent:java-8' -include ':dd-smoke-tests:concurrent:java-21' -include ':dd-smoke-tests:crashtracking' -include ':dd-smoke-tests:custom-systemloader' -include ':dd-smoke-tests:dynamic-config' -include ':dd-smoke-tests:field-injection' -include ':dd-smoke-tests:gradle' -include ':dd-smoke-tests:grpc-1.5' -include ':dd-smoke-tests:java9-modules' -include ':dd-smoke-tests:jersey' -include ':dd-smoke-tests:jersey-2' -include ':dd-smoke-tests:jersey-3' -include ':dd-smoke-tests:jboss-modules' -include ':dd-smoke-tests:kafka-2' -include ':dd-smoke-tests:kafka-3' -include ':dd-smoke-tests:lib-injection' -include ':dd-smoke-tests:log-injection' -include ':dd-smoke-tests:maven' -include ':dd-smoke-tests:opentracing' -include ':dd-smoke-tests:opentelemetry' -include ':dd-smoke-tests:osgi' -include ':dd-smoke-tests:play-2.4' -include ':dd-smoke-tests:play-2.5' -include ':dd-smoke-tests:play-2.6' -include ':dd-smoke-tests:play-2.7' -include ':dd-smoke-tests:play-2.8' -include ':dd-smoke-tests:play-2.8-otel' -include ':dd-smoke-tests:play-2.8-split-routes' -include ':dd-smoke-tests:profiling-integration-tests' -include ':dd-smoke-tests:quarkus' -include ':dd-smoke-tests:quarkus-native' -include ':dd-smoke-tests:sample-trace' -include ':dd-smoke-tests:resteasy' -include ':dd-smoke-tests:spring-boot-3.0-native' -include ':dd-smoke-tests:spring-boot-2.4-webflux' -include ':dd-smoke-tests:spring-boot-2.5-webflux' -include ':dd-smoke-tests:spring-boot-2.6-webflux' -include ':dd-smoke-tests:spring-boot-2.7-webflux' -include ':dd-smoke-tests:spring-boot-3.0-webflux' -include ':dd-smoke-tests:spring-boot-2.3-webmvc-jetty' -include ':dd-smoke-tests:spring-boot-2.6-webmvc' -include ':dd-smoke-tests:spring-boot-3.0-webmvc' -include ':dd-smoke-tests:spring-boot-3.3-webmvc' -include ':dd-smoke-tests:spring-boot-rabbit' -include ':dd-smoke-tests:spring-security' -include ':dd-smoke-tests:springboot' -include ':dd-smoke-tests:springboot-freemarker' -include ':dd-smoke-tests:springboot-grpc' -include ':dd-smoke-tests:springboot-java-11' -include ':dd-smoke-tests:springboot-java-17' -include ':dd-smoke-tests:springboot-jetty-jsp' -include ':dd-smoke-tests:springboot-jpa' -include ':dd-smoke-tests:springboot-mongo' -include ':dd-smoke-tests:springboot-openliberty-20' -include ':dd-smoke-tests:springboot-openliberty-23' -include ':dd-smoke-tests:springboot-thymeleaf' -include ':dd-smoke-tests:springboot-tomcat' -include ':dd-smoke-tests:springboot-tomcat-jsp' -include ':dd-smoke-tests:springboot-velocity' -include ':dd-smoke-tests:vertx-3.4' -include ':dd-smoke-tests:vertx-3.9' -include ':dd-smoke-tests:vertx-3.9-resteasy' -include ':dd-smoke-tests:vertx-4.2' -include ':dd-smoke-tests:wildfly' -include ':dd-smoke-tests:appsec' -include ':dd-smoke-tests:appsec:spring-tomcat7' -include ':dd-smoke-tests:appsec:springboot' -include ':dd-smoke-tests:appsec:springboot-grpc' -include ':dd-smoke-tests:appsec:springboot-graphql' -include ':dd-smoke-tests:appsec:springboot-security' -include ':dd-smoke-tests:debugger-integration-tests' -include ':dd-smoke-tests:datastreams:kafkaschemaregistry' -include ':dd-smoke-tests:iast-propagation' -include ':dd-smoke-tests:iast-util' -include ':dd-smoke-tests:iast-util:iast-util-11' -include ':dd-smoke-tests:iast-util:iast-util-17' -// TODO this fails too often with a jgit failure, so disable until fixed -//include ':dd-smoke-tests:debugger-integration-tests:latest-jdk-app' - -// annotation processor for checking instrumentation advice -include ':dd-java-agent:instrumentation-annotation-processor' - -// instrumentation: -include ':dd-java-agent:instrumentation:aerospike-4' -include ':dd-java-agent:instrumentation:akka-concurrent' -include ':dd-java-agent:instrumentation:akka-http' -include ':dd-java-agent:instrumentation:akka-http:akka-http-10.0' -include ':dd-java-agent:instrumentation:akka-http:akka-http-10.2-iast' -include ':dd-java-agent:instrumentation:akka-http:akka-http-10.6' -include ':dd-java-agent:instrumentation:akka-init' -include ':dd-java-agent:instrumentation:apache-httpasyncclient-4' -include ':dd-java-agent:instrumentation:apache-httpclient-4' -include ':dd-java-agent:instrumentation:apache-httpclient-5' -include ':dd-java-agent:instrumentation:apache-httpcore-4' -include ':dd-java-agent:instrumentation:apache-httpcore-5' -include ':dd-java-agent:instrumentation:armeria-grpc' -include ':dd-java-agent:instrumentation:armeria-jetty' -include ':dd-java-agent:instrumentation:avro' -include ':dd-java-agent:instrumentation:aws-common' -include ':dd-java-agent:instrumentation:aws-java-dynamodb-2.0' -include ':dd-java-agent:instrumentation:aws-java-eventbridge-2.0' -include ':dd-java-agent:instrumentation:aws-java-sdk-1.11.0' -include ':dd-java-agent:instrumentation:aws-java-sdk-2.2' -include ':dd-java-agent:instrumentation:aws-java-sfn-2.0' -include ':dd-java-agent:instrumentation:aws-java-sns-1.0' -include ':dd-java-agent:instrumentation:aws-java-sns-2.0' -include ':dd-java-agent:instrumentation:aws-java-sqs-1.0' -include ':dd-java-agent:instrumentation:aws-java-sqs-2.0' -include ':dd-java-agent:instrumentation:aws-java-s3-2.0' -include ':dd-java-agent:instrumentation:aws-lambda-handler' -include ':dd-java-agent:instrumentation:axis-2' -include ':dd-java-agent:instrumentation:axway-api' -include ':dd-java-agent:instrumentation:azure-functions' -include ':dd-java-agent:instrumentation:caffeine' -include ':dd-java-agent:instrumentation:cdi-1.2' -include ':dd-java-agent:instrumentation:classloading' -include ':dd-java-agent:instrumentation:classloading:jboss-testing' -include ':dd-java-agent:instrumentation:classloading:jsr14-testing' -include ':dd-java-agent:instrumentation:classloading:osgi-testing' -include ':dd-java-agent:instrumentation:classloading:tomcat-testing' -include ':dd-java-agent:instrumentation:commons-codec-1' -include ':dd-java-agent:instrumentation:commons-fileupload' -include ':dd-java-agent:instrumentation:commons-httpclient-2' -include ':dd-java-agent:instrumentation:commons-lang-2' -include ':dd-java-agent:instrumentation:commons-lang-3' -include ':dd-java-agent:instrumentation:commons-text' -include ':dd-java-agent:instrumentation:couchbase' -include ':dd-java-agent:instrumentation:couchbase:couchbase-2.0' -include ':dd-java-agent:instrumentation:couchbase:couchbase-2.6' -include ':dd-java-agent:instrumentation:couchbase:couchbase-3.1' -include ':dd-java-agent:instrumentation:couchbase:couchbase-3.2' -include ':dd-java-agent:instrumentation:cucumber' -include ':dd-java-agent:instrumentation:cxf-2.1' -include ':dd-java-agent:instrumentation:datanucleus-4' -include ':dd-java-agent:instrumentation:datastax-cassandra-3' -include ':dd-java-agent:instrumentation:datastax-cassandra-3.8' -include ':dd-java-agent:instrumentation:datastax-cassandra-4' -include ':dd-java-agent:instrumentation:dropwizard' -include ':dd-java-agent:instrumentation:dropwizard:dropwizard-views' -include ':dd-java-agent:instrumentation:elasticsearch' -include ':dd-java-agent:instrumentation:elasticsearch:rest-5' -include ':dd-java-agent:instrumentation:elasticsearch:rest-6.4' -include ':dd-java-agent:instrumentation:elasticsearch:rest-7' -include ':dd-java-agent:instrumentation:elasticsearch:transport' -include ':dd-java-agent:instrumentation:elasticsearch:transport-2' -include ':dd-java-agent:instrumentation:elasticsearch:transport-5' -include ':dd-java-agent:instrumentation:elasticsearch:transport-5.3' -include ':dd-java-agent:instrumentation:elasticsearch:transport-6' -include ':dd-java-agent:instrumentation:elasticsearch:transport-7.3' -include ':dd-java-agent:instrumentation:enable-wallclock-profiling' -include ':dd-java-agent:instrumentation:exception-profiling' -include ':dd-java-agent:instrumentation:finatra-2.9' -include ':dd-java-agent:instrumentation:freemarker' -include ':dd-java-agent:instrumentation:freemarker:freemarker-2.3.9' -include ':dd-java-agent:instrumentation:freemarker:freemarker-2.3.24' -include ':dd-java-agent:instrumentation:glassfish' -include ':dd-java-agent:instrumentation:google-http-client' -include ':dd-java-agent:instrumentation:google-pubsub' -include ':dd-java-agent:instrumentation:graal:native-image' -include ':dd-java-agent:instrumentation:gradle-3.0' -include ':dd-java-agent:instrumentation:gradle-8.3' -include ':dd-java-agent:instrumentation:gradle-testing' -include ':dd-java-agent:instrumentation:graphql-java' -include ':dd-java-agent:instrumentation:graphql-java:graphql-java-14.0' -include ':dd-java-agent:instrumentation:graphql-java:graphql-java-20.0' -include ':dd-java-agent:instrumentation:graphql-java:graphql-java-common' -include ':dd-java-agent:instrumentation:grizzly-2' -include ':dd-java-agent:instrumentation:grizzly-client-1.9' -include ':dd-java-agent:instrumentation:grizzly-http-2.3.20' -include ':dd-java-agent:instrumentation:grpc-1.5' -include ':dd-java-agent:instrumentation:gson-1.6' -include ':dd-java-agent:instrumentation:guava-10' -include ':dd-java-agent:instrumentation:hazelcast-3.6' -include ':dd-java-agent:instrumentation:hazelcast-3.9' -include ':dd-java-agent:instrumentation:hazelcast-4.0' -include ':dd-java-agent:instrumentation:hibernate' -include ':dd-java-agent:instrumentation:hibernate:core-3.3' -include ':dd-java-agent:instrumentation:hibernate:core-4.0' -include ':dd-java-agent:instrumentation:hibernate:core-4.3' -include ':dd-java-agent:instrumentation:http-url-connection' -include ':dd-java-agent:instrumentation:hystrix-1.4' -include ':dd-java-agent:instrumentation:iast-instrumenter' -include ':dd-java-agent:instrumentation:ignite-2.0' -include ':dd-java-agent:instrumentation:jackson-core' -include ':dd-java-agent:instrumentation:jackson-core:jackson-core-1' -include ':dd-java-agent:instrumentation:jackson-core:jackson-core-2' -include ':dd-java-agent:instrumentation:jackson-core:jackson-core-2.6' -include ':dd-java-agent:instrumentation:jackson-core:jackson-core-2.8' -include ':dd-java-agent:instrumentation:jackson-core:jackson-core-2.12' -include ':dd-java-agent:instrumentation:jackson-core:jackson-core-2.16' -include ':dd-java-agent:instrumentation:jacoco' -include ':dd-java-agent:instrumentation:jakarta-jms' -include ':dd-java-agent:instrumentation:jakarta-mail' -include ':dd-java-agent:instrumentation:jakarta-rs-annotations-3' -include ':dd-java-agent:instrumentation:jakarta-ws-annotations' -include ':dd-java-agent:instrumentation:java-concurrent' -include ':dd-java-agent:instrumentation:java-concurrent:java-completablefuture' -include ':dd-java-agent:instrumentation:java-concurrent:java-concurrent-21' -include ':dd-java-agent:instrumentation:java-concurrent:lambda-testing' -include ':dd-java-agent:instrumentation:java-directbytebuffer' -include ':dd-java-agent:instrumentation:java-http-client' -include ':dd-java-agent:instrumentation:java-io' -include ':dd-java-agent:instrumentation:java-lang' -include ':dd-java-agent:instrumentation:java-lang:java-lang-9' -include ':dd-java-agent:instrumentation:java-lang:java-lang-11' -include ':dd-java-agent:instrumentation:java-lang:java-lang-15' -include ':dd-java-agent:instrumentation:java-lang:java-lang-17' -include ':dd-java-agent:instrumentation:java-net' -include ':dd-java-agent:instrumentation:java-security' -include ':dd-java-agent:instrumentation:java-util' -include ':dd-java-agent:instrumentation:javax-naming' -include ':dd-java-agent:instrumentation:javax-xml' -include ':dd-java-agent:instrumentation:javax-mail' -include ':dd-java-agent:instrumentation:jax-rs-annotations-1' -include ':dd-java-agent:instrumentation:jax-rs-annotations-2' -include ':dd-java-agent:instrumentation:jax-rs-annotations-2:filter-jersey' -include ':dd-java-agent:instrumentation:jax-rs-annotations-2:filter-resteasy-3.0' -include ':dd-java-agent:instrumentation:jax-rs-annotations-2:filter-resteasy-3.1' -include ':dd-java-agent:instrumentation:jax-rs-client-1.1' -include ':dd-java-agent:instrumentation:jax-rs-client-2.0' -include ':dd-java-agent:instrumentation:jax-rs-client-2.0:connection-error-handling-jersey' -include ':dd-java-agent:instrumentation:jax-rs-client-2.0:connection-error-handling-resteasy' -include ':dd-java-agent:instrumentation:jax-ws-annotations-1' -include ':dd-java-agent:instrumentation:jax-ws-annotations-2' -include ':dd-java-agent:instrumentation:jboss-logmanager' -include ':dd-java-agent:instrumentation:jboss-modules' -include ':dd-java-agent:instrumentation:jdbc' -include ':dd-java-agent:instrumentation:jdbc:scalikejdbc' -include ':dd-java-agent:instrumentation:jedis-1.4' -include ':dd-java-agent:instrumentation:jedis-3.0' -include ':dd-java-agent:instrumentation:jedis-4.0' -include ':dd-java-agent:instrumentation:jersey' -include ':dd-java-agent:instrumentation:jersey-2-appsec' -include ':dd-java-agent:instrumentation:jersey-3-appsec' -include ':dd-java-agent:instrumentation:jetty-7.0' -include ':dd-java-agent:instrumentation:jetty-7.6' -include ':dd-java-agent:instrumentation:jetty-9' -include ':dd-java-agent:instrumentation:jetty-11' -include ':dd-java-agent:instrumentation:jetty-12' -include ':dd-java-agent:instrumentation:jetty-appsec-7' -include ':dd-java-agent:instrumentation:jetty-appsec-8.1.3' -include ':dd-java-agent:instrumentation:jetty-appsec-9.2' -include ':dd-java-agent:instrumentation:jetty-appsec-9.3' -include ':dd-java-agent:instrumentation:jetty-client:jetty-client-common' -include ':dd-java-agent:instrumentation:jetty-client:jetty-client-9.1' -include ':dd-java-agent:instrumentation:jetty-client:jetty-client-10.0' -include ':dd-java-agent:instrumentation:jetty-client:jetty-client-12.0' -include ':dd-java-agent:instrumentation:jetty-common' -include ':dd-java-agent:instrumentation:jetty-util' -include ':dd-java-agent:instrumentation:jms' -include ':dd-java-agent:instrumentation:jose-jwt' -include ':dd-java-agent:instrumentation:org-json' -include ':dd-java-agent:instrumentation:jsp-2.3' -include ':dd-java-agent:instrumentation:junit-4.10' -include ':dd-java-agent:instrumentation:junit-4.10:cucumber-junit-4' -include ':dd-java-agent:instrumentation:junit-4.10:junit-4.13' -include ':dd-java-agent:instrumentation:junit-4.10:munit-junit-4' -include ':dd-java-agent:instrumentation:junit-5.3' -include ':dd-java-agent:instrumentation:junit-5.3:junit-5.8' -include ':dd-java-agent:instrumentation:junit-5.3:cucumber-junit-5' -include ':dd-java-agent:instrumentation:junit-5.3:spock-junit-5' -include ':dd-java-agent:instrumentation:kafka-clients-0.11' -include ':dd-java-agent:instrumentation:kafka-clients-3.8' -include ':dd-java-agent:instrumentation:kafka-common' -include ':dd-java-agent:instrumentation:kafka-connect-0.11' -include ':dd-java-agent:instrumentation:kafka-streams-0.11' -include ':dd-java-agent:instrumentation:kafka-streams-1.0' -include ':dd-java-agent:instrumentation:karate' -include ':dd-java-agent:instrumentation:kotlin-coroutines' -include ':dd-java-agent:instrumentation:lettuce-4' -include ':dd-java-agent:instrumentation:lettuce-5' -include ':dd-java-agent:instrumentation:liberty-20' -include ':dd-java-agent:instrumentation:liberty-23' -include ':dd-java-agent:instrumentation:log4j-2.7' -include ':dd-java-agent:instrumentation:log4j1' -include ':dd-java-agent:instrumentation:log4j2' -include ':dd-java-agent:instrumentation:log4j2:logs-intake' -include ':dd-java-agent:instrumentation:logback-1' -include ':dd-java-agent:instrumentation:maven-3.2.1' -include ':dd-java-agent:instrumentation:maven-surefire' -include ':dd-java-agent:instrumentation:micronaut' -include ':dd-java-agent:instrumentation:micronaut:http-server-netty-2.0' -include ':dd-java-agent:instrumentation:micronaut:http-server-netty-3.0' -include ':dd-java-agent:instrumentation:micronaut:http-server-netty-4.0' -include ':dd-java-agent:instrumentation:mongo' -include ':dd-java-agent:instrumentation:mongo:common' -include ':dd-java-agent:instrumentation:mongo:bson-document' -include ':dd-java-agent:instrumentation:mongo:driver-3.1' -include ':dd-java-agent:instrumentation:mongo:driver-3.4' -include ':dd-java-agent:instrumentation:mongo:driver-3.1-core-test' -include ':dd-java-agent:instrumentation:mongo:driver-3.7-core-test' -include ':dd-java-agent:instrumentation:mongo:driver-4.0' -include ':dd-java-agent:instrumentation:mongo:driver-3.3-async-test' -include ':dd-java-agent:instrumentation:mongo:driver-3.10-sync-test' -include ':dd-java-agent:instrumentation:mule-4' -include ':dd-java-agent:instrumentation:netty-3.8' -include ':dd-java-agent:instrumentation:netty-4.0' -include ':dd-java-agent:instrumentation:netty-4.1-shared' -include ':dd-java-agent:instrumentation:netty-4.1' -include ':dd-java-agent:instrumentation:netty-buffer-4' -include ':dd-java-agent:instrumentation:netty-concurrent-4' -include ':dd-java-agent:instrumentation:netty-promise-4' -include ':dd-java-agent:instrumentation:okhttp-2' -include ':dd-java-agent:instrumentation:okhttp-3' -include ':dd-java-agent:instrumentation:ognl-appsec' -include ':dd-java-agent:instrumentation:opensearch' -include ':dd-java-agent:instrumentation:opensearch:rest' -include ':dd-java-agent:instrumentation:opensearch:transport' -include ':dd-java-agent:instrumentation:openai-client' -include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-0.3' -include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-1.4' -include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-annotations-1.20' -include ':dd-java-agent:instrumentation:opentelemetry:opentelemetry-annotations-1.26' -include ':dd-java-agent:instrumentation:opentracing' -include ':dd-java-agent:instrumentation:opentracing:api-0.31' -include ':dd-java-agent:instrumentation:opentracing:api-0.32' -include ':dd-java-agent:instrumentation:osgi-4.3' -include ':dd-java-agent:instrumentation:owasp-esapi-2' -include ':dd-java-agent:instrumentation:pekko-concurrent' -include ':dd-java-agent:instrumentation:pekko-http-1.0' -include ':dd-java-agent:instrumentation:play-2.3' -include ':dd-java-agent:instrumentation:play-2.4' -include ':dd-java-agent:instrumentation:play-2.6' -include ':dd-java-agent:instrumentation:play-ws' -include ':dd-java-agent:instrumentation:play-ws-1' -include ':dd-java-agent:instrumentation:play-ws-2' -include ':dd-java-agent:instrumentation:play-ws-2.1' -include ':dd-java-agent:instrumentation:protobuf' -include ':dd-java-agent:instrumentation:quartz-2' -include ':dd-java-agent:instrumentation:rabbitmq-amqp-2.7' -include ':dd-java-agent:instrumentation:ratpack-1.5' -include ':dd-java-agent:instrumentation:reactive-streams' -include ':dd-java-agent:instrumentation:reactor-core-3.1' -include ':dd-java-agent:instrumentation:reactor-netty-1' -include ':dd-java-agent:instrumentation:rediscala-1.8.0' -include ':dd-java-agent:instrumentation:renaissance' -include ':dd-java-agent:instrumentation:resteasy-appsec' -include ':dd-java-agent:instrumentation:restlet-2.2' -include ':dd-java-agent:instrumentation:rmi' -include ':dd-java-agent:instrumentation:rxjava-1' -include ':dd-java-agent:instrumentation:rxjava-2' -include ':dd-java-agent:instrumentation:scala' -include ':dd-java-agent:instrumentation:scala-concurrent' -include ':dd-java-agent:instrumentation:scala-promise' -include ':dd-java-agent:instrumentation:scala-promise:scala-promise-2.10' -include ':dd-java-agent:instrumentation:scala-promise:scala-promise-2.13' -include ':dd-java-agent:instrumentation:scalatest' -include ':dd-java-agent:instrumentation:selenium' -include ':dd-java-agent:instrumentation:servicetalk' -include ':dd-java-agent:instrumentation:servicetalk:servicetalk-0.42.0' -include ':dd-java-agent:instrumentation:servicetalk:servicetalk-0.42.56' -include ':dd-java-agent:instrumentation:servlet' -include ':dd-java-agent:instrumentation:servlet-common' -include ':dd-java-agent:instrumentation:servlet:request-2' -include ':dd-java-agent:instrumentation:servlet:request-3' -include ':dd-java-agent:instrumentation:servlet:request-5' -include ':dd-java-agent:instrumentation:shutdown' -include ':dd-java-agent:instrumentation:slick' -include ':dd-java-agent:instrumentation:snakeyaml' -include ':dd-java-agent:instrumentation:span-origin' -include ':dd-java-agent:instrumentation:spark' -include ':dd-java-agent:instrumentation:spark:spark_2.12' -include ':dd-java-agent:instrumentation:spark:spark_2.13' -include ':dd-java-agent:instrumentation:spark-executor' -include ':dd-java-agent:instrumentation:sparkjava-2.3' -include ':dd-java-agent:instrumentation:spray-1.3' -include ':dd-java-agent:instrumentation:spring-beans' -include ':dd-java-agent:instrumentation:spring-boot' -include ':dd-java-agent:instrumentation:spring-cloud-zuul-2' -include ':dd-java-agent:instrumentation:spring-core' -include ':dd-java-agent:instrumentation:spring-data-1.8' -include ':dd-java-agent:instrumentation:spring-jms-3.1' -include ':dd-java-agent:instrumentation:spring-messaging-4' -include ':dd-java-agent:instrumentation:spring-rabbit' -include ':dd-java-agent:instrumentation:spring-scheduling-3.1' -include ':dd-java-agent:instrumentation:spring-security-5' -include ':dd-java-agent:instrumentation:spring-security-6' -include ':dd-java-agent:instrumentation:spring-webflux-5' -include ':dd-java-agent:instrumentation:spring-webflux-6' -include ':dd-java-agent:instrumentation:spring-webmvc-3.1' -include ':dd-java-agent:instrumentation:spring-webmvc-5.3' -include ':dd-java-agent:instrumentation:spring-webmvc-6.0' -include ':dd-java-agent:instrumentation:spring-ws-2' -include ':dd-java-agent:instrumentation:spymemcached-2.10' -include ':dd-java-agent:instrumentation:sslsocket' -include ':dd-java-agent:instrumentation:synapse-3' -include ':dd-java-agent:instrumentation:testng' -include ':dd-java-agent:instrumentation:testng:testng-6' -include ':dd-java-agent:instrumentation:testng:testng-7' -include ':dd-java-agent:instrumentation:thymeleaf' -include ':dd-java-agent:instrumentation:tinylog-2' -include ':dd-java-agent:instrumentation:tibco-businessworks' -include ':dd-java-agent:instrumentation:tibco-businessworks:tibcobw-stubs' -include ':dd-java-agent:instrumentation:tibco-businessworks:tibcobw-5' -include ':dd-java-agent:instrumentation:tibco-businessworks:tibcobw-6' -include ':dd-java-agent:instrumentation:tomcat-5.5' -include ':dd-java-agent:instrumentation:tomcat-5.5-common' -include ':dd-java-agent:instrumentation:tomcat-appsec-5.5' -include ':dd-java-agent:instrumentation:tomcat-appsec-6' -include ':dd-java-agent:instrumentation:tomcat-appsec-7' -include ':dd-java-agent:instrumentation:tomcat-classloading-9' -include ':dd-java-agent:instrumentation:trace-annotation' -include ':dd-java-agent:instrumentation:twilio' -include ':dd-java-agent:instrumentation:unbescape' -include ':dd-java-agent:instrumentation:undertow' -include ':dd-java-agent:instrumentation:undertow:undertow-2.0' -include ':dd-java-agent:instrumentation:undertow:undertow-2.2' -include ':dd-java-agent:instrumentation:valkey-java' -include ':dd-java-agent:instrumentation:velocity' -include ':dd-java-agent:instrumentation:vertx-mysql-client-3.9' -include ':dd-java-agent:instrumentation:vertx-mysql-client-4.0' -include ':dd-java-agent:instrumentation:vertx-mysql-client-4.4.2' -include ':dd-java-agent:instrumentation:vertx-pg-client-4.0' -include ':dd-java-agent:instrumentation:vertx-pg-client-4.4.2' -include ':dd-java-agent:instrumentation:vertx-redis-client-3.9' -include ':dd-java-agent:instrumentation:vertx-redis-client-3.9:stubs' -include ':dd-java-agent:instrumentation:vertx-rx-3.5' -include ':dd-java-agent:instrumentation:vertx-sql-client-3.9' -include ':dd-java-agent:instrumentation:vertx-web-3.4' -include ':dd-java-agent:instrumentation:vertx-web-3.5' -include ':dd-java-agent:instrumentation:vertx-web-3.9' -include ':dd-java-agent:instrumentation:vertx-web-4.0' -include ':dd-java-agent:instrumentation:vertx-web-5.0' -include ':dd-java-agent:instrumentation:redisson' -include ':dd-java-agent:instrumentation:redisson:redisson-2.0.0' -include ':dd-java-agent:instrumentation:redisson:redisson-2.3.0' -include ':dd-java-agent:instrumentation:redisson:redisson-3.10.3' -include ':dd-java-agent:instrumentation:weaver' -include ':dd-java-agent:instrumentation:websocket' -include ':dd-java-agent:instrumentation:websocket:jakarta-websocket-2.0' -include ':dd-java-agent:instrumentation:websocket:javax-websocket-1.0' -include ':dd-java-agent:instrumentation:websocket:jetty-websocket' -include ':dd-java-agent:instrumentation:websocket:jetty-websocket:jetty-websocket-10' -include ':dd-java-agent:instrumentation:websocket:jetty-websocket:jetty-websocket-11' -include ':dd-java-agent:instrumentation:websocket:jetty-websocket:jetty-websocket-12' -include ':dd-java-agent:instrumentation:websphere-jmx' -include ':dd-java-agent:instrumentation:wildfly-9' -include ':dd-java-agent:instrumentation:zio' -include ':dd-java-agent:instrumentation:zio:zio-2.0' - -// benchmark -include ':dd-java-agent:benchmark' -include ':dd-java-agent:benchmark-integration' -include ':dd-java-agent:benchmark-integration:jetty-perftest' -include ':dd-java-agent:benchmark-integration:play-perftest' diff --git a/settings.gradle.kts b/settings.gradle.kts index 70bbfb5679f..cea51555200 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -459,6 +459,7 @@ include( ":dd-java-agent:instrumentation:okhttp-2", ":dd-java-agent:instrumentation:okhttp-3", ":dd-java-agent:instrumentation:ognl-appsec", + ":dd-java-agent:instrumentation:openai-client", ":dd-java-agent:instrumentation:opensearch", ":dd-java-agent:instrumentation:opensearch:rest", ":dd-java-agent:instrumentation:opensearch:transport", From ce288b10e2b8866317a5932b7e09a4ef0665fc60 Mon Sep 17 00:00:00 2001 From: gary-huang Date: Mon, 4 Aug 2025 09:39:35 -0400 Subject: [PATCH 5/7] import maps --- .../openaiclient/OpenAIClientDecorator.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java index 213026d70f0..a3e6762bccd 100644 --- a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java +++ b/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java @@ -19,7 +19,9 @@ import datadog.trace.bootstrap.instrumentation.api.Tags; import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.ClientDecorator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; public class OpenAIClientDecorator extends ClientDecorator { @@ -126,7 +128,7 @@ public LLMObsSpan startLLMObsChatCompletionSpan(ChatCompletionCreateParams param llmObsSpan.annotateIO(inputData.toString(), null); // No output yet, will be set in response } - java.util.Map metadata = new java.util.HashMap<>(); + Map metadata = new HashMap<>(); metadata.put("endpoint", "/chat/completions"); metadata.put("provider", "openai"); metadata.put("model", modelName); @@ -144,7 +146,7 @@ public void finishLLMObsChatCompletionSpan( try { if (throwable != null) { // Set error information - java.util.Map errorMetadata = new java.util.HashMap<>(); + Map errorMetadata = new HashMap<>(); errorMetadata.put("error.type", throwable.getClass().getSimpleName()); errorMetadata.put("error.message", throwable.getMessage()); llmObsSpan.setMetadata(errorMetadata); @@ -186,13 +188,13 @@ public void finishLLMObsChatCompletionSpan( if (outputData.length() > 0) { llmObsSpan.annotateIO(null, outputData.toString()); } - java.util.Map responseMetadata = new java.util.HashMap<>(); + Map responseMetadata = new HashMap<>(); responseMetadata.put("response.choices_count", choices.size()); llmObsSpan.setMetadata(responseMetadata); } } catch (Exception e) { - java.util.Map errorMetadata = new java.util.HashMap<>(); + Map errorMetadata = new HashMap<>(); errorMetadata.put("error.type", "ResponseProcessingError"); errorMetadata.put("error.message", "Failed to process response: " + e.getMessage()); llmObsSpan.setMetadata(errorMetadata); From 0066c5d6e54f5d2eeee36d1a727d0003e419fe29 Mon Sep 17 00:00:00 2001 From: Nayeem Kamal Date: Tue, 12 Aug 2025 10:08:08 -0400 Subject: [PATCH 6/7] addressed pr comments --- .../src/main/java/datadog/trace/llmobs/LLMObsSystem.java | 3 +-- .../{openai-client => openai-java-2.8}/build.gradle | 0 .../{openai-client => openai-java-2.8}/gradle.lockfile | 0 .../openaiclient/ChatCompletionServiceInstrumentation.java | 5 +++-- .../openaiclient/CompletionServiceInstrumentation.java | 5 +++-- .../openaiclient/EmbeddingServiceInstrumentation.java | 5 +++-- .../instrumentation/openaiclient/OpenAIClientDecorator.java | 0 .../trace/instrumentation/openaiclient/OpenAIClientInfo.java | 0 .../openaiclient/OpenAIClientInstrumentation.java | 5 +++-- .../src/main/java/datadog/trace/core/CoreTracer.java | 2 +- settings.gradle.kts | 2 +- 11 files changed, 15 insertions(+), 12 deletions(-) rename dd-java-agent/instrumentation/{openai-client => openai-java-2.8}/build.gradle (100%) rename dd-java-agent/instrumentation/{openai-client => openai-java-2.8}/gradle.lockfile (100%) rename dd-java-agent/instrumentation/{openai-client => openai-java-2.8}/src/main/java/datadog/trace/instrumentation/openaiclient/ChatCompletionServiceInstrumentation.java (96%) rename dd-java-agent/instrumentation/{openai-client => openai-java-2.8}/src/main/java/datadog/trace/instrumentation/openaiclient/CompletionServiceInstrumentation.java (95%) rename dd-java-agent/instrumentation/{openai-client => openai-java-2.8}/src/main/java/datadog/trace/instrumentation/openaiclient/EmbeddingServiceInstrumentation.java (94%) rename dd-java-agent/instrumentation/{openai-client => openai-java-2.8}/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java (100%) rename dd-java-agent/instrumentation/{openai-client => openai-java-2.8}/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInfo.java (100%) rename dd-java-agent/instrumentation/{openai-client => openai-java-2.8}/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInstrumentation.java (94%) diff --git a/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java b/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java index 42404944c2b..0ad80450a4b 100644 --- a/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java +++ b/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java @@ -9,7 +9,6 @@ import datadog.trace.llmobs.domain.DDLLMObsSpan; import datadog.trace.llmobs.domain.LLMObsEval; import datadog.trace.llmobs.domain.LLMObsInternal; -import java.lang.instrument.Instrumentation; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; @@ -22,7 +21,7 @@ public class LLMObsSystem { private static final String CUSTOM_MODEL_VAL = "custom"; - public static void start(@Nullable Instrumentation inst, SharedCommunicationObjects sco) { + public static void start(SharedCommunicationObjects sco) { Config config = Config.get(); if (!config.isLlmObsEnabled()) { LOGGER.debug("LLM Observability is disabled"); diff --git a/dd-java-agent/instrumentation/openai-client/build.gradle b/dd-java-agent/instrumentation/openai-java-2.8/build.gradle similarity index 100% rename from dd-java-agent/instrumentation/openai-client/build.gradle rename to dd-java-agent/instrumentation/openai-java-2.8/build.gradle diff --git a/dd-java-agent/instrumentation/openai-client/gradle.lockfile b/dd-java-agent/instrumentation/openai-java-2.8/gradle.lockfile similarity index 100% rename from dd-java-agent/instrumentation/openai-client/gradle.lockfile rename to dd-java-agent/instrumentation/openai-java-2.8/gradle.lockfile diff --git a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/ChatCompletionServiceInstrumentation.java b/dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/ChatCompletionServiceInstrumentation.java similarity index 96% rename from dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/ChatCompletionServiceInstrumentation.java rename to dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/ChatCompletionServiceInstrumentation.java index e2890778007..9dad1c236cf 100644 --- a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/ChatCompletionServiceInstrumentation.java +++ b/dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/ChatCompletionServiceInstrumentation.java @@ -24,12 +24,13 @@ public class ChatCompletionServiceInstrumentation extends InstrumenterModule.Tracing implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice { public ChatCompletionServiceInstrumentation() { - super("openai-client", "openai-java", "openai-2.8"); + super("openai-java", "openai-java-2.8", "openai-client"); } @Override protected boolean defaultEnabled() { - return InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); + return super.defaultEnabled() + && InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); } @Override diff --git a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/CompletionServiceInstrumentation.java b/dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/CompletionServiceInstrumentation.java similarity index 95% rename from dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/CompletionServiceInstrumentation.java rename to dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/CompletionServiceInstrumentation.java index 11842ecdd48..edad2d0f071 100644 --- a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/CompletionServiceInstrumentation.java +++ b/dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/CompletionServiceInstrumentation.java @@ -22,12 +22,13 @@ public class CompletionServiceInstrumentation extends InstrumenterModule.Tracing implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice { public CompletionServiceInstrumentation() { - super("openai-client", "openai-java", "openai-2.8"); + super("openai-java", "openai-java-2.8", "openai-client"); } @Override protected boolean defaultEnabled() { - return InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); + return super.defaultEnabled() + && InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); } @Override diff --git a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/EmbeddingServiceInstrumentation.java b/dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/EmbeddingServiceInstrumentation.java similarity index 94% rename from dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/EmbeddingServiceInstrumentation.java rename to dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/EmbeddingServiceInstrumentation.java index ccb659d6030..6e313adf14a 100644 --- a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/EmbeddingServiceInstrumentation.java +++ b/dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/EmbeddingServiceInstrumentation.java @@ -22,12 +22,13 @@ public class EmbeddingServiceInstrumentation extends InstrumenterModule.Tracing implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice { public EmbeddingServiceInstrumentation() { - super("openai", "openai-java", "openai-2.8"); + super("openai-java", "openai-java-2.8", "openai-client"); } @Override protected boolean defaultEnabled() { - return InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); + return super.defaultEnabled() + && InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); } @Override diff --git a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java b/dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java similarity index 100% rename from dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java rename to dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientDecorator.java diff --git a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInfo.java b/dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInfo.java similarity index 100% rename from dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInfo.java rename to dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInfo.java diff --git a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInstrumentation.java b/dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInstrumentation.java similarity index 94% rename from dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInstrumentation.java rename to dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInstrumentation.java index 5c512f12020..9163373d0b5 100644 --- a/dd-java-agent/instrumentation/openai-client/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInstrumentation.java +++ b/dd-java-agent/instrumentation/openai-java-2.8/src/main/java/datadog/trace/instrumentation/openaiclient/OpenAIClientInstrumentation.java @@ -20,12 +20,13 @@ public class OpenAIClientInstrumentation extends InstrumenterModule.Tracing implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { public OpenAIClientInstrumentation() { - super("openai-client", "openai-java", "openai-2.8"); + super("openai-java", "openai-java-2.8", "openai-client"); } @Override protected boolean defaultEnabled() { - return InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); + return super.defaultEnabled() + && InstrumenterConfig.get().isIntegrationEnabled(Collections.singleton("openai"), false); } @Override diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 2bd0fa4fa2d..64859905871 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -791,7 +791,7 @@ private CoreTracer( sharedCommunicationObjects.whenReady(this.dataStreamsMonitoring::start); if (config.isLlmObsEnabled()) { - LLMObsSystem.start(null, sharedCommunicationObjects); + LLMObsSystem.start(sharedCommunicationObjects); } // Register context propagators diff --git a/settings.gradle.kts b/settings.gradle.kts index cea51555200..be00818e1a7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -459,7 +459,7 @@ include( ":dd-java-agent:instrumentation:okhttp-2", ":dd-java-agent:instrumentation:okhttp-3", ":dd-java-agent:instrumentation:ognl-appsec", - ":dd-java-agent:instrumentation:openai-client", + ":dd-java-agent:instrumentation:openai-java-2.8", ":dd-java-agent:instrumentation:opensearch", ":dd-java-agent:instrumentation:opensearch:rest", ":dd-java-agent:instrumentation:opensearch:transport", From 298f31f1de2197247567ec94a10da0fa5c5bd22c Mon Sep 17 00:00:00 2001 From: Nayeem Kamal Date: Tue, 12 Aug 2025 14:05:07 -0400 Subject: [PATCH 7/7] address pr comments --- .../src/main/java/datadog/trace/llmobs/LLMObsSystem.java | 3 ++- dd-trace-core/build.gradle | 2 -- .../src/main/java/datadog/trace/core/CoreTracer.java | 5 ----- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java b/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java index 0ad80450a4b..42404944c2b 100644 --- a/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java +++ b/dd-java-agent/agent-llmobs/src/main/java/datadog/trace/llmobs/LLMObsSystem.java @@ -9,6 +9,7 @@ import datadog.trace.llmobs.domain.DDLLMObsSpan; import datadog.trace.llmobs.domain.LLMObsEval; import datadog.trace.llmobs.domain.LLMObsInternal; +import java.lang.instrument.Instrumentation; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; @@ -21,7 +22,7 @@ public class LLMObsSystem { private static final String CUSTOM_MODEL_VAL = "custom"; - public static void start(SharedCommunicationObjects sco) { + public static void start(@Nullable Instrumentation inst, SharedCommunicationObjects sco) { Config config = Config.get(); if (!config.isLlmObsEnabled()) { LOGGER.debug("LLM Observability is disabled"); diff --git a/dd-trace-core/build.gradle b/dd-trace-core/build.gradle index 98b63012548..d415949e629 100644 --- a/dd-trace-core/build.gradle +++ b/dd-trace-core/build.gradle @@ -72,8 +72,6 @@ dependencies { implementation project(':utils:socket-utils') // for span exception debugging compileOnly project(':dd-java-agent:agent-debugger:debugger-bootstrap') - // for llmobs - compileOnly project(':dd-java-agent:agent-llmobs') implementation libs.slf4j implementation libs.moshi diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 64859905871..6b5ea0b5f10 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -97,7 +97,6 @@ import datadog.trace.core.taginterceptor.TagInterceptor; import datadog.trace.core.traceinterceptor.LatencyTraceInterceptor; import datadog.trace.lambda.LambdaHandler; -import datadog.trace.llmobs.LLMObsSystem; import datadog.trace.relocate.api.RatelimitedLogger; import datadog.trace.util.AgentTaskScheduler; import java.io.IOException; @@ -790,10 +789,6 @@ private CoreTracer( sharedCommunicationObjects.whenReady(this.dataStreamsMonitoring::start); - if (config.isLlmObsEnabled()) { - LLMObsSystem.start(sharedCommunicationObjects); - } - // Register context propagators HttpCodec.Extractor tracingExtractor = extractor == null ? HttpCodec.createExtractor(config, this::captureTraceConfig) : extractor;