attach discord metadata to trace tags #337

Closed
opened 2026-08-13 10:12:30 +00:00 by coilysiren · 3 comments
Owner

offhand, the means:

  • user id
  • guild id
  • message id
  • channel id
  • [ thread id when present ]
  • ...probably other stuff...
offhand, the means: - user id - guild id - message id - channel id - _[ thread id when present ]_ - _...probably other stuff..._
Member

CLAIM — Angie (ENG, claude seat) · 2026-08-13T10:24Z · 20 min. Taking it because it is the other half of the trace work I just landed on #336 — that one hands a member a trace ID, this one makes the trace worth opening.

Waiting the buffer before touching anything. Reading the turn span and the event path meanwhile.

One thing I will raise before I write it, because it is a boundary and not a detail. `AGENTS.md` currently states that accepted turns retain trace-correlated metadata without member data, and `user id` is member data. Your ask is the director's call and I am not arguing it — a numeric snowflake in a private telemetry backend is a very different object from a handle in a public reply. But the repo cannot both say that sentence and carry that attribute, so I will change the sentence in the same commit rather than leave the document lying about the code.

If you would rather the user ID be hashed per-turn or omitted while the other four go in, say so before the merge and it is a small change.

**CLAIM — Angie (ENG, claude seat)** · 2026-08-13T10:24Z · 20 min. Taking it because it is the other half of the trace work I just landed on https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/336 — that one hands a member a trace ID, this one makes the trace worth opening. Waiting the buffer before touching anything. Reading the turn span and the event path meanwhile. **One thing I will raise before I write it, because it is a boundary and not a detail.** \`AGENTS.md\` currently states that accepted turns retain trace-correlated metadata *without member data*, and \`user id\` is member data. Your ask is the director's call and I am not arguing it — a numeric snowflake in a private telemetry backend is a very different object from a handle in a public reply. But the repo cannot both say that sentence and carry that attribute, so I will change the sentence in the same commit rather than leave the document lying about the code. If you would rather the user ID be hashed per-turn or omitted while the other four go in, say so before the merge and it is a small change.
Member

Delivered — Angie (ENG). PR: #342, mergeable, waiting on the director gate. Releasing the claim.

All five of your bullets, on the `community.turn` span, keyed to match the send span so one query returns both halves of an exchange:

you asked key
user id `discord.user.id`
guild id `discord.guild.id`
message id `messaging.message.id`
channel id `discord.channel.id`
thread id when present `discord.thread.id`

Two of these already existed on the outbound half and I reused their names rather than inventing a second vocabulary. That was the largest part of the "probably other stuff" — the identifiers were already being emitted when a reply was sent, and simply were not on the turn the reply answered.

The thread bullet turned out to be the only real design question

Discord models a thread as a channel, so `message.ChannelID` is the thread id when a turn happens in a thread. The naive mapping therefore reports the thread as the channel, and every thread turn disappears from a query for the channel it hangs under — which is the query an operator runs. So the parent is reported as the channel and the thread gets its own key.

Resolution reads cached gateway state and never calls the Discord API. A turn is not worth an API call to learn something optional, and a thread this service can answer in arrived over the gateway to begin with. An unresolved channel reports itself as a channel, which is what it is.

The reversal I flagged in my claim, now landed

The code carried a comment beside this span saying the requester was deliberately not a span attribute, because an account id is not operational telemetry. That was a real position and I have overturned it on your instruction, not quietly: the comment and the `AGENTS.md` safety sentence that both asserted it are corrected in the same commit, and `docs/sirens-echo-turn-identifiers.md` records why, so the next person to find it reads a decision rather than drift.

A test asserts the account id is present. If it should ever come back out, that test is deleted in the same commit — which is the point of it.

What I held back, and you can overrule either

A direct message contributes nothing at all. `AGENTS.md` says a DM never enters the turn logger, and I did not want this change to be the first exception to that as a side effect. If you want DM turns tagged too, that is one condition.

Nothing member-visible goes on the span — no display name, no nickname, no handle. Only the numeric account id. Names in telemetry are a different boundary from ids, and #310 is about the adjacent version of that going wrong.

The next issue in this chain

#339 asks the harness to fetch trace details when a member says `trace`. It is now worth doing — before this, a fetched trace could not tell you which channel or member it belonged to. Leaving it unclaimed rather than taking three in a row from the same thread.

**Delivered — Angie (ENG).** PR: https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/342, mergeable, waiting on the director gate. Releasing the claim. All five of your bullets, on the \`community.turn\` span, keyed to match the send span so one query returns both halves of an exchange: | you asked | key | |---|---| | user id | \`discord.user.id\` | | guild id | \`discord.guild.id\` | | message id | \`messaging.message.id\` | | channel id | \`discord.channel.id\` | | thread id when present | \`discord.thread.id\` | **Two of these already existed on the outbound half** and I reused their names rather than inventing a second vocabulary. That was the largest part of the "probably other stuff" — the identifiers were already being emitted when a reply was sent, and simply were not on the turn the reply answered. ## The thread bullet turned out to be the only real design question Discord models a thread as a channel, so \`message.ChannelID\` **is** the thread id when a turn happens in a thread. The naive mapping therefore reports the thread as the channel, and every thread turn disappears from a query for the channel it hangs under — which is the query an operator runs. So the parent is reported as the channel and the thread gets its own key. Resolution reads cached gateway state and never calls the Discord API. A turn is not worth an API call to learn something optional, and a thread this service can answer in arrived over the gateway to begin with. An unresolved channel reports itself as a channel, which is what it is. ## The reversal I flagged in my claim, now landed The code carried a comment beside this span saying the requester was *deliberately* not a span attribute, because an account id is not operational telemetry. That was a real position and I have overturned it on your instruction, not quietly: the comment and the \`AGENTS.md\` safety sentence that both asserted it are corrected in the same commit, and \`docs/sirens-echo-turn-identifiers.md\` records why, so the next person to find it reads a decision rather than drift. A test asserts the account id is present. If it should ever come back out, that test is deleted in the same commit — which is the point of it. ## What I held back, and you can overrule either **A direct message contributes nothing at all.** \`AGENTS.md\` says a DM never enters the turn logger, and I did not want this change to be the first exception to that as a side effect. If you want DM turns tagged too, that is one condition. **Nothing member-visible goes on the span** — no display name, no nickname, no handle. Only the numeric account id. Names in telemetry are a different boundary from ids, and https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/310 is about the adjacent version of that going wrong. ## The next issue in this chain https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/339 asks the harness to fetch trace details when a member says \`trace\`. It is now worth doing — before this, a fetched trace could not tell you which channel or member it belonged to. Leaving it unclaimed rather than taking three in a row from the same thread.
Member

Releasing my claim from 10:24Z. This was delivered by #342 while I held it, and I closed my own branch unmerged at #345 rather than compete with it.

Kai, two answers to things I raised in the claim, so they do not stay open.

The AGENTS.md sentence is resolved. #342 changed it in the same commit that added the attribute and wrote down the reversal in docs/sirens-echo-turn-identifiers.md, including the comment that had previously argued the opposite. So the repo no longer says one thing and does another, and the account id is present by a decision that has a test attached to it rather than by drift.

I also offered hashing or omitting the user id. That offer was based on a cost I got wrong, so it is worth withdrawing explicitly. I assumed thread resolution needed a Discord API call per turn and priced the whole request around avoiding it. It does not: session.State.Channel is a cached gateway read. All five identifiers you asked for are on the span, at no per-turn call.

One residue of the merge is open as #348, fixed in #349 and awaiting CI. The turn span reports a thread's parent as the channel and the boundary spans reported the thread, so discord.channel.id meant two things in one trace and either query you ran came back partial without looking partial. That does not affect the decision you made here, only whether a query finds all of it.

Releasing my claim from 10:24Z. This was delivered by https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/342 while I held it, and I closed my own branch unmerged at https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/345 rather than compete with it. Kai, two answers to things I raised in the claim, so they do not stay open. The `AGENTS.md` sentence is resolved. https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/342 changed it in the same commit that added the attribute and wrote down the reversal in `docs/sirens-echo-turn-identifiers.md`, including the comment that had previously argued the opposite. So the repo no longer says one thing and does another, and the account id is present by a decision that has a test attached to it rather than by drift. I also offered hashing or omitting the user id. That offer was based on a cost I got wrong, so it is worth withdrawing explicitly. I assumed thread resolution needed a Discord API call per turn and priced the whole request around avoiding it. It does not: `session.State.Channel` is a cached gateway read. All five identifiers you asked for are on the span, at no per-turn call. One residue of the merge is open as https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/348, fixed in https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/349 and awaiting CI. The turn span reports a thread's parent as the channel and the boundary spans reported the thread, so `discord.channel.id` meant two things in one trace and either query you ran came back partial without looking partial. That does not affect the decision you made here, only whether a query finds all of it.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#337
No description provided.