@studion/infra-code-blocks
Version:
Studion common infra components
178 lines (177 loc) • 6.74 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OtelCollectorConfigBuilder = void 0;
const otlp_receiver_1 = require("./otlp-receiver");
class OtelCollectorConfigBuilder {
_receivers = {};
_processors = {};
_exporters = {};
_extensions = {};
_service = {
pipelines: {},
};
withOTLPReceiver(protocols = ['http']) {
if (!protocols.length) {
throw new Error('At least one OTLP receiver protocol should be provided');
}
const protocolsConfig = protocols.reduce((all, current) => {
const protocolConfig = otlp_receiver_1.Protocol[current];
if (!protocolConfig) {
throw new Error(`OTLP receiver protocol ${current} is not supported`);
}
return { ...all, [current]: protocolConfig };
}, {});
this._receivers.otlp = { protocols: protocolsConfig };
return this;
}
withBatchProcessor(name = 'batch', size = 8192, maxSize = 10000, timeout = '5s') {
this._processors[name] = {
send_batch_size: size,
send_batch_max_size: maxSize,
timeout,
};
return this;
}
withMemoryLimiterProcessor(checkInterval = '1s', limitPercentage = 80, spikeLimitPercentage = 15) {
this._processors.memory_limiter = {
check_interval: checkInterval,
limit_percentage: limitPercentage,
spike_limit_percentage: spikeLimitPercentage,
};
return this;
}
withAWSXRayExporter(region) {
this._exporters.awsxray = { region };
return this;
}
withCloudWatchLogsExporter(region, logGroupName, logStreamName, logRetention) {
this._exporters.awscloudwatchlogs = {
region,
log_group_name: logGroupName,
log_stream_name: logStreamName,
log_retention: logRetention,
};
return this;
}
withHealthCheckExtension(endpoint = '0.0.0.0:13133') {
this._extensions.health_check = { endpoint };
return this;
}
withPprofExtension(endpoint = '0.0.0.0:1777') {
this._extensions.pprof = { endpoint };
return this;
}
withAPS(namespace, endpoint, region) {
this._exporters.prometheusremotewrite = {
endpoint,
namespace,
auth: {
authenticator: 'sigv4auth',
},
};
this._extensions.sigv4auth = {
region,
service: 'aps',
};
return this;
}
withDebug(verbosity = 'detailed') {
this._exporters.debug = { verbosity };
return this;
}
withTelemetry(logLevel = 'error', metricsVerbosity = 'basic') {
this._service.telemetry = {
logs: { level: logLevel },
metrics: { level: metricsVerbosity },
};
return this;
}
withMetricsPipeline(receivers, processors, exporters) {
this._service.pipelines.metrics = {
receivers,
processors,
exporters,
};
return this;
}
withTracesPipeline(receivers, processors, exporters) {
this._service.pipelines.traces = {
receivers,
processors,
exporters,
};
return this;
}
withLogsPipeline(receivers, processors, exporters) {
this._service.pipelines.logs = {
receivers,
processors,
exporters,
};
return this;
}
withDefault({ prometheusNamespace, prometheusEndpoint, region, logGroupName, logStreamName, logRetention, }) {
return this.withOTLPReceiver(['http'])
.withMemoryLimiterProcessor()
.withBatchProcessor('batch/metrics')
.withBatchProcessor('batch/traces', 2000, 5000, '2s')
.withBatchProcessor('batch/logs', 1024, 5000, '2s')
.withAPS(prometheusNamespace, prometheusEndpoint, region)
.withAWSXRayExporter(region)
.withCloudWatchLogsExporter(region, logGroupName, logStreamName, logRetention)
.withHealthCheckExtension()
.withMetricsPipeline(['otlp'], ['memory_limiter', 'batch/metrics'], ['prometheusremotewrite'])
.withTracesPipeline(['otlp'], ['memory_limiter', 'batch/traces'], ['awsxray'])
.withLogsPipeline(['otlp'], ['memory_limiter', 'batch/logs'], ['awscloudwatchlogs'])
.withTelemetry();
}
build() {
this.validatePipelineComponents('metrics');
this.validatePipelineComponents('traces');
this.validatePipelineComponents('logs');
this.validatePipelineProcessorOrder('metrics');
this.validatePipelineProcessorOrder('traces');
this.validatePipelineProcessorOrder('logs');
// FIX: Fix type inference
const extensions = Object.keys(this._extensions);
if (extensions.length) {
this._service.extensions = extensions;
}
// TODO: Add schema validation (non-empty receivers, non-empty receiver protocols)
return {
receivers: this._receivers,
processors: this._processors,
exporters: this._exporters,
extensions: this._extensions,
service: this._service,
};
}
validatePipelineProcessorOrder(pipelineType) {
const pipeline = this._service.pipelines[pipelineType];
if (!pipeline)
return;
const { processors } = pipeline;
const memoryLimiterIndex = processors.findIndex(processor => processor === 'memory_limiter');
if (memoryLimiterIndex > 0) {
throw new Error(`memory_limiter processor is not the first processor in the ${pipelineType} pipeline.`);
}
}
validatePipelineComponents(pipelineType) {
this._service.pipelines[pipelineType]?.receivers.forEach(receiver => {
if (!this._receivers[receiver]) {
throw new Error(`Receiver '${receiver}' is used in ${pipelineType} pipeline but not defined`);
}
});
this._service.pipelines[pipelineType]?.processors.forEach(processor => {
if (!this._processors[processor]) {
throw new Error(`Processor '${processor}' is used in ${pipelineType} pipeline but not defined`);
}
});
this._service.pipelines[pipelineType]?.exporters.forEach(exporter => {
if (!this._exporters[exporter]) {
throw new Error(`Exporter '${exporter}' is used in ${pipelineType} pipeline but not defined`);
}
});
}
}
exports.OtelCollectorConfigBuilder = OtelCollectorConfigBuilder;