88import datadog .trace .api .llmobs .LLMObsContext ;
99import datadog .trace .api .llmobs .LLMObsSpan ;
1010import datadog .trace .api .llmobs .LLMObsTags ;
11+ import datadog .trace .api .telemetry .LLMObsMetricCollector ;
1112import datadog .trace .bootstrap .instrumentation .api .AgentSpan ;
1213import datadog .trace .bootstrap .instrumentation .api .AgentSpanContext ;
1314import datadog .trace .bootstrap .instrumentation .api .AgentTracer ;
@@ -47,6 +48,7 @@ public class DDLLMObsSpan implements LLMObsSpan {
4748 private final AgentSpan span ;
4849 private final String spanKind ;
4950 private final ContextScope scope ;
51+ private final boolean hasSessionId ;
5052
5153 private boolean finished = false ;
5254
@@ -68,51 +70,52 @@ public DDLLMObsSpan(
6870 .withServiceName (serviceName )
6971 .withSpanType (DDSpanTypes .LLMOBS );
7072
71- this . span = spanBuilder .start ();
73+ span = spanBuilder .start ();
7274
7375 // set UST (unified service tags, env, service, version)
74- this .span .setTag (ENV , wellKnownTags .getEnv ());
75- this .span .setTag (SERVICE , wellKnownTags .getService ());
76- this .span .setTag (VERSION , wellKnownTags .getVersion ());
77-
78- this .span .setTag (SPAN_KIND , kind );
79- this .spanKind = kind ;
80- this .span .setTag (LLMOBS_TAG_PREFIX + LLMObsTags .ML_APP , mlApp );
81- if (sessionId != null && !sessionId .isEmpty ()) {
82- this .span .setTag (LLMOBS_TAG_PREFIX + LLMObsTags .SESSION_ID , sessionId );
76+ span .setTag (ENV , wellKnownTags .getEnv ());
77+ span .setTag (SERVICE , wellKnownTags .getService ());
78+ span .setTag (VERSION , wellKnownTags .getVersion ());
79+
80+ span .setTag (SPAN_KIND , kind );
81+ spanKind = kind ;
82+ span .setTag (LLMOBS_TAG_PREFIX + LLMObsTags .ML_APP , mlApp );
83+ this .hasSessionId = sessionId != null && !sessionId .isEmpty ();
84+ if (this .hasSessionId ) {
85+ span .setTag (LLMOBS_TAG_PREFIX + LLMObsTags .SESSION_ID , sessionId );
8386 }
8487
8588 AgentSpanContext parent = LLMObsContext .current ();
8689 String parentSpanID = LLMObsContext .ROOT_SPAN_ID ;
8790 if (null != parent ) {
88- if (parent .getTraceId () != this . span .getTraceId ()) {
91+ if (parent .getTraceId () != span .getTraceId ()) {
8992 LOGGER .error (
9093 "trace ID mismatch, retrieved parent from context trace_id={}, span_id={}, started span trace_id={}, span_id={}" ,
9194 parent .getTraceId (),
9295 parent .getSpanId (),
93- this . span .getTraceId (),
94- this . span .getSpanId ());
96+ span .getTraceId (),
97+ span .getSpanId ());
9598 } else {
9699 parentSpanID = String .valueOf (parent .getSpanId ());
97100 }
98101 }
99- this . span .setTag (LLMOBS_TAG_PREFIX + PARENT_ID_TAG_INTERNAL , parentSpanID );
100- this . scope = LLMObsContext .attach (this . span .context ());
102+ span .setTag (LLMOBS_TAG_PREFIX + PARENT_ID_TAG_INTERNAL , parentSpanID );
103+ scope = LLMObsContext .attach (span .context ());
101104 }
102105
103106 @ Override
104107 public String toString () {
105108 return super .toString ()
106109 + ", trace_id="
107- + this . span .context ().getTraceId ()
110+ + span .context ().getTraceId ()
108111 + ", span_id="
109- + this . span .context ().getSpanId ()
112+ + span .context ().getSpanId ()
110113 + ", ml_app="
111- + this . span .getTag (LLMObsTags .ML_APP )
114+ + span .getTag (LLMObsTags .ML_APP )
112115 + ", service="
113- + this . span .getServiceName ()
116+ + span .getServiceName ()
114117 + ", span_kind="
115- + this . span .getTag (SPAN_KIND );
118+ + span .getTag (SPAN_KIND );
116119 }
117120
118121 @ Override
@@ -121,10 +124,10 @@ public void annotateIO(List<LLMObs.LLMMessage> inputData, List<LLMObs.LLMMessage
121124 return ;
122125 }
123126 if (inputData != null && !inputData .isEmpty ()) {
124- this . span .setTag (INPUT , inputData );
127+ span .setTag (INPUT , inputData );
125128 }
126129 if (outputData != null && !outputData .isEmpty ()) {
127- this . span .setTag (OUTPUT , outputData );
130+ span .setTag (OUTPUT , outputData );
128131 }
129132 }
130133
@@ -135,24 +138,24 @@ public void annotateIO(String inputData, String outputData) {
135138 }
136139 boolean wrongSpanKind = false ;
137140 if (inputData != null && !inputData .isEmpty ()) {
138- if (Tags .LLMOBS_LLM_SPAN_KIND .equals (this . spanKind )) {
141+ if (Tags .LLMOBS_LLM_SPAN_KIND .equals (spanKind )) {
139142 wrongSpanKind = true ;
140143 annotateIO (
141144 Collections .singletonList (LLMObs .LLMMessage .from (LLM_MESSAGE_UNKNOWN_ROLE , inputData )),
142145 null );
143146 } else {
144- this . span .setTag (INPUT , inputData );
147+ span .setTag (INPUT , inputData );
145148 }
146149 }
147150 if (outputData != null && !outputData .isEmpty ()) {
148- if (Tags .LLMOBS_LLM_SPAN_KIND .equals (this . spanKind )) {
151+ if (Tags .LLMOBS_LLM_SPAN_KIND .equals (spanKind )) {
149152 wrongSpanKind = true ;
150153 annotateIO (
151154 null ,
152155 Collections .singletonList (
153156 LLMObs .LLMMessage .from (LLM_MESSAGE_UNKNOWN_ROLE , outputData )));
154157 } else {
155- this . span .setTag (OUTPUT , outputData );
158+ span .setTag (OUTPUT , outputData );
156159 }
157160 }
158161 if (wrongSpanKind ) {
@@ -168,7 +171,7 @@ public void setMetadata(Map<String, Object> metadata) {
168171 }
169172 Object value = span .getTag (METADATA );
170173 if (value == null ) {
171- this . span .setTag (METADATA , new HashMap <>(metadata ));
174+ span .setTag (METADATA , new HashMap <>(metadata ));
172175 return ;
173176 }
174177
@@ -178,7 +181,7 @@ public void setMetadata(Map<String, Object> metadata) {
178181 LOGGER .debug (
179182 "unexpected instance type for metadata {}, overwriting for now" ,
180183 value .getClass ().getName ());
181- this . span .setTag (METADATA , new HashMap <>(metadata ));
184+ span .setTag (METADATA , new HashMap <>(metadata ));
182185 }
183186 }
184187
@@ -188,7 +191,7 @@ public void setMetrics(Map<String, Number> metrics) {
188191 return ;
189192 }
190193 for (Map .Entry <String , Number > entry : metrics .entrySet ()) {
191- this . span .setMetric (LLMOBS_METRIC_PREFIX + entry .getKey (), entry .getValue ().doubleValue ());
194+ span .setMetric (LLMOBS_METRIC_PREFIX + entry .getKey (), entry .getValue ().doubleValue ());
192195 }
193196 }
194197
@@ -197,23 +200,23 @@ public void setMetric(CharSequence key, int value) {
197200 if (finished ) {
198201 return ;
199202 }
200- this . span .setMetric (LLMOBS_METRIC_PREFIX + key , value );
203+ span .setMetric (LLMOBS_METRIC_PREFIX + key , value );
201204 }
202205
203206 @ Override
204207 public void setMetric (CharSequence key , long value ) {
205208 if (finished ) {
206209 return ;
207210 }
208- this . span .setMetric (LLMOBS_METRIC_PREFIX + key , value );
211+ span .setMetric (LLMOBS_METRIC_PREFIX + key , value );
209212 }
210213
211214 @ Override
212215 public void setMetric (CharSequence key , double value ) {
213216 if (finished ) {
214217 return ;
215218 }
216- this . span .setMetric (LLMOBS_METRIC_PREFIX + key , value );
219+ span .setMetric (LLMOBS_METRIC_PREFIX + key , value );
217220 }
218221
219222 @ Override
@@ -223,7 +226,7 @@ public void setTags(Map<String, Object> tags) {
223226 }
224227 if (tags != null && !tags .isEmpty ()) {
225228 for (Map .Entry <String , Object > entry : tags .entrySet ()) {
226- this . span .setTag (LLMOBS_TAG_PREFIX + entry .getKey (), entry .getValue ());
229+ span .setTag (LLMOBS_TAG_PREFIX + entry .getKey (), entry .getValue ());
227230 }
228231 }
229232 }
@@ -233,47 +236,47 @@ public void setTag(String key, String value) {
233236 if (finished ) {
234237 return ;
235238 }
236- this . span .setTag (LLMOBS_TAG_PREFIX + key , value );
239+ span .setTag (LLMOBS_TAG_PREFIX + key , value );
237240 }
238241
239242 @ Override
240243 public void setTag (String key , boolean value ) {
241244 if (finished ) {
242245 return ;
243246 }
244- this . span .setTag (LLMOBS_TAG_PREFIX + key , value );
247+ span .setTag (LLMOBS_TAG_PREFIX + key , value );
245248 }
246249
247250 @ Override
248251 public void setTag (String key , int value ) {
249252 if (finished ) {
250253 return ;
251254 }
252- this . span .setTag (LLMOBS_TAG_PREFIX + key , value );
255+ span .setTag (LLMOBS_TAG_PREFIX + key , value );
253256 }
254257
255258 @ Override
256259 public void setTag (String key , long value ) {
257260 if (finished ) {
258261 return ;
259262 }
260- this . span .setTag (LLMOBS_TAG_PREFIX + key , value );
263+ span .setTag (LLMOBS_TAG_PREFIX + key , value );
261264 }
262265
263266 @ Override
264267 public void setTag (String key , double value ) {
265268 if (finished ) {
266269 return ;
267270 }
268- this . span .setTag (LLMOBS_TAG_PREFIX + key , value );
271+ span .setTag (LLMOBS_TAG_PREFIX + key , value );
269272 }
270273
271274 @ Override
272275 public void setError (boolean error ) {
273276 if (finished ) {
274277 return ;
275278 }
276- this . span .setError (error );
279+ span .setError (error );
277280 }
278281
279282 @ Override
@@ -284,8 +287,8 @@ public void setErrorMessage(String errorMessage) {
284287 if (errorMessage == null || errorMessage .isEmpty ()) {
285288 return ;
286289 }
287- this . span .setError (true );
288- this . span .setErrorMessage (errorMessage );
290+ span .setError (true );
291+ span .setErrorMessage (errorMessage );
289292 }
290293
291294 @ Override
@@ -296,27 +299,36 @@ public void addThrowable(Throwable throwable) {
296299 if (throwable == null ) {
297300 return ;
298301 }
299- this . span .setError (true );
300- this . span .addThrowable (throwable );
302+ span .setError (true );
303+ span .addThrowable (throwable );
301304 }
302305
303306 @ Override
304307 public void finish () {
305308 if (finished ) {
306309 return ;
307310 }
308- this .span .finish ();
309- this .scope .close ();
310- this .finished = true ;
311+ span .finish ();
312+ scope .close ();
313+ finished = true ;
314+ boolean isRootSpan = span .getLocalRootSpan () == span ;
315+ LLMObsMetricCollector .get ()
316+ .recordSpanFinished (
317+ LLM_OBS_INSTRUMENTATION_NAME ,
318+ spanKind ,
319+ isRootSpan ,
320+ false ,
321+ span .isError (),
322+ hasSessionId );
311323 }
312324
313325 @ Override
314326 public DDTraceId getTraceId () {
315- return this . span .getTraceId ();
327+ return span .getTraceId ();
316328 }
317329
318330 @ Override
319331 public long getSpanId () {
320- return this . span .getSpanId ();
332+ return span .getSpanId ();
321333 }
322334}
0 commit comments