()
| 524 | } |
| 525 | |
| 526 | export function startToolBlockedOnUserSpan(): Span { |
| 527 | // Start Perfetto span regardless of OTel tracing state |
| 528 | const perfettoSpanId = isPerfettoTracingEnabled() |
| 529 | ? startUserInputPerfettoSpan('tool_permission') |
| 530 | : undefined |
| 531 | |
| 532 | if (!isAnyTracingEnabled()) { |
| 533 | // Still track Perfetto span even if OTel is disabled |
| 534 | if (perfettoSpanId) { |
| 535 | const dummySpan = trace.getActiveSpan() || getTracer().startSpan('dummy') |
| 536 | const spanId = getSpanId(dummySpan) |
| 537 | const spanContextObj: SpanContext = { |
| 538 | span: dummySpan, |
| 539 | startTime: Date.now(), |
| 540 | attributes: { 'span.type': 'tool.blocked_on_user' }, |
| 541 | perfettoSpanId, |
| 542 | } |
| 543 | activeSpans.set(spanId, new WeakRef(spanContextObj)) |
| 544 | strongSpans.set(spanId, spanContextObj) |
| 545 | return dummySpan |
| 546 | } |
| 547 | return trace.getActiveSpan() || getTracer().startSpan('dummy') |
| 548 | } |
| 549 | |
| 550 | const tracer = getTracer() |
| 551 | const parentSpanCtx = toolContext.getStore() |
| 552 | |
| 553 | const attributes = createSpanAttributes('tool.blocked_on_user') |
| 554 | |
| 555 | const ctx = parentSpanCtx |
| 556 | ? trace.setSpan(otelContext.active(), parentSpanCtx.span) |
| 557 | : otelContext.active() |
| 558 | const span = tracer.startSpan( |
| 559 | 'claude_code.tool.blocked_on_user', |
| 560 | { attributes }, |
| 561 | ctx, |
| 562 | ) |
| 563 | |
| 564 | const spanId = getSpanId(span) |
| 565 | const spanContextObj: SpanContext = { |
| 566 | span, |
| 567 | startTime: Date.now(), |
| 568 | attributes, |
| 569 | perfettoSpanId, |
| 570 | } |
| 571 | activeSpans.set(spanId, new WeakRef(spanContextObj)) |
| 572 | strongSpans.set(spanId, spanContextObj) |
| 573 | |
| 574 | return span |
| 575 | } |
| 576 | |
| 577 | export function endToolBlockedOnUserSpan( |
| 578 | decision?: string, |
no test coverage detected