Skip to content

Commit 459ca4e

Browse files
committed
fixup
1 parent e8ef083 commit 459ca4e

6 files changed

Lines changed: 362 additions & 522 deletions

File tree

.github/workflows/instrumentation.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
permissions:
6767
id-token: write
6868
env:
69-
PLUGINS: anthropic-lifecycle
69+
PLUGINS: anthropic|anthropic-lifecycle
7070
steps:
7171
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
7272
- uses: ./.github/actions/instrumentations/test

packages/datadog-instrumentations/src/anthropic.js

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -44,44 +44,57 @@ function waitForVerdict (promise, verdict) {
4444
: promise
4545
}
4646

47+
/**
48+
* Runs the output verdict for a parsed response and finishes the span with it. Finishing after the
49+
* verdict lets a block propagate to anthropic.request and keeps the span wrapping its child.
50+
*
51+
* @param {object} ctx
52+
* @param {object} result
53+
* @param {(body: object) => Promise<void>|undefined} getVerdict
54+
* @param {object|string} [returnedResult]
55+
* @returns {object|string|Promise<object|string>}
56+
*/
57+
function finishResult (ctx, result, getVerdict, returnedResult = result) {
58+
const verdict = getVerdict(result)
59+
if (!verdict) {
60+
finish(ctx, result, null)
61+
return returnedResult
62+
}
63+
64+
return verdict.then(() => {
65+
finish(ctx, result, null)
66+
return returnedResult
67+
})
68+
}
69+
4770
/**
4871
* @param {object} response
4972
* @param {'json'|'text'} method
5073
* @param {object} ctx
51-
* @param {(body: object|string) => Promise<void>|undefined} getVerdict
74+
* @param {(body: object) => Promise<void>|undefined} getVerdict
5275
*/
5376
function wrapResponseReader (response, method, ctx, getVerdict) {
5477
if (typeof response[method] !== 'function') return
5578

5679
shimmer.wrap(response, method, original => function (...args) {
5780
return original.apply(this, args)
58-
.then(body => finishResult(ctx, body, getVerdict))
81+
.then(body => {
82+
if (method === 'json') return finishResult(ctx, body, getVerdict)
83+
84+
try {
85+
return finishResult(ctx, JSON.parse(body), getVerdict, body)
86+
} catch {
87+
finish(ctx)
88+
return body
89+
}
90+
})
5991
.catch(error => {
6092
if (!ctx.finished) finish(ctx, null, error)
6193
throw error
6294
})
6395
})
6496
}
6597

66-
/**
67-
* @param {object} ctx
68-
* @param {object|string} result
69-
* @param {(body: object|string) => Promise<void>|undefined} getVerdict
70-
* @returns {object|string|Promise<object|string>}
71-
*/
72-
function finishResult (ctx, result, getVerdict) {
73-
const verdict = getVerdict(result)
74-
if (!verdict) {
75-
finish(ctx, result, null)
76-
return result
77-
}
78-
79-
return verdict.then(() => {
80-
finish(ctx, result, null)
81-
return result
82-
})
83-
}
84-
8598
function wrapStreamIterator (iterator, ctx) {
8699
return function (...args) {
87100
const itr = iterator.apply(this, args)
@@ -175,24 +188,30 @@ function wrapCreate (create) {
175188
return parseResult
176189
})
177190

178-
// Gate raw access; output evaluation supports only the common json() and text() readers.
179-
shimmer.wrap(apiPromise, 'asResponse', origAsResponse => function (...asResponseArgs) {
180-
return waitForVerdict(origAsResponse.apply(this, asResponseArgs), getBeforeVerdict())
181-
.then(response => {
182-
if (!stream && wrappedResponse !== response) {
183-
wrappedResponse = response
184-
wrapResponseReader(response, 'json', ctx, getAfterVerdict)
185-
wrapResponseReader(response, 'text', ctx, getAfterVerdict)
186-
}
187-
188-
if (afterVerdict) return afterVerdict.then(() => response)
189-
return response
190-
})
191-
.catch(error => {
192-
if (!ctx.finished) finish(ctx, null, error)
193-
throw error
194-
})
195-
})
191+
if (typeof apiPromise.asResponse === 'function') {
192+
shimmer.wrap(apiPromise, 'asResponse', origAsResponse => function (...asResponseArgs) {
193+
return waitForVerdict(origAsResponse.apply(this, asResponseArgs), getBeforeVerdict())
194+
.then(response => {
195+
// Raw output evaluation supports the common json() and text() readers only.
196+
if (!stream &&
197+
(anthropicTracingChannel.start.hasSubscribers ||
198+
afterVerdict ||
199+
messagesAfterChannel.hasSubscribers) &&
200+
wrappedResponse !== response) {
201+
wrappedResponse = response
202+
wrapResponseReader(response, 'json', ctx, getAfterVerdict)
203+
wrapResponseReader(response, 'text', ctx, getAfterVerdict)
204+
}
205+
206+
if (afterVerdict) return afterVerdict.then(() => response)
207+
return response
208+
})
209+
.catch(error => {
210+
if (!ctx.finished) finish(ctx, null, error)
211+
throw error
212+
})
213+
})
214+
}
196215

197216
anthropicTracingChannel.end.publish(ctx)
198217

0 commit comments

Comments
 (0)