Skip to content

Commit

Permalink
Merge branch 'main' into jacksonweber/sampler-without-exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
JacksonWeber authored Jan 24, 2024
2 parents 1d01797 + 0635ab1 commit e0bd102
Show file tree
Hide file tree
Showing 20 changed files with 194 additions and 107 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/

### :rocket: (Enhancement)

* feat(sdk-metrics): add constructor option to add metric readers [#4427](https://github.com/open-telemetry/opentelemetry-js/pull/4427) @pichlermarc
* deprecates `MeterProvider.addMetricReader()` please use the constructor option `readers` instead.

### :bug: (Bug Fix)

* fix(sdk-trace-base): ensure attribute value length limit is enforced on span creation [#4417](https://github.com/open-telemetry/opentelemetry-js/pull/4417) @pichlermarc
* fix(sdk-trace-base): Export processed spans while exporter failed [#4287](https://github.com/open-telemetry/opentelemetry-js/pull/4287) @Zirak

### :books: (Refine Doc)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ const testResource = new Resource({
cost: 112.12,
});

let meterProvider = new MeterProvider({ resource: testResource });

let reader = new TestMetricReader();
meterProvider.addMetricReader(reader);
let meterProvider = new MeterProvider({
resource: testResource,
readers: [reader],
});

let meter = meterProvider.getMeter('default', '0.0.1');

Expand All @@ -67,6 +68,7 @@ export async function collect() {
}

export function setUp() {
reader = new TestMetricReader();
meterProvider = new MeterProvider({
resource: testResource,
views: [
Expand All @@ -75,9 +77,8 @@ export function setUp() {
instrumentName: 'int-histogram',
}),
],
readers: [reader],
});
reader = new TestMetricReader();
meterProvider.addMetricReader(reader);
meter = meterProvider.getMeter('default', '0.0.1');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,24 @@ const defaultResource = Resource.default().merge(
})
);

let meterProvider = new MeterProvider({ resource: defaultResource });
let reader = new TestMetricReader();
meterProvider.addMetricReader(reader);
let meterProvider = new MeterProvider({
resource: defaultResource,
readers: [reader],
});
let meter = meterProvider.getMeter('default', '0.0.1');

export async function collect() {
return (await reader.collect())!;
}

export function setUp(views?: View[]) {
meterProvider = new MeterProvider({ resource: defaultResource, views });
reader = new TestMetricReader();
meterProvider.addMetricReader(reader);
meterProvider = new MeterProvider({
resource: defaultResource,
views,
readers: [reader],
});
meter = meterProvider.getMeter('default', '0.0.1');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ const testResource = new Resource({
cost: 112.12,
});

let meterProvider = new MeterProvider({ resource: testResource });

let reader = new TestMetricReader();
meterProvider.addMetricReader(reader);
let meterProvider = new MeterProvider({
resource: testResource,
readers: [reader],
});

let meter = meterProvider.getMeter('default', '0.0.1');

Expand All @@ -66,6 +67,7 @@ export async function collect() {
}

export function setUp() {
reader = new TestMetricReader();
meterProvider = new MeterProvider({
resource: testResource,
views: [
Expand All @@ -74,9 +76,8 @@ export function setUp() {
instrumentName: 'int-histogram',
}),
],
readers: [reader],
});
reader = new TestMetricReader();
meterProvider.addMetricReader(reader);
meter = meterProvider.getMeter('default', '0.0.1');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,9 @@ describe('PrometheusExporter', () => {

beforeEach(done => {
exporter = new PrometheusExporter({}, () => {
meterProvider = new MeterProvider();
meterProvider.addMetricReader(exporter);
meterProvider = new MeterProvider({
readers: [exporter],
});
meter = meterProvider.getMeter('test-prometheus', '1');
done();
});
Expand Down Expand Up @@ -533,8 +534,9 @@ describe('PrometheusExporter', () => {
let exporter: PrometheusExporter;

function setup(reader: PrometheusExporter) {
meterProvider = new MeterProvider();
meterProvider.addMetricReader(reader);
meterProvider = new MeterProvider({
readers: [exporter],
});

meter = meterProvider.getMeter('test-prometheus');
counter = meter.createCounter('counter');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ describe('PrometheusSerializer', () => {
instrumentName: '*',
}),
],
readers: [reader],
});
meterProvider.addMetricReader(reader);
const meter = meterProvider.getMeter('test');

const counter = meter.createCounter('test_total');
Expand Down Expand Up @@ -141,8 +141,8 @@ describe('PrometheusSerializer', () => {
instrumentName: '*',
}),
],
readers: [reader],
});
meterProvider.addMetricReader(reader);
const meter = meterProvider.getMeter('test');

const histogram = meter.createHistogram('test');
Expand Down Expand Up @@ -206,8 +206,8 @@ describe('PrometheusSerializer', () => {
instrumentName: '*',
}),
],
readers: [reader],
});
meterProvider.addMetricReader(reader);
const meter = meterProvider.getMeter('test');

const counter = meter.createCounter('test_total', {
Expand Down Expand Up @@ -261,8 +261,8 @@ describe('PrometheusSerializer', () => {
instrumentName: '*',
}),
],
readers: [reader],
});
meterProvider.addMetricReader(reader);
const meter = meterProvider.getMeter('test');

const counter = meter.createUpDownCounter('test_total', {
Expand Down Expand Up @@ -315,8 +315,8 @@ describe('PrometheusSerializer', () => {
instrumentName: '*',
}),
],
readers: [reader],
});
meterProvider.addMetricReader(reader);
const meter = meterProvider.getMeter('test');

const counter = meter.createUpDownCounter('test_total', {
Expand Down Expand Up @@ -369,8 +369,8 @@ describe('PrometheusSerializer', () => {
instrumentName: '*',
}),
],
readers: [reader],
});
meterProvider.addMetricReader(reader);
const meter = meterProvider.getMeter('test');

const histogram = meter.createHistogram('test', {
Expand Down Expand Up @@ -424,8 +424,8 @@ describe('PrometheusSerializer', () => {
instrumentName: '*',
}),
],
readers: [reader],
});
meterProvider.addMetricReader(reader);
const meter = meterProvider.getMeter('test');

const upDownCounter = meter.createUpDownCounter('test', {
Expand Down Expand Up @@ -474,8 +474,8 @@ describe('PrometheusSerializer', () => {
views: [
new View({ aggregation: new SumAggregation(), instrumentName: '*' }),
],
readers: [reader],
});
meterProvider.addMetricReader(reader);
const meter = meterProvider.getMeter('test');

const { unit, exportAll = false } = options;
Expand Down Expand Up @@ -563,8 +563,8 @@ describe('PrometheusSerializer', () => {
views: [
new View({ aggregation: new SumAggregation(), instrumentName: '*' }),
],
readers: [reader],
});
meterProvider.addMetricReader(reader);
const meter = meterProvider.getMeter('test');

const counter = meter.createUpDownCounter(name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,12 @@ const protocol = 'http';
const hostname = 'localhost';
const pathname = '/test';
const tracerProvider = new NodeTracerProvider();
const meterProvider = new MeterProvider();
const metricsMemoryExporter = new InMemoryMetricExporter(
AggregationTemporality.DELTA
);
const metricReader = new TestMetricReader(metricsMemoryExporter);
const meterProvider = new MeterProvider({ readers: [metricReader] });

meterProvider.addMetricReader(metricReader);
instrumentation.setTracerProvider(tracerProvider);
instrumentation.setMeterProvider(meterProvider);

Expand Down
9 changes: 5 additions & 4 deletions experimental/packages/opentelemetry-sdk-node/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,15 +356,16 @@ export class NodeSDK {
}

if (this._meterProviderConfig) {
const readers: MetricReader[] = [];
if (this._meterProviderConfig.reader) {
readers.push(this._meterProviderConfig.reader);
}
const meterProvider = new MeterProvider({
resource: this._resource,
views: this._meterProviderConfig?.views ?? [],
readers: readers,
});

if (this._meterProviderConfig.reader) {
meterProvider.addMetricReader(this._meterProviderConfig.reader);
}

this._meterProvider = meterProvider;

metrics.setGlobalMeterProvider(meterProvider);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ export abstract class BatchSpanProcessorBase<T extends BufferConfig>
const flush = () => {
this._isExporting = true;
this._flushOneBatch()
.then(() => {
.finally(() => {
this._isExporting = false;
if (this._finishedSpans.length > 0) {
this._clearTimer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,57 @@ describe('BatchSpanProcessorBase', () => {
});
});

it('should still export when previously failed', async () => {
// The scenario is made of several parts:
// 1. The exporter tries to export some spans
// 2. While it does so, more spans are processed
// 3. The exporter fails
// 4. Spans arriving during step 2 should be exported

let firstCall = true;
const fillingExportStub = sinon
.stub(exporter, 'export')
.callsFake((spans, cb) => {
// The first time export is called, add some spans to the processor.
// Any other time, call through. We don't simply restore the stub
// so we can count the calls with `sinon.assert`
if (!firstCall) {
return fillingExportStub.wrappedMethod.call(exporter, spans, cb);
}

// Step 2: During export, add another span
firstCall = false;
processSpan();

return fillingExportStub.wrappedMethod.call(exporter, spans, () => {
// Step 3: Mock failure
cb({
code: ExportResultCode.FAILED,
});
});
});

const clock = sinon.useFakeTimers();

// Step 1: Export a span
processSpan();
await clock.runAllAsync();

clock.restore();
fillingExportStub.restore();

// Step 4: Make sure all spans were processed
assert.equal(exporter['_finishedSpans'].length, 2);
assert.equal(processor['_finishedSpans'].length, 0);
sinon.assert.calledTwice(fillingExportStub);

function processSpan() {
const span = createSampledSpan('test');
processor.onStart(span, ROOT_CONTEXT);
processor.onEnd(span);
}
});

it('should wait for pending resource on flush', async () => {
const tracer = new BasicTracerProvider({
resource: new Resource(
Expand Down
13 changes: 13 additions & 0 deletions packages/sdk-metrics/src/MeterProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export interface MeterProviderOptions {
/** Resource associated with metric telemetry */
resource?: IResource;
views?: View[];
readers?: MetricReader[];
}

/**
Expand All @@ -54,6 +55,12 @@ export class MeterProvider implements IMeterProvider {
this._sharedState.viewRegistry.addView(view);
}
}

if (options?.readers != null && options.readers.length > 0) {
for (const metricReader of options.readers) {
this.addMetricReader(metricReader);
}
}
}

/**
Expand All @@ -77,7 +84,13 @@ export class MeterProvider implements IMeterProvider {
* Register a {@link MetricReader} to the meter provider. After the
* registration, the MetricReader can start metrics collection.
*
* <p> NOTE: {@link MetricReader} instances MUST be added before creating any instruments.
* A {@link MetricReader} instance registered later may receive no or incomplete metric data.
*
* @param metricReader the metric reader to be registered.
*
* @deprecated This method will be removed in SDK 2.0. Please use
* {@link MeterProviderOptions.readers} via the {@link MeterProvider} constructor instead
*/
addMetricReader(metricReader: MetricReader) {
const collector = new MetricCollector(this._sharedState, metricReader);
Expand Down
11 changes: 6 additions & 5 deletions packages/sdk-metrics/test/Instruments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -751,18 +751,19 @@ describe('Instruments', () => {
});

function setup() {
const meterProvider = new MeterProvider({ resource: defaultResource });
const deltaReader = new TestDeltaMetricReader();
const cumulativeReader = new TestMetricReader();
const meterProvider = new MeterProvider({
resource: defaultResource,
readers: [deltaReader, cumulativeReader],
});
const meter = meterProvider.getMeter(
defaultInstrumentationScope.name,
defaultInstrumentationScope.version,
{
schemaUrl: defaultInstrumentationScope.schemaUrl,
}
);
const deltaReader = new TestDeltaMetricReader();
meterProvider.addMetricReader(deltaReader);
const cumulativeReader = new TestMetricReader();
meterProvider.addMetricReader(cumulativeReader);

return {
meterProvider,
Expand Down
Loading

0 comments on commit e0bd102

Please sign in to comment.