Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce 95% Coverage Requirement for lines and functions #24

Merged
merged 2 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -32,6 +31,7 @@
"prepublishOnly": "npm run compile",
"tdd": "yarn test -- --watch-extensions ts --watch",
"test": "nyc ts-mocha --timeout 10000 -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/**/*.ts'",
"test:coverage": "nyc --all --check-coverage --functions 95 --lines 95 ts-mocha --timeout 10000 -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/**/*.ts'",
"watch": "tsc -w"
},
"bugs": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand All @@ -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();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
awsOtelConfigurator = new AwsOpentelemetryConfigurator([]);
});

// Cleanup any span processors to avoid unit test conflicts
after(() => {
(awsOtelConfigurator as any).spanProcessors.forEach((spanProcessor: SpanProcessor) => {
spanProcessor.shutdown();
});
});

// The probability of this passing once without correct IDs is low, 20 times is inconceivable.
it('ProvideGenerateXrayIdsTest', () => {
const tracerProvider: NodeTracerProvider = new NodeTracerProvider(awsOtelConfigurator.configure());
Expand Down Expand Up @@ -170,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({});
Expand Down Expand Up @@ -262,6 +269,11 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
delete process.env.OTEL_METRIC_EXPORT_INTERVAL;
delete process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED;
}

// shut down exporters for test cleanup
spanProcessors.forEach(spanProcessor => {
spanProcessor.shutdown();
});
});

it('ApplicationSignalsExporterProviderTest', () => {
Expand All @@ -283,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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,52 @@
// SPDX-License-Identifier: Apache-2.0
// Modifications Copyright The OpenTelemetry Authors. Licensed under the Apache License 2.0 License.

import { NodeSDK } from '@opentelemetry/sdk-node';
import * as assert from 'assert';
import { spawnSync, SpawnSyncReturns } from 'child_process';
import expect from 'expect';
import { setAwsDefaultEnvironmentVariables } from '../src/register';

// The OpenTelemetry Authors code
// 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 = () => {};
try {
require('../src/register');
} catch (err: unknown) {
assert.fail(`require register unexpectedly failed: ${err}`);
}

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;
});

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';
process.env.OTEL_PROPAGATORS = 'customPropagators';
process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS = 'customDisabledInstrumentations';
setAwsDefaultEnvironmentVariables();
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', () => {
const proc: SpawnSyncReturns<Buffer> = spawnSync(
process.execPath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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'
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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}'
);
});
});
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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';

Expand Down Expand Up @@ -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);
});
});
Original file line number Diff line number Diff line change
@@ -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);
});
});
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"compile": "lerna run compile",
"prewatch": "npm run precompile",
"test": "lerna run test",
"test:coverage": "lerna run test:coverage",
"test:ci:changed": "lerna run test --since origin/main",
"test:browser": "lerna run test:browser --concurrency 1",
"test-all-versions": "npm run --if-present --workspaces test-all-versions",
Expand Down
Loading