deltacat 1.1.0__py3-none-any.whl → 1.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,575 @@
1
+ import unittest
2
+ from unittest.mock import MagicMock, ANY, call
3
+ import ray
4
+ from deltacat.utils.metrics import (
5
+ metrics,
6
+ success_metric,
7
+ failure_metric,
8
+ latency_metric,
9
+ MetricsActor,
10
+ METRICS_CONFIG_ACTOR_NAME,
11
+ MetricsConfig,
12
+ MetricsTarget,
13
+ METRICS_TARGET_TO_EMITTER_DICT,
14
+ )
15
+ from deltacat.utils.performance import timed_invocation
16
+
17
+
18
+ def method_not_annotated(mock_func):
19
+ mock_func("called")
20
+
21
+
22
+ @metrics
23
+ def metrics_annotated_method(mock_func):
24
+ mock_func("called")
25
+
26
+
27
+ @metrics
28
+ def metrics_annotated_method_error(mock_func):
29
+ raise ValueError()
30
+
31
+
32
+ @metrics(prefix="test_prefix")
33
+ def metrics_with_prefix_annotated_method(mock_func):
34
+ mock_func("called")
35
+
36
+
37
+ @metrics(prefix="test_prefix")
38
+ def metrics_with_prefix_annotated_method_error(mock_func):
39
+ raise ValueError()
40
+
41
+
42
+ class TestMetricsAnnotation(unittest.TestCase):
43
+ def test_metrics_annotation_sanity(self):
44
+ mock, mock_target = MagicMock(), MagicMock()
45
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
46
+ metrics_actor = MetricsActor.options(
47
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
48
+ ).remote()
49
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
50
+ ray.get(metrics_actor.set_metrics_config.remote(config))
51
+
52
+ # action
53
+ metrics_annotated_method(mock)
54
+
55
+ mock.assert_called_once()
56
+ self.assertEqual(2, mock_target.call_count)
57
+ mock_target.assert_has_calls(
58
+ [
59
+ call(
60
+ metrics_name="metrics_annotated_method_time",
61
+ metrics_config=ANY,
62
+ value=ANY,
63
+ ),
64
+ call(
65
+ metrics_name="metrics_annotated_method_success_count",
66
+ metrics_config=ANY,
67
+ value=ANY,
68
+ ),
69
+ ],
70
+ any_order=True,
71
+ )
72
+
73
+ def test_metrics_annotation_when_error(self):
74
+ mock, mock_target = MagicMock(), MagicMock()
75
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
76
+ metrics_actor = MetricsActor.options(
77
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
78
+ ).remote()
79
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
80
+ ray.get(metrics_actor.set_metrics_config.remote(config))
81
+
82
+ # action
83
+ self.assertRaises(ValueError, lambda: metrics_annotated_method_error(mock))
84
+
85
+ mock.assert_not_called()
86
+ self.assertEqual(3, mock_target.call_count)
87
+ mock_target.assert_has_calls(
88
+ [
89
+ call(
90
+ metrics_name="metrics_annotated_method_error_time",
91
+ metrics_config=ANY,
92
+ value=ANY,
93
+ ),
94
+ call(
95
+ metrics_name="metrics_annotated_method_error_failure_count",
96
+ metrics_config=ANY,
97
+ value=ANY,
98
+ ),
99
+ call(
100
+ metrics_name="metrics_annotated_method_error_failure_count.ValueError",
101
+ metrics_config=ANY,
102
+ value=ANY,
103
+ ),
104
+ ],
105
+ any_order=True,
106
+ )
107
+
108
+ def test_metrics_with_prefix_annotation_sanity(self):
109
+ mock, mock_target = MagicMock(), MagicMock()
110
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
111
+ metrics_actor = MetricsActor.options(
112
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
113
+ ).remote()
114
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
115
+ ray.get(metrics_actor.set_metrics_config.remote(config))
116
+
117
+ # action
118
+ metrics_with_prefix_annotated_method(mock)
119
+
120
+ mock.assert_called_once()
121
+ self.assertEqual(2, mock_target.call_count)
122
+ mock_target.assert_has_calls(
123
+ [
124
+ call(metrics_name="test_prefix_time", metrics_config=ANY, value=ANY),
125
+ call(
126
+ metrics_name="test_prefix_success_count",
127
+ metrics_config=ANY,
128
+ value=ANY,
129
+ ),
130
+ ],
131
+ any_order=True,
132
+ )
133
+
134
+ def test_metrics_annotation_performance(self):
135
+ mock, mock_target = MagicMock(), MagicMock()
136
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
137
+ metrics_actor = MetricsActor.options(
138
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
139
+ ).remote()
140
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
141
+ ray.get(metrics_actor.set_metrics_config.remote(config))
142
+
143
+ # action with annotation
144
+ _, actual_latency = timed_invocation(metrics_annotated_method, mock)
145
+ _, second_call_latency = timed_invocation(metrics_annotated_method, mock)
146
+
147
+ mock.assert_called()
148
+ self.assertEqual(4, mock_target.call_count)
149
+ self.assertLess(
150
+ second_call_latency,
151
+ actual_latency,
152
+ "Second call to actor must be much faster",
153
+ )
154
+
155
+ def test_metrics_with_prefix_annotation_when_error(self):
156
+ mock, mock_target = MagicMock(), MagicMock()
157
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
158
+ metrics_actor = MetricsActor.options(
159
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
160
+ ).remote()
161
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
162
+ ray.get(metrics_actor.set_metrics_config.remote(config))
163
+
164
+ # action
165
+ self.assertRaises(
166
+ ValueError, lambda: metrics_with_prefix_annotated_method_error(mock)
167
+ )
168
+
169
+ mock.assert_not_called()
170
+ self.assertEqual(3, mock_target.call_count)
171
+ mock_target.assert_has_calls(
172
+ [
173
+ call(metrics_name="test_prefix_time", metrics_config=ANY, value=ANY),
174
+ call(
175
+ metrics_name="test_prefix_failure_count",
176
+ metrics_config=ANY,
177
+ value=ANY,
178
+ ),
179
+ call(
180
+ metrics_name="test_prefix_failure_count.ValueError",
181
+ metrics_config=ANY,
182
+ value=ANY,
183
+ ),
184
+ ],
185
+ any_order=True,
186
+ )
187
+
188
+ def test_metrics_with_prefix_annotation_without_actor(self):
189
+ mock, mock_target = MagicMock(), MagicMock()
190
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
191
+ metrics_actor = MetricsActor.options(
192
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
193
+ ).remote()
194
+
195
+ # explicitly making sure actor is killed
196
+ ray.kill(metrics_actor)
197
+
198
+ # action
199
+ self.assertRaises(
200
+ ValueError, lambda: metrics_with_prefix_annotated_method_error(mock)
201
+ )
202
+
203
+ mock.assert_not_called()
204
+ mock_target.assert_not_called()
205
+
206
+
207
+ @latency_metric
208
+ def latency_metric_annotated_method(mock_func):
209
+ mock_func("called")
210
+
211
+
212
+ @latency_metric
213
+ def latency_metric_annotated_method_error(mock_func):
214
+ raise ValueError()
215
+
216
+
217
+ @latency_metric(name="test")
218
+ def latency_metric_with_name_annotated_method(mock_func):
219
+ mock_func("called")
220
+
221
+
222
+ @latency_metric(name="test")
223
+ def latency_metric_with_name_annotated_method_error(mock_func):
224
+ raise ValueError()
225
+
226
+
227
+ class TestLatencyMetricAnnotation(unittest.TestCase):
228
+ def test_annotation_sanity(self):
229
+ mock, mock_target = MagicMock(), MagicMock()
230
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
231
+ metrics_actor = MetricsActor.options(
232
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
233
+ ).remote()
234
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
235
+ ray.get(metrics_actor.set_metrics_config.remote(config))
236
+
237
+ # action
238
+ latency_metric_annotated_method(mock)
239
+
240
+ mock.assert_called_once()
241
+ self.assertEqual(1, mock_target.call_count)
242
+ mock_target.assert_has_calls(
243
+ [
244
+ call(
245
+ metrics_name="latency_metric_annotated_method_time",
246
+ metrics_config=ANY,
247
+ value=ANY,
248
+ )
249
+ ],
250
+ any_order=True,
251
+ )
252
+
253
+ def test_annotation_when_error(self):
254
+ mock, mock_target = MagicMock(), MagicMock()
255
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
256
+ metrics_actor = MetricsActor.options(
257
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
258
+ ).remote()
259
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
260
+ ray.get(metrics_actor.set_metrics_config.remote(config))
261
+
262
+ # action
263
+ self.assertRaises(
264
+ ValueError, lambda: latency_metric_annotated_method_error(mock)
265
+ )
266
+
267
+ mock.assert_not_called()
268
+ self.assertEqual(1, mock_target.call_count)
269
+ mock_target.assert_has_calls(
270
+ [
271
+ call(
272
+ metrics_name="latency_metric_annotated_method_error_time",
273
+ metrics_config=ANY,
274
+ value=ANY,
275
+ )
276
+ ],
277
+ any_order=True,
278
+ )
279
+
280
+ def test_annotation_with_args_sanity(self):
281
+ mock, mock_target = MagicMock(), MagicMock()
282
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
283
+ metrics_actor = MetricsActor.options(
284
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
285
+ ).remote()
286
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
287
+ ray.get(metrics_actor.set_metrics_config.remote(config))
288
+
289
+ # action
290
+ latency_metric_with_name_annotated_method(mock)
291
+
292
+ mock.assert_called_once()
293
+ self.assertEqual(1, mock_target.call_count)
294
+ mock_target.assert_has_calls(
295
+ [call(metrics_name="test", metrics_config=ANY, value=ANY)], any_order=True
296
+ )
297
+
298
+ def test_annotation_with_args_when_error(self):
299
+ mock, mock_target = MagicMock(), MagicMock()
300
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
301
+ metrics_actor = MetricsActor.options(
302
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
303
+ ).remote()
304
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
305
+ ray.get(metrics_actor.set_metrics_config.remote(config))
306
+
307
+ # action
308
+ self.assertRaises(
309
+ ValueError, lambda: latency_metric_with_name_annotated_method_error(mock)
310
+ )
311
+
312
+ mock.assert_not_called()
313
+ self.assertEqual(1, mock_target.call_count)
314
+ mock_target.assert_has_calls(
315
+ [call(metrics_name="test", metrics_config=ANY, value=ANY)], any_order=True
316
+ )
317
+
318
+ def test_annotation_without_actor(self):
319
+ mock, mock_target = MagicMock(), MagicMock()
320
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
321
+ metrics_actor = MetricsActor.options(
322
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
323
+ ).remote()
324
+
325
+ # explicitly making sure actor is killed
326
+ ray.kill(metrics_actor)
327
+
328
+ # action
329
+ self.assertRaises(
330
+ ValueError, lambda: latency_metric_with_name_annotated_method_error(mock)
331
+ )
332
+
333
+ mock.assert_not_called()
334
+ mock_target.assert_not_called()
335
+
336
+
337
+ @success_metric
338
+ def success_metric_annotated_method(mock_func):
339
+ mock_func("called")
340
+
341
+
342
+ @success_metric
343
+ def success_metric_annotated_method_error(mock_func):
344
+ raise ValueError()
345
+
346
+
347
+ @success_metric(name="test")
348
+ def success_metric_with_name_annotated_method(mock_func):
349
+ mock_func("called")
350
+
351
+
352
+ @success_metric(name="test")
353
+ def success_metric_with_name_annotated_method_error(mock_func):
354
+ raise ValueError()
355
+
356
+
357
+ class TestSuccessMetricAnnotation(unittest.TestCase):
358
+ def test_annotation_sanity(self):
359
+ mock, mock_target = MagicMock(), MagicMock()
360
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
361
+ metrics_actor = MetricsActor.options(
362
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
363
+ ).remote()
364
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
365
+ ray.get(metrics_actor.set_metrics_config.remote(config))
366
+
367
+ # action
368
+ success_metric_annotated_method(mock)
369
+
370
+ mock.assert_called_once()
371
+ self.assertEqual(1, mock_target.call_count)
372
+ mock_target.assert_has_calls(
373
+ [
374
+ call(
375
+ metrics_name="success_metric_annotated_method_success_count",
376
+ metrics_config=ANY,
377
+ value=ANY,
378
+ )
379
+ ],
380
+ any_order=True,
381
+ )
382
+
383
+ def test_annotation_when_error(self):
384
+ mock, mock_target = MagicMock(), MagicMock()
385
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
386
+ metrics_actor = MetricsActor.options(
387
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
388
+ ).remote()
389
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
390
+ ray.get(metrics_actor.set_metrics_config.remote(config))
391
+
392
+ # action
393
+ self.assertRaises(
394
+ ValueError, lambda: success_metric_annotated_method_error(mock)
395
+ )
396
+
397
+ mock.assert_not_called()
398
+ mock_target.assert_not_called()
399
+
400
+ def test_annotation_with_args_sanity(self):
401
+ mock, mock_target = MagicMock(), MagicMock()
402
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
403
+ metrics_actor = MetricsActor.options(
404
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
405
+ ).remote()
406
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
407
+ ray.get(metrics_actor.set_metrics_config.remote(config))
408
+
409
+ # action
410
+ success_metric_with_name_annotated_method(mock)
411
+
412
+ mock.assert_called_once()
413
+ self.assertEqual(1, mock_target.call_count)
414
+ mock_target.assert_has_calls(
415
+ [call(metrics_name="test", metrics_config=ANY, value=ANY)], any_order=True
416
+ )
417
+
418
+ def test_annotation_with_args_when_error(self):
419
+ mock, mock_target = MagicMock(), MagicMock()
420
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
421
+ metrics_actor = MetricsActor.options(
422
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
423
+ ).remote()
424
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
425
+ ray.get(metrics_actor.set_metrics_config.remote(config))
426
+
427
+ # action
428
+ self.assertRaises(
429
+ ValueError, lambda: success_metric_with_name_annotated_method_error(mock)
430
+ )
431
+
432
+ mock.assert_not_called()
433
+ mock_target.assert_not_called()
434
+
435
+ def test_annotation_without_actor(self):
436
+ mock, mock_target = MagicMock(), MagicMock()
437
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
438
+ metrics_actor = MetricsActor.options(
439
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
440
+ ).remote()
441
+
442
+ # explicitly making sure actor is killed
443
+ ray.kill(metrics_actor)
444
+
445
+ # action
446
+ success_metric_annotated_method(mock)
447
+
448
+ mock.assert_called_once()
449
+ mock_target.assert_not_called()
450
+
451
+
452
+ @failure_metric
453
+ def failure_metric_annotated_method(mock_func):
454
+ mock_func("called")
455
+
456
+
457
+ @failure_metric
458
+ def failure_metric_annotated_method_error(mock_func):
459
+ raise ValueError()
460
+
461
+
462
+ @failure_metric(name="test")
463
+ def failure_metric_with_name_annotated_method(mock_func):
464
+ mock_func("called")
465
+
466
+
467
+ @failure_metric(name="test")
468
+ def failure_metric_with_name_annotated_method_error(mock_func):
469
+ raise ValueError()
470
+
471
+
472
+ class TestFailureMetricAnnotation(unittest.TestCase):
473
+ def test_annotation_sanity(self):
474
+ mock, mock_target = MagicMock(), MagicMock()
475
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
476
+ metrics_actor = MetricsActor.options(
477
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
478
+ ).remote()
479
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
480
+ ray.get(metrics_actor.set_metrics_config.remote(config))
481
+
482
+ # action
483
+ failure_metric_annotated_method(mock)
484
+
485
+ mock.assert_called_once()
486
+ mock_target.assert_not_called()
487
+
488
+ def test_annotation_when_error(self):
489
+ mock, mock_target = MagicMock(), MagicMock()
490
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
491
+ metrics_actor = MetricsActor.options(
492
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
493
+ ).remote()
494
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
495
+ ray.get(metrics_actor.set_metrics_config.remote(config))
496
+
497
+ # action
498
+ self.assertRaises(
499
+ ValueError, lambda: failure_metric_annotated_method_error(mock)
500
+ )
501
+
502
+ mock.assert_not_called()
503
+ self.assertEqual(2, mock_target.call_count)
504
+ mock_target.assert_has_calls(
505
+ [
506
+ call(
507
+ metrics_name="failure_metric_annotated_method_error_failure_count.ValueError",
508
+ metrics_config=ANY,
509
+ value=ANY,
510
+ ),
511
+ call(
512
+ metrics_name="failure_metric_annotated_method_error_failure_count",
513
+ metrics_config=ANY,
514
+ value=ANY,
515
+ ),
516
+ ],
517
+ any_order=True,
518
+ )
519
+
520
+ def test_annotation_with_args_sanity(self):
521
+ mock, mock_target = MagicMock(), MagicMock()
522
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
523
+ metrics_actor = MetricsActor.options(
524
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
525
+ ).remote()
526
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
527
+ ray.get(metrics_actor.set_metrics_config.remote(config))
528
+
529
+ # action
530
+ failure_metric_with_name_annotated_method(mock)
531
+
532
+ mock.assert_called_once()
533
+ mock_target.assert_not_called()
534
+
535
+ def test_annotation_with_args_when_error(self):
536
+ mock, mock_target = MagicMock(), MagicMock()
537
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
538
+ metrics_actor = MetricsActor.options(
539
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
540
+ ).remote()
541
+ config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
542
+ ray.get(metrics_actor.set_metrics_config.remote(config))
543
+
544
+ # action
545
+ self.assertRaises(
546
+ ValueError, lambda: failure_metric_with_name_annotated_method_error(mock)
547
+ )
548
+
549
+ mock.assert_not_called()
550
+ self.assertEqual(2, mock_target.call_count)
551
+ mock_target.assert_has_calls(
552
+ [
553
+ call(metrics_name="test.ValueError", metrics_config=ANY, value=ANY),
554
+ call(metrics_name="test", metrics_config=ANY, value=ANY),
555
+ ],
556
+ any_order=True,
557
+ )
558
+
559
+ def test_annotation_without_actor(self):
560
+ mock, mock_target = MagicMock(), MagicMock()
561
+ METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
562
+ metrics_actor = MetricsActor.options(
563
+ name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
564
+ ).remote()
565
+
566
+ # explicitly making sure actor is killed
567
+ ray.kill(metrics_actor)
568
+
569
+ # action
570
+ self.assertRaises(
571
+ ValueError, lambda: failure_metric_with_name_annotated_method_error(mock)
572
+ )
573
+
574
+ mock.assert_not_called()
575
+ mock_target.assert_not_called()