We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
AttributeError: 'NoneType' object has no attribute 'attributes'
Run a slightly modified version of the [docs example](https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples/metrics):

``` python
from typing import Iterable
from time import sleep

from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
    OTLPMetricExporter,
)
from opentelemetry.metrics import (
    CallbackOptions,
    Observation,
    get_meter_provider,
    set_meter_provider,
)
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader

exporter = OTLPMetricExporter(insecure=True)
reader = PeriodicExportingMetricReader(exporter, export_interval_millis=1000)
provider = MeterProvider(metric_readers=[reader])
set_meter_provider(provider)


def observable_counter_func(options: CallbackOptions) -> Iterable[Observation]:
    yield Observation(1, {})


def observable_up_down_counter_func(
    options: CallbackOptions,
) -> Iterable[Observation]:
    yield Observation(-10, {})


def observable_gauge_func(options: CallbackOptions) -> Iterable[Observation]:
    yield Observation(9, {})


meter = get_meter_provider().get_meter("getting-started", "0.1.2")

# Counter
counter = meter.create_counter("counter")
counter.add(1)

# Async Counter
observable_counter = meter.create_observable_counter(
    "observable_counter",
    [observable_counter_func],
)

# UpDownCounter
updown_counter = meter.create_up_down_counter("updown_counter")
updown_counter.add(1)
updown_counter.add(-5)

# Async UpDownCounter
observable_updown_counter = meter.create_observable_up_down_counter(
    "observable_updown_counter", [observable_up_down_counter_func]
)

# Histogram
histogram = meter.create_histogram("histogram")
histogram.record(99.9)

# Async Gauge
gauge = meter.create_observable_gauge("gauge", [observable_gauge_func])

sleep(6)
```
running this script (after activating the collector via Docker) produces these errors:

```
Exception while exporting metrics 'NoneType' object has no attribute 'attributes'
Traceback (most recent call last):
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py", line 412, in _receive_metrics
    self._exporter.export(metrics_data, timeout_millis=timeout_millis)
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py", line 203, in export
    return self._export(metrics_data)
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py", line 293, in _export
    request=self._translate_data(data),
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py", line 139, in _translate_data
    data_point.attributes
AttributeError: 'NoneType' object has no attribute 'attributes'
Exception while exporting metrics 'NoneType' object has no attribute 'attributes'
Traceback (most recent call last):
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py", line 412, in _receive_metrics
    self._exporter.export(metrics_data, timeout_millis=timeout_millis)
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py", line 203, in export
    return self._export(metrics_data)
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py", line 293, in _export
    request=self._translate_data(data),
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py", line 139, in _translate_data
    data_point.attributes
AttributeError: 'NoneType' object has no attribute 'attributes'
Exception while exporting metrics 'NoneType' object has no attribute 'attributes'
Traceback (most recent call last):
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py", line 412, in _receive_metrics
    self._exporter.export(metrics_data, timeout_millis=timeout_millis)
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py", line 203, in export
    return self._export(metrics_data)
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py", line 293, in _export
    request=self._translate_data(data),
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py", line 139, in _translate_data
    data_point.attributes
AttributeError: 'NoneType' object has no attribute 'attributes'
Exception while exporting metrics 'NoneType' object has no attribute 'attributes'
Traceback (most recent call last):
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py", line 412, in _receive_metrics
    self._exporter.export(metrics_data, timeout_millis=timeout_millis)
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py", line 203, in export
    return self._export(metrics_data)
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py", line 293, in _export
    request=self._translate_data(data),
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py", line 139, in _translate_data
    data_point.attributes
AttributeError: 'NoneType' object has no attribute 'attributes'
Exception while exporting metrics 'NoneType' object has no attribute 'attributes'
Traceback (most recent call last):
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py", line 412, in _receive_metrics
    self._exporter.export(metrics_data, timeout_millis=timeout_millis)
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py", line 203, in export
    return self._export(metrics_data)
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py", line 293, in _export
    request=self._translate_data(data),
  File "/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py", line 139, in _translate_data
    data_point.attributes
AttributeError: 'NoneType' object has no attribute 'attributes'
shutdown
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py`
Content:
```
1 # Copyright The OpenTelemetry Authors
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 
16 from logging import getLogger
17 from threading import Lock
18 from typing import Dict, Iterable
19 
20 from opentelemetry.metrics import Instrument
21 from opentelemetry.sdk.metrics._internal.aggregation import (
22     Aggregation,
23     DefaultAggregation,
24     _Aggregation,
25     _SumAggregation,
26 )
27 from opentelemetry.sdk.metrics._internal.export import AggregationTemporality
28 from opentelemetry.sdk.metrics._internal.measurement import Measurement
29 from opentelemetry.sdk.metrics._internal.point import DataPointT
30 from opentelemetry.sdk.metrics._internal.view import View
31 from opentelemetry.util._time import _time_ns
32 
33 _logger = getLogger(__name__)
34 
35 
36 class _ViewInstrumentMatch:
37     def __init__(
38         self,
39         view: View,
40         instrument: Instrument,
41         instrument_class_aggregation: Dict[type, Aggregation],
42     ):
43         self._start_time_unix_nano = _time_ns()
44         self._view = view
45         self._instrument = instrument
46         self._attributes_aggregation: Dict[frozenset, _Aggregation] = {}
47         self._lock = Lock()
48         self._instrument_class_aggregation = instrument_class_aggregation
49         self._name = self._view._name or self._instrument.name
50         self._description = (
51             self._view._description or self._instrument.description
52         )
53         if not isinstance(self._view._aggregation, DefaultAggregation):
54             self._aggregation = self._view._aggregation._create_aggregation(
55                 self._instrument, None, 0
56             )
57         else:
58             self._aggregation = self._instrument_class_aggregation[
59                 self._instrument.__class__
60             ]._create_aggregation(self._instrument, None, 0)
61 
62     def conflicts(self, other: "_ViewInstrumentMatch") -> bool:
63         # pylint: disable=protected-access
64 
65         result = (
66             self._name == other._name
67             and self._instrument.unit == other._instrument.unit
68             # The aggregation class is being used here instead of data point
69             # type since they are functionally equivalent.
70             and self._aggregation.__class__ == other._aggregation.__class__
71         )
72         if isinstance(self._aggregation, _SumAggregation):
73             result = (
74                 result
75                 and self._aggregation._instrument_is_monotonic
76                 == other._aggregation._instrument_is_monotonic
77                 and self._aggregation._instrument_temporality
78                 == other._aggregation._instrument_temporality
79             )
80 
81         return result
82 
83     # pylint: disable=protected-access
84     def consume_measurement(self, measurement: Measurement) -> None:
85 
86         if self._view._attribute_keys is not None:
87 
88             attributes = {}
89 
90             for key, value in (measurement.attributes or {}).items():
91                 if key in self._view._attribute_keys:
92                     attributes[key] = value
93         elif measurement.attributes is not None:
94             attributes = measurement.attributes
95         else:
96             attributes = {}
97 
98         aggr_key = frozenset(attributes.items())
99 
100         if aggr_key not in self._attributes_aggregation:
101             with self._lock:
102                 if aggr_key not in self._attributes_aggregation:
103                     if not isinstance(
104                         self._view._aggregation, DefaultAggregation
105                     ):
106                         aggregation = (
107                             self._view._aggregation._create_aggregation(
108                                 self._instrument,
109                                 attributes,
110                                 self._start_time_unix_nano,
111                             )
112                         )
113                     else:
114                         aggregation = self._instrument_class_aggregation[
115                             self._instrument.__class__
116                         ]._create_aggregation(
117                             self._instrument,
118                             attributes,
119                             self._start_time_unix_nano,
120                         )
121                     self._attributes_aggregation[aggr_key] = aggregation
122 
123         self._attributes_aggregation[aggr_key].aggregate(measurement)
124 
125     def collect(
126         self,
127         aggregation_temporality: AggregationTemporality,
128         collection_start_nanos: int,
129     ) -> Iterable[DataPointT]:
130 
131         with self._lock:
132             for aggregation in self._attributes_aggregation.values():
133                 yield aggregation.collect(
134                     aggregation_temporality, collection_start_nanos
135                 )
136
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py
--- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py
@@ -130,6 +130,8 @@
 
         with self._lock:
             for aggregation in self._attributes_aggregation.values():
-                yield aggregation.collect(
+                data_point = aggregation.collect(
                     aggregation_temporality, collection_start_nanos
                 )
+                if data_point is not None:
+                    yield data_point

{"golden_diff": "diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py\n--- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py\n+++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py\n@@ -130,6 +130,8 @@\n \n         with self._lock:\n             for aggregation in self._attributes_aggregation.values():\n-                yield aggregation.collect(\n+                data_point = aggregation.collect(\n                     aggregation_temporality, collection_start_nanos\n                 )\n+                if data_point is not None:\n+                    yield data_point\n", "issue": "AttributeError: 'NoneType' object has no attribute 'attributes'\nRun a slightly modified version of the [docs example](https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples/metrics):\r\n\r\n``` python\r\nfrom typing import Iterable\r\nfrom time import sleep\r\n\r\nfrom opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (\r\n    OTLPMetricExporter,\r\n)\r\nfrom opentelemetry.metrics import (\r\n    CallbackOptions,\r\n    Observation,\r\n    get_meter_provider,\r\n    set_meter_provider,\r\n)\r\nfrom opentelemetry.sdk.metrics import MeterProvider\r\nfrom opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader\r\n\r\nexporter = OTLPMetricExporter(insecure=True)\r\nreader = PeriodicExportingMetricReader(exporter, export_interval_millis=1000)\r\nprovider = MeterProvider(metric_readers=[reader])\r\nset_meter_provider(provider)\r\n\r\n\r\ndef observable_counter_func(options: CallbackOptions) -> Iterable[Observation]:\r\n    yield Observation(1, {})\r\n\r\n\r\ndef observable_up_down_counter_func(\r\n    options: CallbackOptions,\r\n) -> Iterable[Observation]:\r\n    yield Observation(-10, {})\r\n\r\n\r\ndef observable_gauge_func(options: CallbackOptions) -> Iterable[Observation]:\r\n    yield Observation(9, {})\r\n\r\n\r\nmeter = get_meter_provider().get_meter(\"getting-started\", \"0.1.2\")\r\n\r\n# Counter\r\ncounter = meter.create_counter(\"counter\")\r\ncounter.add(1)\r\n\r\n# Async Counter\r\nobservable_counter = meter.create_observable_counter(\r\n    \"observable_counter\",\r\n    [observable_counter_func],\r\n)\r\n\r\n# UpDownCounter\r\nupdown_counter = meter.create_up_down_counter(\"updown_counter\")\r\nupdown_counter.add(1)\r\nupdown_counter.add(-5)\r\n\r\n# Async UpDownCounter\r\nobservable_updown_counter = meter.create_observable_up_down_counter(\r\n    \"observable_updown_counter\", [observable_up_down_counter_func]\r\n)\r\n\r\n# Histogram\r\nhistogram = meter.create_histogram(\"histogram\")\r\nhistogram.record(99.9)\r\n\r\n# Async Gauge\r\ngauge = meter.create_observable_gauge(\"gauge\", [observable_gauge_func])\r\n\r\nsleep(6)\r\n```\r\nrunning this script (after activating the collector via Docker) produces these errors:\r\n\r\n```\r\nException while exporting metrics 'NoneType' object has no attribute 'attributes'\r\nTraceback (most recent call last):\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py\", line 412, in _receive_metrics\r\n    self._exporter.export(metrics_data, timeout_millis=timeout_millis)\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py\", line 203, in export\r\n    return self._export(metrics_data)\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py\", line 293, in _export\r\n    request=self._translate_data(data),\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py\", line 139, in _translate_data\r\n    data_point.attributes\r\nAttributeError: 'NoneType' object has no attribute 'attributes'\r\nException while exporting metrics 'NoneType' object has no attribute 'attributes'\r\nTraceback (most recent call last):\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py\", line 412, in _receive_metrics\r\n    self._exporter.export(metrics_data, timeout_millis=timeout_millis)\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py\", line 203, in export\r\n    return self._export(metrics_data)\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py\", line 293, in _export\r\n    request=self._translate_data(data),\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py\", line 139, in _translate_data\r\n    data_point.attributes\r\nAttributeError: 'NoneType' object has no attribute 'attributes'\r\nException while exporting metrics 'NoneType' object has no attribute 'attributes'\r\nTraceback (most recent call last):\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py\", line 412, in _receive_metrics\r\n    self._exporter.export(metrics_data, timeout_millis=timeout_millis)\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py\", line 203, in export\r\n    return self._export(metrics_data)\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py\", line 293, in _export\r\n    request=self._translate_data(data),\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py\", line 139, in _translate_data\r\n    data_point.attributes\r\nAttributeError: 'NoneType' object has no attribute 'attributes'\r\nException while exporting metrics 'NoneType' object has no attribute 'attributes'\r\nTraceback (most recent call last):\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py\", line 412, in _receive_metrics\r\n    self._exporter.export(metrics_data, timeout_millis=timeout_millis)\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py\", line 203, in export\r\n    return self._export(metrics_data)\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py\", line 293, in _export\r\n    request=self._translate_data(data),\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py\", line 139, in _translate_data\r\n    data_point.attributes\r\nAttributeError: 'NoneType' object has no attribute 'attributes'\r\nException while exporting metrics 'NoneType' object has no attribute 'attributes'\r\nTraceback (most recent call last):\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py\", line 412, in _receive_metrics\r\n    self._exporter.export(metrics_data, timeout_millis=timeout_millis)\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py\", line 203, in export\r\n    return self._export(metrics_data)\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py\", line 293, in _export\r\n    request=self._translate_data(data),\r\n  File \"/home/ocelotl/github/ocelotl/opentelemetry-python/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py\", line 139, in _translate_data\r\n    data_point.attributes\r\nAttributeError: 'NoneType' object has no attribute 'attributes'\r\nshutdown\r\n```\r\n\n", "before_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\nfrom logging import getLogger\nfrom threading import Lock\nfrom typing import Dict, Iterable\n\nfrom opentelemetry.metrics import Instrument\nfrom opentelemetry.sdk.metrics._internal.aggregation import (\n    Aggregation,\n    DefaultAggregation,\n    _Aggregation,\n    _SumAggregation,\n)\nfrom opentelemetry.sdk.metrics._internal.export import AggregationTemporality\nfrom opentelemetry.sdk.metrics._internal.measurement import Measurement\nfrom opentelemetry.sdk.metrics._internal.point import DataPointT\nfrom opentelemetry.sdk.metrics._internal.view import View\nfrom opentelemetry.util._time import _time_ns\n\n_logger = getLogger(__name__)\n\n\nclass _ViewInstrumentMatch:\n    def __init__(\n        self,\n        view: View,\n        instrument: Instrument,\n        instrument_class_aggregation: Dict[type, Aggregation],\n    ):\n        self._start_time_unix_nano = _time_ns()\n        self._view = view\n        self._instrument = instrument\n        self._attributes_aggregation: Dict[frozenset, _Aggregation] = {}\n        self._lock = Lock()\n        self._instrument_class_aggregation = instrument_class_aggregation\n        self._name = self._view._name or self._instrument.name\n        self._description = (\n            self._view._description or self._instrument.description\n        )\n        if not isinstance(self._view._aggregation, DefaultAggregation):\n            self._aggregation = self._view._aggregation._create_aggregation(\n                self._instrument, None, 0\n            )\n        else:\n            self._aggregation = self._instrument_class_aggregation[\n                self._instrument.__class__\n            ]._create_aggregation(self._instrument, None, 0)\n\n    def conflicts(self, other: \"_ViewInstrumentMatch\") -> bool:\n        # pylint: disable=protected-access\n\n        result = (\n            self._name == other._name\n            and self._instrument.unit == other._instrument.unit\n            # The aggregation class is being used here instead of data point\n            # type since they are functionally equivalent.\n            and self._aggregation.__class__ == other._aggregation.__class__\n        )\n        if isinstance(self._aggregation, _SumAggregation):\n            result = (\n                result\n                and self._aggregation._instrument_is_monotonic\n                == other._aggregation._instrument_is_monotonic\n                and self._aggregation._instrument_temporality\n                == other._aggregation._instrument_temporality\n            )\n\n        return result\n\n    # pylint: disable=protected-access\n    def consume_measurement(self, measurement: Measurement) -> None:\n\n        if self._view._attribute_keys is not None:\n\n            attributes = {}\n\n            for key, value in (measurement.attributes or {}).items():\n                if key in self._view._attribute_keys:\n                    attributes[key] = value\n        elif measurement.attributes is not None:\n            attributes = measurement.attributes\n        else:\n            attributes = {}\n\n        aggr_key = frozenset(attributes.items())\n\n        if aggr_key not in self._attributes_aggregation:\n            with self._lock:\n                if aggr_key not in self._attributes_aggregation:\n                    if not isinstance(\n                        self._view._aggregation, DefaultAggregation\n                    ):\n                        aggregation = (\n                            self._view._aggregation._create_aggregation(\n                                self._instrument,\n                                attributes,\n                                self._start_time_unix_nano,\n                            )\n                        )\n                    else:\n                        aggregation = self._instrument_class_aggregation[\n                            self._instrument.__class__\n                        ]._create_aggregation(\n                            self._instrument,\n                            attributes,\n                            self._start_time_unix_nano,\n                        )\n                    self._attributes_aggregation[aggr_key] = aggregation\n\n        self._attributes_aggregation[aggr_key].aggregate(measurement)\n\n    def collect(\n        self,\n        aggregation_temporality: AggregationTemporality,\n        collection_start_nanos: int,\n    ) -> Iterable[DataPointT]:\n\n        with self._lock:\n            for aggregation in self._attributes_aggregation.values():\n                yield aggregation.collect(\n                    aggregation_temporality, collection_start_nanos\n                )\n", "path": "opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py"}], "after_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\nfrom logging import getLogger\nfrom threading import Lock\nfrom typing import Dict, Iterable\n\nfrom opentelemetry.metrics import Instrument\nfrom opentelemetry.sdk.metrics._internal.aggregation import (\n    Aggregation,\n    DefaultAggregation,\n    _Aggregation,\n    _SumAggregation,\n)\nfrom opentelemetry.sdk.metrics._internal.export import AggregationTemporality\nfrom opentelemetry.sdk.metrics._internal.measurement import Measurement\nfrom opentelemetry.sdk.metrics._internal.point import DataPointT\nfrom opentelemetry.sdk.metrics._internal.view import View\nfrom opentelemetry.util._time import _time_ns\n\n_logger = getLogger(__name__)\n\n\nclass _ViewInstrumentMatch:\n    def __init__(\n        self,\n        view: View,\n        instrument: Instrument,\n        instrument_class_aggregation: Dict[type, Aggregation],\n    ):\n        self._start_time_unix_nano = _time_ns()\n        self._view = view\n        self._instrument = instrument\n        self._attributes_aggregation: Dict[frozenset, _Aggregation] = {}\n        self._lock = Lock()\n        self._instrument_class_aggregation = instrument_class_aggregation\n        self._name = self._view._name or self._instrument.name\n        self._description = (\n            self._view._description or self._instrument.description\n        )\n        if not isinstance(self._view._aggregation, DefaultAggregation):\n            self._aggregation = self._view._aggregation._create_aggregation(\n                self._instrument, None, 0\n            )\n        else:\n            self._aggregation = self._instrument_class_aggregation[\n                self._instrument.__class__\n            ]._create_aggregation(self._instrument, None, 0)\n\n    def conflicts(self, other: \"_ViewInstrumentMatch\") -> bool:\n        # pylint: disable=protected-access\n\n        result = (\n            self._name == other._name\n            and self._instrument.unit == other._instrument.unit\n            # The aggregation class is being used here instead of data point\n            # type since they are functionally equivalent.\n            and self._aggregation.__class__ == other._aggregation.__class__\n        )\n        if isinstance(self._aggregation, _SumAggregation):\n            result = (\n                result\n                and self._aggregation._instrument_is_monotonic\n                == other._aggregation._instrument_is_monotonic\n                and self._aggregation._instrument_temporality\n                == other._aggregation._instrument_temporality\n            )\n\n        return result\n\n    # pylint: disable=protected-access\n    def consume_measurement(self, measurement: Measurement) -> None:\n\n        if self._view._attribute_keys is not None:\n\n            attributes = {}\n\n            for key, value in (measurement.attributes or {}).items():\n                if key in self._view._attribute_keys:\n                    attributes[key] = value\n        elif measurement.attributes is not None:\n            attributes = measurement.attributes\n        else:\n            attributes = {}\n\n        aggr_key = frozenset(attributes.items())\n\n        if aggr_key not in self._attributes_aggregation:\n            with self._lock:\n                if aggr_key not in self._attributes_aggregation:\n                    if not isinstance(\n                        self._view._aggregation, DefaultAggregation\n                    ):\n                        aggregation = (\n                            self._view._aggregation._create_aggregation(\n                                self._instrument,\n                                attributes,\n                                self._start_time_unix_nano,\n                            )\n                        )\n                    else:\n                        aggregation = self._instrument_class_aggregation[\n                            self._instrument.__class__\n                        ]._create_aggregation(\n                            self._instrument,\n                            attributes,\n                            self._start_time_unix_nano,\n                        )\n                    self._attributes_aggregation[aggr_key] = aggregation\n\n        self._attributes_aggregation[aggr_key].aggregate(measurement)\n\n    def collect(\n        self,\n        aggregation_temporality: AggregationTemporality,\n        collection_start_nanos: int,\n    ) -> Iterable[DataPointT]:\n\n        with self._lock:\n            for aggregation in self._attributes_aggregation.values():\n                data_point = aggregation.collect(\n                    aggregation_temporality, collection_start_nanos\n                )\n                if data_point is not None:\n                    yield data_point\n", "path": "opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py"}]}