Skip to content

feat(slack): Put Slack turns in the ingress trace - #2406

Merged
thomasjiangcy merged 1 commit into
mainfrom
feat/slack-turn-ingress-trace
Oct 30, 2026
Merged

thomasjiangcy merged 1 commit into
mainfrom
feat/slack-turn-ingress-trace

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

Part of #2269

Today a Slack trace ends at slack.message.ingress. The worker and the turn start a new trace, so one trace cannot show the time from message to reply.

Ingress now writes the sentry-trace and baggage headers of the slack.message.ingress span to the mailbox entry as traceContext. #2280 already made readers accept this field, and that reader is in production. Only Slack input writes it.

The Slack worker passes the trace contexts of the turn's input messages, oldest first, in the existing turn input telemetry. withTurnSpan opens chat.turn inside continueTrace with the oldest trace context:

  • chat.turn is a child of the oldest input's slack.message.ingress span, so it is in that trace. It keeps the ingress sampling decision.
  • chat.turn has span links to the slack.message.ingress spans of the other inputs and to the conversation.work.process worker span. continueTrace replaces the active span, so the worker span stays in its own trace and is only linked.
  • Without a stored trace context, chat.turn is a child of the worker span, as before. A malformed sentry-trace value starts a new trace. Neither case is an error.

The chat.turn span is opened tightly around the turn, not around the whole worker call. Otherwise, setup spans such as the processing reaction and state reads would become orphan roots in the ingress trace.

The telemetry test runs real Slack ingress and the real Slack worker with a Sentry client. It checks the trace, the parent, and both links. TELEMETRY.md documents the trace shape.

Resumed slices (yield, hard timeout, OAuth) do not join the trace yet. The stacked PR for #2269 PR 6 adds that.

via @thomasjiangcy.

--

View Session [Sentry]

@vercel

vercel Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
junior-docs Ready Ready Preview Oct 30, 2026 3:34am UTC

Request Review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 9a80461. Configure here.

Comment thread packages/junior/src/chat/providers/slack/turn-input-telemetry.ts
@thomasjiangcy
thomasjiangcy added this pull request to stack #2409 October 30, 2026 03:31
Part of #2269

Co-Authored-By: Thomas Jiang <20501235+thomasjiangcy@users.noreply.github.com>
@thomasjiangcy
thomasjiangcy merged commit b3d84bc into main Oct 30, 2026
44 checks passed
@thomasjiangcy
thomasjiangcy deleted the feat/slack-turn-ingress-trace branch October 30, 2026 03:49
thomasjiangcy added a commit that referenced this pull request Oct 30, 2026
Part of #2269. Stacked on #2406.

A Turn that yields, hits the hard timeout, or waits for OAuth continues
in a resumed slice. Before this change, a resumed slice did not open a
turn span. Its attributes went onto the worker span, and the slice had
no connection to the trace of the first slice.

**Trace context on the Turn cursor**
- `TurnRecord.traceId` becomes `traceContext` (`{ sentryTrace, baggage
}`). Nothing read `traceId`, and `checkpoint.ts` overwrote it on each
save.
- The first checkpoint save stores the active trace. Later saves keep
it. A later save can come from a different trace, such as lost-worker
recovery, so the first value wins.
- The cursor uses the same tolerant schema as the mailbox entry. A
malformed value is dropped and does not reject the cursor.
`storedTurnRecordSchema` uses `.strip()`, so an older worker ignores the
new field.

**Resumed slice span**
- `getPausedTurnRequest` returns the stored trace context.
`runPausedTurn` passes it to `resumeSlackTurn`.
- `resumeSlackTurn` runs in a `chat.turn` span through `withTurnSpan`
from #2406. It continues the stored trace and links to the
`queue.process` worker span. `TELEMETRY.md` already listed a "resumed
`chat.turn`" under Auth And Resume. This change keeps that name and does
not add a new span name or attribute. A resumed `chat.turn` is a child
of the first slice, so you can tell it apart from the first `chat.turn`
by its parent.
- A Turn without stored trace context, such as a Turn from before this
change, gets a `chat.turn` that is a child of the worker span.

All resume paths (yield, timeout, OAuth, lost-worker recovery) go
through `runNextPausedTurn`, so this covers each of them.

`getActiveTraceContext()` in `logging.ts` now gives both the mailbox
writer and the checkpoint the active trace in this shape.

**Tests**
The existing Sentry-client test in `conversation-work-telemetry.test.ts`
gets one resumed-slice case. It saves the first slice in one trace and a
later pause in another trace, then runs `runNextPausedTurn` under a
worker span. It checks that the resumed `chat.turn` is in the first
trace, is a child of the first span, and links to the worker span.

<!-- junior-request-attribution:start -->
via @thomasjiangcy.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:agent%3A119c536080ee889661033807452f49ea -->

--

[View
Session](https://junior-prod.sentry.dev/conversations/agent%3A119c536080ee889661033807452f49ea)
[[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3A119c536080ee889661033807452f49ea/?project=4510944073809921)

<!-- junior-session-footer:end -->

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Thomas Jiang <20501235+thomasjiangcy@users.noreply.github.com>

This branch was successfully deployed

1 active deployment
Preview – junior-docs — 67127882 Deployed Oct 30, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: high PR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant