Skip to content

Commit 895382b

Browse files
committed
PR fixes
1 parent 6081443 commit 895382b

File tree

9 files changed

+210
-62
lines changed

9 files changed

+210
-62
lines changed

packages/instrumentation-google-generativeai/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"tslib": "^2.8.1"
5151
},
5252
"devDependencies": {
53-
"@google/genai": "^1.49.0",
53+
"@google/genai": "^1.50.1",
5454
"@opentelemetry/context-async-hooks": "^2.0.1",
5555
"@opentelemetry/sdk-trace-base": "^2.0.1",
5656
"@opentelemetry/sdk-trace-node": "^2.0.1",

packages/instrumentation-google-generativeai/src/content-block-mapper.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,8 @@ export function mapGenAIContentBlock(block: genai.Part | string): object {
6767
const mimeType = block.inlineData.mimeType;
6868
return {
6969
type: GenAIOtelPartType.BLOB,
70-
// Only set modality/mime_type when mimeType is known — an absent mimeType
71-
// produces the wrong modality if we blindly pass "" to genaiModalityFromMimeType.
72-
...(mimeType
73-
? {
74-
modality: genaiModalityFromMimeType(mimeType),
75-
mime_type: mimeType,
76-
}
77-
: {}),
70+
modality: genaiModalityFromMimeType(mimeType ?? ""),
71+
...(mimeType ? { mime_type: mimeType } : {}),
7872
content: block.inlineData.data,
7973
};
8074
}
@@ -83,12 +77,8 @@ export function mapGenAIContentBlock(block: genai.Part | string): object {
8377
const mimeType = block.fileData.mimeType;
8478
return {
8579
type: GenAIOtelPartType.URI,
86-
...(mimeType
87-
? {
88-
modality: genaiModalityFromMimeType(mimeType),
89-
mime_type: mimeType,
90-
}
91-
: {}),
80+
modality: genaiModalityFromMimeType(mimeType ?? ""),
81+
...(mimeType ? { mime_type: mimeType } : {}),
9282
uri: block.fileData.fileUri,
9383
};
9484
}

packages/instrumentation-google-generativeai/src/instrumentation.ts

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import {
4949
ATTR_GEN_AI_PROVIDER_NAME,
5050
ATTR_GEN_AI_SYSTEM_INSTRUCTIONS,
5151
GEN_AI_OPERATION_NAME_VALUE_GENERATE_CONTENT,
52-
GEN_AI_PROVIDER_NAME_VALUE_GCP_GEMINI,
52+
GEN_AI_PROVIDER_NAME_VALUE_GCP_GEN_AI,
5353
} from "@opentelemetry/semantic-conventions/incubating";
5454
import {
5555
formatInputMessages,
@@ -71,7 +71,7 @@ export const genaiFinishReasonMap: Record<string, string> = {
7171
SAFETY: FinishReasons.CONTENT_FILTER,
7272
RECITATION: FinishReasons.CONTENT_FILTER,
7373
LANGUAGE: FinishReasons.CONTENT_FILTER,
74-
OTHER: FinishReasons.OTHER,
74+
OTHER: FinishReasons.ERROR,
7575
BLOCKLIST: FinishReasons.CONTENT_FILTER,
7676
PROHIBITED_CONTENT: FinishReasons.CONTENT_FILTER,
7777
SPII: FinishReasons.CONTENT_FILTER,
@@ -85,11 +85,6 @@ export const genaiFinishReasonMap: Record<string, string> = {
8585
IMAGE_OTHER: FinishReasons.ERROR,
8686
};
8787

88-
// Lowercase and strip the "finish_reason_" prefix for the span-level attribute.
89-
function geminiReasonToSpanValue(reason: string): string {
90-
return reason.toLowerCase().replace(/^finish_reason_/, "");
91-
}
92-
9388
export class GenAIInstrumentation extends InstrumentationBase {
9489
declare protected _config: GenAIInstrumentationConfig;
9590
/** Tracks already-patched modules to prevent double-patching on repeated calls. */
@@ -292,8 +287,11 @@ export class GenAIInstrumentation extends InstrumentationBase {
292287
for (const part of cParts) {
293288
if (part.text !== undefined) {
294289
const prev = acc[acc.length - 1];
295-
if (prev?.text !== undefined) {
296-
prev.text += part.text; // concatenate consecutive text parts
290+
if (
291+
prev?.text !== undefined &&
292+
!!prev.thought === !!part.thought
293+
) {
294+
prev.text += part.text; // concatenate consecutive same-type text parts
297295
} else {
298296
acc.push({ ...part });
299297
}
@@ -377,7 +375,7 @@ export class GenAIInstrumentation extends InstrumentationBase {
377375
const operationType = GEN_AI_OPERATION_NAME_VALUE_GENERATE_CONTENT;
378376

379377
const attributes: Attributes = {
380-
[ATTR_GEN_AI_PROVIDER_NAME]: GEN_AI_PROVIDER_NAME_VALUE_GCP_GEMINI,
378+
[ATTR_GEN_AI_PROVIDER_NAME]: GEN_AI_PROVIDER_NAME_VALUE_GCP_GEN_AI,
381379
[ATTR_GEN_AI_OPERATION_NAME]: operationType,
382380
[ATTR_GEN_AI_REQUEST_MODEL]: model,
383381
};
@@ -463,18 +461,13 @@ export class GenAIInstrumentation extends InstrumentationBase {
463461
try {
464462
const candidates = response.candidates ?? [];
465463

466-
// Collect finish reasons from all candidates (metadata — always emit).
467-
// Use passthrough lowercase for span attribute; deduplicate across candidates.
468-
const finishReasons = [
469-
...new Set(
470-
candidates
471-
.map((c) => c.finishReason)
472-
.filter((r) => r != null)
473-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
474-
.map((r) => geminiReasonToSpanValue(r!)),
475-
),
476-
];
477-
if (finishReasons.length > 0) {
464+
// Collect finish reasons per-candidate (no dedup — matches Python behaviour).
465+
// null/unspecified → ""; set attr only when at least one reason is non-empty.
466+
const finishReasons = candidates.map((c) => {
467+
const r = c.finishReason;
468+
return r != null ? (genaiFinishReasonMap[r] ?? r) : "";
469+
});
470+
if (finishReasons.some((r) => r !== "")) {
478471
span.setAttribute(ATTR_GEN_AI_RESPONSE_FINISH_REASONS, finishReasons);
479472
}
480473

packages/instrumentation-google-generativeai/tests/content_parts.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ describe("mapGenAIContentBlock", () => {
8787
assert.strictEqual(result.mime_type, "video/mp4");
8888
});
8989

90-
it("maps inlineData without mimeType — omits modality and mime_type", () => {
90+
it("maps inlineData without mimeType — uses document modality fallback", () => {
9191
const result = mapGenAIContentBlock({
9292
inlineData: { data: "rawdata" },
9393
}) as Record<string, unknown>;
9494
assert.strictEqual(result.type, "blob");
9595
assert.strictEqual(result.content, "rawdata");
96-
assert.strictEqual(result.modality, undefined);
96+
assert.strictEqual(result.modality, "document");
9797
assert.strictEqual(result.mime_type, undefined);
9898
});
9999
});

packages/instrumentation-google-generativeai/tests/finish_reasons.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ describe("genaiFinishReasonMap", () => {
7070
);
7171
});
7272

73-
it('maps "OTHER" to other', () => {
74-
assert.strictEqual(genaiFinishReasonMap["OTHER"], FinishReasons.OTHER);
73+
it('maps "OTHER" to error', () => {
74+
assert.strictEqual(genaiFinishReasonMap["OTHER"], FinishReasons.ERROR);
7575
});
7676

7777
it('maps "BLOCKLIST" to content_filter', () => {

0 commit comments

Comments
 (0)