120 lines
3.2 KiB
JavaScript
120 lines
3.2 KiB
JavaScript
import {spawn} from 'node:child_process';
|
|
import {mkdirSync, writeFileSync} from 'node:fs';
|
|
import path from 'node:path';
|
|
|
|
const [, , rawMode = 'debug', ...args] = process.argv;
|
|
const mode = rawMode.trim();
|
|
const printConfigOnly = args.includes('--print-config');
|
|
|
|
const supportedModes = new Set(['debug', 'rider']);
|
|
if (!supportedModes.has(mode)) {
|
|
console.error('[otelcol] mode must be one of: debug, rider');
|
|
process.exit(1);
|
|
}
|
|
|
|
const otlpHttpEndpoint = readEnv('OTELCOL_OTLP_HTTP_ENDPOINT', '127.0.0.1:4318');
|
|
const otlpGrpcEndpoint = readEnv('OTELCOL_OTLP_GRPC_ENDPOINT', '127.0.0.1:4317');
|
|
const riderEndpoint = readEnv('RIDER_OTLP_GRPC_ENDPOINT', '127.0.0.1:17011');
|
|
const debugVerbosity = readEnv('OTELCOL_DEBUG_VERBOSITY', 'detailed');
|
|
const otelcolBin = readEnv('OTELCOL_BIN', 'otelcol-contrib');
|
|
|
|
const configText = buildConfig(mode);
|
|
const configDir = path.resolve('.codex-temp', 'otelcol');
|
|
const configPath = path.join(configDir, `genarrative-${mode}.yaml`);
|
|
mkdirSync(configDir, {recursive: true});
|
|
writeFileSync(configPath, configText, 'utf8');
|
|
|
|
console.log(`[otelcol] wrote ${configPath}`);
|
|
console.log(`[otelcol] receiving OTLP HTTP at http://${otlpHttpEndpoint}`);
|
|
console.log(`[otelcol] receiving OTLP gRPC at ${otlpGrpcEndpoint}`);
|
|
if (mode === 'rider') {
|
|
console.log(`[otelcol] forwarding traces/metrics/logs to Rider OTLP gRPC at ${riderEndpoint}`);
|
|
}
|
|
console.log(
|
|
'[otelcol] api-server env: GENARRATIVE_OTEL_ENABLED=true OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318'
|
|
);
|
|
|
|
if (printConfigOnly) {
|
|
console.log(configText);
|
|
process.exit(0);
|
|
}
|
|
|
|
const child = spawn(otelcolBin, ['--config', configPath], {
|
|
cwd: process.cwd(),
|
|
env: process.env,
|
|
stdio: 'inherit',
|
|
});
|
|
|
|
const stopChild = () => {
|
|
if (!child.killed) {
|
|
child.kill();
|
|
}
|
|
};
|
|
|
|
for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP']) {
|
|
process.on(signal, () => {
|
|
stopChild();
|
|
process.exit(130);
|
|
});
|
|
}
|
|
|
|
process.on('exit', stopChild);
|
|
|
|
child.on('error', (error) => {
|
|
console.error(`[otelcol] failed to start ${otelcolBin}: ${error.message}`);
|
|
console.error('[otelcol] install otelcol-contrib and make sure it is on PATH, or set OTELCOL_BIN.');
|
|
process.exit(1);
|
|
});
|
|
|
|
child.on('exit', (code, signal) => {
|
|
if (signal) {
|
|
console.error(`[otelcol] exited by signal: ${signal}`);
|
|
process.exit(1);
|
|
}
|
|
process.exit(code ?? 0);
|
|
});
|
|
|
|
function readEnv(key, fallback) {
|
|
const value = process.env[key]?.trim();
|
|
return value ? value : fallback;
|
|
}
|
|
|
|
function buildConfig(selectedMode) {
|
|
const exporters =
|
|
selectedMode === 'rider'
|
|
? ` otlp/rider:
|
|
endpoint: ${riderEndpoint}
|
|
tls:
|
|
insecure: true
|
|
debug:
|
|
verbosity: ${debugVerbosity}`
|
|
: ` debug:
|
|
verbosity: ${debugVerbosity}`;
|
|
|
|
const pipelineExporters = selectedMode === 'rider' ? '[otlp/rider, debug]' : '[debug]';
|
|
|
|
return `receivers:
|
|
otlp:
|
|
protocols:
|
|
grpc:
|
|
endpoint: ${otlpGrpcEndpoint}
|
|
http:
|
|
endpoint: ${otlpHttpEndpoint}
|
|
|
|
exporters:
|
|
${exporters}
|
|
|
|
service:
|
|
pipelines:
|
|
traces:
|
|
receivers: [otlp]
|
|
exporters: ${pipelineExporters}
|
|
metrics:
|
|
receivers: [otlp]
|
|
exporters: ${pipelineExporters}
|
|
logs:
|
|
receivers: [otlp]
|
|
exporters: ${pipelineExporters}
|
|
`;
|
|
}
|