Skip to content

Commit

Permalink
add validation tests for adot-js environment variable inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
jj22ee committed Oct 11, 2024
1 parent 032677f commit 6cbb86a
Showing 1 changed file with 209 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
import { Span, TraceFlags, Tracer } from '@opentelemetry/api';
import { OTLPMetricExporter as OTLPGrpcOTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
import { OTLPMetricExporter as OTLPHttpOTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
import { OTLPTraceExporter as OTLPGrpcTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
import { OTLPTraceExporter as OTLPHttpTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { OTLPTraceExporter as OTLPProtoTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { Resource } from '@opentelemetry/resources';
import { PushMetricExporter } from '@opentelemetry/sdk-metrics';
import { ReadableSpan, SpanProcessor } from '@opentelemetry/sdk-trace-base';
import { AlwaysOffSampler, ReadableSpan, SpanProcessor, TraceIdRatioBasedSampler } from '@opentelemetry/sdk-trace-base';
import {
AlwaysOnSampler,
NodeTracerProvider,
Expand Down Expand Up @@ -222,6 +225,16 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {

process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'False';
expect(AwsOpentelemetryConfigurator.isApplicationSignalsEnabled()).toBeFalsy();
process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'abcdefg';
expect(AwsOpentelemetryConfigurator.isApplicationSignalsEnabled()).toBeFalsy();
process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'True_abcdefg';
expect(AwsOpentelemetryConfigurator.isApplicationSignalsEnabled()).toBeFalsy();
process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'abcdefg_True';
expect(AwsOpentelemetryConfigurator.isApplicationSignalsEnabled()).toBeFalsy();
process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = '0';
expect(AwsOpentelemetryConfigurator.isApplicationSignalsEnabled()).toBeFalsy();
process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = '1';
expect(AwsOpentelemetryConfigurator.isApplicationSignalsEnabled()).toBeFalsy();
delete process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED;
expect(AwsOpentelemetryConfigurator.isApplicationSignalsEnabled()).toBeFalsy();
});
Expand Down Expand Up @@ -294,6 +307,9 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
});

it('ApplicationSignalsExporterProviderTest', () => {
const DEFAULT_OTEL_EXPORTER_OTLP_PROTOCOL = process.env.OTEL_EXPORTER_OTLP_PROTOCOL;
delete process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL;

// Check default protocol - HTTP, as specified by aws-distro-opentelemetry-node-autoinstrumentation's register.ts.
let exporter: PushMetricExporter = ApplicationSignalsExporterProvider.Instance.createExporter();
expect(exporter).toBeInstanceOf(OTLPHttpOTLPMetricExporter);
Expand All @@ -310,6 +326,61 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
exporter = ApplicationSignalsExporterProvider.Instance.createExporter();
expect(exporter).toBeInstanceOf(OTLPHttpOTLPMetricExporter);
expect('http://localhost:4316/v1/metrics').toEqual((exporter as any)._otlpExporter.url);

// If for some reason, the env var is undefined (it shouldn't), overwrite protocol to gRPC.
delete process.env.OTEL_EXPORTER_OTLP_PROTOCOL;
exporter = ApplicationSignalsExporterProvider.Instance.createExporter();
expect(exporter).toBeInstanceOf(OTLPGrpcOTLPMetricExporter);
expect('localhost:4315').toEqual((exporter as any)._otlpExporter.url);

// Expect invalid protocol to throw error.
process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'invalid_protocol';
expect(() => ApplicationSignalsExporterProvider.Instance.createExporter()).toThrow();

// Cleanup
process.env.OTEL_EXPORTER_OTLP_PROTOCOL = DEFAULT_OTEL_EXPORTER_OTLP_PROTOCOL;

// Repeat tests using OTEL_EXPORTER_OTLP_METRICS_PROTOCOL environment variable instead

// Check default protocol - HTTP, as specified by aws-distro-opentelemetry-node-autoinstrumentation's register.ts.
exporter = ApplicationSignalsExporterProvider.Instance.createExporter();
expect(exporter).toBeInstanceOf(OTLPHttpOTLPMetricExporter);
expect('http://localhost:4316/v1/metrics').toEqual((exporter as any)._otlpExporter.url);

// Overwrite protocol to gRPC.
process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = 'grpc';
exporter = ApplicationSignalsExporterProvider.Instance.createExporter();
expect(exporter).toBeInstanceOf(OTLPGrpcOTLPMetricExporter);
expect('localhost:4315').toEqual((exporter as any)._otlpExporter.url);

// Overwrite protocol back to HTTP.
process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = 'http/protobuf';
exporter = ApplicationSignalsExporterProvider.Instance.createExporter();
expect(exporter).toBeInstanceOf(OTLPHttpOTLPMetricExporter);
expect('http://localhost:4316/v1/metrics').toEqual((exporter as any)._otlpExporter.url);

// Expect invalid protocol to throw error.
process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = 'invalid_protocol';
expect(() => ApplicationSignalsExporterProvider.Instance.createExporter()).toThrow();

// Test custom URLs via OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT
process.env.OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT = 'my_custom_endpoint';

// Overwrite protocol to gRPC, export to url "my_custom_endpoint"
process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = 'grpc';
exporter = ApplicationSignalsExporterProvider.Instance.createExporter();
expect(exporter).toBeInstanceOf(OTLPGrpcOTLPMetricExporter);
expect('my_custom_endpoint').toEqual((exporter as any)._otlpExporter.url);

// Overwrite protocol back to HTTP, export to url "my_custom_endpoint"
process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = 'http/protobuf';
exporter = ApplicationSignalsExporterProvider.Instance.createExporter();
expect(exporter).toBeInstanceOf(OTLPHttpOTLPMetricExporter);
expect('my_custom_endpoint').toEqual((exporter as any)._otlpExporter.url);

// Cleanup
delete process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL;
delete process.env.OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT;
});

it('tests getSamplerProbabilityFromEnv() ratio out of bounds', () => {
Expand Down Expand Up @@ -411,4 +482,141 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
expect(undefined).toEqual(process.env.OTEL_TRACES_EXPORTER);
expect(undefined).toEqual(process.env.OTEL_METRICS_EXPORTER);
}

it('OtelTracesSamplerInputValidationTest', () => {
let config;

process.env.OTEL_TRACES_SAMPLER = 'always_off';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(config.sampler).toBeInstanceOf(AlwaysOffSampler);

process.env.OTEL_TRACES_SAMPLER = 'always_on';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(config.sampler).toBeInstanceOf(AlwaysOnSampler);

process.env.OTEL_TRACES_SAMPLER = 'parentbased_always_off';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(config.sampler).toBeInstanceOf(ParentBasedSampler);

process.env.OTEL_TRACES_SAMPLER = 'parentbased_always_on';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(config.sampler).toBeInstanceOf(ParentBasedSampler);

process.env.OTEL_TRACES_SAMPLER = 'parentbased_traceidratio';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(config.sampler).toBeInstanceOf(ParentBasedSampler);

process.env.OTEL_TRACES_SAMPLER = 'traceidratio';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(config.sampler).toBeInstanceOf(TraceIdRatioBasedSampler);
process.env.OTEL_TRACES_SAMPLER_ARG = '0.5';
config = new AwsOpentelemetryConfigurator([]).configure();
expect((config.sampler as any)._ratio).toEqual(0.5);
process.env.OTEL_TRACES_SAMPLER_ARG = '2';
config = new AwsOpentelemetryConfigurator([]).configure();
expect((config.sampler as any)._ratio).toEqual(1);
process.env.OTEL_TRACES_SAMPLER_ARG = '-3';
config = new AwsOpentelemetryConfigurator([]).configure();
expect((config.sampler as any)._ratio).toEqual(1);
process.env.OTEL_TRACES_SAMPLER_ARG = 'abc';
config = new AwsOpentelemetryConfigurator([]).configure();
expect((config.sampler as any)._ratio).toEqual(1);

process.env.OTEL_TRACES_SAMPLER = 'xray';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(config.sampler).toBeInstanceOf(AwsXRayRemoteSampler);

// Invalid sampler cases
process.env.OTEL_TRACES_SAMPLER = 'invalid_sampler';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(config.sampler).toBeInstanceOf(AlwaysOnSampler);

process.env.OTEL_TRACES_SAMPLER = '123';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(config.sampler).toBeInstanceOf(AlwaysOnSampler);

// Cleanup
delete process.env.OTEL_TRACES_SAMPLER;
});

it('OtelTraceExporterInputValidationTest - OTEL_TRACES_EXPORTER*', () => {
process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'true';
let config;

process.env.OTEL_TRACES_EXPORTER = 'otlp';
config = new AwsOpentelemetryConfigurator([]).configure();
expect((config.spanProcessors as any)[0]._exporter.delegate).toBeInstanceOf(OTLPProtoTraceExporter);
expect(config.spanProcessors?.length).toEqual(3);

process.env.OTEL_TRACES_EXPORTER = 'invalid_exporter_name';
config = new AwsOpentelemetryConfigurator([]).configure();
expect((config.spanProcessors as any)[0]).toBeInstanceOf(AttributePropagatingSpanProcessor);
expect((config.spanProcessors as any)[1]).toBeInstanceOf(AwsSpanMetricsProcessor);
expect(config.spanProcessors?.length).toEqual(2);

// Cleanup
delete process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED;
delete process.env.OTEL_TRACES_EXPORTER;
});

it('ResourceDetectorInputValidationTest', () => {
let config;
process.env.OTEL_SERVICE_NAME = 'test_service_name';

// Default 2 attributes detected in test environment
process.env.OTEL_NODE_RESOURCE_DETECTORS = 'container';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(Object.keys((config.resource as any).attributes).length).toEqual(2);
expect((config.resource as any).attributes['service.name']).toEqual('test_service_name');
expect((config.resource as any).attributes['telemetry.auto.version'].endsWith('-aws')).toBeTruthy();

// Still default 2 attributes detected given invalid resource detectors
process.env.OTEL_NODE_RESOURCE_DETECTORS = 'invalid_detector_1,invalid_detector_2';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(Object.keys((config.resource as any).attributes).length).toEqual(2);
expect((config.resource as any).attributes['service.name']).toEqual('test_service_name');
expect((config.resource as any).attributes['telemetry.auto.version'].endsWith('-aws')).toBeTruthy();

// Still default 2 attributes detected given mix of valid and invalid resource detectors
process.env.OTEL_NODE_RESOURCE_DETECTORS = 'container,invalid_detector_1,invalid_detector_2';
config = new AwsOpentelemetryConfigurator([]).configure();
expect(Object.keys((config.resource as any).attributes).length).toEqual(2);
expect((config.resource as any).attributes['service.name']).toEqual('test_service_name');
expect((config.resource as any).attributes['telemetry.auto.version'].endsWith('-aws')).toBeTruthy();

// Cleanup
delete process.env.OTEL_SERVICE_NAME;
delete process.env.OTEL_NODE_RESOURCE_DETECTORS;
});

it('AwsSpanProcessorProviderTest', () => {
let spanExporter;

delete process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL;
spanExporter = AwsSpanProcessorProvider.configureOtlp();
expect(spanExporter).toBeInstanceOf(OTLPProtoTraceExporter);

process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'grpc';
spanExporter = AwsSpanProcessorProvider.configureOtlp();
expect(spanExporter).toBeInstanceOf(OTLPGrpcTraceExporter);

process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'http/json';
spanExporter = AwsSpanProcessorProvider.configureOtlp();
expect(spanExporter).toBeInstanceOf(OTLPHttpTraceExporter);

process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'http/protobuf';
spanExporter = AwsSpanProcessorProvider.configureOtlp();
expect(spanExporter).toBeInstanceOf(OTLPProtoTraceExporter);

process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'udp';
spanExporter = AwsSpanProcessorProvider.configureOtlp();
expect(spanExporter).toBeInstanceOf(OTLPUdpSpanExporter);

process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'invalid_protocol';
spanExporter = AwsSpanProcessorProvider.configureOtlp();
expect(spanExporter).toBeInstanceOf(OTLPProtoTraceExporter);

// Cleanup
delete process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL;
});
});

0 comments on commit 6cbb86a

Please sign in to comment.