sentry-arroyo 2.30.0__tar.gz → 2.31.1__tar.gz
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.
- {sentry_arroyo-2.30.0/sentry_arroyo.egg-info → sentry_arroyo-2.31.1}/PKG-INFO +1 -1
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/kafka/__init__.py +2 -1
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/kafka/consumer.py +57 -2
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1/sentry_arroyo.egg-info}/PKG-INFO +1 -1
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/sentry_arroyo.egg-info/SOURCES.txt +1 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/setup.py +1 -1
- sentry_arroyo-2.31.1/tests/backends/test_confluent_producer.py +76 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/LICENSE +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/MANIFEST.in +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/README.md +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/abstract.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/kafka/commit.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/kafka/configuration.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/local/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/local/backend.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/local/storages/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/local/storages/abstract.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/backends/local/storages/memory.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/commit.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/dlq.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/errors.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/processor.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/abstract.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/batching.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/buffer.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/commit.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/filter.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/guard.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/healthcheck.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/noop.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/produce.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/reduce.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/run_task.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/run_task_in_threads.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/run_task_with_multiprocessing.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/unfold.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/py.typed +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/types.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/utils/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/utils/clock.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/utils/codecs.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/utils/concurrent.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/utils/logging.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/utils/metricDefs.json +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/utils/metric_defs.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/utils/metrics.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/utils/profiler.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/utils/retries.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/examples/transform_and_produce/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/examples/transform_and_produce/batched.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/examples/transform_and_produce/script.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/examples/transform_and_produce/simple.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/requirements.txt +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/sentry_arroyo.egg-info/dependency_links.txt +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/sentry_arroyo.egg-info/not-zip-safe +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/sentry_arroyo.egg-info/requires.txt +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/sentry_arroyo.egg-info/top_level.txt +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/setup.cfg +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/backends/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/backends/mixins.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/backends/test_commit.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/backends/test_kafka.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/backends/test_kafka_producer.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/backends/test_local.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_all.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_batching.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_buffer.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_commit.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_filter.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_guard.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_noop.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_produce.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_reduce.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_run_task.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_run_task_in_threads.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_run_task_with_multiprocessing.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/strategies/test_unfold.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/processing/test_processor.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/test_commit.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/test_dlq.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/test_kip848_e2e.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/test_types.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/utils/__init__.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/utils/test_concurrent.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/utils/test_metrics.py +0 -0
- {sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/tests/utils/test_retries.py +0 -0
|
@@ -3,12 +3,13 @@ from .configuration import (
|
|
|
3
3
|
build_kafka_consumer_configuration,
|
|
4
4
|
build_kafka_producer_configuration,
|
|
5
5
|
)
|
|
6
|
-
from .consumer import KafkaConsumer, KafkaPayload, KafkaProducer
|
|
6
|
+
from .consumer import ConfluentProducer, KafkaConsumer, KafkaPayload, KafkaProducer
|
|
7
7
|
|
|
8
8
|
__all__ = [
|
|
9
9
|
"build_kafka_configuration",
|
|
10
10
|
"build_kafka_consumer_configuration",
|
|
11
11
|
"build_kafka_producer_configuration",
|
|
12
|
+
"ConfluentProducer",
|
|
12
13
|
"KafkaConsumer",
|
|
13
14
|
"KafkaPayload",
|
|
14
15
|
"KafkaProducer",
|
|
@@ -33,7 +33,7 @@ from confluent_kafka import (
|
|
|
33
33
|
from confluent_kafka import Consumer as ConfluentConsumer
|
|
34
34
|
from confluent_kafka import KafkaError, KafkaException
|
|
35
35
|
from confluent_kafka import Message as ConfluentMessage
|
|
36
|
-
from confluent_kafka import Producer as
|
|
36
|
+
from confluent_kafka import Producer as ConfluentKafkaProducer
|
|
37
37
|
from confluent_kafka import TopicPartition as ConfluentTopicPartition
|
|
38
38
|
|
|
39
39
|
from arroyo.backends.abstract import (
|
|
@@ -50,6 +50,7 @@ from arroyo.errors import (
|
|
|
50
50
|
)
|
|
51
51
|
from arroyo.types import BrokerValue, Partition, Topic
|
|
52
52
|
from arroyo.utils.concurrent import execute
|
|
53
|
+
from arroyo.utils.metrics import get_metrics
|
|
53
54
|
from arroyo.utils.retries import BasicRetryPolicy
|
|
54
55
|
|
|
55
56
|
logger = logging.getLogger(__name__)
|
|
@@ -657,7 +658,7 @@ class KafkaProducer(Producer[KafkaPayload]):
|
|
|
657
658
|
self, configuration: Mapping[str, Any], use_simple_futures: bool = False
|
|
658
659
|
) -> None:
|
|
659
660
|
self.__configuration = configuration
|
|
660
|
-
self.__producer =
|
|
661
|
+
self.__producer = ConfluentKafkaProducer(configuration)
|
|
661
662
|
self.__shutdown_requested = Event()
|
|
662
663
|
|
|
663
664
|
# The worker must execute in a separate thread to ensure that callbacks
|
|
@@ -742,3 +743,57 @@ class KafkaProducer(Producer[KafkaPayload]):
|
|
|
742
743
|
def close(self) -> Future[None]:
|
|
743
744
|
self.__shutdown_requested.set()
|
|
744
745
|
return self.__result
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
# Type alias for the delivery callback function
|
|
749
|
+
DeliveryCallback = Callable[[Optional[KafkaError], ConfluentMessage], None]
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
class ConfluentProducer(ConfluentKafkaProducer): # type: ignore[misc]
|
|
753
|
+
"""
|
|
754
|
+
A thin wrapper for confluent_kafka.Producer that adds metrics reporting.
|
|
755
|
+
"""
|
|
756
|
+
|
|
757
|
+
def __init__(self, configuration: Mapping[str, Any]) -> None:
|
|
758
|
+
super().__init__(configuration)
|
|
759
|
+
self.__metrics = get_metrics()
|
|
760
|
+
self.producer_name = configuration.get("client.id") or None
|
|
761
|
+
|
|
762
|
+
def __metrics_delivery_callback(
|
|
763
|
+
self,
|
|
764
|
+
error: Optional[KafkaError],
|
|
765
|
+
_message: ConfluentMessage,
|
|
766
|
+
) -> None:
|
|
767
|
+
if error is not None:
|
|
768
|
+
status = "error"
|
|
769
|
+
else:
|
|
770
|
+
status = "success"
|
|
771
|
+
|
|
772
|
+
tags = {"status": status}
|
|
773
|
+
if self.producer_name:
|
|
774
|
+
tags["producer_name"] = self.producer_name
|
|
775
|
+
|
|
776
|
+
self.__metrics.increment(
|
|
777
|
+
"arroyo.producer.produce_status",
|
|
778
|
+
1,
|
|
779
|
+
tags=tags,
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
def __delivery_callback(
|
|
783
|
+
self,
|
|
784
|
+
user_callback: Optional[DeliveryCallback],
|
|
785
|
+
) -> DeliveryCallback:
|
|
786
|
+
def wrapped(error: Optional[KafkaError], message: ConfluentMessage) -> None:
|
|
787
|
+
self.__metrics_delivery_callback(error, message)
|
|
788
|
+
if user_callback is not None:
|
|
789
|
+
user_callback(error, message)
|
|
790
|
+
|
|
791
|
+
return wrapped
|
|
792
|
+
|
|
793
|
+
def produce(self, *args: Any, **kwargs: Any) -> None:
|
|
794
|
+
# callback and on_delivery are aliases, callback takes precedence over on_delivery
|
|
795
|
+
callback = kwargs.pop("callback", None)
|
|
796
|
+
on_delivery = kwargs.pop("on_delivery", None)
|
|
797
|
+
user_callback = callback or on_delivery
|
|
798
|
+
wrapped_callback = self.__delivery_callback(user_callback)
|
|
799
|
+
super().produce(*args, on_delivery=wrapped_callback, **kwargs)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from unittest import mock
|
|
3
|
+
|
|
4
|
+
from confluent_kafka import KafkaError
|
|
5
|
+
from confluent_kafka import Message as ConfluentMessage
|
|
6
|
+
from confluent_kafka import Producer as ConfluentKafkaProducer
|
|
7
|
+
|
|
8
|
+
from arroyo.backends.kafka.consumer import ConfluentProducer
|
|
9
|
+
from tests.metrics import Increment, TestingMetricsBackend
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestConfluentProducer:
|
|
13
|
+
"""
|
|
14
|
+
Tests for ConfluentProducer wrapper around confluent_kafka.Producer.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def test_init(self) -> None:
|
|
18
|
+
"""Test that ConfluentProducer can be instantiated"""
|
|
19
|
+
config = {"bootstrap.servers": "fake:9092"}
|
|
20
|
+
producer = ConfluentProducer(config)
|
|
21
|
+
|
|
22
|
+
assert isinstance(producer, ConfluentProducer)
|
|
23
|
+
assert isinstance(producer, ConfluentKafkaProducer)
|
|
24
|
+
|
|
25
|
+
def test_metrics_callback_records_success(self) -> None:
|
|
26
|
+
"""Test that the metrics callback records success metric"""
|
|
27
|
+
producer = ConfluentProducer(
|
|
28
|
+
{"bootstrap.servers": "fake:9092", "client.id": "test-producer-name"}
|
|
29
|
+
)
|
|
30
|
+
mock_message = mock.Mock(spec=ConfluentMessage)
|
|
31
|
+
producer._ConfluentProducer__metrics_delivery_callback(None, mock_message)
|
|
32
|
+
assert (
|
|
33
|
+
Increment(
|
|
34
|
+
"arroyo.producer.produce_status",
|
|
35
|
+
1,
|
|
36
|
+
{"status": "success", "producer_name": "test-producer-name"},
|
|
37
|
+
)
|
|
38
|
+
in TestingMetricsBackend.calls
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def test_metrics_callback_records_error(self) -> None:
|
|
42
|
+
"""Test that the metrics callback records error metric"""
|
|
43
|
+
producer = ConfluentProducer({"bootstrap.servers": "fake:9092"})
|
|
44
|
+
mock_error = mock.Mock(spec=KafkaError)
|
|
45
|
+
mock_message = mock.Mock(spec=ConfluentMessage)
|
|
46
|
+
producer._ConfluentProducer__metrics_delivery_callback(mock_error, mock_message)
|
|
47
|
+
assert (
|
|
48
|
+
Increment("arroyo.producer.produce_status", 1, {"status": "error"})
|
|
49
|
+
in TestingMetricsBackend.calls
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def test_delivery_callback_wraps_user_callback(self) -> None:
|
|
53
|
+
"""Test that the delivery callback wrapper calls both metrics and user callbacks"""
|
|
54
|
+
producer = ConfluentProducer(
|
|
55
|
+
{"bootstrap.servers": "fake:9092", "client.id": "test-producer-name"}
|
|
56
|
+
)
|
|
57
|
+
user_callback_invoked = []
|
|
58
|
+
|
|
59
|
+
def user_callback(
|
|
60
|
+
error: Optional[KafkaError], message: ConfluentMessage
|
|
61
|
+
) -> None:
|
|
62
|
+
user_callback_invoked.append((error, message))
|
|
63
|
+
|
|
64
|
+
wrapped = producer._ConfluentProducer__delivery_callback(user_callback)
|
|
65
|
+
mock_message = mock.Mock(spec=ConfluentMessage)
|
|
66
|
+
wrapped(None, mock_message)
|
|
67
|
+
assert (
|
|
68
|
+
Increment(
|
|
69
|
+
"arroyo.producer.produce_status",
|
|
70
|
+
1,
|
|
71
|
+
{"status": "success", "producer_name": "test-producer-name"},
|
|
72
|
+
)
|
|
73
|
+
in TestingMetricsBackend.calls
|
|
74
|
+
)
|
|
75
|
+
assert len(user_callback_invoked) == 1
|
|
76
|
+
assert user_callback_invoked[0] == (None, mock_message)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sentry_arroyo-2.30.0 → sentry_arroyo-2.31.1}/arroyo/processing/strategies/run_task_in_threads.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|