Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/cli/telemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**:
Expand Down
107 changes: 107 additions & 0 deletions packages/core/src/telemetry/clearcut-logger/clearcut-logger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -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');
Expand Down
60 changes: 60 additions & 0 deletions packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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,
{
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down Expand Up @@ -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
// ===========================================================================
Expand Down
Loading