in scripts/telemetry_gcp.js [56:178]
async function main() {
console.log('โจ Starting Local Telemetry Exporter for Google Cloud โจ');
let collectorProcess;
let collectorLogFd;
const originalSandboxSetting = manageTelemetrySettings(
true,
'http://localhost:4317',
'gcp',
);
registerCleanup(
() => [collectorProcess].filter((p) => p), // Function to get processes
() => [collectorLogFd].filter((fd) => fd), // Function to get FDs
originalSandboxSetting,
);
const projectId = process.env.OTLP_GOOGLE_CLOUD_PROJECT;
if (!projectId) {
console.error(
'๐ Error: OTLP_GOOGLE_CLOUD_PROJECT environment variable is not exported.',
);
console.log(
' Please set it to your Google Cloud Project ID and try again.',
);
console.log(' `export OTLP_GOOGLE_CLOUD_PROJECT=your-project-id`');
process.exit(1);
}
console.log(`โ
Using OTLP 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๐ To send telemetry, run the Gemini CLI in a separate terminal window.',
);
console.log(`\n๐ Collector logs are being written to: ${OTEL_LOG_FILE}`);
console.log(
`๐ Tail collector logs in another terminal: tail -f ${OTEL_LOG_FILE}`,
);
console.log(`\n๐ View your telemetry data in Google Cloud Console:`);
console.log(
` - 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(
` - Traces: https://console.cloud.google.com/traces/list?project=${projectId}`,
);
console.log(`\nPress Ctrl+C to exit.`);
}