mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-25 12:34:38 -07:00
feat(telemetry): add specific PR, issue, and custom tracking IDs for GitHub Actions (#21129)
This commit is contained in:
@@ -339,6 +339,12 @@ Captures startup configuration and user prompt submissions.
|
|||||||
- `mcp_tools` (string, if applicable)
|
- `mcp_tools` (string, if applicable)
|
||||||
- `mcp_tools_count` (int, if applicable)
|
- `mcp_tools_count` (int, if applicable)
|
||||||
- `output_format` ("text", "json", or "stream-json")
|
- `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.
|
- `gemini_cli.user_prompt`: Emitted when a user submits a prompt.
|
||||||
- **Attributes**:
|
- **Attributes**:
|
||||||
|
|||||||
@@ -195,6 +195,9 @@ describe('ClearcutLogger', () => {
|
|||||||
vi.stubEnv('MONOSPACE_ENV', '');
|
vi.stubEnv('MONOSPACE_ENV', '');
|
||||||
vi.stubEnv('REPLIT_USER', '');
|
vi.stubEnv('REPLIT_USER', '');
|
||||||
vi.stubEnv('__COG_BASHRC_SOURCED', '');
|
vi.stubEnv('__COG_BASHRC_SOURCED', '');
|
||||||
|
vi.stubEnv('GH_PR_NUMBER', '');
|
||||||
|
vi.stubEnv('GH_ISSUE_NUMBER', '');
|
||||||
|
vi.stubEnv('GH_CUSTOM_TRACKING_ID', '');
|
||||||
});
|
});
|
||||||
|
|
||||||
function setup({
|
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', () => {
|
describe('GITHUB_REPOSITORY metadata', () => {
|
||||||
it('includes hashed repository when GITHUB_REPOSITORY is set', () => {
|
it('includes hashed repository when GITHUB_REPOSITORY is set', () => {
|
||||||
vi.stubEnv('GITHUB_REPOSITORY', 'google/gemini-cli');
|
vi.stubEnv('GITHUB_REPOSITORY', 'google/gemini-cli');
|
||||||
|
|||||||
@@ -190,6 +190,34 @@ function determineGHRepositoryName(): string | undefined {
|
|||||||
return process.env['GITHUB_REPOSITORY'];
|
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.
|
* Clearcut URL to send logging events to.
|
||||||
*/
|
*/
|
||||||
@@ -372,6 +400,10 @@ export class ClearcutLogger {
|
|||||||
const email = this.userAccountManager.getCachedGoogleAccount();
|
const email = this.userAccountManager.getCachedGoogleAccount();
|
||||||
const surface = determineSurface();
|
const surface = determineSurface();
|
||||||
const ghWorkflowName = determineGHWorkflowName();
|
const ghWorkflowName = determineGHWorkflowName();
|
||||||
|
const ghEventName = determineGHEventName();
|
||||||
|
const ghPRNumber = determineGHPRNumber();
|
||||||
|
const ghIssueNumber = determineGHIssueNumber();
|
||||||
|
const ghCustomTrackingId = determineGHCustomTrackingId();
|
||||||
const baseMetadata: EventValue[] = [
|
const baseMetadata: EventValue[] = [
|
||||||
...data,
|
...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 = {
|
const logEvent: LogEvent = {
|
||||||
console_type: 'GEMINI_CLI',
|
console_type: 'GEMINI_CLI',
|
||||||
application: 102, // GEMINI_CLI
|
application: 102, // GEMINI_CLI
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
// Defines valid event metadata keys for Clearcut logging.
|
// Defines valid event metadata keys for Clearcut logging.
|
||||||
export enum EventMetadataKey {
|
export enum EventMetadataKey {
|
||||||
// Deleted enums: 24
|
// Deleted enums: 24
|
||||||
// Next ID: 176
|
// Next ID: 180
|
||||||
|
|
||||||
GEMINI_CLI_KEY_UNKNOWN = 0,
|
GEMINI_CLI_KEY_UNKNOWN = 0,
|
||||||
|
|
||||||
@@ -231,6 +231,18 @@ export enum EventMetadataKey {
|
|||||||
// Logs the repository name of the GitHub Action that triggered the session.
|
// Logs the repository name of the GitHub Action that triggered the session.
|
||||||
GEMINI_CLI_GH_REPOSITORY_NAME_HASH = 132,
|
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
|
// Loop Detected Event Keys
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user