get_auth_span_attributes() sets enduser.id = token.client_id, as documented in docs/servers/telemetry.mdx. When telemetry was added (#2869), client_id was the only identity field on AccessToken, so this made sense.
Since then AccessToken.subject exists (MCP SDK), and FastMCP's JWTVerifier populates it from sub. For OIDC-backed servers (e.g. OIDCProxy), client_id resolves via client_id or azp or sub. ID tokens always carry azp, so every user's spans get the same enduser.id: the server's upstream OAuth client ID. Per-user attribution isn't possible from FastMCP's spans.
The OTel enduser.id attribute describes the end user, which here is sub. Proposal:
attrs["enduser.id"] = token.subject or token.client_id
Client-credentials and opaque-token setups without a subject keep today's behavior. If the client identity is still useful on spans, it could move to a separate attribute.
Was reporting client_id intentional for a case we're missing? If so, a supported hook to customize auth span attributes would also solve this. (Happy to send a PR.)
get_auth_span_attributes()setsenduser.id = token.client_id, as documented indocs/servers/telemetry.mdx. When telemetry was added (#2869),client_idwas the only identity field onAccessToken, so this made sense.Since then
AccessToken.subjectexists (MCP SDK), and FastMCP'sJWTVerifierpopulates it fromsub. For OIDC-backed servers (e.g.OIDCProxy),client_idresolves viaclient_id or azp or sub. ID tokens always carryazp, so every user's spans get the sameenduser.id: the server's upstream OAuth client ID. Per-user attribution isn't possible from FastMCP's spans.The OTel
enduser.idattribute describes the end user, which here issub. Proposal:Client-credentials and opaque-token setups without a subject keep today's behavior. If the client identity is still useful on spans, it could move to a separate attribute.
Was reporting
client_idintentional for a case we're missing? If so, a supported hook to customize auth span attributes would also solve this. (Happy to send a PR.)