Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions genai_otel_conformance/specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def attrs_for_requirement_level(self, level: RequirementLevel) -> tuple[str, ...
"gen_ai.usage.cache_read.input_tokens",
"gen_ai.usage.input_tokens",
"gen_ai.usage.output_tokens",
"gen_ai.usage.reasoning.output_tokens",
]
_INFERENCE_OPT_IN = [
"gen_ai.input.messages",
Expand Down
7 changes: 7 additions & 0 deletions tests/dotnet/azure-openai/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ static async Task RunPrototype()
{
activity?.SetTag("gen_ai.usage.input_tokens", completion.Usage.InputTokenCount);
activity?.SetTag("gen_ai.usage.output_tokens", completion.Usage.OutputTokenCount);
if (completion.Usage.OutputTokenDetails?.ReasoningTokenCount > 0)
activity?.SetTag("gen_ai.usage.reasoning.output_tokens", completion.Usage.OutputTokenDetails.ReasoningTokenCount);
}

var content = completion.Content[0].Text;
Expand All @@ -191,6 +193,7 @@ static async Task RunPrototype()
["gen_ai.response.finish_reasons"] = new[] { completion.FinishReason.ToString() },
["gen_ai.usage.input_tokens"] = completion.Usage?.InputTokenCount,
["gen_ai.usage.output_tokens"] = completion.Usage?.OutputTokenCount,
["gen_ai.usage.reasoning.output_tokens"] = completion.Usage?.OutputTokenDetails?.ReasoningTokenCount > 0 ? completion.Usage.OutputTokenDetails.ReasoningTokenCount : null,
["gen_ai.input.messages"] = inputMessagesJson,
["gen_ai.output.messages"] = outputMessagesJson,
["server.address"] = endpoint.Host,
Expand Down Expand Up @@ -228,6 +231,8 @@ static async Task RunPrototype()
{
activity?.SetTag("gen_ai.usage.input_tokens", update.Usage.InputTokenCount);
activity?.SetTag("gen_ai.usage.output_tokens", update.Usage.OutputTokenCount);
if (update.Usage.OutputTokenDetails?.ReasoningTokenCount > 0)
activity?.SetTag("gen_ai.usage.reasoning.output_tokens", update.Usage.OutputTokenDetails.ReasoningTokenCount);
}
}

Expand Down Expand Up @@ -301,6 +306,8 @@ static async Task RunPrototype()
{
activity?.SetTag("gen_ai.usage.input_tokens", completion.Usage.InputTokenCount);
activity?.SetTag("gen_ai.usage.output_tokens", completion.Usage.OutputTokenCount);
if (completion.Usage.OutputTokenDetails?.ReasoningTokenCount > 0)
activity?.SetTag("gen_ai.usage.reasoning.output_tokens", completion.Usage.OutputTokenDetails.ReasoningTokenCount);
}

if (completion.ToolCalls.Count > 0)
Expand Down
1 change: 1 addition & 0 deletions tests/dotnet/azure-openai/data-prototype.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"gen_ai.tool.definitions",
"gen_ai.usage.input_tokens",
"gen_ai.usage.output_tokens",
"gen_ai.usage.reasoning.output_tokens",
"server.address",
"server.port"
]
Expand Down
7 changes: 7 additions & 0 deletions tests/dotnet/extensions-ai/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ static async Task RunPrototype()
{
activity?.SetTag("gen_ai.usage.input_tokens", completion.Usage.InputTokenCount);
activity?.SetTag("gen_ai.usage.output_tokens", completion.Usage.OutputTokenCount);
if (completion.Usage.OutputTokenDetails?.ReasoningTokenCount > 0)
activity?.SetTag("gen_ai.usage.reasoning.output_tokens", completion.Usage.OutputTokenDetails.ReasoningTokenCount);
}

var content = completion.Content[0].Text;
Expand All @@ -190,6 +192,7 @@ static async Task RunPrototype()
["gen_ai.response.finish_reasons"] = new[] { completion.FinishReason.ToString() },
["gen_ai.usage.input_tokens"] = completion.Usage?.InputTokenCount,
["gen_ai.usage.output_tokens"] = completion.Usage?.OutputTokenCount,
["gen_ai.usage.reasoning.output_tokens"] = completion.Usage?.OutputTokenDetails?.ReasoningTokenCount > 0 ? completion.Usage.OutputTokenDetails.ReasoningTokenCount : null,
["gen_ai.input.messages"] = inputMessagesJson,
["gen_ai.output.messages"] = outputMessagesJson,
["server.address"] = endpoint.Host,
Expand Down Expand Up @@ -227,6 +230,8 @@ static async Task RunPrototype()
{
activity?.SetTag("gen_ai.usage.input_tokens", update.Usage.InputTokenCount);
activity?.SetTag("gen_ai.usage.output_tokens", update.Usage.OutputTokenCount);
if (update.Usage.OutputTokenDetails?.ReasoningTokenCount > 0)
activity?.SetTag("gen_ai.usage.reasoning.output_tokens", update.Usage.OutputTokenDetails.ReasoningTokenCount);
}
}

Expand Down Expand Up @@ -300,6 +305,8 @@ static async Task RunPrototype()
{
activity?.SetTag("gen_ai.usage.input_tokens", completion.Usage.InputTokenCount);
activity?.SetTag("gen_ai.usage.output_tokens", completion.Usage.OutputTokenCount);
if (completion.Usage.OutputTokenDetails?.ReasoningTokenCount > 0)
activity?.SetTag("gen_ai.usage.reasoning.output_tokens", completion.Usage.OutputTokenDetails.ReasoningTokenCount);
}

if (completion.ToolCalls.Count > 0)
Expand Down
1 change: 1 addition & 0 deletions tests/dotnet/extensions-ai/data-prototype.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"gen_ai.tool.definitions",
"gen_ai.usage.input_tokens",
"gen_ai.usage.output_tokens",
"gen_ai.usage.reasoning.output_tokens",
"server.address",
"server.port"
]
Expand Down
11 changes: 11 additions & 0 deletions tests/dotnet/semantic-kernel/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ static async Task RunPrototype()
string finishReason = null;
int? inputTokens = null;
int? outputTokens = null;
int? reasoningTokens = null;
if (metadata != null)
{
if (metadata.TryGetValue("Id", out var id) && id != null)
Expand All @@ -213,6 +214,11 @@ static async Task RunPrototype()
outputTokens = usage.OutputTokenCount;
activity?.SetTag("gen_ai.usage.input_tokens", inputTokens);
activity?.SetTag("gen_ai.usage.output_tokens", outputTokens);
if (usage.OutputTokenDetails?.ReasoningTokenCount > 0)
{
reasoningTokens = usage.OutputTokenDetails.ReasoningTokenCount;
activity?.SetTag("gen_ai.usage.reasoning.output_tokens", reasoningTokens);
}
}
}

Expand All @@ -236,6 +242,7 @@ static async Task RunPrototype()
["gen_ai.response.finish_reasons"] = finishReason != null ? new[] { finishReason } : null,
["gen_ai.usage.input_tokens"] = inputTokens,
["gen_ai.usage.output_tokens"] = outputTokens,
["gen_ai.usage.reasoning.output_tokens"] = reasoningTokens,
["gen_ai.input.messages"] = inputMessagesJson,
["gen_ai.output.messages"] = outputMessagesJson,
["server.address"] = endpoint.Host,
Expand Down Expand Up @@ -279,6 +286,8 @@ static async Task RunPrototype()
{
activity?.SetTag("gen_ai.usage.input_tokens", usage.InputTokenCount);
activity?.SetTag("gen_ai.usage.output_tokens", usage.OutputTokenCount);
if (usage.OutputTokenDetails?.ReasoningTokenCount > 0)
activity?.SetTag("gen_ai.usage.reasoning.output_tokens", usage.OutputTokenDetails.ReasoningTokenCount);
}
}
}
Expand Down Expand Up @@ -347,6 +356,8 @@ static async Task RunPrototype()
{
activity?.SetTag("gen_ai.usage.input_tokens", usage.InputTokenCount);
activity?.SetTag("gen_ai.usage.output_tokens", usage.OutputTokenCount);
if (usage.OutputTokenDetails?.ReasoningTokenCount > 0)
activity?.SetTag("gen_ai.usage.reasoning.output_tokens", usage.OutputTokenDetails.ReasoningTokenCount);
}
}

Expand Down
1 change: 1 addition & 0 deletions tests/dotnet/semantic-kernel/data-prototype.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"gen_ai.tool.definitions",
"gen_ai.usage.input_tokens",
"gen_ai.usage.output_tokens",
"gen_ai.usage.reasoning.output_tokens",
"server.address",
"server.port"
],
Expand Down
3 changes: 2 additions & 1 deletion tests/java/openai/data-prototype.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"gen_ai.response.model",
"gen_ai.tool.definitions",
"gen_ai.usage.input_tokens",
"gen_ai.usage.output_tokens"
"gen_ai.usage.output_tokens",
"gen_ai.usage.reasoning.output_tokens"
],
"embeddings": [
"gen_ai.operation.name",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ static void runChat(OpenAIClient client) {
completion.usage().ifPresent(usage -> {
span.setAttribute(longKey("gen_ai.usage.input_tokens"), usage.promptTokens());
span.setAttribute(longKey("gen_ai.usage.output_tokens"), usage.completionTokens());
usage.completionTokensDetails().ifPresent(details -> {
details.reasoningTokens().filter(r -> r > 0).ifPresent(reasoning ->
span.setAttribute(longKey("gen_ai.usage.reasoning.output_tokens"), reasoning));
});
});

String content = choice.message().content().orElse("");
Expand Down Expand Up @@ -132,6 +136,10 @@ static void runChat(OpenAIClient client) {
logBuilder
.setAttribute(longKey("gen_ai.usage.input_tokens"), usage.promptTokens())
.setAttribute(longKey("gen_ai.usage.output_tokens"), usage.completionTokens());
usage.completionTokensDetails().ifPresent(details -> {
details.reasoningTokens().filter(r -> r > 0).ifPresent(reasoning ->
logBuilder.setAttribute(longKey("gen_ai.usage.reasoning.output_tokens"), reasoning));
});
});
logBuilder.emit();

Expand Down Expand Up @@ -173,6 +181,10 @@ static void runChatStreaming(OpenAIClient client) {
chunk.usage().ifPresent(usage -> {
span.setAttribute(longKey("gen_ai.usage.input_tokens"), usage.promptTokens());
span.setAttribute(longKey("gen_ai.usage.output_tokens"), usage.completionTokens());
usage.completionTokensDetails().ifPresent(details -> {
details.reasoningTokens().filter(r -> r > 0).ifPresent(reasoning ->
span.setAttribute(longKey("gen_ai.usage.reasoning.output_tokens"), reasoning));
});
});
});
} catch (Exception e) {
Expand Down Expand Up @@ -238,6 +250,10 @@ static void runChatToolCall(OpenAIClient client) {
completion.usage().ifPresent(usage -> {
span.setAttribute(longKey("gen_ai.usage.input_tokens"), usage.promptTokens());
span.setAttribute(longKey("gen_ai.usage.output_tokens"), usage.completionTokens());
usage.completionTokensDetails().ifPresent(details -> {
details.reasoningTokens().filter(r -> r > 0).ifPresent(reasoning ->
span.setAttribute(longKey("gen_ai.usage.reasoning.output_tokens"), reasoning));
});
});

List<ChatCompletionMessageToolCall> toolCalls =
Expand Down
1 change: 1 addition & 0 deletions tests/js/azure-openai/data-prototype.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"gen_ai.tool.definitions",
"gen_ai.usage.input_tokens",
"gen_ai.usage.output_tokens",
"gen_ai.usage.reasoning.output_tokens",
"server.address",
"server.port"
],
Expand Down
12 changes: 12 additions & 0 deletions tests/js/azure-openai/test_prototype.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ async function main() {
if (resp.usage) {
span.setAttribute("gen_ai.usage.input_tokens", resp.usage.prompt_tokens);
span.setAttribute("gen_ai.usage.output_tokens", resp.usage.completion_tokens);
if (resp.usage.completion_tokens_details?.reasoning_tokens) {
span.setAttribute("gen_ai.usage.reasoning.output_tokens", resp.usage.completion_tokens_details.reasoning_tokens);
}
}

// Emit inference operation details event
Expand All @@ -62,6 +65,7 @@ async function main() {
"gen_ai.response.finish_reasons": resp.choices.map(c => c.finish_reason),
"gen_ai.usage.input_tokens": resp.usage?.prompt_tokens,
"gen_ai.usage.output_tokens": resp.usage?.completion_tokens,
"gen_ai.usage.reasoning.output_tokens": resp.usage?.completion_tokens_details?.reasoning_tokens || undefined,
"gen_ai.input.messages": JSON.stringify(
messages.map(m => ({ role: m.role, parts: [{ type: "text", content: m.content }] }))
),
Expand Down Expand Up @@ -105,6 +109,7 @@ async function main() {
let finishReason = "";
let inputTokens = 0;
let outputTokens = 0;
let reasoningTokens: number | undefined;
for await (const chunk of stream) {
if (chunk.choices[0]?.delta?.content) {
text += chunk.choices[0].delta.content;
Expand All @@ -117,6 +122,9 @@ async function main() {
if (chunk.usage) {
inputTokens = chunk.usage.prompt_tokens;
outputTokens = chunk.usage.completion_tokens;
if (chunk.usage.completion_tokens_details?.reasoning_tokens) {
reasoningTokens = chunk.usage.completion_tokens_details.reasoning_tokens;
}
}
}
span.setAttribute("gen_ai.response.model", model);
Expand All @@ -126,6 +134,7 @@ async function main() {
}
if (inputTokens) span.setAttribute("gen_ai.usage.input_tokens", inputTokens);
if (outputTokens) span.setAttribute("gen_ai.usage.output_tokens", outputTokens);
if (reasoningTokens) span.setAttribute("gen_ai.usage.reasoning.output_tokens", reasoningTokens);
console.log(` -> ${text.slice(0, 60)}`);
span.end();
});
Expand Down Expand Up @@ -168,6 +177,9 @@ async function main() {
if (resp.usage) {
span.setAttribute("gen_ai.usage.input_tokens", resp.usage.prompt_tokens);
span.setAttribute("gen_ai.usage.output_tokens", resp.usage.completion_tokens);
if (resp.usage.completion_tokens_details?.reasoning_tokens) {
span.setAttribute("gen_ai.usage.reasoning.output_tokens", resp.usage.completion_tokens_details.reasoning_tokens);
}
}
const toolCall = resp.choices[0].message.tool_calls?.[0];
if (toolCall?.type === "function") {
Expand Down
1 change: 1 addition & 0 deletions tests/js/openai/data-prototype.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"gen_ai.tool.definitions",
"gen_ai.usage.input_tokens",
"gen_ai.usage.output_tokens",
"gen_ai.usage.reasoning.output_tokens",
"server.address",
"server.port"
],
Expand Down
12 changes: 12 additions & 0 deletions tests/js/openai/test_prototype.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ async function main() {
if (resp.usage) {
span.setAttribute("gen_ai.usage.input_tokens", resp.usage.prompt_tokens);
span.setAttribute("gen_ai.usage.output_tokens", resp.usage.completion_tokens);
if (resp.usage.completion_tokens_details?.reasoning_tokens) {
span.setAttribute("gen_ai.usage.reasoning.output_tokens", resp.usage.completion_tokens_details.reasoning_tokens);
}
}

// Emit inference operation details event
Expand All @@ -58,6 +61,7 @@ async function main() {
"gen_ai.response.finish_reasons": resp.choices.map(c => c.finish_reason),
"gen_ai.usage.input_tokens": resp.usage?.prompt_tokens,
"gen_ai.usage.output_tokens": resp.usage?.completion_tokens,
"gen_ai.usage.reasoning.output_tokens": resp.usage?.completion_tokens_details?.reasoning_tokens || undefined,
"gen_ai.input.messages": JSON.stringify(
messages.map(m => ({ role: m.role, parts: [{ type: "text", content: m.content }] }))
),
Expand Down Expand Up @@ -101,6 +105,7 @@ async function main() {
let finishReason = "";
let inputTokens = 0;
let outputTokens = 0;
let reasoningTokens: number | undefined;
for await (const chunk of stream) {
if (chunk.choices[0]?.delta?.content) {
text += chunk.choices[0].delta.content;
Expand All @@ -113,6 +118,9 @@ async function main() {
if (chunk.usage) {
inputTokens = chunk.usage.prompt_tokens;
outputTokens = chunk.usage.completion_tokens;
if (chunk.usage.completion_tokens_details?.reasoning_tokens) {
reasoningTokens = chunk.usage.completion_tokens_details.reasoning_tokens;
}
}
}
span.setAttribute("gen_ai.response.model", model);
Expand All @@ -122,6 +130,7 @@ async function main() {
}
if (inputTokens) span.setAttribute("gen_ai.usage.input_tokens", inputTokens);
if (outputTokens) span.setAttribute("gen_ai.usage.output_tokens", outputTokens);
if (reasoningTokens) span.setAttribute("gen_ai.usage.reasoning.output_tokens", reasoningTokens);
console.log(` -> ${text.slice(0, 60)}`);
span.end();
});
Expand Down Expand Up @@ -164,6 +173,9 @@ async function main() {
if (resp.usage) {
span.setAttribute("gen_ai.usage.input_tokens", resp.usage.prompt_tokens);
span.setAttribute("gen_ai.usage.output_tokens", resp.usage.completion_tokens);
if (resp.usage.completion_tokens_details?.reasoning_tokens) {
span.setAttribute("gen_ai.usage.reasoning.output_tokens", resp.usage.completion_tokens_details.reasoning_tokens);
}
}
const toolCall = resp.choices[0].message.tool_calls?.[0];
if (toolCall?.type === "function") {
Expand Down
3 changes: 2 additions & 1 deletion tests/js/vertexai/data-prototype.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"gen_ai.response.model",
"gen_ai.tool.definitions",
"gen_ai.usage.input_tokens",
"gen_ai.usage.output_tokens"
"gen_ai.usage.output_tokens",
"gen_ai.usage.reasoning.output_tokens"
]
},
"events": {
Expand Down
7 changes: 7 additions & 0 deletions tests/js/vertexai/test_prototype.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ async function main() {
if (resp.usageMetadata.candidatesTokenCount) {
span.setAttribute("gen_ai.usage.output_tokens", resp.usageMetadata.candidatesTokenCount);
}
if ((resp.usageMetadata as any).thoughtsTokenCount) {
span.setAttribute("gen_ai.usage.reasoning.output_tokens", (resp.usageMetadata as any).thoughtsTokenCount);
}
}
const text = candidate?.content?.parts?.[0]?.text ?? "";

Expand All @@ -97,6 +100,7 @@ async function main() {
"gen_ai.response.finish_reasons": candidate?.finishReason ? [candidate.finishReason] : undefined,
"gen_ai.usage.input_tokens": resp.usageMetadata?.promptTokenCount,
"gen_ai.usage.output_tokens": resp.usageMetadata?.candidatesTokenCount,
"gen_ai.usage.reasoning.output_tokens": (resp.usageMetadata as any)?.thoughtsTokenCount || undefined,
"gen_ai.input.messages": JSON.stringify([
{ role: "user", parts: [{ type: "text", content: userMessage }] }
]),
Expand Down Expand Up @@ -187,6 +191,9 @@ async function main() {
if (aggregated.usageMetadata.candidatesTokenCount) {
span.setAttribute("gen_ai.usage.output_tokens", aggregated.usageMetadata.candidatesTokenCount);
}
if ((aggregated.usageMetadata as any).thoughtsTokenCount) {
span.setAttribute("gen_ai.usage.reasoning.output_tokens", (aggregated.usageMetadata as any).thoughtsTokenCount);
}
}
console.log(` -> ${text.slice(0, 60)}`);
span.end();
Expand Down
Loading