Skip to content

Commit 3bff850

Browse files
authored
chore(llmobs): add span.finished telemetry metric (#5444)
* Add span.finished telemetry metric * Add decorator tag * address comments * Fix root parent bool * Add error tag * Fix boolean coalescing
1 parent f84216a commit 3bff850

File tree

6 files changed

+64
-7
lines changed

6 files changed

+64
-7
lines changed

packages/dd-trace/src/llmobs/constants/tags.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ module.exports = {
44
SPAN_KINDS: ['llm', 'agent', 'workflow', 'task', 'tool', 'embedding', 'retrieval'],
55
SPAN_KIND: '_ml_obs.meta.span.kind',
66
SESSION_ID: '_ml_obs.session_id',
7+
DECORATOR: '_ml_obs.decorator',
8+
INTEGRATION: '_ml_obs.integration',
79
METADATA: '_ml_obs.meta.metadata',
810
METRICS: '_ml_obs.metrics',
911
ML_APP: '_ml_obs.meta.ml_app',

packages/dd-trace/src/llmobs/noop.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ class NoopLLMObs {
4343
const ctx = ctxOrPropertyKey
4444
if (ctx.kind !== 'method') return target
4545

46-
return llmobs.wrap({ name: ctx.name, ...options }, target)
46+
return llmobs.wrap({ name: ctx.name, _decorator: true, ...options }, target)
4747
} else {
4848
const propertyKey = ctxOrPropertyKey
4949
if (descriptor) {
5050
if (typeof descriptor.value !== 'function') return descriptor
5151

5252
const original = descriptor.value
53-
descriptor.value = llmobs.wrap({ name: propertyKey, ...options }, original)
53+
descriptor.value = llmobs.wrap({ name: propertyKey, _decorator: true, ...options }, original)
5454

5555
return descriptor
5656
} else {
@@ -59,7 +59,7 @@ class NoopLLMObs {
5959
const original = target[propertyKey]
6060
Object.defineProperty(target, propertyKey, {
6161
...Object.getOwnPropertyDescriptor(target, propertyKey),
62-
value: llmobs.wrap({ name: propertyKey, ...options }, original)
62+
value: llmobs.wrap({ name: propertyKey, _decorator: true, ...options }, original)
6363
})
6464

6565
return target

packages/dd-trace/src/llmobs/sdk.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ class LLMObs extends NoopLLMObs {
430430
modelProvider,
431431
sessionId,
432432
mlApp,
433+
_decorator,
433434
...spanOptions
434435
} = options
435436

@@ -438,6 +439,7 @@ class LLMObs extends NoopLLMObs {
438439
modelName,
439440
modelProvider,
440441
sessionId,
442+
_decorator,
441443
spanOptions
442444
}
443445
}

packages/dd-trace/src/llmobs/span_processor.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ const {
2727
ERROR_STACK
2828
} = require('../constants')
2929

30+
const telemetry = require('./telemetry')
31+
3032
const LLMObsTagger = require('./tagger')
3133

3234
const tracerVersion = require('../../../../package.json').version
@@ -49,6 +51,7 @@ class LLMObsSpanProcessor {
4951

5052
try {
5153
const formattedEvent = this.format(span)
54+
telemetry.incrementLLMObsSpanFinishedCount(span)
5255
this._writer.append(formattedEvent)
5356
} catch (e) {
5457
// this should be a rare case

packages/dd-trace/src/llmobs/tagger.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const {
1010
INPUT_VALUE,
1111
OUTPUT_DOCUMENTS,
1212
INPUT_DOCUMENTS,
13-
INTEGRATION,
1413
OUTPUT_VALUE,
1514
METADATA,
1615
METRICS,
@@ -23,7 +22,9 @@ const {
2322
ROOT_PARENT_ID,
2423
INPUT_TOKENS_METRIC_KEY,
2524
OUTPUT_TOKENS_METRIC_KEY,
26-
TOTAL_TOKENS_METRIC_KEY
25+
TOTAL_TOKENS_METRIC_KEY,
26+
INTEGRATION,
27+
DECORATOR
2728
} = require('./constants/tags')
2829

2930
// global registry of LLMObs spans
@@ -53,7 +54,8 @@ class LLMObsTagger {
5354
parent,
5455
kind,
5556
name,
56-
integration
57+
integration,
58+
_decorator
5759
} = {}) {
5860
if (!this._config.llmobs.enabled) return
5961
if (!kind) return // do not register it in the map if it doesn't have an llmobs span kind
@@ -69,6 +71,7 @@ class LLMObsTagger {
6971
sessionId = sessionId || registry.get(parent)?.[SESSION_ID]
7072
if (sessionId) this._setTag(span, SESSION_ID, sessionId)
7173
if (integration) this._setTag(span, INTEGRATION, integration)
74+
if (_decorator) this._setTag(span, DECORATOR, _decorator)
7275

7376
if (!mlApp) mlApp = registry.get(parent)?.[ML_APP] || this._config.llmobs.mlApp
7477
this._setTag(span, ML_APP, mlApp)
Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,59 @@
11
'use strict'
22

3+
const {
4+
SPAN_KIND,
5+
MODEL_PROVIDER,
6+
PARENT_ID_KEY,
7+
SESSION_ID,
8+
ROOT_PARENT_ID,
9+
INTEGRATION,
10+
DECORATOR
11+
} = require('./constants/tags')
12+
13+
const ERROR_TYPE = require('../constants')
14+
315
const telemetryMetrics = require('../telemetry/metrics')
16+
17+
const LLMObsTagger = require('./tagger')
18+
419
const llmobsMetrics = telemetryMetrics.manager.namespace('mlobs')
520

621
function incrementLLMObsSpanStartCount (tags, value = 1) {
722
llmobsMetrics.count('span.start', tags).inc(value)
823
}
924

25+
function incrementLLMObsSpanFinishedCount (span, value = 1) {
26+
const mlObsTags = LLMObsTagger.tagMap.get(span)
27+
const spanTags = span.context()._tags
28+
29+
const isRootSpan = mlObsTags[PARENT_ID_KEY] === ROOT_PARENT_ID
30+
const hasSessionId = mlObsTags[SESSION_ID] != null
31+
const integration = mlObsTags[INTEGRATION]
32+
const autoInstrumented = integration != null
33+
const decorator = !!mlObsTags[DECORATOR]
34+
const spanKind = mlObsTags[SPAN_KIND]
35+
const modelProvider = mlObsTags[MODEL_PROVIDER]
36+
const error = spanTags.error || spanTags[ERROR_TYPE]
37+
38+
const tags = {
39+
autoinstrumented: Number(autoInstrumented),
40+
has_session_id: Number(hasSessionId),
41+
is_root_span: Number(isRootSpan),
42+
span_kind: spanKind,
43+
integration: integration || 'N/A',
44+
error: error ? 1 : 0
45+
}
46+
if (!autoInstrumented) {
47+
tags.decorator = Number(decorator)
48+
}
49+
if (modelProvider) {
50+
tags.model_provider = modelProvider
51+
}
52+
53+
llmobsMetrics.count('span.finished', tags).inc(value)
54+
}
55+
1056
module.exports = {
11-
incrementLLMObsSpanStartCount
57+
incrementLLMObsSpanStartCount,
58+
incrementLLMObsSpanFinishedCount
1259
}

0 commit comments

Comments
 (0)