feat(telemetry): add specific PR, issue, and custom tracking IDs for GitHub Actions (#21129)

This commit is contained in:
Coco Sheng
2026-03-10 10:59:13 -04:00
committed by GitHub
parent 47e4f6b13f
commit e91f86c248
4 changed files with 186 additions and 1 deletions

View File

@@ -339,6 +339,12 @@ Captures startup configuration and user prompt submissions.
- `mcp_tools` (string, if applicable)
- `mcp_tools_count` (int, if applicable)
- `output_format` ("text", "json", or "stream-json")
- `github_workflow_name` (string, optional)
- `github_repository_hash` (string, optional)
- `github_event_name` (string, optional)
- `github_pr_number` (string, optional)
- `github_issue_number` (string, optional)
- `github_custom_tracking_id` (string, optional)
- `gemini_cli.user_prompt`: Emitted when a user submits a prompt.
- **Attributes**:

View File

@@ -195,6 +195,9 @@ describe('ClearcutLogger', () => {
vi.stubEnv('MONOSPACE_ENV', '');
vi.stubEnv('REPLIT_USER', '');
vi.stubEnv('__COG_BASHRC_SOURCED', '');
vi.stubEnv('GH_PR_NUMBER', '');
vi.stubEnv('GH_ISSUE_NUMBER', '');
vi.stubEnv('GH_CUSTOM_TRACKING_ID', '');
});
function setup({
@@ -596,6 +599,110 @@ describe('ClearcutLogger', () => {
});
});
describe('GITHUB_EVENT_NAME metadata', () => {
it('includes event name when GITHUB_EVENT_NAME is set', () => {
const { logger } = setup({});
vi.stubEnv('GITHUB_EVENT_NAME', 'issues');
const event = logger?.createLogEvent(EventNames.API_ERROR, []);
expect(event?.event_metadata[0]).toContainEqual({
gemini_cli_key: EventMetadataKey.GEMINI_CLI_GH_EVENT_NAME,
value: 'issues',
});
});
it('does not include event name when GITHUB_EVENT_NAME is not set', () => {
const { logger } = setup({});
vi.stubEnv('GITHUB_EVENT_NAME', undefined);
const event = logger?.createLogEvent(EventNames.API_ERROR, []);
const hasEventName = event?.event_metadata[0].some(
(item) =>
item.gemini_cli_key === EventMetadataKey.GEMINI_CLI_GH_EVENT_NAME,
);
expect(hasEventName).toBe(false);
});
});
describe('GH_PR_NUMBER metadata', () => {
it('includes PR number when GH_PR_NUMBER is set', () => {
vi.stubEnv('GH_PR_NUMBER', '123');
const { logger } = setup({});
const event = logger?.createLogEvent(EventNames.API_ERROR, []);
expect(event?.event_metadata[0]).toContainEqual({
gemini_cli_key: EventMetadataKey.GEMINI_CLI_GH_PR_NUMBER,
value: '123',
});
});
it('does not include PR number when GH_PR_NUMBER is not set', () => {
vi.stubEnv('GH_PR_NUMBER', undefined);
const { logger } = setup({});
const event = logger?.createLogEvent(EventNames.API_ERROR, []);
const hasPRNumber = event?.event_metadata[0].some(
(item) =>
item.gemini_cli_key === EventMetadataKey.GEMINI_CLI_GH_PR_NUMBER,
);
expect(hasPRNumber).toBe(false);
});
});
describe('GH_ISSUE_NUMBER metadata', () => {
it('includes issue number when GH_ISSUE_NUMBER is set', () => {
vi.stubEnv('GH_ISSUE_NUMBER', '456');
const { logger } = setup({});
const event = logger?.createLogEvent(EventNames.API_ERROR, []);
expect(event?.event_metadata[0]).toContainEqual({
gemini_cli_key: EventMetadataKey.GEMINI_CLI_GH_ISSUE_NUMBER,
value: '456',
});
});
it('does not include issue number when GH_ISSUE_NUMBER is not set', () => {
vi.stubEnv('GH_ISSUE_NUMBER', undefined);
const { logger } = setup({});
const event = logger?.createLogEvent(EventNames.API_ERROR, []);
const hasIssueNumber = event?.event_metadata[0].some(
(item) =>
item.gemini_cli_key === EventMetadataKey.GEMINI_CLI_GH_ISSUE_NUMBER,
);
expect(hasIssueNumber).toBe(false);
});
});
describe('GH_CUSTOM_TRACKING_ID metadata', () => {
it('includes custom tracking ID when GH_CUSTOM_TRACKING_ID is set', () => {
vi.stubEnv('GH_CUSTOM_TRACKING_ID', 'abc-789');
const { logger } = setup({});
const event = logger?.createLogEvent(EventNames.API_ERROR, []);
expect(event?.event_metadata[0]).toContainEqual({
gemini_cli_key: EventMetadataKey.GEMINI_CLI_GH_CUSTOM_TRACKING_ID,
value: 'abc-789',
});
});
it('does not include custom tracking ID when GH_CUSTOM_TRACKING_ID is not set', () => {
vi.stubEnv('GH_CUSTOM_TRACKING_ID', undefined);
const { logger } = setup({});
const event = logger?.createLogEvent(EventNames.API_ERROR, []);
const hasTrackingId = event?.event_metadata[0].some(
(item) =>
item.gemini_cli_key ===
EventMetadataKey.GEMINI_CLI_GH_CUSTOM_TRACKING_ID,
);
expect(hasTrackingId).toBe(false);
});
});
describe('GITHUB_REPOSITORY metadata', () => {
it('includes hashed repository when GITHUB_REPOSITORY is set', () => {
vi.stubEnv('GITHUB_REPOSITORY', 'google/gemini-cli');

View File

@@ -190,6 +190,34 @@ function determineGHRepositoryName(): string | undefined {
return process.env['GITHUB_REPOSITORY'];
}
/**
* Determines the GitHub event name if the CLI is running in a GitHub Actions environment.
*/
function determineGHEventName(): string | undefined {
return process.env['GITHUB_EVENT_NAME'];
}
/**
* Determines the GitHub Pull Request number if the CLI is running in a GitHub Actions environment.
*/
function determineGHPRNumber(): string | undefined {
return process.env['GH_PR_NUMBER'];
}
/**
* Determines the GitHub Issue number if the CLI is running in a GitHub Actions environment.
*/
function determineGHIssueNumber(): string | undefined {
return process.env['GH_ISSUE_NUMBER'];
}
/**
* Determines the GitHub custom tracking ID if the CLI is running in a GitHub Actions environment.
*/
function determineGHCustomTrackingId(): string | undefined {
return process.env['GH_CUSTOM_TRACKING_ID'];
}
/**
* Clearcut URL to send logging events to.
*/
@@ -372,6 +400,10 @@ export class ClearcutLogger {
const email = this.userAccountManager.getCachedGoogleAccount();
const surface = determineSurface();
const ghWorkflowName = determineGHWorkflowName();
const ghEventName = determineGHEventName();
const ghPRNumber = determineGHPRNumber();
const ghIssueNumber = determineGHIssueNumber();
const ghCustomTrackingId = determineGHCustomTrackingId();
const baseMetadata: EventValue[] = [
...data,
{
@@ -406,6 +438,34 @@ export class ClearcutLogger {
});
}
if (ghEventName) {
baseMetadata.push({
gemini_cli_key: EventMetadataKey.GEMINI_CLI_GH_EVENT_NAME,
value: ghEventName,
});
}
if (ghPRNumber) {
baseMetadata.push({
gemini_cli_key: EventMetadataKey.GEMINI_CLI_GH_PR_NUMBER,
value: ghPRNumber,
});
}
if (ghIssueNumber) {
baseMetadata.push({
gemini_cli_key: EventMetadataKey.GEMINI_CLI_GH_ISSUE_NUMBER,
value: ghIssueNumber,
});
}
if (ghCustomTrackingId) {
baseMetadata.push({
gemini_cli_key: EventMetadataKey.GEMINI_CLI_GH_CUSTOM_TRACKING_ID,
value: ghCustomTrackingId,
});
}
const logEvent: LogEvent = {
console_type: 'GEMINI_CLI',
application: 102, // GEMINI_CLI

View File

@@ -7,7 +7,7 @@
// Defines valid event metadata keys for Clearcut logging.
export enum EventMetadataKey {
// Deleted enums: 24
// Next ID: 176
// Next ID: 180
GEMINI_CLI_KEY_UNKNOWN = 0,
@@ -231,6 +231,18 @@ export enum EventMetadataKey {
// Logs the repository name of the GitHub Action that triggered the session.
GEMINI_CLI_GH_REPOSITORY_NAME_HASH = 132,
// Logs the event name of the GitHub Action that triggered the session.
GEMINI_CLI_GH_EVENT_NAME = 176,
// Logs the Pull Request number if the workflow is operating on a PR.
GEMINI_CLI_GH_PR_NUMBER = 177,
// Logs the Issue number if the workflow is operating on an Issue.
GEMINI_CLI_GH_ISSUE_NUMBER = 178,
// Logs a custom tracking string (e.g. a comma-separated list of issue IDs for scheduled batches).
GEMINI_CLI_GH_CUSTOM_TRACKING_ID = 179,
// ==========================================================================
// Loop Detected Event Keys
// ===========================================================================