add --telemetry-outfile flag (#4689)

This commit is contained in:
smhendrickson
2025-07-23 17:48:24 -04:00
committed by GitHub
parent 209c8783b4
commit 9d3164621a
5 changed files with 133 additions and 6 deletions

View File

@@ -0,0 +1,89 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import * as fs from 'node:fs';
import { ExportResult, ExportResultCode } from '@opentelemetry/core';
import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
import { ReadableLogRecord, LogRecordExporter } from '@opentelemetry/sdk-logs';
import {
ResourceMetrics,
PushMetricExporter,
AggregationTemporality,
} from '@opentelemetry/sdk-metrics';
class FileExporter {
protected writeStream: fs.WriteStream;
constructor(filePath: string) {
this.writeStream = fs.createWriteStream(filePath, { flags: 'a' });
}
protected serialize(data: unknown): string {
return JSON.stringify(data, null, 2) + '\n';
}
shutdown(): Promise<void> {
return new Promise((resolve) => {
this.writeStream.end(resolve);
});
}
}
export class FileSpanExporter extends FileExporter implements SpanExporter {
export(
spans: ReadableSpan[],
resultCallback: (result: ExportResult) => void,
): void {
const data = spans.map((span) => this.serialize(span)).join('');
this.writeStream.write(data, (err) => {
resultCallback({
code: err ? ExportResultCode.FAILED : ExportResultCode.SUCCESS,
error: err || undefined,
});
});
}
}
export class FileLogExporter extends FileExporter implements LogRecordExporter {
export(
logs: ReadableLogRecord[],
resultCallback: (result: ExportResult) => void,
): void {
const data = logs.map((log) => this.serialize(log)).join('');
this.writeStream.write(data, (err) => {
resultCallback({
code: err ? ExportResultCode.FAILED : ExportResultCode.SUCCESS,
error: err || undefined,
});
});
}
}
export class FileMetricExporter
extends FileExporter
implements PushMetricExporter
{
export(
metrics: ResourceMetrics,
resultCallback: (result: ExportResult) => void,
): void {
const data = this.serialize(metrics);
this.writeStream.write(data, (err) => {
resultCallback({
code: err ? ExportResultCode.FAILED : ExportResultCode.SUCCESS,
error: err || undefined,
});
});
}
getPreferredAggregationTemporality(): AggregationTemporality {
return AggregationTemporality.CUMULATIVE;
}
async forceFlush(): Promise<void> {
return Promise.resolve();
}
}

View File

@@ -29,6 +29,11 @@ import { Config } from '../config/config.js';
import { SERVICE_NAME } from './constants.js';
import { initializeMetrics } from './metrics.js';
import { ClearcutLogger } from './clearcut-logger/clearcut-logger.js';
import {
FileLogExporter,
FileMetricExporter,
FileSpanExporter,
} from './file-exporters.js';
// For troubleshooting, set the log level to DiagLogLevel.DEBUG
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO);
@@ -74,19 +79,24 @@ export function initializeTelemetry(config: Config): void {
const otlpEndpoint = config.getTelemetryOtlpEndpoint();
const grpcParsedEndpoint = parseGrpcEndpoint(otlpEndpoint);
const useOtlp = !!grpcParsedEndpoint;
const telemetryOutfile = config.getTelemetryOutfile();
const spanExporter = useOtlp
? new OTLPTraceExporter({
url: grpcParsedEndpoint,
compression: CompressionAlgorithm.GZIP,
})
: new ConsoleSpanExporter();
: telemetryOutfile
? new FileSpanExporter(telemetryOutfile)
: new ConsoleSpanExporter();
const logExporter = useOtlp
? new OTLPLogExporter({
url: grpcParsedEndpoint,
compression: CompressionAlgorithm.GZIP,
})
: new ConsoleLogRecordExporter();
: telemetryOutfile
? new FileLogExporter(telemetryOutfile)
: new ConsoleLogRecordExporter();
const metricReader = useOtlp
? new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({
@@ -95,10 +105,15 @@ export function initializeTelemetry(config: Config): void {
}),
exportIntervalMillis: 10000,
})
: new PeriodicExportingMetricReader({
exporter: new ConsoleMetricExporter(),
exportIntervalMillis: 10000,
});
: telemetryOutfile
? new PeriodicExportingMetricReader({
exporter: new FileMetricExporter(telemetryOutfile),
exportIntervalMillis: 10000,
})
: new PeriodicExportingMetricReader({
exporter: new ConsoleMetricExporter(),
exportIntervalMillis: 10000,
});
sdk = new NodeSDK({
resource,