-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #550 from myrotvorets/logs-metrics
Add support for metrics and logs; remove legacy code
- Loading branch information
Showing
12 changed files
with
692 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { diag } from '@opentelemetry/api'; | ||
import { getEnv, getEnvWithoutDefaults } from '@opentelemetry/core'; | ||
import { OTLPLogExporter as OTLPGrpcLogExporter } from '@opentelemetry/exporter-logs-otlp-grpc'; | ||
import { OTLPLogExporter as OTLPHttpLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; | ||
import { OTLPLogsExporter as OTLPProtoLogExporter } from '@opentelemetry/exporter-logs-otlp-proto'; | ||
import { type LogRecordExporter, type LogRecordProcessor, SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs'; | ||
import { filterBlanksAndNulls } from './utils.mjs'; | ||
|
||
export class LogsConfigurator { | ||
private readonly _processor: LogRecordProcessor | undefined; | ||
|
||
public constructor() { | ||
const env = process.env; | ||
let exporters = filterBlanksAndNulls(Array.from(new Set((env.OTEL_LOGS_EXPORTER ?? '').split(',')))); | ||
|
||
if (exporters.length === 0) { | ||
exporters = ['otlp']; | ||
} else if (exporters[0] === 'none' && exporters.length === 1) { | ||
diag.info('Logs exporting is disabled.'); | ||
} | ||
|
||
for (const value of exporters) { | ||
const processor = LogsConfigurator.tryCreateLogProcessor(value); | ||
|
||
if (processor) { | ||
this._processor = processor; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
public get processor(): LogRecordProcessor | undefined { | ||
return this._processor; | ||
} | ||
|
||
/** | ||
* @see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection | ||
*/ | ||
protected static getOtlpProtocol(): string { | ||
const parsedEnvValues = getEnvWithoutDefaults(); | ||
const env = getEnv(); | ||
|
||
return ( | ||
parsedEnvValues.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL ?? | ||
parsedEnvValues.OTEL_EXPORTER_OTLP_PROTOCOL ?? | ||
env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL // It will have a default value, no need to fall back to OTEL_EXPORTER_OTLP_PROTOCOL | ||
); | ||
} | ||
|
||
/** | ||
* @see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection | ||
*/ | ||
protected static configureOtlp(): LogRecordExporter | undefined { | ||
const protocol = LogsConfigurator.getOtlpProtocol(); | ||
|
||
switch (protocol) { | ||
case 'grpc': | ||
return new OTLPGrpcLogExporter(); | ||
|
||
case 'http/json': | ||
return new OTLPHttpLogExporter(); | ||
|
||
case 'http/protobuf': | ||
return new OTLPProtoLogExporter(); | ||
|
||
default: | ||
diag.warn(`Unsupported OTLP logs protocol: ${protocol}.`); | ||
return undefined; | ||
} | ||
} | ||
|
||
protected static tryCreateLogProcessor(name: string): LogRecordProcessor | undefined { | ||
switch (name) { | ||
case 'otlp': { | ||
const exporter = LogsConfigurator.configureOtlp(); | ||
return exporter ? new SimpleLogRecordProcessor(exporter) : undefined; | ||
} | ||
|
||
case 'none': | ||
return undefined; | ||
|
||
default: | ||
diag.warn(`Unsupported logs exporter: ${name}.`); | ||
return undefined; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { diag } from '@opentelemetry/api'; | ||
import { getEnv, getEnvWithoutDefaults } from '@opentelemetry/core'; | ||
import { OTLPMetricExporter as OTLPGrpcMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc'; | ||
import { OTLPMetricExporter as OTLPHttpMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'; | ||
import { OTLPMetricExporter as OTLPProtoMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto'; | ||
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus'; | ||
import { type MetricReader, PeriodicExportingMetricReader, type PushMetricExporter } from '@opentelemetry/sdk-metrics'; | ||
import { filterBlanksAndNulls } from './utils.mjs'; | ||
|
||
export class MetricsConfigurator { | ||
private readonly _reader: MetricReader | undefined; | ||
|
||
public constructor() { | ||
const env = process.env; | ||
let exporters = filterBlanksAndNulls(Array.from(new Set((env.OTEL_METRICS_EXPORTER ?? '').split(',')))); | ||
|
||
if (exporters.length === 0) { | ||
exporters = ['otlp']; | ||
} else if (exporters[0] === 'none' && exporters.length === 1) { | ||
diag.info('Metrics exporting is disabled.'); | ||
} | ||
|
||
for (const value of exporters) { | ||
const reader = MetricsConfigurator.tryCreateReader(value); | ||
|
||
if (reader) { | ||
this._reader = reader; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
public get reader(): MetricReader | undefined { | ||
return this._reader; | ||
} | ||
|
||
/** | ||
* @see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection | ||
*/ | ||
protected static getOtlpProtocol(): string { | ||
const parsedEnvValues = getEnvWithoutDefaults(); | ||
const env = getEnv(); | ||
|
||
return ( | ||
parsedEnvValues.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL ?? | ||
parsedEnvValues.OTEL_EXPORTER_OTLP_PROTOCOL ?? | ||
env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL // It will have a default value, no need to fall back to OTEL_EXPORTER_OTLP_PROTOCOL | ||
); | ||
} | ||
|
||
/** | ||
* @see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection | ||
*/ | ||
protected static configureOtlp(): PushMetricExporter | undefined { | ||
const protocol = MetricsConfigurator.getOtlpProtocol(); | ||
|
||
switch (protocol) { | ||
case 'grpc': | ||
return new OTLPGrpcMetricExporter(); | ||
|
||
case 'http/json': | ||
return new OTLPHttpMetricExporter(); | ||
|
||
case 'http/protobuf': | ||
return new OTLPProtoMetricExporter(); | ||
|
||
default: | ||
diag.warn(`Unsupported OTLP metrics protocol: ${protocol}.`); | ||
return undefined; | ||
} | ||
} | ||
|
||
protected static tryCreateReader(name: string): MetricReader | undefined { | ||
switch (name) { | ||
case 'otlp': { | ||
const exporter = MetricsConfigurator.configureOtlp(); | ||
return exporter ? new PeriodicExportingMetricReader({ exporter }) : undefined; | ||
} | ||
|
||
case 'prometheus': | ||
return new PrometheusExporter(); | ||
|
||
case 'none': | ||
return undefined; | ||
|
||
default: | ||
diag.warn(`Unsupported metrics exporter: ${name}.`); | ||
return undefined; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export function filterBlanksAndNulls(list: string[]): string[] { | ||
return list.map((item) => item.trim()).filter((s) => s !== 'null' && s !== ''); | ||
} |
Oops, something went wrong.