查看 Gemini Code Assist 日志

通过在 Cloud Logging 中收集 Gemini Code Assist 活动,您可以审核开发者提示、模型回答和元数据日志(例如遥测数据和接受的代码行)。您可以查询这些日志条目,以评估整个组织中的助理互动情况。如需跟踪汇总趋势(而非原始日志),请参阅监控 Gemini Code Assist 使用情况。

Gemini Code Assist 不会收集或向 Cloud Logging 发送用户与 Gemini Code Assist 的任何其他互动,包括书面反馈。收集的数据会发送到 Cloud Logging 进行存储。您可以通过搜索资源类型为 cloudaicompanion.googleapis.com/Instance 的日志条目来查看这些数据。

此功能不会在 Gemini in Vertex AI 中记录提示或回答。如需为 Gemini in Vertex AI 启用日志,请参阅启用数据访问审核日志。

Identity and Access Management (IAM) 角色控制主账号访问日志的权限。您可以向主账号授予预定义角色,也可以创建自定义角色。如需详细了解所需权限,请参阅访问权限控制。

默认情况下,Cloud Logging 会对以静态方式存储的客户内容进行加密。Logging 存储在日志存储桶中的数据使用密钥加密密钥进行加密,此过程称为信封加密。访问日志记录数据需要访问这些密钥加密密钥,Google 会为您管理这些密钥,您无需执行任何操作。

您的组织可能具有我们的默认静态加密不提供的监管、合规性相关或高级加密要求。为满足贵组织的要求,您可以自行管理用于保护您数据的加密密钥,而不是由 Google 代为管理。

如需详细了解客户管理的加密密钥 (CMEK) 的使用情况(包括优点和限制),请参阅客户管理的加密密钥。

限制

  • Gemini Code Assist 日志数据记录仅限于用户在 IDE 中与 Gemini Code Assist 的互动。

  • 默认情况下,Gemini Code Assist 日志是按项目收集的。如需了解如何配置集中式项目以从多个项目收集日志,请参阅设置多项目日志记录。

  • Gemini Code Assist 日志会记录每个对话和代理请求 (CompleteTask) 的合并 token 数量 (totalTokenCount),您可以使用 labels.user_id 标签将其归因于某个用户。此计数会显示在 RequestLog.metadata.totalTokenCount、ResponseLog.metadata.totalTokenCount 和 MetadataLog.apiRequest.totalTokenCount 字段中。代码补全和代码生成请求(CompleteCode 和 GenerateCode)的日志以及记录遥测事件(例如 codeExposure、codeAcceptance、chatExposure 和 chatAcceptance 事件)的元数据日志不包含 token 计数。日志和 Cloud Monitoring 指标不会单独记录提示和回答的 token 数量。如需查看项目的汇总 token 用量,请参阅 token 和配额指标。

准备工作

查看 Gemini Code Assist 用户日志和元数据日志

如需查看 Gemini Code Assist 用户日志和元数据日志,请执行以下操作之一:

控制台

  1. 在 Google Cloud 控制台中,前往 Logs Explorer 页面:

    前往 Logs Explorer

    如果您使用搜索栏查找此页面,请选择子标题为 Logging 的结果。

  2. 在工具栏中,选择一个 Google Cloud 控制台项目。
  3. 在工具栏中,展开所有资源菜单,然后选择资源 Cloud AI Companion 实例。

gcloud

运行以下命令:

gcloud logging read "resource.type=cloudaicompanion.googleapis.com/Instance" --project PROJECT_ID  --limit 3

将 PROJECT_ID 替换为您要查看其 Gemini Code Assist 日志的项目的 ID。

API

  1. 创建一个包含以下信息的 JSON 文件:

      {
        "resourceNames": [
          "projects/PROJECT_ID"
        ],
        "pageSize": 5,
        "filter": "resource.type: cloudaicompanion.googleapis.com/Instance"
      }
    

    将 PROJECT_ID 替换为您要查看其 Gemini Code Assist 日志的项目的 ID。

  2. 获取身份验证令牌:

    TOKEN=$(gcloud auth print-access-token)
    
  3. 使用 cURL 调用 entries.list 方法:

    curl -X POST --data-binary @JSON_FILE_NAME \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      "https://logging.googleapis.com/v2/entries:list"

    将 JSON_FILE_NAME 替换为您在上一步中创建的 JSON 文件的路径。

    如需详细了解身份验证,请参阅使用 REST 时进行身份验证。

    响应会返回一组日志条目。

Gemini Code Assist 日志

LogEntry 是 Cloud Logging 中的数据基本单位。以下部分列出了 LogEntry 中针对 Gemini Code Assist 平台事件(例如用户请求和 Gemini Code Assist 回答)的字段。

用户请求数量

下表列出了用户请求日志条目中找到的字段:

字段 值和备注
LogEntry.resource.type Gemini Code Assist 资源类型:cloudaicompanion.googleapis.com/Instance。
LogEntry.resource.labels.resource_container 使用 Gemini Code Assist 的资源容器的唯一 ID。
LogEntry.resource.labels.location 使用 Gemini Code Assist 的位置。
LogEntry.resource.labels.instance_id 使用了 Gemini Code Assist 的资源的唯一 ID。
LogEntry.labels.method 可以是以下其中一项,具体取决于调用 logEntry 的内容:

CompleteTask:例如,来自 Gemini Code Assist 的对话请求。

GenerateCode:例如,生成代码的请求,例如 Gemini Code Assist 中的代码转换请求。

CompleteCode:例如,在 IDE 中工作时补全代码的请求,例如 Gemini Code Assist 中的内嵌建议。
LogEntry.labels.product 日志适用的服务的名称。与 Gemini Code Assist 相关的日志使用产品值 code_assist。如果日志与 Gemini Cloud Assist 相关,则此值为 cloud_assist。否则,此值为 unknown。
LogEntry.labels.request_id 用于将请求与回答日志条目相关联的唯一标识符。
LogEntry.labels.user_id 发出此请求的用户的标识符。
LogEntry.jsonPayload 日志条目的载荷。
LogEntry.logName 标识日志。

以下示例展示了对话提示事件的示例日志条目:

{
  "insertId": "654581e30003b19e340bbd96",
  "resource": {
    "type": "cloudaicompanion.googleapis.com/Instance",
    "labels": {
        instance_id: "default"
        location: "global"
        resource_container: "my-project-id"
     }
  },
  "timestamp": "2023-11-03T23:27:31.242078Z",
  "labels": {
    "product": "code_assist",
    "request_id": "4ea1e265-ea5d-4d11-b3c8-39bad9c96326"
    "user_id": "user@company.com"
  },
  "jsonPayload" : {
    @type: "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.RequestLog"
    "taskCompletionRequest":
      input: {
        messages: [{
          author: "USER"
          content: "What are some best practices to save cost on my Google Cloud bill?"
        }]
        preamble: ""
      }
  }
  "logName": "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Frequest",
  "receiveTimestamp": "2023-11-03T23:27:31.255648319Z"
  "severity": "INFO"
}

以下示例展示了自动内嵌代码建议提示和在代码文件中提示 Gemini Code Assist 的 RequestLog 条目示例。

内嵌代码建议的提示数据使用 codeCompletionRequest 对象(如以下示例所示),而手动触发的生成使用 codeGenerationRequest。

{
  "insertId": "654581e30003b19e340bbd96",
  "resource": {
    "type": "cloudaicompanion.googleapis.com/Instance",
    "labels": {
        instance_id: "default"
        location: "global"
        resource_container: "my-project-id"
     }
  },
  "timestamp": "2023-11-03T23:27:31.242078Z",
  "labels": {
    "product": "code_assist",
    "request_id": "4ea1e265-ea5d-4d11-b3c8-39bad9c96326"
    "user_id": "user@company.com"
  },
  "jsonPayload" : {
    @type: "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.RequestLog"
    "codeCompletionRequest": {
      "input_data_context": {
        "additional_context": {
          "files": [
            {
              "language": "go",
              "path": "{/path/to/../current-file.go",
              "segments": [
                {
                  "content": "...Prefix Text..."
                },
                {
                  "content": "...Suffix Text..."
                }
              ],
              "state": ["EDITED"]
            },
            {
              "language": "go",
              "path": "/path/to/../recent-file.go",
              "segments": [
                {
                  "content": "...File Text..."
                }
              ],
              "state": ["RECENTLY_OPENED"]
            }
          ]
        }
      }
    }
  }
  "logName": "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Frequest",
  "receiveTimestamp": "2023-11-03T23:27:31.255648319Z"
  "severity": "INFO"
}

智能体互动日志

与 Gemini 的某些互动可能会针对单个用户操作生成多个日志条目(请求、回答和元数据)。此类互动的示例包括:

  • 代理执行涉及工具使用的任务(例如,模型调用 read_file 或 replace 等内部函数,如日志示例所示)。
  • 一个代理与其他代理进行互动。
请求日志条目

以下示例展示了发起代理互动的请求的示例日志条目:

{
  "insertId": "qe9xxub2r",
  "jsonPayload": {
    "taskCompletionRequest": {
      "input": {
        "messages": [
          {
            "author": "USER",
            "content": "hi can you add one test here\nCurrent File Path:\n```cpp\n/usr/local/google/home/pdec/test.cpp\n```\n\n"
          }
        ],
        "preamble": ""
      }
    },
    "@type": "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.RequestLog"
  },
  "resource": {
    "type": "cloudaicompanion.googleapis.com/Instance",
    "labels": {
      "resource_container": "my-project-id",
      "instance_id": "default",
      "location": "global"
    }
  },
  "timestamp": "2025-10-08T10:09:52.225165428Z",
  "severity": "INFO",
  "labels": {
    "request_id": "e60facb1485b17b7",
    "client_version": "unknown",
    "product": "code_assist",
    "method": "CompleteTask",
    "user_id": "user@company.com",
    "client_name": "cloudcode_cli"
  },
  "logName": "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Frequest",
  "receiveTimestamp": "2025-10-08T10:09:52.581787548Z"
}
响应日志条目

以下示例展示了包含多条消息的代理互动中的示例回答日志条目:

{
  "insertId": "qe9xxub2t",
  "jsonPayload": {
    "@type": "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.ResponseLog",
    "taskCompletionResponse": {
      "output": {
        "messages": [
          {
            "content": "**Reading File Contents**\n\nI'm currently focused on reading the contents of `/usr/local/google/home/pdec/test.cpp`. This will inform what kind of test needs to be written and how it should be structured.\n\n\n",
            "author": "MODEL"
          },
          {
            "author": "MODEL",
            "content": "**File Inspection Begins**\n\nI've initiated the process of reading the test file. My immediate goal is to grasp its existing structure and identify the testing framework, if one exists. This will directly influence the design of the new test case I'll be adding.\n\n\n"
          },
          {
            "author": "MODEL",
            "content": "Of course. What is the test about? I'll read the file to understand the context."
          },
          {
            "content": "read_file({\"absolute_path\":\"/usr/local/google/home/pdec/test.cpp\"})",
            "author": "MODEL"
          }
        ]
      }
    }
  },
  "resource": {
    "type": "cloudaicompanion.googleapis.com/Instance",
    "labels": {
      "resource_container": "my-project-id",
      "instance_id": "default",
      "location": "global"
    }
  },
  "timestamp": "2025-10-08T10:09:52.227354297Z",
  "severity": "INFO",
  "labels": {
    "product": "code_assist",
    "request_id": "e60facb1485b17b7",
    "user_id": "user@company.com",
    "client_version": "unknown",
    "method": "CompleteTask",
    "client_name": "cloudcode_cli"
  },
  "logName": "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Fresponse",
  "receiveTimestamp": "2025-10-08T10:09:52.581787548Z"
}
元数据日志条目

以下示例展示了代理互动中的示例元数据日志条目:

{
  "insertId": "qe9xxub2s",
  "jsonPayload": {
    "apiRequest": {},
    "clientName": "cloudcode_cli",
    "requestId": "e60facb1485b17b7",
    "@type": "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.MetadataLog",
    "clientVersion": "unknown"
  },
  "resource": {
    "type": "cloudaicompanion.googleapis.com/Instance",
    "labels": {
      "location": "global",
      "instance_id": "default",
      "resource_container": "my-project-id"
    }
  },
  "timestamp": "2025-10-08T10:09:52.226420727Z",
  "severity": "INFO",
  "labels": {
    "method": "CompleteTask",
    "product": "code_assist",
    "user_id": "user@company.com"
  },
  "logName": "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Fmetadata",
  "receiveTimestamp": "2025-10-08T10:09:52.581787548Z"
}

以下示例展示了代理互动的日志条目的另一个示例,请求 ID 为 4b66a582bad9cf2c:

请求日志条目

{
  "insertId": "4qvt8nb2k",
  "jsonPayload": {
    "taskCompletionRequest": {
      "input": {
        "messages": [
          {
            "author": "USER",
            "content": "FunctionResponse{name: read_file, response: {\"output\":\"#include <iostream>\\n\\n// Function to calculate the greatest common divisor (GCD) of two numbers.\\nint gcd(int a, int b) {\\n    if (b == 0) {\\n        return a;\\n    }\\n    return gcd(b, a % b);\\n}\\n\\n// Function to calculate the least common multiple (LCM) of two numbers.\\nint lcm(int a, int b) {\\n    return (a * b) / gcd(a, b);\\n}\\n\\n// Function to check if a number is prime.\\nint is_prime(int a) {\\n    if (a < 2) {\\n        return 0;\\n    }\\n    for (int i = 2; i * i <= a; ++i) {\\n        if (a % i == 0) {\\n            return 0;\\n        }\\n    }\\n    return 1;\\n}\\n\\n// Function for extended Euclidean algorithm.\\nint extended_gcd(int a, int b, int &x, int &y) {\\n    if (b == 0) {\\n        x = 1;\\n        y = 0;\\n        return a;\\n    }\\n    int x1, y1;\\n    int d = extended_gcd(b, a % b, x1, y1);\\n    x = y1;\\n    y = x1 - (a / b) * y1;\\n    return d;\\n}\\n\\n// Test function\\nvoid run_tests() {\\n    // Test gcd\\n    if (gcd(10, 15) == 5) {\\n        std::cout << \\\"gcd(10, 15) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"gcd(10, 15) failed\\\" << std::endl;\\n    }\\n\\n    // Test lcm\\n    if (lcm(10, 15) == 30) {\\n        std::cout << \\\"lcm(10, 15) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"lcm(10, 15) failed\\\" << std::endl;\\n    }\\n\\n    // Test is_prime\\n    if (is_prime(7) == 1) {\\n        std::cout << \\\"is_prime(7) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"is_prime(7) failed\\\" << std::endl;\\n    }\\n    if (is_prime(10) == 0) {\\n        std::cout << \\\"is_prime(10) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"is_prime(10) failed\\\" << std::endl;\\n    }\\n\\n    // Test extended_gcd\\n    int x, y;\\n    int g = extended_gcd(35, 15, x, y);\\n    if (g == 5 && 35 * x + 15 * y == g) {\\n        std::cout << \\\"extended_gcd(35, 15) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"extended_gcd(35, 15) failed\\\" << std::endl;\\n    }\\n\\n    // Test is_prime with 1\\n    if (is_prime(1) == 0) {\\n        std::cout << \\\"is_prime(1) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"is_prime(1) failed\\\" << std::endl;\\n    }\\n\\n    // Test is_prime with 9\\n    if (is_prime(9) == 0) {\\n        std::cout << \\\"is_prime(9) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"is_prime(9) failed\\\" << std::endl;\\n    }\\n\\n    // Test is_prime with 13\\n    if (is_prime(13) == 1) {\\n        std::cout << \\\"is_prime(13) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"is_prime(13) failed\\\" << std::endl;\\n    }\\n\\n    // Test lcm with 7 and 9\\n    if (lcm(7, 9) == 63) {\\n        std::cout << \\\"lcm(7, 9) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"lcm(7, 9) failed\\\" << std::endl;\\n    }\\n\\n    // Test gcd with 12 and 18\\n    if (gcd(12, 18) == 6) {\\n        std::cout << \\\"gcd(12, 18) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"gcd(12, 18) failed\\\" << std::endl;\\n    }\\n\\n    // Test gcd with two primes\\n    if (gcd(7, 13) == 1) {\\n        std::cout << \\\"gcd(7, 13) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"gcd(7, 13) failed\\\" << std::endl;\\n    }\\n\\n    // Test is_prime with 97\\n    if (is_prime(97) == 1) {\\n        std::cout << \\\"is_prime(97) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"is_prime(97) failed\\\" << std::endl;\\n    }\\n\\n    // Test extended_gcd with 48 and 18\\n    int x2, y2;\\n    int g2 = extended_gcd(48, 18, x2, y2);\\n    if (g2 == 6 && 48 * x2 + 18 * y2 == g2) {\\n        std::cout << \\\"extended_gcd(48, 18) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"extended_gcd(48, 18) failed\\\" << std::endl;\\n    }\\n\\n    // Test gcd with 27 and 18\\n    if (gcd(27, 18) == 9) {\\n        std::cout << \\\"gcd(27, 18) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"gcd(27, 18) failed\\\" << std::endl;\\n    }\\n    // test 999 and 123\\n    if (gcd(999, 123) == 3) {\\n        std::cout << \\\"gcd(999, 123) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"gcd(999, 123) failed\\\" << std::endl;\\n    }\\n    \\n    \\n}\\n\\nint main() {\\n    run_tests();\\n    return 0;\\n}\"}}"
          }
        ],
        "preamble": ""
      }
    },
    "@type": "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.RequestLog"
  },
  "resource": {
    "type": "cloudaicompanion.googleapis.com/Instance",
    "labels": {
      "resource_container": "my-project-id",
      "instance_id": "default",
      "location": "global"
    }
  },
  "timestamp": "2025-10-08T10:10:03.457717366Z",
  "severity": "INFO",
  "labels": {
    "request_id": "4b66a582bad9cf2c",
    "method": "CompleteTask",
    "client_version": "unknown",
    "product": "code_assist",
    "client_name": "cloudcode_cli",
    "user_id": "user@company.com"
  },
  "logName": "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Frequest",
  "receiveTimestamp": "2025-10-08T10:10:03.606059154Z"
}

响应日志条目

{
  "insertId": "4qvt8nb2m",
  "jsonPayload": {
    "taskCompletionResponse": {
      "output": {
        "messages": [
          {
            "author": "MODEL",
            "content": "**Testing the functions**\\n\\nI'm focusing on adding a new test case to `test.cpp`.  The existing `run_tests` function is a great starting point. I'm considering which function to test further – maybe `extended_gcd`? I'll review the current tests for that function and then devise a new test scenario to add.\\n\\n\\n"
          },
          {
            "author": "MODEL",
            "content": "**Evaluating LCM Test**\\n\\nI've finalized the new test case for the `lcm` function within the `test.cpp` file.  I'm adding a test for `lcm(12, 18)` to confirm the result is 36. I plan to use the `replace` command to inject this new test directly before the closing brace of the `run_tests` function.  I've identified a unique line in `test.cpp` as the anchor for replacement.\\n\\n\\n"
          },
          {
            "author": "MODEL",
            "content": "**Inserting the new test**\\n\\nI've created a test case for `lcm(12, 18)`, confirming the expected result of 36. To implement this, I'm targeting the `run_tests` function.  I'll use the `replace` command and will search the end of the `run_tests` function to inject the new test, right before the closing brace.  I'm ready to implement this and confirm that it passes.\\n\\n\\n"
          },
          {
            "author": "MODEL",
            "content": "I've reviewed the file. I'll add a test case for the `lcm` function with inputs 12 and 18."
          },
          {
            "content": "replace({\"file_path\":\"/usr/local/google/home/pdec/test.cpp\",\"instruction\":\"add a test for the lcm function with 12 and 18\",\"new_string\":\"    // test 999 and 123\\n    if (gcd(999, 123) == 3) {\\n        std::cout << \\\"gcd(999, 123) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"gcd(999, 123) failed\\\" << std::endl;\\n    }\\n    \\n    // Test lcm with 12 and 18\\n    if (lcm(12, 18) == 36) {\\n        std::cout << \\\"lcm(12, 18) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"lcm(12, 18) failed\\\" << std::endl;\\n    }\\n    \\n}\",\"old_string\":\"    // test 999 and 123\\n    if (gcd(999, 123) == 3) {\\n        std::cout << \\\"gcd(999, 123) passed\\\" << std::endl;\\n    } else {\\n        std::cout << \\\"gcd(999, 123) failed\\\" << std::endl;\\n    }\\n    \\n    \\n}\"})",
            "author": "MODEL"
          }
        ]
      }
    },
    "@type": "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.ResponseLog"
  },
  "resource": {
    "type": "cloudaicompanion.googleapis.com/Instance",
    "labels": {
      "location": "global",
      "resource_container": "my-project-id",
      "instance_id": "default"
    }
  },
  "timestamp": "2025-10-08T10:10:03.461137399Z",
  "severity": "INFO",
  "labels": {
    "client_name": "cloudcode_cli",
    "client_version": "unknown",
    "method": "CompleteTask",
    "request_id": "4b66a582bad9cf2c",
    "product": "code_assist",
    "user_id": "user@company.com"
  },
  "logName": "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Fresponse",
  "receiveTimestamp": "2025-10-08T10:10:03.606059154Z"
}

元数据日志条目

{
  "insertId": "4qvt8nb2l",
  "jsonPayload": {
    "clientVersion": "unknown",
    "apiRequest": {},
    "clientName": "cloudcode_cli",
    "requestId": "4b66a582bad9cf2c",
    "@type": "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.MetadataLog"
  },
  "resource": {
    "type": "cloudaicompanion.googleapis.com/Instance",
    "labels": {
      "resource_container": "my-project-id",
      "location": "global",
      "instance_id": "default"
    }
  },
  "timestamp": "2025-10-08T10:10:03.459902984Z",
  "severity": "INFO",
  "labels": {
    "product": "code_assist",
    "user_id": "user@company.com",
    "method": "CompleteTask"
  },
  "logName": "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Fmetadata",
  "receiveTimestamp": "2025-10-08T10:10:03.606059154Z"
}

Gemini Code Assist 的回答

下表展示了 Gemini Code Assist 回答字段和说明:

字段 值和备注
LogEntry.resource.type Gemini Code Assist 资源类型:cloudaicompanion.googleapis.com/Instance。
LogEntry.resource.labels.resource_container 使用 Gemini Code Assist 的资源容器的唯一 ID。
LogEntry.resource.labels.location 使用 Gemini Code Assist 的位置。
LogEntry.resource.labels.instance_id 使用了 Gemini Code Assist 的资源的唯一 ID。
LogEntry.labels.method 可以是以下其中一项,具体取决于调用 logEntry 的内容:

CompleteTask:例如,来自 Gemini Code Assist 的对话请求。

GenerateCode:例如,生成代码的请求,例如 Gemini Code Assist 中的代码转换请求。

CompleteCode:例如,在 IDE 中工作时补全代码的请求,例如 Gemini Code Assist 中的内嵌建议。
LogEntry.labels.product 日志适用的服务的名称。与 Gemini Code Assist 相关的日志使用产品值 code_assist。如果日志与 Gemini Cloud Assist 相关,则此值为 cloud_assist。否则,此值为 unknown。
LogEntry.labels.request_id 用于将请求与回答日志条目相关联的唯一标识符。
LogEntry.labels.user_id 发出此请求的用户的标识符。
LogEntry.jsonPayload 日志条目的载荷。用于生成回答的所有来源引用都以 attribution_context 的形式包含在此对象中。
LogEntry.logName 标识日志。

Gemini Code Assist 元数据日志

如需生成元数据日志,必须为 VS Code 和 IntelliJ 扩展程序启用“Gemini Code Assist 扩展程序”遥测设置。

Gemini Code Assist 元数据日志遵循与 Gemini Code Assist 日志相同的结构,但指定了不同的字段。元数据日志包含以下类型的条目:

  • 请求元数据:Gemini Code Assist 会为每个对话和智能体、代码生成和代码补全请求写入元数据日志条目。这些条目的 labels.method 值为 CompleteTask、GenerateCode 或 CompleteCode。对于对话和代理请求 (CompleteTask),该条目在 apiRequest.totalTokenCount 中包含合并的 token 计数。对于代码生成和代码补全请求,apiRequest 为空。
  • 遥测事件:IDE 会发送遥测事件(例如 codeExposure、codeAcceptance、chatExposure 和 chatAcceptance 事件)以及接受的代码行数。这些条目的 labels.method 值为 Export.Metrics,不包含 token 计数。

下表列出了用户请求日志条目中找到的字段:

字段 值和备注
LogEntry.@type Gemini Code Assist 元数据资源类型:type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.MetadataLog。
LogEntry.labels.method 可以是以下其中一项,具体取决于元数据日志条目的类型:

Export.Metrics:IDE 发送的遥测事件,例如 codeExposure、codeAcceptance、chatExposure 和 chatAcceptance。

CompleteTask、GenerateCode 或 CompleteCode:分别对应于对话和智能体、代码生成和代码补全请求的请求元数据。
LogEntry.labels.product 日志适用的服务的名称。与 Gemini Code Assist 相关的日志使用产品值 code_assist。如果日志与 Gemini Cloud Assist 相关,则此值为 cloud_assist。否则,此值为 unknown。
LogEntry.labels.user_id 发出此请求的用户的标识符。
LogEntry.jsonPayload 元数据日志条目的载荷。对于请求元数据条目,载荷包含一个 apiRequest 对象。对于遥测条目,载荷包含以下遥测事件之一:codeExposure、codeAcceptance、chatExposure 或 chatAcceptance。以下各行介绍了每个遥测事件。
LogEntry.jsonPayload.clientName IDE 名称,例如 CloudCodeVscode。
LogEntry.jsonPayload.clientVersion IDE 版本号。
LogEntry.jsonPayload.apiRequest 存在于请求元数据条目(CompleteTask、GenerateCode 和 CompleteCode)中。对于对话和代理请求 (CompleteTask),包含 totalTokenCount:请求的合并 token 计数。对于代码生成和代码补全请求(GenerateCode 和 CompleteCode),此对象为空 ({})。
LogEntry.jsonPayload.codeAcceptance 仅适用于 VS Code 和 IntelliJ IDE,表示用户发生了某些接受事件,例如覆盖输入、Tab 键或完全接受。还包含以下字段:
  • linesCount:用户接受的代码行总数。
  • commentLinesCount:用户接受的代码中的注释行数。只有当 Gemini Code Assist 能够确定接受的行中有多少是注释行时,此属性才会显示。
  • originalRequestId:用于将 codeExposure 事件与零个或零个以上的 codeAcceptance 事件相关联的标识符。可用于计算接受率和接受的代码行数度量。
  • programmingLanguage:所接受代码的编程语言,例如 python。
LogEntry.jsonPayload.codeExposure 仅适用于 VS Code 和 IntelliJ IDE,表示向用户显示了代码建议。还包含以下字段:
  • programmingLanguage:曝光的编程语言,例如 python。
  • originalRequestId:用于将 codeExposure 事件与零个或零个以上的 codeAcceptance 事件相关联的标识符。可用于计算接受率和接受的代码行数度量。
LogEntry.jsonPayload.chatExposure 表示对话回答已向用户呈现。还包含以下字段:
  • originalRequestId:用于将 chatExposure 事件与零个或零个以上的 chatAcceptance 事件相关联的标识符。可用于计算对话接受率和接受的对话行数度量。
  • is_agentic:一个标识符,用于指示 chatExposure 是否来自智能体模式。可用于区分智能体模式和非智能体模式下的对话接受率和接受的代码行数度量。
LogEntry.jsonPayload.chatAcceptance 指示用户对对话回答中的代码块执行了某个接受事件。还包含以下字段:
  • interactionType:用户与代码块的互动类型,例如 ACCEPT_CODE_BLOCK。
  • programmingLanguage:所接受代码的编程语言,例如 python。
  • linesCount:用户接受的代码行总数。
  • originalRequestId:用于将 chatExposure 事件与零个或零个以上的 chatAcceptance 事件相关联的标识符。
  • is_agentic:一个标识符,用于指示 chatAcceptance 是否来自智能体模式。可用于区分智能体模式和非智能体模式下的对话接受率和接受的代码行数度量。

以下示例展示了 codeExposure 日志条目示例:

{
  insertId: "whfrqgc1gj"
  jsonPayload: {
    @type: "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.MetadataLog"
    clientName: "CloudCodeVscode"
    clientVersion: "1.93.1"
    codeExposure: {
      originalRequestId: "cac019824a0b25ba"
      programmingLanguage: "python"
    }
  requestId: "0c5178fe-446f-4ab6-b996-520dec100cf8"
  }
  labels: {
    method: "Export.Metrics"
    product: "code_assist"
    user_id: "user@company.com"
  }
  logName: "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Fmetadata"
  receiveTimestamp: "2025-02-03T23:34:35.662837985Z"
  resource: {
    labels: {
      instance_id: "default"
      location: "global"
      resource_container: "my-project-id"
    }
  type: "cloudaicompanion.googleapis.com/Instance"
  }
  severity: "INFO"
  timestamp: "2025-02-03T23:34:35.021564463Z"
}

以下示例展示了 codeAcceptance 日志条目示例:

{
  insertId: "whfrqgc1gk"
  jsonPayload: {
    @type: "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.MetadataLog"
    clientName: "CloudCodeVscode"
    clientVersion: "1.93.1"
    codeAcceptance: {
      linesCount: 2
      originalRequestId: "cac019824a0b25ba"
      programmingLanguage: "python"
    }
    requestId: "ddf11040-c315-452e-b7cd-928c3f97984e"
  }
  labels: {
    method: "Export.Metrics"
    product: "code_assist"
    user_id: "user@company.com"
  }
  logName: "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Fmetadata"
  receiveTimestamp: "2025-02-03T23:34:37.632662272Z"
  resource: {
    labels: {
      instance_id: "default"
      location: "global"
      resource_container: "my-project-id"
    }
    type: "cloudaicompanion.googleapis.com/Instance"
  }
  severity: "INFO"
  timestamp: "2025-02-03T23:34:36.778692483Z"
} 

以下示例展示了 chatAcceptance 日志条目示例:

{
  "insertId": "1oru1grbow",
  "jsonPayload": {
    "clientVersion": "1.103.2",
    "requestId": "32a0b0b8c967d8e8",
    "clientName": "CloudCodeVscode",
    "chatAcceptance": {
      "interactionType": "ACCEPT_CODE_BLOCK",
      "programmingLanguage": "go",
      "linesCount": "15",
      "originalRequestId": "75f7c41e63162567"
    },
    "@type": "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.MetadataLog"
  },
  "resource": {
    "type": "cloudaicompanion.googleapis.com/Instance",
    "labels": {
      "resource_container": "my-project-id",
      "instance_id": "default",
      "location": "global"
    }
  },
  "timestamp": "2025-08-25T09:34:01.240377123Z",
  "severity": "INFO",
  "labels": {
    "product": "code_assist",
    "method": "Export.Metrics",
    "user_id": "user@company.com"
  },
  "logName": "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Fmetadata",
  "receiveTimestamp": "2025-08-25T09:34:01.704925625Z"
}

以下示例展示了 chatExposure 日志条目示例:

{
  insertId: "3diaj2c208"
  jsonPayload: {
    @type: "type.googleapis.com/google.cloud.cloudaicompanion.logging.v1.MetadataLog"
    clientName: "CloudCodeVscode"
    clientVersion: "1.93.1"
    chatExposure: {
      originalRequestId: "cac019824a0b25ba"
    }
  requestId: "0c5178fe-446f-4ab6-b996-520dec100cf8"
  }
  labels: {
    method: "Export.Metrics"
    product: "code_assist"
    user_id: "user@company.com"
  }
  logName: "projects/my-project-id/logs/cloudaicompanion.googleapis.com%2Fmetadata"
  receiveTimestamp: "2025-02-03T23:34:35.662837985Z"
  resource: {
    labels: {
      instance_id: "default"
      location: "global"
      resource_container: "my-project-id"
    }
  type: "cloudaicompanion.googleapis.com/Instance"
  }
  severity: "INFO"
  timestamp: "2025-02-03T23:34:35.021564463Z"
}

计算接受率

以下部分介绍了如何使用 Gemini Code Assist 元数据日志计算代码建议接受率、对话回答接受率和总接受率。

计算代码接受率

如需使用 Gemini Code Assist 元数据日志计算代码接受率,请找到包含 codeAcceptance.originalRequestId 的事件中的唯一 ID 总数,然后将其除以包含 codeExposure.originalRequestId 的事件中的唯一 ID 总数。

您可以使用相应的元数据日志事件字段,按编程语言和用户进一步细化此计算结果。

计算对话接受率

如需使用 Gemini Code Assist 元数据日志计算对话接受率,请找到包含 chatAcceptance.originalRequestId 的事件中的唯一 ID 总数,然后将其除以包含 chatExposure.originalRequestId 的事件中的唯一 ID 总数。

您可以使用相应的元数据日志事件字段,按编程语言和用户进一步细化此计算结果。

计算总接受率

如需使用 Gemini Code Assist 元数据日志计算总接受率,请找到接受的事件总数,然后将其除以公开事件总数:

总接受率 = 接受的事件总数 ÷ 公开事件总数

  • 接受事件总数:包含 codeAcceptance.originalRequestId 的事件中的唯一 ID 总数,加上包含 chatAcceptance.originalRequestId 的事件中的唯一 ID 总数。
  • 公开事件总数:包含 codeExposure.originalRequestId 的事件中的唯一 ID 总数,加上包含 chatExposure.originalRequestId 的事件中的唯一 ID 总数。

此公式提供的接受率反映了所有 Gemini Code Assist 功能中任何建议被接受的总体概率。

计算被接受的代码行数

以下部分介绍了如何使用 Gemini Code Assist 元数据日志计算通过代码建议接受的代码行数、通过对话接受的代码行数,以及接受的代码总行数。

计算被接受的代码行数

如需计算接受的代码行数,请针对每个唯一的 codeAcceptance.originalRequestId 查找 codeAcceptance.linesCount 的最大值。 然后,将这些最大值相加,以计算接受的代码总行数。

您可以使用相应的元数据日志事件字段,按编程语言和用户进一步细化此计算结果。

计算通过对话接受的代码行数

如需计算通过对话接受的代码行数,请针对每个唯一的 chatAcceptance.originalRequestId 查找 chatAcceptance.linesCount 字段的值。然后,将这些最大值相加,以计算接受的对话总行数。

计算接受的代码总行数

如需使用 Gemini Code Assist 元数据日志计算接受的总行数,请将接受的代码行数与通过对话接受的代码行数相加。

后续步骤