karafka-web 0.10.4 → 0.11.0

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 (494) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +62 -176
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +88 -44
  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 +2 -2
  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/producers/reporter.rb +1 -1
  325. data/lib/karafka/web/ui/app.rb +19 -112
  326. data/lib/karafka/web/ui/base.rb +60 -3
  327. data/lib/karafka/web/ui/controllers/base_controller.rb +43 -1
  328. data/lib/karafka/web/ui/controllers/cluster_controller.rb +5 -2
  329. data/lib/karafka/web/ui/controllers/errors_controller.rb +13 -4
  330. data/lib/karafka/web/ui/controllers/requests/execution_wrapper.rb +52 -0
  331. data/lib/karafka/web/ui/controllers/requests/hookable.rb +99 -0
  332. data/lib/karafka/web/ui/controllers/requests/params.rb +39 -1
  333. data/lib/karafka/web/ui/controllers/responses/redirect.rb +0 -5
  334. data/lib/karafka/web/ui/controllers/status_controller.rb +3 -0
  335. data/lib/karafka/web/ui/helpers/application_helper.rb +10 -71
  336. data/lib/karafka/web/ui/helpers/paths_helper.rb +54 -10
  337. data/lib/karafka/web/ui/helpers/time_helper.rb +82 -0
  338. data/lib/karafka/web/ui/helpers/topics_helper.rb +156 -0
  339. data/lib/karafka/web/ui/lib/admin.rb +1 -1
  340. data/lib/karafka/web/ui/lib/cache.rb +135 -0
  341. data/lib/karafka/web/ui/models/broker.rb +1 -2
  342. data/lib/karafka/web/ui/models/cluster_info.rb +15 -21
  343. data/lib/karafka/web/ui/models/consumers_metrics.rb +1 -1
  344. data/lib/karafka/web/ui/models/consumers_state.rb +1 -1
  345. data/lib/karafka/web/ui/models/counters.rb +1 -1
  346. data/lib/karafka/web/ui/models/health.rb +9 -7
  347. data/lib/karafka/web/ui/models/message.rb +20 -2
  348. data/lib/karafka/web/ui/models/process.rb +16 -0
  349. data/lib/karafka/web/ui/models/processes.rb +29 -8
  350. data/lib/karafka/web/ui/models/recurring_tasks/schedule.rb +1 -1
  351. data/lib/karafka/web/ui/models/status.rb +28 -9
  352. data/lib/karafka/web/ui/models/topic.rb +1 -2
  353. data/lib/karafka/web/ui/public/javascripts/application.js +8 -98
  354. data/lib/karafka/web/ui/public/javascripts/application.min.js +12 -4
  355. data/lib/karafka/web/ui/public/javascripts/application.min.js.br +0 -0
  356. data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
  357. data/lib/karafka/web/ui/public/javascripts/components/action_confirmation_manager.js +30 -0
  358. data/lib/karafka/web/ui/public/javascripts/components/alerts.js +39 -0
  359. data/lib/karafka/web/ui/public/javascripts/components/button_lock_manager.js +50 -0
  360. data/lib/karafka/web/ui/public/javascripts/components/live_poll.js +71 -19
  361. data/lib/karafka/web/ui/public/javascripts/components/message_republish_manager.js +50 -0
  362. data/lib/karafka/web/ui/public/javascripts/components/page_title_tracker.js +21 -0
  363. data/lib/karafka/web/ui/public/javascripts/components/partition_redirect_manager.js +21 -0
  364. data/lib/karafka/web/ui/public/javascripts/components/time_ago_manager.js +25 -0
  365. data/lib/karafka/web/ui/public/javascripts/components/timestamp_selector.js +30 -0
  366. data/lib/karafka/web/ui/public/javascripts/libs/datepicker.js +2 -2
  367. data/lib/karafka/web/ui/public/stylesheets/application.css +30 -0
  368. data/lib/karafka/web/ui/public/stylesheets/application.min.css +5110 -13
  369. data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
  370. data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
  371. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_dark.min.css.gz +0 -0
  372. data/lib/karafka/web/ui/public/stylesheets/libs/highlight_light.min.css.gz +0 -0
  373. data/lib/karafka/web/ui/public/stylesheets/libs/tailwind.css +507 -214
  374. data/lib/karafka/web/ui/routes/assets.rb +53 -0
  375. data/lib/karafka/web/ui/routes/base.rb +36 -0
  376. data/lib/karafka/web/ui/routes/cluster.rb +28 -0
  377. data/lib/karafka/web/ui/routes/consumers.rb +35 -0
  378. data/lib/karafka/web/ui/routes/dashboard.rb +20 -0
  379. data/lib/karafka/web/ui/routes/errors.rb +30 -0
  380. data/lib/karafka/web/ui/routes/jobs.rb +28 -0
  381. data/lib/karafka/web/ui/routes/pro_only.rb +27 -0
  382. data/lib/karafka/web/ui/routes/routing.rb +26 -0
  383. data/lib/karafka/web/ui/routes/status.rb +19 -0
  384. data/lib/karafka/web/ui/routes/support.rb +19 -0
  385. data/lib/karafka/web/ui/routes/ux.rb +19 -0
  386. data/lib/karafka/web/ui/views/cluster/_partition.erb +2 -2
  387. data/lib/karafka/web/ui/views/cluster/brokers.erb +1 -1
  388. data/lib/karafka/web/ui/views/consumers/_assignments_badges.erb +2 -7
  389. data/lib/karafka/web/ui/views/consumers/_breadcrumbs.erb +7 -1
  390. data/lib/karafka/web/ui/views/consumers/_consumer.erb +1 -1
  391. data/lib/karafka/web/ui/views/consumers/_no_consumers.erb +2 -2
  392. data/lib/karafka/web/ui/views/consumers/_tabs.erb +4 -4
  393. data/lib/karafka/web/ui/views/consumers/index.erb +1 -1
  394. data/lib/karafka/web/ui/views/dashboard/_feature_pro.erb +1 -1
  395. data/lib/karafka/web/ui/views/dashboard/_not_enough_data.erb +2 -2
  396. data/lib/karafka/web/ui/views/dashboard/_ranges_selector.erb +1 -1
  397. data/lib/karafka/web/ui/views/dashboard/index.erb +6 -49
  398. data/lib/karafka/web/ui/views/errors/_breadcrumbs.erb +3 -8
  399. data/lib/karafka/web/ui/views/errors/_detail.erb +3 -3
  400. data/lib/karafka/web/ui/views/errors/_error.erb +6 -1
  401. data/lib/karafka/web/ui/views/errors/index.erb +1 -1
  402. data/lib/karafka/web/ui/views/errors/show.erb +39 -33
  403. data/lib/karafka/web/ui/views/jobs/_job.erb +2 -3
  404. data/lib/karafka/web/ui/views/jobs/pending.erb +1 -1
  405. data/lib/karafka/web/ui/views/jobs/running.erb +1 -1
  406. data/lib/karafka/web/ui/views/layout.erb +7 -5
  407. data/lib/karafka/web/ui/views/shared/_become_pro.erb +1 -1
  408. data/lib/karafka/web/ui/views/shared/_brand.erb +1 -1
  409. data/lib/karafka/web/ui/views/shared/_breadcrumbs.erb +1 -1
  410. data/lib/karafka/web/ui/views/shared/_compacted_message_info.erb +16 -0
  411. data/lib/karafka/web/ui/views/shared/_content.erb +1 -1
  412. data/lib/karafka/web/ui/views/shared/_controls.erb +10 -3
  413. data/lib/karafka/web/ui/views/shared/_custom_nav.erb +9 -0
  414. data/lib/karafka/web/ui/views/shared/_flashes.erb +3 -5
  415. data/lib/karafka/web/ui/views/shared/_header.erb +25 -2
  416. data/lib/karafka/web/ui/views/shared/_navigation.erb +17 -15
  417. data/lib/karafka/web/ui/views/shared/alerts/_error.erb +8 -0
  418. data/lib/karafka/web/ui/views/shared/alerts/_info.erb +8 -0
  419. data/lib/karafka/web/ui/views/shared/alerts/_primary.erb +8 -0
  420. data/lib/karafka/web/ui/views/shared/alerts/_secondary.erb +8 -0
  421. data/lib/karafka/web/ui/views/shared/alerts/_success.erb +8 -0
  422. data/lib/karafka/web/ui/views/shared/alerts/_warning.erb +8 -0
  423. data/lib/karafka/web/ui/views/shared/exceptions/not_allowed.erb +4 -0
  424. data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +5 -1
  425. data/lib/karafka/web/ui/views/shared/exceptions/pro_only.erb +4 -0
  426. data/lib/karafka/web/ui/views/shared/icons/_arrow_left.erb +3 -0
  427. data/lib/karafka/web/ui/views/shared/icons/_arrow_up_tray.erb +3 -0
  428. data/lib/karafka/web/ui/views/shared/icons/_clock.erb +3 -0
  429. data/lib/karafka/web/ui/views/shared/icons/_pencil.erb +3 -0
  430. data/lib/karafka/web/ui/views/shared/icons/_pencil_square.erb +3 -0
  431. data/lib/karafka/web/ui/views/shared/icons/_play_pause.erb +3 -0
  432. data/lib/karafka/web/ui/views/shared/icons/_plus.erb +3 -0
  433. data/lib/karafka/web/ui/views/shared/icons/_trash.erb +3 -0
  434. data/lib/karafka/web/ui/views/status/failures/_live_reporting.erb +1 -1
  435. data/lib/karafka/web/ui/views/status/failures/_partitions.erb +3 -3
  436. data/lib/karafka/web/ui/views/status/failures/_state_calculation.erb +2 -2
  437. data/lib/karafka/web/ui/views/status/info/_components.erb +6 -6
  438. data/lib/karafka/web/ui/views/status/show.erb +15 -0
  439. data/lib/karafka/web/ui/views/status/warnings/_consumers_schemas.erb +31 -0
  440. data/lib/karafka/web/ui/views/ux/_icons.erb +1 -1
  441. data/lib/karafka/web/version.rb +1 -1
  442. data/lib/karafka/web.rb +3 -0
  443. data/package-lock.json +868 -1255
  444. data/package.json +6 -7
  445. data/postcss.config.js +1 -2
  446. data/renovate.json +20 -1
  447. data/tailwind.config.js +0 -4
  448. metadata +235 -135
  449. checksums.yaml.gz.sig +0 -0
  450. data/certs/cert.pem +0 -26
  451. data/lib/karafka/web/pro/commanding/commands/quiet.rb +0 -34
  452. data/lib/karafka/web/pro/commanding/commands/stop.rb +0 -34
  453. data/lib/karafka/web/pro/commanding/commands/trace.rb +0 -41
  454. data/lib/karafka/web/pro/ui/controllers/commanding_controller.rb +0 -118
  455. data/lib/karafka/web/pro/ui/controllers/commands_controller.rb +0 -96
  456. data/lib/karafka/web/pro/ui/controllers/consumers_controller.rb +0 -138
  457. data/lib/karafka/web/pro/ui/controllers/explorer_controller.rb +0 -220
  458. data/lib/karafka/web/pro/ui/controllers/messages_controller.rb +0 -107
  459. data/lib/karafka/web/pro/ui/controllers/search_controller.rb +0 -73
  460. data/lib/karafka/web/pro/ui/controllers/topics_controller.rb +0 -130
  461. data/lib/karafka/web/pro/ui/views/commands/_breadcrumbs.erb +0 -21
  462. data/lib/karafka/web/pro/ui/views/commands/_command_details.erb +0 -1
  463. data/lib/karafka/web/pro/ui/views/commands/_empty.erb +0 -3
  464. data/lib/karafka/web/pro/ui/views/commands/show.erb +0 -33
  465. data/lib/karafka/web/pro/ui/views/consumers/_breadcrumbs.erb +0 -55
  466. data/lib/karafka/web/pro/ui/views/consumers/_tabs.erb +0 -33
  467. data/lib/karafka/web/pro/ui/views/consumers/consumer/_commands.erb +0 -72
  468. data/lib/karafka/web/pro/ui/views/consumers/consumer/_consumer_group.erb +0 -8
  469. data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_jobs.erb +0 -7
  470. data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_subscriptions.erb +0 -7
  471. data/lib/karafka/web/pro/ui/views/consumers/details.erb +0 -13
  472. data/lib/karafka/web/pro/ui/views/consumers/subscriptions.erb +0 -25
  473. data/lib/karafka/web/pro/ui/views/explorer/_no_topics.erb +0 -1
  474. data/lib/karafka/web/pro/ui/views/explorer/_topic.erb +0 -10
  475. data/lib/karafka/web/pro/ui/views/explorer/index.erb +0 -14
  476. data/lib/karafka/web/pro/ui/views/explorer/messages/_headers.erb +0 -33
  477. data/lib/karafka/web/pro/ui/views/explorer/partition/_cleaned.erb +0 -3
  478. data/lib/karafka/web/pro/ui/views/explorer/partition/_empty.erb +0 -3
  479. data/lib/karafka/web/pro/ui/views/explorer/show.erb +0 -97
  480. data/lib/karafka/web/pro/ui/views/explorer/topic/_empty.erb +0 -3
  481. data/lib/karafka/web/pro/ui/views/search/_breadcrumbs.erb +0 -1
  482. data/lib/karafka/web/pro/ui/views/search/_fix_errors.erb +0 -3
  483. data/lib/karafka/web/pro/ui/views/search/_no_results.erb +0 -3
  484. data/lib/karafka/web/pro/ui/views/search/_timeout.erb +0 -3
  485. data/lib/karafka/web/pro/ui/views/search/index.erb +0 -29
  486. data/lib/karafka/web/pro/ui/views/topics/_breadcrumbs.erb +0 -45
  487. data/lib/karafka/web/pro/ui/views/topics/_partition_offsets.erb +0 -10
  488. data/lib/karafka/web/pro/ui/views/topics/_topic.erb +0 -9
  489. data/lib/karafka/web/pro/ui/views/topics/distribution/_empty_partitions.erb +0 -1
  490. data/lib/karafka/web/pro/ui/views/topics/distribution/_partition.erb +0 -10
  491. data/lib/karafka/web/pro/ui/views/topics/index.erb +0 -14
  492. data/lib/karafka/web/ui/lib/ttl_cache.rb +0 -82
  493. data.tar.gz.sig +0 -0
  494. 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
@@ -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]