karafka 1.4.12 → 2.2.10

Sign up to get free protection for your applications and to get access to all the features.
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