Gemini coverage
Four paths to bring every Gemini call at your company under Trefur. Pick one — or layer them. They are designed to compose: the two audit-log connectors cover the long tail of users you can't reach with code changes; the proxy + SDK paths give you full content scanning where you can.
Choose your path
Trade-off summary. None of these mutually exclude each other — most production deployments run all four.
| Path | Setup effort | Latency | What we see | User attribution | Best for |
|---|---|---|---|---|---|
| Workspace audit log | Google Workspace OAuth | 5-15 min lag | Gemini-in-Apps generation events (Docs / Sheets / Gmail) | Workspace user → Trefur user binding | Knowledge-worker usage attribution + license efficiency |
| Vertex AI audit log | GCP OAuth, one click | 1-5 min lag | Metadata only (no prompt/completion text) | principalEmail bound to user record | Inventory + discovery — find every Gemini agent, attribute every call |
| Gemini API proxy | API key + base_url swap | Real-time | Full prompt + completion + tool calls | X-Observe-Agent-Key header (or default key) | Runtime visibility + PII redaction + cost attribution |
| SDK patch (in-process) | pip / npm install + one import | Real-time | Same as proxy + framework chain context | Resolved from the SDK's observe key config | Multi-framework agents (LangChain, LlamaIndex, custom) |
Path 1 — Google Workspace audit log
For knowledge-worker Gemini usage (Docs / Sheets / Gmail / Meet summaries), connect Google Workspace via OAuth and Trefur ingests the gemini_in_apps admin reports plus generation events from each app. Useful for attributing every employee's Gemini activity to a Trefur-tracked agent record without per-user setup.
# Settings → Integrations → Google Workspace → Connect # Required scopes: # https://www.googleapis.com/auth/admin.reports.audit.readonly # What gets ingested (both Reports API applications): # - applications/gemini_in_workspace_apps (Docs / Sheets / Gmail / Drive) # - applications/gemini (standalone gemini.google.com under Workspace) # Surfaces: # Drive / Docs / Sheets / Gmail Gemini-generated content events # Standalone gemini.google.com prompt-submission events # Per-user generation counts for license / usage attribution
For developer Gemini usage (apps calling generativelanguage.googleapis.com or aiplatform.googleapis.com), use Path 2 / 3 / 4 below.
Path 2 — Vertex AI audit log
The CISO connects Trefur to GCP via OAuth once. Trefur polls Cloud Audit Logs for every Vertex AI prediction call, registers each unique principal as an observed agent, and binds the call to a Trefur user record via principalEmail. No SDK install, no proxy traffic redirect, no per-application changes — this is the path that scales to a 50,000-employee company.
# Settings → Integrations → Vertex AI Audit Logs → Connect # (You'll be redirected to Google for OAuth consent.) # Required scopes (already requested by the connector): # https://www.googleapis.com/auth/cloud-platform.read-only # (transitively grants logging.read) # What gets ingested (two surfaces, one connector): # 1. Vertex AI: resource.type = "aiplatform.googleapis.com/Model" # methodName = GenerateContent / StreamGenerateContent / CountTokens / Predict / RawPredict # 2. Cloud Assist: serviceName = "cloudaicompanion.googleapis.com" # Covers "Explain this error", "Generate Terraform", # Code Assist, and the in-console Gemini chat. # Per call, Trefur records the calling principal (bound to a user), # the Gemini model, token usage, and any tool calls the model made. # Cloud Audit Logs do NOT include prompt or completion text.
Cloud Audit Logs do not include prompt or completion text. For prompt+completion content scanning (PII, secrets, tool misuse), layer the proxy or SDK path on top.
Path 3 — Gemini API proxy (local collector)
Run the trefur collector and point your applications at its LLM proxy on http://localhost:9091. The path prefix /proxy/generativelanguage.googleapis.com/… tells the collector which upstream to forward to, so it proxies every request to generativelanguage.googleapis.com and captures the full prompt + completion. Streaming SSE calls (streamGenerateContent) are passed through chunk-by-chunk while we tee the content into the telemetry pipeline.
cURL
# Point your Gemini-using application at the local collector's LLM proxy.
# The collector runs on http://localhost:9091 by default; the path prefix
# /proxy/<provider-host>/ tells it which upstream to forward to.
# (Change localhost:9091 to your collector's address if it runs elsewhere.)
# Drop-in swap for https://generativelanguage.googleapis.com
curl http://localhost:9091/proxy/generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "X-Observe-Agent-Key: trf_obs_live_REPLACE_ME" \
-H "Content-Type: application/json" \
-d '{
"contents": [{
"parts": [{"text": "Summarize last quarter sales."}]
}]
}'
# Streaming (SSE) calls work the same way:
curl http://localhost:9091/proxy/generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:streamGenerateContent \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{...}'Drop-in SDK swap
# Python SDK — point the endpoint at the collector's LLM proxy:
import google.generativeai as genai
genai.configure(
api_key="$GEMINI_API_KEY",
transport="rest",
client_options={"api_endpoint": "http://localhost:9091/proxy/generativelanguage.googleapis.com"},
)
# Node.js SDK:
import { GoogleGenerativeAI } from "@google/generative-ai";
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!, {
baseUrl: "http://localhost:9091/proxy/generativelanguage.googleapis.com",
});Path 4 — SDK patch (in-process)
The Trefur SDK monkey-patches the official Gemini SDK so calls go through Google directly while telemetry is captured in-process. Same content visibility as the proxy, plus framework-level context like LangChain chain id, agent role, and tool name — surfaced as trefur.tool.name attributes via the OpenTelemetry conventions. Coverage spans both the legacy and the new Gemini SDKs in Python + Node; Go calls are routed through the collector LLM proxy (see below) because Go's typed RPC interfaces don't lend themselves to runtime monkey-patching.
Python — new google-genai (recommended)
# Python — new google-genai SDK (recommended).
# pip install trefur-observe google-genai
from google import genai
from trefur_observe import TrefurObserve, patch_gemini
TrefurObserve.init(api_key="$TREFUR_API_KEY")
patch_gemini(TrefurObserve.get_instance())
client = genai.Client(api_key="$GOOGLE_API_KEY")
resp = client.models.generate_content(
model="gemini-2.0-flash",
contents="Summarize last quarter sales.",
)Python — legacy google-generativeai
# Python — legacy google-generativeai SDK.
# pip install trefur-observe google-generativeai
import google.generativeai as genai
from trefur_observe import TrefurObserve, patch_gemini
TrefurObserve.init(api_key="$TREFUR_API_KEY")
patch_gemini(TrefurObserve.get_instance())
genai.configure(api_key="$GOOGLE_API_KEY")
model = genai.GenerativeModel("gemini-1.5-pro")
resp = model.generate_content("Summarize last quarter sales.")Node — new @google/genai (recommended)
// Node — new @google/genai SDK (recommended).
// npm install @trefur/observe @google/genai
import * as GenAI from "@google/genai";
import { TrefurObserve, patchGemini } from "@trefur/observe";
TrefurObserve.init({ apiKey: process.env.TREFUR_API_KEY! });
patchGemini(GenAI, TrefurObserve.getInstance());
const client = new GenAI.GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY! });
const resp = await client.models.generateContent({
model: "gemini-2.0-flash",
contents: "Summarize last quarter sales.",
});Node — legacy @google/generative-ai
// Node — legacy @google/generative-ai SDK.
// npm install @trefur/observe @google/generative-ai
import * as Gemini from "@google/generative-ai";
import { TrefurObserve, patchGemini } from "@trefur/observe";
TrefurObserve.init({ apiKey: process.env.TREFUR_API_KEY! });
patchGemini(Gemini, TrefurObserve.getInstance());
const client = new Gemini.GoogleGenerativeAI(process.env.GOOGLE_API_KEY!);
const model = client.getGenerativeModel({ model: "gemini-1.5-pro" });
const resp = await model.generateContent("Summarize last quarter sales.");Go — proxy-routed (no in-process patch)
Go gets the same prompt+completion + cost coverage as the SDK paths in Python / Node — just via the collector's LLM proxy port (default 9091) instead of an in-process monkey-patch.
// Go — Gemini calls go through Trefur's collector LLM proxy, not a
// monkey-patched SDK. (Go's typed RPC interfaces don't lend to runtime
// patching the way Python and Node do.) Run trefur-collector locally,
// then point the official SDK at the proxy:
client, _ := genai.NewClient(ctx,
option.WithAPIKey(os.Getenv("GOOGLE_API_KEY")),
option.WithEndpoint("http://localhost:9091/proxy/generativelanguage.googleapis.com"),
)
defer client.Close()
model := client.GenerativeModel("gemini-2.0-flash")
resp, _ := model.GenerateContent(ctx, genai.Text("Summarize last quarter sales."))Captured fields per call (every SDK path): model name, prompt + completion text, input / output / cached_content_token_count, finish reason, function-call (tool_call) parts, package version (so a single dashboard distinguishes google-genai 1.0 vs google-generativeai 0.8), latency, and cost computed from Gemini's published pricing (including the higher long-context rate above 128K input tokens and the reduced rate for cached tokens).
PII redaction is enabled by default
Both the proxy and the SDK paths route prompt and completion payloads through the collector's redaction pipeline before export. Built-in patterns cover email, SSN, credit card, IBAN, API keys, JWT, and phone numbers — replaced with typed placeholders. Configure the redaction level per credential, per observe key, or per tenant default in Settings → Security inside the app.
See the Python or JavaScript SDK references for install steps.