mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 05:12:55 -07:00
feat(telemetry): track if session is running in a Git worktree (#23265)
This commit is contained in:
@@ -306,6 +306,7 @@ Emitted at startup with the CLI configuration.
|
|||||||
- `extension_ids` (string)
|
- `extension_ids` (string)
|
||||||
- `extensions_count` (int)
|
- `extensions_count` (int)
|
||||||
- `auth_type` (string)
|
- `auth_type` (string)
|
||||||
|
- `worktree_active` (boolean)
|
||||||
- `github_workflow_name` (string, optional)
|
- `github_workflow_name` (string, optional)
|
||||||
- `github_repository_hash` (string, optional)
|
- `github_repository_hash` (string, optional)
|
||||||
- `github_event_name` (string, optional)
|
- `github_event_name` (string, optional)
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export const createMockConfig = (overrides: Partial<Config> = {}): Config =>
|
|||||||
getDeleteSession: vi.fn(() => undefined),
|
getDeleteSession: vi.fn(() => undefined),
|
||||||
setSessionId: vi.fn(),
|
setSessionId: vi.fn(),
|
||||||
getSessionId: vi.fn().mockReturnValue('mock-session-id'),
|
getSessionId: vi.fn().mockReturnValue('mock-session-id'),
|
||||||
|
getWorktreeSettings: vi.fn(() => undefined),
|
||||||
getContentGeneratorConfig: vi.fn(() => ({ authType: 'google' })),
|
getContentGeneratorConfig: vi.fn(() => ({ authType: 'google' })),
|
||||||
getAcpMode: vi.fn(() => false),
|
getAcpMode: vi.fn(() => false),
|
||||||
isBrowserLaunchSuppressed: vi.fn(() => false),
|
isBrowserLaunchSuppressed: vi.fn(() => false),
|
||||||
|
|||||||
@@ -687,6 +687,11 @@ export class ClearcutLogger {
|
|||||||
gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_EXTENSION_IDS,
|
gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_EXTENSION_IDS,
|
||||||
value: event.extension_ids.toString(),
|
value: event.extension_ids.toString(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
gemini_cli_key:
|
||||||
|
EventMetadataKey.GEMINI_CLI_START_SESSION_WORKTREE_ACTIVE,
|
||||||
|
value: event.worktree_active.toString(),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Add hardware information only to the start session event
|
// Add hardware information only to the start session event
|
||||||
|
|||||||
@@ -452,6 +452,9 @@ export enum EventMetadataKey {
|
|||||||
// Logs the name of extensions as a comma-separated string
|
// Logs the name of extensions as a comma-separated string
|
||||||
GEMINI_CLI_START_SESSION_EXTENSION_IDS = 120,
|
GEMINI_CLI_START_SESSION_EXTENSION_IDS = 120,
|
||||||
|
|
||||||
|
// Logs whether the session is running in a Git worktree.
|
||||||
|
GEMINI_CLI_START_SESSION_WORKTREE_ACTIVE = 191,
|
||||||
|
|
||||||
// Logs the setting scope for an extension enablement.
|
// Logs the setting scope for an extension enablement.
|
||||||
GEMINI_CLI_EXTENSION_ENABLE_SETTING_SCOPE = 102,
|
GEMINI_CLI_EXTENSION_ENABLE_SETTING_SCOPE = 102,
|
||||||
|
|
||||||
|
|||||||
@@ -195,48 +195,51 @@ describe('loggers', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('logCliConfiguration', () => {
|
describe('logCliConfiguration', () => {
|
||||||
|
const baseMockConfig = {
|
||||||
|
getSessionId: () => 'test-session-id',
|
||||||
|
getModel: () => 'test-model',
|
||||||
|
getEmbeddingModel: () => 'test-embedding-model',
|
||||||
|
getSandbox: () => true,
|
||||||
|
getCoreTools: () => ['ls', 'read-file'],
|
||||||
|
getApprovalMode: () => 'default',
|
||||||
|
getContentGeneratorConfig: () => ({
|
||||||
|
model: 'test-model',
|
||||||
|
apiKey: 'test-api-key',
|
||||||
|
authType: AuthType.USE_VERTEX_AI,
|
||||||
|
}),
|
||||||
|
getTelemetryEnabled: () => true,
|
||||||
|
getUsageStatisticsEnabled: () => true,
|
||||||
|
getTelemetryLogPromptsEnabled: () => true,
|
||||||
|
getFileFilteringRespectGitIgnore: () => true,
|
||||||
|
getFileFilteringAllowBuildArtifacts: () => false,
|
||||||
|
getDebugMode: () => true,
|
||||||
|
getMcpServers: () => {
|
||||||
|
throw new Error('Should not call');
|
||||||
|
},
|
||||||
|
getQuestion: () => 'test-question',
|
||||||
|
getTargetDir: () => 'target-dir',
|
||||||
|
getProxy: () => 'http://test.proxy.com:8080',
|
||||||
|
getOutputFormat: () => OutputFormat.JSON,
|
||||||
|
getExtensions: () =>
|
||||||
|
[
|
||||||
|
{ name: 'ext-one', id: 'id-one' },
|
||||||
|
{ name: 'ext-two', id: 'id-two' },
|
||||||
|
] as GeminiCLIExtension[],
|
||||||
|
getMcpClientManager: () => ({
|
||||||
|
getMcpServers: () => ({
|
||||||
|
'test-server': {
|
||||||
|
command: 'test-command',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
isInteractive: () => false,
|
||||||
|
getExperiments: () => undefined,
|
||||||
|
getExperimentsAsync: async () => undefined,
|
||||||
|
getWorktreeSettings: () => undefined,
|
||||||
|
} as unknown as Config;
|
||||||
|
|
||||||
it('should log the cli configuration', async () => {
|
it('should log the cli configuration', async () => {
|
||||||
const mockConfig = {
|
const mockConfig = baseMockConfig;
|
||||||
getSessionId: () => 'test-session-id',
|
|
||||||
getModel: () => 'test-model',
|
|
||||||
getEmbeddingModel: () => 'test-embedding-model',
|
|
||||||
getSandbox: () => true,
|
|
||||||
getCoreTools: () => ['ls', 'read-file'],
|
|
||||||
getApprovalMode: () => 'default',
|
|
||||||
getContentGeneratorConfig: () => ({
|
|
||||||
model: 'test-model',
|
|
||||||
apiKey: 'test-api-key',
|
|
||||||
authType: AuthType.USE_VERTEX_AI,
|
|
||||||
}),
|
|
||||||
getTelemetryEnabled: () => true,
|
|
||||||
getUsageStatisticsEnabled: () => true,
|
|
||||||
getTelemetryLogPromptsEnabled: () => true,
|
|
||||||
getFileFilteringRespectGitIgnore: () => true,
|
|
||||||
getFileFilteringAllowBuildArtifacts: () => false,
|
|
||||||
getDebugMode: () => true,
|
|
||||||
getMcpServers: () => {
|
|
||||||
throw new Error('Should not call');
|
|
||||||
},
|
|
||||||
getQuestion: () => 'test-question',
|
|
||||||
getTargetDir: () => 'target-dir',
|
|
||||||
getProxy: () => 'http://test.proxy.com:8080',
|
|
||||||
getOutputFormat: () => OutputFormat.JSON,
|
|
||||||
getExtensions: () =>
|
|
||||||
[
|
|
||||||
{ name: 'ext-one', id: 'id-one' },
|
|
||||||
{ name: 'ext-two', id: 'id-two' },
|
|
||||||
] as GeminiCLIExtension[],
|
|
||||||
getMcpClientManager: () => ({
|
|
||||||
getMcpServers: () => ({
|
|
||||||
'test-server': {
|
|
||||||
command: 'test-command',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
isInteractive: () => false,
|
|
||||||
getExperiments: () => undefined,
|
|
||||||
getExperimentsAsync: async () => undefined,
|
|
||||||
} as unknown as Config;
|
|
||||||
|
|
||||||
const startSessionEvent = new StartSessionEvent(mockConfig);
|
const startSessionEvent = new StartSessionEvent(mockConfig);
|
||||||
logCliConfiguration(mockConfig, startSessionEvent);
|
logCliConfiguration(mockConfig, startSessionEvent);
|
||||||
@@ -270,9 +273,32 @@ describe('loggers', () => {
|
|||||||
extensions_count: 2,
|
extensions_count: 2,
|
||||||
extensions: 'ext-one,ext-two',
|
extensions: 'ext-one,ext-two',
|
||||||
auth_type: 'vertex-ai',
|
auth_type: 'vertex-ai',
|
||||||
|
worktree_active: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set worktree_active to true when worktree settings are present', async () => {
|
||||||
|
const mockConfig = {
|
||||||
|
...baseMockConfig,
|
||||||
|
getWorktreeSettings: () => ({
|
||||||
|
name: 'test-worktree',
|
||||||
|
path: '/path/to/worktree',
|
||||||
|
baseSha: 'test-sha',
|
||||||
|
}),
|
||||||
|
} as unknown as Config;
|
||||||
|
|
||||||
|
const startSessionEvent = new StartSessionEvent(mockConfig);
|
||||||
|
logCliConfiguration(mockConfig, startSessionEvent);
|
||||||
|
|
||||||
|
await new Promise(process.nextTick);
|
||||||
|
expect(mockLogger.emit).toHaveBeenCalledWith({
|
||||||
|
body: 'CLI configuration loaded.',
|
||||||
|
attributes: expect.objectContaining({
|
||||||
|
worktree_active: true,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('logUserPrompt', () => {
|
describe('logUserPrompt', () => {
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ export class StartSessionEvent implements BaseTelemetryEvent {
|
|||||||
extensions: string;
|
extensions: string;
|
||||||
extension_ids: string;
|
extension_ids: string;
|
||||||
auth_type?: string;
|
auth_type?: string;
|
||||||
|
worktree_active: boolean;
|
||||||
|
|
||||||
constructor(config: Config, toolRegistry?: ToolRegistry) {
|
constructor(config: Config, toolRegistry?: ToolRegistry) {
|
||||||
const generatorConfig = config.getContentGeneratorConfig();
|
const generatorConfig = config.getContentGeneratorConfig();
|
||||||
@@ -114,6 +115,7 @@ export class StartSessionEvent implements BaseTelemetryEvent {
|
|||||||
this.extensions = extensions.map((e) => e.name).join(',');
|
this.extensions = extensions.map((e) => e.name).join(',');
|
||||||
this.extension_ids = extensions.map((e) => e.id).join(',');
|
this.extension_ids = extensions.map((e) => e.id).join(',');
|
||||||
this.auth_type = generatorConfig?.authType;
|
this.auth_type = generatorConfig?.authType;
|
||||||
|
this.worktree_active = !!config.getWorktreeSettings();
|
||||||
if (toolRegistry) {
|
if (toolRegistry) {
|
||||||
const mcpTools = toolRegistry
|
const mcpTools = toolRegistry
|
||||||
.getAllTools()
|
.getAllTools()
|
||||||
@@ -147,6 +149,7 @@ export class StartSessionEvent implements BaseTelemetryEvent {
|
|||||||
extensions_count: this.extensions_count,
|
extensions_count: this.extensions_count,
|
||||||
extension_ids: this.extension_ids,
|
extension_ids: this.extension_ids,
|
||||||
auth_type: this.auth_type,
|
auth_type: this.auth_type,
|
||||||
|
worktree_active: this.worktree_active,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user