|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
15 | | -from opencensus.ext.azure.metrics_exporter.standard_metrics.cpu import ( |
16 | | - ProcessorTimeMetric, |
17 | | -) |
18 | | -from opencensus.ext.azure.metrics_exporter.standard_metrics.http_requests import ( # noqa E501 |
19 | | - RequestsAvgExecutionMetric, |
20 | | - RequestsRateMetric, |
21 | | -) |
22 | | -from opencensus.ext.azure.metrics_exporter.standard_metrics.memory import ( |
23 | | - AvailableMemoryMetric, |
24 | | -) |
25 | | -from opencensus.ext.azure.metrics_exporter.standard_metrics.process import ( |
26 | | - ProcessCPUMetric, |
27 | | - ProcessMemoryMetric, |
28 | | -) |
29 | | -from opencensus.metrics.export.gauge import Registry |
30 | | -from opencensus.metrics.export.metric_producer import MetricProducer |
31 | | - |
32 | | -# List of standard metrics to track |
33 | | -STANDARD_METRICS = [AvailableMemoryMetric, |
34 | | - ProcessCPUMetric, |
35 | | - ProcessMemoryMetric, |
36 | | - ProcessorTimeMetric, |
37 | | - RequestsAvgExecutionMetric, |
38 | | - RequestsRateMetric] |
39 | | - |
40 | | - |
41 | | -def register_metrics(): |
42 | | - registry = Registry() |
43 | | - for standard_metric in STANDARD_METRICS: |
44 | | - metric = standard_metric() |
45 | | - registry.add_gauge(metric()) |
46 | | - return registry |
47 | | - |
48 | | - |
49 | | -class AzureStandardMetricsProducer(MetricProducer): |
50 | | - """Implementation of the producer of standard metrics. |
51 | | -
|
52 | | - Includes Azure specific standard metrics, implemented |
53 | | - using gauges. |
54 | | - """ |
55 | | - def __init__(self): |
56 | | - self.registry = register_metrics() |
57 | | - |
58 | | - def get_metrics(self): |
59 | | - return self.registry.get_metrics() |
60 | | - |
61 | | - |
62 | | -producer = AzureStandardMetricsProducer() |
| 15 | +import collections |
| 16 | +import sys |
| 17 | +import unittest |
| 18 | + |
| 19 | +import mock |
| 20 | +import requests |
| 21 | + |
| 22 | +from opencensus.ext.azure.metrics_exporter import standard_metrics |
| 23 | + |
| 24 | +if sys.version_info < (3,): |
| 25 | + from BaseHTTPServer import HTTPServer |
| 26 | +else: |
| 27 | + from http.server import HTTPServer |
| 28 | + |
| 29 | +ORIGINAL_FUNCTION = requests.Session.request |
| 30 | +ORIGINAL_CONS = HTTPServer.__init__ |
| 31 | + |
| 32 | + |
| 33 | +class TestStandardMetrics(unittest.TestCase): |
| 34 | + def setUp(self): |
| 35 | + standard_metrics.http_requests.requests_map.clear() |
| 36 | + requests.Session.request = ORIGINAL_FUNCTION |
| 37 | + standard_metrics.http_requests.ORIGINAL_CONSTRUCTOR = ORIGINAL_CONS |
| 38 | + |
| 39 | + @mock.patch('opencensus.ext.azure.metrics_exporter' |
| 40 | + '.standard_metrics.register_metrics') |
| 41 | + def test_producer_ctor(self, avail_mock): |
| 42 | + standard_metrics.AzureStandardMetricsProducer() |
| 43 | + |
| 44 | + self.assertEqual(len(avail_mock.call_args_list), 1) |
| 45 | + |
| 46 | + def test_producer_get_metrics(self): |
| 47 | + producer = standard_metrics.AzureStandardMetricsProducer() |
| 48 | + metrics = producer.get_metrics() |
| 49 | + |
| 50 | + self.assertEqual(len(metrics), 6) |
| 51 | + |
| 52 | + def test_register_metrics(self): |
| 53 | + registry = standard_metrics.register_metrics() |
| 54 | + |
| 55 | + self.assertEqual(len(registry.get_metrics()), 6) |
| 56 | + |
| 57 | + def test_get_available_memory_metric(self): |
| 58 | + metric = standard_metrics.AvailableMemoryMetric() |
| 59 | + gauge = metric() |
| 60 | + |
| 61 | + self.assertEqual(gauge.descriptor.name, '\\Memory\\Available Bytes') |
| 62 | + |
| 63 | + @mock.patch('psutil.virtual_memory') |
| 64 | + def test_get_available_memory(self, psutil_mock): |
| 65 | + memory = collections.namedtuple('memory', 'available') |
| 66 | + vmem = memory(available=100) |
| 67 | + psutil_mock.return_value = vmem |
| 68 | + mem = standard_metrics.AvailableMemoryMetric.get_value() |
| 69 | + |
| 70 | + self.assertEqual(mem, 100) |
| 71 | + |
| 72 | + def test_get_process_private_bytes_metric(self): |
| 73 | + metric = standard_metrics.ProcessMemoryMetric() |
| 74 | + gauge = metric() |
| 75 | + |
| 76 | + # TODO: Refactor names to be platform generic |
| 77 | + self.assertEqual(gauge.descriptor.name, |
| 78 | + '\\Process(??APP_WIN32_PROC??)\\Private Bytes') |
| 79 | + |
| 80 | + def test_get_process_private_bytes(self): |
| 81 | + with mock.patch('opencensus.ext.azure.metrics_exporter' |
| 82 | + '.standard_metrics.process.PROCESS') as process_mock: |
| 83 | + memory = collections.namedtuple('memory', 'rss') |
| 84 | + pmem = memory(rss=100) |
| 85 | + process_mock.memory_info.return_value = pmem |
| 86 | + mem = standard_metrics.ProcessMemoryMetric.get_value() |
| 87 | + |
| 88 | + self.assertEqual(mem, 100) |
| 89 | + |
| 90 | + @mock.patch('opencensus.ext.azure.metrics_exporter' |
| 91 | + '.standard_metrics.process.logger') |
| 92 | + def test_get_process_private_bytes_exception(self, logger_mock): |
| 93 | + with mock.patch('opencensus.ext.azure.metrics_exporter' |
| 94 | + '.standard_metrics.process.PROCESS') as process_mock: |
| 95 | + process_mock.memory_info.side_effect = Exception() |
| 96 | + standard_metrics.ProcessMemoryMetric.get_value() |
| 97 | + |
| 98 | + logger_mock.exception.assert_called() |
| 99 | + |
| 100 | + def test_get_processor_time_metric(self): |
| 101 | + metric = standard_metrics.ProcessorTimeMetric() |
| 102 | + gauge = metric() |
| 103 | + |
| 104 | + self.assertEqual(gauge.descriptor.name, |
| 105 | + '\\Processor(_Total)\\% Processor Time') |
| 106 | + |
| 107 | + def test_get_processor_time(self): |
| 108 | + with mock.patch('psutil.cpu_times_percent') as processor_mock: |
| 109 | + cpu = collections.namedtuple('cpu', 'idle') |
| 110 | + cpu_times = cpu(idle=94.5) |
| 111 | + processor_mock.return_value = cpu_times |
| 112 | + processor_time = standard_metrics.ProcessorTimeMetric.get_value() |
| 113 | + |
| 114 | + self.assertEqual(processor_time, 5.5) |
| 115 | + |
| 116 | + def test_get_process_cpu_usage_metric(self): |
| 117 | + metric = standard_metrics.ProcessCPUMetric() |
| 118 | + gauge = metric() |
| 119 | + |
| 120 | + self.assertEqual(gauge.descriptor.name, |
| 121 | + '\\Process(??APP_WIN32_PROC??)\\% Processor Time') |
| 122 | + |
| 123 | + @mock.patch('opencensus.ext.azure.metrics_exporter' |
| 124 | + '.standard_metrics.process.psutil') |
| 125 | + def test_get_process_cpu_usage(self, psutil_mock): |
| 126 | + with mock.patch('opencensus.ext.azure.metrics_exporter' |
| 127 | + '.standard_metrics.process.PROCESS') as process_mock: |
| 128 | + process_mock.cpu_percent.return_value = 44.4 |
| 129 | + psutil_mock.cpu_count.return_value = 2 |
| 130 | + cpu_usage = standard_metrics.ProcessCPUMetric.get_value() |
| 131 | + |
| 132 | + self.assertEqual(cpu_usage, 22.2) |
| 133 | + |
| 134 | + @mock.patch('opencensus.ext.azure.metrics_exporter' |
| 135 | + '.standard_metrics.process.logger') |
| 136 | + def test_get_process_cpu_usage_exception(self, logger_mock): |
| 137 | + with mock.patch('opencensus.ext.azure.metrics_exporter' |
| 138 | + '.standard_metrics.process.psutil') as psutil_mock: |
| 139 | + psutil_mock.cpu_count.return_value = None |
| 140 | + standard_metrics.ProcessCPUMetric.get_value() |
| 141 | + |
| 142 | + logger_mock.exception.assert_called() |
| 143 | + |
| 144 | + def test_request_patch(self): |
| 145 | + map = standard_metrics.http_requests.requests_map |
| 146 | + func = mock.Mock() |
| 147 | + new_func = standard_metrics.http_requests.request_patch(func) |
| 148 | + new_func() |
| 149 | + |
| 150 | + self.assertEqual(map['count'], 1) |
| 151 | + self.assertIsNotNone(map['duration']) |
| 152 | + self.assertEqual(len(func.call_args_list), 1) |
| 153 | + |
| 154 | + def test_server_patch(self): |
| 155 | + standard_metrics. \ |
| 156 | + http_requests. \ |
| 157 | + ORIGINAL_CONSTRUCTOR = lambda x, y, z: None |
| 158 | + with mock.patch('opencensus.ext.azure.metrics_exporter' |
| 159 | + '.standard_metrics.http_requests' |
| 160 | + '.request_patch') as request_mock: |
| 161 | + handler = mock.Mock() |
| 162 | + handler.do_DELETE.return_value = None |
| 163 | + handler.do_GET.return_value = None |
| 164 | + handler.do_HEAD.return_value = None |
| 165 | + handler.do_OPTIONS.return_value = None |
| 166 | + handler.do_POST.return_value = None |
| 167 | + handler.do_PUT.return_value = None |
| 168 | + result = standard_metrics. \ |
| 169 | + http_requests. \ |
| 170 | + server_patch(None, None, handler) |
| 171 | + handler.do_DELETE() |
| 172 | + handler.do_GET() |
| 173 | + handler.do_HEAD() |
| 174 | + handler.do_OPTIONS() |
| 175 | + handler.do_POST() |
| 176 | + handler.do_PUT() |
| 177 | + |
| 178 | + self.assertEqual(result, None) |
| 179 | + self.assertEqual(len(request_mock.call_args_list), 6) |
| 180 | + |
| 181 | + def test_server_patch_no_methods(self): |
| 182 | + standard_metrics. \ |
| 183 | + http_requests. \ |
| 184 | + ORIGINAL_CONSTRUCTOR = lambda x, y, z: None |
| 185 | + with mock.patch('opencensus.ext.azure.metrics_exporter' |
| 186 | + '.standard_metrics.http_requests' |
| 187 | + '.request_patch') as request_mock: |
| 188 | + handler = mock.Mock() |
| 189 | + result = standard_metrics. \ |
| 190 | + http_requests. \ |
| 191 | + server_patch(None, None, handler) |
| 192 | + handler.do_DELETE() |
| 193 | + handler.do_GET() |
| 194 | + handler.do_HEAD() |
| 195 | + handler.do_OPTIONS() |
| 196 | + handler.do_POST() |
| 197 | + handler.do_PUT() |
| 198 | + |
| 199 | + self.assertEqual(result, None) |
| 200 | + self.assertEqual(len(request_mock.call_args_list), 0) |
| 201 | + |
| 202 | + def test_server_patch_no_args(self): |
| 203 | + standard_metrics \ |
| 204 | + .http_requests \ |
| 205 | + .ORIGINAL_CONSTRUCTOR = lambda x, y: None |
| 206 | + r = standard_metrics.http_requests.server_patch(None, None) |
| 207 | + |
| 208 | + self.assertEqual(r, None) |
| 209 | + |
| 210 | + def test_server_patch_no_handler(self): |
| 211 | + standard_metrics \ |
| 212 | + .http_requests \ |
| 213 | + .ORIGINAL_CONSTRUCTOR = lambda x, y, z: None |
| 214 | + r = standard_metrics.http_requests.server_patch(None, None, None) |
| 215 | + |
| 216 | + self.assertEqual(r, None) |
| 217 | + |
| 218 | + def test_get_requests_rate_metric(self): |
| 219 | + metric = standard_metrics.RequestsRateMetric() |
| 220 | + gauge = metric() |
| 221 | + |
| 222 | + name = '\\ASP.NET Applications(??APP_W3SVC_PROC??)\\Requests/Sec' |
| 223 | + self.assertEqual(gauge.descriptor.name, name) |
| 224 | + |
| 225 | + def test_get_requests_rate_first_time(self): |
| 226 | + rate = standard_metrics.http_requests.get_requests_rate() |
| 227 | + |
| 228 | + self.assertEqual(rate, 0) |
| 229 | + |
| 230 | + @mock.patch('opencensus.ext.azure.metrics_exporter' |
| 231 | + '.standard_metrics.http_requests.time') |
| 232 | + def test_get_requests_rate(self, time_mock): |
| 233 | + time_mock.time.return_value = 100 |
| 234 | + standard_metrics.http_requests.requests_map['last_time'] = 98 |
| 235 | + standard_metrics.http_requests.requests_map['count'] = 4 |
| 236 | + rate = standard_metrics.http_requests.get_requests_rate() |
| 237 | + |
| 238 | + self.assertEqual(rate, 2) |
| 239 | + |
| 240 | + @mock.patch('opencensus.ext.azure.metrics_exporter' |
| 241 | + '.standard_metrics.http_requests.time') |
| 242 | + def test_get_requests_rate_error(self, time_mock): |
| 243 | + time_mock.time.return_value = 100 |
| 244 | + standard_metrics.http_requests.requests_map['last_rate'] = 5 |
| 245 | + standard_metrics.http_requests.requests_map['last_time'] = 100 |
| 246 | + result = standard_metrics.http_requests.get_requests_rate() |
| 247 | + |
| 248 | + self.assertEqual(result, 5) |
| 249 | + |
| 250 | + def test_get_requests_execution_metric(self): |
| 251 | + metric = standard_metrics.RequestsAvgExecutionMetric() |
| 252 | + gauge = metric() |
| 253 | + |
| 254 | + name = '\\ASP.NET Applications(??APP_W3SVC_PROC??)' \ |
| 255 | + '\\Request Execution Time' |
| 256 | + self.assertEqual(gauge.descriptor.name, name) |
| 257 | + |
| 258 | + def test_get_requests_execution(self): |
| 259 | + map = standard_metrics.http_requests.requests_map |
| 260 | + map['duration'] = 0.1 |
| 261 | + map['count'] = 10 |
| 262 | + map['last_count'] = 5 |
| 263 | + result = standard_metrics.http_requests.get_average_execution_time() |
| 264 | + |
| 265 | + self.assertEqual(result, 20) |
| 266 | + |
| 267 | + def test_get_requests_execution_error(self): |
| 268 | + map = standard_metrics.http_requests.requests_map |
| 269 | + map['duration'] = 0.1 |
| 270 | + map['count'] = 10 |
| 271 | + map['last_count'] = 10 |
| 272 | + result = standard_metrics.http_requests.get_average_execution_time() |
| 273 | + |
| 274 | + self.assertEqual(result, 0) |
0 commit comments