//! Stable OpenTelemetry span names + attribute keys for mcptest
//! (SEP-414 alignment).
//!
//! Calling these out as constants rather than inlining the strings
//! in the exporter keeps the conventions in one place. v1 ships the
//! convention; v2 wires it to a real OTel SDK.

/// Top-level span for a `mcptest run` invocation. One per process.
pub const RUN_SPAN_NAME: &str = "mcptest.run";

/// Per-test span name. The reporter attaches the test name as a
/// span attribute (`mcptest.test.name`) rather than baking it into
/// the span name so cardinality stays bounded.
pub const TEST_SPAN_NAME: &str = "mcptest.test";

/// Build a span name for a tool-call dispatch. The shape matches
/// the OTel semantic-convention for RPC clients: `<rpc.service>/<rpc.method>`,
/// where the service is `mcp` and the method is the MCP method name
/// (for `tools/call`, the tool name is an attribute, not part of
/// the span name, again to bound cardinality).
pub fn tool_call_span_name(method: &str) -> String {
    format!("mcp/{method}")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn run_and_test_span_names_are_stable() {
        // Pinning these makes future grep-based collector dashboards
        // safe across mcptest releases.
        assert_eq!(RUN_SPAN_NAME, "mcptest.run");
        assert_eq!(TEST_SPAN_NAME, "mcptest.test");
    }

    #[test]
    fn tool_call_span_name_uses_otel_semantic_conventions() {
        assert_eq!(tool_call_span_name("tools/call"), "mcp/tools/call");
        assert_eq!(tool_call_span_name("resources/read"), "mcp/resources/read");
    }
}
