diff options
| author | Jerop Kipruto <[email protected]> | 2025-06-13 20:28:18 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-06-13 23:28:18 -0400 |
| commit | 1452bb4ca4ffe3b5c13aab81baaf510d4c45f06f (patch) | |
| tree | b61768b4dcfd0ec783798be22877a721487c1e24 /scripts/telemetry_gcp.js | |
| parent | defb0fac2cf0bfd86f9696336f12b05493059a27 (diff) | |
Add GCP telemetry script (#1033)
Adds a script - `scripts/telemetry_gcp.js` - to simplify setting up a local OpenTelemetry collector that forwards data to Google Cloud. This is a follow up to the script for local telemetry `scripts/local_telemetry.js` added in #1015.
This script automates downloading necessary binaries, configuring the collector, and updating workspace settings.
Also includes `scripts/telemetry_utils.js` with shared helper functions for telemetry scripts. Will refactor `scripts/local_t elemetry.js` in next steps to use this shared functionality.
Updates `docs/core/telemetry.md` to include:
- A new "Quick Start" section
- Detailed instructions for the new GCP automated script
- Reorganization of existing sections for clarity
#750
---
```
โจ Starting Local Telemetry Exporter for Google Cloud โจ
โ๏ธ Enabled telemetry in workspace settings.
๐ง Set telemetry OTLP endpoint to http://localhost:4317.
โ
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: 65145)...
โ
OTEL collector started successfully on port 4317.
โจ Local OTEL collector for GCP is running.
๐ Collector logs are being written to: /Users/jerop/github/gemini-cli/.gemini/otel/collector-gcp.log
๐ View your telemetry data in Google Cloud Console:
- Traces: https://console.cloud.google.com/traces/list?project=foo-bar
- Metrics: https://console.cloud.google.com/monitoring/metrics-explorer?project=foo-bar
- Logs: https://console.cloud.google.com/logs/query;query=logName%3D%22projects%2Ffoo-bar%2Flogs%2Fgemini_cli%22?project=foo-bar
Press Ctrl+C to exit.
^C
๐ Shutting down...
โ๏ธ Disabled telemetry in workspace settings.
๐ง Cleared telemetry OTLP endpoint.
โ
Workspace settings updated.
๐ Stopping otelcol-contrib (PID: 65145)...
โ
otelcol-contrib stopped.
```
Diffstat (limited to 'scripts/telemetry_gcp.js')
| -rwxr-xr-x | scripts/telemetry_gcp.js | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/scripts/telemetry_gcp.js b/scripts/telemetry_gcp.js new file mode 100755 index 00000000..a842625e --- /dev/null +++ b/scripts/telemetry_gcp.js @@ -0,0 +1,178 @@ +#!/usr/bin/env node + +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import path from 'path'; +import fs from 'fs'; +import { spawn, execSync } from 'child_process'; +import { + OTEL_DIR, + BIN_DIR, + fileExists, + waitForPort, + ensureBinary, + manageTelemetrySettings, + registerCleanup, +} from './telemetry_utils.js'; + +const OTEL_CONFIG_FILE = path.join(OTEL_DIR, 'collector-gcp.yaml'); +const OTEL_LOG_FILE = path.join(OTEL_DIR, 'collector-gcp.log'); + +const getOtelConfigContent = (projectId) => ` +receivers: + otlp: + protocols: + grpc: + endpoint: "localhost:4317" +processors: + batch: + timeout: 1s +exporters: + googlecloud: + project: "${projectId}" + metric: + prefix: "custom.googleapis.com/gemini_cli" + log: + default_log_name: "gemini_cli" + debug: + verbosity: detailed +service: + telemetry: + logs: + level: "debug" + metrics: + level: "none" + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [googlecloud] + metrics: + receivers: [otlp] + processors: [batch] + exporters: [googlecloud, debug] + logs: + receivers: [otlp] + processors: [batch] + exporters: [googlecloud, debug] +`; + +async function main() { + console.log('โจ Starting Local Telemetry Exporter for Google Cloud โจ'); + + let collectorProcess; + let collectorLogFd; + + const originalSandboxSetting = manageTelemetrySettings( + true, + 'http://localhost:4317', + ); + registerCleanup( + () => [collectorProcess].filter((p) => p), // Function to get processes + () => [collectorLogFd].filter((fd) => fd), // Function to get FDs + originalSandboxSetting, + ); + + const projectId = process.env.GOOGLE_CLOUD_PROJECT; + if (!projectId) { + console.error( + '๐ Error: GOOGLE_CLOUD_PROJECT environment variable is not set.', + ); + console.log('Please set it to your Google Cloud Project ID and try again.'); + process.exit(1); + } + console.log(`โ
Using Google Cloud Project ID: ${projectId}`); + + console.log('\n๐ Please ensure you are authenticated with Google Cloud:'); + console.log( + ' - Run `gcloud auth application-default login` OR ensure `GOOGLE_APPLICATION_CREDENTIALS` environment variable points to a valid service account key.', + ); + console.log( + ' - The account needs "Cloud Trace Agent", "Monitoring Metric Writer", and "Logs Writer" roles.', + ); + + if (!fileExists(BIN_DIR)) fs.mkdirSync(BIN_DIR, { recursive: true }); + + const otelcolPath = await ensureBinary( + 'otelcol-contrib', + 'open-telemetry/opentelemetry-collector-releases', + (version, platform, arch, ext) => + `otelcol-contrib_${version}_${platform}_${arch}.${ext}`, + 'otelcol-contrib', + false, // isJaeger = false + ).catch((e) => { + console.error(`๐ Error getting otelcol-contrib: ${e.message}`); + return null; + }); + if (!otelcolPath) process.exit(1); + + console.log('๐งน Cleaning up old processes and logs...'); + try { + execSync('pkill -f "otelcol-contrib"'); + console.log('โ
Stopped existing otelcol-contrib process.'); + } catch (_e) { + /* no-op */ + } + try { + fs.unlinkSync(OTEL_LOG_FILE); + console.log('โ
Deleted old GCP collector log.'); + } catch (e) { + if (e.code !== 'ENOENT') console.error(e); + } + + if (!fileExists(OTEL_DIR)) fs.mkdirSync(OTEL_DIR, { recursive: true }); + fs.writeFileSync(OTEL_CONFIG_FILE, getOtelConfigContent(projectId)); + console.log(`๐ Wrote OTEL collector config to ${OTEL_CONFIG_FILE}`); + + console.log(`๐ Starting OTEL collector for GCP... Logs: ${OTEL_LOG_FILE}`); + collectorLogFd = fs.openSync(OTEL_LOG_FILE, 'a'); + collectorProcess = spawn(otelcolPath, ['--config', OTEL_CONFIG_FILE], { + stdio: ['ignore', collectorLogFd, collectorLogFd], + env: { ...process.env }, + }); + + console.log( + `โณ Waiting for OTEL collector to start (PID: ${collectorProcess.pid})...`, + ); + + try { + await waitForPort(4317); + console.log(`โ
OTEL collector started successfully on port 4317.`); + } catch (err) { + console.error(`๐ Error: OTEL collector failed to start on port 4317.`); + console.error(err.message); + if (collectorProcess && collectorProcess.pid) { + process.kill(collectorProcess.pid, 'SIGKILL'); + } + if (fileExists(OTEL_LOG_FILE)) { + console.error('๐ OTEL Collector Log Output:'); + console.error(fs.readFileSync(OTEL_LOG_FILE, 'utf-8')); + } + process.exit(1); + } + + collectorProcess.on('error', (err) => { + console.error(`${collectorProcess.spawnargs[0]} process error:`, err); + process.exit(1); + }); + + console.log(`\nโจ Local OTEL collector for GCP is running.`); + 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}`, + ); + 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}`, + ); + console.log(`\nPress Ctrl+C to exit.`); +} + +main(); |
