karafka-web 0.10.4 → 0.11.2

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 (496) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -176
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +78 -45
  5. data/LICENSE +6 -2
  6. data/Rakefile +4 -0
  7. data/bin/verify_kafka_warnings +35 -0
  8. data/bin/verify_topics_naming +35 -0
  9. data/config/locales/pro_errors.yml +1 -0
  10. data/config/locales/slogans.yml +1 -1
  11. data/docker-compose.yml +1 -1
  12. data/gulpfile.js +0 -2
  13. data/karafka-web.gemspec +2 -7
  14. data/lib/karafka/web/config.rb +80 -9
  15. data/lib/karafka/web/contracts/config.rb +44 -5
  16. data/lib/karafka/web/errors.rb +10 -12
  17. data/lib/karafka/web/management/actions/create_initial_states.rb +6 -6
  18. data/lib/karafka/web/management/actions/create_topics.rb +30 -64
  19. data/lib/karafka/web/management/actions/delete_topics.rb +5 -5
  20. data/lib/karafka/web/management/actions/enable.rb +5 -5
  21. data/lib/karafka/web/pro/commanding/commands/base.rb +37 -13
  22. data/lib/karafka/web/pro/commanding/commands/consumers/quiet.rb +33 -0
  23. data/lib/karafka/web/pro/commanding/commands/consumers/stop.rb +32 -0
  24. data/lib/karafka/web/pro/commanding/commands/consumers/trace.rb +37 -0
  25. data/lib/karafka/web/pro/commanding/commands/partitions/pause.rb +30 -0
  26. data/lib/karafka/web/pro/commanding/commands/partitions/resume.rb +30 -0
  27. data/lib/karafka/web/pro/commanding/commands/partitions/seek.rb +30 -0
  28. data/lib/karafka/web/pro/commanding/config.rb +6 -10
  29. data/lib/karafka/web/pro/commanding/contracts/config.rb +2 -10
  30. data/lib/karafka/web/pro/commanding/dispatcher.rb +45 -24
  31. data/lib/karafka/web/pro/commanding/handlers/partitions/commands/base.rb +67 -0
  32. data/lib/karafka/web/pro/commanding/handlers/partitions/commands/pause.rb +44 -0
  33. data/lib/karafka/web/pro/commanding/handlers/partitions/commands/resume.rb +29 -0
  34. data/lib/karafka/web/pro/commanding/handlers/partitions/commands/seek.rb +86 -0
  35. data/lib/karafka/web/pro/commanding/handlers/partitions/executor.rb +56 -0
  36. data/lib/karafka/web/pro/commanding/handlers/partitions/listener.rb +55 -0
  37. data/lib/karafka/web/pro/commanding/handlers/partitions/tracker.rb +62 -0
  38. data/lib/karafka/web/pro/commanding/listener.rb +4 -12
  39. data/lib/karafka/web/pro/commanding/manager.rb +36 -24
  40. data/lib/karafka/web/pro/commanding/matcher.rb +7 -17
  41. data/lib/karafka/web/pro/commanding/request.rb +39 -0
  42. data/lib/karafka/web/pro/commanding.rb +2 -10
  43. data/lib/karafka/web/pro/loader.rb +13 -10
  44. data/lib/karafka/web/pro/ui/app.rb +31 -390
  45. data/lib/karafka/web/pro/ui/controllers/base_controller.rb +8 -10
  46. data/lib/karafka/web/pro/ui/controllers/cluster_controller.rb +2 -10
  47. data/lib/karafka/web/pro/ui/controllers/consumers/base_controller.rb +21 -0
  48. data/lib/karafka/web/pro/ui/controllers/consumers/commanding_controller.rb +148 -0
  49. data/lib/karafka/web/pro/ui/controllers/consumers/commands_controller.rb +96 -0
  50. data/lib/karafka/web/pro/ui/controllers/consumers/consumers_controller.rb +99 -0
  51. data/lib/karafka/web/pro/ui/controllers/consumers/controls_controller.rb +36 -0
  52. data/lib/karafka/web/pro/ui/controllers/consumers/jobs_controller.rb +57 -0
  53. data/lib/karafka/web/pro/ui/controllers/consumers/partitions/base_controller.rb +86 -0
  54. data/lib/karafka/web/pro/ui/controllers/consumers/partitions/offsets_controller.rb +75 -0
  55. data/lib/karafka/web/pro/ui/controllers/consumers/partitions/pauses_controller.rb +110 -0
  56. data/lib/karafka/web/pro/ui/controllers/dashboard_controller.rb +2 -10
  57. data/lib/karafka/web/pro/ui/controllers/dlq_controller.rb +2 -10
  58. data/lib/karafka/web/pro/ui/controllers/errors_controller.rb +11 -15
  59. data/lib/karafka/web/pro/ui/controllers/explorer/base_controller.rb +21 -0
  60. data/lib/karafka/web/pro/ui/controllers/explorer/explorer_controller.rb +225 -0
  61. data/lib/karafka/web/pro/ui/controllers/explorer/messages_controller.rb +145 -0
  62. data/lib/karafka/web/pro/ui/controllers/explorer/search_controller.rb +68 -0
  63. data/lib/karafka/web/pro/ui/controllers/health_controller.rb +2 -10
  64. data/lib/karafka/web/pro/ui/controllers/jobs_controller.rb +2 -10
  65. data/lib/karafka/web/pro/ui/controllers/recurring_tasks_controller.rb +12 -13
  66. data/lib/karafka/web/pro/ui/controllers/routing_controller.rb +2 -10
  67. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/base_controller.rb +2 -10
  68. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/explorer_controller.rb +8 -16
  69. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/messages_controller.rb +9 -15
  70. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/schedules_controller.rb +2 -10
  71. data/lib/karafka/web/pro/ui/controllers/status_controller.rb +2 -10
  72. data/lib/karafka/web/pro/ui/controllers/support_controller.rb +2 -10
  73. data/lib/karafka/web/pro/ui/controllers/topics/base_controller.rb +21 -0
  74. data/lib/karafka/web/pro/ui/controllers/topics/configs_controller.rb +86 -0
  75. data/lib/karafka/web/pro/ui/controllers/topics/distributions_controller.rb +91 -0
  76. data/lib/karafka/web/pro/ui/controllers/topics/offsets_controller.rb +55 -0
  77. data/lib/karafka/web/pro/ui/controllers/topics/replications_controller.rb +37 -0
  78. data/lib/karafka/web/pro/ui/controllers/topics/topics_controller.rb +101 -0
  79. data/lib/karafka/web/pro/ui/controllers/ux_controller.rb +2 -10
  80. data/lib/karafka/web/pro/ui/lib/branding/config.rb +2 -10
  81. data/lib/karafka/web/pro/ui/lib/branding/contracts/config.rb +2 -10
  82. data/lib/karafka/web/pro/ui/lib/branding.rb +2 -10
  83. data/lib/karafka/web/pro/ui/lib/features.rb +53 -0
  84. data/lib/karafka/web/pro/ui/lib/patterns_detector.rb +2 -10
  85. data/lib/karafka/web/pro/ui/lib/policies/config.rb +2 -10
  86. data/lib/karafka/web/pro/ui/lib/policies/contracts/config.rb +2 -10
  87. data/lib/karafka/web/pro/ui/lib/policies/messages.rb +2 -10
  88. data/lib/karafka/web/pro/ui/lib/policies/requests.rb +2 -10
  89. data/lib/karafka/web/pro/ui/lib/policies.rb +2 -10
  90. data/lib/karafka/web/pro/ui/lib/safe_runner.rb +5 -0
  91. data/lib/karafka/web/pro/ui/lib/search/config.rb +2 -10
  92. data/lib/karafka/web/pro/ui/lib/search/contracts/config.rb +2 -10
  93. data/lib/karafka/web/pro/ui/lib/search/contracts/form.rb +2 -10
  94. data/lib/karafka/web/pro/ui/lib/search/matchers/base.rb +2 -10
  95. data/lib/karafka/web/pro/ui/lib/search/matchers/raw_header_includes.rb +10 -11
  96. data/lib/karafka/web/pro/ui/lib/search/matchers/raw_key_includes.rb +2 -10
  97. data/lib/karafka/web/pro/ui/lib/search/matchers/raw_payload_includes.rb +23 -11
  98. data/lib/karafka/web/pro/ui/lib/search/normalizer.rb +2 -10
  99. data/lib/karafka/web/pro/ui/lib/search/runner.rb +3 -11
  100. data/lib/karafka/web/pro/ui/lib/search.rb +2 -10
  101. data/lib/karafka/web/pro/ui/routes/base.rb +19 -0
  102. data/lib/karafka/web/pro/ui/routes/cluster.rb +37 -0
  103. data/lib/karafka/web/pro/ui/routes/consumers.rb +145 -0
  104. data/lib/karafka/web/pro/ui/routes/dashboard.rb +25 -0
  105. data/lib/karafka/web/pro/ui/routes/dlq.rb +24 -0
  106. data/lib/karafka/web/pro/ui/routes/errors.rb +39 -0
  107. data/lib/karafka/web/pro/ui/routes/explorer.rb +118 -0
  108. data/lib/karafka/web/pro/ui/routes/health.rb +47 -0
  109. data/lib/karafka/web/pro/ui/routes/jobs.rb +33 -0
  110. data/lib/karafka/web/pro/ui/routes/recurring_tasks.rb +59 -0
  111. data/lib/karafka/web/pro/ui/routes/routing.rb +31 -0
  112. data/lib/karafka/web/pro/ui/routes/scheduled_messages.rb +75 -0
  113. data/lib/karafka/web/pro/ui/routes/status.rb +24 -0
  114. data/lib/karafka/web/pro/ui/routes/support.rb +24 -0
  115. data/lib/karafka/web/pro/ui/routes/topics.rb +90 -0
  116. data/lib/karafka/web/pro/ui/routes/ux.rb +24 -0
  117. data/lib/karafka/web/pro/ui/views/cluster/_breadcrumbs.erb +3 -0
  118. data/lib/karafka/web/pro/ui/views/cluster/_broker.erb +3 -0
  119. data/lib/karafka/web/pro/ui/views/cluster/_config.erb +3 -0
  120. data/lib/karafka/web/pro/ui/views/cluster/_tabs.erb +3 -0
  121. data/lib/karafka/web/pro/ui/views/cluster/index.erb +4 -1
  122. data/lib/karafka/web/pro/ui/views/cluster/show.erb +3 -0
  123. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_backtrace.erb +3 -0
  124. data/lib/karafka/web/pro/ui/views/consumers/commands/_breadcrumbs.erb +24 -0
  125. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_command.erb +22 -6
  126. data/lib/karafka/web/pro/ui/views/consumers/commands/_command_details.erb +4 -0
  127. data/lib/karafka/web/pro/ui/views/consumers/commands/_empty.erb +6 -0
  128. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_incompatible_schema.erb +3 -0
  129. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_metadata.erb +4 -1
  130. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_table.erb +5 -2
  131. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/index.erb +7 -4
  132. data/lib/karafka/web/pro/ui/views/consumers/commands/show.erb +32 -0
  133. data/lib/karafka/web/pro/ui/views/consumers/consumers/_breadcrumbs.erb +46 -0
  134. data/lib/karafka/web/pro/ui/views/consumers/{_consumer.erb → consumers/_consumer.erb} +4 -1
  135. data/lib/karafka/web/pro/ui/views/consumers/{_consumer_performance.erb → consumers/_consumer_performance.erb} +4 -1
  136. data/lib/karafka/web/pro/ui/views/consumers/consumers/_tabs.erb +38 -0
  137. data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_commands.erb +80 -0
  138. data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_consumer_group.erb +11 -0
  139. data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_metrics.erb +3 -0
  140. data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_no_subscriptions.erb +10 -0
  141. data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_partition.erb +16 -0
  142. data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_partition_edit_options.erb +33 -0
  143. data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_stopped.erb +3 -0
  144. data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_subscription_group.erb +7 -3
  145. data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_tabs.erb +7 -4
  146. data/lib/karafka/web/pro/ui/views/consumers/consumers/details.erb +15 -0
  147. data/lib/karafka/web/pro/ui/views/consumers/{index.erb → consumers/index.erb} +6 -3
  148. data/lib/karafka/web/pro/ui/views/consumers/{performance.erb → consumers/performance.erb} +6 -3
  149. data/lib/karafka/web/pro/ui/views/consumers/consumers/subscriptions.erb +24 -0
  150. data/lib/karafka/web/pro/ui/views/consumers/controls/_breadcrumbs.erb +16 -0
  151. data/lib/karafka/web/pro/ui/views/consumers/{_consumer_controls.erb → controls/_controls.erb} +10 -7
  152. data/lib/karafka/web/pro/ui/views/consumers/{controls.erb → controls/index.erb} +8 -5
  153. data/lib/karafka/web/pro/ui/views/consumers/jobs/_breadcrumbs.erb +36 -0
  154. data/lib/karafka/web/pro/ui/views/consumers/{consumer → jobs}/_job.erb +4 -2
  155. data/lib/karafka/web/pro/ui/views/consumers/jobs/_no_jobs.erb +6 -0
  156. data/lib/karafka/web/pro/ui/views/consumers/{pending_jobs.erb → jobs/pending.erb} +7 -8
  157. data/lib/karafka/web/pro/ui/views/consumers/{running_jobs.erb → jobs/running.erb} +7 -8
  158. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_basics.erb +77 -0
  159. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_breadcrumbs.erb +58 -0
  160. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_form.erb +109 -0
  161. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_not_running_error.erb +16 -0
  162. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_running_warning.erb +15 -0
  163. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/edit.erb +16 -0
  164. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_active_not_editable.erb +22 -0
  165. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_adjusting_warning.erb +27 -0
  166. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_breadcrumbs.erb +60 -0
  167. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_edit_form.erb +59 -0
  168. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_lrj_not_manageable.erb +24 -0
  169. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_new_form.erb +78 -0
  170. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_not_running.erb +16 -0
  171. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/edit.erb +24 -0
  172. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/new.erb +20 -0
  173. data/lib/karafka/web/pro/ui/views/dashboard/index.erb +4 -1
  174. data/lib/karafka/web/pro/ui/views/dlq/_breadcrumbs.erb +3 -0
  175. data/lib/karafka/web/pro/ui/views/dlq/_no_topics.erb +3 -0
  176. data/lib/karafka/web/pro/ui/views/dlq/_topic.erb +4 -1
  177. data/lib/karafka/web/pro/ui/views/dlq/index.erb +3 -0
  178. data/lib/karafka/web/pro/ui/views/errors/_breadcrumbs.erb +4 -6
  179. data/lib/karafka/web/pro/ui/views/errors/_error.erb +9 -1
  180. data/lib/karafka/web/pro/ui/views/errors/_partition_option.erb +3 -0
  181. data/lib/karafka/web/pro/ui/views/errors/_selector.erb +3 -0
  182. data/lib/karafka/web/pro/ui/views/errors/_table.erb +4 -1
  183. data/lib/karafka/web/pro/ui/views/errors/index.erb +6 -3
  184. data/lib/karafka/web/pro/ui/views/errors/partition.erb +5 -2
  185. data/lib/karafka/web/pro/ui/views/errors/show.erb +42 -33
  186. data/lib/karafka/web/pro/ui/views/explorer/{_breadcrumbs.erb → explorer/_breadcrumbs.erb} +7 -4
  187. data/lib/karafka/web/pro/ui/views/explorer/{_failed_deserialization.erb → explorer/_failed_deserialization.erb} +3 -0
  188. data/lib/karafka/web/pro/ui/views/explorer/{_filtered.erb → explorer/_filtered.erb} +3 -0
  189. data/lib/karafka/web/pro/ui/views/explorer/{_message.erb → explorer/_message.erb} +4 -1
  190. data/lib/karafka/web/pro/ui/views/explorer/explorer/_no_topics.erb +4 -0
  191. data/lib/karafka/web/pro/ui/views/explorer/{_partition_option.erb → explorer/_partition_option.erb} +4 -1
  192. data/lib/karafka/web/pro/ui/views/explorer/{_selector.erb → explorer/_selector.erb} +4 -1
  193. data/lib/karafka/web/pro/ui/views/explorer/explorer/_topic.erb +13 -0
  194. data/lib/karafka/web/pro/ui/views/explorer/explorer/index.erb +17 -0
  195. data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_metadata.erb +10 -7
  196. data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_payload.erb +6 -3
  197. data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_resources_utilization.erb +7 -4
  198. data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_too_big_to_be_displayed.erb +3 -0
  199. data/lib/karafka/web/pro/ui/views/explorer/{messages → explorer/messages}/_detail.erb +3 -0
  200. data/lib/karafka/web/pro/ui/views/explorer/explorer/messages/_headers.erb +51 -0
  201. data/lib/karafka/web/pro/ui/views/explorer/{messages → explorer/messages}/_key.erb +3 -0
  202. data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_cleaned.erb +6 -0
  203. data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_empty.erb +6 -0
  204. data/lib/karafka/web/pro/ui/views/explorer/{partition → explorer/partition}/_messages.erb +4 -1
  205. data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_time_selector.erb +16 -0
  206. data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_timestamp_selector.erb +33 -0
  207. data/lib/karafka/web/pro/ui/views/explorer/{partition.erb → explorer/partition.erb} +24 -17
  208. data/lib/karafka/web/pro/ui/views/explorer/explorer/show.erb +100 -0
  209. data/lib/karafka/web/pro/ui/views/explorer/{topic → explorer/topic}/_actions.erb +5 -2
  210. data/lib/karafka/web/pro/ui/views/explorer/explorer/topic/_empty.erb +6 -0
  211. data/lib/karafka/web/pro/ui/views/explorer/{topic → explorer/topic}/_limited.erb +3 -0
  212. data/lib/karafka/web/pro/ui/views/explorer/{topic.erb → explorer/topic.erb} +7 -4
  213. data/lib/karafka/web/pro/ui/views/explorer/messages/_breadcrumbs.erb +32 -0
  214. data/lib/karafka/web/pro/ui/views/explorer/messages/forward.erb +143 -0
  215. data/lib/karafka/web/pro/ui/views/explorer/search/_breadcrumbs.erb +4 -0
  216. data/lib/karafka/web/pro/ui/views/explorer/search/_fix_errors.erb +6 -0
  217. data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_metadata.erb +3 -0
  218. data/lib/karafka/web/pro/ui/views/explorer/search/_no_results.erb +6 -0
  219. data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_no_search_criteria.erb +3 -0
  220. data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_search_criteria.erb +3 -0
  221. data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_search_modal.erb +5 -2
  222. data/lib/karafka/web/pro/ui/views/explorer/search/_timeout.erb +6 -0
  223. data/lib/karafka/web/pro/ui/views/explorer/search/index.erb +32 -0
  224. data/lib/karafka/web/pro/ui/views/health/_breadcrumbs.erb +3 -0
  225. data/lib/karafka/web/pro/ui/views/health/_no_data.erb +3 -0
  226. data/lib/karafka/web/pro/ui/views/health/_partition.erb +16 -1
  227. data/lib/karafka/web/pro/ui/views/health/_partition_lags.erb +3 -0
  228. data/lib/karafka/web/pro/ui/views/health/_partition_offset.erb +3 -0
  229. data/lib/karafka/web/pro/ui/views/health/_partition_times.erb +3 -0
  230. data/lib/karafka/web/pro/ui/views/health/_table_metadata.erb +4 -1
  231. data/lib/karafka/web/pro/ui/views/health/_tabs.erb +3 -0
  232. data/lib/karafka/web/pro/ui/views/health/changes.erb +4 -1
  233. data/lib/karafka/web/pro/ui/views/health/cluster_lags.erb +3 -0
  234. data/lib/karafka/web/pro/ui/views/health/lags.erb +5 -2
  235. data/lib/karafka/web/pro/ui/views/health/offsets.erb +4 -1
  236. data/lib/karafka/web/pro/ui/views/health/overview.erb +8 -3
  237. data/lib/karafka/web/pro/ui/views/jobs/_job.erb +5 -3
  238. data/lib/karafka/web/pro/ui/views/jobs/_no_jobs.erb +3 -0
  239. data/lib/karafka/web/pro/ui/views/jobs/pending.erb +4 -1
  240. data/lib/karafka/web/pro/ui/views/jobs/running.erb +4 -1
  241. data/lib/karafka/web/pro/ui/views/recurring_tasks/_actions.erb +3 -0
  242. data/lib/karafka/web/pro/ui/views/recurring_tasks/_batch_actions.erb +3 -0
  243. data/lib/karafka/web/pro/ui/views/recurring_tasks/_breadcrumbs.erb +3 -0
  244. data/lib/karafka/web/pro/ui/views/recurring_tasks/_log.erb +3 -0
  245. data/lib/karafka/web/pro/ui/views/recurring_tasks/_not_active.erb +3 -0
  246. data/lib/karafka/web/pro/ui/views/recurring_tasks/_tabs.erb +3 -0
  247. data/lib/karafka/web/pro/ui/views/recurring_tasks/_task.erb +3 -0
  248. data/lib/karafka/web/pro/ui/views/recurring_tasks/logs.erb +3 -0
  249. data/lib/karafka/web/pro/ui/views/recurring_tasks/schedule.erb +3 -0
  250. data/lib/karafka/web/pro/ui/views/routing/_consumer_group.erb +3 -0
  251. data/lib/karafka/web/pro/ui/views/routing/_detail.erb +3 -0
  252. data/lib/karafka/web/pro/ui/views/routing/_topic.erb +3 -0
  253. data/lib/karafka/web/pro/ui/views/routing/index.erb +3 -0
  254. data/lib/karafka/web/pro/ui/views/routing/show.erb +3 -0
  255. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_breadcrumbs.erb +6 -3
  256. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_key.erb +3 -0
  257. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_message.erb +28 -115
  258. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_messages.erb +3 -0
  259. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/message/_cancel.erb +49 -0
  260. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/message/_compacted.erb +16 -0
  261. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/message/_schedule.erb +83 -0
  262. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/message/_tombstone.erb +69 -0
  263. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/message/_unknown.erb +26 -0
  264. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/partition.erb +23 -16
  265. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/topic.erb +6 -3
  266. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/_breadcrumbs.erb +3 -0
  267. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/_no_groups.erb +3 -0
  268. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/index.erb +4 -1
  269. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/show.erb +17 -1
  270. data/lib/karafka/web/pro/ui/views/shared/_navigation.erb +25 -17
  271. data/lib/karafka/web/pro/ui/views/shared/_rdkafka_form_error_alert_box.erb +16 -0
  272. data/lib/karafka/web/pro/ui/views/shared/branding/_label.erb +3 -0
  273. data/lib/karafka/web/pro/ui/views/shared/branding/_notice.erb +3 -0
  274. data/lib/karafka/web/pro/ui/views/topics/configs/_breadcrumbs.erb +34 -0
  275. data/lib/karafka/web/pro/ui/views/topics/configs/_config.erb +26 -0
  276. data/lib/karafka/web/pro/ui/views/topics/configs/_delete_button.erb +13 -0
  277. data/lib/karafka/web/pro/ui/views/topics/configs/_edit_form.erb +50 -0
  278. data/lib/karafka/web/pro/ui/views/topics/configs/_edit_plan.erb +16 -0
  279. data/lib/karafka/web/pro/ui/views/topics/configs/_edit_warning.erb +12 -0
  280. data/lib/karafka/web/pro/ui/views/topics/configs/edit.erb +16 -0
  281. data/lib/karafka/web/pro/ui/views/topics/{config.erb → configs/index.erb} +9 -3
  282. data/lib/karafka/web/pro/ui/views/topics/distributions/_add_partitions_button.erb +13 -0
  283. data/lib/karafka/web/pro/ui/views/topics/{distribution → distributions}/_badges.erb +3 -0
  284. data/lib/karafka/web/pro/ui/views/topics/distributions/_breadcrumbs.erb +28 -0
  285. data/lib/karafka/web/pro/ui/views/topics/{distribution → distributions}/_chart.erb +3 -0
  286. data/lib/karafka/web/pro/ui/views/topics/distributions/_edit_form.erb +47 -0
  287. data/lib/karafka/web/pro/ui/views/topics/distributions/_edit_hints.erb +15 -0
  288. data/lib/karafka/web/pro/ui/views/topics/distributions/_edit_warnings.erb +14 -0
  289. data/lib/karafka/web/pro/ui/views/topics/distributions/_empty_partitions.erb +4 -0
  290. data/lib/karafka/web/pro/ui/views/topics/{distribution → distributions}/_limited.erb +3 -0
  291. data/lib/karafka/web/pro/ui/views/topics/distributions/_partition.erb +13 -0
  292. data/lib/karafka/web/pro/ui/views/topics/distributions/edit.erb +16 -0
  293. data/lib/karafka/web/pro/ui/views/topics/{distribution.erb → distributions/show.erb} +11 -7
  294. data/lib/karafka/web/pro/ui/views/topics/offsets/_breadcrumbs.erb +20 -0
  295. data/lib/karafka/web/pro/ui/views/topics/offsets/_partition.erb +13 -0
  296. data/lib/karafka/web/pro/ui/views/topics/{offsets.erb → offsets/show.erb} +6 -3
  297. data/lib/karafka/web/pro/ui/views/topics/replications/_breadcrumbs.erb +20 -0
  298. data/lib/karafka/web/pro/ui/views/topics/{_partition.erb → replications/_partition.erb} +4 -1
  299. data/lib/karafka/web/pro/ui/views/topics/{replication.erb → replications/show.erb} +6 -3
  300. data/lib/karafka/web/pro/ui/views/topics/topics/_breadcrumbs.erb +32 -0
  301. data/lib/karafka/web/pro/ui/views/topics/topics/_create_button.erb +13 -0
  302. data/lib/karafka/web/pro/ui/views/topics/topics/_create_hints.erb +15 -0
  303. data/lib/karafka/web/pro/ui/views/topics/topics/_delete_form.erb +36 -0
  304. data/lib/karafka/web/pro/ui/views/topics/topics/_delete_hints.erb +15 -0
  305. data/lib/karafka/web/pro/ui/views/topics/topics/_delete_warning.erb +13 -0
  306. data/lib/karafka/web/pro/ui/views/topics/topics/_new_form.erb +80 -0
  307. data/lib/karafka/web/pro/ui/views/topics/{_tabs.erb → topics/_tabs.erb} +7 -4
  308. data/lib/karafka/web/pro/ui/views/topics/topics/_topic.erb +12 -0
  309. data/lib/karafka/web/pro/ui/views/topics/topics/edit.erb +10 -0
  310. data/lib/karafka/web/pro/ui/views/topics/topics/index.erb +19 -0
  311. data/lib/karafka/web/pro/ui/views/topics/topics/new.erb +12 -0
  312. data/lib/karafka/web/processing/consumer.rb +7 -7
  313. data/lib/karafka/web/processing/consumers/aggregators/state.rb +14 -14
  314. data/lib/karafka/web/processing/consumers/metrics.rb +1 -1
  315. data/lib/karafka/web/processing/consumers/state.rb +1 -1
  316. data/lib/karafka/web/processing/publisher.rb +4 -4
  317. data/lib/karafka/web/tracking/consumers/contracts/partition.rb +1 -0
  318. data/lib/karafka/web/tracking/consumers/listeners/errors.rb +1 -0
  319. data/lib/karafka/web/tracking/consumers/listeners/pausing.rb +2 -2
  320. data/lib/karafka/web/tracking/consumers/listeners/transactions.rb +44 -0
  321. data/lib/karafka/web/tracking/consumers/reporter.rb +8 -4
  322. data/lib/karafka/web/tracking/consumers/sampler.rb +81 -14
  323. data/lib/karafka/web/tracking/helpers/sysconf.rb +33 -0
  324. data/lib/karafka/web/tracking/helpers/ttls/array.rb +11 -0
  325. data/lib/karafka/web/tracking/helpers/ttls/hash.rb +7 -1
  326. data/lib/karafka/web/tracking/producers/reporter.rb +5 -3
  327. data/lib/karafka/web/ui/app.rb +19 -112
  328. data/lib/karafka/web/ui/base.rb +60 -3
  329. data/lib/karafka/web/ui/controllers/base_controller.rb +43 -1
  330. data/lib/karafka/web/ui/controllers/cluster_controller.rb +5 -2
  331. data/lib/karafka/web/ui/controllers/errors_controller.rb +13 -4
  332. data/lib/karafka/web/ui/controllers/requests/execution_wrapper.rb +52 -0
  333. data/lib/karafka/web/ui/controllers/requests/hookable.rb +99 -0
  334. data/lib/karafka/web/ui/controllers/requests/params.rb +39 -1
  335. data/lib/karafka/web/ui/controllers/responses/redirect.rb +0 -5
  336. data/lib/karafka/web/ui/controllers/status_controller.rb +3 -0
  337. data/lib/karafka/web/ui/helpers/application_helper.rb +10 -71
  338. data/lib/karafka/web/ui/helpers/paths_helper.rb +54 -10
  339. data/lib/karafka/web/ui/helpers/time_helper.rb +82 -0
  340. data/lib/karafka/web/ui/helpers/topics_helper.rb +156 -0
  341. data/lib/karafka/web/ui/lib/admin.rb +1 -1
  342. data/lib/karafka/web/ui/lib/cache.rb +135 -0
  343. data/lib/karafka/web/ui/models/broker.rb +1 -2
  344. data/lib/karafka/web/ui/models/cluster_info.rb +15 -21
  345. data/lib/karafka/web/ui/models/consumers_metrics.rb +1 -1
  346. data/lib/karafka/web/ui/models/consumers_state.rb +1 -1
  347. data/lib/karafka/web/ui/models/counters.rb +1 -1
  348. data/lib/karafka/web/ui/models/health.rb +9 -7
  349. data/lib/karafka/web/ui/models/message.rb +20 -2
  350. data/lib/karafka/web/ui/models/process.rb +16 -0
  351. data/lib/karafka/web/ui/models/processes.rb +29 -8
  352. data/lib/karafka/web/ui/models/recurring_tasks/schedule.rb +1 -1
  353. data/lib/karafka/web/ui/models/status.rb +28 -9
  354. data/lib/karafka/web/ui/models/topic.rb +1 -2
  355. data/lib/karafka/web/ui/public/javascripts/application.js +8 -98
  356. data/lib/karafka/web/ui/public/javascripts/application.min.js +12 -4
  357. data/lib/karafka/web/ui/public/javascripts/application.min.js.br +0 -0
  358. data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
  359. data/lib/karafka/web/ui/public/javascripts/components/action_confirmation_manager.js +30 -0
  360. data/lib/karafka/web/ui/public/javascripts/components/alerts.js +39 -0
  361. data/lib/karafka/web/ui/public/javascripts/components/button_lock_manager.js +50 -0
  362. data/lib/karafka/web/ui/public/javascripts/components/live_poll.js +71 -19
  363. data/lib/karafka/web/ui/public/javascripts/components/message_republish_manager.js +50 -0
  364. data/lib/karafka/web/ui/public/javascripts/components/page_title_tracker.js +21 -0
  365. data/lib/karafka/web/ui/public/javascripts/components/partition_redirect_manager.js +21 -0
  366. data/lib/karafka/web/ui/public/javascripts/components/time_ago_manager.js +25 -0
  367. data/lib/karafka/web/ui/public/javascripts/components/timestamp_selector.js +30 -0
  368. data/lib/karafka/web/ui/public/javascripts/libs/datepicker.js +2 -2
  369. data/lib/karafka/web/ui/public/stylesheets/application.css +30 -0
  370. data/lib/karafka/web/ui/public/stylesheets/application.min.css +5120 -13
  371. data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
  372. data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
  373. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_dark.min.css.gz +0 -0
  374. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_light.min.css.gz +0 -0
  375. data/lib/karafka/web/ui/public/stylesheets/libs/tailwind.css +507 -214
  376. data/lib/karafka/web/ui/routes/assets.rb +53 -0
  377. data/lib/karafka/web/ui/routes/base.rb +36 -0
  378. data/lib/karafka/web/ui/routes/cluster.rb +28 -0
  379. data/lib/karafka/web/ui/routes/consumers.rb +35 -0
  380. data/lib/karafka/web/ui/routes/dashboard.rb +20 -0
  381. data/lib/karafka/web/ui/routes/errors.rb +30 -0
  382. data/lib/karafka/web/ui/routes/jobs.rb +28 -0
  383. data/lib/karafka/web/ui/routes/pro_only.rb +27 -0
  384. data/lib/karafka/web/ui/routes/routing.rb +26 -0
  385. data/lib/karafka/web/ui/routes/status.rb +19 -0
  386. data/lib/karafka/web/ui/routes/support.rb +19 -0
  387. data/lib/karafka/web/ui/routes/ux.rb +19 -0
  388. data/lib/karafka/web/ui/views/cluster/_partition.erb +2 -2
  389. data/lib/karafka/web/ui/views/cluster/brokers.erb +1 -1
  390. data/lib/karafka/web/ui/views/consumers/_assignments_badges.erb +2 -7
  391. data/lib/karafka/web/ui/views/consumers/_breadcrumbs.erb +7 -1
  392. data/lib/karafka/web/ui/views/consumers/_consumer.erb +1 -1
  393. data/lib/karafka/web/ui/views/consumers/_no_consumers.erb +2 -2
  394. data/lib/karafka/web/ui/views/consumers/_tabs.erb +4 -4
  395. data/lib/karafka/web/ui/views/consumers/index.erb +1 -1
  396. data/lib/karafka/web/ui/views/dashboard/_feature_pro.erb +1 -1
  397. data/lib/karafka/web/ui/views/dashboard/_not_enough_data.erb +2 -2
  398. data/lib/karafka/web/ui/views/dashboard/_ranges_selector.erb +1 -1
  399. data/lib/karafka/web/ui/views/dashboard/index.erb +6 -49
  400. data/lib/karafka/web/ui/views/errors/_breadcrumbs.erb +3 -8
  401. data/lib/karafka/web/ui/views/errors/_detail.erb +3 -3
  402. data/lib/karafka/web/ui/views/errors/_error.erb +6 -1
  403. data/lib/karafka/web/ui/views/errors/index.erb +1 -1
  404. data/lib/karafka/web/ui/views/errors/show.erb +39 -33
  405. data/lib/karafka/web/ui/views/jobs/_job.erb +2 -3
  406. data/lib/karafka/web/ui/views/jobs/pending.erb +1 -1
  407. data/lib/karafka/web/ui/views/jobs/running.erb +1 -1
  408. data/lib/karafka/web/ui/views/layout.erb +7 -5
  409. data/lib/karafka/web/ui/views/shared/_become_pro.erb +1 -1
  410. data/lib/karafka/web/ui/views/shared/_brand.erb +1 -1
  411. data/lib/karafka/web/ui/views/shared/_breadcrumbs.erb +1 -1
  412. data/lib/karafka/web/ui/views/shared/_compacted_message_info.erb +16 -0
  413. data/lib/karafka/web/ui/views/shared/_content.erb +1 -1
  414. data/lib/karafka/web/ui/views/shared/_controls.erb +10 -3
  415. data/lib/karafka/web/ui/views/shared/_custom_nav.erb +9 -0
  416. data/lib/karafka/web/ui/views/shared/_flashes.erb +3 -5
  417. data/lib/karafka/web/ui/views/shared/_header.erb +25 -2
  418. data/lib/karafka/web/ui/views/shared/_navigation.erb +17 -15
  419. data/lib/karafka/web/ui/views/shared/alerts/_error.erb +8 -0
  420. data/lib/karafka/web/ui/views/shared/alerts/_info.erb +8 -0
  421. data/lib/karafka/web/ui/views/shared/alerts/_primary.erb +8 -0
  422. data/lib/karafka/web/ui/views/shared/alerts/_secondary.erb +8 -0
  423. data/lib/karafka/web/ui/views/shared/alerts/_success.erb +8 -0
  424. data/lib/karafka/web/ui/views/shared/alerts/_warning.erb +8 -0
  425. data/lib/karafka/web/ui/views/shared/exceptions/not_allowed.erb +4 -0
  426. data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +5 -1
  427. data/lib/karafka/web/ui/views/shared/exceptions/pro_only.erb +4 -0
  428. data/lib/karafka/web/ui/views/shared/icons/_arrow_left.erb +3 -0
  429. data/lib/karafka/web/ui/views/shared/icons/_arrow_up_tray.erb +3 -0
  430. data/lib/karafka/web/ui/views/shared/icons/_clock.erb +3 -0
  431. data/lib/karafka/web/ui/views/shared/icons/_pencil.erb +3 -0
  432. data/lib/karafka/web/ui/views/shared/icons/_pencil_square.erb +3 -0
  433. data/lib/karafka/web/ui/views/shared/icons/_play_pause.erb +3 -0
  434. data/lib/karafka/web/ui/views/shared/icons/_plus.erb +3 -0
  435. data/lib/karafka/web/ui/views/shared/icons/_trash.erb +3 -0
  436. data/lib/karafka/web/ui/views/status/failures/_live_reporting.erb +1 -1
  437. data/lib/karafka/web/ui/views/status/failures/_partitions.erb +3 -3
  438. data/lib/karafka/web/ui/views/status/failures/_state_calculation.erb +2 -2
  439. data/lib/karafka/web/ui/views/status/info/_components.erb +6 -6
  440. data/lib/karafka/web/ui/views/status/show.erb +15 -0
  441. data/lib/karafka/web/ui/views/status/warnings/_consumers_schemas.erb +31 -0
  442. data/lib/karafka/web/ui/views/ux/_icons.erb +1 -1
  443. data/lib/karafka/web/version.rb +1 -1
  444. data/lib/karafka/web.rb +3 -0
  445. data/package-lock.json +867 -1282
  446. data/package.json +6 -7
  447. data/postcss.config.js +1 -2
  448. data/renovate.json +20 -1
  449. data/tailwind.config.js +0 -4
  450. metadata +235 -135
  451. checksums.yaml.gz.sig +0 -0
  452. data/certs/cert.pem +0 -26
  453. data/lib/karafka/web/pro/commanding/commands/quiet.rb +0 -34
  454. data/lib/karafka/web/pro/commanding/commands/stop.rb +0 -34
  455. data/lib/karafka/web/pro/commanding/commands/trace.rb +0 -41
  456. data/lib/karafka/web/pro/ui/controllers/commanding_controller.rb +0 -118
  457. data/lib/karafka/web/pro/ui/controllers/commands_controller.rb +0 -96
  458. data/lib/karafka/web/pro/ui/controllers/consumers_controller.rb +0 -138
  459. data/lib/karafka/web/pro/ui/controllers/explorer_controller.rb +0 -220
  460. data/lib/karafka/web/pro/ui/controllers/messages_controller.rb +0 -107
  461. data/lib/karafka/web/pro/ui/controllers/search_controller.rb +0 -73
  462. data/lib/karafka/web/pro/ui/controllers/topics_controller.rb +0 -130
  463. data/lib/karafka/web/pro/ui/views/commands/_breadcrumbs.erb +0 -21
  464. data/lib/karafka/web/pro/ui/views/commands/_command_details.erb +0 -1
  465. data/lib/karafka/web/pro/ui/views/commands/_empty.erb +0 -3
  466. data/lib/karafka/web/pro/ui/views/commands/show.erb +0 -33
  467. data/lib/karafka/web/pro/ui/views/consumers/_breadcrumbs.erb +0 -55
  468. data/lib/karafka/web/pro/ui/views/consumers/_tabs.erb +0 -33
  469. data/lib/karafka/web/pro/ui/views/consumers/consumer/_commands.erb +0 -72
  470. data/lib/karafka/web/pro/ui/views/consumers/consumer/_consumer_group.erb +0 -8
  471. data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_jobs.erb +0 -7
  472. data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_subscriptions.erb +0 -7
  473. data/lib/karafka/web/pro/ui/views/consumers/details.erb +0 -13
  474. data/lib/karafka/web/pro/ui/views/consumers/subscriptions.erb +0 -25
  475. data/lib/karafka/web/pro/ui/views/explorer/_no_topics.erb +0 -1
  476. data/lib/karafka/web/pro/ui/views/explorer/_topic.erb +0 -10
  477. data/lib/karafka/web/pro/ui/views/explorer/index.erb +0 -14
  478. data/lib/karafka/web/pro/ui/views/explorer/messages/_headers.erb +0 -33
  479. data/lib/karafka/web/pro/ui/views/explorer/partition/_cleaned.erb +0 -3
  480. data/lib/karafka/web/pro/ui/views/explorer/partition/_empty.erb +0 -3
  481. data/lib/karafka/web/pro/ui/views/explorer/show.erb +0 -97
  482. data/lib/karafka/web/pro/ui/views/explorer/topic/_empty.erb +0 -3
  483. data/lib/karafka/web/pro/ui/views/search/_breadcrumbs.erb +0 -1
  484. data/lib/karafka/web/pro/ui/views/search/_fix_errors.erb +0 -3
  485. data/lib/karafka/web/pro/ui/views/search/_no_results.erb +0 -3
  486. data/lib/karafka/web/pro/ui/views/search/_timeout.erb +0 -3
  487. data/lib/karafka/web/pro/ui/views/search/index.erb +0 -29
  488. data/lib/karafka/web/pro/ui/views/topics/_breadcrumbs.erb +0 -45
  489. data/lib/karafka/web/pro/ui/views/topics/_partition_offsets.erb +0 -10
  490. data/lib/karafka/web/pro/ui/views/topics/_topic.erb +0 -9
  491. data/lib/karafka/web/pro/ui/views/topics/distribution/_empty_partitions.erb +0 -1
  492. data/lib/karafka/web/pro/ui/views/topics/distribution/_partition.erb +0 -10
  493. data/lib/karafka/web/pro/ui/views/topics/index.erb +0 -14
  494. data/lib/karafka/web/ui/lib/ttl_cache.rb +0 -82
  495. data.tar.gz.sig +0 -0
  496. metadata.gz.sig +0 -0
@@ -0,0 +1,80 @@
1
+ <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
+ <%# See LICENSE for details. %>
3
+
4
+ <div class="card bg-base-100 mt-4">
5
+ <div class="card-body border-error">
6
+ <form class="space-y-4 w-full" method="post" action="<%= topics_path %>" data-turbo="false">
7
+ <%== csrf_tag(topics_path) %>
8
+
9
+ <div class="flex items-center w-full mb-8">
10
+ <label class="w-1/4 text-gray-700">Topic Name:</label>
11
+ <div class="w-3/4">
12
+ <input
13
+ type="text"
14
+ name="topic_name"
15
+ class="block input input-bordered w-full"
16
+ placeholder="Enter topic name"
17
+ pattern="[A-Za-z0-9\-_.]+"
18
+ minlength="1"
19
+ maxlength="249"
20
+ value="<%= params.fetch(:topic_name, '') %>"
21
+ required
22
+ />
23
+ <div class="text-sm text-gray-500 mt-1">
24
+ Only alphanumeric characters, dots, underscores, and hyphens are allowed
25
+ </div>
26
+ </div>
27
+ </div>
28
+
29
+ <div class="flex items-center w-full mb-8">
30
+ <label class="w-1/4 text-gray-700">Number of Partitions:</label>
31
+ <div class="w-3/4">
32
+ <input
33
+ type="number"
34
+ min="1"
35
+ max="10000"
36
+ name="partitions_count"
37
+ class="block input input-bordered w-full"
38
+ placeholder="Enter number of partitions"
39
+ value="<%= params.fetch(:partitions_count, 5) %>"
40
+ required
41
+ />
42
+ <div class="text-sm text-gray-500 mt-1">
43
+ Minimum 1 partition, cannot be decreased after creation
44
+ </div>
45
+ </div>
46
+ </div>
47
+
48
+ <div class="flex items-center w-full">
49
+ <label class="w-1/4 text-gray-700">Replication Factor:</label>
50
+ <div class="w-3/4">
51
+ <input
52
+ type="number"
53
+ min="1"
54
+ max="100"
55
+ name="replication_factor"
56
+ class="block input input-bordered w-full"
57
+ placeholder="Enter replication factor"
58
+ value="<%= params.fetch(:replication_factor, 1) %>"
59
+ required
60
+ />
61
+ <div class="text-sm text-gray-500 mt-1">
62
+ Number of replicas for each partition (minimum 1, recommended 3 for production)
63
+ </div>
64
+ </div>
65
+ </div>
66
+
67
+ <div class="fieldset text-center mt-6">
68
+ <div class="flex gap-4 justify-end">
69
+ <a href="<%= topics_path %>" class="btn btn-ghost">
70
+ Cancel
71
+ </a>
72
+ <button type="submit" class="btn btn-primary gap-2 btn-lockable">
73
+ <%== icon(:plus) %>
74
+ Create Topic
75
+ </button>
76
+ </div>
77
+ </div>
78
+ </form>
79
+ </div>
80
+ </div>
@@ -1,28 +1,31 @@
1
+ <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
+ <%# See LICENSE for details. %>
3
+
1
4
  <div class="tab-container-wrapper">
2
5
  <div class="tab-container">
3
6
  <a
4
- href="<%= root_path('topics', @topic.topic_name, 'config') %>"
7
+ href="<%= topics_path(@topic.topic_name, 'config') %>"
5
8
  class="custom-tab <%= nav_class(end_with: 'config') %>"
6
9
  >
7
10
  Configuration
8
11
  </a>
9
12
 
10
13
  <a
11
- href="<%= root_path('topics', @topic.topic_name, 'replication') %>"
14
+ href="<%= topics_path(@topic.topic_name, 'replication') %>"
12
15
  class="custom-tab <%= nav_class(end_with: 'replication') %>"
13
16
  >
14
17
  Replication
15
18
  </a>
16
19
 
17
20
  <a
18
- href="<%= root_path('topics', @topic.topic_name, 'distribution') %>"
21
+ href="<%= topics_path(@topic.topic_name, 'distribution') %>"
19
22
  class="custom-tab <%= nav_class(end_with: 'distribution') %>"
20
23
  >
21
24
  Distribution
22
25
  </a>
23
26
 
24
27
  <a
25
- href="<%= root_path('topics', @topic.topic_name, 'offsets') %>"
28
+ href="<%= topics_path(@topic.topic_name, 'offsets') %>"
26
29
  class="custom-tab <%= nav_class(end_with: 'offsets') %>"
27
30
  >
28
31
  Offsets
@@ -0,0 +1,12 @@
1
+ <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
+ <%# See LICENSE for details. %>
3
+
4
+ <div class="topic-tile">
5
+ <div class="topic-tile-body">
6
+ <p class="topic-tile-text">
7
+ <a href="<%= topics_path(topic.topic_name, 'config') %>" class="topic-tile-link">
8
+ <%= topic.topic_name %> / <%= topic.partition_count %>
9
+ </a>
10
+ </p>
11
+ </div>
12
+ </div>
@@ -0,0 +1,10 @@
1
+ <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
+ <%# See LICENSE for details. %>
3
+
4
+ <% view_title "Topic #{@topic.topic_name} Removal Confirmation" %>
5
+
6
+ <div class="space-y-4">
7
+ <%== partial 'topics/topics/delete_warning' %>
8
+ <%== partial 'topics/topics/delete_hints' %>
9
+ <%== partial 'topics/topics/delete_form' %>
10
+ </div>
@@ -0,0 +1,19 @@
1
+ <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
+ <%# See LICENSE for details. %>
3
+
4
+ <% view_title 'Topics' %>
5
+
6
+ <%== partial 'topics/topics/create_button' %>
7
+
8
+ <% if @topics.empty? %>
9
+ <%== partial 'explorer/explorer/no_topics' %>
10
+ <% else %>
11
+ <div class="topic-tiles">
12
+ <%==
13
+ each_partial(
14
+ @topics,
15
+ 'topics/topics/topic'
16
+ )
17
+ %>
18
+ </div>
19
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
+ <%# See LICENSE for details. %>
3
+
4
+ <% view_title "Creating New Topic" %>
5
+
6
+ <% if @form_error %>
7
+ <%== partial 'shared/rdkafka_form_error_alert_box' %>
8
+ <% else %>
9
+ <%== partial 'topics/topics/create_hints' %>
10
+ <% end %>
11
+
12
+ <%== partial 'topics/topics/new_form' %>
@@ -29,14 +29,14 @@ module Karafka
29
29
 
30
30
  raise ::Karafka::Web::Errors::Processing::IncompatibleSchemaError
31
31
  # Older reports mean someone is in the middle of upgrade. Schema change related
32
- # upgrades always should happen without a rolling-upgrade, hence we can reject those
33
- # requests without significant or any impact on data quality but without having to
34
- # worry about backwards compatibility. Errors are tracked independently, so it should
35
- # not be a problem.
36
- #
37
- # In case user wants to do a rolling upgrade, the user docs state that this can happen
38
- # and it is something user should be aware
32
+ # upgrades always should happen without a rolling-upgrade. For such, since we cannot
33
+ # reason about their statistics structure, we only track state, so we can provide
34
+ # basic upgrade reporting details in the status page. All other data is rejected and
35
+ # since in most cases this is intermediate due to rolling upgrades, this should not
36
+ # significantly impact the state tracking and processing.
39
37
  when :older
38
+ @state_aggregator.add_state(message.payload, message.offset)
39
+
40
40
  next
41
41
  else
42
42
  raise ::Karafka::Errors::UnsupportedCaseError
@@ -36,7 +36,7 @@ module Karafka
36
36
  def add(report, offset)
37
37
  super(report)
38
38
  increment_total_counters(report)
39
- update_process_state(report, offset)
39
+ add_state(report, offset)
40
40
  # We always evict after counters updates because we want to use expired (stopped)
41
41
  # data for counters as it was valid previously. This can happen only when web consumer
42
42
  # had a lag and is catching up.
@@ -46,6 +46,19 @@ module Karafka
46
46
  refresh_current_stats
47
47
  end
48
48
 
49
+ # Registers or updates the given process state based on the report
50
+ #
51
+ # @param report [Hash]
52
+ # @param offset [Integer]
53
+ def add_state(report, offset)
54
+ process_id = report[:process][:id]
55
+
56
+ state[:processes][process_id] = {
57
+ dispatched_at: report[:dispatched_at],
58
+ offset: offset
59
+ }
60
+ end
61
+
49
62
  # @return [Array<Hash, Float>] aggregated current stats value and time from which this
50
63
  # aggregation comes from
51
64
  #
@@ -84,19 +97,6 @@ module Karafka
84
97
  end
85
98
  end
86
99
 
87
- # Registers or updates the given process state based on the report
88
- #
89
- # @param report [Hash]
90
- # @param offset [Integer]
91
- def update_process_state(report, offset)
92
- process_id = report[:process][:id]
93
-
94
- state[:processes][process_id] = {
95
- dispatched_at: report[:dispatched_at],
96
- offset: offset
97
- }
98
- end
99
-
100
100
  # Evicts expired processes from the current state
101
101
  # We consider processes dead if they do not report often enough
102
102
  # @note We do not evict based on states (stopped), because we want to report the
@@ -12,7 +12,7 @@ module Karafka
12
12
  # @return [Hash] latest (current) aggregated metrics state
13
13
  def current!
14
14
  metrics_message = ::Karafka::Admin.read_topic(
15
- Karafka::Web.config.topics.consumers.metrics,
15
+ Karafka::Web.config.topics.consumers.metrics.name,
16
16
  0,
17
17
  # We need to take more in case there would be transactions running.
18
18
  # In theory we could take two but this compensates for any involuntary
@@ -12,7 +12,7 @@ module Karafka
12
12
  # @return [Hash] last (current) aggregated processes state
13
13
  def current!
14
14
  state_message = ::Karafka::Admin.read_topic(
15
- Karafka::Web.config.topics.consumers.states,
15
+ Karafka::Web.config.topics.consumers.states.name,
16
16
  0,
17
17
  # We need to take more in case there would be transactions running.
18
18
  # In theory we could take two but this compensates for any involuntary
@@ -36,17 +36,17 @@ module Karafka
36
36
  def prepare_data(consumers_state, consumers_metrics)
37
37
  [
38
38
  {
39
- topic: Karafka::Web.config.topics.consumers.states,
39
+ topic: Karafka::Web.config.topics.consumers.states.name,
40
40
  payload: Zlib::Deflate.deflate(consumers_state.to_json),
41
41
  # This will ensure that the consumer states are compacted
42
- key: Karafka::Web.config.topics.consumers.states,
42
+ key: Karafka::Web.config.topics.consumers.states.name,
43
43
  partition: 0,
44
44
  headers: { 'zlib' => 'true' }
45
45
  },
46
46
  {
47
- topic: Karafka::Web.config.topics.consumers.metrics,
47
+ topic: Karafka::Web.config.topics.consumers.metrics.name,
48
48
  payload: Zlib::Deflate.deflate(consumers_metrics.to_json),
49
- key: Karafka::Web.config.topics.consumers.metrics,
49
+ key: Karafka::Web.config.topics.consumers.metrics.name,
50
50
  partition: 0,
51
51
  headers: { 'zlib' => 'true' }
52
52
  }
@@ -28,6 +28,7 @@ module Karafka
28
28
  required(:ls_offset) { |val| val.is_a?(Integer) }
29
29
  required(:ls_offset_d) { |val| val.is_a?(Integer) }
30
30
  required(:ls_offset_fd) { |val| val.is_a?(Integer) && val >= 0 }
31
+ required(:transactional) { |val| [true, false].include?(val) }
31
32
  end
32
33
  end
33
34
  end
@@ -85,6 +85,7 @@ module Karafka
85
85
  # with -1001, which is "N/A" offset position for all the offsets here
86
86
  committed_offset: (consumer.coordinator.seek_offset || -1_000) - 1,
87
87
  consumer: consumer.class.to_s,
88
+ trace_id: Karafka.pro? ? consumer.errors_tracker.trace_id : nil,
88
89
  tags: consumer.tags
89
90
  }
90
91
  end
@@ -8,10 +8,10 @@ module Karafka
8
8
  # Tracks pausing and un-pausing of topics partitions for both user requested and
9
9
  # automatic events.
10
10
  class Pausing < Base
11
- # Indicate pause
11
+ # Tracks the pause start
12
12
  #
13
13
  # @param event [Karafka::Core::Monitoring::Event]
14
- def on_consumer_consuming_pause(event)
14
+ def on_client_pause(event)
15
15
  track do |sampler|
16
16
  sampler.pauses[pause_id(event)] = {
17
17
  timeout: event[:timeout],
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Web
5
+ module Tracking
6
+ module Consumers
7
+ module Listeners
8
+ # Tracks data related to transactions
9
+ # seek offsets are needed because when consumer offsets are committed in transactions,
10
+ # librdkafka does not publish the lags in a regular way (they are set to -1) and we need
11
+ # to compute them via enrichment of information.
12
+ class Transactions < Base
13
+ # Tracking of things needed to support transactional consumers post successful
14
+ # transaction.
15
+ #
16
+ # @param event [Karafka::Core::Monitoring::Event]
17
+ def on_consumer_consuming_transaction(event)
18
+ consumer = event[:caller]
19
+ sg_id = consumer.topic.subscription_group.id
20
+ topic_name = consumer.topic.name
21
+ # We store it as a string because librdkafka also does that and its easier to align
22
+ # without casting it later
23
+ partition_id = consumer.partition
24
+
25
+ track do |sampler|
26
+ break unless sampler.subscription_groups.key?(sg_id)
27
+
28
+ seek_offset = consumer.coordinator.seek_offset
29
+
30
+ break if seek_offset.nil?
31
+
32
+ topics_scope = sampler.subscription_groups[sg_id][:topics]
33
+ p_scope = topics_scope[topic_name][partition_id]
34
+
35
+ p_scope[:transactional] = true
36
+ p_scope[:seek_offset] = seek_offset
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -49,6 +49,10 @@ module Karafka
49
49
  # block during this time
50
50
  sampler.sample
51
51
 
52
+ messages = nil
53
+
54
+ # We aggregate all the data behind a mutex to make sure, we do not corrupt the already
55
+ # aggregated data in a different thread
52
56
  MUTEX.synchronize do
53
57
  return unless report?(forced)
54
58
 
@@ -63,7 +67,7 @@ module Karafka
63
67
  # Report consumers statuses
64
68
  messages = [
65
69
  {
66
- topic: ::Karafka::Web.config.topics.consumers.reports,
70
+ topic: ::Karafka::Web.config.topics.consumers.reports.name,
67
71
  payload: Zlib::Deflate.deflate(report.to_json),
68
72
  key: process_id,
69
73
  partition: 0,
@@ -76,7 +80,7 @@ module Karafka
76
80
  @error_contract.validate!(error)
77
81
 
78
82
  {
79
- topic: Karafka::Web.config.topics.errors,
83
+ topic: Karafka::Web.config.topics.errors.name,
80
84
  payload: Zlib::Deflate.deflate(error.to_json),
81
85
  # Always dispatch errors from the same process to the same partition
82
86
  key: process_id,
@@ -84,12 +88,12 @@ module Karafka
84
88
  }
85
89
  end
86
90
 
87
- produce(messages)
88
-
89
91
  # Clear the sampler so it tracks new state changes without previous once impacting
90
92
  # the data
91
93
  sampler.clear
92
94
  end
95
+
96
+ produce(messages)
93
97
  end
94
98
 
95
99
  # Reports bypassing frequency check. This can be used to report when state changes in the
@@ -15,7 +15,7 @@ module Karafka
15
15
  # Current schema version
16
16
  # This is used for detecting incompatible changes and not using outdated data during
17
17
  # upgrades
18
- SCHEMA_VERSION = '1.4.0'
18
+ SCHEMA_VERSION = '1.4.1'
19
19
 
20
20
  # Counters that count events occurrences during the given window
21
21
  COUNTERS_BASE = {
@@ -51,7 +51,17 @@ module Karafka
51
51
  @subscription_groups = Hash.new do |h, sg_id|
52
52
  h[sg_id] = {
53
53
  id: sg_id,
54
- polled_at: monotonic_now
54
+ polled_at: monotonic_now,
55
+ topics: Hash.new do |h1, topic|
56
+ h1[topic] = Hash.new do |h2, partition|
57
+ # We track those details in case we need to fill statistical gaps for
58
+ # transactional consumers
59
+ h2[partition] = {
60
+ seek_offset: -1,
61
+ transactional: false
62
+ }
63
+ end
64
+ end
55
65
  }
56
66
  end
57
67
 
@@ -223,11 +233,9 @@ module Karafka
223
233
  def memory_size
224
234
  @memory_size ||= case RUBY_PLATFORM
225
235
  when /linux/
226
- @shell
227
- .call('grep MemTotal /proc/meminfo')
228
- .match(/(\d+)/)
229
- .to_s
230
- .to_i
236
+ mem_info = File.read('/proc/meminfo')
237
+ mem_total_line = mem_info.match(/MemTotal:\s*(?<total>\d+)/)
238
+ mem_total_line['total'].to_i
231
239
  when /darwin|bsd/
232
240
  @shell
233
241
  .call('sysctl -a')
@@ -245,7 +253,13 @@ module Karafka
245
253
  # @return [Array<Float>] load averages for last 1, 5 and 15 minutes
246
254
  def cpu_usage
247
255
  case RUBY_PLATFORM
248
- when /darwin|bsd|linux/
256
+ when /linux/
257
+ File
258
+ .read('/proc/loadavg')
259
+ .split(' ')
260
+ .first(3)
261
+ .map(&:to_f)
262
+ when /darwin|bsd/
249
263
  @shell
250
264
  .call('w | head -1')
251
265
  .strip
@@ -280,10 +294,21 @@ module Karafka
280
294
  def memory_threads_ps
281
295
  @memory_threads_ps = case RUBY_PLATFORM
282
296
  when /linux/
283
- @shell
284
- .call('ps -A -o rss=,thcount=,pid=')
285
- .split("\n")
286
- .map { |row| row.strip.split(' ').map(&:to_i) }
297
+ page_size = Karafka::Web::Tracking::Helpers::Sysconf.page_size
298
+ status_file = "/proc/#{::Process.pid}/status"
299
+
300
+ pid = status_file.match(%r{/proc/(\d+)/status})[1]
301
+
302
+ # Extract thread count from /proc/<pid>/status
303
+ thcount = File.read(status_file)[/^Threads:\s+(\d+)/, 1].to_i
304
+
305
+ # Extract RSS from /proc/<pid>/statm (second field)
306
+ statm_file = "/proc/#{pid}/statm"
307
+ rss_pages = File.read(statm_file).split[1].to_i rescue 0
308
+ # page size is retrieved from Sysconf
309
+ rss_kb = (rss_pages * page_size) / 1024
310
+
311
+ [[rss_kb, thcount, pid.to_i]]
287
312
  # thcount is not available on macos ps
288
313
  # because of that we inject 0 as threads count similar to how
289
314
  # we do on windows
@@ -308,9 +333,51 @@ module Karafka
308
333
  # This should be always available, since the subscription group polled at time
309
334
  # is first initialized before we start polling, there should be no case where
310
335
  # we have statistics about a given subscription group but we do not have the
311
- # last polling time
312
- polled_at = subscription_groups.fetch(sg_id).fetch(:polled_at)
336
+ # sg reference
337
+ sg_tracking = subscription_groups.fetch(sg_id)
338
+
339
+ polled_at = sg_tracking.fetch(:polled_at)
313
340
  sg_details[:state][:poll_age] = (monotonic_now - polled_at).round(2)
341
+
342
+ sg_details[:topics].each do |topic_name, topic_details|
343
+ topic_details[:partitions].each do |partition_id, partition_details|
344
+ # Always assume non-transactional as default. Will be overwritten by the
345
+ # consumer level details if collected
346
+ partition_details[:transactional] ||= false
347
+
348
+ # If we have stored offset or stored lag, it means it's not a transactional
349
+ # consumer at all so we can skip enrichment
350
+ next if partition_details[:lag_stored].positive?
351
+ next if partition_details[:stored_offset].positive?
352
+ next unless sg_tracking[:topics].key?(topic_name)
353
+ next unless sg_tracking[:topics][topic_name].key?(partition_id)
354
+
355
+ k_partition_details = sg_tracking[:topics][topic_name][partition_id]
356
+
357
+ # If seek offset was not yey set, nothing to enrich
358
+ next unless k_partition_details[:seek_offset].positive?
359
+
360
+ partition_details[:transactional] = k_partition_details[:transactional]
361
+
362
+ # Seek offset is always +1 from the last stored in Karafka
363
+ seek_offset = k_partition_details[:seek_offset]
364
+ stored_offset = seek_offset - 1
365
+
366
+ # In case of transactions we have to compute the lag ourselves
367
+ # -1 because ls offset (or high watermark) is last + 1
368
+ lag = partition_details[:ls_offset] - seek_offset
369
+ # This can happen if ls_offset is refreshed slower than our stored offset
370
+ # fetching from Karafka transactional layer
371
+ lag = 0 if lag.negative?
372
+
373
+ partition_details[:lag] = lag
374
+ partition_details[:lag_d] = 0
375
+ partition_details[:lag_stored] = lag
376
+ partition_details[:lag_stored_d] = 0
377
+ partition_details[:stored_offset] = stored_offset
378
+ partition_details[:committed_offset] = stored_offset
379
+ end
380
+ end
314
381
  end
315
382
  end
316
383
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Web
5
+ module Tracking
6
+ # Namespace for tracking related helpers
7
+ module Helpers
8
+ # Namespace for unix-based helper methods used to fetch OS details
9
+ module Sysconf
10
+ extend FFI::Library
11
+
12
+ case RUBY_PLATFORM
13
+ when /linux/
14
+ ffi_lib 'libc.so.6' # Standard C library on Linux
15
+ SC_PAGESIZE = 30 # _SC_PAGESIZE constant
16
+ when /darwin/
17
+ ffi_lib 'libSystem.B.dylib' # Standard C library on macOS
18
+ SC_PAGESIZE = 29 # _SC_PAGESIZE constant
19
+ end
20
+
21
+ attach_function :sysconf, [:int], :long
22
+
23
+ class << self
24
+ # @return [Integer]
25
+ def page_size
26
+ sysconf(SC_PAGESIZE)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -56,6 +56,17 @@ module Karafka
56
56
  super
57
57
  end
58
58
 
59
+ # @return [String] thread-safe inspection string
60
+ def inspect
61
+ clear
62
+ size = @accu.size
63
+
64
+ parts = ["ttl=#{@ttl}ms"]
65
+ parts << "size=#{size}"
66
+
67
+ "#<#{self.class.name}:#{format('%#x', object_id)} #{parts.join(' ')}>"
68
+ end
69
+
59
70
  private
60
71
 
61
72
  # Evicts outdated samples
@@ -10,7 +10,8 @@ module Karafka
10
10
  class Hash < Hash
11
11
  # @param ttl [Integer] milliseconds ttl
12
12
  def initialize(ttl)
13
- super() { |k, v| k[v] = Ttls::Array.new(ttl) }
13
+ @ttl = ttl
14
+ super() { |k, v| k[v] = Ttls::Array.new(@ttl) }
14
15
  end
15
16
 
16
17
  # Takes a block where we provide a hash select filtering to select keys we are
@@ -26,6 +27,11 @@ module Karafka
26
27
  select(&block)
27
28
  )
28
29
  end
30
+
31
+ # @return [String] thread-safe inspect of the ttls hash
32
+ def inspect
33
+ "#<#{self.class.name}:#{format('%#x', object_id)} size=#{size} ttl=#{@ttl}ms>"
34
+ end
29
35
  end
30
36
  end
31
37
  end
@@ -23,6 +23,8 @@ module Karafka
23
23
 
24
24
  # Dispatches the current state from sampler to appropriate topics
25
25
  def report
26
+ messages = nil
27
+
26
28
  MUTEX.synchronize do
27
29
  return unless report?
28
30
 
@@ -33,7 +35,7 @@ module Karafka
33
35
  @error_contract.validate!(error)
34
36
 
35
37
  {
36
- topic: Karafka::Web.config.topics.errors,
38
+ topic: Karafka::Web.config.topics.errors.name,
37
39
  payload: error.to_json,
38
40
  # Always dispatch errors from the same process to the same partition
39
41
  key: error[:process][:id]
@@ -42,12 +44,12 @@ module Karafka
42
44
 
43
45
  return if messages.empty?
44
46
 
45
- produce(messages)
46
-
47
47
  # Clear the sampler so it tracks new state changes without previous once impacting
48
48
  # the data
49
49
  sampler.clear
50
50
  end
51
+
52
+ produce(messages)
51
53
  end
52
54
 
53
55
  private