Skip to content

Commit 288d5c8

Browse files
authored
feat: added dynamic vendor detection (#608)
1 parent 1045733 commit 288d5c8

File tree

11 files changed

+105
-33
lines changed

11 files changed

+105
-33
lines changed

packages/instrumentation-bedrock/src/instrumentation.ts

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,14 @@ export class BedrockInstrumentation extends InstrumentationBase {
152152

153153
try {
154154
const input = params.input as bedrock.InvokeModelCommandInput;
155-
const [vendor, model] = input.modelId
156-
? input.modelId.split(".")
157-
: ["", ""];
155+
const { modelVendor, model } = this._extractVendorAndModel(
156+
input.modelId || "",
157+
);
158158

159159
attributes = {
160-
[SpanAttributes.LLM_SYSTEM]: vendor,
160+
[SpanAttributes.LLM_SYSTEM]: "AWS",
161161
[SpanAttributes.LLM_REQUEST_MODEL]: model,
162-
[SpanAttributes.LLM_RESPONSE_MODEL]: model,
162+
[SpanAttributes.LLM_RESPONSE_MODEL]: input.modelId,
163163
[SpanAttributes.LLM_REQUEST_TYPE]: LLMRequestTypeValues.COMPLETION,
164164
};
165165

@@ -168,7 +168,7 @@ export class BedrockInstrumentation extends InstrumentationBase {
168168

169169
attributes = {
170170
...attributes,
171-
...this._setRequestAttributes(vendor, requestBody),
171+
...this._setRequestAttributes(modelVendor, requestBody),
172172
};
173173
}
174174
} catch (e) {
@@ -199,6 +199,13 @@ export class BedrockInstrumentation extends InstrumentationBase {
199199
: {};
200200

201201
if (SpanAttributes.LLM_SYSTEM in attributes) {
202+
const modelId = attributes[
203+
SpanAttributes.LLM_RESPONSE_MODEL
204+
] as string;
205+
const { modelVendor, model } = this._extractVendorAndModel(modelId);
206+
207+
span.setAttribute(SpanAttributes.LLM_RESPONSE_MODEL, model);
208+
202209
if (!(result.body instanceof Object.getPrototypeOf(Uint8Array))) {
203210
const rawRes = result.body as AsyncIterable<bedrock.ResponseStream>;
204211

@@ -235,7 +242,7 @@ export class BedrockInstrumentation extends InstrumentationBase {
235242
}
236243

237244
let responseAttributes = this._setResponseAttributes(
238-
attributes[SpanAttributes.LLM_SYSTEM],
245+
modelVendor,
239246
parsedResponse,
240247
true,
241248
);
@@ -266,7 +273,7 @@ export class BedrockInstrumentation extends InstrumentationBase {
266273
const parsedResponse = JSON.parse(jsonString);
267274

268275
const responseAttributes = this._setResponseAttributes(
269-
attributes[SpanAttributes.LLM_SYSTEM],
276+
modelVendor,
270277
parsedResponse,
271278
);
272279

@@ -494,4 +501,19 @@ export class BedrockInstrumentation extends InstrumentationBase {
494501
? this._config.traceContent
495502
: true;
496503
}
504+
505+
private _extractVendorAndModel(modelId: string): {
506+
modelVendor: string;
507+
model: string;
508+
} {
509+
if (!modelId) {
510+
return { modelVendor: "", model: "" };
511+
}
512+
513+
const parts = modelId.split(".");
514+
return {
515+
modelVendor: parts[0] || "",
516+
model: parts[1] || "",
517+
};
518+
}
497519
}

packages/instrumentation-bedrock/tests/ai21.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ describe("Test Ai21 with AWS Bedrock Instrumentation", () => {
107107
body: JSON.stringify(params),
108108
};
109109

110-
const [vendor, model] = input.modelId.split(".");
110+
const [, model] = input.modelId.split(".");
111111

112112
const command = new bedrock.InvokeModelCommand(input);
113113
const response = await bedrockRuntimeClient.send(command);
@@ -117,7 +117,7 @@ describe("Test Ai21 with AWS Bedrock Instrumentation", () => {
117117
const spans = memoryExporter.getFinishedSpans();
118118

119119
const attributes = spans[0].attributes;
120-
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], vendor);
120+
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], "AWS");
121121
assert.strictEqual(
122122
attributes[SpanAttributes.LLM_REQUEST_TYPE],
123123
"completion",

packages/instrumentation-bedrock/tests/amazon.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ describe("Test Amazon Titan with AWS Bedrock Instrumentation", () => {
108108
body: JSON.stringify(params),
109109
};
110110

111-
const [vendor, model] = input.modelId.split(".");
111+
const [, model] = input.modelId.split(".");
112112

113113
const command = new bedrock.InvokeModelCommand(input);
114114
const response = await bedrockRuntimeClient.send(command);
@@ -118,7 +118,7 @@ describe("Test Amazon Titan with AWS Bedrock Instrumentation", () => {
118118
const spans = memoryExporter.getFinishedSpans();
119119

120120
const attributes = spans[0].attributes;
121-
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], vendor);
121+
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], "AWS");
122122
assert.strictEqual(
123123
attributes[SpanAttributes.LLM_REQUEST_TYPE],
124124
"completion",
@@ -190,7 +190,7 @@ describe("Test Amazon Titan with AWS Bedrock Instrumentation", () => {
190190
body: JSON.stringify(params),
191191
};
192192

193-
const [vendor, model] = input.modelId.split(".");
193+
const [, model] = input.modelId.split(".");
194194

195195
const command = new bedrock.InvokeModelWithResponseStreamCommand(input);
196196
const response = await bedrockRuntimeClient.send(command);
@@ -203,7 +203,7 @@ describe("Test Amazon Titan with AWS Bedrock Instrumentation", () => {
203203

204204
const attributes = spans[0].attributes;
205205

206-
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], vendor);
206+
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], "AWS");
207207
assert.strictEqual(
208208
attributes[SpanAttributes.LLM_REQUEST_TYPE],
209209
"completion",

packages/instrumentation-bedrock/tests/anthropic.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ describe("Test Anthropic with AWS Bedrock Instrumentation", () => {
106106
body: JSON.stringify(params),
107107
};
108108

109-
const [vendor, model] = input.modelId.split(".");
109+
const [, model] = input.modelId.split(".");
110110

111111
const command = new bedrock.InvokeModelCommand(input);
112112
const response = await bedrockRuntimeClient.send(command);
@@ -116,7 +116,7 @@ describe("Test Anthropic with AWS Bedrock Instrumentation", () => {
116116
const spans = memoryExporter.getFinishedSpans();
117117

118118
const attributes = spans[0].attributes;
119-
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], vendor);
119+
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], "AWS");
120120
assert.strictEqual(
121121
attributes[SpanAttributes.LLM_REQUEST_TYPE],
122122
"completion",
@@ -170,7 +170,7 @@ describe("Test Anthropic with AWS Bedrock Instrumentation", () => {
170170
body: JSON.stringify(params),
171171
};
172172

173-
const [vendor, model] = input.modelId.split(".");
173+
const [, model] = input.modelId.split(".");
174174

175175
const command = new bedrock.InvokeModelWithResponseStreamCommand(input);
176176
const response = await bedrockRuntimeClient.send(command);
@@ -190,7 +190,7 @@ describe("Test Anthropic with AWS Bedrock Instrumentation", () => {
190190

191191
const attributes = spans[0].attributes;
192192

193-
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], vendor);
193+
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], "AWS");
194194
assert.strictEqual(
195195
attributes[SpanAttributes.LLM_REQUEST_TYPE],
196196
"completion",

packages/instrumentation-bedrock/tests/cohere.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ describe("Test Cohere with AWS Bedrock Instrumentation", () => {
106106
body: JSON.stringify(params),
107107
};
108108

109-
const [vendor, model] = input.modelId.split(".");
109+
const [, model] = input.modelId.split(".");
110110

111111
const command = new bedrock.InvokeModelCommand(input);
112112
const response = await bedrockRuntimeClient.send(command);
@@ -116,7 +116,7 @@ describe("Test Cohere with AWS Bedrock Instrumentation", () => {
116116
const spans = memoryExporter.getFinishedSpans();
117117

118118
const attributes = spans[0].attributes;
119-
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], vendor);
119+
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], "AWS");
120120
assert.strictEqual(
121121
attributes[SpanAttributes.LLM_REQUEST_TYPE],
122122
"completion",
@@ -171,7 +171,7 @@ describe("Test Cohere with AWS Bedrock Instrumentation", () => {
171171
body: JSON.stringify(params),
172172
};
173173

174-
const [vendor, model] = input.modelId.split(".");
174+
const [, model] = input.modelId.split(".");
175175

176176
const command = new bedrock.InvokeModelWithResponseStreamCommand(input);
177177
const response = await bedrockRuntimeClient.send(command);
@@ -184,7 +184,7 @@ describe("Test Cohere with AWS Bedrock Instrumentation", () => {
184184

185185
const attributes = spans[0].attributes;
186186

187-
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], vendor);
187+
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], "AWS");
188188
assert.strictEqual(
189189
attributes[SpanAttributes.LLM_REQUEST_TYPE],
190190
"completion",

packages/instrumentation-bedrock/tests/meta.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ describe("Test Meta with AWS Bedrock Instrumentation", () => {
105105
body: JSON.stringify(params),
106106
};
107107

108-
const [vendor, model] = input.modelId.split(".");
108+
const [, model] = input.modelId.split(".");
109109

110110
const command = new bedrock.InvokeModelCommand(input);
111111
const response = await bedrockRuntimeClient.send(command);
@@ -115,7 +115,7 @@ describe("Test Meta with AWS Bedrock Instrumentation", () => {
115115
const spans = memoryExporter.getFinishedSpans();
116116

117117
const attributes = spans[0].attributes;
118-
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], vendor);
118+
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], "AWS");
119119
assert.strictEqual(
120120
attributes[SpanAttributes.LLM_REQUEST_TYPE],
121121
"completion",
@@ -184,7 +184,7 @@ describe("Test Meta with AWS Bedrock Instrumentation", () => {
184184
body: JSON.stringify(params),
185185
};
186186

187-
const [vendor, model] = input.modelId.split(".");
187+
const [, model] = input.modelId.split(".");
188188

189189
const command = new bedrock.InvokeModelWithResponseStreamCommand(input);
190190
const response = await bedrockRuntimeClient.send(command);
@@ -197,7 +197,7 @@ describe("Test Meta with AWS Bedrock Instrumentation", () => {
197197

198198
const attributes = spans[0].attributes;
199199

200-
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], vendor);
200+
assert.strictEqual(attributes[SpanAttributes.LLM_SYSTEM], "AWS");
201201
assert.strictEqual(
202202
attributes[SpanAttributes.LLM_REQUEST_TYPE],
203203
"completion",

packages/instrumentation-openai/src/instrumentation.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,14 @@ export class OpenAIInstrumentation extends InstrumentationBase {
156156
params: args[0] as ChatCompletionCreateParamsNonStreaming & {
157157
extraAttributes?: Record<string, any>;
158158
},
159+
client: this,
159160
})
160161
: plugin.startSpan({
161162
type,
162163
params: args[0] as CompletionCreateParamsNonStreaming & {
163164
extraAttributes?: Record<string, any>;
164165
},
166+
client: this,
165167
});
166168

167169
const execContext = trace.setSpan(context.active(), span);
@@ -214,21 +216,26 @@ export class OpenAIInstrumentation extends InstrumentationBase {
214216
private startSpan({
215217
type,
216218
params,
219+
client,
217220
}:
218221
| {
219222
type: "chat";
220223
params: ChatCompletionCreateParamsNonStreaming & {
221224
extraAttributes?: Record<string, any>;
222225
};
226+
client: any;
223227
}
224228
| {
225229
type: "completion";
226230
params: CompletionCreateParamsNonStreaming & {
227231
extraAttributes?: Record<string, any>;
228232
};
233+
client: any;
229234
}): Span {
235+
const { provider } = this._detectVendorFromURL(client);
236+
230237
const attributes: Attributes = {
231-
[SpanAttributes.LLM_SYSTEM]: "OpenAI",
238+
[SpanAttributes.LLM_SYSTEM]: provider,
232239
[SpanAttributes.LLM_REQUEST_TYPE]: type,
233240
};
234241

@@ -744,4 +751,47 @@ export class OpenAIInstrumentation extends InstrumentationBase {
744751

745752
return encoding.encode(text).length;
746753
}
754+
755+
private _detectVendorFromURL(client: any): {
756+
provider: string;
757+
modelVendor: string;
758+
} {
759+
const modelVendor = "OpenAI";
760+
761+
try {
762+
if (!client?.baseURL) {
763+
return { provider: "OpenAI", modelVendor };
764+
}
765+
766+
const baseURL = client.baseURL.toLowerCase();
767+
768+
if (baseURL.includes("azure") || baseURL.includes("openai.azure.com")) {
769+
return { provider: "Azure", modelVendor };
770+
}
771+
772+
if (
773+
baseURL.includes("openai.com") ||
774+
baseURL.includes("api.openai.com")
775+
) {
776+
return { provider: "OpenAI", modelVendor };
777+
}
778+
779+
if (baseURL.includes("amazonaws.com") || baseURL.includes("bedrock")) {
780+
return { provider: "AWS", modelVendor };
781+
}
782+
783+
if (baseURL.includes("googleapis.com")) {
784+
return { provider: "Google", modelVendor };
785+
}
786+
787+
if (baseURL.includes("openrouter")) {
788+
return { provider: "OpenRouter", modelVendor };
789+
}
790+
791+
return { provider: "OpenAI", modelVendor };
792+
} catch (e) {
793+
this._diag.debug(`Failed to detect vendor from URL: ${e}`);
794+
return { provider: "OpenAI", modelVendor };
795+
}
796+
}
747797
}

packages/instrumentation-vertexai/src/aiplatform-instrumentation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export class AIPlatformInstrumentation extends InstrumentationBase {
157157
| undefined;
158158
}): Span {
159159
const attributes: Attributes = {
160-
[SpanAttributes.LLM_SYSTEM]: "VertexAI",
160+
[SpanAttributes.LLM_SYSTEM]: "Google",
161161
[SpanAttributes.LLM_REQUEST_TYPE]: "completion",
162162
};
163163

packages/instrumentation-vertexai/src/vertexai-instrumentation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ export class VertexAIInstrumentation extends InstrumentationBase {
137137
params: vertexAI.GenerateContentRequest;
138138
}): Span {
139139
const attributes: Attributes = {
140-
[SpanAttributes.LLM_SYSTEM]: "VertexAI",
140+
[SpanAttributes.LLM_SYSTEM]: "Google",
141141
[SpanAttributes.LLM_REQUEST_TYPE]: "completion",
142142
};
143143

packages/instrumentation-vertexai/tests/gemini.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe.skip("Test Gemini GenerativeModel Instrumentation", () => {
8484

8585
const attributes = spans[0].attributes;
8686

87-
assert.strictEqual(attributes["gen_ai.system"], "VertexAI");
87+
assert.strictEqual(attributes["gen_ai.system"], "Google");
8888
assert.strictEqual(attributes["llm.request.type"], "completion");
8989
assert.strictEqual(attributes["gen_ai.request.model"], model);
9090
assert.strictEqual(attributes["gen_ai.request.top_p"], 0.9);
@@ -137,7 +137,7 @@ describe.skip("Test Gemini GenerativeModel Instrumentation", () => {
137137

138138
const attributes = spans[0].attributes;
139139

140-
assert.strictEqual(attributes["gen_ai.system"], "VertexAI");
140+
assert.strictEqual(attributes["gen_ai.system"], "Google");
141141
assert.strictEqual(attributes["llm.request.type"], "completion");
142142
assert.strictEqual(attributes["gen_ai.request.model"], model);
143143
assert.strictEqual(attributes["gen_ai.request.top_p"], 0.9);

0 commit comments

Comments
 (0)