Skip to content

Commit 65f9be4

Browse files
authored
fix: handle exceptions (#214)
1 parent bc808ae commit 65f9be4

File tree

24 files changed

+1212
-907
lines changed

24 files changed

+1212
-907
lines changed

package-lock.json

+59
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/instrumentation-anthropic/src/instrumentation.ts

+112-92
Original file line numberDiff line numberDiff line change
@@ -193,44 +193,49 @@ export class AnthropicInstrumentation extends InstrumentationBase<any> {
193193
[SpanAttributes.LLM_REQUEST_TYPE]: type,
194194
};
195195

196-
attributes[SpanAttributes.LLM_REQUEST_MODEL] = params.model;
197-
attributes[SpanAttributes.LLM_TEMPERATURE] = params.temperature;
198-
attributes[SpanAttributes.LLM_TOP_P] = params.top_p;
199-
attributes[SpanAttributes.LLM_TOP_K] = params.top_k;
200-
201-
if (type === "completion") {
202-
attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] =
203-
params.max_tokens_to_sample;
204-
} else {
205-
attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] = params.max_tokens;
206-
}
207-
208-
if (
209-
params.extraAttributes !== undefined &&
210-
typeof params.extraAttributes === "object"
211-
) {
212-
Object.keys(params.extraAttributes).forEach((key: string) => {
213-
attributes[key] = params.extraAttributes![key];
214-
});
215-
}
196+
try {
197+
attributes[SpanAttributes.LLM_REQUEST_MODEL] = params.model;
198+
attributes[SpanAttributes.LLM_TEMPERATURE] = params.temperature;
199+
attributes[SpanAttributes.LLM_TOP_P] = params.top_p;
200+
attributes[SpanAttributes.LLM_TOP_K] = params.top_k;
201+
202+
if (type === "completion") {
203+
attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] =
204+
params.max_tokens_to_sample;
205+
} else {
206+
attributes[SpanAttributes.LLM_REQUEST_MAX_TOKENS] = params.max_tokens;
207+
}
216208

217-
if (this._shouldSendPrompts()) {
218-
if (type === "chat") {
219-
params.messages.forEach((message, index) => {
220-
attributes[`${SpanAttributes.LLM_PROMPTS}.${index}.role`] =
221-
message.role;
222-
if (typeof message.content === "string") {
223-
attributes[`${SpanAttributes.LLM_PROMPTS}.${index}.content`] =
224-
(message.content as string) || "";
225-
} else {
226-
attributes[`${SpanAttributes.LLM_PROMPTS}.${index}.content`] =
227-
JSON.stringify(message.content);
228-
}
209+
if (
210+
params.extraAttributes !== undefined &&
211+
typeof params.extraAttributes === "object"
212+
) {
213+
Object.keys(params.extraAttributes).forEach((key: string) => {
214+
attributes[key] = params.extraAttributes![key];
229215
});
230-
} else {
231-
attributes[`${SpanAttributes.LLM_PROMPTS}.0.role`] = "user";
232-
attributes[`${SpanAttributes.LLM_PROMPTS}.0.content`] = params.prompt;
233216
}
217+
218+
if (this._shouldSendPrompts()) {
219+
if (type === "chat") {
220+
params.messages.forEach((message, index) => {
221+
attributes[`${SpanAttributes.LLM_PROMPTS}.${index}.role`] =
222+
message.role;
223+
if (typeof message.content === "string") {
224+
attributes[`${SpanAttributes.LLM_PROMPTS}.${index}.content`] =
225+
(message.content as string) || "";
226+
} else {
227+
attributes[`${SpanAttributes.LLM_PROMPTS}.${index}.content`] =
228+
JSON.stringify(message.content);
229+
}
230+
});
231+
} else {
232+
attributes[`${SpanAttributes.LLM_PROMPTS}.0.role`] = "user";
233+
attributes[`${SpanAttributes.LLM_PROMPTS}.0.content`] = params.prompt;
234+
}
235+
}
236+
} catch (e) {
237+
this._diag.warn(e);
238+
this._config.exceptionLogger?.(e);
234239
}
235240

236241
return this.tracer.startSpan(`anthropic.${type}`, {
@@ -268,20 +273,25 @@ export class AnthropicInstrumentation extends InstrumentationBase<any> {
268273
for await (const chunk of await promise) {
269274
yield chunk;
270275

271-
switch (chunk.type) {
272-
case "content_block_start":
273-
if (result.content.length <= chunk.index) {
274-
result.content.push(chunk.content_block);
275-
}
276-
break;
277-
278-
case "content_block_delta":
279-
if (chunk.index < result.content.length) {
280-
result.content[chunk.index] = {
281-
type: "text",
282-
text: result.content[chunk.index].text + chunk.delta.text,
283-
};
284-
}
276+
try {
277+
switch (chunk.type) {
278+
case "content_block_start":
279+
if (result.content.length <= chunk.index) {
280+
result.content.push(chunk.content_block);
281+
}
282+
break;
283+
284+
case "content_block_delta":
285+
if (chunk.index < result.content.length) {
286+
result.content[chunk.index] = {
287+
type: "text",
288+
text: result.content[chunk.index].text + chunk.delta.text,
289+
};
290+
}
291+
}
292+
} catch (e) {
293+
this._diag.warn(e);
294+
this._config.exceptionLogger?.(e);
285295
}
286296
}
287297

@@ -297,17 +307,22 @@ export class AnthropicInstrumentation extends InstrumentationBase<any> {
297307
for await (const chunk of await promise) {
298308
yield chunk;
299309

300-
result.id = chunk.id;
301-
result.model = chunk.model;
302-
303-
if (chunk.stop_reason) {
304-
result.stop_reason = chunk.stop_reason;
305-
}
306-
if (chunk.model) {
310+
try {
311+
result.id = chunk.id;
307312
result.model = chunk.model;
308-
}
309-
if (chunk.completion) {
310-
result.completion += chunk.completion;
313+
314+
if (chunk.stop_reason) {
315+
result.stop_reason = chunk.stop_reason;
316+
}
317+
if (chunk.model) {
318+
result.model = chunk.model;
319+
}
320+
if (chunk.completion) {
321+
result.completion += chunk.completion;
322+
}
323+
} catch (e) {
324+
this._diag.warn(e);
325+
this._config.exceptionLogger?.(e);
311326
}
312327
}
313328

@@ -365,48 +380,53 @@ export class AnthropicInstrumentation extends InstrumentationBase<any> {
365380
type: "completion";
366381
result: Completion;
367382
}) {
368-
span.setAttribute(SpanAttributes.LLM_RESPONSE_MODEL, result.model);
369-
if (type === "chat" && result.usage) {
370-
span.setAttribute(
371-
SpanAttributes.LLM_USAGE_TOTAL_TOKENS,
372-
result.usage?.input_tokens + result.usage?.output_tokens,
373-
);
374-
span.setAttribute(
375-
SpanAttributes.LLM_USAGE_COMPLETION_TOKENS,
376-
result.usage?.output_tokens,
377-
);
378-
span.setAttribute(
379-
SpanAttributes.LLM_USAGE_PROMPT_TOKENS,
380-
result.usage?.input_tokens,
381-
);
382-
}
383-
384-
result.stop_reason &&
385-
span.setAttribute(
386-
`${SpanAttributes.LLM_COMPLETIONS}.0.finish_reason`,
387-
result.stop_reason,
388-
);
389-
390-
if (this._shouldSendPrompts()) {
391-
if (type === "chat") {
383+
try {
384+
span.setAttribute(SpanAttributes.LLM_RESPONSE_MODEL, result.model);
385+
if (type === "chat" && result.usage) {
392386
span.setAttribute(
393-
`${SpanAttributes.LLM_COMPLETIONS}.0.role`,
394-
"assistant",
387+
SpanAttributes.LLM_USAGE_TOTAL_TOKENS,
388+
result.usage?.input_tokens + result.usage?.output_tokens,
395389
);
396390
span.setAttribute(
397-
`${SpanAttributes.LLM_COMPLETIONS}.0.content`,
398-
JSON.stringify(result.content),
391+
SpanAttributes.LLM_USAGE_COMPLETION_TOKENS,
392+
result.usage?.output_tokens,
399393
);
400-
} else {
401394
span.setAttribute(
402-
`${SpanAttributes.LLM_COMPLETIONS}.0.role`,
403-
"assistant",
395+
SpanAttributes.LLM_USAGE_PROMPT_TOKENS,
396+
result.usage?.input_tokens,
404397
);
398+
}
399+
400+
result.stop_reason &&
405401
span.setAttribute(
406-
`${SpanAttributes.LLM_COMPLETIONS}.0.content`,
407-
result.completion,
402+
`${SpanAttributes.LLM_COMPLETIONS}.0.finish_reason`,
403+
result.stop_reason,
408404
);
405+
406+
if (this._shouldSendPrompts()) {
407+
if (type === "chat") {
408+
span.setAttribute(
409+
`${SpanAttributes.LLM_COMPLETIONS}.0.role`,
410+
"assistant",
411+
);
412+
span.setAttribute(
413+
`${SpanAttributes.LLM_COMPLETIONS}.0.content`,
414+
JSON.stringify(result.content),
415+
);
416+
} else {
417+
span.setAttribute(
418+
`${SpanAttributes.LLM_COMPLETIONS}.0.role`,
419+
"assistant",
420+
);
421+
span.setAttribute(
422+
`${SpanAttributes.LLM_COMPLETIONS}.0.content`,
423+
result.completion,
424+
);
425+
}
409426
}
427+
} catch (e) {
428+
this._diag.warn(e);
429+
this._config.exceptionLogger?.(e);
410430
}
411431

412432
span.end();

packages/instrumentation-anthropic/src/types.ts

+5
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,9 @@ export interface AnthropicInstrumentationConfig extends InstrumentationConfig {
66
* @default true
77
*/
88
traceContent?: boolean;
9+
10+
/**
11+
* A custom logger to log any exceptions that happen during span creation.
12+
*/
13+
exceptionLogger?: (e: Error) => void;
914
}

0 commit comments

Comments
 (0)