kafka-python 3.0.0__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.
Files changed (373) hide show
  1. kafka/__init__.py +34 -0
  2. kafka/__main__.py +5 -0
  3. kafka/admin/__init__.py +29 -0
  4. kafka/admin/__main__.py +5 -0
  5. kafka/admin/_acls.py +355 -0
  6. kafka/admin/_cluster.py +359 -0
  7. kafka/admin/_configs.py +479 -0
  8. kafka/admin/_groups.py +754 -0
  9. kafka/admin/_partitions.py +595 -0
  10. kafka/admin/_topics.py +281 -0
  11. kafka/admin/_transactions.py +450 -0
  12. kafka/admin/_users.py +194 -0
  13. kafka/admin/client.py +373 -0
  14. kafka/benchmarks/__init__.py +0 -0
  15. kafka/benchmarks/consumer_performance.py +138 -0
  16. kafka/benchmarks/load_example.py +109 -0
  17. kafka/benchmarks/producer_encode_path.py +201 -0
  18. kafka/benchmarks/producer_performance.py +161 -0
  19. kafka/benchmarks/profile_protocol.py +138 -0
  20. kafka/benchmarks/protocol_old_vs_new.py +447 -0
  21. kafka/benchmarks/record_batch_compose.py +77 -0
  22. kafka/benchmarks/record_batch_read.py +82 -0
  23. kafka/benchmarks/varint_speed.py +426 -0
  24. kafka/cli/__init__.py +36 -0
  25. kafka/cli/admin/__init__.py +117 -0
  26. kafka/cli/admin/acls/__init__.py +9 -0
  27. kafka/cli/admin/acls/common.py +76 -0
  28. kafka/cli/admin/acls/create.py +19 -0
  29. kafka/cli/admin/acls/delete.py +23 -0
  30. kafka/cli/admin/acls/describe.py +16 -0
  31. kafka/cli/admin/cluster/__init__.py +14 -0
  32. kafka/cli/admin/cluster/describe.py +11 -0
  33. kafka/cli/admin/cluster/describe_quorum.py +11 -0
  34. kafka/cli/admin/cluster/features.py +52 -0
  35. kafka/cli/admin/cluster/log_dirs.py +43 -0
  36. kafka/cli/admin/cluster/versions.py +33 -0
  37. kafka/cli/admin/configs/__init__.py +10 -0
  38. kafka/cli/admin/configs/alter.py +43 -0
  39. kafka/cli/admin/configs/common.py +17 -0
  40. kafka/cli/admin/configs/describe.py +30 -0
  41. kafka/cli/admin/configs/list.py +16 -0
  42. kafka/cli/admin/configs/reset.py +20 -0
  43. kafka/cli/admin/groups/__init__.py +16 -0
  44. kafka/cli/admin/groups/alter_offsets.py +30 -0
  45. kafka/cli/admin/groups/delete.py +11 -0
  46. kafka/cli/admin/groups/delete_offsets.py +29 -0
  47. kafka/cli/admin/groups/describe.py +11 -0
  48. kafka/cli/admin/groups/list.py +28 -0
  49. kafka/cli/admin/groups/list_offsets.py +29 -0
  50. kafka/cli/admin/groups/remove_members.py +40 -0
  51. kafka/cli/admin/groups/reset_offsets.py +139 -0
  52. kafka/cli/admin/partitions/__init__.py +21 -0
  53. kafka/cli/admin/partitions/alter_reassignments.py +37 -0
  54. kafka/cli/admin/partitions/create.py +27 -0
  55. kafka/cli/admin/partitions/delete_records.py +31 -0
  56. kafka/cli/admin/partitions/describe.py +36 -0
  57. kafka/cli/admin/partitions/elect_leaders.py +53 -0
  58. kafka/cli/admin/partitions/list_offsets.py +88 -0
  59. kafka/cli/admin/partitions/list_reassignments.py +35 -0
  60. kafka/cli/admin/topics/__init__.py +10 -0
  61. kafka/cli/admin/topics/create.py +13 -0
  62. kafka/cli/admin/topics/delete.py +19 -0
  63. kafka/cli/admin/topics/describe.py +18 -0
  64. kafka/cli/admin/topics/list.py +11 -0
  65. kafka/cli/admin/transactions/__init__.py +17 -0
  66. kafka/cli/admin/transactions/abort.py +38 -0
  67. kafka/cli/admin/transactions/describe.py +24 -0
  68. kafka/cli/admin/transactions/describe_producers.py +29 -0
  69. kafka/cli/admin/transactions/find_hanging.py +26 -0
  70. kafka/cli/admin/transactions/list.py +37 -0
  71. kafka/cli/admin/users/__init__.py +8 -0
  72. kafka/cli/admin/users/alter_user_scram_credentials.py +34 -0
  73. kafka/cli/admin/users/describe_user_scram_credentials.py +15 -0
  74. kafka/cli/common.py +95 -0
  75. kafka/cli/consumer/__init__.py +63 -0
  76. kafka/cli/producer/__init__.py +57 -0
  77. kafka/cluster.py +824 -0
  78. kafka/codec.py +325 -0
  79. kafka/consumer/__init__.py +5 -0
  80. kafka/consumer/__main__.py +5 -0
  81. kafka/consumer/fetcher.py +2012 -0
  82. kafka/consumer/group.py +1347 -0
  83. kafka/consumer/subscription_state.py +897 -0
  84. kafka/coordinator/__init__.py +0 -0
  85. kafka/coordinator/assignors/__init__.py +0 -0
  86. kafka/coordinator/assignors/abstract.py +90 -0
  87. kafka/coordinator/assignors/cooperative_sticky.py +167 -0
  88. kafka/coordinator/assignors/range.py +81 -0
  89. kafka/coordinator/assignors/roundrobin.py +101 -0
  90. kafka/coordinator/assignors/sticky/StickyAssignorUserData.json +37 -0
  91. kafka/coordinator/assignors/sticky/__init__.py +0 -0
  92. kafka/coordinator/assignors/sticky/partition_movements.py +149 -0
  93. kafka/coordinator/assignors/sticky/sorted_set.py +63 -0
  94. kafka/coordinator/assignors/sticky/sticky_assignor.py +665 -0
  95. kafka/coordinator/assignors/sticky/user_data.py +8 -0
  96. kafka/coordinator/base.py +1215 -0
  97. kafka/coordinator/consumer.py +1224 -0
  98. kafka/coordinator/heartbeat.py +82 -0
  99. kafka/coordinator/subscription.py +34 -0
  100. kafka/errors.py +1004 -0
  101. kafka/future.py +166 -0
  102. kafka/metrics/__init__.py +13 -0
  103. kafka/metrics/compound_stat.py +33 -0
  104. kafka/metrics/dict_reporter.py +81 -0
  105. kafka/metrics/kafka_metric.py +36 -0
  106. kafka/metrics/measurable.py +27 -0
  107. kafka/metrics/measurable_stat.py +13 -0
  108. kafka/metrics/metric_config.py +33 -0
  109. kafka/metrics/metric_name.py +105 -0
  110. kafka/metrics/metrics.py +261 -0
  111. kafka/metrics/metrics_reporter.py +53 -0
  112. kafka/metrics/quota.py +41 -0
  113. kafka/metrics/stat.py +19 -0
  114. kafka/metrics/stats/__init__.py +15 -0
  115. kafka/metrics/stats/avg.py +24 -0
  116. kafka/metrics/stats/count.py +17 -0
  117. kafka/metrics/stats/histogram.py +99 -0
  118. kafka/metrics/stats/max_stat.py +17 -0
  119. kafka/metrics/stats/min_stat.py +19 -0
  120. kafka/metrics/stats/percentile.py +14 -0
  121. kafka/metrics/stats/percentiles.py +75 -0
  122. kafka/metrics/stats/rate.py +118 -0
  123. kafka/metrics/stats/sampled_stat.py +99 -0
  124. kafka/metrics/stats/sensor.py +136 -0
  125. kafka/metrics/stats/total.py +15 -0
  126. kafka/net/__init__.py +19 -0
  127. kafka/net/compat.py +165 -0
  128. kafka/net/connection.py +593 -0
  129. kafka/net/http_connect.py +144 -0
  130. kafka/net/inet.py +122 -0
  131. kafka/net/manager.py +451 -0
  132. kafka/net/metrics.py +149 -0
  133. kafka/net/sasl/__init__.py +32 -0
  134. kafka/net/sasl/abc.py +28 -0
  135. kafka/net/sasl/gssapi.py +95 -0
  136. kafka/net/sasl/msk.py +245 -0
  137. kafka/net/sasl/oauth.py +98 -0
  138. kafka/net/sasl/plain.py +42 -0
  139. kafka/net/sasl/scram.py +135 -0
  140. kafka/net/sasl/sspi.py +111 -0
  141. kafka/net/selector.py +644 -0
  142. kafka/net/socks5.py +262 -0
  143. kafka/net/transport.py +415 -0
  144. kafka/net/wakeup_notifier.py +72 -0
  145. kafka/partitioner/__init__.py +8 -0
  146. kafka/partitioner/abc.py +8 -0
  147. kafka/partitioner/default.py +89 -0
  148. kafka/partitioner/sticky.py +109 -0
  149. kafka/producer/__init__.py +5 -0
  150. kafka/producer/__main__.py +5 -0
  151. kafka/producer/future.py +101 -0
  152. kafka/producer/kafka.py +1123 -0
  153. kafka/producer/producer_batch.py +192 -0
  154. kafka/producer/record_accumulator.py +647 -0
  155. kafka/producer/sender.py +884 -0
  156. kafka/producer/transaction_manager.py +1326 -0
  157. kafka/protocol/__init__.py +0 -0
  158. kafka/protocol/admin/__init__.py +29 -0
  159. kafka/protocol/admin/acl.py +83 -0
  160. kafka/protocol/admin/acl.pyi +375 -0
  161. kafka/protocol/admin/client_quotas.py +14 -0
  162. kafka/protocol/admin/client_quotas.pyi +265 -0
  163. kafka/protocol/admin/cluster.py +31 -0
  164. kafka/protocol/admin/cluster.pyi +620 -0
  165. kafka/protocol/admin/configs.py +22 -0
  166. kafka/protocol/admin/configs.pyi +437 -0
  167. kafka/protocol/admin/groups.py +24 -0
  168. kafka/protocol/admin/groups.pyi +261 -0
  169. kafka/protocol/admin/topics.py +53 -0
  170. kafka/protocol/admin/topics.pyi +982 -0
  171. kafka/protocol/admin/transactions.py +18 -0
  172. kafka/protocol/admin/transactions.pyi +311 -0
  173. kafka/protocol/admin/users.py +14 -0
  174. kafka/protocol/admin/users.pyi +223 -0
  175. kafka/protocol/api_data.py +125 -0
  176. kafka/protocol/api_header.py +55 -0
  177. kafka/protocol/api_key.py +97 -0
  178. kafka/protocol/api_message.py +277 -0
  179. kafka/protocol/broker_version_data.py +246 -0
  180. kafka/protocol/consumer/__init__.py +13 -0
  181. kafka/protocol/consumer/fetch.py +16 -0
  182. kafka/protocol/consumer/fetch.pyi +298 -0
  183. kafka/protocol/consumer/group.py +38 -0
  184. kafka/protocol/consumer/group.pyi +824 -0
  185. kafka/protocol/consumer/metadata.py +30 -0
  186. kafka/protocol/consumer/metadata.pyi +89 -0
  187. kafka/protocol/consumer/offsets.py +75 -0
  188. kafka/protocol/consumer/offsets.pyi +288 -0
  189. kafka/protocol/data_container.py +166 -0
  190. kafka/protocol/frame.py +30 -0
  191. kafka/protocol/generate_stubs.py +468 -0
  192. kafka/protocol/metadata/__init__.py +10 -0
  193. kafka/protocol/metadata/api_versions.py +41 -0
  194. kafka/protocol/metadata/api_versions.pyi +128 -0
  195. kafka/protocol/metadata/find_coordinator.py +19 -0
  196. kafka/protocol/metadata/find_coordinator.pyi +105 -0
  197. kafka/protocol/metadata/metadata.py +34 -0
  198. kafka/protocol/metadata/metadata.pyi +160 -0
  199. kafka/protocol/old/__init__.py +0 -0
  200. kafka/protocol/old/abstract.py +17 -0
  201. kafka/protocol/old/add_offsets_to_txn.py +54 -0
  202. kafka/protocol/old/add_partitions_to_txn.py +71 -0
  203. kafka/protocol/old/admin.py +1086 -0
  204. kafka/protocol/old/api.py +205 -0
  205. kafka/protocol/old/api_versions.py +133 -0
  206. kafka/protocol/old/commit.py +355 -0
  207. kafka/protocol/old/consumer_protocol.py +36 -0
  208. kafka/protocol/old/end_txn.py +53 -0
  209. kafka/protocol/old/fetch.py +408 -0
  210. kafka/protocol/old/find_coordinator.py +72 -0
  211. kafka/protocol/old/group.py +451 -0
  212. kafka/protocol/old/init_producer_id.py +42 -0
  213. kafka/protocol/old/list_offsets.py +186 -0
  214. kafka/protocol/old/metadata.py +290 -0
  215. kafka/protocol/old/offset_for_leader_epoch.py +133 -0
  216. kafka/protocol/old/produce.py +247 -0
  217. kafka/protocol/old/sasl_authenticate.py +38 -0
  218. kafka/protocol/old/sasl_handshake.py +39 -0
  219. kafka/protocol/old/struct.py +87 -0
  220. kafka/protocol/old/txn_offset_commit.py +73 -0
  221. kafka/protocol/old/types.py +440 -0
  222. kafka/protocol/parser.py +191 -0
  223. kafka/protocol/producer/__init__.py +7 -0
  224. kafka/protocol/producer/produce.py +17 -0
  225. kafka/protocol/producer/produce.pyi +197 -0
  226. kafka/protocol/producer/transaction.py +30 -0
  227. kafka/protocol/producer/transaction.pyi +663 -0
  228. kafka/protocol/sasl.py +52 -0
  229. kafka/protocol/sasl.pyi +126 -0
  230. kafka/protocol/schemas/__init__.py +7 -0
  231. kafka/protocol/schemas/fields/__init__.py +7 -0
  232. kafka/protocol/schemas/fields/array.py +127 -0
  233. kafka/protocol/schemas/fields/base.py +156 -0
  234. kafka/protocol/schemas/fields/codecs/__init__.py +12 -0
  235. kafka/protocol/schemas/fields/codecs/encode_buffer.py +82 -0
  236. kafka/protocol/schemas/fields/codecs/tagged_fields.py +109 -0
  237. kafka/protocol/schemas/fields/codecs/types.py +505 -0
  238. kafka/protocol/schemas/fields/codegen.py +40 -0
  239. kafka/protocol/schemas/fields/simple.py +127 -0
  240. kafka/protocol/schemas/fields/struct.py +357 -0
  241. kafka/protocol/schemas/fields/struct_array.py +142 -0
  242. kafka/protocol/schemas/load_json.py +42 -0
  243. kafka/protocol/schemas/resources/AddOffsetsToTxnRequest.json +40 -0
  244. kafka/protocol/schemas/resources/AddOffsetsToTxnResponse.json +35 -0
  245. kafka/protocol/schemas/resources/AddPartitionsToTxnRequest.json +65 -0
  246. kafka/protocol/schemas/resources/AddPartitionsToTxnResponse.json +60 -0
  247. kafka/protocol/schemas/resources/AlterClientQuotasRequest.json +47 -0
  248. kafka/protocol/schemas/resources/AlterClientQuotasResponse.json +41 -0
  249. kafka/protocol/schemas/resources/AlterConfigsRequest.json +43 -0
  250. kafka/protocol/schemas/resources/AlterConfigsResponse.json +39 -0
  251. kafka/protocol/schemas/resources/AlterPartitionReassignmentsRequest.json +42 -0
  252. kafka/protocol/schemas/resources/AlterPartitionReassignmentsResponse.json +47 -0
  253. kafka/protocol/schemas/resources/AlterReplicaLogDirsRequest.json +41 -0
  254. kafka/protocol/schemas/resources/AlterReplicaLogDirsResponse.json +41 -0
  255. kafka/protocol/schemas/resources/AlterUserScramCredentialsRequest.json +45 -0
  256. kafka/protocol/schemas/resources/AlterUserScramCredentialsResponse.json +35 -0
  257. kafka/protocol/schemas/resources/ApiVersionsRequest.json +34 -0
  258. kafka/protocol/schemas/resources/ApiVersionsResponse.json +79 -0
  259. kafka/protocol/schemas/resources/ConsumerProtocolAssignment.json +42 -0
  260. kafka/protocol/schemas/resources/ConsumerProtocolSubscription.json +49 -0
  261. kafka/protocol/schemas/resources/CreateAclsRequest.json +46 -0
  262. kafka/protocol/schemas/resources/CreateAclsResponse.json +37 -0
  263. kafka/protocol/schemas/resources/CreatePartitionsRequest.json +47 -0
  264. kafka/protocol/schemas/resources/CreatePartitionsResponse.json +41 -0
  265. kafka/protocol/schemas/resources/CreateTopicsRequest.json +65 -0
  266. kafka/protocol/schemas/resources/CreateTopicsResponse.json +72 -0
  267. kafka/protocol/schemas/resources/DeleteAclsRequest.json +46 -0
  268. kafka/protocol/schemas/resources/DeleteAclsResponse.json +59 -0
  269. kafka/protocol/schemas/resources/DeleteGroupsRequest.json +30 -0
  270. kafka/protocol/schemas/resources/DeleteGroupsResponse.json +36 -0
  271. kafka/protocol/schemas/resources/DeleteRecordsRequest.json +42 -0
  272. kafka/protocol/schemas/resources/DeleteRecordsResponse.json +43 -0
  273. kafka/protocol/schemas/resources/DeleteTopicsRequest.json +43 -0
  274. kafka/protocol/schemas/resources/DeleteTopicsResponse.json +52 -0
  275. kafka/protocol/schemas/resources/DescribeAclsRequest.json +43 -0
  276. kafka/protocol/schemas/resources/DescribeAclsResponse.json +55 -0
  277. kafka/protocol/schemas/resources/DescribeClientQuotasRequest.json +37 -0
  278. kafka/protocol/schemas/resources/DescribeClientQuotasResponse.json +47 -0
  279. kafka/protocol/schemas/resources/DescribeClusterRequest.json +35 -0
  280. kafka/protocol/schemas/resources/DescribeClusterResponse.json +56 -0
  281. kafka/protocol/schemas/resources/DescribeConfigsRequest.json +42 -0
  282. kafka/protocol/schemas/resources/DescribeConfigsResponse.json +69 -0
  283. kafka/protocol/schemas/resources/DescribeGroupsRequest.json +38 -0
  284. kafka/protocol/schemas/resources/DescribeGroupsResponse.json +74 -0
  285. kafka/protocol/schemas/resources/DescribeLogDirsRequest.json +38 -0
  286. kafka/protocol/schemas/resources/DescribeLogDirsResponse.json +65 -0
  287. kafka/protocol/schemas/resources/DescribeProducersRequest.json +32 -0
  288. kafka/protocol/schemas/resources/DescribeProducersResponse.json +55 -0
  289. kafka/protocol/schemas/resources/DescribeQuorumRequest.json +39 -0
  290. kafka/protocol/schemas/resources/DescribeQuorumResponse.json +82 -0
  291. kafka/protocol/schemas/resources/DescribeTopicPartitionsRequest.json +40 -0
  292. kafka/protocol/schemas/resources/DescribeTopicPartitionsResponse.json +66 -0
  293. kafka/protocol/schemas/resources/DescribeTransactionsRequest.json +27 -0
  294. kafka/protocol/schemas/resources/DescribeTransactionsResponse.json +52 -0
  295. kafka/protocol/schemas/resources/DescribeUserScramCredentialsRequest.json +30 -0
  296. kafka/protocol/schemas/resources/DescribeUserScramCredentialsResponse.json +45 -0
  297. kafka/protocol/schemas/resources/ElectLeadersRequest.json +41 -0
  298. kafka/protocol/schemas/resources/ElectLeadersResponse.json +45 -0
  299. kafka/protocol/schemas/resources/EndTxnRequest.json +43 -0
  300. kafka/protocol/schemas/resources/EndTxnResponse.json +41 -0
  301. kafka/protocol/schemas/resources/FetchRequest.json +125 -0
  302. kafka/protocol/schemas/resources/FetchResponse.json +124 -0
  303. kafka/protocol/schemas/resources/FindCoordinatorRequest.json +43 -0
  304. kafka/protocol/schemas/resources/FindCoordinatorResponse.json +58 -0
  305. kafka/protocol/schemas/resources/HeartbeatRequest.json +39 -0
  306. kafka/protocol/schemas/resources/HeartbeatResponse.json +35 -0
  307. kafka/protocol/schemas/resources/IncrementalAlterConfigsRequest.json +44 -0
  308. kafka/protocol/schemas/resources/IncrementalAlterConfigsResponse.json +38 -0
  309. kafka/protocol/schemas/resources/InitProducerIdRequest.json +50 -0
  310. kafka/protocol/schemas/resources/InitProducerIdResponse.json +47 -0
  311. kafka/protocol/schemas/resources/JoinGroupRequest.json +63 -0
  312. kafka/protocol/schemas/resources/JoinGroupResponse.json +69 -0
  313. kafka/protocol/schemas/resources/LeaveGroupRequest.json +47 -0
  314. kafka/protocol/schemas/resources/LeaveGroupResponse.json +47 -0
  315. kafka/protocol/schemas/resources/ListConfigResourcesRequest.json +31 -0
  316. kafka/protocol/schemas/resources/ListConfigResourcesResponse.json +37 -0
  317. kafka/protocol/schemas/resources/ListGroupsRequest.json +36 -0
  318. kafka/protocol/schemas/resources/ListGroupsResponse.json +49 -0
  319. kafka/protocol/schemas/resources/ListOffsetsRequest.json +72 -0
  320. kafka/protocol/schemas/resources/ListOffsetsResponse.json +71 -0
  321. kafka/protocol/schemas/resources/ListPartitionReassignmentsRequest.json +34 -0
  322. kafka/protocol/schemas/resources/ListPartitionReassignmentsResponse.json +46 -0
  323. kafka/protocol/schemas/resources/ListTransactionsRequest.json +40 -0
  324. kafka/protocol/schemas/resources/ListTransactionsResponse.json +42 -0
  325. kafka/protocol/schemas/resources/MetadataRequest.json +56 -0
  326. kafka/protocol/schemas/resources/MetadataResponse.json +101 -0
  327. kafka/protocol/schemas/resources/OffsetCommitRequest.json +76 -0
  328. kafka/protocol/schemas/resources/OffsetCommitResponse.json +71 -0
  329. kafka/protocol/schemas/resources/OffsetDeleteRequest.json +39 -0
  330. kafka/protocol/schemas/resources/OffsetDeleteResponse.json +42 -0
  331. kafka/protocol/schemas/resources/OffsetFetchRequest.json +76 -0
  332. kafka/protocol/schemas/resources/OffsetFetchResponse.json +107 -0
  333. kafka/protocol/schemas/resources/OffsetForLeaderEpochRequest.json +52 -0
  334. kafka/protocol/schemas/resources/OffsetForLeaderEpochResponse.json +51 -0
  335. kafka/protocol/schemas/resources/ProduceRequest.json +73 -0
  336. kafka/protocol/schemas/resources/ProduceResponse.json +96 -0
  337. kafka/protocol/schemas/resources/RequestHeader.json +44 -0
  338. kafka/protocol/schemas/resources/ResponseHeader.json +26 -0
  339. kafka/protocol/schemas/resources/SaslAuthenticateRequest.json +29 -0
  340. kafka/protocol/schemas/resources/SaslAuthenticateResponse.json +34 -0
  341. kafka/protocol/schemas/resources/SaslHandshakeRequest.json +31 -0
  342. kafka/protocol/schemas/resources/SaslHandshakeResponse.json +32 -0
  343. kafka/protocol/schemas/resources/SyncGroupRequest.json +56 -0
  344. kafka/protocol/schemas/resources/SyncGroupResponse.json +46 -0
  345. kafka/protocol/schemas/resources/TxnOffsetCommitRequest.json +68 -0
  346. kafka/protocol/schemas/resources/TxnOffsetCommitResponse.json +47 -0
  347. kafka/protocol/schemas/resources/UpdateFeaturesRequest.json +43 -0
  348. kafka/protocol/schemas/resources/UpdateFeaturesResponse.json +39 -0
  349. kafka/protocol/schemas/resources/WriteTxnMarkersRequest.json +49 -0
  350. kafka/protocol/schemas/resources/WriteTxnMarkersResponse.json +45 -0
  351. kafka/protocol/schemas/resources/__init__.py +0 -0
  352. kafka/record/__init__.py +3 -0
  353. kafka/record/_crc32c.py +161 -0
  354. kafka/record/abc.py +144 -0
  355. kafka/record/default_records.py +782 -0
  356. kafka/record/legacy_records.py +587 -0
  357. kafka/record/memory_records.py +255 -0
  358. kafka/record/util.py +135 -0
  359. kafka/serializer/__init__.py +4 -0
  360. kafka/serializer/abstract.py +20 -0
  361. kafka/serializer/default.py +16 -0
  362. kafka/serializer/json.py +17 -0
  363. kafka/serializer/wrapper.py +21 -0
  364. kafka/structs.py +69 -0
  365. kafka/util.py +159 -0
  366. kafka/vendor/__init__.py +0 -0
  367. kafka/version.py +1 -0
  368. kafka_python-3.0.0.dist-info/METADATA +319 -0
  369. kafka_python-3.0.0.dist-info/RECORD +373 -0
  370. kafka_python-3.0.0.dist-info/WHEEL +5 -0
  371. kafka_python-3.0.0.dist-info/entry_points.txt +2 -0
  372. kafka_python-3.0.0.dist-info/licenses/LICENSE +202 -0
  373. kafka_python-3.0.0.dist-info/top_level.txt +1 -0
kafka/net/manager.py ADDED
@@ -0,0 +1,451 @@
1
+ import copy
2
+ import logging
3
+ import inspect
4
+ import random
5
+ import socket
6
+ import ssl
7
+ import time
8
+
9
+ from .inet import create_connection
10
+ from .connection import KafkaConnection
11
+ from .metrics import KafkaManagerMetrics
12
+ from .transport import KafkaSSLTransport, KafkaTCPTransport
13
+ from kafka.cluster import ClusterMetadata
14
+ import kafka.errors as Errors
15
+ from kafka.net.wakeup_notifier import WakeupNotifier
16
+ from kafka.protocol.broker_version_data import BrokerVersionData
17
+ from kafka.future import Future
18
+ from kafka.version import __version__
19
+
20
+
21
+ log = logging.getLogger(__name__)
22
+
23
+ class KafkaConnectionManager:
24
+ DEFAULT_CONFIG = {
25
+ 'bootstrap_servers': 'localhost:9092',
26
+ 'client_id': 'kafka-python-' + __version__,
27
+ 'client_software_name': 'kafka-python',
28
+ 'client_software_version': __version__,
29
+ 'receive_message_max_bytes': 1000000,
30
+ 'reconnect_backoff_ms': 50,
31
+ 'reconnect_backoff_max_ms': 30000,
32
+ 'request_timeout_ms': 30000,
33
+ 'socket_connection_setup_timeout_ms': 10000,
34
+ 'socket_connection_setup_timeout_max_ms': 30000,
35
+ 'socket_options': [
36
+ (socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),
37
+ (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
38
+ ],
39
+ 'max_in_flight_requests_per_connection': 5,
40
+ 'connections_max_idle_ms': 9 * 60 * 1000,
41
+ 'security_protocol': 'PLAINTEXT',
42
+ 'ssl_context': None,
43
+ 'ssl_check_hostname': True,
44
+ 'ssl_cafile': None,
45
+ 'ssl_certfile': None,
46
+ 'ssl_keyfile': None,
47
+ 'ssl_password': None,
48
+ 'ssl_crlfile': None,
49
+ 'sasl_mechanism': None,
50
+ 'sasl_plain_username': None,
51
+ 'sasl_plain_password': None,
52
+ 'sasl_kerberos_name': None,
53
+ 'sasl_kerberos_service_name': 'kafka',
54
+ 'sasl_kerberos_domain_name': None,
55
+ 'sasl_oauth_token_provider': None,
56
+ 'proxy_url': None,
57
+ 'api_version': None,
58
+ 'metrics': None,
59
+ 'metric_group_prefix': '',
60
+ 'metadata_max_age_ms': 300000,
61
+ 'client_dns_lookup': 'use_all_dns_ips',
62
+ }
63
+ _VALID_DNS_LOOKUP_MODES = ('use_all_dns_ips', 'resolve_canonical_bootstrap_servers_only')
64
+
65
+ def __init__(self, net, **configs):
66
+ self.config = copy.copy(self.DEFAULT_CONFIG)
67
+ for key in self.config:
68
+ if key in configs:
69
+ self.config[key] = configs[key]
70
+
71
+ if self.config['client_dns_lookup'] not in self._VALID_DNS_LOOKUP_MODES:
72
+ raise ValueError(
73
+ "client_dns_lookup must be one of %s; got %r"
74
+ % (self._VALID_DNS_LOOKUP_MODES, self.config['client_dns_lookup']))
75
+
76
+ if 'socks5_proxy' in configs:
77
+ if self.config['proxy_url'] is None:
78
+ log.warning('socks5_proxy is deprecated, use proxy_url instead')
79
+ self.config['proxy_url'] = configs['socks5_proxy']
80
+
81
+ self._net = net
82
+ self.cluster = ClusterMetadata(
83
+ bootstrap_servers=self.config['bootstrap_servers'],
84
+ metadata_max_age_ms=self.config['metadata_max_age_ms'],
85
+ client_dns_lookup=self.config['client_dns_lookup'],
86
+ )
87
+ self.cluster.attach(self)
88
+ self._conns = {}
89
+ self._backoff = dict() # node_id => (failures, backoff_until, socket_connect_setup_timeout_ms)
90
+ # Cache the most recent SASL / SSL / auth failure per node so we can
91
+ # surface it to the user instead of silently retrying forever.
92
+ # Cleared on successful connect.
93
+ self._auth_failures = {} # node_id => AuthenticationError
94
+ self._idle_check_delay = self.config['connections_max_idle_ms'] / 1000
95
+ self.close_idle_connections()
96
+ self.broker_version_data = None
97
+ self._bootstrap_future = None
98
+ self._bootstrap_wakeup = WakeupNotifier(self._net)
99
+ if self.config['metrics']:
100
+ self._sensors = KafkaManagerMetrics(
101
+ self.config['metrics'], self.config['metric_group_prefix'], self._conns)
102
+ else:
103
+ self._sensors = None
104
+ if self.config['api_version'] is not None:
105
+ self.broker_version_data = BrokerVersionData(self.config['api_version'])
106
+ self.closed = False
107
+
108
+ @property
109
+ def broker_version(self):
110
+ if self.broker_version_data is None:
111
+ return None
112
+ return self.broker_version_data.broker_version
113
+
114
+ def least_used_connections(self):
115
+ return sorted(filter(lambda conn: conn.connected, self._conns.values()), key=lambda conn: conn.transport.last_activity)
116
+
117
+ async def _do_bootstrap(self, deadline):
118
+ while not self.closed and (deadline is None or time.monotonic() < deadline):
119
+ bootstrap_broker = random.choice(self.cluster.bootstrap_brokers())
120
+ log.debug('Attempting bootstrap with %s', bootstrap_broker)
121
+ try:
122
+ timeout_ms = (deadline - time.monotonic()) * 1000 if deadline is not None else None
123
+ conn = self.get_connection(bootstrap_broker.node_id,
124
+ timeout_ms=timeout_ms,
125
+ pop_on_close=False,
126
+ refresh_metadata_on_err=False,
127
+ reset_backoff_on_connect=False)
128
+ except Errors.NodeNotReadyError:
129
+ delay = self.connection_delay(bootstrap_broker.node_id)
130
+ if deadline is not None:
131
+ delay = min(delay, max(0, deadline - time.monotonic()))
132
+ log.debug('Bootstrap %s NodeNotReadyError: backoff %s', bootstrap_broker, delay)
133
+ await self._bootstrap_wakeup(delay)
134
+ continue
135
+
136
+ try:
137
+ await conn
138
+ except Errors.IncompatibleBrokerVersion:
139
+ log.error('Did you attempt to connect to a kafka controller (no metadata support)?')
140
+ raise
141
+ except Exception as exc:
142
+ self._conns.pop(bootstrap_broker.node_id, conn).close(exc)
143
+ continue
144
+
145
+ try:
146
+ await self.cluster.refresh_metadata(bootstrap_broker.node_id)
147
+ if not self.cluster.brokers():
148
+ log.warning('Bootstrap metadata response has no brokers. Retrying.')
149
+ self.update_backoff(bootstrap_broker.node_id)
150
+ continue
151
+ except Exception as exc:
152
+ log.error(f'Bootstrap attempt to {bootstrap_broker.node_id} failed: {exc}')
153
+ self.update_backoff(bootstrap_broker.node_id)
154
+ continue
155
+ else:
156
+ self.reset_backoff(bootstrap_broker.node_id)
157
+ self.cluster.start_refresh_loop()
158
+ log.info('Bootstrap complete: %s', self.cluster)
159
+ return True
160
+ finally:
161
+ self._conns.pop(bootstrap_broker.node_id, conn).close()
162
+ else:
163
+ raise Errors.KafkaTimeoutError(
164
+ 'Unable to bootstrap from %s' % (self.cluster.config['bootstrap_servers'],))
165
+
166
+ def bootstrap_async(self, timeout_ms=None, refresh=True):
167
+ if self._bootstrap_future is not None and (not refresh or not self._bootstrap_future.is_done):
168
+ return self._bootstrap_future
169
+ deadline = None if timeout_ms is None else time.monotonic() + timeout_ms / 1000
170
+ log.debug('Starting new bootstrap')
171
+ self._bootstrap_future = self.call_soon(self._do_bootstrap, deadline)
172
+ self._bootstrap_future.add_errback(lambda exc: log.error('Bootstrap failed: %s', exc))
173
+ return self._bootstrap_future
174
+
175
+ def bootstrap(self, timeout_ms=None, refresh=True):
176
+ self._net.run(self.bootstrap_async, timeout_ms, refresh)
177
+
178
+ @property
179
+ def bootstrapped(self):
180
+ return self._bootstrap_future is not None and self._bootstrap_future.succeeded()
181
+
182
+ def _connection_idle_at(self, conn):
183
+ return conn.transport.last_activity + self._idle_check_delay
184
+
185
+ def close_idle_connections(self):
186
+ for conn in self.least_used_connections():
187
+ next_idle_at = self._connection_idle_at(conn)
188
+ if time.monotonic() >= next_idle_at:
189
+ log.info('Closing idle connection to node %s', conn.node_id)
190
+ conn.close()
191
+ else:
192
+ break
193
+ else:
194
+ next_idle_at = time.monotonic() + self._idle_check_delay
195
+ log.debug('Next idle connections check in %d secs', next_idle_at - time.monotonic())
196
+ self._net.call_at(next_idle_at, self.close_idle_connections)
197
+
198
+ @property
199
+ def ssl_enabled(self):
200
+ return self.config['security_protocol'] in ('SSL', 'SASL_SSL')
201
+
202
+ def _build_ssl_context(self):
203
+ if self.config['ssl_context'] is not None:
204
+ return self.config['ssl_context']
205
+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
206
+ ctx.minimum_version = ssl.TLSVersion.TLSv1_2
207
+ ctx.check_hostname = self.config['ssl_check_hostname']
208
+ if self.config['ssl_cafile']:
209
+ ctx.load_verify_locations(self.config['ssl_cafile'])
210
+ else:
211
+ ctx.load_default_certs()
212
+ if self.config['ssl_certfile']:
213
+ ctx.load_cert_chain(
214
+ certfile=self.config['ssl_certfile'],
215
+ keyfile=self.config['ssl_keyfile'],
216
+ password=self.config['ssl_password'],
217
+ )
218
+ if self.config['ssl_crlfile']:
219
+ ctx.load_verify_locations(crl=self.config['ssl_crlfile'])
220
+ ctx.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
221
+ return ctx
222
+
223
+ async def _build_transport(self, node, timeout_at=None):
224
+ sock = await create_connection(self._net, node.host, node.port,
225
+ self.config['socket_options'],
226
+ proxy_url=self.config['proxy_url'],
227
+ timeout_at=timeout_at)
228
+ if self.ssl_enabled:
229
+ transport = KafkaSSLTransport(self._net, sock, self._build_ssl_context(),
230
+ host=node.host, ssl_check_hostname=self.config['ssl_check_hostname'])
231
+ else:
232
+ transport = KafkaTCPTransport(self._net, sock, host=node.host)
233
+
234
+ try:
235
+ await transport.handshake()
236
+ except Exception as e:
237
+ raise Errors.KafkaConnectionError('Handshake failed: %s' % e)
238
+ else:
239
+ return transport
240
+
241
+ async def _connect(self, node, conn, reset_backoff_on_connect=True, timeout_at=None):
242
+ try:
243
+ transport = await self._build_transport(node, timeout_at=timeout_at)
244
+ conn.connection_made(transport)
245
+ await conn.initialize(timeout_at=timeout_at)
246
+ except Exception as exc:
247
+ log.error('Connection failed: %s', exc)
248
+ conn.connection_lost(exc)
249
+ self.update_backoff(node.node_id)
250
+ if isinstance(exc, (Errors.SaslAuthenticationFailedError,
251
+ Errors.AuthorizationError)):
252
+ self._auth_failures[node.node_id] = exc
253
+ return
254
+
255
+ if self._sensors:
256
+ self._sensors.connection_created.record()
257
+ if reset_backoff_on_connect:
258
+ self.reset_backoff(node.node_id)
259
+ self._auth_failures.pop(node.node_id, None)
260
+ if conn.broker_version_data is not None:
261
+ if self.cluster.is_bootstrap(node.node_id):
262
+ self.broker_version_data = conn.broker_version_data
263
+
264
+ def get_connection(self, node_id, timeout_ms=None,
265
+ pop_on_close=True,
266
+ refresh_metadata_on_err=True,
267
+ reset_backoff_on_connect=True):
268
+ if node_id is None:
269
+ raise Errors.NodeNotReadyError('No node_id provided')
270
+ self.maybe_raise_auth_failure(node_id)
271
+ if self.connection_delay(node_id) > 0:
272
+ raise Errors.NodeNotReadyError(node_id)
273
+ elif node_id in self._conns:
274
+ return self._conns[node_id]
275
+ node = self.cluster.broker_metadata(node_id)
276
+ if node is None:
277
+ raise Errors.UnknownBrokerIdError(node_id)
278
+ conn = KafkaConnection(self._net, node_id=node_id, broker_version_data=self.broker_version_data, **self.config)
279
+ if pop_on_close:
280
+ conn.close_future.add_both(lambda _: self._conns.pop(node.node_id, None))
281
+ if self._sensors:
282
+ conn.close_future.add_both(lambda _: self._sensors.connection_closed.record())
283
+ if refresh_metadata_on_err:
284
+ conn.close_future.add_errback(lambda _: self.cluster.request_update())
285
+ self._conns[node_id] = conn
286
+ if timeout_ms is None:
287
+ timeout_ms = self.socket_connection_setup_timeout_ms(node_id)
288
+ timeout_at = time.monotonic() + timeout_ms / 1000
289
+ self._net.call_soon(lambda: self._connect(node, conn, reset_backoff_on_connect=reset_backoff_on_connect, timeout_at=timeout_at))
290
+ return conn
291
+
292
+ def send(self, request, node_id=None, request_timeout_ms=None):
293
+ node_id = node_id if node_id is not None else self.least_loaded_node()
294
+ try:
295
+ conn = self.get_connection(node_id)
296
+ except Errors.NodeNotReadyError as e:
297
+ return Future().failure(e)
298
+ else:
299
+ return conn.send_request(request, request_timeout_ms=request_timeout_ms)
300
+
301
+ def least_loaded_node(self):
302
+ """Choose the node with fewest outstanding requests, with fallbacks.
303
+
304
+ This method will prefer a node with an existing connection (not throttled)
305
+ with no in-flight-requests. If no such node is found, a node will be chosen
306
+ randomly from all nodes that are not throttled or "blacked out" (i.e.,
307
+ are not subject to a reconnect backoff). If no node metadata has been
308
+ obtained, will return a bootstrap node.
309
+
310
+ Returns:
311
+ node_id or None if no suitable node was found
312
+ """
313
+ nodes = [broker.node_id for broker in self.cluster.brokers()]
314
+ random.shuffle(nodes)
315
+
316
+ inflight = float('inf')
317
+ found = None
318
+ for node_id in nodes:
319
+ conn = self._conns.get(node_id)
320
+ connected = conn is not None and conn.connected and not conn.paused
321
+ blacked_out = (conn and conn.paused) or self.connection_delay(node_id) > 0
322
+ curr_inflight = len(conn.in_flight_requests) if conn is not None else 0
323
+ if connected and curr_inflight == 0:
324
+ # if we find an established connection (not throttled)
325
+ # with no in-flight requests, we can stop right away
326
+ return node_id
327
+ elif not blacked_out and curr_inflight < inflight:
328
+ # otherwise if this is the best we have found so far, record that
329
+ inflight = curr_inflight
330
+ found = node_id
331
+ return found
332
+
333
+ def reset_backoff(self, node_id):
334
+ try:
335
+ del self._backoff[node_id]
336
+ except KeyError:
337
+ pass
338
+
339
+ def jitter_pct(self):
340
+ return random.uniform(0.8, 1.2)
341
+
342
+ def _calculate_exp_timeout(self, key, failures):
343
+ max_keys = {
344
+ 'reconnect_backoff_ms': 'reconnect_backoff_max_ms',
345
+ 'socket_connection_setup_timeout_ms': 'socket_connection_setup_timeout_max_ms',
346
+ }
347
+ timeout_ms = self.config[key] * 2 ** (failures - 1)
348
+ if key in max_keys:
349
+ max_ms = self.config[max_keys[key]]
350
+ timeout_ms = min(max_ms, timeout_ms)
351
+ return timeout_ms * self.jitter_pct()
352
+
353
+ def update_backoff(self, node_id):
354
+ failures, _, _ = self._backoff.get(node_id, (0, 0, 0))
355
+ failures += 1
356
+ backoff_ms = self._calculate_exp_timeout('reconnect_backoff_ms', failures)
357
+ connect_ms = self._calculate_exp_timeout('socket_connection_setup_timeout_ms', failures)
358
+ log.debug('%s reconnect backoff %d ms / connect timeout %d ms after %s failures',
359
+ node_id, backoff_ms, connect_ms, failures)
360
+ backoff_until_time = time.monotonic() + (backoff_ms / 1000)
361
+ self._backoff[node_id] = (failures, backoff_until_time, connect_ms)
362
+
363
+ def connection_delay(self, node_id):
364
+ """Connection delay in seconds.
365
+
366
+ Uses exponential backoff/retry with jitter. See KIP-144.
367
+ """
368
+ if node_id not in self._backoff:
369
+ return 0
370
+ return max(0, self._backoff[node_id][1] - time.monotonic())
371
+
372
+ def socket_connection_setup_timeout_ms(self, node_id):
373
+ if node_id not in self._backoff:
374
+ return self.config['socket_connection_setup_timeout_ms']
375
+ return self._backoff[node_id][2]
376
+
377
+ def auth_failure(self, node_id):
378
+ """Return the most recent auth-class failure for ``node_id``,
379
+ or None if there is no sticky failure on record."""
380
+ return self._auth_failures.get(node_id)
381
+
382
+ def maybe_raise_auth_failure(self, node_id):
383
+ """Raise the cached auth-class failure for ``node_id`` if any."""
384
+ exc = self._auth_failures.get(node_id)
385
+ if exc is not None:
386
+ raise exc
387
+
388
+ def close(self, node_id=None, timeout_ms=None):
389
+ if node_id is not None:
390
+ conn = self._conns.get(node_id)
391
+ if conn is not None:
392
+ conn.close()
393
+ elif not self.closed:
394
+ self.closed = True
395
+ self._bootstrap_wakeup.notify()
396
+ for conn in list(self._conns.values()):
397
+ conn.close()
398
+ self.cluster.close()
399
+
400
+ async def wait_for(self, future, timeout_ms):
401
+ """Await `future` with a timeout in ms. Raises KafkaTimeoutError on timeout.
402
+
403
+ Must be awaited from a coroutine running on this loop. The underlying
404
+ future is not cancelled on timeout - it continues to run; the timeout
405
+ only unblocks the awaiter.
406
+ """
407
+ if timeout_ms is None:
408
+ return await future
409
+ wrapper = Future()
410
+ def _on_success(value):
411
+ if not wrapper.is_done:
412
+ wrapper.success(value)
413
+ def _on_failure(exc):
414
+ if not wrapper.is_done:
415
+ wrapper.failure(exc)
416
+ future.add_callback(_on_success)
417
+ future.add_errback(_on_failure)
418
+ def _on_timeout():
419
+ if not wrapper.is_done:
420
+ wrapper.failure(Errors.KafkaTimeoutError(
421
+ 'Timed out after %s ms' % timeout_ms))
422
+ timer = self._net.call_later(timeout_ms / 1000, _on_timeout)
423
+ try:
424
+ return await wrapper
425
+ finally:
426
+ if not timer.is_done:
427
+ try:
428
+ self._net.unschedule(timer)
429
+ except ValueError:
430
+ pass
431
+
432
+ def call_soon(self, coro, *args):
433
+ """Accepts a coroutine / awaitable / function and schedules it on the event loop.
434
+
435
+ Thread-safe.
436
+
437
+ Returns: Future
438
+ """
439
+ return self._net.call_soon_with_future(coro, *args)
440
+
441
+ def run(self, coro, *args):
442
+ """Schedules coro on the event loop, blocks until complete, returns value or raises.
443
+
444
+ If an IO thread is running (via start()), the caller thread blocks on
445
+ a cross-thread Event while the coroutine runs on the IO thread. Safe
446
+ to call concurrently from multiple caller threads.
447
+
448
+ If no IO thread is running, falls back to driving the loop on the
449
+ caller thread (legacy behavior).
450
+ """
451
+ return self._net.run(coro, *args)
kafka/net/metrics.py ADDED
@@ -0,0 +1,149 @@
1
+ """Metrics for kafka.net connection manager and connections.
2
+ """
3
+ import logging
4
+
5
+ from kafka.metrics.measurable import AnonMeasurable
6
+ from kafka.metrics.stats import Avg, Count, Max, Rate
7
+ from kafka.metrics.stats.rate import TimeUnit
8
+
9
+ log = logging.getLogger(__name__)
10
+
11
+
12
+ class KafkaManagerMetrics:
13
+ """Metrics for KafkaConnectionManager (equivalent to KafkaClientMetrics).
14
+ Note that kafka.net does not track select_time or io_time.
15
+ """
16
+ def __init__(self, metrics, metric_group_prefix, conns):
17
+ self.metrics = metrics
18
+ metric_group_name = metric_group_prefix + '-metrics'
19
+
20
+ self.connection_closed = metrics.sensor('connections-closed')
21
+ self.connection_closed.add(metrics.metric_name(
22
+ 'connection-close-rate', metric_group_name,
23
+ 'Connections closed per second in the window.'), Rate())
24
+
25
+ self.connection_created = metrics.sensor('connections-created')
26
+ self.connection_created.add(metrics.metric_name(
27
+ 'connection-creation-rate', metric_group_name,
28
+ 'New connections established per second in the window.'), Rate())
29
+
30
+ metrics.add_metric(metrics.metric_name(
31
+ 'connection-count', metric_group_name,
32
+ 'The current number of active connections.'), AnonMeasurable(
33
+ lambda config, now: len(conns)))
34
+
35
+
36
+ class KafkaConnectionMetrics:
37
+ """Metrics for a single KafkaConnection (equivalent to BrokerConnectionMetrics)."""
38
+ def __init__(self, metrics, metric_group_prefix, node_id):
39
+ self.metrics = metrics
40
+
41
+ # Global aggregate sensors (created once, shared across all connections)
42
+ if not metrics.get_sensor('bytes-sent-received'):
43
+ metric_group_name = metric_group_prefix + '-metrics'
44
+
45
+ bytes_transferred = metrics.sensor('bytes-sent-received')
46
+ bytes_transferred.add(metrics.metric_name(
47
+ 'network-io-rate', metric_group_name,
48
+ 'The average number of network operations (reads or writes) on all'
49
+ ' connections per second.'), Rate(sampled_stat=Count()))
50
+
51
+ bytes_sent = metrics.sensor('bytes-sent',
52
+ parents=[bytes_transferred])
53
+ bytes_sent.add(metrics.metric_name(
54
+ 'outgoing-byte-rate', metric_group_name,
55
+ 'The average number of outgoing bytes sent per second to all'
56
+ ' servers.'), Rate())
57
+ bytes_sent.add(metrics.metric_name(
58
+ 'request-rate', metric_group_name,
59
+ 'The average number of requests sent per second.'),
60
+ Rate(sampled_stat=Count()))
61
+ bytes_sent.add(metrics.metric_name(
62
+ 'request-size-avg', metric_group_name,
63
+ 'The average size of all requests in the window.'), Avg())
64
+ bytes_sent.add(metrics.metric_name(
65
+ 'request-size-max', metric_group_name,
66
+ 'The maximum size of any request sent in the window.'), Max())
67
+
68
+ bytes_received = metrics.sensor('bytes-received',
69
+ parents=[bytes_transferred])
70
+ bytes_received.add(metrics.metric_name(
71
+ 'incoming-byte-rate', metric_group_name,
72
+ 'Bytes/second read off all sockets'), Rate())
73
+ bytes_received.add(metrics.metric_name(
74
+ 'response-rate', metric_group_name,
75
+ 'Responses received sent per second.'),
76
+ Rate(sampled_stat=Count()))
77
+
78
+ request_latency = metrics.sensor('request-latency')
79
+ request_latency.add(metrics.metric_name(
80
+ 'request-latency-avg', metric_group_name,
81
+ 'The average request latency in ms.'), Avg())
82
+ request_latency.add(metrics.metric_name(
83
+ 'request-latency-max', metric_group_name,
84
+ 'The maximum request latency in ms.'), Max())
85
+
86
+ throttle_time = metrics.sensor('throttle-time')
87
+ throttle_time.add(metrics.metric_name(
88
+ 'throttle-time-avg', metric_group_name,
89
+ 'The average throttle time in ms.'), Avg())
90
+ throttle_time.add(metrics.metric_name(
91
+ 'throttle-time-max', metric_group_name,
92
+ 'The maximum throttle time in ms.'), Max())
93
+
94
+ # Per-node sensors (created per connection, parent to global sensors)
95
+ if not metrics.get_sensor(f'node-{node_id}.bytes-sent'):
96
+ metric_group_name = f'{metric_group_prefix}-node-metrics.node-{node_id}'
97
+
98
+ bytes_sent = metrics.sensor(
99
+ f'node-{node_id}.bytes-sent',
100
+ parents=[metrics.get_sensor('bytes-sent')])
101
+ bytes_sent.add(metrics.metric_name(
102
+ 'outgoing-byte-rate', metric_group_name,
103
+ 'The average number of outgoing bytes sent per second.'), Rate())
104
+ bytes_sent.add(metrics.metric_name(
105
+ 'request-rate', metric_group_name,
106
+ 'The average number of requests sent per second.'),
107
+ Rate(sampled_stat=Count()))
108
+ bytes_sent.add(metrics.metric_name(
109
+ 'request-size-avg', metric_group_name,
110
+ 'The average size of all requests in the window.'), Avg())
111
+ bytes_sent.add(metrics.metric_name(
112
+ 'request-size-max', metric_group_name,
113
+ 'The maximum size of any request sent in the window.'), Max())
114
+
115
+ bytes_received = metrics.sensor(
116
+ f'node-{node_id}.bytes-received',
117
+ parents=[metrics.get_sensor('bytes-received')])
118
+ bytes_received.add(metrics.metric_name(
119
+ 'incoming-byte-rate', metric_group_name,
120
+ 'Bytes/second read off node-connection socket'), Rate())
121
+ bytes_received.add(metrics.metric_name(
122
+ 'response-rate', metric_group_name,
123
+ 'The average number of responses received per second.'),
124
+ Rate(sampled_stat=Count()))
125
+
126
+ request_time = metrics.sensor(
127
+ f'node-{node_id}.latency',
128
+ parents=[metrics.get_sensor('request-latency')])
129
+ request_time.add(metrics.metric_name(
130
+ 'request-latency-avg', metric_group_name,
131
+ 'The average request latency in ms.'), Avg())
132
+ request_time.add(metrics.metric_name(
133
+ 'request-latency-max', metric_group_name,
134
+ 'The maximum request latency in ms.'), Max())
135
+
136
+ throttle_time = metrics.sensor(
137
+ f'node-{node_id}.throttle',
138
+ parents=[metrics.get_sensor('throttle-time')])
139
+ throttle_time.add(metrics.metric_name(
140
+ 'throttle-time-avg', metric_group_name,
141
+ 'The average throttle time in ms.'), Avg())
142
+ throttle_time.add(metrics.metric_name(
143
+ 'throttle-time-max', metric_group_name,
144
+ 'The maximum throttle time in ms.'), Max())
145
+
146
+ self.bytes_sent = metrics.sensor(f'node-{node_id}.bytes-sent')
147
+ self.bytes_received = metrics.sensor(f'node-{node_id}.bytes-received')
148
+ self.request_time = metrics.sensor(f'node-{node_id}.latency')
149
+ self.throttle_time = metrics.sensor(f'node-{node_id}.throttle')
@@ -0,0 +1,32 @@
1
+ import platform
2
+
3
+ from .gssapi import SaslMechanismGSSAPI
4
+ from .msk import SaslMechanismAwsMskIam
5
+ from .oauth import SaslMechanismOAuth
6
+ from .plain import SaslMechanismPlain
7
+ from .scram import SaslMechanismScram
8
+ from .sspi import SaslMechanismSSPI
9
+
10
+
11
+ SASL_MECHANISMS = {}
12
+
13
+
14
+ def register_sasl_mechanism(name, klass, overwrite=False):
15
+ if not overwrite and name in SASL_MECHANISMS:
16
+ raise ValueError('Sasl mechanism %s already defined!' % name)
17
+ SASL_MECHANISMS[name] = klass
18
+
19
+
20
+ def get_sasl_mechanism(name):
21
+ return SASL_MECHANISMS[name]
22
+
23
+
24
+ register_sasl_mechanism('AWS_MSK_IAM', SaslMechanismAwsMskIam)
25
+ if platform.system() == 'Windows':
26
+ register_sasl_mechanism('GSSAPI', SaslMechanismSSPI)
27
+ else:
28
+ register_sasl_mechanism('GSSAPI', SaslMechanismGSSAPI)
29
+ register_sasl_mechanism('OAUTHBEARER', SaslMechanismOAuth)
30
+ register_sasl_mechanism('PLAIN', SaslMechanismPlain)
31
+ register_sasl_mechanism('SCRAM-SHA-256', SaslMechanismScram)
32
+ register_sasl_mechanism('SCRAM-SHA-512', SaslMechanismScram)
kafka/net/sasl/abc.py ADDED
@@ -0,0 +1,28 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class SaslMechanism(ABC):
5
+ @abstractmethod
6
+ def __init__(self, **config):
7
+ pass
8
+
9
+ @abstractmethod
10
+ def auth_bytes(self):
11
+ pass
12
+
13
+ @abstractmethod
14
+ def receive(self, auth_bytes):
15
+ pass
16
+
17
+ @abstractmethod
18
+ def is_done(self):
19
+ pass
20
+
21
+ @abstractmethod
22
+ def is_authenticated(self):
23
+ pass
24
+
25
+ def auth_details(self):
26
+ if not self.is_authenticated:
27
+ raise RuntimeError('Not authenticated yet!')
28
+ return 'Authenticated via SASL'