Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
108 changes: 82 additions & 26 deletions packages/instrumentation-bedrock/src/instrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,26 +335,45 @@ export class BedrockInstrumentation extends InstrumentationBase {
};
}
case "anthropic": {
return {
const baseAttributes = {
[SpanAttributes.LLM_REQUEST_TOP_P]: requestBody["top_p"],
[SpanAttributes.LLM_TOP_K]: requestBody["top_k"],
[SpanAttributes.LLM_REQUEST_TEMPERATURE]: requestBody["temperature"],
[SpanAttributes.LLM_REQUEST_MAX_TOKENS]:
requestBody["max_tokens_to_sample"],

// Prompt & Role
...(this._shouldSendPrompts()
? {
[`${SpanAttributes.LLM_PROMPTS}.0.role`]: "user",
[`${SpanAttributes.LLM_PROMPTS}.0.content`]: requestBody[
"prompt"
]
// The format is removing when we are setting span attribute
.replace("\n\nHuman:", "")
.replace("\n\nAssistant:", ""),
}
: {}),
requestBody["max_tokens_to_sample"] || requestBody["max_tokens"],
};

if (!this._shouldSendPrompts()) {
return baseAttributes;
}

// Handle new messages API format (used by langchain)
if (requestBody["messages"]) {
const promptAttributes: Record<string, any> = {};
requestBody["messages"].forEach((message: any, index: number) => {
promptAttributes[`${SpanAttributes.LLM_PROMPTS}.${index}.role`] =
message.role;
promptAttributes[`${SpanAttributes.LLM_PROMPTS}.${index}.content`] =
typeof message.content === "string"
? message.content
: JSON.stringify(message.content);
});
return { ...baseAttributes, ...promptAttributes };
}

// Handle legacy prompt format
if (requestBody["prompt"]) {
return {
...baseAttributes,
[`${SpanAttributes.LLM_PROMPTS}.0.role`]: "user",
[`${SpanAttributes.LLM_PROMPTS}.0.content`]: requestBody["prompt"]
// The format is removing when we are setting span attribute
.replace("\n\nHuman:", "")
.replace("\n\nAssistant:", ""),
};
}

return baseAttributes;
}
case "cohere": {
return {
Expand All @@ -368,7 +387,7 @@ export class BedrockInstrumentation extends InstrumentationBase {
? {
[`${SpanAttributes.LLM_PROMPTS}.0.role`]: "user",
[`${SpanAttributes.LLM_PROMPTS}.0.content`]:
requestBody["prompt"],
requestBody["message"] || requestBody["prompt"],
}
: {}),
};
Expand Down Expand Up @@ -439,30 +458,67 @@ export class BedrockInstrumentation extends InstrumentationBase {
};
}
case "anthropic": {
return {
const baseAttributes = {
[`${SpanAttributes.LLM_COMPLETIONS}.0.finish_reason`]:
response["stop_reason"],
[`${SpanAttributes.LLM_COMPLETIONS}.0.role`]: "assistant",
...(this._shouldSendPrompts()
? {
[`${SpanAttributes.LLM_COMPLETIONS}.0.content`]:
response["completion"],
}
: {}),
};

if (!this._shouldSendPrompts()) {
return baseAttributes;
}

// Handle new messages API format response
if (response["content"]) {
const content = Array.isArray(response["content"])
? response["content"].map((c: any) => c.text || c).join("")
: response["content"];
return {
...baseAttributes,
[`${SpanAttributes.LLM_COMPLETIONS}.0.content`]: content,
};
}

// Handle legacy completion format
if (response["completion"]) {
return {
...baseAttributes,
[`${SpanAttributes.LLM_COMPLETIONS}.0.content`]:
response["completion"],
};
}

return baseAttributes;
}
case "cohere": {
return {
const baseAttributes = {
[`${SpanAttributes.LLM_COMPLETIONS}.0.finish_reason`]:
response["generations"][0]["finish_reason"],
response["generations"]?.[0]?.["finish_reason"],
[`${SpanAttributes.LLM_COMPLETIONS}.0.role`]: "assistant",
...(this._shouldSendPrompts()
? {
[`${SpanAttributes.LLM_COMPLETIONS}.0.content`]:
response["generations"][0]["text"],
response["generations"]?.[0]?.["text"],
}
: {}),
};

// Add token usage if available
if (response["meta"] && response["meta"]["billed_units"]) {
const billedUnits = response["meta"]["billed_units"];
return {
...baseAttributes,
[SpanAttributes.LLM_USAGE_PROMPT_TOKENS]:
billedUnits["input_tokens"],
[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS]:
billedUnits["output_tokens"],
[SpanAttributes.LLM_USAGE_TOTAL_TOKENS]:
(billedUnits["input_tokens"] || 0) +
(billedUnits["output_tokens"] || 0),
};
}

return baseAttributes;
}
case "meta": {
return {
Expand Down
6 changes: 4 additions & 2 deletions packages/instrumentation-langchain/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"access": "public"
},
"dependencies": {
"@langchain/core": "^0.3.58",
"@langchain/core": "^0.3.70",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/core": "^2.0.1",
"@opentelemetry/instrumentation": "^0.203.0",
Expand All @@ -47,15 +47,17 @@
"tslib": "^2.8.1"
},
"devDependencies": {
"@langchain/community": "^0.3.49",
"@langchain/community": "^0.3.50",
"@langchain/openai": "^0.6.2",
"@opentelemetry/context-async-hooks": "^2.0.1",
"@opentelemetry/sdk-trace-node": "^2.0.1",
"@pollyjs/adapter-fetch": "^6.0.6",
"@pollyjs/adapter-node-http": "^6.0.6",
"@pollyjs/core": "^6.0.6",
"@pollyjs/persister-fs": "^6.0.6",
"@traceloop/instrumentation-bedrock": "workspace:*",
"@types/mocha": "^10.0.10",
"@types/node": "^24.0.15",
"langchain": "^0.3.30",
"mocha": "^11.7.1",
"ts-mocha": "^11.1.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
"log": {
"_recordingName": "Test Langchain instrumentation/should set attributes in span for BedrockChat with tools",
"creator": {
"comment": "persister:fs",
"name": "Polly.JS",
"version": "6.0.6"
},
"entries": [
{
"_id": "33d0981109e372ba00d53a7539abbf6c",
"_order": 0,
"cache": {},
"request": {
"bodySize": 181,
"cookies": [],
"headers": [
{
"name": "accept",
"value": "application/json"
},
{
"name": "content-type",
"value": "application/json"
},
{
"name": "host",
"value": "bedrock-runtime.us-east-1.amazonaws.com"
},
{
"name": "x-amz-content-sha256",
"value": "310e77b0f186ec71e53132330f18b74d81cec1ef6123bdfb6e7bb1d60acc149a"
},
{
"name": "x-amz-date",
"value": "20250817T135829Z"
}
],
"headersSize": 599,
"httpVersion": "HTTP/1.1",
"method": "POST",
"postData": {
"mimeType": "application/json",
"params": [],
"text": "{\"anthropic_version\":\"bedrock-2023-05-31\",\"messages\":[{\"role\":\"user\",\"content\":\"What is a popular landmark in the most populous city in the US?\"}],\"max_tokens\":1024,\"temperature\":0}"
},
"queryString": [],
"url": "https://bedrock-runtime.us-east-1.amazonaws.com/model/us.anthropic.claude-3-7-sonnet-20250219-v1:0/invoke"
},
"response": {
"bodySize": 636,
"content": {
"mimeType": "application/json",
"size": 636,
"text": "{\"id\":\"msg_bdrk_012QekNLTDnyWFKgKZZvt5bU\",\"type\":\"message\",\"role\":\"assistant\",\"model\":\"claude-3-7-sonnet-20250219\",\"content\":[{\"type\":\"text\",\"text\":\"One of the most popular landmarks in New York City (the most populous city in the US) is the Statue of Liberty. Other famous landmarks include the Empire State Building, Times Square, Central Park, and the Brooklyn Bridge. These iconic sites attract millions of visitors each year and are symbols of the city recognized worldwide.\"}],\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"usage\":{\"input_tokens\":21,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"output_tokens\":67}}"
},
"cookies": [],
"headers": [
{
"name": "connection",
"value": "keep-alive"
},
{
"name": "content-length",
"value": "636"
},
{
"name": "content-type",
"value": "application/json"
},
{
"name": "date",
"value": "Sun, 17 Aug 2025 13:58:31 GMT"
},
{
"name": "x-amzn-bedrock-input-token-count",
"value": "21"
},
{
"name": "x-amzn-bedrock-invocation-latency",
"value": "1556"
},
{
"name": "x-amzn-bedrock-output-token-count",
"value": "67"
},
{
"name": "x-amzn-requestid",
"value": "05d04cc7-d04a-4303-ae05-764aae5b533a"
}
],
"headersSize": 290,
"httpVersion": "HTTP/1.1",
"redirectURL": "",
"status": 200,
"statusText": "OK"
},
"startedDateTime": "2025-08-17T13:58:29.310Z",
"time": 2038,
"timings": {
"blocked": -1,
"connect": -1,
"dns": -1,
"receive": 0,
"send": 0,
"ssl": -1,
"wait": 2038
}
}
],
"pages": [],
"version": "1.2"
}
}
Loading