|
12 | 12 | # See the License for the specific language governing permissions and
|
13 | 13 | # limitations under the License.
|
14 | 14 |
|
| 15 | +from timeit import default_timer |
15 | 16 | from unittest.mock import patch
|
16 | 17 |
|
17 | 18 | from pyramid.config import Configurator
|
18 | 19 |
|
19 | 20 | from opentelemetry import trace
|
20 | 21 | from opentelemetry.instrumentation.pyramid import PyramidInstrumentor
|
| 22 | +from opentelemetry.sdk.metrics.export import ( |
| 23 | + HistogramDataPoint, |
| 24 | + NumberDataPoint, |
| 25 | +) |
21 | 26 | from opentelemetry.test.globals_test import reset_trace_globals
|
22 | 27 | from opentelemetry.test.wsgitestutil import WsgiTestBase
|
23 | 28 | from opentelemetry.trace import SpanKind
|
24 | 29 | from opentelemetry.trace.status import StatusCode
|
25 | 30 | from opentelemetry.util.http import (
|
26 | 31 | OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST,
|
27 | 32 | OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE,
|
| 33 | + _active_requests_count_attrs, |
| 34 | + _duration_attrs, |
28 | 35 | )
|
29 | 36 |
|
30 | 37 | # pylint: disable=import-error
|
31 | 38 | from .pyramid_base_test import InstrumentationTest
|
32 | 39 |
|
| 40 | +_expected_metric_names = [ |
| 41 | + "http.server.active_requests", |
| 42 | + "http.server.duration", |
| 43 | +] |
| 44 | +_recommended_attrs = { |
| 45 | + "http.server.active_requests": _active_requests_count_attrs, |
| 46 | + "http.server.duration": _duration_attrs, |
| 47 | +} |
| 48 | + |
33 | 49 |
|
34 | 50 | class TestAutomatic(InstrumentationTest, WsgiTestBase):
|
35 | 51 | def setUp(self):
|
@@ -156,6 +172,89 @@ def test_400s_response_is_not_an_error(self):
|
156 | 172 | span_list = self.memory_exporter.get_finished_spans()
|
157 | 173 | self.assertEqual(len(span_list), 1)
|
158 | 174 |
|
| 175 | + def test_pyramid_metric(self): |
| 176 | + self.client.get("/hello/756") |
| 177 | + self.client.get("/hello/756") |
| 178 | + self.client.get("/hello/756") |
| 179 | + metrics_list = self.memory_metrics_reader.get_metrics_data() |
| 180 | + number_data_point_seen = False |
| 181 | + histogram_data_point_seen = False |
| 182 | + self.assertTrue(len(metrics_list.resource_metrics) == 1) |
| 183 | + for resource_metric in metrics_list.resource_metrics: |
| 184 | + self.assertTrue(len(resource_metric.scope_metrics) == 1) |
| 185 | + for scope_metric in resource_metric.scope_metrics: |
| 186 | + self.assertTrue(len(scope_metric.metrics) == 2) |
| 187 | + for metric in scope_metric.metrics: |
| 188 | + self.assertIn(metric.name, _expected_metric_names) |
| 189 | + data_points = list(metric.data.data_points) |
| 190 | + self.assertEqual(len(data_points), 1) |
| 191 | + for point in data_points: |
| 192 | + if isinstance(point, HistogramDataPoint): |
| 193 | + self.assertEqual(point.count, 3) |
| 194 | + histogram_data_point_seen = True |
| 195 | + if isinstance(point, NumberDataPoint): |
| 196 | + number_data_point_seen = True |
| 197 | + for attr in point.attributes: |
| 198 | + self.assertIn( |
| 199 | + attr, _recommended_attrs[metric.name] |
| 200 | + ) |
| 201 | + self.assertTrue(number_data_point_seen and histogram_data_point_seen) |
| 202 | + |
| 203 | + def test_basic_metric_success(self): |
| 204 | + start = default_timer() |
| 205 | + self.client.get("/hello/756") |
| 206 | + duration = max(round((default_timer() - start) * 1000), 0) |
| 207 | + expected_duration_attributes = { |
| 208 | + "http.method": "GET", |
| 209 | + "http.host": "localhost", |
| 210 | + "http.scheme": "http", |
| 211 | + "http.flavor": "1.1", |
| 212 | + "http.server_name": "localhost", |
| 213 | + "net.host.port": 80, |
| 214 | + "http.status_code": 200, |
| 215 | + } |
| 216 | + expected_requests_count_attributes = { |
| 217 | + "http.method": "GET", |
| 218 | + "http.host": "localhost", |
| 219 | + "http.scheme": "http", |
| 220 | + "http.flavor": "1.1", |
| 221 | + "http.server_name": "localhost", |
| 222 | + } |
| 223 | + metrics_list = self.memory_metrics_reader.get_metrics_data() |
| 224 | + for metric in ( |
| 225 | + metrics_list.resource_metrics[0].scope_metrics[0].metrics |
| 226 | + ): |
| 227 | + for point in list(metric.data.data_points): |
| 228 | + if isinstance(point, HistogramDataPoint): |
| 229 | + self.assertDictEqual( |
| 230 | + expected_duration_attributes, |
| 231 | + dict(point.attributes), |
| 232 | + ) |
| 233 | + self.assertEqual(point.count, 1) |
| 234 | + self.assertAlmostEqual(duration, point.sum, delta=20) |
| 235 | + if isinstance(point, NumberDataPoint): |
| 236 | + self.assertDictEqual( |
| 237 | + expected_requests_count_attributes, |
| 238 | + dict(point.attributes), |
| 239 | + ) |
| 240 | + self.assertEqual(point.value, 0) |
| 241 | + |
| 242 | + def test_metric_uninstruemnt(self): |
| 243 | + self.client.get("/hello/756") |
| 244 | + PyramidInstrumentor().uninstrument() |
| 245 | + self.config = Configurator() |
| 246 | + self._common_initialization(self.config) |
| 247 | + self.client.get("/hello/756") |
| 248 | + metrics_list = self.memory_metrics_reader.get_metrics_data() |
| 249 | + for metric in ( |
| 250 | + metrics_list.resource_metrics[0].scope_metrics[0].metrics |
| 251 | + ): |
| 252 | + for point in list(metric.data.data_points): |
| 253 | + if isinstance(point, HistogramDataPoint): |
| 254 | + self.assertEqual(point.count, 1) |
| 255 | + if isinstance(point, NumberDataPoint): |
| 256 | + self.assertEqual(point.value, 0) |
| 257 | + |
159 | 258 |
|
160 | 259 | class TestWrappedWithOtherFramework(InstrumentationTest, WsgiTestBase):
|
161 | 260 | def setUp(self):
|
|
0 commit comments