diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index e2cf0cc..40fd3d0 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -39,7 +39,7 @@ jobs: - name: Compile all NPM projects run: npm run compile - name: Unit tests (Full) - run: npm run test + run: npm run test:coverage - name: Report Coverage if: ${{ matrix.code-coverage && !cancelled()}} uses: codecov/codecov-action@v4 diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/package.json b/aws-distro-opentelemetry-node-autoinstrumentation/package.json index 8765020..eab2d72 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/package.json +++ b/aws-distro-opentelemetry-node-autoinstrumentation/package.json @@ -17,7 +17,6 @@ "main": "build/src/index.js", "types": "build/src/index.d.ts", "exports": { - ".": "./build/src/index.js", "./register": "./build/src/register.js" }, "repository": "aws-observability/aws-otel-js-instrumentation", diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/src/sampler/aws-xray-remote-sampler.ts b/aws-distro-opentelemetry-node-autoinstrumentation/src/sampler/aws-xray-remote-sampler.ts index 46a30a5..41b77bf 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/src/sampler/aws-xray-remote-sampler.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/src/sampler/aws-xray-remote-sampler.ts @@ -54,7 +54,7 @@ export class AwsXRayRemoteSampler implements Sampler { this.awsProxyEndpoint = samplerConfig.endpoint ? samplerConfig.endpoint : DEFAULT_AWS_PROXY_ENDPOINT; this.fallbackSampler = new ParentBasedSampler({ root: new FallbackSampler() }); - this.clientId = this.generateClientId(); + this.clientId = AwsXRayRemoteSampler.generateClientId(); this.ruleCache = new RuleCache(samplerConfig.resource); this.samplingClient = new AwsXraySamplingClient(this.awsProxyEndpoint, this.samplerDiag); @@ -202,7 +202,7 @@ export class AwsXRayRemoteSampler implements Sampler { } } - private generateClientId(): string { + private static generateClientId(): string { const hexChars: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; const clientIdArray: string[] = []; for (let _: number = 0; _ < 24; _ += 1) { diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/always-record-sampler.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/always-record-sampler.test.ts index 9287f4e..544c88f 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/test/always-record-sampler.test.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/always-record-sampler.test.ts @@ -37,6 +37,11 @@ describe('AlwaysRecordSamplerTest', () => { it('testDropSamplingDecision', () => { validateShouldSample(SamplingDecision.NOT_RECORD, SamplingDecision.RECORD); }); + + it('testCreateAlwaysRecordSamplerThrows', () => { + expect(() => AlwaysRecordSampler.create(null as unknown as Sampler)).toThrow(); + expect(() => AlwaysRecordSampler.create(undefined as unknown as Sampler)).toThrow(); + }); }); function validateShouldSample(rootDecision: SamplingDecision, expectedDecision: SamplingDecision): void { diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/attribute-propagating-span-processor-builder.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/attribute-propagating-span-processor-builder.test.ts index 3f56bdb..a622406 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/test/attribute-propagating-span-processor-builder.test.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/attribute-propagating-span-processor-builder.test.ts @@ -1,11 +1,11 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import { AttributePropagatingSpanProcessor } from '../src/attribute-propagating-span-processor'; -import { AttributePropagatingSpanProcessorBuilder } from '../src/attribute-propagating-span-processor-builder'; -import expect from 'expect'; import { ReadableSpan, Span } from '@opentelemetry/sdk-trace-base'; +import expect from 'expect'; import * as sinon from 'sinon'; +import { AttributePropagatingSpanProcessor } from '../src/attribute-propagating-span-processor'; +import { AttributePropagatingSpanProcessorBuilder } from '../src/attribute-propagating-span-processor-builder'; describe('AttributePropagatingSpanProcessorBuilderTest', () => { it('BasicTest', () => { @@ -23,4 +23,11 @@ describe('AttributePropagatingSpanProcessorBuilderTest', () => { expect((spanProcessor as any).propagationDataExtractor(sinon.createStubInstance(Span))).toEqual('test'); expect((spanProcessor as any).attributesKeysToPropagate).toEqual(['test']); }); + + it('throws errors when expected to', () => { + const builder: AttributePropagatingSpanProcessorBuilder = AttributePropagatingSpanProcessorBuilder.create(); + expect(() => builder.setPropagationDataExtractor(undefined as any)).toThrow(); + expect(() => builder.setPropagationDataKey(undefined as any)).toThrow(); + expect(() => builder.setAttributesKeysToPropagate(undefined as any)).toThrow(); + }); }); diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-opentelemetry-configurator.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-opentelemetry-configurator.test.ts index a6081f7..3022e2a 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-opentelemetry-configurator.test.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-opentelemetry-configurator.test.ts @@ -177,7 +177,7 @@ describe('AwsOpenTelemetryConfiguratorTest', () => { const tmp = (AwsXraySamplingClient.prototype as any).makeSamplingRequest; (AwsXraySamplingClient.prototype as any).makeSamplingRequest = ( - endpoint: string, + url: string, callback: (responseObject: GetSamplingRulesResponse) => void ) => { callback({}); @@ -295,6 +295,24 @@ describe('AwsOpenTelemetryConfiguratorTest', () => { expect('http://localhost:4316/v1/metrics').toEqual((exporter as any)._otlpExporter.url); }); + it('tests getSamplerProbabilityFromEnv() ratio out of bounds', () => { + process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'True'; + process.env.OTEL_TRACES_SAMPLER = 'traceidratio'; + process.env.OTEL_TRACES_SAMPLER_ARG = '105'; + awsOtelConfigurator = new AwsOpentelemetryConfigurator([]); + delete process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED; + delete process.env.OTEL_TRACES_SAMPLER_ARG; + }); + + it('tests getSamplerProbabilityFromEnv() ratio not a number', () => { + process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'True'; + process.env.OTEL_TRACES_SAMPLER = 'traceidratio'; + process.env.OTEL_TRACES_SAMPLER_ARG = 'abc'; + awsOtelConfigurator = new AwsOpentelemetryConfigurator([]); + delete process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED; + delete process.env.OTEL_TRACES_SAMPLER_ARG; + }); + function validateConfiguratorEnviron() { // Set by register.ts expect('http/protobuf').toEqual(process.env.OTEL_EXPORTER_OTLP_PROTOCOL); diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/register.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/register.test.ts index d4a2c2f..da61fac 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/test/register.test.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/register.test.ts @@ -12,30 +12,30 @@ import { setAwsDefaultEnvironmentVariables } from '../src/register'; // Extend register.test.ts functionality to also test exported span with Application Signals enabled describe('Register', function () { it('Requires without error', () => { - const originalPrototypeStart = NodeSDK.prototype.start - NodeSDK.prototype.start = () => {} + const originalPrototypeStart = NodeSDK.prototype.start; + NodeSDK.prototype.start = () => {}; try { require('../src/register'); - } catch(err: unknown) { + } catch (err: unknown) { assert.fail(`require register unexpectedly failed: ${err}`); } - NodeSDK.prototype.start = originalPrototypeStart - }) + NodeSDK.prototype.start = originalPrototypeStart; + }); it('Tests AWS Default Environment Variables', () => { this.beforeEach(() => { - delete process.env.OTEL_EXPORTER_OTLP_PROTOCOL - delete process.env.OTEL_PROPAGATORS - delete process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS - }) + delete process.env.OTEL_EXPORTER_OTLP_PROTOCOL; + delete process.env.OTEL_PROPAGATORS; + delete process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS; + }); it('sets AWS Default Environment Variables', () => { setAwsDefaultEnvironmentVariables(); expect(process.env.OTEL_EXPORTER_OTLP_PROTOCOL).toEqual('http/protobuf'); expect(process.env.OTEL_PROPAGATORS).toEqual('xray,tracecontext,b3,b3multi'); expect(process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS).toEqual('fs'); - }) + }); it('Does not set AWS Default Environment Variables', () => { process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'customProtocol'; @@ -45,7 +45,7 @@ describe('Register', function () { expect(process.env.OTEL_EXPORTER_OTLP_PROTOCOL).toEqual('customProtocol'); expect(process.env.OTEL_PROPAGATORS).toEqual('customPropagators'); expect(process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS).toEqual('customDisabledInstrumentations'); - }) + }); }); it('can load auto instrumentation from command line', () => { diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/aws-xray-remote-sampler.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/aws-xray-remote-sampler.test.ts index 6464497..ca20537 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/aws-xray-remote-sampler.test.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/aws-xray-remote-sampler.test.ts @@ -191,4 +191,10 @@ describe('AwsXrayRemoteSampler', () => { }, 2000); }, 100); }); + + it('generates valid ClientId', () => { + const clientId: string = (AwsXRayRemoteSampler as any).generateClientId(); + const match: RegExpMatchArray | null = clientId.match(/[0-9a-z]{24}/g); + expect(match).not.toBeNull(); + }); }); diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/fallback-sampler.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/fallback-sampler.test.ts index 82a6946..17ff7de 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/fallback-sampler.test.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/fallback-sampler.test.ts @@ -127,4 +127,10 @@ describe('FallBackSampler', () => { } expect(sampled).toEqual(1); }); + + it('toString()', () => { + expect(new FallbackSampler().toString()).toEqual( + 'FallbackSampler{fallback sampling with sampling config of 1 req/sec and 5% of additional requests' + ); + }); }); diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/rate-limiting-sampler.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/rate-limiting-sampler.test.ts index 6d9bd33..781907d 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/rate-limiting-sampler.test.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/rate-limiting-sampler.test.ts @@ -136,4 +136,10 @@ describe('RateLimitingSampler', () => { } expect(sampled).toEqual(1); }); + + it('toString()', () => { + expect(new RateLimitingSampler(123).toString()).toEqual( + 'RateLimitingSampler{rate limiting sampling with sampling config of 123 req/sec and 0% of additional requests}' + ); + }); }); diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/sampling-rule-applier.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/sampling-rule-applier.test.ts index dfa4971..2aa0bb4 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/sampling-rule-applier.test.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/sampling-rule-applier.test.ts @@ -1,7 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import { expect } from 'expect'; import { Attributes } from '@opentelemetry/api/build/src/common/Attributes'; import { Resource } from '@opentelemetry/resources'; import { @@ -13,6 +12,7 @@ import { SEMRESATTRS_CLOUD_PLATFORM, SEMRESATTRS_SERVICE_NAME, } from '@opentelemetry/semantic-conventions'; +import { expect } from 'expect'; import { SamplingRule } from '../../src/sampler/sampling-rule'; import { SamplingRuleApplier } from '../../src/sampler/sampling-rule-applier'; @@ -184,4 +184,33 @@ describe('SamplingRuleApplier', () => { expect(ruleApplier.matches(attributes, new Resource({}))).toEqual(true); expect(ruleApplier.matches({}, new Resource({}))).toEqual(true); }); + + it('testApplierMatchesWithHttpUrlWithHttpTargetUndefined', () => { + const ruleApplier = new SamplingRuleApplier( + new SamplingRule({ + Attributes: {}, + FixedRate: 0.11, + HTTPMethod: '*', + Host: '*', + Priority: 20, + ReservoirSize: 1, + ResourceARN: '*', + RuleARN: 'arn:aws:xray:us-east-1:999999999999:sampling-rule/test', + RuleName: 'test', + ServiceName: '*', + ServiceType: '*', + URLPath: '/somerandompath', + Version: 1, + }) + ); + + const attributes: Attributes = { + [SEMATTRS_HTTP_URL]: 'https://somerandomurl.com/somerandompath', + }; + const resource = new Resource({}); + + expect(ruleApplier.matches(attributes, resource)).toEqual(true); + expect(ruleApplier.matches(attributes, Resource.EMPTY)).toEqual(true); + expect(ruleApplier.matches(attributes, new Resource({}))).toEqual(true); + }); }); diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/statistics.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/statistics.test.ts new file mode 100644 index 0000000..7f1b8d3 --- /dev/null +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/sampler/statistics.test.ts @@ -0,0 +1,18 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { expect } from 'expect'; +import { Statistics } from '../../src/sampler/statistics'; + +describe('Statistics', () => { + it('construct statistics and get statistics', () => { + const statistics = new Statistics(12, 3456, 7); + expect(statistics.RequestCount).toEqual(12); + expect(statistics.SampleCount).toEqual(3456); + expect(statistics.BorrowCount).toEqual(7); + const obtainedStatistics = statistics.getStatistics(); + expect(obtainedStatistics.RequestCount).toEqual(12); + expect(obtainedStatistics.SampleCount).toEqual(3456); + expect(obtainedStatistics.BorrowCount).toEqual(7); + }); +});