🪵 feat: Add OpenTelemetry Logs Pipeline via Winston Bridge (#15565)

Exports application logs as OTel log records when OTEL_LOGS_ENABLED=true,
correlated with the active trace, and gates every signal explicitly so a
disabled signal never falls back to the SDK's default OTLP exporter.
Verified end to end over OTLP/gRPC against an in-process collector.
This commit is contained in:
Danny Avila 2026-09-03 21:16:09 -04:00 • committed by GitHub
parent aec2121923
commit a6cf61abcf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 533 additions and 100 deletions

View file

@ -62,6 +62,7 @@
"@opentelemetry/resources": "^2.6.1",
"@opentelemetry/sdk-node": "^0.221.0",
"@opentelemetry/semantic-conventions": "^1.39.0",
"@opentelemetry/winston-transport": "^0.28.0",
"@redis/client": "5.10.0",
"@smithy/node-http-handler": "^4.4.5",
"ai-tokenizer": "^1.0.6",

View file

@ -5,7 +5,9 @@ function isTruthy(value) {
}
function isTelemetryEnabled() {
return isTruthy(process.env.OTEL_TRACING_ENABLED) && !isTruthy(process.env.OTEL_SDK_DISABLED);
const signalEnabled =
isTruthy(process.env.OTEL_TRACING_ENABLED) || isTruthy(process.env.OTEL_LOGS_ENABLED);
return signalEnabled && !isTruthy(process.env.OTEL_SDK_DISABLED);
}
if (isTelemetryEnabled()) {

View file

@ -4,6 +4,7 @@ describe('telemetry bootstrap', () => {
beforeEach(() => {
jest.resetModules();
process.env = { ...originalEnv };
delete process.env.OTEL_LOGS_ENABLED;
delete process.env.OTEL_SDK_DISABLED;
delete process.env.OTEL_TRACING_ENABLED;
jest.doMock('dotenv', () => ({
@ -34,6 +35,7 @@ describe('telemetry bootstrap', () => {
});
it('does not load OpenTelemetry packages when the SDK is disabled', () => {
process.env.OTEL_LOGS_ENABLED = 'true';
process.env.OTEL_SDK_DISABLED = 'true';
process.env.OTEL_TRACING_ENABLED = 'true';
jest.doMock(
@ -88,4 +90,28 @@ describe('telemetry bootstrap', () => {
expect(telemetry.enabled).toBe(false);
expect(telemetry.status).toBe('failed');
});
it('initializes telemetry when only logs are enabled', () => {
process.env.OTEL_LOGS_ENABLED = 'true';
const initializeTelemetry = jest.fn(() => ({
enabled: true,
status: 'started',
shutdown: jest.fn(),
}));
jest.doMock(
'@librechat/api/telemetry',
() => ({
initializeTelemetry,
telemetryMiddleware: jest.fn(),
telemetryErrorMiddleware: jest.fn(),
}),
{ virtual: true },
);
const telemetry = require('./telemetry');
expect(initializeTelemetry).toHaveBeenCalledTimes(1);
expect(telemetry.enabled).toBe(true);
expect(telemetry.status).toBe('started');
});
});