From 27ce0868aa4e66cff448a286c6851d1c0b2926aa Mon Sep 17 00:00:00 2001
From: legendecas <legendecas@gmail.com>
Date: Tue, 8 Mar 2022 15:59:42 +0800
Subject: [PATCH 1/5] refactor(sdk-metrics-base): meter shared states

---
 .../src/Meter.ts                              |  71 ++----------
 .../src/state/MeterProviderSharedState.ts     |  14 ++-
 .../src/state/MeterSharedState.ts             |  89 +++++++++++++++
 .../src/state/MetricCollector.ts              |   4 +-
 .../test/export/TestMetricExporter.ts         |  39 +++++++
 .../test/state/MeterSharedState.test.ts       | 106 ++++++++++++++++++
 .../test/state/MetricCollector.test.ts        |  35 ++----
 .../test/util.ts                              |   2 +-
 tsconfig.es5.json                             |   3 +-
 9 files changed, 272 insertions(+), 91 deletions(-)
 create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts
 create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricExporter.ts
 create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts

diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts
index 7954c4fff0f..f1c818fafb3 100644
--- a/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts
+++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts
@@ -16,27 +16,19 @@
 
 import * as metrics from '@opentelemetry/api-metrics-wip';
 import { InstrumentationLibrary } from '@opentelemetry/core';
-import { createInstrumentDescriptor, InstrumentDescriptor, InstrumentType } from './InstrumentDescriptor';
+import { createInstrumentDescriptor, InstrumentType } from './InstrumentDescriptor';
 import { Counter, Histogram, UpDownCounter } from './Instruments';
 import { MeterProviderSharedState } from './state/MeterProviderSharedState';
-import { MultiMetricStorage } from './state/MultiWritableMetricStorage';
-import { SyncMetricStorage } from './state/SyncMetricStorage';
-import { InstrumentationLibraryMetrics } from './export/MetricData';
-import { isNotNullish } from './utils';
-import { MetricCollectorHandle } from './state/MetricCollector';
-import { HrTime } from '@opentelemetry/api';
-import { AsyncMetricStorage } from './state/AsyncMetricStorage';
-import { WritableMetricStorage } from './state/WritableMetricStorage';
-import { MetricStorageRegistry } from './state/MetricStorageRegistry';
+import { MeterSharedState } from './state/MeterSharedState';
 
 /**
  * This class implements the {@link metrics.Meter} interface.
  */
 export class Meter implements metrics.Meter {
-  private _metricStorageRegistry = new MetricStorageRegistry();
+  private _meterSharedState: MeterSharedState;
 
-  constructor(private _meterProviderSharedState: MeterProviderSharedState, private _instrumentationLibrary: InstrumentationLibrary) {
-    this._meterProviderSharedState.meters.push(this);
+  constructor(meterProviderSharedState: MeterProviderSharedState, instrumentationLibrary: InstrumentationLibrary) {
+    this._meterSharedState = meterProviderSharedState.getMeterSharedState(instrumentationLibrary);
   }
 
   /**
@@ -44,7 +36,7 @@ export class Meter implements metrics.Meter {
    */
   createHistogram(name: string, options?: metrics.HistogramOptions): metrics.Histogram {
     const descriptor = createInstrumentDescriptor(name, InstrumentType.HISTOGRAM, options);
-    const storage = this._registerMetricStorage(descriptor);
+    const storage = this._meterSharedState.registerMetricStorage(descriptor);
     return new Histogram(storage, descriptor);
   }
 
@@ -53,7 +45,7 @@ export class Meter implements metrics.Meter {
    */
   createCounter(name: string, options?: metrics.CounterOptions): metrics.Counter {
     const descriptor = createInstrumentDescriptor(name, InstrumentType.COUNTER, options);
-    const storage = this._registerMetricStorage(descriptor);
+    const storage = this._meterSharedState.registerMetricStorage(descriptor);
     return new Counter(storage, descriptor);
   }
 
@@ -62,7 +54,7 @@ export class Meter implements metrics.Meter {
    */
   createUpDownCounter(name: string, options?: metrics.UpDownCounterOptions): metrics.UpDownCounter {
     const descriptor = createInstrumentDescriptor(name, InstrumentType.UP_DOWN_COUNTER, options);
-    const storage = this._registerMetricStorage(descriptor);
+    const storage = this._meterSharedState.registerMetricStorage(descriptor);
     return new UpDownCounter(storage, descriptor);
   }
 
@@ -75,7 +67,7 @@ export class Meter implements metrics.Meter {
     options?: metrics.ObservableGaugeOptions,
   ): void {
     const descriptor = createInstrumentDescriptor(name, InstrumentType.OBSERVABLE_GAUGE, options);
-    this._registerAsyncMetricStorage(descriptor, callback);
+    this._meterSharedState.registerAsyncMetricStorage(descriptor, callback);
   }
 
   /**
@@ -87,7 +79,7 @@ export class Meter implements metrics.Meter {
     options?: metrics.ObservableCounterOptions,
   ): void {
     const descriptor = createInstrumentDescriptor(name, InstrumentType.OBSERVABLE_COUNTER, options);
-    this._registerAsyncMetricStorage(descriptor, callback);
+    this._meterSharedState.registerAsyncMetricStorage(descriptor, callback);
   }
 
   /**
@@ -99,47 +91,6 @@ export class Meter implements metrics.Meter {
     options?: metrics.ObservableUpDownCounterOptions,
   ): void {
     const descriptor = createInstrumentDescriptor(name, InstrumentType.OBSERVABLE_UP_DOWN_COUNTER, options);
-    this._registerAsyncMetricStorage(descriptor, callback);
-  }
-
-  private _registerMetricStorage(descriptor: InstrumentDescriptor): WritableMetricStorage {
-    const views = this._meterProviderSharedState.viewRegistry.findViews(descriptor, this._instrumentationLibrary);
-    const storages = views.map(view => this._metricStorageRegistry.register(SyncMetricStorage.create(view, descriptor)))
-      .filter(isNotNullish);
-
-    if (storages.length === 1) {
-      return storages[0];
-    }
-
-    // This will be a no-op WritableMetricStorage when length is null.
-    return new MultiMetricStorage(storages);
-  }
-
-  private _registerAsyncMetricStorage(descriptor: InstrumentDescriptor, callback: metrics.ObservableCallback) {
-    const views = this._meterProviderSharedState.viewRegistry.findViews(descriptor, this._instrumentationLibrary);
-    views.forEach(view => {
-      this._metricStorageRegistry.register(AsyncMetricStorage.create(view, descriptor, callback));
-    });
-  }
-
-  /**
-   * @internal
-   * @param collector opaque handle of {@link MetricCollector} which initiated the collection.
-   * @param collectionTime the HrTime at which the collection was initiated.
-   * @returns the list of {@link MetricData} collected.
-   */
-  async collect(collector: MetricCollectorHandle, collectionTime: HrTime): Promise<InstrumentationLibraryMetrics> {
-    const metricData = await Promise.all(this._metricStorageRegistry.getStorages().map(metricStorage => {
-      return metricStorage.collect(
-        collector,
-        this._meterProviderSharedState.metricCollectors,
-        this._meterProviderSharedState.sdkStartTime,
-        collectionTime);
-    }));
-
-    return {
-      instrumentationLibrary: this._instrumentationLibrary,
-      metrics: metricData.filter(isNotNullish),
-    };
+    this._meterSharedState.registerAsyncMetricStorage(descriptor, callback);
   }
 }
diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts
index f6d81a82f94..6c35e650bf8 100644
--- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts
+++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts
@@ -15,10 +15,10 @@
  */
 
 import { HrTime } from '@opentelemetry/api';
-import { hrTime } from '@opentelemetry/core';
+import { hrTime, InstrumentationLibrary } from '@opentelemetry/core';
 import { Resource } from '@opentelemetry/resources';
-import { Meter } from '../Meter';
 import { ViewRegistry } from '../view/ViewRegistry';
+import { MeterSharedState } from './MeterSharedState';
 import { MetricCollector } from './MetricCollector';
 
 /**
@@ -30,7 +30,15 @@ export class MeterProviderSharedState {
 
   metricCollectors: MetricCollector[] = [];
 
-  meters: Meter[] = [];
+  meterSharedStates: MeterSharedState[] = [];
 
   constructor(public resource: Resource) {}
+
+  getMeterSharedState(instrumentationLibrary: InstrumentationLibrary) {
+    // TODO: meter identity
+    // https://github.com/open-telemetry/opentelemetry-js/issues/2593
+    const meterSharedState = new MeterSharedState(this, instrumentationLibrary);
+    this.meterSharedStates.push(meterSharedState);
+    return meterSharedState;
+  }
 }
diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts
new file mode 100644
index 00000000000..cf59bbe932f
--- /dev/null
+++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts
@@ -0,0 +1,89 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { HrTime } from '@opentelemetry/api';
+import * as metrics from '@opentelemetry/api-metrics-wip';
+import { InstrumentationLibrary } from '@opentelemetry/core';
+import { InstrumentationLibraryMetrics } from '../export/MetricData';
+import { createInstrumentDescriptorWithView, InstrumentDescriptor } from '../InstrumentDescriptor';
+import { isNotNullish } from '../utils';
+import { AsyncMetricStorage } from './AsyncMetricStorage';
+import { MeterProviderSharedState } from './MeterProviderSharedState';
+import { MetricCollectorHandle } from './MetricCollector';
+import { MetricStorageRegistry } from './MetricStorageRegistry';
+import { MultiMetricStorage } from './MultiWritableMetricStorage';
+import { SyncMetricStorage } from './SyncMetricStorage';
+
+/**
+ * An internal record for shared meter provider states.
+ */
+export class MeterSharedState {
+  private _metricStorageRegistry = new MetricStorageRegistry();
+
+  constructor(private _meterProviderSharedState: MeterProviderSharedState, private _instrumentationLibrary: InstrumentationLibrary) {}
+
+  registerMetricStorage(descriptor: InstrumentDescriptor) {
+    const views = this._meterProviderSharedState.viewRegistry.findViews(descriptor, this._instrumentationLibrary);
+    const storages = views
+      .map(view => {
+        const viewDescriptor = createInstrumentDescriptorWithView(view, descriptor);
+        const aggregator = view.aggregation.createAggregator(viewDescriptor);
+        const storage = new SyncMetricStorage(viewDescriptor, aggregator, view.attributesProcessor);
+        return this._metricStorageRegistry.register(storage);
+      })
+      .filter(isNotNullish);
+    if (storages.length === 1)  {
+      return storages[0];
+    }
+    return new MultiMetricStorage(storages);
+  }
+
+  registerAsyncMetricStorage(descriptor: InstrumentDescriptor, callback: metrics.ObservableCallback) {
+    const views = this._meterProviderSharedState.viewRegistry.findViews(descriptor, this._instrumentationLibrary);
+    views.forEach(view => {
+      const viewDescriptor = createInstrumentDescriptorWithView(view, descriptor);
+      const aggregator = view.aggregation.createAggregator(viewDescriptor);
+      const viewStorage = new AsyncMetricStorage(viewDescriptor, aggregator, view.attributesProcessor, callback);
+      this._metricStorageRegistry.register(viewStorage);
+    });
+  }
+
+  /**
+   * @param collector opaque handle of {@link MetricCollector} which initiated the collection.
+   * @param collectionTime the HrTime at which the collection was initiated.
+   * @returns the list of {@link MetricData} collected.
+   */
+  async collect(collector: MetricCollectorHandle, collectionTime: HrTime): Promise<InstrumentationLibraryMetrics> {
+    /**
+     * 1. Call all observable callbacks first.
+     * 2. Collect metric result for the collector.
+     */
+    const metricDataList = await Promise.all(Array.from(this._metricStorageRegistry.getStorages())
+      .map(metricStorage => {
+        return metricStorage.collect(
+          collector,
+          this._meterProviderSharedState.metricCollectors,
+          this._meterProviderSharedState.sdkStartTime,
+          collectionTime);
+      })
+      .filter(isNotNullish));
+
+    return {
+      instrumentationLibrary: this._instrumentationLibrary,
+      metrics: metricDataList.filter(isNotNullish),
+    };
+  }
+}
diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts
index 6be9022b990..0cff46838a3 100644
--- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts
+++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts
@@ -34,8 +34,8 @@ export class MetricCollector implements MetricProducer {
 
   async collect(): Promise<ResourceMetrics> {
     const collectionTime = hrTime();
-    const instrumentationLibraryMetrics = (await Promise.all(this._sharedState.meters
-      .map(meter => meter.collect(this, collectionTime))));
+    const instrumentationLibraryMetrics = (await Promise.all(this._sharedState.meterSharedStates
+      .map(meterSharedState => meterSharedState.collect(this, collectionTime))));
 
     return {
       resource: this._sharedState.resource,
diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricExporter.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricExporter.ts
new file mode 100644
index 00000000000..43df025473d
--- /dev/null
+++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricExporter.ts
@@ -0,0 +1,39 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ExportResult, ExportResultCode } from '@opentelemetry/core';
+import { AggregationTemporality, PushMetricExporter, ResourceMetrics } from '../../src';
+
+export class TestMetricExporter implements PushMetricExporter {
+  resourceMetricsList: ResourceMetrics[] = [];
+  export(resourceMetrics: ResourceMetrics, resultCallback: (result: ExportResult) => void): void {
+    this.resourceMetricsList.push(resourceMetrics);
+    process.nextTick(() => resultCallback({ code: ExportResultCode.SUCCESS }));
+  }
+
+  async forceFlush(): Promise<void> {}
+  async shutdown(): Promise<void> {}
+
+  getPreferredAggregationTemporality(): AggregationTemporality {
+    return AggregationTemporality.CUMULATIVE;
+  }
+}
+
+export class TestDeltaMetricExporter extends TestMetricExporter {
+  override getPreferredAggregationTemporality(): AggregationTemporality {
+    return AggregationTemporality.DELTA;
+  }
+}
diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts
new file mode 100644
index 00000000000..602e834c6c1
--- /dev/null
+++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts
@@ -0,0 +1,106 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import * as assert from 'assert';
+import * as sinon from 'sinon';
+import { Meter, MeterProvider, PointDataType } from '../../src';
+import { assertMetricData, defaultInstrumentationLibrary, defaultResource } from '../util';
+import { TestMetricReader } from '../export/TestMetricReader';
+import { TestDeltaMetricExporter, TestMetricExporter } from '../export/TestMetricExporter';
+import { MeterSharedState } from '../../src/state/MeterSharedState';
+import { View } from '../../src/view/View';
+import { InstrumentSelector } from '../../src/view/InstrumentSelector';
+import { MeterSelector } from '../../src/view/MeterSelector';
+
+describe('MeterSharedState', () => {
+  afterEach(() => {
+    sinon.restore();
+  });
+
+  describe('collect', () => {
+    function setupInstruments() {
+      const meterProvider = new MeterProvider({ resource: defaultResource });
+
+      const cumulativeReader = new TestMetricReader(new TestMetricExporter().getPreferredAggregationTemporality());
+      meterProvider.addMetricReader(cumulativeReader);
+      const cumulativeCollector = cumulativeReader.getMetricCollector();
+
+      const deltaReader = new TestMetricReader(new TestDeltaMetricExporter().getPreferredAggregationTemporality());
+      meterProvider.addMetricReader(deltaReader);
+      const deltaCollector = deltaReader.getMetricCollector();
+
+      const metricCollectors = [cumulativeCollector, deltaCollector];
+
+      const meter = meterProvider.getMeter(defaultInstrumentationLibrary.name, defaultInstrumentationLibrary.version, {
+        schemaUrl: defaultInstrumentationLibrary.schemaUrl,
+      }) as Meter;
+      const meterSharedState = meter['_meterSharedState'] as MeterSharedState;
+
+      return { metricCollectors, cumulativeCollector, deltaCollector, meter, meterSharedState, meterProvider };
+    }
+
+    it('should collect sync metrics', async () => {
+      /** preparing test instrumentations */
+      const { metricCollectors, meter } = setupInstruments();
+
+      /** creating metric events */
+      const counter = meter.createCounter('test');
+
+      /** collect metrics */
+      counter.add(1);
+      await Promise.all(metricCollectors.map(async collector => {
+        const result = await collector.collect();
+        assert.strictEqual(result.instrumentationLibraryMetrics.length, 1);
+        assert.strictEqual(result.instrumentationLibraryMetrics[0].metrics.length, 1);
+        assertMetricData(result.instrumentationLibraryMetrics[0].metrics[0], PointDataType.SINGULAR, {
+          name: 'test',
+        });
+      }));
+    });
+
+    it('should collect sync metrics with views', async () => {
+      /** preparing test instrumentations */
+      const { metricCollectors, meter, meterProvider } = setupInstruments();
+
+      /** creating metric events */
+      meterProvider.addView(
+        new View({ name: 'foo' }),
+        new InstrumentSelector({ name: 'test' }),
+        new MeterSelector());
+      meterProvider.addView(
+        new View({ name: 'bar' }),
+        new InstrumentSelector({ name: 'test' }),
+        new MeterSelector());
+
+      const counter = meter.createCounter('test');
+
+      /** collect metrics */
+      counter.add(1);
+      await Promise.all(metricCollectors.map(async collector => {
+        const result = await collector.collect();
+        assert.strictEqual(result.instrumentationLibraryMetrics.length, 1);
+        assert.strictEqual(result.instrumentationLibraryMetrics[0].metrics.length, 2);
+        assertMetricData(result.instrumentationLibraryMetrics[0].metrics[0], PointDataType.SINGULAR, {
+          name: 'foo',
+        });
+        assertMetricData(result.instrumentationLibraryMetrics[0].metrics[1], PointDataType.SINGULAR, {
+          name: 'bar',
+        });
+      }));
+    });
+
+  });
+});
diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts
index 56ac74a701e..00d66438b7b 100644
--- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts
+++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts
@@ -17,34 +17,21 @@
 import * as assert from 'assert';
 import * as sinon from 'sinon';
 import { MeterProvider } from '../../src';
-import { AggregationTemporality } from '../../src/export/AggregationTemporality';
-import { PointDataType, ResourceMetrics } from '../../src/export/MetricData';
+import { PointDataType } from '../../src/export/MetricData';
 import { PushMetricExporter } from '../../src/export/MetricExporter';
 import { MeterProviderSharedState } from '../../src/state/MeterProviderSharedState';
 import { MetricCollector } from '../../src/state/MetricCollector';
-import { defaultInstrumentationLibrary, defaultResource, assertMetricData, assertPointData } from '../util';
+import {
+  defaultInstrumentationLibrary,
+  defaultResource,
+  assertMetricData,
+  assertPointData,
+} from '../util';
+import {
+  TestMetricExporter,
+  TestDeltaMetricExporter
+} from '../export/TestMetricExporter';
 import { TestMetricReader } from '../export/TestMetricReader';
-import { ExportResult, ExportResultCode } from '@opentelemetry/core';
-
-class TestMetricExporter implements PushMetricExporter {
-  async export(metrics: ResourceMetrics, resultCallback: (result: ExportResult) => void): Promise<void> {
-    resultCallback({code: ExportResultCode.SUCCESS});
-  }
-
-  async shutdown(): Promise<void> {}
-
-  async forceFlush(): Promise<void> {}
-
-  getPreferredAggregationTemporality(): AggregationTemporality {
-    return AggregationTemporality.CUMULATIVE;
-  }
-}
-
-class TestDeltaMetricExporter extends TestMetricExporter {
-  override getPreferredAggregationTemporality(): AggregationTemporality {
-    return AggregationTemporality.DELTA;
-  }
-}
 
 describe('MetricCollector', () => {
   afterEach(() => {
diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/util.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/util.ts
index 89eef5e65bb..56e7d21279d 100644
--- a/experimental/packages/opentelemetry-sdk-metrics-base/test/util.ts
+++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/util.ts
@@ -49,7 +49,7 @@ a = '1';
 })];
 
 export const sleep = (time: number) =>
-  new Promise(resolve => {
+  new Promise<void>(resolve => {
     return setTimeout(resolve, time);
   });
 
diff --git a/tsconfig.es5.json b/tsconfig.es5.json
index 3c83c51a2b0..89cefe2d438 100644
--- a/tsconfig.es5.json
+++ b/tsconfig.es5.json
@@ -1,6 +1,7 @@
 {
   "extends": "./tsconfig.base.json",
   "compilerOptions": {
-    "target": "es5"
+    "target": "es5",
+    "downlevelIteration": true
   }
 }

From ed822dcdbb801a269b5b3da0b4c6d2f74fe122a9 Mon Sep 17 00:00:00 2001
From: legendecas <legendecas@gmail.com>
Date: Wed, 23 Mar 2022 11:48:25 +0800
Subject: [PATCH 2/5] fixup!

---
 .../test/state/MeterSharedState.test.ts       | 21 ++++++-------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts
index 602e834c6c1..1e0cd68f99c 100644
--- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts
+++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts
@@ -16,14 +16,11 @@
 
 import * as assert from 'assert';
 import * as sinon from 'sinon';
-import { Meter, MeterProvider, PointDataType } from '../../src';
+import { Meter, MeterProvider, DataPointType } from '../../src';
 import { assertMetricData, defaultInstrumentationLibrary, defaultResource } from '../util';
 import { TestMetricReader } from '../export/TestMetricReader';
 import { TestDeltaMetricExporter, TestMetricExporter } from '../export/TestMetricExporter';
 import { MeterSharedState } from '../../src/state/MeterSharedState';
-import { View } from '../../src/view/View';
-import { InstrumentSelector } from '../../src/view/InstrumentSelector';
-import { MeterSelector } from '../../src/view/MeterSelector';
 
 describe('MeterSharedState', () => {
   afterEach(() => {
@@ -65,7 +62,7 @@ describe('MeterSharedState', () => {
         const result = await collector.collect();
         assert.strictEqual(result.instrumentationLibraryMetrics.length, 1);
         assert.strictEqual(result.instrumentationLibraryMetrics[0].metrics.length, 1);
-        assertMetricData(result.instrumentationLibraryMetrics[0].metrics[0], PointDataType.SINGULAR, {
+        assertMetricData(result.instrumentationLibraryMetrics[0].metrics[0], DataPointType.SINGULAR, {
           name: 'test',
         });
       }));
@@ -76,14 +73,8 @@ describe('MeterSharedState', () => {
       const { metricCollectors, meter, meterProvider } = setupInstruments();
 
       /** creating metric events */
-      meterProvider.addView(
-        new View({ name: 'foo' }),
-        new InstrumentSelector({ name: 'test' }),
-        new MeterSelector());
-      meterProvider.addView(
-        new View({ name: 'bar' }),
-        new InstrumentSelector({ name: 'test' }),
-        new MeterSelector());
+      meterProvider.addView({ name: 'foo' }, { instrument: { name: 'test' } });
+      meterProvider.addView({ name: 'bar' }, { instrument: { name: 'test' } });
 
       const counter = meter.createCounter('test');
 
@@ -93,10 +84,10 @@ describe('MeterSharedState', () => {
         const result = await collector.collect();
         assert.strictEqual(result.instrumentationLibraryMetrics.length, 1);
         assert.strictEqual(result.instrumentationLibraryMetrics[0].metrics.length, 2);
-        assertMetricData(result.instrumentationLibraryMetrics[0].metrics[0], PointDataType.SINGULAR, {
+        assertMetricData(result.instrumentationLibraryMetrics[0].metrics[0], DataPointType.SINGULAR, {
           name: 'foo',
         });
-        assertMetricData(result.instrumentationLibraryMetrics[0].metrics[1], PointDataType.SINGULAR, {
+        assertMetricData(result.instrumentationLibraryMetrics[0].metrics[1], DataPointType.SINGULAR, {
           name: 'bar',
         });
       }));

From f4aa04295902d604d85e7139da16b17be107a4af Mon Sep 17 00:00:00 2001
From: legendecas <legendecas@gmail.com>
Date: Wed, 6 Apr 2022 22:43:38 +0800
Subject: [PATCH 3/5] fixup! CHANGELOG

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02999c34c9c..1e849b5e0ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file.
 ### :house: (Internal)
 
 * [#2847](https://github.com/open-telemetry/opentelemetry-js/pull/2847) chore: require changelog entry to merge PR ([@dyladan](https://github.com/dyladan))
+* refactor(sdk-metrics-base): meter shared states #2821 @legendecas
 
 ## 1.1.1
 

From cf796dd0ad6da67eba0939740096dda97a09b763 Mon Sep 17 00:00:00 2001
From: legendecas <legendecas@gmail.com>
Date: Fri, 8 Apr 2022 00:18:09 +0800
Subject: [PATCH 4/5] fixup!

---
 CHANGELOG.md              | 1 -
 experimental/CHANGELOG.md | 1 +
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1e849b5e0ee..02999c34c9c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,7 +17,6 @@ All notable changes to this project will be documented in this file.
 ### :house: (Internal)
 
 * [#2847](https://github.com/open-telemetry/opentelemetry-js/pull/2847) chore: require changelog entry to merge PR ([@dyladan](https://github.com/dyladan))
-* refactor(sdk-metrics-base): meter shared states #2821 @legendecas
 
 ## 1.1.1
 
diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md
index 1490c7826f2..276928d2165 100644
--- a/experimental/CHANGELOG.md
+++ b/experimental/CHANGELOG.md
@@ -45,6 +45,7 @@ All notable changes to experimental packages in this project will be documented
 ### :house: (Internal)
 
 * [#2835](https://github.com/open-telemetry/opentelemetry-js/pull/2835) chore: move trace exporters back to experimental ([@dyladan](https://github.com/dyladan))
+* refactor(sdk-metrics-base): meter shared states #2821 @legendecas
 
 ## v0.27.0
 

From 03fa81f0c99f68cfef70c6a5d75312d6c32231a7 Mon Sep 17 00:00:00 2001
From: legendecas <legendecas@gmail.com>
Date: Fri, 8 Apr 2022 10:58:55 +0800
Subject: [PATCH 5/5] fixup!

---
 .../src/state/MeterSharedState.ts                               | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts
index cf59bbe932f..912cf54557c 100644
--- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts
+++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts
@@ -15,7 +15,7 @@
  */
 
 import { HrTime } from '@opentelemetry/api';
-import * as metrics from '@opentelemetry/api-metrics-wip';
+import * as metrics from '@opentelemetry/api-metrics';
 import { InstrumentationLibrary } from '@opentelemetry/core';
 import { InstrumentationLibraryMetrics } from '../export/MetricData';
 import { createInstrumentDescriptorWithView, InstrumentDescriptor } from '../InstrumentDescriptor';