Add telemetry command and refactor telemetry settings (#1060)
#750 ### Telemetry Settings Refactors telemetry configuration to use a nested `telemetry` object in `settings.json`, for example: ```json { "telemetry": { "enabled": true, "target": "gcp" "log-prompts": "true" }, "sandbox": false } ``` The above includes - Centralized telemetry settings under a `telemetry` object in `settings.json`. - CLI flags for the `gemini` command to override all telemetry sub-settings: - `--telemetry` / `--no-telemetry` - `--telemetry-target <local|gcp>` - `--telemetry-otlp-endpoint <URL>` - `--telemetry-log-prompts` / `--no-telemetry-log-prompts` - Updates `packages/cli/src/config/config.ts` and `packages/core/src/config/config.ts` to read from the new settings structure and respect the new CLI flags. - Modifies `scripts/handle-telemetry.js`, `scripts/local_telemetry.js`, and `scripts/telemetry_utils.js` to align with the new settings structure. - Updates `docs/core/telemetry.md` to reflect the new settings structure, CLI flags, and order of precedence. - Renames `logUserPromptsEnabled` to `logPrompts` for brevity. ### `npm run telemetry` Add a new `npm run telemetry` command that uses `scripts/telemetry.js`, automates the entire process of setting up a local and GCP telemetry pipelines, including configuring the necessary settings in the `.gemini/settings.json` workspace file and installing required binaries (e.g. `otelcol-contrib`). --- ```shell $ npm run telemetry -- --target=gcp > gemini-cli@0.1.0 telemetry > node scripts/telemetry.js --target=gcp ⚙️ Using command-line target: gcp 🚀 Running telemetry script for target: gcp. ✨ Starting Local Telemetry Exporter for Google Cloud ✨ ⚙️ Enabled telemetry in workspace settings. 🔧 Set telemetry OTLP endpoint to http://localhost:4317. 🎯 Set telemetry target to gcp. ✅ Workspace settings updated. ✅ Using Google Cloud Project ID: foo-bar 🔑 Please ensure you are authenticated with Google Cloud: - Run `gcloud auth application-default login` OR ensure `GOOGLE_APPLICATION_CREDENTIALS` environment variable points to a valid service account key. - The account needs "Cloud Trace Agent", "Monitoring Metric Writer", and "Logs Writer" roles. ✅ otelcol-contrib already exists at /Users/jerop/github/gemini-cli/.gemini/otel/bin/otelcol-contrib 🧹 Cleaning up old processes and logs... ✅ Deleted old GCP collector log. 📄 Wrote OTEL collector config to /Users/jerop/github/gemini-cli/.gemini/otel/collector-gcp.yaml 🚀 Starting OTEL collector for GCP... Logs: /Users/jerop/github/gemini-cli/.gemini/otel/collector-gcp.log ⏳ Waiting for OTEL collector to start (PID: 17013)... ✅ OTEL collector started successfully on port 4317. ✨ Local OTEL collector for GCP is running. 🚀 To send telemetry, run the Gemini CLI in a separate terminal window. 📄 Collector logs are being written to: /Users/jerop/github/gemini-cli/.gemini/otel/collector-gcp.log 📊 View your telemetry data in Google Cloud Console: - Logs: https://console.cloud.google.com/logs/query;query=logName%3D%22projects%2Ffoo-bar%2Flogs%2Fgemini_cli%22?project=foo-bar - Metrics: https://console.cloud.google.com/monitoring/metrics-explorer?project=foo-bar - Traces: https://console.cloud.google.com/traces/list?project=foo-bar Press Ctrl+C to exit. ^C 👋 Shutting down... ⚙️ Disabled telemetry in workspace settings. 🔧 Cleared telemetry OTLP endpoint. 🎯 Cleared telemetry target. ✅ Workspace settings updated. 🛑 Stopping otelcol-contrib (PID: 17013)... ✅ otelcol-contrib stopped. ```
This commit is contained in:
parent
32dd298351
commit
53753f0455
|
@ -15,19 +15,19 @@ This entire system is built on the **[OpenTelemetry] (OTEL)** standard, allowing
|
|||
- You have exported the `GOOGLE_CLOUD_PROJECT` environment variable.
|
||||
- You have authenticated with Google Cloud and have the necessary IAM roles.
|
||||
For full details, see the [Google Cloud](#google-cloud) prerequisites.
|
||||
2. **Run the Script:** Execute the following command from the project root:
|
||||
1. **Run the Command:** Execute the following command from the project root:
|
||||
```bash
|
||||
./scripts/telemetry_gcp.js
|
||||
npm run telemetry -- --target=gcp
|
||||
```
|
||||
3. **Run Gemini CLI:** In a separate terminal, run your Gemini CLI commands. This will generate telemetry data that the collector will capture.
|
||||
4. **View Data:** The script will provide links to view your telemetry data (traces, metrics, logs) in the Google Cloud Console.
|
||||
5. **Details:** Refer to documentation for telemetry in [Google Cloud](#google-cloud).
|
||||
1. **Run Gemini CLI:** In a separate terminal, run your Gemini CLI commands. This will generate telemetry data that the collector will capture.
|
||||
1. **View Data:** The script will provide links to view your telemetry data (traces, metrics, logs) in the Google Cloud Console.
|
||||
1. **Details:** Refer to documentation for telemetry in [Google Cloud](#google-cloud).
|
||||
|
||||
### Local Telemetry with Jaeger UI (for Traces)
|
||||
|
||||
1. **Run the Script:** Execute the following command from the project root:
|
||||
1. **Run the Command:** Execute the following command from the project root:
|
||||
```bash
|
||||
./scripts/local_telemetry.js
|
||||
npm run telemetry -- --target=local
|
||||
```
|
||||
2. **Run Gemini CLI:** In a separate terminal, run your Gemini CLI commands. This will generate telemetry data that the collector will capture.
|
||||
3. **View Logs/Metrics:** Check the `.gemini/otel/collector.log` file for raw logs and metrics.
|
||||
|
@ -42,16 +42,35 @@ You can enable telemetry in multiple ways. [Configuration](configuration.md) is
|
|||
|
||||
**Order of Precedence:**
|
||||
|
||||
1. **CLI Flag (`--telemetry`):** These override all other settings for the current session.
|
||||
2. **Workspace Settings File (`.gemini/settings.json`):** If no CLI flag is used, the `telemetry` value from this project-specific file is used.
|
||||
3. **User Settings File (`~/.gemini/settings.json`):** If not set by a flag or workspace settings, the value from this global user file is used.
|
||||
4. **Default:** If telemetry is not configured by a flag or in any settings file, it is disabled.
|
||||
Telemetry settings are resolved in the following order (highest precedence first):
|
||||
|
||||
Add these lines to enable telemetry by in workspace (`.gemini/settings.json`) or user (`~/.gemini/settings.json`) settings:
|
||||
1. **CLI Flags (for `gemini` command):**
|
||||
- `--telemetry` / `--no-telemetry`: Overrides `telemetry.enabled`. If this flag is not provided, telemetry is disabled unless enabled in settings files.
|
||||
- `--telemetry-target <local|gcp>`: Overrides `telemetry.target`.
|
||||
- `--telemetry-otlp-endpoint <URL>`: Overrides `telemetry.otlpEndpoint`.
|
||||
- `--telemetry-log-prompts` / `--no-telemetry-log-prompts`: Overrides `telemetry.logPrompts`.
|
||||
2. **Environment Variables:**
|
||||
- `OTEL_EXPORTER_OTLP_ENDPOINT`: Overrides `telemetry.otlpEndpoint` if no `--telemetry-otlp-endpoint` flag is present.
|
||||
3. **Workspace Settings File (`.gemini/settings.json`):** Values from the `telemetry` object in this project-specific file.
|
||||
4. **User Settings File (`~/.gemini/settings.json`):** Values from the `telemetry` object in this global user file.
|
||||
5. **Defaults:** applied if not set by any of the above.
|
||||
- `telemetry.enabled`: `false`
|
||||
- `telemetry.target`: `local`
|
||||
- `telemetry.otlpEndpoint`: `http://localhost:4317`
|
||||
- `telemetry.logPrompts`: `true`
|
||||
|
||||
**For the `npm run telemetry -- --target=<gcp|local>` script:**
|
||||
The `--target` argument to this script _only_ overrides the `telemetry.target` for the duration and purpose of that script (i.e., choosing which collector to start). It does not permanently change your `settings.json`. The script will first look at `settings.json` for a `telemetry.target` to use as its default.
|
||||
|
||||
**Example settings:**
|
||||
Add these lines to configure telemetry in your workspace (`.gemini/settings.json`) or user (`~/.gemini/settings.json`) settings for GCP:
|
||||
|
||||
```json
|
||||
{
|
||||
"telemetry": true,
|
||||
"telemetry": {
|
||||
"enabled": true,
|
||||
"target": "gcp"
|
||||
},
|
||||
"sandbox": false
|
||||
}
|
||||
```
|
||||
|
@ -80,13 +99,13 @@ mkdir .gemini/otel
|
|||
|
||||
### Local
|
||||
|
||||
Use the `scripts/local_telemetry.js` script that automates the entire process of setting up a local telemetry pipeline, including configuring the necessary settings in your `.gemini/settings.json` file. The script installs `otelcol-contrib` (The OpenTelemetry Collector) and `jaeger` (The Jaeger UI for viewing traces). To use it:
|
||||
Use the `npm run telemetry -- --target=local` command which automates the entire process of setting up a local telemetry pipeline, including configuring the necessary settings in your `.gemini/settings.json` file. The underlying script installs `otelcol-contrib` (The OpenTelemetry Collector) and `jaeger` (The Jaeger UI for viewing traces). To use it:
|
||||
|
||||
1. **Run the Script**:
|
||||
Execute the script from the root of the repository:
|
||||
1. **Run the Command**:
|
||||
Execute the command from the root of the repository:
|
||||
|
||||
```bash
|
||||
./scripts/local_telemetry.js
|
||||
npm run telemetry -- --target=local
|
||||
```
|
||||
|
||||
The script will:
|
||||
|
@ -110,7 +129,7 @@ Use the `scripts/local_telemetry.js` script that automates the entire process of
|
|||
|
||||
### Google Cloud
|
||||
|
||||
For a streamlined setup targeting Google Cloud, use the `scripts/telemetry_gcp.js` script which automates setting up a local OpenTelemetry collector that forwards data to your Google Cloud project.
|
||||
Use the `npm run telemetry -- --target=gcp` command which automates setting up a local OpenTelemetry collector that forwards data to your Google Cloud project, including configuring the necessary settings in your `.gemini/settings.json` file. The underlying script installs `otelcol-contrib`. To use it:
|
||||
|
||||
1. **Prerequisites**:
|
||||
|
||||
|
@ -122,11 +141,11 @@ For a streamlined setup targeting Google Cloud, use the `scripts/telemetry_gcp.j
|
|||
- Authenticate with Google Cloud (e.g., run `gcloud auth application-default login` or ensure `GOOGLE_APPLICATION_CREDENTIALS` is set).
|
||||
- Ensure your account/service account has the necessary roles: "Cloud Trace Agent", "Monitoring Metric Writer", and "Logs Writer".
|
||||
|
||||
2. **Run the Script**:
|
||||
Execute the script from the root of the repository:
|
||||
2. **Run the Command**:
|
||||
Execute the command from the root of the repository:
|
||||
|
||||
```bash
|
||||
./scripts/telemetry_gcp.js
|
||||
npm run telemetry -- --target=gcp
|
||||
```
|
||||
|
||||
The script will:
|
||||
|
@ -172,7 +191,7 @@ These are timestamped records of specific events.
|
|||
- `api_key_enabled` (boolean)
|
||||
- `vertex_ai_enabled` (boolean)
|
||||
- `code_assist_enabled` (boolean)
|
||||
- `log_user_prompts_enabled` (boolean)
|
||||
- `log_prompts_enabled` (boolean)
|
||||
- `file_filtering_respect_git_ignore` (boolean)
|
||||
- `debug_mode` (boolean)
|
||||
- `mcp_servers` (string)
|
||||
|
@ -181,7 +200,7 @@ These are timestamped records of specific events.
|
|||
|
||||
- **Attributes**:
|
||||
- `prompt_length`
|
||||
- `prompt` (except if `log_user_prompts_enabled` is false)
|
||||
- `prompt` (except if `log_prompts_enabled` is false)
|
||||
|
||||
- `gemini_cli.tool_call`: Fired for every function call.
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
"prepare:cli-packagejson": "node scripts/prepare-cli-packagejson.js",
|
||||
"publish:sandbox": "node scripts/publish-sandbox.js",
|
||||
"publish:npm": "npm publish --workspaces ${NPM_PUBLISH_TAG:+--tag=$NPM_PUBLISH_TAG} ${NPM_DRY_RUN:+--dry-run}",
|
||||
"publish:release": "npm run build:packages && npm run prepare:cli-packagejson && npm run build:docker && npm run tag:docker && npm run publish:sandbox && npm run publish:npm"
|
||||
"publish:release": "npm run build:packages && npm run prepare:cli-packagejson && npm run build:docker && npm run tag:docker && npm run publish:sandbox && npm run publish:npm",
|
||||
"telemetry": "node scripts/telemetry.js"
|
||||
},
|
||||
"bin": {
|
||||
"gemini": "bundle/gemini.js"
|
||||
|
|
|
@ -127,31 +127,120 @@ describe('loadCliConfig telemetry', () => {
|
|||
|
||||
it('should use telemetry value from settings if CLI flag is not present (settings true)', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const settings: Settings = { telemetry: true };
|
||||
const settings: Settings = { telemetry: { enabled: true } };
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it('should use telemetry value from settings if CLI flag is not present (settings false)', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const settings: Settings = { telemetry: false };
|
||||
const settings: Settings = { telemetry: { enabled: false } };
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryEnabled()).toBe(false);
|
||||
});
|
||||
|
||||
it('should prioritize --telemetry CLI flag (true) over settings (false)', async () => {
|
||||
process.argv = ['node', 'script.js', '--telemetry'];
|
||||
const settings: Settings = { telemetry: false };
|
||||
const settings: Settings = { telemetry: { enabled: false } };
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it('should prioritize --no-telemetry CLI flag (false) over settings (true)', async () => {
|
||||
process.argv = ['node', 'script.js', '--no-telemetry'];
|
||||
const settings: Settings = { telemetry: true };
|
||||
const settings: Settings = { telemetry: { enabled: true } };
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryEnabled()).toBe(false);
|
||||
});
|
||||
|
||||
it('should use telemetry OTLP endpoint from settings if CLI flag is not present', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const settings: Settings = {
|
||||
telemetry: { otlpEndpoint: 'http://settings.example.com' },
|
||||
};
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryOtlpEndpoint()).toBe(
|
||||
'http://settings.example.com',
|
||||
);
|
||||
});
|
||||
|
||||
it('should prioritize --telemetry-otlp-endpoint CLI flag over settings', async () => {
|
||||
process.argv = [
|
||||
'node',
|
||||
'script.js',
|
||||
'--telemetry-otlp-endpoint',
|
||||
'http://cli.example.com',
|
||||
];
|
||||
const settings: Settings = {
|
||||
telemetry: { otlpEndpoint: 'http://settings.example.com' },
|
||||
};
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryOtlpEndpoint()).toBe('http://cli.example.com');
|
||||
});
|
||||
|
||||
it('should use default endpoint if no OTLP endpoint is provided via CLI or settings', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const settings: Settings = { telemetry: { enabled: true } };
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryOtlpEndpoint()).toBe('http://localhost:4317');
|
||||
});
|
||||
|
||||
it('should use telemetry target from settings if CLI flag is not present', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const settings: Settings = {
|
||||
telemetry: { target: ServerConfig.DEFAULT_TELEMETRY_TARGET },
|
||||
};
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryTarget()).toBe(
|
||||
ServerConfig.DEFAULT_TELEMETRY_TARGET,
|
||||
);
|
||||
});
|
||||
|
||||
it('should prioritize --telemetry-target CLI flag over settings', async () => {
|
||||
process.argv = ['node', 'script.js', '--telemetry-target', 'gcp'];
|
||||
const settings: Settings = {
|
||||
telemetry: { target: ServerConfig.DEFAULT_TELEMETRY_TARGET },
|
||||
};
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryTarget()).toBe('gcp');
|
||||
});
|
||||
|
||||
it('should use default target if no target is provided via CLI or settings', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const settings: Settings = { telemetry: { enabled: true } };
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryTarget()).toBe(
|
||||
ServerConfig.DEFAULT_TELEMETRY_TARGET,
|
||||
);
|
||||
});
|
||||
|
||||
it('should use telemetry log prompts from settings if CLI flag is not present', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const settings: Settings = { telemetry: { logPrompts: false } };
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryLogPromptsEnabled()).toBe(false);
|
||||
});
|
||||
|
||||
it('should prioritize --telemetry-log-prompts CLI flag (true) over settings (false)', async () => {
|
||||
process.argv = ['node', 'script.js', '--telemetry-log-prompts'];
|
||||
const settings: Settings = { telemetry: { logPrompts: false } };
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryLogPromptsEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it('should prioritize --no-telemetry-log-prompts CLI flag (false) over settings (true)', async () => {
|
||||
process.argv = ['node', 'script.js', '--no-telemetry-log-prompts'];
|
||||
const settings: Settings = { telemetry: { logPrompts: true } };
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryLogPromptsEnabled()).toBe(false);
|
||||
});
|
||||
|
||||
it('should use default log prompts (true) if no value is provided via CLI or settings', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const settings: Settings = { telemetry: { enabled: true } };
|
||||
const config = await loadCliConfig(settings, [], [], 'test-session');
|
||||
expect(config.getTelemetryLogPromptsEnabled()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('API Key Handling', () => {
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
DEFAULT_GEMINI_MODEL,
|
||||
DEFAULT_GEMINI_EMBEDDING_MODEL,
|
||||
FileDiscoveryService,
|
||||
TelemetryTarget,
|
||||
} from '@gemini-cli/core';
|
||||
import { Settings } from './settings.js';
|
||||
import { getEffectiveModel } from '../utils/modelCheck.js';
|
||||
|
@ -47,6 +48,9 @@ interface CliArgs {
|
|||
yolo: boolean | undefined;
|
||||
telemetry: boolean | undefined;
|
||||
checkpoint: boolean | undefined;
|
||||
telemetryTarget: string | undefined;
|
||||
telemetryOtlpEndpoint: string | undefined;
|
||||
telemetryLogPrompts: boolean | undefined;
|
||||
}
|
||||
|
||||
async function parseArguments(): Promise<CliArgs> {
|
||||
|
@ -93,7 +97,24 @@ async function parseArguments(): Promise<CliArgs> {
|
|||
})
|
||||
.option('telemetry', {
|
||||
type: 'boolean',
|
||||
description: 'Enable telemetry?',
|
||||
description:
|
||||
'Enable telemetry? This flag specifically controls if telemetry is sent. Other --telemetry-* flags set specific values but do not enable telemetry on their own.',
|
||||
})
|
||||
.option('telemetry-target', {
|
||||
type: 'string',
|
||||
choices: ['local', 'gcp'],
|
||||
description:
|
||||
'Set the telemetry target (local or gcp). Overrides settings files.',
|
||||
})
|
||||
.option('telemetry-otlp-endpoint', {
|
||||
type: 'string',
|
||||
description:
|
||||
'Set the OTLP endpoint for telemetry. Overrides environment variables and settings files.',
|
||||
})
|
||||
.option('telemetry-log-prompts', {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Enable or disable logging of user prompts for telemetry. Overrides settings files.',
|
||||
})
|
||||
.option('checkpoint', {
|
||||
alias: 'c',
|
||||
|
@ -190,10 +211,16 @@ export async function loadCliConfig(
|
|||
showMemoryUsage:
|
||||
argv.show_memory_usage || settings.showMemoryUsage || false,
|
||||
accessibility: settings.accessibility,
|
||||
telemetry:
|
||||
argv.telemetry !== undefined
|
||||
? argv.telemetry
|
||||
: (settings.telemetry ?? false),
|
||||
telemetry: {
|
||||
enabled: argv.telemetry ?? settings.telemetry?.enabled,
|
||||
target: (argv.telemetryTarget ??
|
||||
settings.telemetry?.target) as TelemetryTarget,
|
||||
otlpEndpoint:
|
||||
argv.telemetryOtlpEndpoint ??
|
||||
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ??
|
||||
settings.telemetry?.otlpEndpoint,
|
||||
logPrompts: argv.telemetryLogPrompts ?? settings.telemetry?.logPrompts,
|
||||
},
|
||||
// Git-aware file filtering settings
|
||||
fileFilteringRespectGitIgnore: settings.fileFiltering?.respectGitIgnore,
|
||||
checkpoint: argv.checkpoint,
|
||||
|
@ -203,8 +230,6 @@ export async function loadCliConfig(
|
|||
process.env.HTTP_PROXY ||
|
||||
process.env.http_proxy,
|
||||
cwd: process.cwd(),
|
||||
telemetryOtlpEndpoint:
|
||||
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? settings.telemetryOtlpEndpoint,
|
||||
fileDiscoveryService: fileService,
|
||||
bugCommand: settings.bugCommand,
|
||||
});
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
MCPServerConfig,
|
||||
getErrorMessage,
|
||||
BugCommandSettings,
|
||||
TelemetrySettings,
|
||||
} from '@gemini-cli/core';
|
||||
import stripJsonComments from 'strip-json-comments';
|
||||
import { DefaultLight } from '../ui/themes/default-light.js';
|
||||
|
@ -41,8 +42,7 @@ export interface Settings {
|
|||
showMemoryUsage?: boolean;
|
||||
contextFileName?: string | string[];
|
||||
accessibility?: AccessibilitySettings;
|
||||
telemetry?: boolean;
|
||||
telemetryOtlpEndpoint?: string;
|
||||
telemetry?: TelemetrySettings;
|
||||
preferredEditor?: string;
|
||||
bugCommand?: BugCommandSettings;
|
||||
|
||||
|
|
|
@ -8,6 +8,10 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|||
import { Config, ConfigParameters } from './config.js';
|
||||
import * as path from 'path';
|
||||
import { setGeminiMdFilename as mockSetGeminiMdFilename } from '../tools/memoryTool.js';
|
||||
import {
|
||||
DEFAULT_TELEMETRY_TARGET,
|
||||
DEFAULT_OTLP_ENDPOINT,
|
||||
} from '../telemetry/index.js';
|
||||
|
||||
// Mock dependencies that might be called during Config construction or createServerConfig
|
||||
vi.mock('../tools/tool-registry', () => {
|
||||
|
@ -38,6 +42,14 @@ vi.mock('../tools/memoryTool', () => ({
|
|||
GEMINI_CONFIG_DIR: '.gemini',
|
||||
}));
|
||||
|
||||
vi.mock('../telemetry/index.js', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('../telemetry/index.js')>();
|
||||
return {
|
||||
...actual,
|
||||
initializeTelemetry: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
describe('Server Config (config.ts)', () => {
|
||||
const API_KEY = 'server-api-key';
|
||||
const MODEL = 'gemini-pro';
|
||||
|
@ -47,7 +59,7 @@ describe('Server Config (config.ts)', () => {
|
|||
const QUESTION = 'test question';
|
||||
const FULL_CONTEXT = false;
|
||||
const USER_MEMORY = 'Test User Memory';
|
||||
const TELEMETRY = false;
|
||||
const TELEMETRY_SETTINGS = { enabled: false };
|
||||
const EMBEDDING_MODEL = 'gemini-embedding';
|
||||
const SESSION_ID = 'test-session-id';
|
||||
const baseParams: ConfigParameters = {
|
||||
|
@ -63,7 +75,7 @@ describe('Server Config (config.ts)', () => {
|
|||
question: QUESTION,
|
||||
fullContext: FULL_CONTEXT,
|
||||
userMemory: USER_MEMORY,
|
||||
telemetry: TELEMETRY,
|
||||
telemetry: TELEMETRY_SETTINGS,
|
||||
sessionId: SESSION_ID,
|
||||
};
|
||||
|
||||
|
@ -120,7 +132,7 @@ describe('Server Config (config.ts)', () => {
|
|||
it('Config constructor should set telemetry to true when provided as true', () => {
|
||||
const paramsWithTelemetry: ConfigParameters = {
|
||||
...baseParams,
|
||||
telemetry: true,
|
||||
telemetry: { enabled: true },
|
||||
};
|
||||
const config = new Config(paramsWithTelemetry);
|
||||
expect(config.getTelemetryEnabled()).toBe(true);
|
||||
|
@ -129,7 +141,7 @@ describe('Server Config (config.ts)', () => {
|
|||
it('Config constructor should set telemetry to false when provided as false', () => {
|
||||
const paramsWithTelemetry: ConfigParameters = {
|
||||
...baseParams,
|
||||
telemetry: false,
|
||||
telemetry: { enabled: false },
|
||||
};
|
||||
const config = new Config(paramsWithTelemetry);
|
||||
expect(config.getTelemetryEnabled()).toBe(false);
|
||||
|
@ -139,7 +151,7 @@ describe('Server Config (config.ts)', () => {
|
|||
const paramsWithoutTelemetry: ConfigParameters = { ...baseParams };
|
||||
delete paramsWithoutTelemetry.telemetry;
|
||||
const config = new Config(paramsWithoutTelemetry);
|
||||
expect(config.getTelemetryEnabled()).toBe(TELEMETRY);
|
||||
expect(config.getTelemetryEnabled()).toBe(TELEMETRY_SETTINGS.enabled);
|
||||
});
|
||||
|
||||
it('should have a getFileService method that returns FileDiscoveryService', () => {
|
||||
|
@ -147,4 +159,73 @@ describe('Server Config (config.ts)', () => {
|
|||
const fileService = config.getFileService();
|
||||
expect(fileService).toBeDefined();
|
||||
});
|
||||
|
||||
describe('Telemetry Settings', () => {
|
||||
it('should return default telemetry target if not provided', () => {
|
||||
const params: ConfigParameters = {
|
||||
...baseParams,
|
||||
telemetry: { enabled: true },
|
||||
};
|
||||
const config = new Config(params);
|
||||
expect(config.getTelemetryTarget()).toBe(DEFAULT_TELEMETRY_TARGET);
|
||||
});
|
||||
|
||||
it('should return provided OTLP endpoint', () => {
|
||||
const endpoint = 'http://custom.otel.collector:4317';
|
||||
const params: ConfigParameters = {
|
||||
...baseParams,
|
||||
telemetry: { enabled: true, otlpEndpoint: endpoint },
|
||||
};
|
||||
const config = new Config(params);
|
||||
expect(config.getTelemetryOtlpEndpoint()).toBe(endpoint);
|
||||
});
|
||||
|
||||
it('should return default OTLP endpoint if not provided', () => {
|
||||
const params: ConfigParameters = {
|
||||
...baseParams,
|
||||
telemetry: { enabled: true },
|
||||
};
|
||||
const config = new Config(params);
|
||||
expect(config.getTelemetryOtlpEndpoint()).toBe(DEFAULT_OTLP_ENDPOINT);
|
||||
});
|
||||
|
||||
it('should return provided logPrompts setting', () => {
|
||||
const params: ConfigParameters = {
|
||||
...baseParams,
|
||||
telemetry: { enabled: true, logPrompts: false },
|
||||
};
|
||||
const config = new Config(params);
|
||||
expect(config.getTelemetryLogPromptsEnabled()).toBe(false);
|
||||
});
|
||||
|
||||
it('should return default logPrompts setting (true) if not provided', () => {
|
||||
const params: ConfigParameters = {
|
||||
...baseParams,
|
||||
telemetry: { enabled: true },
|
||||
};
|
||||
const config = new Config(params);
|
||||
expect(config.getTelemetryLogPromptsEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return default logPrompts setting (true) if telemetry object is not provided', () => {
|
||||
const paramsWithoutTelemetry: ConfigParameters = { ...baseParams };
|
||||
delete paramsWithoutTelemetry.telemetry;
|
||||
const config = new Config(paramsWithoutTelemetry);
|
||||
expect(config.getTelemetryLogPromptsEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return default telemetry target if telemetry object is not provided', () => {
|
||||
const paramsWithoutTelemetry: ConfigParameters = { ...baseParams };
|
||||
delete paramsWithoutTelemetry.telemetry;
|
||||
const config = new Config(paramsWithoutTelemetry);
|
||||
expect(config.getTelemetryTarget()).toBe(DEFAULT_TELEMETRY_TARGET);
|
||||
});
|
||||
|
||||
it('should return default OTLP endpoint if telemetry object is not provided', () => {
|
||||
const paramsWithoutTelemetry: ConfigParameters = { ...baseParams };
|
||||
delete paramsWithoutTelemetry.telemetry;
|
||||
const config = new Config(paramsWithoutTelemetry);
|
||||
expect(config.getTelemetryOtlpEndpoint()).toBe(DEFAULT_OTLP_ENDPOINT);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,7 +23,12 @@ import { GeminiClient } from '../core/client.js';
|
|||
import { GEMINI_CONFIG_DIR as GEMINI_DIR } from '../tools/memoryTool.js';
|
||||
import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
|
||||
import { GitService } from '../services/gitService.js';
|
||||
import { initializeTelemetry } from '../telemetry/index.js';
|
||||
import {
|
||||
initializeTelemetry,
|
||||
DEFAULT_TELEMETRY_TARGET,
|
||||
DEFAULT_OTLP_ENDPOINT,
|
||||
TelemetryTarget,
|
||||
} from '../telemetry/index.js';
|
||||
import { DEFAULT_GEMINI_EMBEDDING_MODEL } from './models.js';
|
||||
|
||||
export enum ApprovalMode {
|
||||
|
@ -40,6 +45,13 @@ export interface BugCommandSettings {
|
|||
urlTemplate: string;
|
||||
}
|
||||
|
||||
export interface TelemetrySettings {
|
||||
enabled?: boolean;
|
||||
target?: TelemetryTarget;
|
||||
otlpEndpoint?: string;
|
||||
logPrompts?: boolean;
|
||||
}
|
||||
|
||||
export class MCPServerConfig {
|
||||
constructor(
|
||||
// For stdio transport
|
||||
|
@ -82,9 +94,7 @@ export interface ConfigParameters {
|
|||
showMemoryUsage?: boolean;
|
||||
contextFileName?: string | string[];
|
||||
accessibility?: AccessibilitySettings;
|
||||
telemetry?: boolean;
|
||||
telemetryLogUserPromptsEnabled?: boolean;
|
||||
telemetryOtlpEndpoint?: string;
|
||||
telemetry?: TelemetrySettings;
|
||||
fileFilteringRespectGitIgnore?: boolean;
|
||||
checkpoint?: boolean;
|
||||
proxy?: string;
|
||||
|
@ -114,9 +124,7 @@ export class Config {
|
|||
private approvalMode: ApprovalMode;
|
||||
private readonly showMemoryUsage: boolean;
|
||||
private readonly accessibility: AccessibilitySettings;
|
||||
private readonly telemetry: boolean;
|
||||
private readonly telemetryLogUserPromptsEnabled: boolean;
|
||||
private readonly telemetryOtlpEndpoint: string;
|
||||
private readonly telemetrySettings: TelemetrySettings;
|
||||
private readonly geminiClient: GeminiClient;
|
||||
private readonly fileFilteringRespectGitIgnore: boolean;
|
||||
private fileDiscoveryService: FileDiscoveryService | null = null;
|
||||
|
@ -147,11 +155,13 @@ export class Config {
|
|||
this.approvalMode = params.approvalMode ?? ApprovalMode.DEFAULT;
|
||||
this.showMemoryUsage = params.showMemoryUsage ?? false;
|
||||
this.accessibility = params.accessibility ?? {};
|
||||
this.telemetry = params.telemetry ?? false;
|
||||
this.telemetryLogUserPromptsEnabled =
|
||||
params.telemetryLogUserPromptsEnabled ?? true;
|
||||
this.telemetryOtlpEndpoint =
|
||||
params.telemetryOtlpEndpoint ?? 'http://localhost:4317';
|
||||
this.telemetrySettings = {
|
||||
enabled: params.telemetry?.enabled ?? false,
|
||||
target: params.telemetry?.target ?? DEFAULT_TELEMETRY_TARGET,
|
||||
otlpEndpoint: params.telemetry?.otlpEndpoint ?? DEFAULT_OTLP_ENDPOINT,
|
||||
logPrompts: params.telemetry?.logPrompts ?? true,
|
||||
};
|
||||
|
||||
this.fileFilteringRespectGitIgnore =
|
||||
params.fileFilteringRespectGitIgnore ?? true;
|
||||
this.checkpoint = params.checkpoint ?? false;
|
||||
|
@ -167,7 +177,7 @@ export class Config {
|
|||
this.toolRegistry = createToolRegistry(this);
|
||||
this.geminiClient = new GeminiClient(this);
|
||||
|
||||
if (this.telemetry) {
|
||||
if (this.telemetrySettings.enabled) {
|
||||
initializeTelemetry(this);
|
||||
}
|
||||
}
|
||||
|
@ -272,15 +282,19 @@ export class Config {
|
|||
}
|
||||
|
||||
getTelemetryEnabled(): boolean {
|
||||
return this.telemetry;
|
||||
return this.telemetrySettings.enabled ?? false;
|
||||
}
|
||||
|
||||
getTelemetryLogUserPromptsEnabled(): boolean {
|
||||
return this.telemetryLogUserPromptsEnabled;
|
||||
getTelemetryLogPromptsEnabled(): boolean {
|
||||
return this.telemetrySettings.logPrompts ?? true;
|
||||
}
|
||||
|
||||
getTelemetryOtlpEndpoint(): string {
|
||||
return this.telemetryOtlpEndpoint;
|
||||
return this.telemetrySettings.otlpEndpoint ?? DEFAULT_OTLP_ENDPOINT;
|
||||
}
|
||||
|
||||
getTelemetryTarget(): TelemetryTarget {
|
||||
return this.telemetrySettings.target ?? DEFAULT_TELEMETRY_TARGET;
|
||||
}
|
||||
|
||||
getGeminiClient(): GeminiClient {
|
||||
|
|
|
@ -26,7 +26,7 @@ const mockModelsModule = {
|
|||
|
||||
const mockConfig = {
|
||||
getSessionId: () => 'test-session-id',
|
||||
getTelemetryLogUserPromptsEnabled: () => true,
|
||||
getTelemetryLogPromptsEnabled: () => true,
|
||||
} as unknown as Config;
|
||||
|
||||
describe('GeminiChat', () => {
|
||||
|
|
|
@ -153,7 +153,7 @@ export class GeminiChat {
|
|||
model: string,
|
||||
): Promise<void> {
|
||||
const shouldLogUserPrompts = (config: Config): boolean =>
|
||||
config.getTelemetryLogUserPromptsEnabled() ?? false;
|
||||
config.getTelemetryLogPromptsEnabled() ?? false;
|
||||
|
||||
const requestText = this._getRequestTextFromContents(contents);
|
||||
logApiRequest(this.config, {
|
||||
|
|
|
@ -4,6 +4,15 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
export enum TelemetryTarget {
|
||||
GCP = 'gcp',
|
||||
LOCAL = 'local',
|
||||
}
|
||||
|
||||
const DEFAULT_TELEMETRY_TARGET = TelemetryTarget.LOCAL;
|
||||
const DEFAULT_OTLP_ENDPOINT = 'http://localhost:4317';
|
||||
|
||||
export { DEFAULT_TELEMETRY_TARGET, DEFAULT_OTLP_ENDPOINT };
|
||||
export {
|
||||
initializeTelemetry,
|
||||
shutdownTelemetry,
|
||||
|
|
|
@ -60,7 +60,7 @@ describe('loggers', () => {
|
|||
vertexai: true,
|
||||
codeAssist: false,
|
||||
}),
|
||||
getTelemetryLogUserPromptsEnabled: () => true,
|
||||
getTelemetryLogPromptsEnabled: () => true,
|
||||
getFileFilteringRespectGitIgnore: () => true,
|
||||
getDebugMode: () => true,
|
||||
getMcpServers: () => ({
|
||||
|
@ -99,7 +99,7 @@ describe('loggers', () => {
|
|||
describe('logUserPrompt', () => {
|
||||
const mockConfig = {
|
||||
getSessionId: () => 'test-session-id',
|
||||
getTelemetryLogUserPromptsEnabled: () => true,
|
||||
getTelemetryLogPromptsEnabled: () => true,
|
||||
} as unknown as Config;
|
||||
|
||||
it('should log a user prompt', () => {
|
||||
|
@ -125,7 +125,7 @@ describe('loggers', () => {
|
|||
it('should not log prompt if disabled', () => {
|
||||
const mockConfig = {
|
||||
getSessionId: () => 'test-session-id',
|
||||
getTelemetryLogUserPromptsEnabled: () => false,
|
||||
getTelemetryLogPromptsEnabled: () => false,
|
||||
} as unknown as Config;
|
||||
const event = {
|
||||
prompt: 'test-prompt',
|
||||
|
|
|
@ -37,7 +37,7 @@ import {
|
|||
} from '@google/genai';
|
||||
|
||||
const shouldLogUserPrompts = (config: Config): boolean =>
|
||||
config.getTelemetryLogUserPromptsEnabled() ?? false;
|
||||
config.getTelemetryLogPromptsEnabled() ?? false;
|
||||
|
||||
function getCommonAttributes(config: Config): LogAttributes {
|
||||
return {
|
||||
|
@ -86,7 +86,7 @@ export function logCliConfiguration(config: Config): void {
|
|||
api_key_enabled: !!generatorConfig.apiKey,
|
||||
vertex_ai_enabled: !!generatorConfig.vertexai,
|
||||
code_assist_enabled: !!generatorConfig.codeAssist,
|
||||
log_user_prompts_enabled: config.getTelemetryLogUserPromptsEnabled(),
|
||||
log_user_prompts_enabled: config.getTelemetryLogPromptsEnabled(),
|
||||
file_filtering_respect_git_ignore:
|
||||
config.getFileFilteringRespectGitIgnore(),
|
||||
debug_mode: config.getDebugMode(),
|
||||
|
|
|
@ -348,8 +348,13 @@ async function main() {
|
|||
|
||||
// Restore original settings
|
||||
const finalSettings = readJsonFile(WORKSPACE_SETTINGS_FILE);
|
||||
delete finalSettings.telemetry;
|
||||
delete finalSettings.telemetryOtlpEndpoint;
|
||||
if (finalSettings.telemetry) {
|
||||
delete finalSettings.telemetry.enabled;
|
||||
delete finalSettings.telemetry.otlpEndpoint;
|
||||
if (Object.keys(finalSettings.telemetry).length === 0) {
|
||||
delete finalSettings.telemetry;
|
||||
}
|
||||
}
|
||||
finalSettings.sandbox = originalSandboxSetting;
|
||||
writeJsonFile(WORKSPACE_SETTINGS_FILE, finalSettings);
|
||||
console.log('✅ Restored original telemetry and sandbox settings.');
|
||||
|
@ -393,8 +398,12 @@ async function main() {
|
|||
const originalSandboxSetting = workspaceSettings.sandbox;
|
||||
let settingsModified = false;
|
||||
|
||||
if (workspaceSettings.telemetry !== true) {
|
||||
workspaceSettings.telemetry = true;
|
||||
if (typeof workspaceSettings.telemetry !== 'object') {
|
||||
workspaceSettings.telemetry = {};
|
||||
}
|
||||
|
||||
if (workspaceSettings.telemetry.enabled !== true) {
|
||||
workspaceSettings.telemetry.enabled = true;
|
||||
settingsModified = true;
|
||||
console.log('⚙️ Enabled telemetry in workspace settings.');
|
||||
}
|
||||
|
@ -405,12 +414,18 @@ async function main() {
|
|||
console.log('✅ Disabled sandbox mode for local telemetry.');
|
||||
}
|
||||
|
||||
if (workspaceSettings.telemetryOtlpEndpoint !== 'http://localhost:4317') {
|
||||
workspaceSettings.telemetryOtlpEndpoint = 'http://localhost:4317';
|
||||
if (workspaceSettings.telemetry.otlpEndpoint !== 'http://localhost:4317') {
|
||||
workspaceSettings.telemetry.otlpEndpoint = 'http://localhost:4317';
|
||||
settingsModified = true;
|
||||
console.log('🔧 Set telemetry endpoint to http://localhost:4317.');
|
||||
}
|
||||
|
||||
if (workspaceSettings.telemetry.target !== 'local') {
|
||||
workspaceSettings.telemetry.target = 'local';
|
||||
settingsModified = true;
|
||||
console.log('🎯 Set telemetry target to local.');
|
||||
}
|
||||
|
||||
if (settingsModified) {
|
||||
writeJsonFile(WORKSPACE_SETTINGS_FILE, workspaceSettings);
|
||||
console.log('✅ Workspace settings updated.');
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { execSync } from 'child_process';
|
||||
import { join } from 'path';
|
||||
import { existsSync, readFileSync } from 'fs';
|
||||
|
||||
const projectRoot = join(import.meta.dirname, '..');
|
||||
|
||||
const SETTINGS_DIRECTORY_NAME = '.gemini';
|
||||
const USER_SETTINGS_DIR = join(
|
||||
process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH || '',
|
||||
SETTINGS_DIRECTORY_NAME,
|
||||
);
|
||||
const USER_SETTINGS_PATH = join(USER_SETTINGS_DIR, 'settings.json');
|
||||
const WORKSPACE_SETTINGS_PATH = join(
|
||||
projectRoot,
|
||||
SETTINGS_DIRECTORY_NAME,
|
||||
'settings.json',
|
||||
);
|
||||
|
||||
let settingsTarget = undefined;
|
||||
|
||||
function loadSettingsValue(filePath) {
|
||||
try {
|
||||
if (existsSync(filePath)) {
|
||||
const content = readFileSync(filePath, 'utf-8');
|
||||
const jsonContent = content.replace(/\/\/[^\n]*/g, '');
|
||||
const settings = JSON.parse(jsonContent);
|
||||
return settings.telemetry?.target;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`⚠️ Warning: Could not parse settings file at ${filePath}: ${e.message}`,
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
settingsTarget = loadSettingsValue(WORKSPACE_SETTINGS_PATH);
|
||||
|
||||
if (!settingsTarget) {
|
||||
settingsTarget = loadSettingsValue(USER_SETTINGS_PATH);
|
||||
}
|
||||
|
||||
let target = settingsTarget || 'local';
|
||||
const allowedTargets = ['local', 'gcp'];
|
||||
|
||||
const targetArg = process.argv.find((arg) => arg.startsWith('--target='));
|
||||
if (targetArg) {
|
||||
const potentialTarget = targetArg.split('=')[1];
|
||||
if (allowedTargets.includes(potentialTarget)) {
|
||||
target = potentialTarget;
|
||||
console.log(`⚙️ Using command-line target: ${target}`);
|
||||
} else {
|
||||
console.error(
|
||||
`🛑 Error: Invalid target '${potentialTarget}'. Allowed targets are: ${allowedTargets.join(', ')}.`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
} else if (settingsTarget) {
|
||||
console.log(
|
||||
`⚙️ Using telemetry target from settings.json: ${settingsTarget}`,
|
||||
);
|
||||
}
|
||||
|
||||
const scriptPath = join(
|
||||
projectRoot,
|
||||
'scripts',
|
||||
target === 'gcp' ? 'telemetry_gcp.js' : 'local_telemetry.js',
|
||||
);
|
||||
|
||||
try {
|
||||
console.log(`🚀 Running telemetry script for target: ${target}.`);
|
||||
execSync(`node ${scriptPath}`, { stdio: 'inherit', cwd: projectRoot });
|
||||
} catch (error) {
|
||||
console.error(`🛑 Failed to run telemetry script for target: ${target}`);
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
|
@ -70,6 +70,7 @@ async function main() {
|
|||
const originalSandboxSetting = manageTelemetrySettings(
|
||||
true,
|
||||
'http://localhost:4317',
|
||||
'gcp',
|
||||
);
|
||||
registerCleanup(
|
||||
() => [collectorProcess].filter((p) => p), // Function to get processes
|
||||
|
@ -80,9 +81,12 @@ async function main() {
|
|||
const projectId = process.env.GOOGLE_CLOUD_PROJECT;
|
||||
if (!projectId) {
|
||||
console.error(
|
||||
'🛑 Error: GOOGLE_CLOUD_PROJECT environment variable is not set.',
|
||||
'🛑 Error: GOOGLE_CLOUD_PROJECT environment variable is not exported.',
|
||||
);
|
||||
console.log('Please set it to your Google Cloud Project ID and try again.');
|
||||
console.log(
|
||||
' Please set it to your Google Cloud Project ID and try again.',
|
||||
);
|
||||
console.log(' `export GOOGLE_CLOUD_PROJECT=your-project-id`');
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`✅ Using Google Cloud Project ID: ${projectId}`);
|
||||
|
@ -167,13 +171,13 @@ async function main() {
|
|||
console.log(`\n📄 Collector logs are being written to: ${OTEL_LOG_FILE}`);
|
||||
console.log(`\n📊 View your telemetry data in Google Cloud Console:`);
|
||||
console.log(
|
||||
` - Traces: https://console.cloud.google.com/traces/list?project=${projectId}`,
|
||||
` - Logs: https://console.cloud.google.com/logs/query;query=logName%3D%22projects%2F${projectId}%2Flogs%2Fgemini_cli%22?project=${projectId}`,
|
||||
);
|
||||
console.log(
|
||||
` - Metrics: https://console.cloud.google.com/monitoring/metrics-explorer?project=${projectId}`,
|
||||
);
|
||||
console.log(
|
||||
` - Logs: https://console.cloud.google.com/logs/query;query=logName%3D%22projects%2F${projectId}%2Flogs%2Fgemini_cli%22?project=${projectId}`,
|
||||
` - Traces: https://console.cloud.google.com/traces/list?project=${projectId}`,
|
||||
);
|
||||
console.log(`\nPress Ctrl+C to exit.`);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import path from 'path';
|
|||
import fs from 'fs';
|
||||
import net from 'net';
|
||||
import os from 'os';
|
||||
import { execSync } from 'child_process'; // Removed spawn, it's not used here
|
||||
import { execSync } from 'child_process';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
|
@ -251,15 +251,20 @@ export async function ensureBinary(
|
|||
export function manageTelemetrySettings(
|
||||
enable,
|
||||
oTelEndpoint = 'http://localhost:4317',
|
||||
target = 'local',
|
||||
originalSandboxSettingToRestore,
|
||||
) {
|
||||
const workspaceSettings = readJsonFile(WORKSPACE_SETTINGS_FILE);
|
||||
const currentSandboxSetting = workspaceSettings.sandbox;
|
||||
let settingsModified = false;
|
||||
|
||||
if (typeof workspaceSettings.telemetry !== 'object') {
|
||||
workspaceSettings.telemetry = {};
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
if (workspaceSettings.telemetry !== true) {
|
||||
workspaceSettings.telemetry = true;
|
||||
if (workspaceSettings.telemetry.enabled !== true) {
|
||||
workspaceSettings.telemetry.enabled = true;
|
||||
settingsModified = true;
|
||||
console.log('⚙️ Enabled telemetry in workspace settings.');
|
||||
}
|
||||
|
@ -268,22 +273,36 @@ export function manageTelemetrySettings(
|
|||
settingsModified = true;
|
||||
console.log('✅ Disabled sandbox mode for telemetry.');
|
||||
}
|
||||
if (workspaceSettings.telemetryOtlpEndpoint !== oTelEndpoint) {
|
||||
workspaceSettings.telemetryOtlpEndpoint = oTelEndpoint;
|
||||
if (workspaceSettings.telemetry.otlpEndpoint !== oTelEndpoint) {
|
||||
workspaceSettings.telemetry.otlpEndpoint = oTelEndpoint;
|
||||
settingsModified = true;
|
||||
console.log(`🔧 Set telemetry OTLP endpoint to ${oTelEndpoint}.`);
|
||||
}
|
||||
} else {
|
||||
if (workspaceSettings.telemetry === true) {
|
||||
delete workspaceSettings.telemetry;
|
||||
if (workspaceSettings.telemetry.target !== target) {
|
||||
workspaceSettings.telemetry.target = target;
|
||||
settingsModified = true;
|
||||
console.log('⚙️ Disabled telemetry in workspace settings.');
|
||||
console.log(`🎯 Set telemetry target to ${target}.`);
|
||||
}
|
||||
if (workspaceSettings.telemetryOtlpEndpoint) {
|
||||
delete workspaceSettings.telemetryOtlpEndpoint;
|
||||
} else {
|
||||
if (workspaceSettings.telemetry.enabled === true) {
|
||||
delete workspaceSettings.telemetry.enabled;
|
||||
settingsModified = true;
|
||||
console.log('⚙️ Disabled telemetry in workspace settings.');
|
||||
}
|
||||
if (workspaceSettings.telemetry.otlpEndpoint) {
|
||||
delete workspaceSettings.telemetry.otlpEndpoint;
|
||||
settingsModified = true;
|
||||
console.log('🔧 Cleared telemetry OTLP endpoint.');
|
||||
}
|
||||
if (workspaceSettings.telemetry.target) {
|
||||
delete workspaceSettings.telemetry.target;
|
||||
settingsModified = true;
|
||||
console.log('🎯 Cleared telemetry target.');
|
||||
}
|
||||
if (Object.keys(workspaceSettings.telemetry).length === 0) {
|
||||
delete workspaceSettings.telemetry;
|
||||
}
|
||||
|
||||
if (
|
||||
originalSandboxSettingToRestore !== undefined &&
|
||||
workspaceSettings.sandbox !== originalSandboxSettingToRestore
|
||||
|
|
Loading…
Reference in New Issue