Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

Across all AI integrations (OpenAI, Anthropic, Google GenAI, LangChain, and LangGraph), the SDK no longer sends an event to Sentry for errors that the AI framework propagates to your code. Previously the instrumentation reported these as unhandled (`handled: false`) before your own error handling ran, so an error your code caught still showed up in Sentry as an unhandled crash. The span is still marked as errored and the error still propagates, so reporting is left to your application: if your code does not handle the error, it reaches Sentry's global error handlers and is captured as unhandled, just like any other uncaught error. Errors that a provider surfaces as data on an otherwise successful response (such as Anthropic error-shaped responses or Google GenAI blocked content) are still captured, since your code never sees them propagate.

Work in this release was contributed by @ryanrho-mercor and @lux-in-tenebris-lucet. Thank you for your contributions!
Work in this release was contributed by @ryanrho-mercor, @lux-in-tenebris-lucet, and @suhailopensource. Thank you for your contributions!

## 10.71.0

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/tracing/idleSpan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
*/
function _restartChildSpanTimeout(endTimestamp?: number): void {
_cancelChildSpanTimeout();
_idleTimeoutID = setTimeout(() => {
_childSpanTimeoutID = setTimeout(() => {
if (!_finished && _autoFinishAllowed) {
_finishReason = FINISH_REASON_HEARTBEAT_FAILED;
span.end(endTimestamp);
Expand Down
23 changes: 23 additions & 0 deletions packages/core/test/lib/tracing/idleSpan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,29 @@ describe('startIdleSpan', () => {
expect(spanToJSON(idleSpan).timestamp).toBeDefined();
});

it('measures the idle timeout from the last child end, not from the auto-finish signal', () => {
const idleSpan = startIdleSpan({ name: 'idle span' }, { disableAutoFinish: true, finalTimeout: 99_999 });
const idleSpanId = idleSpan.spanContext().spanId;

const child = startInactiveSpan({ name: 'inner' });

vi.advanceTimersByTime(500);
getClient()!.emit('idleSpanEnableAutoFinish', idleSpan);

vi.advanceTimersByTime(700);
child!.end();

vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout - 199);
expect(spanToJSON(idleSpan).timestamp).toBeUndefined();

const lateChild = startInactiveSpan({ name: 'late' });
expect(spanToJSON(lateChild!).parent_span_id).toBe(idleSpanId);

lateChild!.end();
vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout);
expect(spanToJSON(idleSpan).timestamp).toBeDefined();
});

it('times out at final timeout if disableAutoFinish=true', () => {
const idleSpan = startIdleSpan({ name: 'idle span' }, { disableAutoFinish: true });
expect(idleSpan).toBeDefined();
Expand Down
Loading