sentry-arroyo 2.31.0__py3-none-any.whl → 2.31.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.
- arroyo/backends/kafka/consumer.py +36 -6
- arroyo/processing/processor.py +3 -3
- {sentry_arroyo-2.31.0.dist-info → sentry_arroyo-2.31.2.dist-info}/METADATA +1 -1
- {sentry_arroyo-2.31.0.dist-info → sentry_arroyo-2.31.2.dist-info}/RECORD +8 -8
- tests/backends/test_confluent_producer.py +19 -4
- {sentry_arroyo-2.31.0.dist-info → sentry_arroyo-2.31.2.dist-info}/WHEEL +0 -0
- {sentry_arroyo-2.31.0.dist-info → sentry_arroyo-2.31.2.dist-info}/licenses/LICENSE +0 -0
- {sentry_arroyo-2.31.0.dist-info → sentry_arroyo-2.31.2.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import time
|
|
5
|
+
from collections import defaultdict
|
|
4
6
|
from concurrent.futures import Future
|
|
5
7
|
from datetime import datetime
|
|
6
8
|
from enum import Enum
|
|
@@ -21,6 +23,7 @@ from typing import (
|
|
|
21
23
|
Tuple,
|
|
22
24
|
Type,
|
|
23
25
|
Union,
|
|
26
|
+
cast,
|
|
24
27
|
)
|
|
25
28
|
|
|
26
29
|
from confluent_kafka import (
|
|
@@ -748,6 +751,9 @@ class KafkaProducer(Producer[KafkaPayload]):
|
|
|
748
751
|
# Type alias for the delivery callback function
|
|
749
752
|
DeliveryCallback = Callable[[Optional[KafkaError], ConfluentMessage], None]
|
|
750
753
|
|
|
754
|
+
# Interval between metric flushes (in seconds)
|
|
755
|
+
METRICS_FREQUENCY_SEC = 1.0
|
|
756
|
+
|
|
751
757
|
|
|
752
758
|
class ConfluentProducer(ConfluentKafkaProducer): # type: ignore[misc]
|
|
753
759
|
"""
|
|
@@ -756,7 +762,10 @@ class ConfluentProducer(ConfluentKafkaProducer): # type: ignore[misc]
|
|
|
756
762
|
|
|
757
763
|
def __init__(self, configuration: Mapping[str, Any]) -> None:
|
|
758
764
|
super().__init__(configuration)
|
|
765
|
+
self.producer_name = configuration.get("client.id") or None
|
|
759
766
|
self.__metrics = get_metrics()
|
|
767
|
+
self.__produce_counters: MutableMapping[str, int] = defaultdict(int)
|
|
768
|
+
self.__reset_metrics()
|
|
760
769
|
|
|
761
770
|
def __metrics_delivery_callback(
|
|
762
771
|
self,
|
|
@@ -767,12 +776,8 @@ class ConfluentProducer(ConfluentKafkaProducer): # type: ignore[misc]
|
|
|
767
776
|
status = "error"
|
|
768
777
|
else:
|
|
769
778
|
status = "success"
|
|
770
|
-
|
|
771
|
-
self.
|
|
772
|
-
"arroyo.producer.produce_status",
|
|
773
|
-
1,
|
|
774
|
-
tags={"status": status},
|
|
775
|
-
)
|
|
779
|
+
self.__produce_counters[status] += 1
|
|
780
|
+
self.__throttled_record()
|
|
776
781
|
|
|
777
782
|
def __delivery_callback(
|
|
778
783
|
self,
|
|
@@ -792,3 +797,28 @@ class ConfluentProducer(ConfluentKafkaProducer): # type: ignore[misc]
|
|
|
792
797
|
user_callback = callback or on_delivery
|
|
793
798
|
wrapped_callback = self.__delivery_callback(user_callback)
|
|
794
799
|
super().produce(*args, on_delivery=wrapped_callback, **kwargs)
|
|
800
|
+
|
|
801
|
+
def __flush_metrics(self) -> None:
|
|
802
|
+
for status, count in self.__produce_counters.items():
|
|
803
|
+
tags = {"status": status}
|
|
804
|
+
if self.producer_name:
|
|
805
|
+
tags["producer_name"] = self.producer_name
|
|
806
|
+
self.__metrics.increment(
|
|
807
|
+
name="arroyo.producer.produce_status",
|
|
808
|
+
value=count,
|
|
809
|
+
tags=tags,
|
|
810
|
+
)
|
|
811
|
+
self.__reset_metrics()
|
|
812
|
+
|
|
813
|
+
def flush(self, timeout: float = -1) -> int:
|
|
814
|
+
# Kafka producer flush should flush metrics too
|
|
815
|
+
self.__flush_metrics()
|
|
816
|
+
return cast(int, super().flush(timeout))
|
|
817
|
+
|
|
818
|
+
def __reset_metrics(self) -> None:
|
|
819
|
+
self.__produce_counters.clear()
|
|
820
|
+
self.__last_record_time = time.time()
|
|
821
|
+
|
|
822
|
+
def __throttled_record(self) -> None:
|
|
823
|
+
if time.time() - self.__last_record_time > METRICS_FREQUENCY_SEC:
|
|
824
|
+
self.__flush_metrics()
|
arroyo/processing/processor.py
CHANGED
|
@@ -146,9 +146,9 @@ class StreamProcessor(Generic[TStrategyPayload]):
|
|
|
146
146
|
self.__processor_factory = processor_factory
|
|
147
147
|
self.__metrics_buffer = MetricsBuffer()
|
|
148
148
|
|
|
149
|
-
self.__processing_strategy: Optional[
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
self.__processing_strategy: Optional[ProcessingStrategy[TStrategyPayload]] = (
|
|
150
|
+
None
|
|
151
|
+
)
|
|
152
152
|
|
|
153
153
|
self.__message: Optional[BrokerValue[TStrategyPayload]] = None
|
|
154
154
|
|
|
@@ -9,14 +9,14 @@ arroyo/backends/abstract.py,sha256=NQ5xG9rjchSUW8URl1WtSYSzMFtwRKB6wtJhWmDyR9E,9
|
|
|
9
9
|
arroyo/backends/kafka/__init__.py,sha256=xgf-AqHbQkJsh73YokO2uoyyHfZf8XwUp6BULtM8stI,445
|
|
10
10
|
arroyo/backends/kafka/commit.py,sha256=LPsjvX5PPXR62DT6sa5GuSF78qk9F_L--Fz4kw7-m-s,3060
|
|
11
11
|
arroyo/backends/kafka/configuration.py,sha256=g1Y-vdu3OT9pqWuYRp9fw29Nmm1KBBExQLr3VhDsp90,8950
|
|
12
|
-
arroyo/backends/kafka/consumer.py,sha256=
|
|
12
|
+
arroyo/backends/kafka/consumer.py,sha256=hABMHwTFm0IMziSCTxDQkepvATjcKCjDB0l_NFPypKs,31093
|
|
13
13
|
arroyo/backends/local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
arroyo/backends/local/backend.py,sha256=7odjCnzoGgdo8JHLgG1ntaXa-ZR9GteGkquiA2WAWmM,13880
|
|
15
15
|
arroyo/backends/local/storages/__init__.py,sha256=AGYujdAAcn3osoj9jq84IzTywYbkIDv9wRg2rLhLXeg,104
|
|
16
16
|
arroyo/backends/local/storages/abstract.py,sha256=1qVQp6roxHkK6XT2aklZyZk1qq7RzcPN6Db_CA5--kg,2901
|
|
17
17
|
arroyo/backends/local/storages/memory.py,sha256=AoKDsVZzBXkOJyWArKWp3vfGfU9xLlKFXE9gsJiMIzQ,2613
|
|
18
18
|
arroyo/processing/__init__.py,sha256=vZVg0wJvJfoVzlzGvnL59bT6YNIRJNQ5t7oU045Qbk4,87
|
|
19
|
-
arroyo/processing/processor.py,sha256=
|
|
19
|
+
arroyo/processing/processor.py,sha256=PeuCnnwp2Ehxkl3Wj_81ICKbWe45OJya1rByYcYJNlA,21323
|
|
20
20
|
arroyo/processing/strategies/__init__.py,sha256=EU_JMb54eOxMxaC5mIFpI-sAF-X2ZScbE8czBZ7bQkY,1106
|
|
21
21
|
arroyo/processing/strategies/abstract.py,sha256=nu7juEz_aQmQIH35Z8u--FBuLjkK8_LQ1hIG2xpw9AA,4808
|
|
22
22
|
arroyo/processing/strategies/batching.py,sha256=s89xC6lQpBseEaApu1iNTipXGKeO95OMwinj2VBKn9s,4778
|
|
@@ -46,11 +46,11 @@ examples/transform_and_produce/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
|
|
|
46
46
|
examples/transform_and_produce/batched.py,sha256=st2R6qTneAtV0JFbKP30Ti3sJDYj8Jkbmta9JckKdZU,2636
|
|
47
47
|
examples/transform_and_produce/script.py,sha256=8kSMIjQNqGYEVyE0PvrfJh-a_UYCrJSstTp_De7kyyg,2306
|
|
48
48
|
examples/transform_and_produce/simple.py,sha256=H7xqxItjl4tx34wVW5dy6mB9G39QucAtxkJSBzVmjgA,1637
|
|
49
|
-
sentry_arroyo-2.31.
|
|
49
|
+
sentry_arroyo-2.31.2.dist-info/licenses/LICENSE,sha256=0Ng3MFdEcnz0sVD1XvGBBzbavvNp_7OAM5yVObB46jU,10829
|
|
50
50
|
tests/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
51
51
|
tests/backends/mixins.py,sha256=sfNyE0VTeiD3GHOnBYl-9urvPuURI2G1BWke0cz7Dvc,20445
|
|
52
52
|
tests/backends/test_commit.py,sha256=iTHfK1qsBxim0XwxgMvNNSMqDUMEHoYkYBDcgxGBFbs,831
|
|
53
|
-
tests/backends/test_confluent_producer.py,sha256=
|
|
53
|
+
tests/backends/test_confluent_producer.py,sha256=KWqgvjDvqAdd0HxngdWKsUJaV7Hl1L5vAVQhBYlHeHU,3146
|
|
54
54
|
tests/backends/test_kafka.py,sha256=6W6EA41X-ECTfcOeivhQxURnmV2Y0fYy-UzDCnJgDsU,12830
|
|
55
55
|
tests/backends/test_kafka_producer.py,sha256=LpwkqnstcCDxemlKZ0FpzNKrP-1UuXXY15P7P-spjhE,3912
|
|
56
56
|
tests/backends/test_local.py,sha256=Mfd4DFuWVSVtl1GomQ6TIoWuJNcAliKqKU0BShPlEMY,3363
|
|
@@ -74,7 +74,7 @@ tests/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
74
74
|
tests/utils/test_concurrent.py,sha256=Gwdzym2UZ1HO3rhOSGmzxImWcLFygY8P7MXHT3Q0xTE,455
|
|
75
75
|
tests/utils/test_metrics.py,sha256=bI0EtGgPokMQyEqX58i0-8zvLfxRP2nWaWr2wLMaJ_o,917
|
|
76
76
|
tests/utils/test_retries.py,sha256=AxJLkXWeL9AjHv_p1n0pe8CXXJp24ZQIuYBHfNcmiz4,3075
|
|
77
|
-
sentry_arroyo-2.31.
|
|
78
|
-
sentry_arroyo-2.31.
|
|
79
|
-
sentry_arroyo-2.31.
|
|
80
|
-
sentry_arroyo-2.31.
|
|
77
|
+
sentry_arroyo-2.31.2.dist-info/METADATA,sha256=3pXtE_zg-qbvUHSaMkpixJnBkFHmdNI-2Ln8YBlZkX0,2208
|
|
78
|
+
sentry_arroyo-2.31.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
79
|
+
sentry_arroyo-2.31.2.dist-info/top_level.txt,sha256=DVdMZKysL_iIxm5aY0sYgZtP5ZXMg9YBaBmGQHVmDXA,22
|
|
80
|
+
sentry_arroyo-2.31.2.dist-info/RECORD,,
|
|
@@ -24,11 +24,18 @@ class TestConfluentProducer:
|
|
|
24
24
|
|
|
25
25
|
def test_metrics_callback_records_success(self) -> None:
|
|
26
26
|
"""Test that the metrics callback records success metric"""
|
|
27
|
-
producer = ConfluentProducer(
|
|
27
|
+
producer = ConfluentProducer(
|
|
28
|
+
{"bootstrap.servers": "fake:9092", "client.id": "test-producer-name"}
|
|
29
|
+
)
|
|
28
30
|
mock_message = mock.Mock(spec=ConfluentMessage)
|
|
29
31
|
producer._ConfluentProducer__metrics_delivery_callback(None, mock_message)
|
|
32
|
+
producer.flush() # Flush buffered metrics
|
|
30
33
|
assert (
|
|
31
|
-
Increment(
|
|
34
|
+
Increment(
|
|
35
|
+
"arroyo.producer.produce_status",
|
|
36
|
+
1,
|
|
37
|
+
{"status": "success", "producer_name": "test-producer-name"},
|
|
38
|
+
)
|
|
32
39
|
in TestingMetricsBackend.calls
|
|
33
40
|
)
|
|
34
41
|
|
|
@@ -38,6 +45,7 @@ class TestConfluentProducer:
|
|
|
38
45
|
mock_error = mock.Mock(spec=KafkaError)
|
|
39
46
|
mock_message = mock.Mock(spec=ConfluentMessage)
|
|
40
47
|
producer._ConfluentProducer__metrics_delivery_callback(mock_error, mock_message)
|
|
48
|
+
producer.flush() # Flush buffered metrics
|
|
41
49
|
assert (
|
|
42
50
|
Increment("arroyo.producer.produce_status", 1, {"status": "error"})
|
|
43
51
|
in TestingMetricsBackend.calls
|
|
@@ -45,7 +53,9 @@ class TestConfluentProducer:
|
|
|
45
53
|
|
|
46
54
|
def test_delivery_callback_wraps_user_callback(self) -> None:
|
|
47
55
|
"""Test that the delivery callback wrapper calls both metrics and user callbacks"""
|
|
48
|
-
producer = ConfluentProducer(
|
|
56
|
+
producer = ConfluentProducer(
|
|
57
|
+
{"bootstrap.servers": "fake:9092", "client.id": "test-producer-name"}
|
|
58
|
+
)
|
|
49
59
|
user_callback_invoked = []
|
|
50
60
|
|
|
51
61
|
def user_callback(
|
|
@@ -56,8 +66,13 @@ class TestConfluentProducer:
|
|
|
56
66
|
wrapped = producer._ConfluentProducer__delivery_callback(user_callback)
|
|
57
67
|
mock_message = mock.Mock(spec=ConfluentMessage)
|
|
58
68
|
wrapped(None, mock_message)
|
|
69
|
+
producer.flush() # Flush buffered metrics
|
|
59
70
|
assert (
|
|
60
|
-
Increment(
|
|
71
|
+
Increment(
|
|
72
|
+
"arroyo.producer.produce_status",
|
|
73
|
+
1,
|
|
74
|
+
{"status": "success", "producer_name": "test-producer-name"},
|
|
75
|
+
)
|
|
61
76
|
in TestingMetricsBackend.calls
|
|
62
77
|
)
|
|
63
78
|
assert len(user_callback_invoked) == 1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|