karafka 1.4.12 → 2.2.10

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 (359) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/FUNDING.yml +1 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +10 -9
  5. data/.github/workflows/ci.yml +169 -31
  6. data/.rspec +4 -0
  7. data/.ruby-version +1 -1
  8. data/CHANGELOG.md +716 -607
  9. data/CONTRIBUTING.md +10 -19
  10. data/Gemfile +7 -0
  11. data/Gemfile.lock +69 -92
  12. data/LICENSE +17 -0
  13. data/LICENSE-COMM +89 -0
  14. data/LICENSE-LGPL +165 -0
  15. data/README.md +48 -47
  16. data/bin/benchmarks +99 -0
  17. data/bin/create_token +22 -0
  18. data/bin/integrations +310 -0
  19. data/bin/karafka +5 -14
  20. data/bin/record_rss +50 -0
  21. data/bin/rspecs +6 -0
  22. data/bin/scenario +29 -0
  23. data/bin/stress_many +13 -0
  24. data/bin/stress_one +13 -0
  25. data/bin/verify_license_integrity +37 -0
  26. data/bin/wait_for_kafka +24 -0
  27. data/certs/cert_chain.pem +26 -0
  28. data/certs/karafka-pro.pem +11 -0
  29. data/config/locales/errors.yml +97 -0
  30. data/config/locales/pro_errors.yml +59 -0
  31. data/docker-compose.yml +19 -11
  32. data/karafka.gemspec +26 -22
  33. data/lib/active_job/karafka.rb +17 -0
  34. data/lib/active_job/queue_adapters/karafka_adapter.rb +32 -0
  35. data/lib/karafka/active_job/consumer.rb +49 -0
  36. data/lib/karafka/active_job/current_attributes/loading.rb +36 -0
  37. data/lib/karafka/active_job/current_attributes/persistence.rb +28 -0
  38. data/lib/karafka/active_job/current_attributes.rb +42 -0
  39. data/lib/karafka/active_job/dispatcher.rb +69 -0
  40. data/lib/karafka/active_job/job_extensions.rb +34 -0
  41. data/lib/karafka/active_job/job_options_contract.rb +32 -0
  42. data/lib/karafka/admin.rb +313 -0
  43. data/lib/karafka/app.rb +47 -23
  44. data/lib/karafka/base_consumer.rb +260 -29
  45. data/lib/karafka/cli/base.rb +67 -36
  46. data/lib/karafka/cli/console.rb +18 -12
  47. data/lib/karafka/cli/help.rb +24 -0
  48. data/lib/karafka/cli/info.rb +47 -12
  49. data/lib/karafka/cli/install.rb +23 -14
  50. data/lib/karafka/cli/server.rb +101 -44
  51. data/lib/karafka/cli/topics.rb +146 -0
  52. data/lib/karafka/cli.rb +24 -27
  53. data/lib/karafka/connection/client.rb +553 -90
  54. data/lib/karafka/connection/consumer_group_coordinator.rb +48 -0
  55. data/lib/karafka/connection/listener.rb +294 -38
  56. data/lib/karafka/connection/listeners_batch.rb +40 -0
  57. data/lib/karafka/connection/messages_buffer.rb +84 -0
  58. data/lib/karafka/connection/pauses_manager.rb +46 -0
  59. data/lib/karafka/connection/proxy.rb +98 -0
  60. data/lib/karafka/connection/raw_messages_buffer.rb +101 -0
  61. data/lib/karafka/connection/rebalance_manager.rb +105 -0
  62. data/lib/karafka/contracts/base.rb +17 -0
  63. data/lib/karafka/contracts/config.rb +130 -11
  64. data/lib/karafka/contracts/consumer_group.rb +32 -187
  65. data/lib/karafka/contracts/server_cli_options.rb +80 -19
  66. data/lib/karafka/contracts/topic.rb +65 -0
  67. data/lib/karafka/contracts.rb +1 -1
  68. data/lib/karafka/embedded.rb +36 -0
  69. data/lib/karafka/env.rb +46 -0
  70. data/lib/karafka/errors.rb +37 -21
  71. data/lib/karafka/helpers/async.rb +33 -0
  72. data/lib/karafka/helpers/colorize.rb +26 -0
  73. data/lib/karafka/helpers/multi_delegator.rb +2 -2
  74. data/lib/karafka/instrumentation/callbacks/error.rb +39 -0
  75. data/lib/karafka/instrumentation/callbacks/rebalance.rb +64 -0
  76. data/lib/karafka/instrumentation/callbacks/statistics.rb +51 -0
  77. data/lib/karafka/instrumentation/logger_listener.rb +303 -0
  78. data/lib/karafka/instrumentation/monitor.rb +13 -61
  79. data/lib/karafka/instrumentation/notifications.rb +79 -0
  80. data/lib/karafka/instrumentation/proctitle_listener.rb +7 -16
  81. data/lib/karafka/instrumentation/vendors/appsignal/base.rb +30 -0
  82. data/lib/karafka/instrumentation/vendors/appsignal/client.rb +122 -0
  83. data/lib/karafka/instrumentation/vendors/appsignal/dashboard.json +222 -0
  84. data/lib/karafka/instrumentation/vendors/appsignal/errors_listener.rb +30 -0
  85. data/lib/karafka/instrumentation/vendors/appsignal/metrics_listener.rb +331 -0
  86. data/lib/karafka/instrumentation/vendors/datadog/dashboard.json +1 -0
  87. data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +155 -0
  88. data/lib/karafka/instrumentation/vendors/datadog/metrics_listener.rb +264 -0
  89. data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +176 -0
  90. data/lib/karafka/licenser.rb +78 -0
  91. data/lib/karafka/messages/batch_metadata.rb +52 -0
  92. data/lib/karafka/messages/builders/batch_metadata.rb +60 -0
  93. data/lib/karafka/messages/builders/message.rb +40 -0
  94. data/lib/karafka/messages/builders/messages.rb +36 -0
  95. data/lib/karafka/{params/params.rb → messages/message.rb} +20 -13
  96. data/lib/karafka/messages/messages.rb +71 -0
  97. data/lib/karafka/{params → messages}/metadata.rb +4 -6
  98. data/lib/karafka/messages/parser.rb +14 -0
  99. data/lib/karafka/messages/seek.rb +12 -0
  100. data/lib/karafka/patches/rdkafka/bindings.rb +122 -0
  101. data/lib/karafka/patches/rdkafka/opaque.rb +36 -0
  102. data/lib/karafka/pro/active_job/consumer.rb +47 -0
  103. data/lib/karafka/pro/active_job/dispatcher.rb +86 -0
  104. data/lib/karafka/pro/active_job/job_options_contract.rb +45 -0
  105. data/lib/karafka/pro/cleaner/errors.rb +27 -0
  106. data/lib/karafka/pro/cleaner/messages/message.rb +46 -0
  107. data/lib/karafka/pro/cleaner/messages/messages.rb +42 -0
  108. data/lib/karafka/pro/cleaner.rb +41 -0
  109. data/lib/karafka/pro/contracts/base.rb +23 -0
  110. data/lib/karafka/pro/contracts/server_cli_options.rb +111 -0
  111. data/lib/karafka/pro/encryption/cipher.rb +58 -0
  112. data/lib/karafka/pro/encryption/contracts/config.rb +79 -0
  113. data/lib/karafka/pro/encryption/errors.rb +27 -0
  114. data/lib/karafka/pro/encryption/messages/middleware.rb +46 -0
  115. data/lib/karafka/pro/encryption/messages/parser.rb +56 -0
  116. data/lib/karafka/pro/encryption/setup/config.rb +48 -0
  117. data/lib/karafka/pro/encryption.rb +47 -0
  118. data/lib/karafka/pro/iterator/expander.rb +95 -0
  119. data/lib/karafka/pro/iterator/tpl_builder.rb +155 -0
  120. data/lib/karafka/pro/iterator.rb +170 -0
  121. data/lib/karafka/pro/loader.rb +106 -0
  122. data/lib/karafka/pro/performance_tracker.rb +84 -0
  123. data/lib/karafka/pro/processing/collapser.rb +62 -0
  124. data/lib/karafka/pro/processing/coordinator.rb +147 -0
  125. data/lib/karafka/pro/processing/filters/base.rb +61 -0
  126. data/lib/karafka/pro/processing/filters/delayer.rb +70 -0
  127. data/lib/karafka/pro/processing/filters/expirer.rb +51 -0
  128. data/lib/karafka/pro/processing/filters/inline_insights_delayer.rb +78 -0
  129. data/lib/karafka/pro/processing/filters/throttler.rb +84 -0
  130. data/lib/karafka/pro/processing/filters/virtual_limiter.rb +52 -0
  131. data/lib/karafka/pro/processing/filters_applier.rb +105 -0
  132. data/lib/karafka/pro/processing/jobs/consume_non_blocking.rb +39 -0
  133. data/lib/karafka/pro/processing/jobs/revoked_non_blocking.rb +37 -0
  134. data/lib/karafka/pro/processing/jobs_builder.rb +50 -0
  135. data/lib/karafka/pro/processing/partitioner.rb +69 -0
  136. data/lib/karafka/pro/processing/scheduler.rb +75 -0
  137. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom.rb +70 -0
  138. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_lrj_mom_vp.rb +76 -0
  139. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom.rb +72 -0
  140. data/lib/karafka/pro/processing/strategies/aj/dlq_ftr_mom_vp.rb +76 -0
  141. data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom.rb +66 -0
  142. data/lib/karafka/pro/processing/strategies/aj/dlq_lrj_mom_vp.rb +70 -0
  143. data/lib/karafka/pro/processing/strategies/aj/dlq_mom.rb +64 -0
  144. data/lib/karafka/pro/processing/strategies/aj/dlq_mom_vp.rb +69 -0
  145. data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom.rb +38 -0
  146. data/lib/karafka/pro/processing/strategies/aj/ftr_lrj_mom_vp.rb +66 -0
  147. data/lib/karafka/pro/processing/strategies/aj/ftr_mom.rb +38 -0
  148. data/lib/karafka/pro/processing/strategies/aj/ftr_mom_vp.rb +58 -0
  149. data/lib/karafka/pro/processing/strategies/aj/lrj_mom.rb +37 -0
  150. data/lib/karafka/pro/processing/strategies/aj/lrj_mom_vp.rb +82 -0
  151. data/lib/karafka/pro/processing/strategies/aj/mom.rb +36 -0
  152. data/lib/karafka/pro/processing/strategies/aj/mom_vp.rb +52 -0
  153. data/lib/karafka/pro/processing/strategies/base.rb +26 -0
  154. data/lib/karafka/pro/processing/strategies/default.rb +105 -0
  155. data/lib/karafka/pro/processing/strategies/dlq/default.rb +137 -0
  156. data/lib/karafka/pro/processing/strategies/dlq/ftr.rb +61 -0
  157. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj.rb +75 -0
  158. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom.rb +71 -0
  159. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_mom_vp.rb +43 -0
  160. data/lib/karafka/pro/processing/strategies/dlq/ftr_lrj_vp.rb +41 -0
  161. data/lib/karafka/pro/processing/strategies/dlq/ftr_mom.rb +69 -0
  162. data/lib/karafka/pro/processing/strategies/dlq/ftr_mom_vp.rb +41 -0
  163. data/lib/karafka/pro/processing/strategies/dlq/ftr_vp.rb +40 -0
  164. data/lib/karafka/pro/processing/strategies/dlq/lrj.rb +64 -0
  165. data/lib/karafka/pro/processing/strategies/dlq/lrj_mom.rb +65 -0
  166. data/lib/karafka/pro/processing/strategies/dlq/lrj_mom_vp.rb +36 -0
  167. data/lib/karafka/pro/processing/strategies/dlq/lrj_vp.rb +39 -0
  168. data/lib/karafka/pro/processing/strategies/dlq/mom.rb +68 -0
  169. data/lib/karafka/pro/processing/strategies/dlq/mom_vp.rb +37 -0
  170. data/lib/karafka/pro/processing/strategies/dlq/vp.rb +40 -0
  171. data/lib/karafka/pro/processing/strategies/ftr/default.rb +111 -0
  172. data/lib/karafka/pro/processing/strategies/ftr/vp.rb +40 -0
  173. data/lib/karafka/pro/processing/strategies/lrj/default.rb +85 -0
  174. data/lib/karafka/pro/processing/strategies/lrj/ftr.rb +69 -0
  175. data/lib/karafka/pro/processing/strategies/lrj/ftr_mom.rb +67 -0
  176. data/lib/karafka/pro/processing/strategies/lrj/ftr_mom_vp.rb +40 -0
  177. data/lib/karafka/pro/processing/strategies/lrj/ftr_vp.rb +39 -0
  178. data/lib/karafka/pro/processing/strategies/lrj/mom.rb +77 -0
  179. data/lib/karafka/pro/processing/strategies/lrj/mom_vp.rb +38 -0
  180. data/lib/karafka/pro/processing/strategies/lrj/vp.rb +36 -0
  181. data/lib/karafka/pro/processing/strategies/mom/default.rb +46 -0
  182. data/lib/karafka/pro/processing/strategies/mom/ftr.rb +53 -0
  183. data/lib/karafka/pro/processing/strategies/mom/ftr_vp.rb +37 -0
  184. data/lib/karafka/pro/processing/strategies/mom/vp.rb +35 -0
  185. data/lib/karafka/pro/processing/strategies/vp/default.rb +124 -0
  186. data/lib/karafka/pro/processing/strategies.rb +22 -0
  187. data/lib/karafka/pro/processing/strategy_selector.rb +84 -0
  188. data/lib/karafka/pro/processing/virtual_offset_manager.rb +147 -0
  189. data/lib/karafka/pro/routing/features/active_job/builder.rb +45 -0
  190. data/lib/karafka/pro/routing/features/active_job.rb +26 -0
  191. data/lib/karafka/pro/routing/features/base.rb +24 -0
  192. data/lib/karafka/pro/routing/features/dead_letter_queue/contracts/topic.rb +53 -0
  193. data/lib/karafka/pro/routing/features/dead_letter_queue.rb +27 -0
  194. data/lib/karafka/pro/routing/features/delaying/config.rb +27 -0
  195. data/lib/karafka/pro/routing/features/delaying/contracts/topic.rb +41 -0
  196. data/lib/karafka/pro/routing/features/delaying/topic.rb +59 -0
  197. data/lib/karafka/pro/routing/features/delaying.rb +29 -0
  198. data/lib/karafka/pro/routing/features/expiring/config.rb +27 -0
  199. data/lib/karafka/pro/routing/features/expiring/contracts/topic.rb +41 -0
  200. data/lib/karafka/pro/routing/features/expiring/topic.rb +59 -0
  201. data/lib/karafka/pro/routing/features/expiring.rb +27 -0
  202. data/lib/karafka/pro/routing/features/filtering/config.rb +40 -0
  203. data/lib/karafka/pro/routing/features/filtering/contracts/topic.rb +44 -0
  204. data/lib/karafka/pro/routing/features/filtering/topic.rb +51 -0
  205. data/lib/karafka/pro/routing/features/filtering.rb +27 -0
  206. data/lib/karafka/pro/routing/features/inline_insights/config.rb +32 -0
  207. data/lib/karafka/pro/routing/features/inline_insights/contracts/topic.rb +41 -0
  208. data/lib/karafka/pro/routing/features/inline_insights/topic.rb +52 -0
  209. data/lib/karafka/pro/routing/features/inline_insights.rb +26 -0
  210. data/lib/karafka/pro/routing/features/long_running_job/config.rb +28 -0
  211. data/lib/karafka/pro/routing/features/long_running_job/contracts/topic.rb +40 -0
  212. data/lib/karafka/pro/routing/features/long_running_job/topic.rb +42 -0
  213. data/lib/karafka/pro/routing/features/long_running_job.rb +28 -0
  214. data/lib/karafka/pro/routing/features/patterns/builder.rb +38 -0
  215. data/lib/karafka/pro/routing/features/patterns/config.rb +54 -0
  216. data/lib/karafka/pro/routing/features/patterns/consumer_group.rb +72 -0
  217. data/lib/karafka/pro/routing/features/patterns/contracts/consumer_group.rb +62 -0
  218. data/lib/karafka/pro/routing/features/patterns/contracts/pattern.rb +46 -0
  219. data/lib/karafka/pro/routing/features/patterns/contracts/topic.rb +41 -0
  220. data/lib/karafka/pro/routing/features/patterns/detector.rb +71 -0
  221. data/lib/karafka/pro/routing/features/patterns/pattern.rb +95 -0
  222. data/lib/karafka/pro/routing/features/patterns/patterns.rb +35 -0
  223. data/lib/karafka/pro/routing/features/patterns/topic.rb +50 -0
  224. data/lib/karafka/pro/routing/features/patterns/topics.rb +53 -0
  225. data/lib/karafka/pro/routing/features/patterns.rb +33 -0
  226. data/lib/karafka/pro/routing/features/pausing/contracts/topic.rb +51 -0
  227. data/lib/karafka/pro/routing/features/pausing/topic.rb +44 -0
  228. data/lib/karafka/pro/routing/features/pausing.rb +25 -0
  229. data/lib/karafka/pro/routing/features/throttling/config.rb +32 -0
  230. data/lib/karafka/pro/routing/features/throttling/contracts/topic.rb +44 -0
  231. data/lib/karafka/pro/routing/features/throttling/topic.rb +69 -0
  232. data/lib/karafka/pro/routing/features/throttling.rb +30 -0
  233. data/lib/karafka/pro/routing/features/virtual_partitions/config.rb +30 -0
  234. data/lib/karafka/pro/routing/features/virtual_partitions/contracts/topic.rb +55 -0
  235. data/lib/karafka/pro/routing/features/virtual_partitions/topic.rb +56 -0
  236. data/lib/karafka/pro/routing/features/virtual_partitions.rb +27 -0
  237. data/lib/karafka/pro.rb +13 -0
  238. data/lib/karafka/process.rb +24 -8
  239. data/lib/karafka/processing/coordinator.rb +181 -0
  240. data/lib/karafka/processing/coordinators_buffer.rb +62 -0
  241. data/lib/karafka/processing/executor.rb +155 -0
  242. data/lib/karafka/processing/executors_buffer.rb +72 -0
  243. data/lib/karafka/processing/expansions_selector.rb +22 -0
  244. data/lib/karafka/processing/inline_insights/consumer.rb +41 -0
  245. data/lib/karafka/processing/inline_insights/listener.rb +19 -0
  246. data/lib/karafka/processing/inline_insights/tracker.rb +128 -0
  247. data/lib/karafka/processing/jobs/base.rb +55 -0
  248. data/lib/karafka/processing/jobs/consume.rb +45 -0
  249. data/lib/karafka/processing/jobs/idle.rb +24 -0
  250. data/lib/karafka/processing/jobs/revoked.rb +22 -0
  251. data/lib/karafka/processing/jobs/shutdown.rb +23 -0
  252. data/lib/karafka/processing/jobs_builder.rb +28 -0
  253. data/lib/karafka/processing/jobs_queue.rb +150 -0
  254. data/lib/karafka/processing/partitioner.rb +24 -0
  255. data/lib/karafka/processing/result.rb +42 -0
  256. data/lib/karafka/processing/scheduler.rb +22 -0
  257. data/lib/karafka/processing/strategies/aj_dlq_mom.rb +44 -0
  258. data/lib/karafka/processing/strategies/aj_mom.rb +21 -0
  259. data/lib/karafka/processing/strategies/base.rb +52 -0
  260. data/lib/karafka/processing/strategies/default.rb +158 -0
  261. data/lib/karafka/processing/strategies/dlq.rb +88 -0
  262. data/lib/karafka/processing/strategies/dlq_mom.rb +49 -0
  263. data/lib/karafka/processing/strategies/mom.rb +29 -0
  264. data/lib/karafka/processing/strategy_selector.rb +47 -0
  265. data/lib/karafka/processing/worker.rb +93 -0
  266. data/lib/karafka/processing/workers_batch.rb +27 -0
  267. data/lib/karafka/railtie.rb +141 -0
  268. data/lib/karafka/routing/activity_manager.rb +84 -0
  269. data/lib/karafka/routing/builder.rb +45 -19
  270. data/lib/karafka/routing/consumer_group.rb +56 -20
  271. data/lib/karafka/routing/consumer_mapper.rb +1 -12
  272. data/lib/karafka/routing/features/active_job/builder.rb +33 -0
  273. data/lib/karafka/routing/features/active_job/config.rb +15 -0
  274. data/lib/karafka/routing/features/active_job/contracts/topic.rb +44 -0
  275. data/lib/karafka/routing/features/active_job/proxy.rb +14 -0
  276. data/lib/karafka/routing/features/active_job/topic.rb +33 -0
  277. data/lib/karafka/routing/features/active_job.rb +13 -0
  278. data/lib/karafka/routing/features/base/expander.rb +59 -0
  279. data/lib/karafka/routing/features/base.rb +71 -0
  280. data/lib/karafka/routing/features/dead_letter_queue/config.rb +19 -0
  281. data/lib/karafka/routing/features/dead_letter_queue/contracts/topic.rb +46 -0
  282. data/lib/karafka/routing/features/dead_letter_queue/topic.rb +41 -0
  283. data/lib/karafka/routing/features/dead_letter_queue.rb +16 -0
  284. data/lib/karafka/routing/features/declaratives/config.rb +18 -0
  285. data/lib/karafka/routing/features/declaratives/contracts/topic.rb +33 -0
  286. data/lib/karafka/routing/features/declaratives/topic.rb +44 -0
  287. data/lib/karafka/routing/features/declaratives.rb +14 -0
  288. data/lib/karafka/routing/features/inline_insights/config.rb +15 -0
  289. data/lib/karafka/routing/features/inline_insights/contracts/topic.rb +27 -0
  290. data/lib/karafka/routing/features/inline_insights/topic.rb +31 -0
  291. data/lib/karafka/routing/features/inline_insights.rb +40 -0
  292. data/lib/karafka/routing/features/manual_offset_management/config.rb +15 -0
  293. data/lib/karafka/routing/features/manual_offset_management/contracts/topic.rb +27 -0
  294. data/lib/karafka/routing/features/manual_offset_management/topic.rb +35 -0
  295. data/lib/karafka/routing/features/manual_offset_management.rb +18 -0
  296. data/lib/karafka/routing/proxy.rb +22 -21
  297. data/lib/karafka/routing/router.rb +24 -10
  298. data/lib/karafka/routing/subscription_group.rb +110 -0
  299. data/lib/karafka/routing/subscription_groups_builder.rb +65 -0
  300. data/lib/karafka/routing/topic.rb +87 -24
  301. data/lib/karafka/routing/topics.rb +46 -0
  302. data/lib/karafka/runner.rb +52 -0
  303. data/lib/karafka/serialization/json/deserializer.rb +7 -15
  304. data/lib/karafka/server.rb +113 -37
  305. data/lib/karafka/setup/attributes_map.rb +348 -0
  306. data/lib/karafka/setup/config.rb +256 -175
  307. data/lib/karafka/status.rb +54 -7
  308. data/lib/karafka/templates/example_consumer.rb.erb +16 -0
  309. data/lib/karafka/templates/karafka.rb.erb +33 -55
  310. data/lib/karafka/time_trackers/base.rb +14 -0
  311. data/lib/karafka/time_trackers/pause.rb +122 -0
  312. data/lib/karafka/time_trackers/poll.rb +69 -0
  313. data/lib/karafka/version.rb +1 -1
  314. data/lib/karafka.rb +91 -17
  315. data/renovate.json +9 -0
  316. data.tar.gz.sig +0 -0
  317. metadata +330 -168
  318. metadata.gz.sig +0 -0
  319. data/MIT-LICENCE +0 -18
  320. data/certs/mensfeld.pem +0 -25
  321. data/config/errors.yml +0 -41
  322. data/lib/karafka/assignment_strategies/round_robin.rb +0 -13
  323. data/lib/karafka/attributes_map.rb +0 -63
  324. data/lib/karafka/backends/inline.rb +0 -16
  325. data/lib/karafka/base_responder.rb +0 -226
  326. data/lib/karafka/cli/flow.rb +0 -48
  327. data/lib/karafka/cli/missingno.rb +0 -19
  328. data/lib/karafka/code_reloader.rb +0 -67
  329. data/lib/karafka/connection/api_adapter.rb +0 -158
  330. data/lib/karafka/connection/batch_delegator.rb +0 -55
  331. data/lib/karafka/connection/builder.rb +0 -23
  332. data/lib/karafka/connection/message_delegator.rb +0 -36
  333. data/lib/karafka/consumers/batch_metadata.rb +0 -10
  334. data/lib/karafka/consumers/callbacks.rb +0 -71
  335. data/lib/karafka/consumers/includer.rb +0 -64
  336. data/lib/karafka/consumers/responders.rb +0 -24
  337. data/lib/karafka/consumers/single_params.rb +0 -15
  338. data/lib/karafka/contracts/consumer_group_topic.rb +0 -19
  339. data/lib/karafka/contracts/responder_usage.rb +0 -54
  340. data/lib/karafka/fetcher.rb +0 -42
  341. data/lib/karafka/helpers/class_matcher.rb +0 -88
  342. data/lib/karafka/helpers/config_retriever.rb +0 -46
  343. data/lib/karafka/helpers/inflector.rb +0 -26
  344. data/lib/karafka/instrumentation/stdout_listener.rb +0 -140
  345. data/lib/karafka/params/batch_metadata.rb +0 -26
  346. data/lib/karafka/params/builders/batch_metadata.rb +0 -30
  347. data/lib/karafka/params/builders/params.rb +0 -38
  348. data/lib/karafka/params/builders/params_batch.rb +0 -25
  349. data/lib/karafka/params/params_batch.rb +0 -60
  350. data/lib/karafka/patches/ruby_kafka.rb +0 -47
  351. data/lib/karafka/persistence/client.rb +0 -29
  352. data/lib/karafka/persistence/consumers.rb +0 -45
  353. data/lib/karafka/persistence/topics.rb +0 -48
  354. data/lib/karafka/responders/builder.rb +0 -36
  355. data/lib/karafka/responders/topic.rb +0 -55
  356. data/lib/karafka/routing/topic_mapper.rb +0 -53
  357. data/lib/karafka/serialization/json/serializer.rb +0 -31
  358. data/lib/karafka/setup/configurators/water_drop.rb +0 -36
  359. data/lib/karafka/templates/application_responder.rb.erb +0 -11
@@ -0,0 +1,303 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Instrumentation
5
+ # Default listener that hooks up to our instrumentation and uses its events for logging
6
+ # It can be removed/replaced or anything without any harm to the Karafka app flow.
7
+ class LoggerListener
8
+ # Log levels that we use in this particular listener
9
+ USED_LOG_LEVELS = %i[
10
+ debug
11
+ info
12
+ warn
13
+ error
14
+ fatal
15
+ ].freeze
16
+
17
+ private_constant :USED_LOG_LEVELS
18
+
19
+ # Logs each messages fetching attempt
20
+ #
21
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
22
+ def on_connection_listener_fetch_loop(event)
23
+ listener = event[:caller]
24
+ debug "[#{listener.id}] Polling messages..."
25
+ end
26
+
27
+ # Logs about messages that we've received from Kafka
28
+ #
29
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
30
+ def on_connection_listener_fetch_loop_received(event)
31
+ listener = event[:caller]
32
+ time = event[:time]
33
+ messages_count = event[:messages_buffer].size
34
+
35
+ message = "[#{listener.id}] Polled #{messages_count} messages in #{time}ms"
36
+
37
+ # We don't want the "polled 0" in dev as it would spam the log
38
+ # Instead we publish only info when there was anything we could poll and fail over to the
39
+ # zero notifications when in debug mode
40
+ messages_count.zero? ? debug(message) : info(message)
41
+ end
42
+
43
+ # Prints info about the fact that a given job has started
44
+ #
45
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
46
+ def on_worker_process(event)
47
+ job = event[:job]
48
+ job_type = job.class.to_s.split('::').last
49
+ consumer = job.executor.topic.consumer
50
+ topic = job.executor.topic.name
51
+ partition = job.executor.partition
52
+ info "[#{job.id}] #{job_type} job for #{consumer} on #{topic}/#{partition} started"
53
+ end
54
+
55
+ # Prints info about the fact that a given job has finished
56
+ #
57
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
58
+ def on_worker_processed(event)
59
+ job = event[:job]
60
+ time = event[:time]
61
+ job_type = job.class.to_s.split('::').last
62
+ consumer = job.executor.topic.consumer
63
+ topic = job.executor.topic.name
64
+ partition = job.executor.partition
65
+ info <<~MSG.tr("\n", ' ').strip!
66
+ [#{job.id}] #{job_type} job for #{consumer}
67
+ on #{topic}/#{partition} finished in #{time}ms
68
+ MSG
69
+ end
70
+
71
+ # Prints info about a consumer pause occurrence. Irrelevant if user or system initiated.
72
+ #
73
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
74
+ # @note There may be no offset provided in case user wants to pause on the consecutive offset
75
+ # position. This can be beneficial when not wanting to purge the buffers.
76
+ def on_client_pause(event)
77
+ topic = event[:topic]
78
+ partition = event[:partition]
79
+ offset = event[:offset]
80
+ client = event[:caller]
81
+
82
+ info <<~MSG.tr("\n", ' ').strip!
83
+ [#{client.id}]
84
+ Pausing on topic #{topic}/#{partition}
85
+ on #{offset ? "offset #{offset}" : 'the consecutive offset'}
86
+ MSG
87
+ end
88
+
89
+ # Prints information about resuming of processing of a given topic partition
90
+ #
91
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
92
+ def on_client_resume(event)
93
+ topic = event[:topic]
94
+ partition = event[:partition]
95
+ client = event[:caller]
96
+
97
+ info <<~MSG.tr("\n", ' ').strip!
98
+ [#{client.id}] Resuming on topic #{topic}/#{partition}
99
+ MSG
100
+ end
101
+
102
+ # Prints info about retry of processing after an error
103
+ #
104
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
105
+ def on_consumer_consuming_retry(event)
106
+ topic = event[:topic]
107
+ partition = event[:partition]
108
+ offset = event[:offset]
109
+ consumer = event[:caller]
110
+ timeout = event[:timeout]
111
+
112
+ info <<~MSG.tr("\n", ' ').strip!
113
+ [#{consumer.id}] Retrying of #{consumer.class} after #{timeout} ms
114
+ on topic #{topic}/#{partition} from offset #{offset}
115
+ MSG
116
+ end
117
+
118
+ # Logs info about system signals that Karafka received and prints backtrace for threads in
119
+ # case of ttin
120
+ #
121
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
122
+ def on_process_notice_signal(event)
123
+ info "Received #{event[:signal]} system signal"
124
+
125
+ # We print backtrace only for ttin
126
+ return unless event[:signal] == :SIGTTIN
127
+
128
+ # Inspired by Sidekiq
129
+ Thread.list.each do |thread|
130
+ tid = (thread.object_id ^ ::Process.pid).to_s(36)
131
+
132
+ warn "Thread TID-#{tid} #{thread['label']}"
133
+
134
+ if thread.backtrace
135
+ warn thread.backtrace.join("\n")
136
+ else
137
+ warn '<no backtrace available>'
138
+ end
139
+ end
140
+ end
141
+
142
+ # Logs info that we're running Karafka app.
143
+ #
144
+ # @param _event [Karafka::Core::Monitoring::Event] event details including payload
145
+ def on_app_running(_event)
146
+ info "Running in #{RUBY_DESCRIPTION}"
147
+ info "Running Karafka #{Karafka::VERSION} server"
148
+
149
+ return if Karafka.pro?
150
+
151
+ info 'See LICENSE and the LGPL-3.0 for licensing details'
152
+ end
153
+
154
+ # @param _event [Karafka::Core::Monitoring::Event] event details including payload
155
+ def on_app_quieting(_event)
156
+ info 'Switching to quiet mode. New messages will not be processed'
157
+ end
158
+
159
+ # @param _event [Karafka::Core::Monitoring::Event] event details including payload
160
+ def on_app_quiet(_event)
161
+ info 'Reached quiet mode. No messages will be processed anymore'
162
+ end
163
+
164
+ # Logs info that we're going to stop the Karafka server.
165
+ #
166
+ # @param _event [Karafka::Core::Monitoring::Event] event details including payload
167
+ def on_app_stopping(_event)
168
+ info 'Stopping Karafka server'
169
+ end
170
+
171
+ # Logs info that we stopped the Karafka server.
172
+ #
173
+ # @param _event [Karafka::Core::Monitoring::Event] event details including payload
174
+ def on_app_stopped(_event)
175
+ info 'Stopped Karafka server'
176
+ end
177
+
178
+ # Logs info when we have dispatched a message the the DLQ
179
+ #
180
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
181
+ def on_dead_letter_queue_dispatched(event)
182
+ consumer = event[:caller]
183
+ topic = consumer.topic.name
184
+ message = event[:message]
185
+ offset = message.offset
186
+ dlq_topic = consumer.topic.dead_letter_queue.topic
187
+ partition = message.partition
188
+
189
+ info <<~MSG.tr("\n", ' ').strip!
190
+ [#{consumer.id}] Dispatched message #{offset}
191
+ from #{topic}/#{partition}
192
+ to DLQ topic: #{dlq_topic}
193
+ MSG
194
+ end
195
+
196
+ # Logs info about throttling event
197
+ #
198
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
199
+ def on_filtering_throttled(event)
200
+ consumer = event[:caller]
201
+ topic = consumer.topic.name
202
+ # Here we get last message before throttle
203
+ message = event[:message]
204
+ partition = message.partition
205
+ offset = message.offset
206
+
207
+ info <<~MSG.tr("\n", ' ').strip!
208
+ [#{consumer.id}] Throttled and will resume
209
+ from message #{offset}
210
+ on #{topic}/#{partition}
211
+ MSG
212
+ end
213
+
214
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
215
+ def on_filtering_seek(event)
216
+ consumer = event[:caller]
217
+ topic = consumer.topic.name
218
+ # Message to which we seek
219
+ message = event[:message]
220
+ partition = message.partition
221
+ offset = message.offset
222
+
223
+ info <<~MSG.tr("\n", ' ').strip!
224
+ [#{consumer.id}] Post-filtering seeking to message #{offset}
225
+ on #{topic}/#{partition}
226
+ MSG
227
+ end
228
+
229
+ # There are many types of errors that can occur in many places, but we provide a single
230
+ # handler for all of them to simplify error instrumentation.
231
+ # @param event [Karafka::Core::Monitoring::Event] event details including payload
232
+ def on_error_occurred(event)
233
+ type = event[:type]
234
+ error = event[:error]
235
+ details = (error.backtrace || []).join("\n")
236
+
237
+ case type
238
+ when 'consumer.consume.error'
239
+ error "Consumer consuming error: #{error}"
240
+ error details
241
+ when 'consumer.revoked.error'
242
+ error "Consumer on revoked failed due to an error: #{error}"
243
+ error details
244
+ when 'consumer.before_enqueue.error'
245
+ error "Consumer before enqueue failed due to an error: #{error}"
246
+ error details
247
+ when 'consumer.before_consume.error'
248
+ error "Consumer before consume failed due to an error: #{error}"
249
+ error details
250
+ when 'consumer.after_consume.error'
251
+ error "Consumer after consume failed due to an error: #{error}"
252
+ error details
253
+ when 'consumer.idle.error'
254
+ error "Consumer idle failed due to an error: #{error}"
255
+ error details
256
+ when 'consumer.shutdown.error'
257
+ error "Consumer on shutdown failed due to an error: #{error}"
258
+ error details
259
+ when 'worker.process.error'
260
+ fatal "Worker processing failed due to an error: #{error}"
261
+ fatal details
262
+ when 'connection.listener.fetch_loop.error'
263
+ error "Listener fetch loop error: #{error}"
264
+ error details
265
+ when 'runner.call.error'
266
+ fatal "Runner crashed due to an error: #{error}"
267
+ fatal details
268
+ when 'app.stopping.error'
269
+ error 'Forceful Karafka server stop'
270
+ when 'librdkafka.error'
271
+ error "librdkafka internal error occurred: #{error}"
272
+ error details
273
+ # Those can occur when emitted statistics are consumed by the end user and the processing
274
+ # of statistics fails. The statistics are emitted from librdkafka main loop thread and
275
+ # any errors there crash the whole thread
276
+ when 'statistics.emitted.error'
277
+ error "statistics.emitted processing failed due to an error: #{error}"
278
+ error details
279
+ # Those will only occur when retries in the client fail and when they did not stop after
280
+ # back-offs
281
+ when 'connection.client.poll.error'
282
+ error "Data polling error occurred: #{error}"
283
+ error details
284
+ when 'connection.client.rebalance_callback.error'
285
+ error "Rebalance callback error occurred: #{error}"
286
+ error details
287
+ when 'connection.client.unsubscribe.error'
288
+ error "Client unsubscribe error occurred: #{error}"
289
+ error details
290
+ else
291
+ # This should never happen. Please contact the maintainers
292
+ raise Errors::UnsupportedCaseError, event
293
+ end
294
+ end
295
+
296
+ USED_LOG_LEVELS.each do |log_level|
297
+ define_method log_level do |*args|
298
+ Karafka.logger.send(log_level, *args)
299
+ end
300
+ end
301
+ end
302
+ end
303
+ end
@@ -1,69 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Karafka
4
- # Namespace for all the things related with Karafka instrumentation process
5
4
  module Instrumentation
6
- # Monitor is used to hookup external monitoring services to monitor how Karafka works
7
- # It provides a standardized API for checking incoming messages/enqueueing etc
8
- # Since it is a pub-sub based on dry-monitor, you can use as many subscribers/loggers at the
9
- # same time, which means that you might have for example file logging and NewRelic at the same
10
- # time
11
- # @note This class acts as a singleton because we are only permitted to have single monitor
12
- # per running process (just as logger)
13
- class Monitor < Dry::Monitor::Notifications
14
- # List of events that we support in the system and to which a monitor client can hook up
15
- # @note The non-error once support timestamp benchmarking
16
- # @note Depending on Karafka extensions and additional engines, this might not be the
17
- # complete list of all the events. Please use the #available_events on fully loaded
18
- # Karafka system to determine all of the events you can use.
19
- # Last 4 events are from WaterDrop but for convenience we use the same monitor for the
20
- # whole karafka ecosystem
21
- BASE_EVENTS = %w[
22
- params.params.deserialize
23
- params.params.deserialize.error
24
- connection.listener.before_fetch_loop
25
- connection.listener.fetch_loop
26
- connection.listener.fetch_loop.error
27
- connection.client.fetch_loop.error
28
- connection.batch_delegator.call
29
- connection.message_delegator.call
30
- fetcher.call.error
31
- backends.inline.process
32
- process.notice_signal
33
- consumers.responders.respond_with
34
- async_producer.call.error
35
- async_producer.call.retry
36
- sync_producer.call.error
37
- sync_producer.call.retry
38
- app.initializing
39
- app.initialized
40
- app.running
41
- app.stopping
42
- app.stopping.error
43
- app.stopped
44
- ].freeze
5
+ # Karafka instrumentation monitor that we use to publish events
6
+ # By default uses our internal notifications bus but can be used with
7
+ # `ActiveSupport::Notifications` as well
8
+ class Monitor < ::Karafka::Core::Monitoring::Monitor
9
+ attr_reader :notifications_bus
45
10
 
46
- private_constant :BASE_EVENTS
47
-
48
- # @return [Karafka::Instrumentation::Monitor] monitor instance for system instrumentation
49
- def initialize
50
- super(:karafka)
51
- BASE_EVENTS.each(&method(:register_event))
52
- end
53
-
54
- # Allows us to subscribe to events with a code that will be yielded upon events
55
- # @param event_name_or_listener [String, Object] name of the event we want to subscribe to
56
- # or a listener if we decide to go with object listener
57
- def subscribe(event_name_or_listener)
58
- return super unless event_name_or_listener.is_a?(String)
59
- return super if available_events.include?(event_name_or_listener)
60
-
61
- raise Errors::UnregisteredMonitorEventError, event_name_or_listener
62
- end
63
-
64
- # @return [Array<String>] names of available events to which we can subscribe
65
- def available_events
66
- __bus__.events.keys
11
+ # @param notifications_bus [Object] either our internal notifications bus or
12
+ # `ActiveSupport::Notifications`
13
+ # @param namespace [String, nil] namespace for events or nil if no namespace
14
+ def initialize(
15
+ notifications_bus = ::Karafka::Instrumentation::Notifications.new,
16
+ namespace = nil
17
+ )
18
+ super(notifications_bus, namespace)
67
19
  end
68
20
  end
69
21
  end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ # Namespace for all the things related with Karafka instrumentation process
5
+ module Instrumentation
6
+ # Monitor is used to hookup external monitoring services to monitor how Karafka works
7
+ # It provides a standardized API for checking incoming messages/enqueueing etc
8
+ # Since it is a pub-sub based on dry-monitor, you can use as many subscribers/loggers at the
9
+ # same time, which means that you might have for example file logging and NewRelic at the same
10
+ # time
11
+ # @note This class acts as a singleton because we are only permitted to have single monitor
12
+ # per running process (just as logger)
13
+ class Notifications < Karafka::Core::Monitoring::Notifications
14
+ # List of events that we support in the system and to which a monitor client can hook up
15
+ # @note The non-error once support timestamp benchmarking
16
+ # @note Depending on Karafka extensions and additional engines, this might not be the
17
+ # complete list of all the events. Please use the #available_events on fully loaded
18
+ # Karafka system to determine all of the events you can use.
19
+ EVENTS = %w[
20
+ active_job.consume
21
+ active_job.consumed
22
+
23
+ app.initialized
24
+ app.running
25
+ app.quieting
26
+ app.quiet
27
+ app.stopping
28
+ app.stopped
29
+ app.terminated
30
+
31
+ client.pause
32
+ client.resume
33
+
34
+ connection.listener.before_fetch_loop
35
+ connection.listener.fetch_loop
36
+ connection.listener.fetch_loop.received
37
+
38
+ connection.client.poll.error
39
+ connection.client.unsubscribe.error
40
+
41
+ rebalance.partitions_assign
42
+ rebalance.partitions_assigned
43
+ rebalance.partitions_revoke
44
+ rebalance.partitions_revoked
45
+
46
+ consumer.consume
47
+ consumer.consumed
48
+ consumer.consuming.pause
49
+ consumer.consuming.retry
50
+ consumer.idle
51
+ consumer.revoke
52
+ consumer.revoked
53
+ consumer.shutting_down
54
+ consumer.shutdown
55
+
56
+ dead_letter_queue.dispatched
57
+
58
+ filtering.throttled
59
+ filtering.seek
60
+
61
+ process.notice_signal
62
+
63
+ statistics.emitted
64
+
65
+ worker.process
66
+ worker.processed
67
+ worker.completed
68
+
69
+ error.occurred
70
+ ].freeze
71
+
72
+ # @return [Karafka::Instrumentation::Monitor] monitor instance for system instrumentation
73
+ def initialize
74
+ super
75
+ EVENTS.each { |event| register_event(event) }
76
+ end
77
+ end
78
+ end
79
+ end
@@ -4,22 +4,13 @@ module Karafka
4
4
  module Instrumentation
5
5
  # Listener that sets a proc title with a nice descriptive value
6
6
  class ProctitleListener
7
- # Updates proc title to an initializing one
8
- # @param _event [Dry::Events::Event] event details including payload
9
- def on_app_initializing(_event)
10
- setproctitle('initializing')
11
- end
12
-
13
- # Updates proc title to a running one
14
- # @param _event [Dry::Events::Event] event details including payload
15
- def on_app_running(_event)
16
- setproctitle('running')
17
- end
18
-
19
- # Updates proc title to a stopping one
20
- # @param _event [Dry::Events::Event] event details including payload
21
- def on_app_stopping(_event)
22
- setproctitle('stopping')
7
+ Status::STATES.each_key do |state|
8
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
9
+ # Updates proc title to an appropriate state
10
+ def on_app_#{state}(_event)
11
+ setproctitle('#{state}')
12
+ end
13
+ RUBY
23
14
  end
24
15
 
25
16
  private
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'client'
4
+
5
+ module Karafka
6
+ module Instrumentation
7
+ module Vendors
8
+ # Namespace for Appsignal instrumentation
9
+ module Appsignal
10
+ # Base for all the instrumentation listeners
11
+ class Base
12
+ include ::Karafka::Core::Configurable
13
+ extend Forwardable
14
+
15
+ # @param block [Proc] configuration block
16
+ def initialize(&block)
17
+ configure
18
+ setup(&block) if block
19
+ end
20
+
21
+ # @param block [Proc] configuration block
22
+ # @note We define this alias to be consistent with `Karafka#setup`
23
+ def setup(&block)
24
+ configure(&block)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Instrumentation
5
+ module Vendors
6
+ module Appsignal
7
+ # Appsignal client wrapper
8
+ # We wrap the native client so we can inject our own stub in specs when needed
9
+ #
10
+ # It also abstracts away the notion of transactions and their management
11
+ #
12
+ # @note This client is abstract, it has no notion of Karafka whatsoever
13
+ class Client
14
+ # Starts an appsignal transaction with a given action name
15
+ #
16
+ # @param action_name [String] action name. For processing this should be equal to
17
+ # consumer class + method name
18
+ def start_transaction(action_name)
19
+ transaction = ::Appsignal::Transaction.create(
20
+ SecureRandom.uuid,
21
+ ::Appsignal::Transaction::BACKGROUND_JOB,
22
+ ::Appsignal::Transaction::GenericRequest.new({})
23
+ )
24
+
25
+ transaction.set_action_if_nil(action_name)
26
+ end
27
+
28
+ # Stops the current transaction (if any)
29
+ def stop_transaction
30
+ return unless transaction?
31
+
32
+ ::Appsignal::Transaction.complete_current!
33
+ end
34
+
35
+ # Sets metadata on a current transaction (if any)
36
+ #
37
+ # @param metadata_hash [Hash] hash with metadata we want to set
38
+ def metadata=(metadata_hash)
39
+ return unless transaction?
40
+
41
+ transaction = ::Appsignal::Transaction.current
42
+
43
+ stringify_hash(metadata_hash).each do |key, value|
44
+ transaction.set_metadata(key, value)
45
+ end
46
+ end
47
+
48
+ # Increments counter with the given value and tags
49
+ #
50
+ # @param key [String] key we want to use
51
+ # @param value [Integer] increment value
52
+ # @param tags [Hash] additional extra tags
53
+ def count(key, value, tags)
54
+ ::Appsignal.increment_counter(
55
+ key,
56
+ value,
57
+ stringify_hash(tags)
58
+ )
59
+ end
60
+
61
+ # Sets gauge with the given value and tags
62
+ #
63
+ # @param key [String] key we want to use
64
+ # @param value [Integer] gauge value
65
+ # @param tags [Hash] additional extra tags
66
+ def gauge(key, value, tags)
67
+ ::Appsignal.set_gauge(
68
+ key,
69
+ value,
70
+ stringify_hash(tags)
71
+ )
72
+ end
73
+
74
+ # Sends the error that occurred to Appsignal
75
+ #
76
+ # @param error [Object] error we want to ship to Appsignal
77
+ def send_error(error)
78
+ # If we have an active transaction we should use it instead of creating a generic one
79
+ # That way proper namespace and other data may be transferred
80
+ #
81
+ # In case there is no transaction, a new generic background job one will be used
82
+ if transaction?
83
+ transaction.set_error(error)
84
+ else
85
+ ::Appsignal.send_error(error) do |transaction|
86
+ transaction.set_namespace(::Appsignal::Transaction::BACKGROUND_JOB)
87
+ end
88
+ end
89
+ end
90
+
91
+ # Registers the probe under a given name
92
+ # @param name [Symbol] probe name
93
+ # @param probe [Proc] code to run every minute
94
+ def register_probe(name, probe)
95
+ ::Appsignal::Minutely.probes.register(name, probe)
96
+ end
97
+
98
+ private
99
+
100
+ # @return [Boolean] do we have a transaction
101
+ def transaction?
102
+ ::Appsignal::Transaction.current?
103
+ end
104
+
105
+ # @return [::Appsignal::Transaction, nil] transaction or nil if not started
106
+ def transaction
107
+ ::Appsignal::Transaction.current
108
+ end
109
+
110
+ # Converts both keys and values of a hash into strings
111
+ # @param hash [Hash]
112
+ # @return [Hash]
113
+ def stringify_hash(hash)
114
+ hash
115
+ .transform_values(&:to_s)
116
+ .transform_keys!(&:to_s)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end