本文档介绍了如何使用 Google Cloud 控制台或 API 为项目配置 Gemini Code Assist Standard 和 Enterprise 日志记录。
限制
Google Cloud 中的 Gemini Standard 和 Enterprise 日志数据记录仅限于用户在 IDE 中与 Gemini Code Assist 的互动。
默认情况下,Gemini for Google Cloud 日志是按项目收集的。如需了解如何配置集中式 项目以从多个项目收集日志,请参阅 设置多项目日志记录。
GitHub 中的 Gemini Code Assist 不支持使用 Cloud Logging 进行日志记录。
准备工作
验证您的 Google Cloud 项目是否已关联结算账号。
验证 IAM 权限
如需配置 Gemini Code Assist 日志记录,您需要特定的 IAM 权限。如需遵循最小权限原则, 请授予仅包含必要权限的自定义角色。
请让管理员创建包含以下权限的自定义角色:
serviceusage.services.enable:为您的项目启用 API。cloudaicompanion.loggingSettings.create:创建日志记录设置。cloudaicompanion.loggingSettings.get:查看日志记录设置。cloudaicompanion.loggingSettings.list:列出日志记录设置。cloudaicompanion.loggingSettings.update:更新日志记录设置。cloudaicompanion.loggingSettingBindings.create:将日志记录设置绑定到项目。cloudaicompanion.loggingSettingBindings.get:查看日志记录设置绑定。cloudaicompanion.loggingSettingBindings.list:列出日志记录设置绑定。
或者,您也可以授予预定义角色
Gemini for Google Cloud Settings Admin (roles/cloudaicompanion.settingsAdmin) 和
Service Usage Admin (roles/serviceusage.serviceUsageAdmin)。
不过,这些角色包含配置所有 Gemini for Google Cloud
管理员设置和管理服务使用情况的权限,这可能超出配置日志记录设置所需的权限。
配置 Gemini Code Assist 日志记录
以下部分介绍了在 Cloud Logging 中启用 Gemini Code Assist Standard 和 Enterprise 活动的收集和存储所需的步骤,包括:
Gemini Code Assist Standard 和 Enterprise 提示和回答日志,例如用户输入、上下文信息和回答。
Gemini Code Assist Standard 和 Enterprise 元数据日志,例如用户接受的遥测元数据和代码行。
如需详细了解这两种类型的日志,请参阅 查看 Gemini 日志。
在项目中为 Gemini Code Assist 启用日志记录
选择以下某个选项:
控制台
验证您是否已在项目中启用 Cloud Logging API。
在 Google Cloud 控制台中,前往 Gemini 管理中心 页面。
系统会加载 Gemini for Google Cloud 页面。
点击左侧导航菜单中的设置。
系统会加载设置页面。
(可选)点击 Code Assist 元数据的日志记录,以记录项目中的 Gemini Code Assist Standard 和 Enterprise 用户生成的元数据。
(可选)点击 Code Assist 提示和回答的日志记录,以记录项目中的 Gemini Code Assist Standard 和 Enterprise 用户生成的提示和回答。
点击保存更改。
API
如需为 Gemini Code Assist Standard 和 Enterprise 启用日志记录,请使用 loggingSettings 资源定义所需的日志记录设置,并使用 loggingSettings.settingBindings 资源将设置绑定到项目:
验证您是否已在项目中启用 Cloud Logging API 。
设置项及其专用值:
获取令牌:
TOKEN=$(gcloud auth print-access-token)
启用 Gemini Code Assist Standard 和 Enterprise 日志。用户日志和元数据日志分别通过
log_prompts_and_responses和log_metadata字段进行启用。如果您不想启用某个字段,请将其从请求中排除。运行以下命令以创建设置:
curl -X POST \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "log_prompts_and_responses": true, "log_metadata": true, } ' \ "https://cloudaicompanion.googleapis.com/v1/projects/CONTAINER_PROJECT_NAME/locations/global/loggingSettings?logging_setting_id=LOGS_SETTING_ID"替换以下内容:
CONTAINER_PROJECT_NAME:输入在其中存储绑定资源的项目的项目 ID。这是绑定的父级项目。LOGS_SETTING_ID:输入唯一的设置名称,例如gcalm。
如果命令成功,则会返回一个响应正文,其中显示
log_prompts_and_responses和log_metadata设置为true:{ "name": "projects/CONTAINER_PROJECT_NAME/locations/global/loggingSettings/LOGS_SETTING_ID", "createTime": "2025-01-23T15:22:49.717166932Z", "updateTime": "2025-01-23T15:22:49.717166932Z", "log_prompts_and_responses": true, "log_metadata": true }运行以下命令以创建 Gemini Code Assist Standard 和 Enterprise 日志设置绑定:
curl -X POST \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "target": "projects/TARGET_PROJECT_NAME" }' \ "https://cloudaicompanion.googleapis.com/v1/projects/CONTAINER_PROJECT_NAME/locations/global/loggingSettings/LOGS_SETTING_ID/settingBindings?setting_binding_id=LOGS_BINDING_ID"
替换以下内容:
TARGET_PROJECT_NAME:输入绑定的目标项目。这通常与容器项目相同。不过,您可以将某项设置绑定到多个项目,以便不必复制设置资源。LOGS_BINDING_ID:使用与创建设置时相同的 LOGS_SETTING_ID,但在其后附加b1。例如,使用gcalmb1。
如果命令成功,则会采用以下格式返回操作元数据:
{ "name": "projects/<var>CONTAINER_PROJECT_NAME</var>/locations/global/operations/operation-1737646069712-62c6140bb04bb-49261230-43701daf", "metadata": { "@type": "type.googleapis.com/google.cloud.cloudaicompanion.v1.OperationMetadata", "createTime": "2025-01-23T15:27:50.076075570Z", "target": "projects/<var>TARGET_PROJECT_NAME</var>/locations/global/loggingSettings/<var>LOGS_SETTING_ID</var>/settingBindings/<var>LOGS_BINDING_ID</var>", "verb": "create", "requestedCancellation": false, "apiVersion": "v1" }, "done": false }
在项目中为 Gemini Code Assist 停用日志记录
选择以下某个选项:
控制台
在 Google Cloud 控制台中,前往 Gemini 管理中心 页面。
系统会加载 Gemini for Google Cloud 页面。
点击左侧导航菜单中的设置。
系统会加载设置页面。
点击 Code Assist 元数据的日志记录,以停止记录此项目中对 Gemini Code Assist Standard 和 Enterprise 的使用所生成的元数据。
点击保存更改。
API
如需为 Gemini Code Assist Standard 和 Enterprise 停用日志记录,请使用 loggingSetting 方法。
设置项及其专用值:
获取令牌:
TOKEN=$(gcloud auth print-access-token)
运行以下命令以停用 Gemini Code Assist Standard 和 Enterprise 日志设置:
curl -X POST \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "log_prompts_and_responses": false, "log_metadata": false, } ' \ "https://cloudaicompanion.googleapis.com/v1/projects/CONTAINER_PROJECT_NAME/locations/global/loggingSettings?logging_metadata_id=LOGS_SETTING_ID"替换以下内容:
CONTAINER_PROJECT_NAME:输入父项目 ID。LOGS_SETTING_ID:输入现有设置名称,例如gcalm。如果命令成功,则会返回一个响应正文,其中显示
log_prompts_and_responses和log_metadata设置为false:{ "name": "projects/CONTAINER_PROJECT_NAME/locations/global/loggingSettings/LOGS_SETTING_ID", "createTime": "2025-01-23T15:22:49.717166932Z", "updateTime": "2025-01-23T15:22:49.717166932Z", "log_prompts_and_responses": false, "log_metadata": false }
设置多项目日志记录
您可以使用 Gemini Code Assist 中的日志来创建指标和信息中心,以监控每个项目的使用情况。如果您的组织有多个项目,您可以配置一个集中式日志记录项目,以从多个项目收集日志并跨这些项目生成信息中心。
创建集中式日志记录项目
此项目将作为其他项目的日志中心。
在 Google Cloud 控制台中,前往项目创建 页面。
在新建项目 窗口中,为以下字段输入值:
- 项目名称:集中式日志记录项目的名称。
- 结算账号:选择结算账号。
- 组织:选择您的组织。集中式项目只能从同一组织中的项目收集日志。
- 位置:选择一个位置。
点击创建 。
配置日志接收器
如需将日志定向到集中式项目,请在要从中收集日志的每个项目中配置日志接收器。
如需为每个项目配置日志接收器,请执行以下操作:
- 在 Google Cloud 控制台中,切换到要从中收集日志的项目。
前往日志路由器 页面:
点击创建接收器 。
对于接收器详情,输入接收器的名称和说明,然后 点击下一步。
对于接收器目标位置,请执行以下操作:
- 在选择接收器服务 菜单中,选择 Logging 存储分区 。
- 在日志存储分区 菜单中,选择使用其他项目中的日志存储分区 。
在接收器目标位置 字段中,输入以下内容:
logging.googleapis.com/projects/CENTRALIZED_PROJECT_ID/locations/global/buckets/_Default将
CENTRALIZED_PROJECT_ID替换为您创建的集中式日志记录项目的项目 ID。点击下一步 。
对于选择要包含在接收器中的日志,通过输入 以下内容在包含过滤器字段中构建包含过滤器:
resource.type="cloudaicompanion.googleapis.com/Instance"点击下一步 。
对于选择要从接收器中过滤掉的日志 ,将排除过滤器留空,然后点击创建接收器 。
创建接收器后,在日志路由器 页面中,找到您创建的接收器。
在写入者身份 列中,复制完整的服务账号电子邮件地址。
配置访问权限
如需授予接收器将日志写入集中式项目的权限,请执行以下操作:
- 在 Google Cloud 控制台中,切换到您创建的集中式项目。
前往 IAM 页面:
点击授予访问权限 。
在新的主账号 字段中,粘贴您在上一步中复制的服务账号电子邮件地址。
点击添加其他角色 。
搜索并选择 Logs Bucket Writer 角色 (
roles/logging.bucketWriter)。点击保存 。
在集中式项目中创建信息中心
将集中式项目配置为接收日志后,您可以创建信息中心以查看多个项目的指标:
在 Google Cloud 控制台中,前往 Monitoring > 信息中心:
点击创建信息中心 。
在工具栏中,依次点击设置和JSON,然后选择JSON 编辑器。
在 JSON 编辑器中,粘贴以下代码:
{ "displayName": "Multi-Project Gemini Code Assist Overview from Metadata Logs", "dashboardFilters": [], "labels": {}, "mosaicLayout": { "columns": 48, "tiles": [ { "height": 16, "width": 24, "widget": { "title": "Active Users by Day", "id": "", "xyChart": { "chartOptions": { "displayHorizontal": false, "mode": "COLOR", "showLegend": false }, "dataSets": [ { "breakdowns": [], "dimensions": [ { "column": "event_date", "columnType": "DATE", "maxBinCount": 0, "sortColumn": "event_date", "sortOrder": "SORT_ORDER_ASCENDING", "timeBinSize": "0s", "xMax": 0, "xMin": 0 } ], "legendTemplate": "", "measures": [ { "aggregationFunction": { "parameters": [], "type": "average" }, "column": "DAU" } ], "plotType": "LINE", "targetAxis": "Y1", "timeSeriesQuery": { "opsAnalyticsQuery": { "queryExecutionRules": { "useReservedSlots": false }, "queryHandle": "", "savedQueryId": "", "sql": "SELECT\n COUNT (DISTINCT JSON_VALUE(labels, '$.user_id')) as DAU, CAST(timestamp AS DATE) AS event_date\nFROM\n `CENTRALIZED_PROJECT_ID.global._Default._Default`\nWHERE\n JSON_VALUE(labels, '$.user_id') is not NULL\n AND (\n JSON_VALUE(json_payload, '$.chatExposure.originalRequestId') is not NULL\n OR JSON_VALUE(json_payload, '$.codeAcceptance.originalRequestId') is not NULL\n OR JSON_VALUE(json_payload, '$.codeExposure.originalRequestId') is not NULL\n )\n AND resource.type = \"cloudaicompanion.googleapis.com/Instance\"\n AND (JSON_VALUE(resource.labels, '$.resource_container') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2') or JSON_VALUE(resource.labels, '$.project_id') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2'))\nGROUP BY\nevent_date\nORDER BY\nevent_date\n" }, "outputFullDuration": false, "unitOverride": "" } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } } }, { "xPos": 24, "height": 16, "width": 24, "widget": { "title": "Acceptance Rate by Day", "id": "", "xyChart": { "chartOptions": { "displayHorizontal": false, "mode": "COLOR", "showLegend": false }, "dataSets": [ { "breakdowns": [], "dimensions": [ { "column": "exposures_date", "columnType": "DATE", "maxBinCount": 0, "sortColumn": "exposures_date", "sortOrder": "SORT_ORDER_ASCENDING", "timeBinSize": "0s", "xMax": 0, "xMin": 0 } ], "legendTemplate": "", "measures": [ { "aggregationFunction": { "parameters": [], "type": "average" }, "column": "acceptance_rate" } ], "plotType": "LINE", "targetAxis": "Y1", "timeSeriesQuery": { "opsAnalyticsQuery": { "queryExecutionRules": { "useReservedSlots": false }, "queryHandle": "", "savedQueryId": "", "sql": "SELECT\nexposures_date,\nacceptances_count / exposures_count as acceptance_rate\nFROM\n(\nSELECT\nCOUNT (DISTINCT JSON_VALUE(json_payload, '$.codeAcceptance.originalRequestId')) as acceptances_count, CAST(timestamp AS DATE) AS acceptances_date\nFROM\n`CENTRALIZED_PROJECT_ID.global._Default._Default`\nWHERE\nJSON_VALUE(json_payload, '$.codeAcceptance.originalRequestId') is not NULL\nAND resource.type = \"cloudaicompanion.googleapis.com/Instance\"\nAND (JSON_VALUE(resource.labels, '$.resource_container') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2') or JSON_VALUE(resource.labels, '$.project_id') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2'))\nGROUP BY\nacceptances_date\n) as acceptances\nJOIN\n(\nSELECT\nCOUNT (DISTINCT JSON_VALUE(json_payload, '$.codeExposure.originalRequestId')) as exposures_count, CAST(timestamp AS DATE) AS exposures_date\nFROM\n`CENTRALIZED_PROJECT_ID.global._Default._Default`\nWHERE\nJSON_VALUE(json_payload, '$.codeExposure.originalRequestId') is not NULL\nAND resource.type = \"cloudaicompanion.googleapis.com/Instance\"\nAND (JSON_VALUE(resource.labels, '$.resource_container') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2') or JSON_VALUE(resource.labels, '$.project_id') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2'))\nGROUP BY\nexposures_date\n) as exposures\nON\nexposures.exposures_date = acceptances.acceptances_date\nORDER BY\nexposures_date ASC" }, "outputFullDuration": false, "unitOverride": "" } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } } }, { "yPos": 16, "height": 16, "width": 24, "widget": { "title": "Code Suggestions by Day", "id": "", "xyChart": { "chartOptions": { "displayHorizontal": false, "mode": "COLOR", "showLegend": false }, "dataSets": [ { "breakdowns": [], "dimensions": [ { "column": "exposures_date", "columnType": "DATE", "maxBinCount": 0, "sortColumn": "exposures_date", "sortOrder": "SORT_ORDER_ASCENDING", "timeBinSize": "0s", "xMax": 0, "xMin": 0 } ], "legendTemplate": "", "measures": [ { "aggregationFunction": { "parameters": [], "type": "average" }, "column": "exposures_count" } ], "plotType": "STACKED_BAR", "targetAxis": "Y1", "timeSeriesQuery": { "opsAnalyticsQuery": { "queryExecutionRules": { "useReservedSlots": false }, "queryHandle": "", "savedQueryId": "", "sql": "SELECT\n COUNT (DISTINCT JSON_VALUE(json_payload, '$.codeExposure.originalRequestId')) as exposures_count, CAST(timestamp AS DATE) AS exposures_date\nFROM\n `CENTRALIZED_PROJECT_ID.global._Default._Default`\nWHERE\n JSON_VALUE(json_payload, '$.codeExposure.originalRequestId') is not NULL\n AND resource.type = \"cloudaicompanion.googleapis.com/Instance\"\n AND (JSON_VALUE(resource.labels, '$.resource_container') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2') or JSON_VALUE(resource.labels, '$.project_id') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2'))\nGROUP BY\n exposures_date\nORDER BY\n exposures_date" }, "outputFullDuration": false, "unitOverride": "" } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } } }, { "yPos": 16, "xPos": 24, "height": 16, "width": 24, "widget": { "title": "Code Acceptances by Day", "id": "", "xyChart": { "chartOptions": { "displayHorizontal": false, "mode": "COLOR", "showLegend": false }, "dataSets": [ { "breakdowns": [], "dimensions": [ { "column": "acceptances_date", "columnType": "DATE", "maxBinCount": 0, "sortColumn": "acceptances_date", "sortOrder": "SORT_ORDER_ASCENDING", "timeBinSize": "0s", "xMax": 0, "xMin": 0 } ], "legendTemplate": "", "measures": [ { "aggregationFunction": { "parameters": [], "type": "average" }, "column": "acceptances_count" } ], "plotType": "STACKED_BAR", "targetAxis": "Y1", "timeSeriesQuery": { "opsAnalyticsQuery": { "queryExecutionRules": { "useReservedSlots": false }, "queryHandle": "", "savedQueryId": "", "sql": "SELECT\n COUNT (DISTINCT JSON_VALUE(json_payload, '$.codeAcceptance.originalRequestId')) as acceptances_count, CAST(timestamp AS DATE) AS acceptances_date\nFROM\n `CENTRALIZED_PROJECT_ID.global._Default._Default`\nWHERE\n JSON_VALUE(json_payload, '$.codeAcceptance.originalRequestId') is not NULL\n AND resource.type = \"cloudaicompanion.googleapis.com/Instance\"\n AND (JSON_VALUE(resource.labels, '$.resource_container') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2') or JSON_VALUE(resource.labels, '$.project_id') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2'))\nGROUP BY\n acceptances_date\nORDER BY\n acceptances_date\n" }, "outputFullDuration": false, "unitOverride": "" } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } } }, { "yPos": 32, "height": 16, "width": 24, "widget": { "title": "Lines of Code Accepted by Day", "id": "", "xyChart": { "chartOptions": { "displayHorizontal": false, "mode": "COLOR", "showLegend": false }, "dataSets": [ { "breakdowns": [], "dimensions": [ { "column": "line_count_day", "columnType": "DATE", "maxBinCount": 0, "sortColumn": "line_count_day", "sortOrder": "SORT_ORDER_ASCENDING", "timeBinSize": "0s", "xMax": 0, "xMin": 0 } ], "legendTemplate": "", "measures": [ { "aggregationFunction": { "parameters": [], "type": "average" }, "column": "lines_count" } ], "plotType": "STACKED_BAR", "targetAxis": "Y1", "timeSeriesQuery": { "opsAnalyticsQuery": { "queryExecutionRules": { "useReservedSlots": false }, "queryHandle": "", "savedQueryId": "", "sql": "SELECT\n SUM(lines) as lines_count,\n CAST(max_timestamp AS DATE) AS line_count_day\nFROM\n(\n SELECT\n JSON_VALUE(json_payload, '$.codeAcceptance.originalRequestId') as request_id,\n MAX(CAST(JSON_VALUE(json_payload, '$.codeAcceptance.linesCount') AS INT)) as lines,\n MAX(timestamp) as max_timestamp\n FROM\n `CENTRALIZED_PROJECT_ID.global._Default._Default`\n WHERE\n JSON_VALUE(json_payload, '$.codeAcceptance.originalRequestId') is not NULL\n AND resource.type = \"cloudaicompanion.googleapis.com/Instance\"\n AND (JSON_VALUE(resource.labels, '$.resource_container') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2') or JSON_VALUE(resource.labels, '$.project_id') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2'))\n GROUP BY\n request_id\n )\nGROUP BY\n line_count_day\nORDER BY\n line_count_day" }, "outputFullDuration": false, "unitOverride": "" } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } } }, { "yPos": 32, "xPos": 24, "height": 16, "width": 24, "widget": { "title": "Chat Exposures by Day", "id": "", "xyChart": { "chartOptions": { "displayHorizontal": false, "mode": "COLOR", "showLegend": false }, "dataSets": [ { "breakdowns": [], "dimensions": [ { "column": "chat_exposures_date", "columnType": "DATE", "maxBinCount": 0, "sortColumn": "chat_exposures_date", "sortOrder": "SORT_ORDER_ASCENDING", "timeBinSize": "0s", "xMax": 0, "xMin": 0 } ], "legendTemplate": "", "measures": [ { "aggregationFunction": { "parameters": [], "type": "average" }, "column": "chat_exposures_count" } ], "plotType": "STACKED_BAR", "targetAxis": "Y1", "timeSeriesQuery": { "opsAnalyticsQuery": { "queryExecutionRules": { "useReservedSlots": false }, "queryHandle": "", "savedQueryId": "", "sql": "SELECT\n COUNT (DISTINCT JSON_VALUE(json_payload, '$.chatExposure.originalRequestId')) as chat_exposures_count, CAST(timestamp AS DATE) AS chat_exposures_date\nFROM\n `CENTRALIZED_PROJECT_ID.global._Default._Default`\nWHERE\n JSON_VALUE(json_payload, '$.chatExposure.originalRequestId') is not NULL\n AND resource.type = \"cloudaicompanion.googleapis.com/Instance\"\n AND (JSON_VALUE(resource.labels, '$.resource_container') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2') or JSON_VALUE(resource.labels, '$.project_id') in ('SOURCE_PROJECT_ID_1', 'SOURCE_PROJECT_ID_2'))\nGROUP BY\n chat_exposures_date\nORDER BY\n chat_exposures_date" }, "outputFullDuration": false, "unitOverride": "" } } ], "thresholds": [], "yAxis": { "label": "", "scale": "LINEAR" } } } } ] } }替换以下内容:
CENTRALIZED_PROJECT_ID:您创建的集中式日志记录项目的项目 ID。SOURCE_PROJECT_ID_1和SOURCE_PROJECT_ID_2:您要从中收集日志的项目的项目 ID。 如果要从两个以上的项目收集日志,则可以将更多项目 ID 添加到查询的in子句中。
停用多项目日志记录
如果您为多个项目配置了 Gemini Code Assist 日志记录,则可以通过删除将日志路由到集中式项目的日志接收器来停用它。如需停止将日志从单个项目发送到集中式项目,请删除在该项目中创建的日志接收器:
- 在 Google Cloud 控制台中,切换到要停止从中收集日志的项目。
前往日志路由器 页面:
找到将日志路由到集中式项目的接收器。
在该接收器对应的行中,点击更多操作,然后选择 删除接收器。
在随即显示的对话框中,点击删除 。
对要停止向集中式项目发送日志的每个项目重复执行上述步骤。