@traceai/google-genai-sdk 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -2
- package/dist/capture.d.ts +44 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +414 -0
- package/dist/capture.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +543 -0
- package/dist/index.js.map +1 -0
- package/dist/promise.d.ts +6 -0
- package/dist/promise.d.ts.map +1 -0
- package/dist/promise.js +46 -0
- package/dist/promise.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/package.json +47 -3
- package/src/capture.ts +443 -0
- package/src/index.ts +668 -0
- package/src/promise.ts +52 -0
- package/src/version.ts +1 -0
package/README.md
CHANGED
|
@@ -1,3 +1,73 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Google GenAI tracing for Node.js
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Trace calls to the modern `@google/genai` SDK in Future AGI, including generation, chat, embeddings and Interactions.
|
|
4
|
+
|
|
5
|
+
Use Node.js 20 or later and `@google/genai` 1.33–2.x. This package does not instrument the older `@google/generative-ai` SDK; keep `@traceai/google-genai` for applications using that legacy SDK. Keep your Future AGI secret key on your server, not in a browser bundle.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @google/genai@^2.32.0 @traceai/google-genai-sdk @traceai/fi-core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Set `GOOGLE_API_KEY`, `FI_API_KEY` and `FI_SECRET_KEY` in your server environment. Create your Future AGI keys in your workspace settings. The FI exporter sends OTLP traces to `https://api.futureagi.com/tracer/v1/traces`; it maps the FI environment variables to the `x-api-key` and `x-secret-key` collector headers. These credentials are not added to Google requests.
|
|
14
|
+
|
|
15
|
+
## Trace your client
|
|
16
|
+
|
|
17
|
+
Save this as `example.mjs` and run `node example.mjs`.
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
import { GoogleGenAI } from '@google/genai';
|
|
21
|
+
import { register, ProjectType } from '@traceai/fi-core';
|
|
22
|
+
import { instrumentGoogleGenAI } from '@traceai/google-genai-sdk';
|
|
23
|
+
|
|
24
|
+
const provider = register({
|
|
25
|
+
projectName: 'google-genai-app',
|
|
26
|
+
projectType: ProjectType.OBSERVE,
|
|
27
|
+
batch: true,
|
|
28
|
+
});
|
|
29
|
+
const ai = new GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY });
|
|
30
|
+
const tracing = instrumentGoogleGenAI(ai, { tracerProvider: provider });
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const response = await ai.models.generateContent({
|
|
34
|
+
model: 'gemini-2.5-flash',
|
|
35
|
+
contents: 'Suggest a name for a neighborhood bookstore.',
|
|
36
|
+
});
|
|
37
|
+
console.log(response.text);
|
|
38
|
+
|
|
39
|
+
for await (const chunk of await ai.models.generateContentStream({
|
|
40
|
+
model: 'gemini-2.5-flash',
|
|
41
|
+
contents: 'Write a one-sentence welcome for the bookstore.',
|
|
42
|
+
})) {
|
|
43
|
+
process.stdout.write(chunk.text ?? '');
|
|
44
|
+
}
|
|
45
|
+
} finally {
|
|
46
|
+
tracing.dispose();
|
|
47
|
+
await provider.forceFlush();
|
|
48
|
+
await provider.shutdown();
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Open your `google-genai-app` project in Future AGI and inspect the generation spans. Each public SDK call is one logical span; automatic tool calling and continuation remain the SDK's responsibility, without additional synthetic tool-execution spans. Generation usage sums independent Google requests, counting each stream's cumulative usage only once. Tool definitions come from the declarations the SDK resolves, without invoking tools again. Existing OpenTelemetry parents and FI session/user context are retained.
|
|
53
|
+
|
|
54
|
+
If a generation request omits usage, `google.genai.usage_capture=partial` marks the observed counts as incomplete. If per-request observation is unavailable, for example because SDK methods were frozen before setup, usage is omitted and marked `google.genai.usage_capture=unavailable` rather than reporting the final tool hop as a complete call total.
|
|
55
|
+
|
|
56
|
+
## Supported calls
|
|
57
|
+
|
|
58
|
+
- `models.generateContent` and `generateContentStream`, including chat calls through `chats.create().sendMessage` and `sendMessageStream`.
|
|
59
|
+
- `models.embedContent`: text inputs, returned embedding count/dimensions and usage when exposed by the SDK. Vectors are never captured. Text-batch input counts are recorded only for unambiguous input shapes.
|
|
60
|
+
- `interactions.create`, `get`, `cancel` and `delete` when the installed SDK exposes them. Older SDK promise helpers are preserved: `withResponse()` retains parsed data and the HTTP response; `asResponse()` leaves the body unread and records request-only timing (`google.genai.response_capture=request_only`). Background calls describe submission or an explicit poll, not remote execution. No extra polling is performed.
|
|
61
|
+
- `models.generateImages`, `editImage` and `generateVideos` where the Google backend supports them. Video spans describe submission, not finished video generation. Media bytes and file URLs are never captured.
|
|
62
|
+
|
|
63
|
+
Consume streams with `for await`, or use the Interactions stream's reader/legacy readable conversion. Finish consumption or close the iterator when you stop early so its span can end. Stream branching/piping retains the SDK's behavior but ends a request-only span, marked `google.genai.stream_capture=request_only`; use iteration or readers for full stream timing and content. Live WebSocket sessions, cache/file/batch administration and token counting are not traced by this package; their SDK methods remain available.
|
|
64
|
+
|
|
65
|
+
## Privacy and lifecycle
|
|
66
|
+
|
|
67
|
+
The shared FI controls apply when you instrument the client: `FI_HIDE_INPUTS`, `FI_HIDE_OUTPUTS`, `FI_HIDE_INPUT_MESSAGES`, `FI_HIDE_OUTPUT_MESSAGES`, `FI_HIDE_INPUT_TEXT`, `FI_HIDE_OUTPUT_TEXT`, `FI_HIDE_INPUT_IMAGES`, `FI_HIDE_EMBEDDING_VECTORS`, `FI_PII_REDACTION` and `FI_HIDE_ERROR_DETAILS`. Set them before calling `instrumentGoogleGenAI`, or pass the corresponding `traceConfig` options.
|
|
68
|
+
|
|
69
|
+
Text-hiding options omit that side's entire content surface, including tool arguments and schemas. Raw request/response objects, transport headers, media bytes, URLs, embedding vectors and provider error messages/stacks are never recorded, even with content capture enabled. Error spans retain error status and a generic error type. `FI_BASE64_IMAGE_MAX_LENGTH` cannot enable media capture. Content capture is bounded to 16,384 characters per call; adjust `maxContentLength` between 0 and 65,536. Truncated captures carry `google.genai.capture_truncated`.
|
|
70
|
+
|
|
71
|
+
`disable()` stops tracing new calls; `enable()` resumes it. `dispose()` stops tracing new calls immediately and restores the client's methods after in-flight calls drain. Repeated setup on a client returns the existing handle and retains its original options. To change providers or privacy settings, dispose and instrument again. Frozen methods cannot be instrumented; configure tracing before freezing your client. Always flush and shut down the provider when your process exits.
|
|
72
|
+
|
|
73
|
+
If you already configured an OpenTelemetry provider, pass it as `tracerProvider` instead of registering another provider. Instrument each client once, and avoid combining this package with another instrumentor for the same SDK calls.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Span } from "@opentelemetry/api";
|
|
2
|
+
import type { TraceConfig } from "@traceai/fi-core";
|
|
3
|
+
type RecordValue = Record<string, unknown>;
|
|
4
|
+
export declare function record(value: unknown): RecordValue;
|
|
5
|
+
/** Capture is deliberately allowlisted: never serialize SDK options, HTTP responses or binary. */
|
|
6
|
+
export declare class Capture {
|
|
7
|
+
private span;
|
|
8
|
+
private remaining;
|
|
9
|
+
private output;
|
|
10
|
+
private firstContent;
|
|
11
|
+
private truncated;
|
|
12
|
+
private generation;
|
|
13
|
+
private embedding;
|
|
14
|
+
private embeddingUsageSnapshot;
|
|
15
|
+
private hops;
|
|
16
|
+
private capturedTools;
|
|
17
|
+
private usageTotals;
|
|
18
|
+
private usageHops;
|
|
19
|
+
private started;
|
|
20
|
+
private allowInput;
|
|
21
|
+
private allowOutput;
|
|
22
|
+
constructor(span: Span, config: TraceConfig, limit: number);
|
|
23
|
+
private bounded;
|
|
24
|
+
private text;
|
|
25
|
+
private json;
|
|
26
|
+
private parts;
|
|
27
|
+
input(params: RecordValue, operation: string): void;
|
|
28
|
+
private tools;
|
|
29
|
+
/** A hop gets its own cumulative usage snapshot. Sum independent hops, not SSE chunks. */
|
|
30
|
+
generationHop(params: RecordValue): (value: unknown) => void;
|
|
31
|
+
string(key: string, value: unknown): void;
|
|
32
|
+
private usage;
|
|
33
|
+
/** Only numeric, allowlisted billing fields from the SDK-owned JSON parse. */
|
|
34
|
+
embeddingUsage(value: unknown): void;
|
|
35
|
+
/** Vertex exposes billing counts on the converted embeddings, not usageMetadata.
|
|
36
|
+
* Missing or invalid statistics must not turn a partial sum into a call total.
|
|
37
|
+
*/
|
|
38
|
+
private embeddingTokens;
|
|
39
|
+
response(value: unknown): void;
|
|
40
|
+
private append;
|
|
41
|
+
finish(): void;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=capture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC3C,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAIlD;AAID,kGAAkG;AAClG,qBAAa,OAAO;IAgBhB,OAAO,CAAC,IAAI;IAfd,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,sBAAsB,CAA6B;IAC3D,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,WAAW,CAAU;gBAEnB,IAAI,EAAE,IAAI,EAClB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM;IAef,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,IAAI;IA6BZ,OAAO,CAAC,KAAK;IAuBb,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAmEnD,OAAO,CAAC,KAAK;IAQb,0FAA0F;IAC1F,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;IAiC5D,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAMzC,OAAO,CAAC,KAAK;IAsDb,8EAA8E;IAC9E,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAMpC;;OAEG;IACH,OAAO,CAAC,eAAe;IAWvB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAuH9B,OAAO,CAAC,MAAM;IAId,MAAM,IAAI,IAAI;CAiBf"}
|
package/dist/capture.js
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Capture = void 0;
|
|
4
|
+
exports.record = record;
|
|
5
|
+
const fi_semantic_conventions_1 = require("@traceai/fi-semantic-conventions");
|
|
6
|
+
function record(value) {
|
|
7
|
+
return value !== null && typeof value === "object"
|
|
8
|
+
? value
|
|
9
|
+
: {};
|
|
10
|
+
}
|
|
11
|
+
const list = (value) => Array.isArray(value) ? value : value == null ? [] : [value];
|
|
12
|
+
/** Capture is deliberately allowlisted: never serialize SDK options, HTTP responses or binary. */
|
|
13
|
+
class Capture {
|
|
14
|
+
span;
|
|
15
|
+
remaining;
|
|
16
|
+
output = [];
|
|
17
|
+
firstContent = false;
|
|
18
|
+
truncated = false;
|
|
19
|
+
generation = false;
|
|
20
|
+
embedding = false;
|
|
21
|
+
embeddingUsageSnapshot = new Map();
|
|
22
|
+
hops = 0;
|
|
23
|
+
capturedTools = false;
|
|
24
|
+
usageTotals = new Map();
|
|
25
|
+
usageHops = new Map();
|
|
26
|
+
started = performance.now();
|
|
27
|
+
allowInput;
|
|
28
|
+
allowOutput;
|
|
29
|
+
constructor(span, config, limit) {
|
|
30
|
+
this.span = span;
|
|
31
|
+
this.remaining = limit;
|
|
32
|
+
// Suppress the whole content surface for text hiding, including tool arguments and schemas.
|
|
33
|
+
this.allowInput = !(config.hideInputs ||
|
|
34
|
+
config.hideInputMessages ||
|
|
35
|
+
config.hideInputText);
|
|
36
|
+
this.allowOutput = !(config.hideOutputs ||
|
|
37
|
+
config.hideOutputMessages ||
|
|
38
|
+
config.hideOutputText);
|
|
39
|
+
}
|
|
40
|
+
bounded(value, size) {
|
|
41
|
+
const items = list(value);
|
|
42
|
+
if (items.length > size)
|
|
43
|
+
this.truncated = true;
|
|
44
|
+
return items.slice(0, size);
|
|
45
|
+
}
|
|
46
|
+
text(value) {
|
|
47
|
+
if (typeof value !== "string")
|
|
48
|
+
return undefined;
|
|
49
|
+
const result = value.slice(0, Math.max(0, Math.min(this.remaining, 4096)));
|
|
50
|
+
if (result.length < value.length)
|
|
51
|
+
this.truncated = true;
|
|
52
|
+
if (this.remaining <= 0)
|
|
53
|
+
return undefined;
|
|
54
|
+
this.remaining -= result.length + 16;
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
json(value, depth = 0) {
|
|
58
|
+
if (typeof value === "function" || value === undefined)
|
|
59
|
+
return undefined;
|
|
60
|
+
if (this.remaining <= 0 || depth > 6) {
|
|
61
|
+
this.truncated = true;
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
this.remaining -= 16;
|
|
65
|
+
if (value === null)
|
|
66
|
+
return null;
|
|
67
|
+
if (typeof value === "string")
|
|
68
|
+
return this.text(value);
|
|
69
|
+
if (typeof value === "boolean" || typeof value === "number")
|
|
70
|
+
return value;
|
|
71
|
+
if (Array.isArray(value))
|
|
72
|
+
return this.bounded(value, 32).map((v) => this.json(v, depth + 1));
|
|
73
|
+
const result = {};
|
|
74
|
+
const keys = Object.keys(record(value));
|
|
75
|
+
if (keys.length > 32)
|
|
76
|
+
this.truncated = true;
|
|
77
|
+
for (const key of keys.slice(0, 32)) {
|
|
78
|
+
// Tool arguments and responses can carry credentials at any nesting level.
|
|
79
|
+
if (/data|bytes|base64|headers|api.?key|secret|token|uri|url|auth|cookie|password|passphrase|passwd|pwd|credential|private.?key|access.?key/i.test(key))
|
|
80
|
+
continue;
|
|
81
|
+
const boundedKey = this.text(key);
|
|
82
|
+
if (boundedKey === undefined)
|
|
83
|
+
break;
|
|
84
|
+
result[boundedKey] = this.json(record(value)[key], depth + 1);
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
parts(value) {
|
|
89
|
+
const result = [];
|
|
90
|
+
for (const item of this.bounded(value, 64)) {
|
|
91
|
+
if (this.remaining <= 0)
|
|
92
|
+
break;
|
|
93
|
+
const part = record(item);
|
|
94
|
+
const text = this.text(typeof item === "string" ? item : part.text);
|
|
95
|
+
if (text !== undefined)
|
|
96
|
+
result.push({ type: "text", text });
|
|
97
|
+
for (const key of ["functionCall", "functionResponse"]) {
|
|
98
|
+
if (part[key])
|
|
99
|
+
result.push({ type: key, ...record(this.json(part[key])) });
|
|
100
|
+
}
|
|
101
|
+
if (part.type === "function_call" || part.type === "function_result")
|
|
102
|
+
result.push(this.json(part));
|
|
103
|
+
// Only modality is retained for media, not raw bytes, signed URLs, or file URIs.
|
|
104
|
+
for (const key of ["inlineData", "fileData", "image", "audio", "video"]) {
|
|
105
|
+
if (part[key]) {
|
|
106
|
+
result.push({ type: key });
|
|
107
|
+
this.remaining -= 32;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
input(params, operation) {
|
|
114
|
+
this.generation =
|
|
115
|
+
operation === "generateContent" || operation === "generateContentStream";
|
|
116
|
+
this.embedding = operation === "embedContent";
|
|
117
|
+
this.string(fi_semantic_conventions_1.SemanticConventions.LLM_MODEL_NAME, params.model);
|
|
118
|
+
if (this.embedding) {
|
|
119
|
+
this.string(fi_semantic_conventions_1.SemanticConventions.EMBEDDING_MODEL_NAME, params.model);
|
|
120
|
+
// Text batch semantics. Multimodal embedding models group parts differently;
|
|
121
|
+
// omit a speculative input count for those shapes.
|
|
122
|
+
if (typeof params.contents === "string")
|
|
123
|
+
this.span.setAttribute("embedding.input_count", 1);
|
|
124
|
+
else if (Array.isArray(params.contents) &&
|
|
125
|
+
params.contents.every((v) => typeof v === "string") &&
|
|
126
|
+
!String(params.model).includes("gemini-embedding-2"))
|
|
127
|
+
this.span.setAttribute("embedding.input_count", params.contents.length);
|
|
128
|
+
}
|
|
129
|
+
this.string("google.genai.previous_interaction_id", params.previous_interaction_id);
|
|
130
|
+
if (typeof params.background === "boolean")
|
|
131
|
+
this.span.setAttribute("google.genai.background", params.background);
|
|
132
|
+
const config = record(params.config ?? params.generation_config);
|
|
133
|
+
const numeric = {};
|
|
134
|
+
for (const key of [
|
|
135
|
+
"temperature",
|
|
136
|
+
"topP",
|
|
137
|
+
"topK",
|
|
138
|
+
"maxOutputTokens",
|
|
139
|
+
"candidateCount",
|
|
140
|
+
"seed",
|
|
141
|
+
"top_p",
|
|
142
|
+
"top_k",
|
|
143
|
+
"max_output_tokens",
|
|
144
|
+
]) {
|
|
145
|
+
if (typeof config[key] === "number")
|
|
146
|
+
numeric[key] = config[key];
|
|
147
|
+
}
|
|
148
|
+
this.span.setAttribute(fi_semantic_conventions_1.SemanticConventions.LLM_INVOCATION_PARAMETERS, JSON.stringify(numeric));
|
|
149
|
+
if (!this.allowInput)
|
|
150
|
+
return;
|
|
151
|
+
const messages = [];
|
|
152
|
+
const system = params.system_instruction ?? config.systemInstruction;
|
|
153
|
+
if (system)
|
|
154
|
+
messages.push({
|
|
155
|
+
role: "system",
|
|
156
|
+
content: this.parts(record(system).parts ?? system),
|
|
157
|
+
});
|
|
158
|
+
for (const item of this.bounded(params.contents ?? params.input ?? params.prompt, 64)) {
|
|
159
|
+
if (this.remaining <= 0)
|
|
160
|
+
break;
|
|
161
|
+
const content = record(item);
|
|
162
|
+
messages.push({
|
|
163
|
+
role: this.text(content.role) ?? "user",
|
|
164
|
+
content: this.parts(content.parts ?? content.content ?? item),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (messages.length)
|
|
168
|
+
this.span.setAttribute(fi_semantic_conventions_1.SemanticConventions.LLM_INPUT_MESSAGES, JSON.stringify(messages));
|
|
169
|
+
// Generation tools are observed only after the SDK resolves CallableTools.
|
|
170
|
+
if (!this.generation)
|
|
171
|
+
this.tools(config.tools ?? params.tools);
|
|
172
|
+
}
|
|
173
|
+
tools(value) {
|
|
174
|
+
if (!this.allowInput || this.capturedTools || value == null)
|
|
175
|
+
return;
|
|
176
|
+
this.capturedTools = true;
|
|
177
|
+
this.span.setAttribute(fi_semantic_conventions_1.SemanticConventions.LLM_TOOLS, JSON.stringify(this.json(value)) ?? "[]");
|
|
178
|
+
}
|
|
179
|
+
/** A hop gets its own cumulative usage snapshot. Sum independent hops, not SSE chunks. */
|
|
180
|
+
generationHop(params) {
|
|
181
|
+
this.hops++;
|
|
182
|
+
this.tools(record(params.config).tools);
|
|
183
|
+
const previous = new Map();
|
|
184
|
+
let promptInput;
|
|
185
|
+
let toolInput;
|
|
186
|
+
return (value) => {
|
|
187
|
+
const usage = record(record(value).usageMetadata);
|
|
188
|
+
const counts = this.usage(usage);
|
|
189
|
+
const prompt = counts.get(fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT);
|
|
190
|
+
if (prompt !== undefined)
|
|
191
|
+
promptInput = prompt;
|
|
192
|
+
const tool = usage.toolUsePromptTokenCount;
|
|
193
|
+
if (typeof tool === "number" && Number.isFinite(tool) && tool >= 0)
|
|
194
|
+
toolInput = tool;
|
|
195
|
+
// Built-in tool results are additional input, not generated output. Keep
|
|
196
|
+
// each counter's latest snapshot even when a later chunk omits one, then
|
|
197
|
+
// let the existing hop accounting deduplicate the combined input count.
|
|
198
|
+
if (toolInput !== undefined) {
|
|
199
|
+
const input = (promptInput ?? 0) + toolInput;
|
|
200
|
+
if ((promptInput ?? 0) >= 0 && Number.isFinite(input))
|
|
201
|
+
counts.set(fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT, input);
|
|
202
|
+
}
|
|
203
|
+
for (const [key, count] of counts) {
|
|
204
|
+
const total = (this.usageTotals.get(key) ?? 0) + count - (previous.get(key) ?? 0);
|
|
205
|
+
if (!previous.has(key))
|
|
206
|
+
this.usageHops.set(key, (this.usageHops.get(key) ?? 0) + 1);
|
|
207
|
+
previous.set(key, count);
|
|
208
|
+
this.usageTotals.set(key, total);
|
|
209
|
+
this.span.setAttribute(key, total);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
string(key, value) {
|
|
214
|
+
if (typeof value === "string") {
|
|
215
|
+
if (value.length > 256)
|
|
216
|
+
this.truncated = true;
|
|
217
|
+
this.span.setAttribute(key, value.slice(0, 256));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
usage(usage) {
|
|
221
|
+
const result = new Map();
|
|
222
|
+
for (const [key, names] of [
|
|
223
|
+
[
|
|
224
|
+
fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT,
|
|
225
|
+
["promptTokenCount", "total_input_tokens", "input_tokens"],
|
|
226
|
+
],
|
|
227
|
+
[
|
|
228
|
+
fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_COMPLETION,
|
|
229
|
+
["candidatesTokenCount", "total_output_tokens", "output_tokens"],
|
|
230
|
+
],
|
|
231
|
+
[fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_TOTAL, ["totalTokenCount", "total_tokens"]],
|
|
232
|
+
[
|
|
233
|
+
fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ,
|
|
234
|
+
["cachedContentTokenCount", "total_cached_tokens"],
|
|
235
|
+
],
|
|
236
|
+
[
|
|
237
|
+
fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING,
|
|
238
|
+
[
|
|
239
|
+
"thoughtsTokenCount",
|
|
240
|
+
"total_thought_tokens",
|
|
241
|
+
"total_reasoning_tokens",
|
|
242
|
+
],
|
|
243
|
+
],
|
|
244
|
+
]) {
|
|
245
|
+
const count = names
|
|
246
|
+
.map((name) => usage[name])
|
|
247
|
+
.find((v) => typeof v === "number" && Number.isFinite(v));
|
|
248
|
+
if (typeof count === "number")
|
|
249
|
+
result.set(key, count);
|
|
250
|
+
}
|
|
251
|
+
// These are numeric cost inputs, not media content. Keep them even when all
|
|
252
|
+
// content is hidden. Fixed modality names avoid provider-controlled keys.
|
|
253
|
+
for (const [prefix, details] of [
|
|
254
|
+
// EmbeddingUsageMetadata uses singular Token; generation uses Tokens.
|
|
255
|
+
// These are aliases of one snapshot, not independent counts to add.
|
|
256
|
+
[fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT, usage.promptTokensDetails ?? usage.promptTokenDetails ?? usage.input_tokens_by_modality],
|
|
257
|
+
[fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_COMPLETION, usage.candidatesTokensDetails ?? usage.output_tokens_by_modality],
|
|
258
|
+
[fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ, usage.cacheTokensDetails ?? usage.cached_tokens_by_modality],
|
|
259
|
+
]) {
|
|
260
|
+
for (const value of list(details)) {
|
|
261
|
+
const detail = record(value);
|
|
262
|
+
const modality = typeof detail.modality === "string" ? detail.modality.toLowerCase() : "";
|
|
263
|
+
const count = detail.tokenCount ?? detail.tokens;
|
|
264
|
+
if (["text", "audio", "image", "video", "document"].includes(modality) &&
|
|
265
|
+
typeof count === "number" && Number.isFinite(count) && count >= 0) {
|
|
266
|
+
const key = `${prefix}.${modality}`;
|
|
267
|
+
result.set(key, (result.get(key) ?? 0) + count);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
/** Only numeric, allowlisted billing fields from the SDK-owned JSON parse. */
|
|
274
|
+
embeddingUsage(value) {
|
|
275
|
+
for (const [key, count] of this.usage(record(record(value).usageMetadata))) {
|
|
276
|
+
this.embeddingUsageSnapshot.set(key, count);
|
|
277
|
+
this.span.setAttribute(key, count);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/** Vertex exposes billing counts on the converted embeddings, not usageMetadata.
|
|
281
|
+
* Missing or invalid statistics must not turn a partial sum into a call total.
|
|
282
|
+
*/
|
|
283
|
+
embeddingTokens(embeddings) {
|
|
284
|
+
if (!Array.isArray(embeddings) || embeddings.length === 0)
|
|
285
|
+
return undefined;
|
|
286
|
+
let total = 0;
|
|
287
|
+
for (const embedding of embeddings) {
|
|
288
|
+
const count = record(record(embedding).statistics).tokenCount;
|
|
289
|
+
if (typeof count !== "number" || !Number.isFinite(count) || count < 0)
|
|
290
|
+
return undefined;
|
|
291
|
+
total += count;
|
|
292
|
+
}
|
|
293
|
+
return Number.isFinite(total) ? total : undefined;
|
|
294
|
+
}
|
|
295
|
+
response(value) {
|
|
296
|
+
const response = record(value);
|
|
297
|
+
const interaction = record(response.interaction);
|
|
298
|
+
this.string(fi_semantic_conventions_1.SemanticConventions.GEN_AI_RESPONSE_ID, response.responseId ?? interaction.id ?? response.id);
|
|
299
|
+
this.string(fi_semantic_conventions_1.SemanticConventions.GEN_AI_RESPONSE_MODEL, response.modelVersion ?? interaction.model ?? response.model);
|
|
300
|
+
this.string("google.genai.status", interaction.status ?? response.status);
|
|
301
|
+
this.string("google.genai.operation_id", response.name);
|
|
302
|
+
if (typeof response.done === "boolean")
|
|
303
|
+
this.span.setAttribute("google.genai.operation_done", response.done);
|
|
304
|
+
if (Array.isArray(response.embeddings)) {
|
|
305
|
+
this.span.setAttribute("embedding.count", response.embeddings.length);
|
|
306
|
+
const values = record(response.embeddings[0]).values;
|
|
307
|
+
if (Array.isArray(values))
|
|
308
|
+
this.span.setAttribute("embedding.dimensions", values.length);
|
|
309
|
+
}
|
|
310
|
+
if (!this.generation) {
|
|
311
|
+
const usage = record(response.usageMetadata ??
|
|
312
|
+
interaction.usage ??
|
|
313
|
+
response.usage ??
|
|
314
|
+
record(response.metadata).total_usage);
|
|
315
|
+
const counts = this.usage(usage);
|
|
316
|
+
if (this.embedding) {
|
|
317
|
+
// The parse hook and public result describe the same response. Preserve
|
|
318
|
+
// aggregate fields stripped by SDK conversion, without adding snapshots.
|
|
319
|
+
for (const [key, count] of this.embeddingUsageSnapshot)
|
|
320
|
+
if (!counts.has(key))
|
|
321
|
+
counts.set(key, count);
|
|
322
|
+
if (!counts.has(fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT)) {
|
|
323
|
+
const input = this.embeddingTokens(response.embeddings);
|
|
324
|
+
if (input !== undefined)
|
|
325
|
+
counts.set(fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT, input);
|
|
326
|
+
}
|
|
327
|
+
const input = counts.get(fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT);
|
|
328
|
+
if (input !== undefined && !counts.has(fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_TOTAL))
|
|
329
|
+
counts.set(fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_TOTAL, input);
|
|
330
|
+
}
|
|
331
|
+
for (const [key, count] of counts)
|
|
332
|
+
this.span.setAttribute(key, count);
|
|
333
|
+
}
|
|
334
|
+
const candidates = list(response.candidates);
|
|
335
|
+
const reasons = candidates
|
|
336
|
+
.map((c) => record(c).finishReason)
|
|
337
|
+
.filter((x) => typeof x === "string");
|
|
338
|
+
if (reasons.length > 16 || reasons.some((reason) => reason.length > 128))
|
|
339
|
+
this.truncated = true;
|
|
340
|
+
if (reasons.length)
|
|
341
|
+
this.span.setAttribute(fi_semantic_conventions_1.SemanticConventions.GEN_AI_RESPONSE_FINISH_REASONS, reasons.slice(0, 16).map((reason) => reason.slice(0, 128)));
|
|
342
|
+
if (!this.firstContent &&
|
|
343
|
+
(candidates
|
|
344
|
+
.slice(0, 16)
|
|
345
|
+
.some((candidate) => list(record(record(candidate).content).parts).length > 0) ||
|
|
346
|
+
response.event_type === "content.delta" ||
|
|
347
|
+
response.event_type === "step.delta" ||
|
|
348
|
+
list(response.steps ??
|
|
349
|
+
interaction.steps ??
|
|
350
|
+
response.outputs ??
|
|
351
|
+
interaction.outputs).length > 0)) {
|
|
352
|
+
this.firstContent = true;
|
|
353
|
+
this.span.setAttribute("gen_ai.response.time_to_first_token", (performance.now() - this.started) / 1000);
|
|
354
|
+
}
|
|
355
|
+
if (!this.allowOutput || this.remaining <= 0)
|
|
356
|
+
return;
|
|
357
|
+
for (const candidate of this.bounded(candidates, 16)) {
|
|
358
|
+
const content = record(record(candidate).content);
|
|
359
|
+
this.append({
|
|
360
|
+
role: this.text(content.role) ?? "model",
|
|
361
|
+
content: this.parts(content.parts),
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
// Released Interactions use model_output steps; older releases use outputs.
|
|
365
|
+
const steps = response.steps ?? interaction.steps;
|
|
366
|
+
if (steps !== undefined) {
|
|
367
|
+
this.output = [];
|
|
368
|
+
for (const step of this.bounded(steps, 64)) {
|
|
369
|
+
if (record(step).type === "model_output")
|
|
370
|
+
this.append({
|
|
371
|
+
role: "model",
|
|
372
|
+
content: this.parts(record(step).content),
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
else if (response.outputs ?? interaction.outputs) {
|
|
377
|
+
this.output = [];
|
|
378
|
+
this.append({
|
|
379
|
+
role: "model",
|
|
380
|
+
content: this.parts(response.outputs ?? interaction.outputs),
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
else if (response.event_type === "content.delta" ||
|
|
384
|
+
response.event_type === "step.delta") {
|
|
385
|
+
this.append({ role: "model", content: this.parts(response.delta) });
|
|
386
|
+
}
|
|
387
|
+
else if (response.event_type === "step.start" &&
|
|
388
|
+
record(response.step).type === "model_output") {
|
|
389
|
+
this.append({
|
|
390
|
+
role: "model",
|
|
391
|
+
content: this.parts(record(response.step).content),
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
append(message) {
|
|
396
|
+
if (!list(record(message).content).length)
|
|
397
|
+
return;
|
|
398
|
+
this.output.push(message);
|
|
399
|
+
}
|
|
400
|
+
finish() {
|
|
401
|
+
if (this.output.length)
|
|
402
|
+
this.span.setAttribute(fi_semantic_conventions_1.SemanticConventions.LLM_OUTPUT_MESSAGES, JSON.stringify(this.output));
|
|
403
|
+
if (this.truncated || this.remaining <= 0)
|
|
404
|
+
this.span.setAttribute("google.genai.capture_truncated", true);
|
|
405
|
+
if (this.generation && !this.hops)
|
|
406
|
+
this.span.setAttribute("google.genai.usage_capture", "unavailable");
|
|
407
|
+
else if (this.generation &&
|
|
408
|
+
(!this.usageHops.size ||
|
|
409
|
+
[...this.usageHops.values()].some((count) => count < this.hops)))
|
|
410
|
+
this.span.setAttribute("google.genai.usage_capture", "partial");
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
exports.Capture = Capture;
|
|
414
|
+
//# sourceMappingURL=capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type TracerProvider } from "@opentelemetry/api";
|
|
2
|
+
import { type TraceConfigOptions } from "@traceai/fi-core";
|
|
3
|
+
export { VERSION } from "./version.js";
|
|
4
|
+
export interface GoogleGenAITracingOptions {
|
|
5
|
+
tracerProvider?: TracerProvider;
|
|
6
|
+
traceConfig?: TraceConfigOptions;
|
|
7
|
+
/** Total captured content budget per call, in characters. Default 16,384; maximum 65,536. */
|
|
8
|
+
maxContentLength?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface GoogleGenAITracing {
|
|
11
|
+
/** Stops tracing new calls. In-flight calls finish normally. */
|
|
12
|
+
disable(): void;
|
|
13
|
+
enable(): void;
|
|
14
|
+
/** Stops new tracing; restores methods after in-flight calls drain. Does not shut down the provider. */
|
|
15
|
+
dispose(): void;
|
|
16
|
+
}
|
|
17
|
+
/** Instruments one modern @google/genai client in place, including existing chats.
|
|
18
|
+
* Duplicate setup returns the existing handle (its original options win).
|
|
19
|
+
* No global module patch, private chat-field rewrite, exporter, or hidden API call is installed.
|
|
20
|
+
*/
|
|
21
|
+
export declare function instrumentGoogleGenAI(client: {
|
|
22
|
+
readonly models: object;
|
|
23
|
+
}, options?: GoogleGenAITracingOptions): GoogleGenAITracing;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,WAAW,yBAAyB;IACxC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,6FAA6F;IAC7F,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AACD,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,OAAO,IAAI,IAAI,CAAC;IAChB,MAAM,IAAI,IAAI,CAAC;IACf,wGAAwG;IACxG,OAAO,IAAI,IAAI,CAAC;CACjB;AA2ND;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACnC,OAAO,GAAE,yBAA8B,GACtC,kBAAkB,CAsVpB"}
|