BigQuery 回调处理器
社区Python预览> Google BigQuery 是一个无服务器且经济高效的企业数据仓库,可跨云运行并随数据扩展。
该 BigQueryCallbackHandler 允许您将 LangChain 和 LangGraph 中的事件记录到 Google BigQuery。这对于监控、审计和分析 LLM 应用程序的性能非常有用。
主要功能: - **LangGraph 支持**:自动检测 LangGraph 节点及 AGENT_STARTING / AGENT_COMPLETED 事件和顶级 INVOCATION_STARTING / INVOCATION_COMPLETED 边界(词汇与 Google ADK 的 BigQueryAgentAnalyticsPlugin) - **自动创建的 analytics 视图**:每个事件类型一列 CREATE OR REPLACE VIEW 个类型化列(v_llm_response.usage_total_tokens 而不是 JSON_VALUE(...)) - **自动 schema 升级**:追加式 ALTER TABLE ADD COLUMN 在现有表上,由 schema-version 标签控制,因此每个版本最多运行一次 - **子代理归属**: agent BigQuery 列从 langgraph_node 自动派生(当没有显式 agent 在元数据中设置时),因此多代理图按子代理标记,无需用户更改 - **丰富的 LLM 遥测**:token 使用(prompt_tokens / completion_tokens / total_tokens / cached_content_token_count), model_version、完整 usage_metadata, cache_metadata加上 llm_config (temperature、top_p、…)和 tools on LLM_REQUEST - **延迟追踪**:内置延迟测量,用于所有 LLM 和工具调用 - **事件过滤**: configurable allowlist / denylist plus an opt-in skip_internal_chain_events 启发式算法,可丢弃嘈杂的框架链(ChannelWrite, RunnableLambda、…),而不破坏追踪连续性 - **图上下文管理器**:显式 INVOCATION_* 边界和精确计时 - **flush() 在请求之间**:排空队列而不关闭处理器 - **实时仪表板**:带实时事件流 FastAPI 监控 Web 应用
安装
您需要安装 langchain-google-community 以及 bigquery 额外依赖项。对于此示例,您还需要 langchain-google-genai 和 langgraph.
pip install "langchain-google-community[bigquery]" langchain langchain-google-genai langgraph
前提条件
1. **Google Cloud 项目** 启用 **BigQuery API** enabled. 2. **BigQuery 数据集**:在使用回调处理器之前创建一个数据集来存储日志表。回调处理器会在数据集内自动创建必要的事件表(如果该表不存在)。 3. **Google Cloud Storage 存储桶(可选)**:如果您计划记录多模态内容(图像、音频等),建议创建 GCS 存储桶以卸载大文件。 4. **身份验证**: - 本地:运行 gcloud auth application-default login. - 云端:确保您的服务账号具有所需的权限。
IAM 权限
为使回调处理器正常工作,运行应用程序的主体(例如服务账号、用户账号)需要具有以下 Google Cloud 角色:
- -
roles/bigquery.jobUser在项目级别运行 BigQuery 查询。 - -
roles/bigquery.dataEditorat Table Level to write log/event data. - - 如果使用 GCS 卸载:
roles/storage.objectCreator和roles/storage.objectViewer在目标存储桶上。
与 LangGraph agent 配合使用
要将 BigQueryCallbackHandler 与 LangGraph agent 配合使用,请使用您的 Google Cloud 项目 ID 和数据集 ID 实例化它。处理器会在首次运行时创建事件表(以及按事件类型划分的分析视图)。使用 graph_context() 方法跟踪顶级调用边界——它会在进入时发出 INVOCATION_STARTING ,在异常时发出 INVOCATION_COMPLETED (or INVOCATION_ERROR ),并提供准确的延迟。
通过 session_id, user_id中的 agent 字典传递 metadata (以及可选的) config 对象来调用 agent 时。如果 agent 未设置,处理器会从 metadata['langgraph_node'] 自动派生,以便正确归因每个子 agent 的事件。
from datetime import datetime
from langchain.agents import create_agent
from langchain.messages import HumanMessage
from langchain.tools import tool
from langchain_google_community.callbacks.bigquery_callback import (
BigQueryCallbackHandler,
BigQueryLoggerConfig,
)
from langchain_google_genai import ChatGoogleGenerativeAI
# 1. Define tools for the agent
@tool
def get_current_time() -> str:
"""Returns the current local time."""
now = datetime.now()
return f"Current time: {now.strftime('%I:%M:%S %p')} on {now.strftime('%B %d, %Y')}"
@tool
def get_weather(city: str) -> str:
"""Returns the current weather for a specific city."""
# Simulated weather data (use real API in production)
weather_data = {
"new york": {"temp": 22, "condition": "Clear"},
"tokyo": {"temp": 24, "condition": "Sunny"},
"london": {"temp": 14, "condition": "Overcast"},
}
city_lower = city.lower()
if city_lower in weather_data:
data = weather_data[city_lower]
return f"Weather in {city.title()}: {data['temp']}°C, {data['condition']}"
return f"Weather data for '{city}' not available."
@tool
def convert_currency(amount: float, from_currency: str, to_currency: str) -> str:
"""Convert an amount between currencies."""
rates = {"USD": 1.0, "EUR": 1.08, "GBP": 1.27, "JPY": 0.0067}
from_curr, to_curr = from_currency.upper(), to_currency.upper()
if from_curr not in rates or to_curr not in rates:
return f"Unknown currency"
result = amount * rates[from_curr] / rates[to_curr]
return f"{amount} {from_curr} = {result:.2f} {to_curr}"
def run_agent_example(project_id: str):
"""Run a LangGraph agent with BigQuery logging."""
dataset_id = "agent_analytics"
# 2. Configure the callback handler.
# `table_id` defaults to "agent_events"; pass it explicitly only if you
# want a different table. The handler creates the table and the
# per-event-type `v_*` analytics views on first run.
config = BigQueryLoggerConfig(
batch_size=1,
batch_flush_interval=0.5,
custom_tags={"env": "prod", "service": "travel"}, # static tags on every event
)
handler = BigQueryCallbackHandler(
project_id=project_id,
dataset_id=dataset_id,
config=config,
graph_name="travel_assistant", # used for INVOCATION_* events + root_agent_name
)
# 3. Create the LLM and agent
# Use project parameter for Vertex AI, or api_key for Gemini Developer API
llm = ChatGoogleGenerativeAI(
model="gemini-2.5-flash",
project=project_id, # For Vertex AI
)
tools = [get_current_time, get_weather, convert_currency]
agent = create_agent(llm, tools)
# 4. Run with graph_context for INVOCATION_STARTING / INVOCATION_COMPLETED
query = "What time is it? What's the weather in Tokyo? How much is 100 USD in EUR?"
run_metadata = {
"session_id": "session-001",
"user_id": "user-123",
# `agent` is optional — when omitted the handler falls back to
# metadata['langgraph_node'] for per-sub-agent attribution.
}
with handler.graph_context("travel_assistant", metadata=run_metadata):
result = agent.invoke(
{"messages": [HumanMessage(content=query)]},
config={
"callbacks": [handler],
"metadata": run_metadata,
},
)
print(f"Response: {result['messages'][-1].content}")
# 5. Block until pending rows are written (between request boundaries).
# Does NOT shut the handler down — subsequent invocations still work.
handler.flush(timeout=5.0)
# 6. Final cleanup at process exit.
handler.shutdown()
if __name__ == "__main__":
project_id = os.environ.get("GCP_PROJECT_ID", "your-project-id")
run_agent_example(project_id)
配置选项
您可以使用 BigQueryLoggerConfig.
自定义回调处理器。要禁止处理器将数据记录到 BigQuery 表,请将此参数设置为 False.
自动创建 BigQuery 表时用于聚类的字段。
用于卸载大内容(图像、blob、大文本)的 GCS 存储桶名称。如果未提供,大内容可能会被截断或替换为占位符。
BigQuery 连接 ID(例如 us.my-connection)用作 ObjectRef 列的授权者。配合 BigQuery ML 使用 ObjectRef 时需要此参数。
(500 KB)在卸载到 GCS(如已配置)或截断之前,要以内联方式存储在 BigQuery 中的文本内容的最大长度(字符数)。
写入 BigQuery 之前要批量处理的事件数。
刷新部分批次之前的最大等待时间(秒)。
关闭时等待日志刷新的秒数。
要记录的事件类型列表。如果 None,除了以下事件外记录所有事件 event_denylist.
要跳过记录的事件类型列表。
是否记录详细的内容部分(包括 GCS 引用)。
如果未向回调处理程序构造函数显式提供,则使用的默认表 ID。
写入 BigQuery 失败时的重试逻辑配置(最大重试次数、延迟、倍数)。
在丢弃新事件之前,内部缓冲区队列中可容纳的最大事件数。
当 True,丢弃 CHAIN_* 框架内部 Runnables 发出的事件(ChannelWrite, ChannelRead, Branch, RunnableLambda, RunnableSequence, RunnableParallel, RunnableAssign, RunnablePassthrough, RunnableBinding, Pregel, __start__, __end__). Skipped runs are still registered in the trace registry so child LLM/tool events keep the real graph root as their trace_id (无断开的追踪)。每次抑制都记录一条 DEBUG 行,以便审计启发式算法。
静态标签写入 attributes.custom_tags 每行事件。可用于按部署、群组或实验分割仪表板(例如: {"env": "prod", "agent_role": "sales"}).
当 True,转储用户提供的 RunnableConfig 元数据(减去我们已经提升为一类列的键,例如 session_id, user_id, agent, langgraph_node)在 attributes.session_metadata.
可选 (raw_content, event_type) -> formatted 在内容解析前调用的钩子。用于 PII 重标识或强制自定义负载。失败时回退到原始内容并发出警告——格式化程序无法破坏代理。
当 True,以追加方式 ALTER TABLE ADD COLUMN 此处理程序未来版本添加到事件架构的任何新字段。由一个 langchain_bq_schema_version 表标签控制,以便差异最多每个架构版本运行一次。永不删除、重命名或更改列类型。
当 True,自动 CREATE OR REPLACE 在事件表旁边按事件类型创建分析视图。每个视图将 JSON 列展开为类型化的顶级列(见 自动创建的分析视图 下文)。
自动创建视图名称的前缀(v_llm_request, v_tool_completed,…)。当多个处理程序实例共享一个数据集时,按表设置以避免冲突。
以下代码示例展示如何定义具有事件过滤功能的 BigQuery 回调处理程序配置:
from langchain_google_community.callbacks.bigquery_callback import (
BigQueryCallbackHandler,
BigQueryLoggerConfig,
)
# 1. Configure BigQueryLoggerConfig
config = BigQueryLoggerConfig(
enabled=True,
event_allowlist=["LLM_REQUEST", "LLM_RESPONSE"], # Only log these specific events
shutdown_timeout=10.0, # Wait up to 10s for logs to flush on exit
max_content_length=500, # Truncate content to 500 characters
)
# 2. Initialize the Callback Handler
handler = BigQueryCallbackHandler(
project_id="your-project-id",
dataset_id="your_dataset",
table_id="your_table",
config=config,
)
架构和生产环境设置
如果表不存在,插件会自动创建该表。但是,对于生产环境,我们建议使用以下 DDL 手动创建表,该语句利用了 **JSON** 类型以提高灵活性,以及 **REPEATED RECORD**用于多模态内容。
推荐的 DDL:
CREATE TABLE `your-gcp-project-id.adk_agent_logs.agent_events`
(
timestamp TIMESTAMP NOT NULL OPTIONS(description="The UTC timestamp when the event occurred."),
event_type STRING OPTIONS(description="The category of the event."),
agent STRING OPTIONS(description="The name of the agent."),
session_id STRING OPTIONS(description="A unique identifier for the conversation session."),
invocation_id STRING OPTIONS(description="A unique identifier for a single turn."),
user_id STRING OPTIONS(description="The identifier of the end-user."),
trace_id STRING OPTIONS(description="OpenTelemetry trace ID."),
span_id STRING OPTIONS(description="OpenTelemetry span ID."),
parent_span_id STRING OPTIONS(description="OpenTelemetry parent span ID."),
content JSON OPTIONS(description="The primary payload of the event."),
content_parts ARRAY<STRUCT<
mime_type STRING,
uri STRING,
object_ref STRUCT<
uri STRING,
version STRING,
authorizer STRING,
details JSON
>,
text STRING,
part_index INT64,
part_attributes STRING,
storage_mode STRING
>> OPTIONS(description="For multi-modal events, contains a list of content parts."),
attributes JSON OPTIONS(description="Arbitrary key-value pairs."),
latency_ms JSON OPTIONS(description="Latency measurements."),
status STRING OPTIONS(description="The outcome of the event."),
error_message STRING OPTIONS(description="Detailed error message."),
is_truncated BOOLEAN OPTIONS(description="Flag indicating if content was truncated.")
)
PARTITION BY DATE(timestamp)
CLUSTER BY event_type, agent, user_id;
自动创建的分析视图
当处理程序创建事件表时,它还会创建一个 CREATE OR REPLACE VIEW 每个事件类型在其旁边(由 create_views控制,默认 True)。每个视图将 JSON 列展开为 类型化的顶层列,这样分析查询就不必每次都拼写 JSON_VALUE(...) 每次:
-- With the auto-view
SELECT agent, SUM(usage_total_tokens) AS tokens
FROM `PROJECT.DATASET.v_llm_response`
GROUP BY agent;
-- Equivalent against the raw table
SELECT agent,
SUM(CAST(JSON_VALUE(attributes, '$.usage.total_tokens') AS INT64)) AS tokens
FROM `PROJECT.DATASET.agent_events`
WHERE event_type = 'LLM_RESPONSE'
GROUP BY agent;
默认视图名称(可通过以下方式配置 view_prefix)以及类型化的 列,每个视图在始终包含的列之上添加:
| 视图 | 额外的类型化列 |
|---|---|
v_invocation_starting | _(无 — 仅包含始终包含的列)_ |
v_invocation_completed / v_invocation_error | total_ms |
v_agent_starting | node_name, step |
v_agent_completed | node_name, step, total_ms |
v_agent_error | node_name, total_ms |
v_llm_request | model, request_content, llm_config, tools |
v_llm_response | response, usage_prompt_tokens, usage_completion_tokens, usage_total_tokens, usage_cached_tokens, context_cache_hit_rate, total_ms, ttft_ms, model_version, usage_metadata, cache_metadata |
v_llm_error | total_ms |
v_tool_starting | tool_name, tool_args |
v_tool_completed | tool_name, tool_result, total_ms |
v_tool_error | tool_name, total_ms |
v_retriever_start | query |
v_retriever_end / v_retriever_error | total_ms |
每个视图还公开原始表中的始终包含的列 (timestamp, event_type, agent, session_id, invocation_id, user_id, trace_id, span_id, parent_span_id, status, error_message, is_truncated)加上从 attributes JSON: root_agent_name, custom_tags, session_metadata.
自动模式升级
现有表在处理程序模式获得新列时以追加方式自动升级 。处理程序在启动时读取表并运行 ALTER TABLE ADD COLUMN 用于任何新字段,由 langchain_bq_schema_version 表标签控制,这样差异运行最多一次 每个模式版本。 **从不** 删除、重命名或重新类型化列。 使用以下方式禁用 auto_schema_upgrade=False.
子代理归因
对于多代理 LangGraph 部署, agent BigQuery 列是 从这个备用链自动派生的:
1. metadata["agent"] — 用户提供的显式值(最高优先级) 2. metadata["langgraph_node"] — 活动的 LangGraph 节点,因此每个 子代理的事件都标记有节点名称 3. metadata["checkpoint_ns"] — LangGraph 检查点命名空间 4. handler.graph_name — 顶级回退 INVOCATION_* 事件
多智能体图(例如 supervisor → TheCritic, TheMeteo,...)因此 生成遥测数据,其中每个事件都归属于来源 子代理,无任何用户更改。
事件类型和负载
该 content 列包含一个 **JSON** 特定于 event_type. 该 content_parts 列提供内容的结构化视图,对于图像或卸载的数据特别有用。
LLM 交互
这些事件跟踪发送给 LLM 的原始请求和从 LLM 接收的响应。
| 事件类型 | 内容 (JSON) 结构 | 属性 (JSON) |
|---|---|---|
LLM_REQUEST | **聊天模型:** {"messages": [<dumped messages>]}<br/>**旧版模型:** {"prompt": [<prompts>]} | {"tags": ["..."], "model": "...", "llm_config": {"temperature": 0.2, ...}, "tools": ["get_weather", ...]} |
LLM_RESPONSE | {"response": "<generation text>"} | {"usage": {"prompt_tokens": 100, "completion_tokens": 25, "total_tokens": 125}, "model_version": "gemini-2.5-flash-001", "usage_metadata": {"cached_content_token_count": 30, ...}, "cache_metadata": {...}} |
LLM_ERROR | {"data": null} (实际异常文本位于 error_message 列中) | {} |
子代理(LangGraph 节点)和调用生命周期
这些事件来自 LangGraph 的节点和图上下文生命周期。 agent 自动派生自 metadata['langgraph_node'] 当没有 显式 agent 被设置时,因此事件按子代理标记。
| 事件类型 | 描述 |
|---|---|
AGENT_STARTING / AGENT_COMPLETED / AGENT_ERROR | A LangGraph node begins / ends / errors |
INVOCATION_STARTING / INVOCATION_COMPLETED / INVOCATION_ERROR | Top-level graph invocation begins / ends / errors (emitted by handler.graph_context()) |
工具使用
这些事件跟踪代理执行工具的情况。工具名称在 中也有显示, attributes.tool_name 并且(对于自动视图)作为 类型化 tool_name column.
| 事件类型 | 内容 (JSON) 结构 |
|---|---|
TOOL_STARTING | {"tool": "<name>", "input": "<input string>"} — e.g. {"tool": "get_weather", "input": "city='Paris'"} |
TOOL_COMPLETED | {"tool": "<name>", "result": "<output string>"} — e.g. {"tool": "get_weather", "result": "25°C, Sunny"} |
TOOL_ERROR | {"data": null} (实际异常文本位于 error_message 列中) |
链执行
这些事件为非图的 LangChain Runnable 生命周期触发(图 调用和 LangGraph 节点使用 INVOCATION_* / AGENT_* 事件 上面列出的代替)。
| 事件类型 | 内容 (JSON) 结构 |
|---|---|
CHAIN_START | {"data": ""} |
CHAIN_END | {"data": ""} |
CHAIN_ERROR | {"data": null} (见 error_message 列) |
检索器使用
这些事件跟踪检索器的执行。
| 事件类型 | 内容 (JSON) 结构 |
|---|---|
RETRIEVER_START | {"data": "<query string>"} — e.g. {"data": "What is the capital of France?"} |
RETRIEVER_END | {"data": ""} |
RETRIEVER_ERROR | {"data": null} (实际异常文本位于 error_message 列中) |
代理操作
这些事件来自旧版 LangChain AgentExecutor风格代理 (on_agent_action / on_agent_finish)。 data 字段包含 JSON-serialized string of the action / finish payload.
| 事件类型 | 内容 (JSON) 结构 |
|---|---|
AGENT_ACTION | {"data": "{\"tool\": \"Calculator\", \"input\": \"2 + 2\"}"} |
AGENT_FINISH | {"data": "{\"output\": \"The answer is 4\"}"} |
其他事件
| 事件类型 | 内容 (JSON) 结构 |
|---|---|
TEXT | {"data": "<text>"} — e.g. {"data": "Some logging text..."} |
高级分析查询
一旦您的代理运行并记录事件,您可以对 agent_events table.
### 1. 重建追踪(对话轮次) 使用 trace_id 将所有事件(链、LLM、工具)分组到单个执行流程中。
SELECT
timestamp,
event_type,
span_id,
parent_span_id,
-- Extract summary or specific content based on event type
COALESCE(
JSON_VALUE(content, '$.messages[0].content'),
JSON_VALUE(content, '$.summary'),
JSON_VALUE(content)
) AS summary,
JSON_VALUE(latency_ms, '$.total_ms') AS duration_ms
FROM
`your-gcp-project-id.adk_agent_logs.agent_events`
WHERE
-- Replace with a specific trace_id from your logs
trace_id = '019bb986-a0db-7da1-802d-2725795ab340'
ORDER BY
timestamp ASC;
### 2. 分析 LLM 延迟和令牌使用情况 计算 LLM 调用的平均延迟和总令牌使用量。
SELECT
JSON_VALUE(attributes, '$.model') AS model,
COUNT(*) AS total_calls,
AVG(CAST(JSON_VALUE(latency_ms, '$.total_ms') AS FLOAT64)) AS avg_latency_ms,
SUM(CAST(JSON_VALUE(attributes, '$.usage.total_tokens') AS INT64)) AS total_tokens
FROM
`your-gcp-project-id.adk_agent_logs.agent_events`
WHERE
event_type = 'LLM_RESPONSE'
GROUP BY
1;
3. 使用 BigQuery 远程模型(Gemini)分析多模态内容
如果您将图像卸载到 GCS,可以使用 BigQuery ML 直接分析它们。
SELECT
logs.session_id,
-- Get a signed URL for the image (optional, for viewing)
STRING(OBJ.GET_ACCESS_URL(parts.object_ref, "r").access_urls.read_url) as signed_url,
-- Analyze the image using a remote model (e.g., gemini-2.5-flash)
AI.GENERATE(
('Describe this image briefly. What company logo?', parts.object_ref)
) AS generated_result
FROM
`your-gcp-project-id.adk_agent_logs.agent_events` logs,
UNNEST(logs.content_parts) AS parts
WHERE
parts.mime_type LIKE 'image/%'
ORDER BY logs.timestamp DESC
LIMIT 1;
### 4. 分析跨度层次结构和持续时间 使用 span ID 可视化您代理的操作执行流程和性能(LLM 调用、工具使用)。
SELECT
span_id,
parent_span_id,
event_type,
timestamp,
-- Extract duration from latency_ms for completed operations
CAST(JSON_VALUE(latency_ms, '$.total_ms') AS INT64) as duration_ms,
-- Identify the specific tool or operation
COALESCE(
JSON_VALUE(content, '$.tool'),
'LLM_CALL'
) as operation
FROM `your-gcp-project-id.adk_agent_logs.agent_events`
WHERE trace_id = 'your-trace-id'
AND event_type IN ('LLM_RESPONSE', 'TOOL_COMPLETED')
ORDER BY timestamp ASC;
5. 查询卸载的内容(获取签名 URL)
SELECT
timestamp,
event_type,
part.mime_type,
part.storage_mode,
part.object_ref.uri AS gcs_uri,
-- Generate a signed URL to read the content directly (requires connection_id configuration)
STRING(OBJ.GET_ACCESS_URL(part.object_ref, 'r').access_urls.read_url) AS signed_url
FROM `your-gcp-project-id.adk_agent_logs.agent_events`,
UNNEST(content_parts) AS part
WHERE part.storage_mode = 'GCS_REFERENCE'
ORDER BY timestamp DESC
LIMIT 10;
6. 高级 SQL 场景
这些高级模式展示了如何使用 BigQuery ML 对数据进行会话化分析、工具使用分析以及执行根本原因分析。
-- 1. Sessionize Conversation History (Create View)
-- Consolidates all events into a single row per session with a formatted history.
CREATE OR REPLACE VIEW `your-project.your-dataset.agent_sessions` AS
SELECT
session_id,
user_id,
MIN(timestamp) AS session_start,
MAX(timestamp) AS session_end,
ARRAY_AGG(
STRUCT(timestamp, event_type, TO_JSON_STRING(content) as content, error_message)
ORDER BY timestamp ASC
) AS events,
STRING_AGG(
CASE
-- LLM_REQUEST carries the user's prompt under content.messages
WHEN event_type = 'LLM_REQUEST' THEN CONCAT('User: ', JSON_VALUE(content, '$.summary'))
WHEN event_type = 'LLM_RESPONSE' THEN CONCAT('Agent: ', JSON_VALUE(content, '$.summary'))
WHEN event_type = 'TOOL_STARTING' THEN CONCAT('SYS: Calling ', JSON_VALUE(content, '$.tool'))
WHEN event_type = 'TOOL_COMPLETED' THEN CONCAT('SYS: Result from ', JSON_VALUE(content, '$.tool'))
WHEN event_type = 'TOOL_ERROR' THEN CONCAT('SYS: ERROR in ', JSON_VALUE(content, '$.tool'))
ELSE NULL
END,
'\n' ORDER BY timestamp ASC
) AS full_conversation
FROM
`your-project.your-dataset.agent_events`
GROUP BY
session_id, user_id;
-- 2. Tool Usage Analysis
-- Extract tool names from content (the auto-view `v_tool_completed`
-- exposes `tool_name` directly if you'd rather skip the JSON_VALUE).
SELECT
JSON_VALUE(content, '$.tool') AS tool_name,
event_type,
COUNT(*) as count
FROM `your-project.your-dataset.agent_events`
WHERE event_type IN ('TOOL_STARTING', 'TOOL_COMPLETED', 'TOOL_ERROR')
GROUP BY 1, 2
ORDER BY tool_name, event_type;
-- 3. Granular Cost & Token Estimation
-- Estimate tokens based on content character length (approx 4 chars/token)
SELECT
session_id,
COUNT(*) as interaction_count,
SUM(LENGTH(TO_JSON_STRING(content))) / 4 AS estimated_tokens,
-- Example cost: $0.0001 per 1k tokens
ROUND((SUM(LENGTH(TO_JSON_STRING(content))) / 4) / 1000 * 0.0001, 6) AS estimated_cost_usd
FROM `your-project.your-dataset.agent_events`
GROUP BY session_id
ORDER BY estimated_cost_usd DESC
LIMIT 5;
-- 4. AI-Powered Root Cause Analysis (Requires BigQuery ML)
-- Use Gemini to analyze failed sessions
SELECT
session_id,
AI.GENERATE(
('Analyze this conversation and explain the failure root cause. Log: ', full_conversation),
connection_id => 'your-project.us.bqml_connection',
endpoint => 'gemini-2.5-flash'
).result AS root_cause_explanation
FROM `your-project.your-dataset.agent_sessions`
WHERE error_message IS NOT NULL
LIMIT 5;
BigQuery 中的会话分析
Looker Studio 仪表板
您可以使用我们预构建的 Looker Studio 仪表板模板.
要将此仪表板连接到您自己的 BigQuery 表,请使用以下链接格式,将占位符替换为您的特定项目、数据集和表 ID:
https://lookerstudio.google.com/reporting/create?c.reportId=f1c5b513-3095-44f8-90a2-54953d41b125&ds.ds3.connector=bigQuery&ds.ds3.type=TABLE&ds.ds3.projectId=<your-project-id>&ds.ds3.datasetId=<your-dataset-id>&ds.ds3.tableId=<your-table-id>
LangGraph 集成
该 BigQueryCallbackHandler 为 LangGraph 代理提供增强支持,包括自动节点检测、图级别跟踪和延迟测量。
LangGraph 事件类型
除了标准 LangChain 事件外,回调处理器还会自动检测并记录 LangGraph 特定事件:
| 事件类型 | 描述 |
|---|---|
AGENT_STARTING | 当 LangGraph 节点开始执行时发出 |
AGENT_COMPLETED | 当 LangGraph 节点成功完成时发出 |
AGENT_ERROR | 当 LangGraph 节点失败时发出 |
INVOCATION_STARTING | 当图执行开始时发出(通过上下文管理器) |
INVOCATION_COMPLETED | 当图执行完成时发出 |
INVOCATION_ERROR | 当图执行失败时发出 |
图上下文管理器
使用 graph_context() 方法明确标记图执行边界。这启用了 INVOCATION_STARTING 和 INVOCATION_COMPLETED 事件并提供准确的延迟测量:
from langchain.agents import create_agent
from langchain.messages import HumanMessage
from langchain_google_community.callbacks.bigquery_callback import (
BigQueryCallbackHandler,
BigQueryLoggerConfig,
)
# Initialize handler with graph name
handler = BigQueryCallbackHandler(
project_id="your-project-id",
dataset_id="agent_analytics",
table_id="agent_events",
graph_name="my_agent",
)
# Create your agent
agent = create_agent(llm, tools)
# Use the graph context manager for proper INVOCATION_STARTING/INVOCATION_COMPLETED events
run_metadata = {
"session_id": "session-123",
"user_id": "user-456",
"agent": "my_agent",
}
with handler.graph_context("my_agent", metadata=run_metadata):
result = agent.invoke(
{"messages": [HumanMessage(content="What is the weather in Tokyo?")]},
config={
"callbacks": [handler],
"metadata": run_metadata,
},
)
延迟跟踪
回调处理器自动跟踪所有操作的延迟,并将测量结果存储在 latency_ms JSON 列中:
-- Query latency by event type
SELECT
event_type,
agent,
COUNT(*) as count,
ROUND(AVG(CAST(JSON_EXTRACT_SCALAR(latency_ms, '$.total_ms') AS FLOAT64)), 2) as avg_latency_ms,
ROUND(APPROX_QUANTILES(CAST(JSON_EXTRACT_SCALAR(latency_ms, '$.total_ms') AS FLOAT64), 100)[OFFSET(95)], 2) as p95_latency_ms
FROM `your-project.your-dataset.agent_events`
WHERE DATE(timestamp) = CURRENT_DATE()
AND event_type IN ('LLM_RESPONSE', 'TOOL_COMPLETED', 'INVOCATION_COMPLETED')
GROUP BY event_type, agent
ORDER BY avg_latency_ms DESC;
事件过滤
使用 event_allowlist 和 event_denylist 控制记录哪些事件:
from langchain_google_community.callbacks.bigquery_callback import (
BigQueryCallbackHandler,
BigQueryLoggerConfig,
)
# Production config: Only log important events
config = BigQueryLoggerConfig(
event_allowlist=[
"LLM_RESPONSE",
"LLM_ERROR",
"TOOL_COMPLETED",
"TOOL_ERROR",
"INVOCATION_COMPLETED",
"INVOCATION_ERROR",
],
)
handler = BigQueryCallbackHandler(
project_id="your-project-id",
dataset_id="agent_analytics",
config=config,
)
或排除嘈杂事件:
# Exclude chain events but log everything else
config = BigQueryLoggerConfig(
event_denylist=["CHAIN_START", "CHAIN_END"],
)
示例和资源
示例代码
以下示例演示了 BigQuery 回调处理器的各种功能:
| 示例 | 描述 |
|---|---|
| 基本示例 | 带 LLM 调用的基本回调用法 |
| LangGraph 代理 | 具有 6 个逼真工具的完整 ReAct 代理 |
| 异步示例 | 带并发查询的异步处理器 |
| 事件过滤 | Allowlist/denylist configurations |
| 样本数据生成器 | 跨多种代理类型生成样本数据 |
分析笔记本
此 LangGraph 代理分析笔记本 提供全面的 BigQuery 分析查询,包括:
- - 实时事件监控
- - 工具使用分析
- - 延迟分析与趋势
- - 错误调试
- - 用户参与度指标
- - 时间序列可视化
实时监控仪表板
A 基于 FastAPI 的监控仪表板 可用于实时代理监控:
Features: - 通过服务器发送事件(SSE)的实时事件流 - 事件分布和延迟趋势的交互式图表 - 具有详细时间线视图的会话追踪 - 20 多个用于分析查询的 REST API 端点 - 每 5 秒自动刷新
# Run the dashboard
cd libs/community/examples/bigquery_callback/webapp
pip install -r requirements.txt
uvicorn main:app --port 8001
# Open http://localhost:8001
## 反馈 我们欢迎您对 BigQuery 代理分析的反馈。如有问题、建议或遇到任何问题,请通过 bqaa-feedback@google.com 联系团队。
其他资源
- - BigQuery 存储写入 API
- - 对象表简介
- - 示例代码和笔记本