karafka-web 0.10.4 → 0.11.0.beta1

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 (479) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +54 -176
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +87 -43
  6. data/LICENSE +6 -2
  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/docker-compose.yml +1 -1
  11. data/gulpfile.js +0 -2
  12. data/karafka-web.gemspec +2 -2
  13. data/lib/karafka/web/config.rb +80 -9
  14. data/lib/karafka/web/contracts/config.rb +44 -5
  15. data/lib/karafka/web/errors.rb +10 -0
  16. data/lib/karafka/web/management/actions/create_initial_states.rb +6 -6
  17. data/lib/karafka/web/management/actions/create_topics.rb +30 -64
  18. data/lib/karafka/web/management/actions/delete_topics.rb +5 -5
  19. data/lib/karafka/web/management/actions/enable.rb +5 -5
  20. data/lib/karafka/web/pro/commanding/commands/base.rb +37 -13
  21. data/lib/karafka/web/pro/commanding/commands/consumers/quiet.rb +33 -0
  22. data/lib/karafka/web/pro/commanding/commands/consumers/stop.rb +32 -0
  23. data/lib/karafka/web/pro/commanding/commands/consumers/trace.rb +37 -0
  24. data/lib/karafka/web/pro/commanding/commands/partitions/pause.rb +30 -0
  25. data/lib/karafka/web/pro/commanding/commands/partitions/resume.rb +30 -0
  26. data/lib/karafka/web/pro/commanding/commands/partitions/seek.rb +30 -0
  27. data/lib/karafka/web/pro/commanding/config.rb +6 -10
  28. data/lib/karafka/web/pro/commanding/contracts/config.rb +2 -10
  29. data/lib/karafka/web/pro/commanding/dispatcher.rb +45 -24
  30. data/lib/karafka/web/pro/commanding/handlers/partitions/commands/base.rb +67 -0
  31. data/lib/karafka/web/pro/commanding/handlers/partitions/commands/pause.rb +44 -0
  32. data/lib/karafka/web/pro/commanding/handlers/partitions/commands/resume.rb +29 -0
  33. data/lib/karafka/web/pro/commanding/handlers/partitions/commands/seek.rb +86 -0
  34. data/lib/karafka/web/pro/commanding/handlers/partitions/executor.rb +56 -0
  35. data/lib/karafka/web/pro/commanding/handlers/partitions/listener.rb +55 -0
  36. data/lib/karafka/web/pro/commanding/handlers/partitions/tracker.rb +62 -0
  37. data/lib/karafka/web/pro/commanding/listener.rb +4 -12
  38. data/lib/karafka/web/pro/commanding/manager.rb +36 -24
  39. data/lib/karafka/web/pro/commanding/matcher.rb +7 -17
  40. data/lib/karafka/web/pro/commanding/request.rb +39 -0
  41. data/lib/karafka/web/pro/commanding.rb +2 -10
  42. data/lib/karafka/web/pro/loader.rb +13 -10
  43. data/lib/karafka/web/pro/ui/app.rb +31 -390
  44. data/lib/karafka/web/pro/ui/controllers/base_controller.rb +8 -10
  45. data/lib/karafka/web/pro/ui/controllers/cluster_controller.rb +2 -10
  46. data/lib/karafka/web/pro/ui/controllers/consumers/base_controller.rb +21 -0
  47. data/lib/karafka/web/pro/ui/controllers/consumers/commanding_controller.rb +148 -0
  48. data/lib/karafka/web/pro/ui/controllers/consumers/commands_controller.rb +96 -0
  49. data/lib/karafka/web/pro/ui/controllers/consumers/consumers_controller.rb +101 -0
  50. data/lib/karafka/web/pro/ui/controllers/consumers/controls_controller.rb +36 -0
  51. data/lib/karafka/web/pro/ui/controllers/consumers/jobs_controller.rb +57 -0
  52. data/lib/karafka/web/pro/ui/controllers/consumers/partitions/base_controller.rb +86 -0
  53. data/lib/karafka/web/pro/ui/controllers/consumers/partitions/offsets_controller.rb +75 -0
  54. data/lib/karafka/web/pro/ui/controllers/consumers/partitions/pauses_controller.rb +110 -0
  55. data/lib/karafka/web/pro/ui/controllers/dashboard_controller.rb +2 -10
  56. data/lib/karafka/web/pro/ui/controllers/dlq_controller.rb +2 -10
  57. data/lib/karafka/web/pro/ui/controllers/errors_controller.rb +3 -11
  58. data/lib/karafka/web/pro/ui/controllers/explorer/base_controller.rb +21 -0
  59. data/lib/karafka/web/pro/ui/controllers/explorer/explorer_controller.rb +215 -0
  60. data/lib/karafka/web/pro/ui/controllers/explorer/messages_controller.rb +145 -0
  61. data/lib/karafka/web/pro/ui/controllers/explorer/search_controller.rb +68 -0
  62. data/lib/karafka/web/pro/ui/controllers/health_controller.rb +2 -10
  63. data/lib/karafka/web/pro/ui/controllers/jobs_controller.rb +2 -10
  64. data/lib/karafka/web/pro/ui/controllers/recurring_tasks_controller.rb +12 -13
  65. data/lib/karafka/web/pro/ui/controllers/routing_controller.rb +2 -10
  66. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/base_controller.rb +2 -10
  67. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/explorer_controller.rb +8 -16
  68. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/messages_controller.rb +9 -15
  69. data/lib/karafka/web/pro/ui/controllers/scheduled_messages/schedules_controller.rb +2 -10
  70. data/lib/karafka/web/pro/ui/controllers/status_controller.rb +2 -10
  71. data/lib/karafka/web/pro/ui/controllers/support_controller.rb +2 -10
  72. data/lib/karafka/web/pro/ui/controllers/topics/base_controller.rb +21 -0
  73. data/lib/karafka/web/pro/ui/controllers/topics/configs_controller.rb +86 -0
  74. data/lib/karafka/web/pro/ui/controllers/topics/distributions_controller.rb +91 -0
  75. data/lib/karafka/web/pro/ui/controllers/topics/offsets_controller.rb +55 -0
  76. data/lib/karafka/web/pro/ui/controllers/topics/replications_controller.rb +37 -0
  77. data/lib/karafka/web/pro/ui/controllers/topics/topics_controller.rb +101 -0
  78. data/lib/karafka/web/pro/ui/controllers/ux_controller.rb +2 -10
  79. data/lib/karafka/web/pro/ui/lib/branding/config.rb +2 -10
  80. data/lib/karafka/web/pro/ui/lib/branding/contracts/config.rb +2 -10
  81. data/lib/karafka/web/pro/ui/lib/branding.rb +2 -10
  82. data/lib/karafka/web/pro/ui/lib/features.rb +53 -0
  83. data/lib/karafka/web/pro/ui/lib/patterns_detector.rb +2 -10
  84. data/lib/karafka/web/pro/ui/lib/policies/config.rb +2 -10
  85. data/lib/karafka/web/pro/ui/lib/policies/contracts/config.rb +2 -10
  86. data/lib/karafka/web/pro/ui/lib/policies/messages.rb +2 -10
  87. data/lib/karafka/web/pro/ui/lib/policies/requests.rb +2 -10
  88. data/lib/karafka/web/pro/ui/lib/policies.rb +2 -10
  89. data/lib/karafka/web/pro/ui/lib/safe_runner.rb +5 -0
  90. data/lib/karafka/web/pro/ui/lib/search/config.rb +2 -10
  91. data/lib/karafka/web/pro/ui/lib/search/contracts/config.rb +2 -10
  92. data/lib/karafka/web/pro/ui/lib/search/contracts/form.rb +2 -10
  93. data/lib/karafka/web/pro/ui/lib/search/matchers/base.rb +2 -10
  94. data/lib/karafka/web/pro/ui/lib/search/matchers/raw_header_includes.rb +10 -11
  95. data/lib/karafka/web/pro/ui/lib/search/matchers/raw_key_includes.rb +2 -10
  96. data/lib/karafka/web/pro/ui/lib/search/matchers/raw_payload_includes.rb +23 -11
  97. data/lib/karafka/web/pro/ui/lib/search/normalizer.rb +2 -10
  98. data/lib/karafka/web/pro/ui/lib/search/runner.rb +3 -11
  99. data/lib/karafka/web/pro/ui/lib/search.rb +2 -10
  100. data/lib/karafka/web/pro/ui/routes/base.rb +19 -0
  101. data/lib/karafka/web/pro/ui/routes/cluster.rb +37 -0
  102. data/lib/karafka/web/pro/ui/routes/consumers.rb +145 -0
  103. data/lib/karafka/web/pro/ui/routes/dashboard.rb +25 -0
  104. data/lib/karafka/web/pro/ui/routes/dlq.rb +24 -0
  105. data/lib/karafka/web/pro/ui/routes/errors.rb +39 -0
  106. data/lib/karafka/web/pro/ui/routes/explorer.rb +118 -0
  107. data/lib/karafka/web/pro/ui/routes/health.rb +47 -0
  108. data/lib/karafka/web/pro/ui/routes/jobs.rb +33 -0
  109. data/lib/karafka/web/pro/ui/routes/recurring_tasks.rb +59 -0
  110. data/lib/karafka/web/pro/ui/routes/routing.rb +31 -0
  111. data/lib/karafka/web/pro/ui/routes/scheduled_messages.rb +75 -0
  112. data/lib/karafka/web/pro/ui/routes/status.rb +24 -0
  113. data/lib/karafka/web/pro/ui/routes/support.rb +24 -0
  114. data/lib/karafka/web/pro/ui/routes/topics.rb +90 -0
  115. data/lib/karafka/web/pro/ui/routes/ux.rb +24 -0
  116. data/lib/karafka/web/pro/ui/views/cluster/_breadcrumbs.erb +3 -0
  117. data/lib/karafka/web/pro/ui/views/cluster/_broker.erb +3 -0
  118. data/lib/karafka/web/pro/ui/views/cluster/_config.erb +3 -0
  119. data/lib/karafka/web/pro/ui/views/cluster/_tabs.erb +3 -0
  120. data/lib/karafka/web/pro/ui/views/cluster/index.erb +4 -1
  121. data/lib/karafka/web/pro/ui/views/cluster/show.erb +3 -0
  122. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_backtrace.erb +3 -0
  123. data/lib/karafka/web/pro/ui/views/consumers/commands/_breadcrumbs.erb +24 -0
  124. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_command.erb +22 -6
  125. data/lib/karafka/web/pro/ui/views/consumers/commands/_command_details.erb +4 -0
  126. data/lib/karafka/web/pro/ui/views/consumers/commands/_empty.erb +6 -0
  127. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_incompatible_schema.erb +3 -0
  128. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_metadata.erb +4 -1
  129. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_table.erb +5 -2
  130. data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/index.erb +7 -4
  131. data/lib/karafka/web/pro/ui/views/consumers/commands/show.erb +32 -0
  132. data/lib/karafka/web/pro/ui/views/consumers/consumers/_breadcrumbs.erb +46 -0
  133. data/lib/karafka/web/pro/ui/views/consumers/consumers/_consumer.erb +59 -0
  134. data/lib/karafka/web/pro/ui/views/consumers/consumers/_consumer_performance.erb +71 -0
  135. data/lib/karafka/web/pro/ui/views/consumers/consumers/_tabs.erb +38 -0
  136. data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_commands.erb +80 -0
  137. data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_consumer_group.erb +11 -0
  138. data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_metrics.erb +3 -0
  139. data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_no_subscriptions.erb +10 -0
  140. data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_partition.erb +16 -0
  141. data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_partition_edit_options.erb +33 -0
  142. data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_stopped.erb +3 -0
  143. data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_subscription_group.erb +7 -3
  144. data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_tabs.erb +7 -4
  145. data/lib/karafka/web/pro/ui/views/consumers/consumers/details.erb +15 -0
  146. data/lib/karafka/web/pro/ui/views/consumers/{index.erb → consumers/index.erb} +6 -3
  147. data/lib/karafka/web/pro/ui/views/consumers/{performance.erb → consumers/performance.erb} +6 -3
  148. data/lib/karafka/web/pro/ui/views/consumers/consumers/subscriptions.erb +24 -0
  149. data/lib/karafka/web/pro/ui/views/consumers/controls/_breadcrumbs.erb +16 -0
  150. data/lib/karafka/web/pro/ui/views/consumers/controls/_controls.erb +107 -0
  151. data/lib/karafka/web/pro/ui/views/consumers/{controls.erb → controls/index.erb} +8 -5
  152. data/lib/karafka/web/pro/ui/views/consumers/jobs/_breadcrumbs.erb +36 -0
  153. data/lib/karafka/web/pro/ui/views/consumers/{consumer → jobs}/_job.erb +3 -0
  154. data/lib/karafka/web/pro/ui/views/consumers/{consumer → jobs}/_no_jobs.erb +3 -0
  155. data/lib/karafka/web/pro/ui/views/consumers/{pending_jobs.erb → jobs/pending.erb} +7 -8
  156. data/lib/karafka/web/pro/ui/views/consumers/{running_jobs.erb → jobs/running.erb} +7 -8
  157. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_basics.erb +77 -0
  158. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_breadcrumbs.erb +58 -0
  159. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_form.erb +109 -0
  160. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_not_running_error.erb +16 -0
  161. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_running_warning.erb +15 -0
  162. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/edit.erb +12 -0
  163. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_active_not_editable.erb +22 -0
  164. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_adjusting_warning.erb +27 -0
  165. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_breadcrumbs.erb +60 -0
  166. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_edit_form.erb +59 -0
  167. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_lrj_not_manageable.erb +24 -0
  168. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_new_form.erb +78 -0
  169. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_not_running.erb +16 -0
  170. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/edit.erb +20 -0
  171. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/new.erb +16 -0
  172. data/lib/karafka/web/pro/ui/views/dashboard/index.erb +4 -1
  173. data/lib/karafka/web/pro/ui/views/dlq/_breadcrumbs.erb +3 -0
  174. data/lib/karafka/web/pro/ui/views/dlq/_no_topics.erb +3 -0
  175. data/lib/karafka/web/pro/ui/views/dlq/_topic.erb +4 -1
  176. data/lib/karafka/web/pro/ui/views/dlq/index.erb +3 -0
  177. data/lib/karafka/web/pro/ui/views/errors/_breadcrumbs.erb +3 -0
  178. data/lib/karafka/web/pro/ui/views/errors/_error.erb +3 -0
  179. data/lib/karafka/web/pro/ui/views/errors/_partition_option.erb +3 -0
  180. data/lib/karafka/web/pro/ui/views/errors/_selector.erb +3 -0
  181. data/lib/karafka/web/pro/ui/views/errors/_table.erb +4 -1
  182. data/lib/karafka/web/pro/ui/views/errors/index.erb +6 -3
  183. data/lib/karafka/web/pro/ui/views/errors/partition.erb +5 -2
  184. data/lib/karafka/web/pro/ui/views/errors/show.erb +3 -0
  185. data/lib/karafka/web/pro/ui/views/explorer/{_breadcrumbs.erb → explorer/_breadcrumbs.erb} +7 -4
  186. data/lib/karafka/web/pro/ui/views/explorer/{_failed_deserialization.erb → explorer/_failed_deserialization.erb} +3 -0
  187. data/lib/karafka/web/pro/ui/views/explorer/{_filtered.erb → explorer/_filtered.erb} +3 -0
  188. data/lib/karafka/web/pro/ui/views/explorer/{_message.erb → explorer/_message.erb} +4 -1
  189. data/lib/karafka/web/pro/ui/views/explorer/explorer/_no_topics.erb +4 -0
  190. data/lib/karafka/web/pro/ui/views/explorer/{_partition_option.erb → explorer/_partition_option.erb} +4 -1
  191. data/lib/karafka/web/pro/ui/views/explorer/{_selector.erb → explorer/_selector.erb} +4 -1
  192. data/lib/karafka/web/pro/ui/views/explorer/explorer/_topic.erb +13 -0
  193. data/lib/karafka/web/pro/ui/views/explorer/explorer/index.erb +17 -0
  194. data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_metadata.erb +10 -7
  195. data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_payload.erb +6 -3
  196. data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_resources_utilization.erb +7 -4
  197. data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_too_big_to_be_displayed.erb +3 -0
  198. data/lib/karafka/web/pro/ui/views/explorer/{messages → explorer/messages}/_detail.erb +3 -0
  199. data/lib/karafka/web/pro/ui/views/explorer/explorer/messages/_headers.erb +51 -0
  200. data/lib/karafka/web/pro/ui/views/explorer/{messages → explorer/messages}/_key.erb +3 -0
  201. data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_cleaned.erb +6 -0
  202. data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_empty.erb +6 -0
  203. data/lib/karafka/web/pro/ui/views/explorer/{partition → explorer/partition}/_messages.erb +4 -1
  204. data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_time_selector.erb +16 -0
  205. data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_timestamp_selector.erb +33 -0
  206. data/lib/karafka/web/pro/ui/views/explorer/{partition.erb → explorer/partition.erb} +24 -17
  207. data/lib/karafka/web/pro/ui/views/explorer/{show.erb → explorer/show.erb} +17 -19
  208. data/lib/karafka/web/pro/ui/views/explorer/{topic → explorer/topic}/_actions.erb +5 -2
  209. data/lib/karafka/web/pro/ui/views/explorer/explorer/topic/_empty.erb +6 -0
  210. data/lib/karafka/web/pro/ui/views/explorer/{topic → explorer/topic}/_limited.erb +3 -0
  211. data/lib/karafka/web/pro/ui/views/explorer/{topic.erb → explorer/topic.erb} +7 -4
  212. data/lib/karafka/web/pro/ui/views/explorer/messages/_breadcrumbs.erb +32 -0
  213. data/lib/karafka/web/pro/ui/views/explorer/messages/forward.erb +143 -0
  214. data/lib/karafka/web/pro/ui/views/explorer/search/_breadcrumbs.erb +4 -0
  215. data/lib/karafka/web/pro/ui/views/explorer/search/_fix_errors.erb +6 -0
  216. data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_metadata.erb +3 -0
  217. data/lib/karafka/web/pro/ui/views/explorer/search/_no_results.erb +6 -0
  218. data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_no_search_criteria.erb +3 -0
  219. data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_search_criteria.erb +3 -0
  220. data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_search_modal.erb +5 -2
  221. data/lib/karafka/web/pro/ui/views/explorer/search/_timeout.erb +6 -0
  222. data/lib/karafka/web/pro/ui/views/explorer/search/index.erb +32 -0
  223. data/lib/karafka/web/pro/ui/views/health/_breadcrumbs.erb +3 -0
  224. data/lib/karafka/web/pro/ui/views/health/_no_data.erb +3 -0
  225. data/lib/karafka/web/pro/ui/views/health/_partition.erb +16 -1
  226. data/lib/karafka/web/pro/ui/views/health/_partition_lags.erb +3 -0
  227. data/lib/karafka/web/pro/ui/views/health/_partition_offset.erb +3 -0
  228. data/lib/karafka/web/pro/ui/views/health/_partition_times.erb +3 -0
  229. data/lib/karafka/web/pro/ui/views/health/_table_metadata.erb +4 -1
  230. data/lib/karafka/web/pro/ui/views/health/_tabs.erb +3 -0
  231. data/lib/karafka/web/pro/ui/views/health/changes.erb +4 -1
  232. data/lib/karafka/web/pro/ui/views/health/cluster_lags.erb +3 -0
  233. data/lib/karafka/web/pro/ui/views/health/lags.erb +5 -2
  234. data/lib/karafka/web/pro/ui/views/health/offsets.erb +4 -1
  235. data/lib/karafka/web/pro/ui/views/health/overview.erb +8 -3
  236. data/lib/karafka/web/pro/ui/views/jobs/_job.erb +50 -38
  237. data/lib/karafka/web/pro/ui/views/jobs/_no_jobs.erb +3 -0
  238. data/lib/karafka/web/pro/ui/views/jobs/pending.erb +4 -1
  239. data/lib/karafka/web/pro/ui/views/jobs/running.erb +4 -1
  240. data/lib/karafka/web/pro/ui/views/recurring_tasks/_actions.erb +3 -0
  241. data/lib/karafka/web/pro/ui/views/recurring_tasks/_batch_actions.erb +3 -0
  242. data/lib/karafka/web/pro/ui/views/recurring_tasks/_breadcrumbs.erb +3 -0
  243. data/lib/karafka/web/pro/ui/views/recurring_tasks/_log.erb +3 -0
  244. data/lib/karafka/web/pro/ui/views/recurring_tasks/_not_active.erb +3 -0
  245. data/lib/karafka/web/pro/ui/views/recurring_tasks/_tabs.erb +3 -0
  246. data/lib/karafka/web/pro/ui/views/recurring_tasks/_task.erb +3 -0
  247. data/lib/karafka/web/pro/ui/views/recurring_tasks/logs.erb +3 -0
  248. data/lib/karafka/web/pro/ui/views/recurring_tasks/schedule.erb +3 -0
  249. data/lib/karafka/web/pro/ui/views/routing/_consumer_group.erb +3 -0
  250. data/lib/karafka/web/pro/ui/views/routing/_detail.erb +3 -0
  251. data/lib/karafka/web/pro/ui/views/routing/_topic.erb +3 -0
  252. data/lib/karafka/web/pro/ui/views/routing/index.erb +3 -0
  253. data/lib/karafka/web/pro/ui/views/routing/show.erb +3 -0
  254. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_breadcrumbs.erb +6 -3
  255. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_key.erb +3 -0
  256. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_message.erb +4 -1
  257. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_messages.erb +3 -0
  258. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/partition.erb +23 -16
  259. data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/topic.erb +6 -3
  260. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/_breadcrumbs.erb +3 -0
  261. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/_no_groups.erb +3 -0
  262. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/index.erb +4 -1
  263. data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/show.erb +3 -0
  264. data/lib/karafka/web/pro/ui/views/shared/_navigation.erb +25 -17
  265. data/lib/karafka/web/pro/ui/views/shared/_rdkafka_form_error_alert_box.erb +16 -0
  266. data/lib/karafka/web/pro/ui/views/shared/branding/_label.erb +3 -0
  267. data/lib/karafka/web/pro/ui/views/shared/branding/_notice.erb +3 -0
  268. data/lib/karafka/web/pro/ui/views/topics/configs/_breadcrumbs.erb +34 -0
  269. data/lib/karafka/web/pro/ui/views/topics/configs/_config.erb +26 -0
  270. data/lib/karafka/web/pro/ui/views/topics/configs/_delete_button.erb +13 -0
  271. data/lib/karafka/web/pro/ui/views/topics/configs/_edit_form.erb +50 -0
  272. data/lib/karafka/web/pro/ui/views/topics/configs/_edit_plan.erb +16 -0
  273. data/lib/karafka/web/pro/ui/views/topics/configs/_edit_warning.erb +12 -0
  274. data/lib/karafka/web/pro/ui/views/topics/configs/edit.erb +16 -0
  275. data/lib/karafka/web/pro/ui/views/topics/{config.erb → configs/index.erb} +9 -3
  276. data/lib/karafka/web/pro/ui/views/topics/distributions/_add_partitions_button.erb +13 -0
  277. data/lib/karafka/web/pro/ui/views/topics/{distribution → distributions}/_badges.erb +3 -0
  278. data/lib/karafka/web/pro/ui/views/topics/distributions/_breadcrumbs.erb +28 -0
  279. data/lib/karafka/web/pro/ui/views/topics/{distribution → distributions}/_chart.erb +3 -0
  280. data/lib/karafka/web/pro/ui/views/topics/distributions/_edit_form.erb +47 -0
  281. data/lib/karafka/web/pro/ui/views/topics/distributions/_edit_hints.erb +15 -0
  282. data/lib/karafka/web/pro/ui/views/topics/distributions/_edit_warnings.erb +14 -0
  283. data/lib/karafka/web/pro/ui/views/topics/distributions/_empty_partitions.erb +4 -0
  284. data/lib/karafka/web/pro/ui/views/topics/{distribution → distributions}/_limited.erb +3 -0
  285. data/lib/karafka/web/pro/ui/views/topics/distributions/_partition.erb +13 -0
  286. data/lib/karafka/web/pro/ui/views/topics/distributions/edit.erb +16 -0
  287. data/lib/karafka/web/pro/ui/views/topics/{distribution.erb → distributions/show.erb} +11 -7
  288. data/lib/karafka/web/pro/ui/views/topics/offsets/_breadcrumbs.erb +20 -0
  289. data/lib/karafka/web/pro/ui/views/topics/offsets/_partition.erb +13 -0
  290. data/lib/karafka/web/pro/ui/views/topics/{offsets.erb → offsets/show.erb} +6 -3
  291. data/lib/karafka/web/pro/ui/views/topics/replications/_breadcrumbs.erb +20 -0
  292. data/lib/karafka/web/pro/ui/views/topics/{_partition.erb → replications/_partition.erb} +4 -1
  293. data/lib/karafka/web/pro/ui/views/topics/{replication.erb → replications/show.erb} +6 -3
  294. data/lib/karafka/web/pro/ui/views/topics/topics/_breadcrumbs.erb +32 -0
  295. data/lib/karafka/web/pro/ui/views/topics/topics/_create_button.erb +13 -0
  296. data/lib/karafka/web/pro/ui/views/topics/topics/_create_hints.erb +15 -0
  297. data/lib/karafka/web/pro/ui/views/topics/topics/_delete_form.erb +36 -0
  298. data/lib/karafka/web/pro/ui/views/topics/topics/_delete_hints.erb +15 -0
  299. data/lib/karafka/web/pro/ui/views/topics/topics/_delete_warning.erb +13 -0
  300. data/lib/karafka/web/pro/ui/views/topics/topics/_new_form.erb +80 -0
  301. data/lib/karafka/web/pro/ui/views/topics/{_tabs.erb → topics/_tabs.erb} +7 -4
  302. data/lib/karafka/web/pro/ui/views/topics/topics/_topic.erb +12 -0
  303. data/lib/karafka/web/pro/ui/views/topics/topics/edit.erb +10 -0
  304. data/lib/karafka/web/pro/ui/views/topics/topics/index.erb +19 -0
  305. data/lib/karafka/web/pro/ui/views/topics/topics/new.erb +12 -0
  306. data/lib/karafka/web/processing/consumers/metrics.rb +1 -1
  307. data/lib/karafka/web/processing/consumers/state.rb +1 -1
  308. data/lib/karafka/web/processing/publisher.rb +4 -4
  309. data/lib/karafka/web/tracking/consumers/contracts/partition.rb +1 -0
  310. data/lib/karafka/web/tracking/consumers/listeners/pausing.rb +2 -2
  311. data/lib/karafka/web/tracking/consumers/listeners/transactions.rb +44 -0
  312. data/lib/karafka/web/tracking/consumers/reporter.rb +2 -2
  313. data/lib/karafka/web/tracking/consumers/sampler.rb +81 -14
  314. data/lib/karafka/web/tracking/helpers/sysconf.rb +33 -0
  315. data/lib/karafka/web/tracking/producers/reporter.rb +1 -1
  316. data/lib/karafka/web/ui/app.rb +19 -112
  317. data/lib/karafka/web/ui/base.rb +63 -4
  318. data/lib/karafka/web/ui/controllers/base_controller.rb +43 -1
  319. data/lib/karafka/web/ui/controllers/cluster_controller.rb +5 -2
  320. data/lib/karafka/web/ui/controllers/errors_controller.rb +1 -1
  321. data/lib/karafka/web/ui/controllers/requests/execution_wrapper.rb +52 -0
  322. data/lib/karafka/web/ui/controllers/requests/hookable.rb +99 -0
  323. data/lib/karafka/web/ui/controllers/requests/params.rb +39 -1
  324. data/lib/karafka/web/ui/controllers/responses/redirect.rb +0 -5
  325. data/lib/karafka/web/ui/controllers/status_controller.rb +3 -0
  326. data/lib/karafka/web/ui/helpers/application_helper.rb +10 -1
  327. data/lib/karafka/web/ui/helpers/paths_helper.rb +54 -10
  328. data/lib/karafka/web/ui/lib/admin.rb +1 -1
  329. data/lib/karafka/web/ui/lib/cache.rb +135 -0
  330. data/lib/karafka/web/ui/models/broker.rb +1 -2
  331. data/lib/karafka/web/ui/models/cluster_info.rb +15 -21
  332. data/lib/karafka/web/ui/models/consumers_metrics.rb +1 -1
  333. data/lib/karafka/web/ui/models/consumers_state.rb +1 -1
  334. data/lib/karafka/web/ui/models/counters.rb +1 -1
  335. data/lib/karafka/web/ui/models/health.rb +9 -7
  336. data/lib/karafka/web/ui/models/process.rb +14 -0
  337. data/lib/karafka/web/ui/models/processes.rb +2 -2
  338. data/lib/karafka/web/ui/models/recurring_tasks/schedule.rb +1 -1
  339. data/lib/karafka/web/ui/models/status.rb +27 -8
  340. data/lib/karafka/web/ui/models/topic.rb +1 -2
  341. data/lib/karafka/web/ui/public/javascripts/application.js +8 -98
  342. data/lib/karafka/web/ui/public/javascripts/application.min.js +12 -4
  343. data/lib/karafka/web/ui/public/javascripts/application.min.js.br +0 -0
  344. data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
  345. data/lib/karafka/web/ui/public/javascripts/components/action_confirmation_manager.js +30 -0
  346. data/lib/karafka/web/ui/public/javascripts/components/alerts.js +39 -0
  347. data/lib/karafka/web/ui/public/javascripts/components/button_lock_manager.js +50 -0
  348. data/lib/karafka/web/ui/public/javascripts/components/live_poll.js +71 -19
  349. data/lib/karafka/web/ui/public/javascripts/components/message_republish_manager.js +50 -0
  350. data/lib/karafka/web/ui/public/javascripts/components/page_title_tracker.js +21 -0
  351. data/lib/karafka/web/ui/public/javascripts/components/partition_redirect_manager.js +21 -0
  352. data/lib/karafka/web/ui/public/javascripts/components/time_ago_manager.js +25 -0
  353. data/lib/karafka/web/ui/public/javascripts/components/timestamp_selector.js +30 -0
  354. data/lib/karafka/web/ui/public/javascripts/libs/datepicker.js +2 -2
  355. data/lib/karafka/web/ui/public/stylesheets/application.css +30 -0
  356. data/lib/karafka/web/ui/public/stylesheets/application.min.css +5122 -13
  357. data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
  358. data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
  359. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_dark.min.css.gz +0 -0
  360. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_light.min.css.gz +0 -0
  361. data/lib/karafka/web/ui/public/stylesheets/libs/tailwind.css +512 -213
  362. data/lib/karafka/web/ui/routes/assets.rb +53 -0
  363. data/lib/karafka/web/ui/routes/base.rb +36 -0
  364. data/lib/karafka/web/ui/routes/cluster.rb +28 -0
  365. data/lib/karafka/web/ui/routes/consumers.rb +35 -0
  366. data/lib/karafka/web/ui/routes/dashboard.rb +20 -0
  367. data/lib/karafka/web/ui/routes/errors.rb +26 -0
  368. data/lib/karafka/web/ui/routes/jobs.rb +28 -0
  369. data/lib/karafka/web/ui/routes/pro_only.rb +27 -0
  370. data/lib/karafka/web/ui/routes/routing.rb +26 -0
  371. data/lib/karafka/web/ui/routes/status.rb +19 -0
  372. data/lib/karafka/web/ui/routes/support.rb +19 -0
  373. data/lib/karafka/web/ui/routes/ux.rb +19 -0
  374. data/lib/karafka/web/ui/views/cluster/_partition.erb +2 -2
  375. data/lib/karafka/web/ui/views/cluster/brokers.erb +1 -1
  376. data/lib/karafka/web/ui/views/consumers/_breadcrumbs.erb +7 -1
  377. data/lib/karafka/web/ui/views/consumers/_consumer.erb +39 -30
  378. data/lib/karafka/web/ui/views/consumers/_incompatible.erb +13 -0
  379. data/lib/karafka/web/ui/views/consumers/_no_consumers.erb +2 -2
  380. data/lib/karafka/web/ui/views/consumers/_tabs.erb +4 -4
  381. data/lib/karafka/web/ui/views/consumers/index.erb +1 -1
  382. data/lib/karafka/web/ui/views/dashboard/_feature_pro.erb +1 -1
  383. data/lib/karafka/web/ui/views/dashboard/_not_enough_data.erb +2 -2
  384. data/lib/karafka/web/ui/views/dashboard/_ranges_selector.erb +1 -1
  385. data/lib/karafka/web/ui/views/dashboard/index.erb +6 -49
  386. data/lib/karafka/web/ui/views/errors/_detail.erb +3 -3
  387. data/lib/karafka/web/ui/views/errors/index.erb +1 -1
  388. data/lib/karafka/web/ui/views/jobs/_job.erb +38 -29
  389. data/lib/karafka/web/ui/views/jobs/pending.erb +1 -1
  390. data/lib/karafka/web/ui/views/jobs/running.erb +1 -1
  391. data/lib/karafka/web/ui/views/layout.erb +7 -5
  392. data/lib/karafka/web/ui/views/shared/_become_pro.erb +1 -1
  393. data/lib/karafka/web/ui/views/shared/_brand.erb +1 -1
  394. data/lib/karafka/web/ui/views/shared/_breadcrumbs.erb +1 -1
  395. data/lib/karafka/web/ui/views/shared/_content.erb +1 -1
  396. data/lib/karafka/web/ui/views/shared/_controls.erb +10 -3
  397. data/lib/karafka/web/ui/views/shared/_custom_nav.erb +9 -0
  398. data/lib/karafka/web/ui/views/shared/_flashes.erb +3 -5
  399. data/lib/karafka/web/ui/views/shared/_header.erb +25 -2
  400. data/lib/karafka/web/ui/views/shared/_navigation.erb +17 -15
  401. data/lib/karafka/web/ui/views/shared/alerts/_error.erb +8 -0
  402. data/lib/karafka/web/ui/views/shared/alerts/_info.erb +8 -0
  403. data/lib/karafka/web/ui/views/shared/alerts/_primary.erb +8 -0
  404. data/lib/karafka/web/ui/views/shared/alerts/_secondary.erb +8 -0
  405. data/lib/karafka/web/ui/views/shared/alerts/_success.erb +8 -0
  406. data/lib/karafka/web/ui/views/shared/alerts/_warning.erb +8 -0
  407. data/lib/karafka/web/ui/views/shared/exceptions/incompatible_schema.erb +34 -0
  408. data/lib/karafka/web/ui/views/shared/exceptions/not_allowed.erb +4 -0
  409. data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +5 -1
  410. data/lib/karafka/web/ui/views/shared/exceptions/pro_only.erb +4 -0
  411. data/lib/karafka/web/ui/views/shared/icons/_arrow_left.erb +3 -0
  412. data/lib/karafka/web/ui/views/shared/icons/_arrow_up_tray.erb +3 -0
  413. data/lib/karafka/web/ui/views/shared/icons/_clock.erb +3 -0
  414. data/lib/karafka/web/ui/views/shared/icons/_pencil.erb +3 -0
  415. data/lib/karafka/web/ui/views/shared/icons/_pencil_square.erb +3 -0
  416. data/lib/karafka/web/ui/views/shared/icons/_play_pause.erb +3 -0
  417. data/lib/karafka/web/ui/views/shared/icons/_plus.erb +3 -0
  418. data/lib/karafka/web/ui/views/shared/icons/_trash.erb +3 -0
  419. data/lib/karafka/web/ui/views/status/failures/_live_reporting.erb +1 -1
  420. data/lib/karafka/web/ui/views/status/failures/_partitions.erb +3 -3
  421. data/lib/karafka/web/ui/views/status/failures/_state_calculation.erb +2 -2
  422. data/lib/karafka/web/ui/views/status/info/_components.erb +6 -6
  423. data/lib/karafka/web/ui/views/status/show.erb +15 -0
  424. data/lib/karafka/web/ui/views/status/warnings/_consumers_schemas.erb +31 -0
  425. data/lib/karafka/web/ui/views/ux/_icons.erb +1 -1
  426. data/lib/karafka/web/ui/views/ux/_status_rows.erb +6 -0
  427. data/lib/karafka/web/version.rb +1 -1
  428. data/lib/karafka/web.rb +3 -0
  429. data/package-lock.json +776 -1208
  430. data/package.json +3 -4
  431. data/postcss.config.js +1 -2
  432. data/renovate.json +13 -1
  433. data/tailwind.config.js +0 -4
  434. data.tar.gz.sig +0 -0
  435. metadata +232 -108
  436. metadata.gz.sig +0 -0
  437. data/lib/karafka/web/pro/commanding/commands/quiet.rb +0 -34
  438. data/lib/karafka/web/pro/commanding/commands/stop.rb +0 -34
  439. data/lib/karafka/web/pro/commanding/commands/trace.rb +0 -41
  440. data/lib/karafka/web/pro/ui/controllers/commanding_controller.rb +0 -118
  441. data/lib/karafka/web/pro/ui/controllers/commands_controller.rb +0 -96
  442. data/lib/karafka/web/pro/ui/controllers/consumers_controller.rb +0 -138
  443. data/lib/karafka/web/pro/ui/controllers/explorer_controller.rb +0 -220
  444. data/lib/karafka/web/pro/ui/controllers/messages_controller.rb +0 -107
  445. data/lib/karafka/web/pro/ui/controllers/search_controller.rb +0 -73
  446. data/lib/karafka/web/pro/ui/controllers/topics_controller.rb +0 -130
  447. data/lib/karafka/web/pro/ui/views/commands/_breadcrumbs.erb +0 -21
  448. data/lib/karafka/web/pro/ui/views/commands/_command_details.erb +0 -1
  449. data/lib/karafka/web/pro/ui/views/commands/_empty.erb +0 -3
  450. data/lib/karafka/web/pro/ui/views/commands/show.erb +0 -33
  451. data/lib/karafka/web/pro/ui/views/consumers/_breadcrumbs.erb +0 -55
  452. data/lib/karafka/web/pro/ui/views/consumers/_consumer.erb +0 -47
  453. data/lib/karafka/web/pro/ui/views/consumers/_consumer_controls.erb +0 -95
  454. data/lib/karafka/web/pro/ui/views/consumers/_consumer_performance.erb +0 -59
  455. data/lib/karafka/web/pro/ui/views/consumers/_tabs.erb +0 -33
  456. data/lib/karafka/web/pro/ui/views/consumers/consumer/_commands.erb +0 -72
  457. data/lib/karafka/web/pro/ui/views/consumers/consumer/_consumer_group.erb +0 -8
  458. data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_subscriptions.erb +0 -7
  459. data/lib/karafka/web/pro/ui/views/consumers/details.erb +0 -13
  460. data/lib/karafka/web/pro/ui/views/consumers/subscriptions.erb +0 -25
  461. data/lib/karafka/web/pro/ui/views/explorer/_no_topics.erb +0 -1
  462. data/lib/karafka/web/pro/ui/views/explorer/_topic.erb +0 -10
  463. data/lib/karafka/web/pro/ui/views/explorer/index.erb +0 -14
  464. data/lib/karafka/web/pro/ui/views/explorer/messages/_headers.erb +0 -33
  465. data/lib/karafka/web/pro/ui/views/explorer/partition/_cleaned.erb +0 -3
  466. data/lib/karafka/web/pro/ui/views/explorer/partition/_empty.erb +0 -3
  467. data/lib/karafka/web/pro/ui/views/explorer/topic/_empty.erb +0 -3
  468. data/lib/karafka/web/pro/ui/views/search/_breadcrumbs.erb +0 -1
  469. data/lib/karafka/web/pro/ui/views/search/_fix_errors.erb +0 -3
  470. data/lib/karafka/web/pro/ui/views/search/_no_results.erb +0 -3
  471. data/lib/karafka/web/pro/ui/views/search/_timeout.erb +0 -3
  472. data/lib/karafka/web/pro/ui/views/search/index.erb +0 -29
  473. data/lib/karafka/web/pro/ui/views/topics/_breadcrumbs.erb +0 -45
  474. data/lib/karafka/web/pro/ui/views/topics/_partition_offsets.erb +0 -10
  475. data/lib/karafka/web/pro/ui/views/topics/_topic.erb +0 -9
  476. data/lib/karafka/web/pro/ui/views/topics/distribution/_empty_partitions.erb +0 -1
  477. data/lib/karafka/web/pro/ui/views/topics/distribution/_partition.erb +0 -10
  478. data/lib/karafka/web/pro/ui/views/topics/index.erb +0 -14
  479. data/lib/karafka/web/ui/lib/ttl_cache.rb +0 -82
@@ -0,0 +1,15 @@
1
+ <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
+ <%# See LICENSE for details. %>
3
+
4
+ <div class="alert">
5
+ <div class="space-y-2">
6
+ <p>Before proceeding, ensure that:</p>
7
+
8
+ <ul class="list-disc ml-6">
9
+ <li>All applications consuming from this topic have been properly shut down</li>
10
+ <li>All producers to this topic have been stopped</li>
11
+ <li>You have backed up any critical data if needed</li>
12
+ <li>You have notified relevant team members about this deletion</li>
13
+ </ul>
14
+ </div>
15
+ </div>
@@ -0,0 +1,13 @@
1
+ <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
+ <%# See LICENSE for details. %>
3
+
4
+ <% alert_box_warning('Topic Removal Warning') do %>
5
+ <div class="space-y-4">
6
+ <ul class="list-disc ml-6">
7
+ <li>All data in this topic will be permanently deleted and cannot be recovered</li>
8
+ <li>All consumers and producers for this topic will stop functioning</li>
9
+ <li>Applications dependent on this topic may experience errors or disruptions</li>
10
+ <li>Consumer group offsets associated with this topic will be lost</li>
11
+ </ul>
12
+ </div>
13
+ <% end %>
@@ -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' %>
@@ -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
@@ -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
@@ -63,7 +63,7 @@ module Karafka
63
63
  # Report consumers statuses
64
64
  messages = [
65
65
  {
66
- topic: ::Karafka::Web.config.topics.consumers.reports,
66
+ topic: ::Karafka::Web.config.topics.consumers.reports.name,
67
67
  payload: Zlib::Deflate.deflate(report.to_json),
68
68
  key: process_id,
69
69
  partition: 0,
@@ -76,7 +76,7 @@ module Karafka
76
76
  @error_contract.validate!(error)
77
77
 
78
78
  {
79
- topic: Karafka::Web.config.topics.errors,
79
+ topic: Karafka::Web.config.topics.errors.name,
80
80
  payload: Zlib::Deflate.deflate(error.to_json),
81
81
  # Always dispatch errors from the same process to the same partition
82
82
  key: process_id,
@@ -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
@@ -33,7 +33,7 @@ module Karafka
33
33
  @error_contract.validate!(error)
34
34
 
35
35
  {
36
- topic: Karafka::Web.config.topics.errors,
36
+ topic: Karafka::Web.config.topics.errors.name,
37
37
  payload: error.to_json,
38
38
  # Always dispatch errors from the same process to the same partition
39
39
  key: error[:process][:id]
@@ -11,122 +11,29 @@ module Karafka
11
11
 
12
12
  instance_exec(&CONTEXT_DETAILS)
13
13
 
14
+ # Sub-routes for given pieces of the Web UI
15
+ SUB_ROUTES = [
16
+ Routes::Assets,
17
+ Routes::Dashboard,
18
+ Routes::Consumers,
19
+ Routes::ProOnly,
20
+ Routes::Jobs,
21
+ Routes::Routing,
22
+ Routes::Cluster,
23
+ Routes::Errors,
24
+ Routes::Status,
25
+ Routes::Support,
26
+ Routes::Ux
27
+ ].freeze
28
+
29
+ private_constant :SUB_ROUTES
30
+
14
31
  route do |r|
15
32
  r.root { r.redirect root_path('dashboard') }
16
33
 
17
- # Serve current version specific assets to prevent users from fetching old assets
18
- # after upgrade
19
- r.on 'assets', Karafka::Web::VERSION do
20
- r.public
21
- end
22
-
23
- r.get 'dashboard' do
24
- @breadcrumbs = false
25
- controller = Controllers::DashboardController.new(params)
26
- controller.index
27
- end
28
-
29
- r.on 'consumers' do
30
- %w[
31
- performance
32
- controls
33
- commands
34
- ].each do |path|
35
- r.get path do |_process_id|
36
- raise Errors::Ui::ProOnlyError
37
- end
38
- end
39
-
40
- r.get String, 'subscriptions' do |_process_id|
41
- raise Errors::Ui::ProOnlyError
42
- end
43
-
44
- r.get do
45
- controller = Controllers::ConsumersController.new(params)
46
- controller.index
47
- end
48
- end
49
-
50
- %w[
51
- health
52
- explorer
53
- dlq
54
- ].each do |route|
55
- r.get route, [String, true], [String, true] do
56
- raise Errors::Ui::ProOnlyError
57
- end
58
- end
59
-
60
- r.on 'jobs' do
61
- controller = Controllers::JobsController.new(params)
62
-
63
- r.get 'running' do
64
- controller.running
65
- end
66
-
67
- r.get 'pending' do
68
- controller.pending
69
- end
70
-
71
- r.redirect root_path('jobs/running')
72
- end
73
-
74
- r.on 'routing' do
75
- controller = Controllers::RoutingController.new(params)
76
-
77
- r.get String do |topic_id|
78
- controller.show(topic_id)
79
- end
80
-
81
- r.get do
82
- controller.index
83
- end
84
- end
85
-
86
- r.on 'cluster' do
87
- controller = Controllers::ClusterController.new(params)
88
-
89
- r.get 'brokers' do
90
- controller.brokers
91
- end
92
-
93
- r.get 'replication' do
94
- controller.replication
95
- end
96
-
97
- r.redirect root_path('cluster/brokers')
98
- end
99
-
100
- r.on 'topics' do
101
- raise Errors::Ui::ProOnlyError
102
- end
103
-
104
- r.on 'errors' do
105
- controller = Controllers::ErrorsController.new(params)
106
-
107
- r.get Integer do |offset|
108
- controller.show(offset)
109
- end
110
-
111
- r.get do
112
- controller.index
113
- end
114
- end
115
-
116
- r.get 'status' do
117
- controller = Controllers::StatusController.new(params)
118
- controller.show
119
- end
120
-
121
- r.get 'ux' do
122
- controller = Controllers::UxController.new(params)
123
- controller.show
124
- end
34
+ SUB_ROUTES.each { |sub_route| sub_route.bind(self, r) }
125
35
 
126
- r.get 'support' do
127
- controller = Controllers::SupportController.new(params)
128
- controller.show
129
- end
36
+ nil
130
37
  end
131
38
  end
132
39
  end