55import datadog .communication .serialization .Writable ;
66import datadog .trace .api .DDTags ;
77import datadog .trace .api .intake .TrackType ;
8+ import datadog .trace .api .llmobs .LLMObs ;
89import datadog .trace .api .llmobs .LLMObsTags ;
910import datadog .trace .bootstrap .instrumentation .api .InternalSpanTypes ;
1011import datadog .trace .bootstrap .instrumentation .api .Tags ;
@@ -63,6 +64,15 @@ public class LLMObsSpanMapper implements RemoteMapper {
6364 private static final byte [] METRICS = "metrics" .getBytes (StandardCharsets .UTF_8 );
6465 private static final byte [] TAGS = "tags" .getBytes (StandardCharsets .UTF_8 );
6566
67+ private static final byte [] LLM_MESSAGE_ROLE = "role" .getBytes (StandardCharsets .UTF_8 );
68+ private static final byte [] LLM_MESSAGE_CONTENT = "content" .getBytes (StandardCharsets .UTF_8 );
69+ private static final byte [] LLM_MESSAGE_TOOL_CALLS = "tool_calls" .getBytes (StandardCharsets .UTF_8 );
70+
71+ private static final byte [] LLM_TOOL_CALL_NAME = "name" .getBytes (StandardCharsets .UTF_8 );
72+ private static final byte [] LLM_TOOL_CALL_TYPE = "type" .getBytes (StandardCharsets .UTF_8 );
73+ private static final byte [] LLM_TOOL_CALL_TOOL_ID = "tool_id" .getBytes (StandardCharsets .UTF_8 );
74+ private static final byte [] LLM_TOOL_CALL_ARGUMENTS = "arguments" .getBytes (StandardCharsets .UTF_8 );
75+
6676 private final LLMObsSpanMapper .MetaWriter metaWriter = new MetaWriter ();
6777 private final int size ;
6878
@@ -266,8 +276,50 @@ public void accept(Metadata metadata) {
266276 if (key .equals (INPUT ) || key .equals (OUTPUT )) {
267277 if (!spanKind .equals (Tags .LLMOBS_LLM_SPAN_KIND )) {
268278 key += ".value" ;
279+ writable .writeString (key , null );
280+ writable .writeObject (val , null );
269281 } else {
282+ if (!(val instanceof List )) {
283+ LOGGER .warn ("unexpectedly found incorrect type for LLM span IO {}, expecting list" , val .getClass ().getName ());
284+ continue ;
285+ }
286+ // llm span kind must have llm objects
287+ List <LLMObs .LLMMessage > messages = (List <LLMObs .LLMMessage >) val ;
270288 key += ".messages" ;
289+ writable .writeString (key , null );
290+ writable .startArray (messages .size ());
291+ for (LLMObs .LLMMessage message : messages ) {
292+ List <LLMObs .ToolCall > toolCalls = message .getToolCalls ();
293+ boolean hasToolCalls = null != toolCalls && !toolCalls .isEmpty ();
294+ writable .startMap (hasToolCalls ? 3 : 2 );
295+ writable .writeUTF8 (LLM_MESSAGE_ROLE );
296+ writable .writeString (message .getRole (), null );
297+ writable .writeUTF8 (LLM_MESSAGE_CONTENT );
298+ writable .writeString (message .getContent (), null );
299+ if (hasToolCalls ) {
300+ writable .writeUTF8 (LLM_MESSAGE_TOOL_CALLS );
301+ writable .startArray (toolCalls .size ());
302+ for (LLMObs .ToolCall toolCall : toolCalls ) {
303+ Map <String , Object > arguments = toolCall .getArguments ();
304+ boolean hasArguments = null != arguments && !arguments .isEmpty ();
305+ writable .startMap (hasArguments ? 4 : 3 );
306+ writable .writeUTF8 (LLM_TOOL_CALL_NAME );
307+ writable .writeString (toolCall .getName (), null );
308+ writable .writeUTF8 (LLM_TOOL_CALL_TYPE );
309+ writable .writeString (toolCall .getType (), null );
310+ writable .writeUTF8 (LLM_TOOL_CALL_TOOL_ID );
311+ writable .writeString (toolCall .getToolID (), null );
312+ if (hasArguments ) {
313+ writable .writeUTF8 (LLM_TOOL_CALL_ARGUMENTS );
314+ writable .startMap (arguments .size ());
315+ for (Map .Entry <String , Object > argument : arguments .entrySet ()) {
316+ writable .writeString (argument .getKey (), null );
317+ writable .writeObject (argument .getValue (), null );
318+ }
319+ }
320+ }
321+ }
322+ }
271323 }
272324 } else if (key .equals (LLMObsTags .METADATA ) && val instanceof Map ) {
273325 Map <String , Object > metadataMap = (Map ) val ;
@@ -277,10 +329,10 @@ public void accept(Metadata metadata) {
277329 writable .writeString (entry .getKey (), null );
278330 writable .writeObject (entry .getValue (), null );
279331 }
280- continue ;
332+ } else {
333+ writable .writeString (key , null );
334+ writable .writeObject (val , null );
281335 }
282- writable .writeString (key , null );
283- writable .writeObject (val , null );
284336 }
285337 }
286338 }
0 commit comments