karafka-web 0.8.2 → 0.9.0.rc2

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 (271) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/ci.yml +5 -16
  4. data/CHANGELOG.md +40 -0
  5. data/Gemfile.lock +21 -23
  6. data/LICENSE +3 -3
  7. data/bin/rspecs +1 -1
  8. data/config/locales/pro_errors.yml +11 -0
  9. data/config/locales/slogans.yml +62 -0
  10. data/docker-compose.yml +1 -1
  11. data/karafka-web.gemspec +4 -2
  12. data/lib/karafka/web/app.rb +1 -1
  13. data/lib/karafka/web/config.rb +23 -3
  14. data/lib/karafka/web/contracts/config.rb +7 -1
  15. data/lib/karafka/web/management/actions/create_topics.rb +21 -0
  16. data/lib/karafka/web/management/actions/delete_topics.rb +1 -0
  17. data/lib/karafka/web/management/actions/enable.rb +12 -6
  18. data/lib/karafka/web/management/migrations/0_base.rb +1 -1
  19. data/lib/karafka/web/pro/commanding/commands/base.rb +33 -0
  20. data/lib/karafka/web/pro/commanding/commands/probe.rb +41 -0
  21. data/lib/karafka/web/pro/commanding/commands/quiet.rb +31 -0
  22. data/lib/karafka/web/pro/commanding/commands/stop.rb +31 -0
  23. data/lib/karafka/web/pro/commanding/config.rb +51 -0
  24. data/lib/karafka/web/pro/commanding/contracts/config.rb +56 -0
  25. data/lib/karafka/web/pro/commanding/dispatcher.rb +93 -0
  26. data/lib/karafka/web/pro/commanding/listener.rb +97 -0
  27. data/lib/karafka/web/pro/commanding/manager.rb +98 -0
  28. data/lib/karafka/web/pro/commanding/matcher.rb +50 -0
  29. data/lib/karafka/web/pro/commanding.rb +40 -0
  30. data/lib/karafka/web/pro/loader.rb +40 -0
  31. data/lib/karafka/web/{ui/pro → pro/ui}/app.rb +103 -22
  32. data/lib/karafka/web/{ui/pro/controllers/cluster.rb → pro/ui/controllers/base_controller.rb} +4 -5
  33. data/lib/karafka/web/pro/ui/controllers/cluster_controller.rb +54 -0
  34. data/lib/karafka/web/pro/ui/controllers/commanding_controller.rb +118 -0
  35. data/lib/karafka/web/pro/ui/controllers/commands_controller.rb +96 -0
  36. data/lib/karafka/web/{ui/pro/controllers/consumers.rb → pro/ui/controllers/consumers_controller.rb} +31 -4
  37. data/lib/karafka/web/{ui/pro/controllers/dashboard.rb → pro/ui/controllers/dashboard_controller.rb} +5 -3
  38. data/lib/karafka/web/pro/ui/controllers/dlq_controller.rb +60 -0
  39. data/lib/karafka/web/{ui/pro/controllers/errors.rb → pro/ui/controllers/errors_controller.rb} +5 -7
  40. data/lib/karafka/web/{ui/pro/controllers/explorer.rb → pro/ui/controllers/explorer_controller.rb} +24 -19
  41. data/lib/karafka/web/{ui/pro/controllers/health.rb → pro/ui/controllers/health_controller.rb} +16 -3
  42. data/lib/karafka/web/{ui/pro/controllers/jobs.rb → pro/ui/controllers/jobs_controller.rb} +4 -4
  43. data/lib/karafka/web/{ui/pro/controllers/messages.rb → pro/ui/controllers/messages_controller.rb} +8 -6
  44. data/lib/karafka/web/{ui/pro/controllers/routing.rb → pro/ui/controllers/routing_controller.rb} +6 -22
  45. data/lib/karafka/web/{ui/pro/controllers/status.rb → pro/ui/controllers/status_controller.rb} +3 -3
  46. data/lib/karafka/web/pro/ui/controllers/topics_controller.rb +99 -0
  47. data/lib/karafka/web/pro/ui/lib/patterns_detector.rb +50 -0
  48. data/lib/karafka/web/pro/ui/views/cluster/_breadcrumbs.erb +29 -0
  49. data/lib/karafka/web/pro/ui/views/cluster/_broker.erb +13 -0
  50. data/lib/karafka/web/pro/ui/views/cluster/_config.erb +13 -0
  51. data/lib/karafka/web/pro/ui/views/cluster/_tabs.erb +27 -0
  52. data/lib/karafka/web/pro/ui/views/cluster/brokers.erb +27 -0
  53. data/lib/karafka/web/pro/ui/views/cluster/index.erb +27 -0
  54. data/lib/karafka/web/pro/ui/views/cluster/show.erb +27 -0
  55. data/lib/karafka/web/pro/ui/views/commands/_backtrace.erb +20 -0
  56. data/lib/karafka/web/pro/ui/views/commands/_breadcrumbs.erb +21 -0
  57. data/lib/karafka/web/pro/ui/views/commands/_command.erb +60 -0
  58. data/lib/karafka/web/pro/ui/views/commands/_command_details.erb +11 -0
  59. data/lib/karafka/web/pro/ui/views/commands/_details.erb +26 -0
  60. data/lib/karafka/web/pro/ui/views/commands/_empty.erb +3 -0
  61. data/lib/karafka/web/pro/ui/views/commands/_incompatible_schema.erb +14 -0
  62. data/lib/karafka/web/pro/ui/views/commands/_metadata.erb +50 -0
  63. data/lib/karafka/web/pro/ui/views/commands/_table.erb +23 -0
  64. data/lib/karafka/web/pro/ui/views/commands/index.erb +17 -0
  65. data/lib/karafka/web/pro/ui/views/commands/show.erb +38 -0
  66. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/_breadcrumbs.erb +20 -4
  67. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/_consumer.erb +2 -21
  68. data/lib/karafka/web/pro/ui/views/consumers/_consumer_controls.erb +78 -0
  69. data/lib/karafka/web/pro/ui/views/consumers/_consumer_performance.erb +59 -0
  70. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/_counters.erb +7 -5
  71. data/lib/karafka/web/pro/ui/views/consumers/_tabs.erb +35 -0
  72. data/lib/karafka/web/pro/ui/views/consumers/consumer/_commands.erb +32 -0
  73. data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_jobs.erb +7 -0
  74. data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_subscriptions.erb +7 -0
  75. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_subscription_group.erb +13 -8
  76. data/lib/karafka/web/pro/ui/views/consumers/consumer/_title.erb +5 -0
  77. data/lib/karafka/web/pro/ui/views/consumers/controls.erb +67 -0
  78. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/details.erb +6 -1
  79. data/lib/karafka/web/pro/ui/views/consumers/index.erb +39 -0
  80. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/pending_jobs.erb +15 -7
  81. data/lib/karafka/web/pro/ui/views/consumers/performance.erb +52 -0
  82. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/running_jobs.erb +15 -7
  83. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/subscriptions.erb +6 -1
  84. data/lib/karafka/web/{ui/pro → pro/ui}/views/dashboard/index.erb +10 -10
  85. data/lib/karafka/web/pro/ui/views/dlq/_no_topics.erb +7 -0
  86. data/lib/karafka/web/{ui/pro → pro/ui}/views/dlq/index.erb +1 -1
  87. data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_error.erb +2 -6
  88. data/lib/karafka/web/pro/ui/views/errors/_table.erb +23 -0
  89. data/lib/karafka/web/pro/ui/views/explorer/_failed_deserialization.erb +4 -0
  90. data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_message.erb +7 -1
  91. data/lib/karafka/web/pro/ui/views/explorer/_no_topics.erb +5 -0
  92. data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/index.erb +1 -6
  93. data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_metadata.erb +33 -9
  94. data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_payload.erb +4 -4
  95. data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_payload_actions.erb +1 -1
  96. data/lib/karafka/web/pro/ui/views/explorer/messages/_headers.erb +33 -0
  97. data/lib/karafka/web/pro/ui/views/explorer/messages/_key.erb +20 -0
  98. data/lib/karafka/web/pro/ui/views/explorer/partition/_cleaned.erb +5 -0
  99. data/lib/karafka/web/pro/ui/views/explorer/partition/_empty.erb +5 -0
  100. data/lib/karafka/web/pro/ui/views/explorer/partition/_messages.erb +21 -0
  101. data/lib/karafka/web/pro/ui/views/explorer/topic/_empty.erb +5 -0
  102. data/lib/karafka/web/pro/ui/views/explorer/topic/_limited.erb +10 -0
  103. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_breadcrumbs.erb +8 -0
  104. data/lib/karafka/web/pro/ui/views/health/_no_data.erb +7 -0
  105. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition.erb +1 -1
  106. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition_lags.erb +6 -3
  107. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_tabs.erb +11 -1
  108. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/changes.erb +13 -8
  109. data/lib/karafka/web/pro/ui/views/health/cluster_lags.erb +54 -0
  110. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/lags.erb +14 -8
  111. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/offsets.erb +15 -12
  112. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/overview.erb +21 -7
  113. data/lib/karafka/web/{ui/pro → pro/ui}/views/jobs/_job.erb +1 -1
  114. data/lib/karafka/web/pro/ui/views/jobs/_no_jobs.erb +7 -0
  115. data/lib/karafka/web/{ui/pro → pro/ui}/views/jobs/pending.erb +12 -8
  116. data/lib/karafka/web/{ui/pro → pro/ui}/views/jobs/running.erb +12 -8
  117. data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/_consumer_group.erb +2 -2
  118. data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/index.erb +1 -1
  119. data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/show.erb +1 -1
  120. data/lib/karafka/web/{ui/pro → pro/ui}/views/shared/_navigation.erb +14 -0
  121. data/lib/karafka/web/pro/ui/views/topics/_breadcrumbs.erb +37 -0
  122. data/lib/karafka/web/pro/ui/views/topics/_partition.erb +16 -0
  123. data/lib/karafka/web/pro/ui/views/topics/_tabs.erb +37 -0
  124. data/lib/karafka/web/pro/ui/views/topics/_topic.erb +12 -0
  125. data/lib/karafka/web/pro/ui/views/topics/config.erb +29 -0
  126. data/lib/karafka/web/pro/ui/views/topics/distribution/_badges.erb +7 -0
  127. data/lib/karafka/web/pro/ui/views/topics/distribution/_chart.erb +2 -0
  128. data/lib/karafka/web/pro/ui/views/topics/distribution/_empty_partitions.erb +1 -0
  129. data/lib/karafka/web/pro/ui/views/topics/distribution/_limited.erb +10 -0
  130. data/lib/karafka/web/pro/ui/views/topics/distribution/_partition.erb +10 -0
  131. data/lib/karafka/web/pro/ui/views/topics/distribution.erb +47 -0
  132. data/lib/karafka/web/pro/ui/views/topics/index.erb +16 -0
  133. data/lib/karafka/web/pro/ui/views/topics/replication.erb +28 -0
  134. data/lib/karafka/web/processing/consumers/aggregators/base.rb +1 -1
  135. data/lib/karafka/web/processing/consumers/aggregators/metrics.rb +1 -1
  136. data/lib/karafka/web/processing/consumers/aggregators/state.rb +4 -4
  137. data/lib/karafka/web/tracking/consumers/contracts/report.rb +1 -1
  138. data/lib/karafka/web/tracking/consumers/listeners/booting.rb +3 -1
  139. data/lib/karafka/web/tracking/consumers/listeners/errors.rb +2 -2
  140. data/lib/karafka/web/tracking/consumers/reporter.rb +3 -3
  141. data/lib/karafka/web/tracking/consumers/sampler.rb +2 -2
  142. data/lib/karafka/web/tracking/contracts/error.rb +1 -1
  143. data/lib/karafka/web/tracking/producers/listeners/booting.rb +3 -1
  144. data/lib/karafka/web/tracking/producers/listeners/errors.rb +2 -2
  145. data/lib/karafka/web/tracking/producers/reporter.rb +1 -1
  146. data/lib/karafka/web/tracking/producers/sampler.rb +1 -1
  147. data/lib/karafka/web/tracking/sampler.rb +3 -3
  148. data/lib/karafka/web/ui/app.rb +13 -9
  149. data/lib/karafka/web/ui/base.rb +1 -0
  150. data/lib/karafka/web/ui/controllers/{base.rb → base_controller.rb} +15 -2
  151. data/lib/karafka/web/ui/controllers/{become_pro.rb → become_pro_controller.rb} +1 -1
  152. data/lib/karafka/web/ui/controllers/{cluster.rb → cluster_controller.rb} +4 -4
  153. data/lib/karafka/web/ui/controllers/{consumers.rb → consumers_controller.rb} +3 -3
  154. data/lib/karafka/web/ui/controllers/{dashboard.rb → dashboard_controller.rb} +1 -1
  155. data/lib/karafka/web/ui/controllers/{errors.rb → errors_controller.rb} +2 -2
  156. data/lib/karafka/web/ui/controllers/{jobs.rb → jobs_controller.rb} +5 -5
  157. data/lib/karafka/web/ui/controllers/{routing.rb → routing_controller.rb} +2 -2
  158. data/lib/karafka/web/ui/controllers/{status.rb → status_controller.rb} +1 -1
  159. data/lib/karafka/web/ui/helpers/alerts_helper.rb +23 -0
  160. data/lib/karafka/web/ui/helpers/application_helper.rb +53 -1
  161. data/lib/karafka/web/ui/lib/paginations/offset_based.rb +3 -4
  162. data/lib/karafka/web/ui/lib/safe_runner.rb +59 -0
  163. data/lib/karafka/web/ui/models/broker.rb +66 -0
  164. data/lib/karafka/web/ui/models/health.rb +28 -2
  165. data/lib/karafka/web/ui/models/message.rb +9 -3
  166. data/lib/karafka/web/ui/models/process.rb +10 -5
  167. data/lib/karafka/web/ui/models/processes.rb +2 -2
  168. data/lib/karafka/web/ui/models/status.rb +1 -1
  169. data/lib/karafka/web/ui/models/topic.rb +78 -0
  170. data/lib/karafka/web/ui/public/javascripts/application.js +18 -1
  171. data/lib/karafka/web/ui/public/javascripts/charts/data_formatting_utility.js +71 -0
  172. data/lib/karafka/web/ui/public/javascripts/charts/dataset_state_manager.js +49 -0
  173. data/lib/karafka/web/ui/public/javascripts/charts/types/bar.js +123 -0
  174. data/lib/karafka/web/ui/public/javascripts/charts/types/line.js +143 -0
  175. data/lib/karafka/web/ui/public/javascripts/charts.js +10 -325
  176. data/lib/karafka/web/ui/public/javascripts/live_poll.js +5 -5
  177. data/lib/karafka/web/ui/public/javascripts/tabs_manager.js +57 -0
  178. data/lib/karafka/web/ui/public/stylesheets/application.css +7 -6
  179. data/lib/karafka/web/ui/views/cluster/_breadcrumbs.erb +3 -3
  180. data/lib/karafka/web/ui/views/cluster/_no_partitions.erb +1 -3
  181. data/lib/karafka/web/ui/views/cluster/_tabs.erb +3 -3
  182. data/lib/karafka/web/ui/views/cluster/brokers.erb +19 -19
  183. data/lib/karafka/web/ui/views/cluster/replication.erb +37 -0
  184. data/lib/karafka/web/ui/views/consumers/_assignments_badges.erb +24 -0
  185. data/lib/karafka/web/ui/views/consumers/_consumer.erb +2 -15
  186. data/lib/karafka/web/ui/views/consumers/_counters.erb +1 -1
  187. data/lib/karafka/web/ui/views/consumers/_summary.erb +5 -5
  188. data/lib/karafka/web/ui/views/consumers/index.erb +22 -20
  189. data/lib/karafka/web/ui/views/dashboard/index.erb +9 -9
  190. data/lib/karafka/web/ui/views/errors/_cleaned.erb +1 -3
  191. data/lib/karafka/web/ui/views/errors/_error.erb +2 -6
  192. data/lib/karafka/web/ui/views/errors/_no_errors.erb +1 -3
  193. data/lib/karafka/web/ui/views/errors/index.erb +22 -20
  194. data/lib/karafka/web/ui/views/jobs/_job.erb +4 -1
  195. data/lib/karafka/web/ui/views/jobs/_no_jobs.erb +1 -3
  196. data/lib/karafka/web/ui/views/jobs/pending.erb +4 -3
  197. data/lib/karafka/web/ui/views/jobs/running.erb +4 -3
  198. data/lib/karafka/web/ui/views/routing/_consumer_group.erb +2 -2
  199. data/lib/karafka/web/ui/views/routing/index.erb +1 -1
  200. data/lib/karafka/web/ui/views/routing/show.erb +1 -1
  201. data/lib/karafka/web/ui/views/shared/_become_pro.erb +3 -3
  202. data/lib/karafka/web/ui/views/shared/_header.erb +16 -10
  203. data/lib/karafka/web/ui/views/shared/_navigation.erb +17 -3
  204. data/lib/karafka/web/ui/views/shared/_not_a_message.erb +5 -0
  205. data/lib/karafka/web/ui/views/shared/alerts/_info.erb +3 -0
  206. data/lib/karafka/web/ui/views/shared/charts/_bar.erb +7 -0
  207. data/lib/karafka/web/ui/views/shared/{_chart.erb → charts/_line.erb} +1 -1
  208. data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +1 -1
  209. data/lib/karafka/web/ui/views/status/show.erb +1 -1
  210. data/lib/karafka/web/version.rb +1 -1
  211. data/lib/karafka/web.rb +17 -1
  212. data.tar.gz.sig +0 -0
  213. metadata +189 -120
  214. metadata.gz.sig +0 -0
  215. data/lib/karafka/web/ui/pro/controllers/dlq.rb +0 -43
  216. data/lib/karafka/web/ui/pro/views/consumers/consumer/_no_jobs.erb +0 -9
  217. data/lib/karafka/web/ui/pro/views/consumers/consumer/_no_subscriptions.erb +0 -9
  218. data/lib/karafka/web/ui/pro/views/consumers/index.erb +0 -36
  219. data/lib/karafka/web/ui/pro/views/dlq/_no_topics.erb +0 -9
  220. data/lib/karafka/web/ui/pro/views/errors/_table.erb +0 -21
  221. data/lib/karafka/web/ui/pro/views/explorer/_failed_deserialization.erb +0 -4
  222. data/lib/karafka/web/ui/pro/views/explorer/_no_topics.erb +0 -7
  223. data/lib/karafka/web/ui/pro/views/explorer/messages/_headers.erb +0 -15
  224. data/lib/karafka/web/ui/pro/views/explorer/messages/_key.erb +0 -12
  225. data/lib/karafka/web/ui/pro/views/explorer/partition/_cleaned.erb +0 -3
  226. data/lib/karafka/web/ui/pro/views/explorer/partition/_empty.erb +0 -3
  227. data/lib/karafka/web/ui/pro/views/explorer/partition/_messages.erb +0 -19
  228. data/lib/karafka/web/ui/pro/views/explorer/topic/_empty.erb +0 -3
  229. data/lib/karafka/web/ui/pro/views/explorer/topic/_limited.erb +0 -4
  230. data/lib/karafka/web/ui/pro/views/health/_no_data.erb +0 -9
  231. data/lib/karafka/web/ui/pro/views/jobs/_no_jobs.erb +0 -9
  232. data/lib/karafka/web/ui/public/javascripts/tabs.js +0 -59
  233. data/lib/karafka/web/ui/views/cluster/topics.erb +0 -35
  234. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_consumer_group.erb +0 -0
  235. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_job.erb +0 -0
  236. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_metrics.erb +0 -0
  237. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_partition.erb +0 -0
  238. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_stopped.erb +0 -0
  239. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_tabs.erb +0 -0
  240. /data/lib/karafka/web/{ui/pro → pro/ui}/views/dlq/_breadcrumbs.erb +0 -0
  241. /data/lib/karafka/web/{ui/pro → pro/ui}/views/dlq/_topic.erb +0 -0
  242. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_breadcrumbs.erb +0 -0
  243. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_partition_option.erb +0 -0
  244. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_title_with_select.erb +0 -0
  245. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/index.erb +0 -0
  246. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/partition.erb +0 -0
  247. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/show.erb +0 -0
  248. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_breadcrumbs.erb +0 -0
  249. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_filtered.erb +0 -0
  250. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_partition_option.erb +0 -0
  251. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_topic.erb +0 -0
  252. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_message_actions.erb +0 -0
  253. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/messages/_detail.erb +0 -0
  254. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/partition/_details.erb +0 -0
  255. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/partition.erb +0 -0
  256. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/show.erb +0 -0
  257. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/topic/_details.erb +0 -0
  258. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/topic.erb +0 -0
  259. /data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_consumer_group_header.erb +0 -0
  260. /data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition_offset.erb +0 -0
  261. /data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition_times.erb +0 -0
  262. /data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/_detail.erb +0 -0
  263. /data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/_topic.erb +0 -0
  264. /data/lib/karafka/web/ui/public/javascripts/{bootstrap.min.js → libs/bootstrap.min.js} +0 -0
  265. /data/lib/karafka/web/ui/public/javascripts/{chart.min.js → libs/chart.min.js} +0 -0
  266. /data/lib/karafka/web/ui/public/javascripts/{datepicker.js → libs/datepicker.js} +0 -0
  267. /data/lib/karafka/web/ui/public/javascripts/{highlight.min.js → libs/highlight.min.js} +0 -0
  268. /data/lib/karafka/web/ui/public/javascripts/{timeago.min.js → libs/timeago.min.js} +0 -0
  269. /data/lib/karafka/web/ui/public/stylesheets/{bootstrap.min.css → libs/bootstrap.min.css} +0 -0
  270. /data/lib/karafka/web/ui/public/stylesheets/{datepicker.min.css → libs/datepicker.min.css} +0 -0
  271. /data/lib/karafka/web/ui/public/stylesheets/{highlight.min.css → libs/highlight.min.css} +0 -0
@@ -13,17 +13,18 @@
13
13
 
14
14
  module Karafka
15
15
  module Web
16
- module Ui
16
+ # Namespace for all the pro components of the Web UI
17
+ module Pro
17
18
  # Pro Web UI components
18
- module Pro
19
+ module Ui
19
20
  # Main Roda Web App that servers all the metrics and stats
20
- class App < Ui::Base
21
- opts[:root] = Karafka::Web.gem_root.join('lib/karafka/web/ui/pro')
21
+ class App < Web::Ui::Base
22
+ opts[:root] = Karafka::Web.gem_root.join('lib/karafka/web/pro/ui')
22
23
 
23
24
  instance_exec(&CONTEXT_DETAILS)
24
25
 
25
26
  plugin :render, escape: true, engine: 'erb', allowed_paths: [
26
- Karafka::Web.gem_root.join('lib/karafka/web/ui/pro/views'),
27
+ Karafka::Web.gem_root.join('lib/karafka/web/pro/ui/views'),
27
28
  Karafka::Web.gem_root.join('lib/karafka/web/ui/views')
28
29
  ]
29
30
 
@@ -42,12 +43,25 @@ module Karafka
42
43
 
43
44
  r.get 'dashboard' do
44
45
  @breadcrumbs = false
45
- controller = Controllers::Dashboard.new(params)
46
+ controller = Controllers::DashboardController.new(params)
46
47
  controller.index
47
48
  end
48
49
 
49
50
  r.on 'consumers' do
50
- controller = Controllers::Consumers.new(params)
51
+ controller = Controllers::ConsumersController.new(params)
52
+
53
+ r.get 'overview' do
54
+ @breadcrumbs = false
55
+ controller.index
56
+ end
57
+
58
+ r.get 'performance' do
59
+ controller.performance
60
+ end
61
+
62
+ r.get 'controls' do
63
+ controller.controls
64
+ end
51
65
 
52
66
  r.on String, 'jobs' do |process_id|
53
67
  r.get 'running' do
@@ -69,14 +83,53 @@ module Karafka
69
83
  controller.details(process_id)
70
84
  end
71
85
 
86
+ r.redirect root_path('consumers/overview')
87
+ end
88
+
89
+ r.on 'commands' do
90
+ controller = Controllers::CommandsController.new(params)
91
+
92
+ r.on Integer do |offset_id|
93
+ controller.show(offset_id)
94
+ end
95
+
96
+ r.get 'recent' do
97
+ controller.recent
98
+ end
99
+
72
100
  r.get do
73
- @breadcrumbs = false
74
101
  controller.index
75
102
  end
76
103
  end
77
104
 
105
+ r.on 'commanding' do
106
+ controller = Controllers::CommandingController.new(params)
107
+
108
+ r.post 'quiet_all' do
109
+ controller.quiet_all
110
+ end
111
+
112
+ r.post 'stop_all' do
113
+ controller.stop_all
114
+ end
115
+
116
+ r.on String do |process_id|
117
+ r.post 'probe' do
118
+ controller.probe(process_id)
119
+ end
120
+
121
+ r.post 'quiet' do
122
+ controller.quiet(process_id)
123
+ end
124
+
125
+ r.post 'stop' do
126
+ controller.stop(process_id)
127
+ end
128
+ end
129
+ end
130
+
78
131
  r.on 'jobs' do
79
- controller = Controllers::Jobs.new(params)
132
+ controller = Controllers::JobsController.new(params)
80
133
 
81
134
  r.get 'running' do
82
135
  controller.running
@@ -90,7 +143,7 @@ module Karafka
90
143
  end
91
144
 
92
145
  r.on 'routing' do
93
- controller = Controllers::Routing.new(params)
146
+ controller = Controllers::RoutingController.new(params)
94
147
 
95
148
  r.get String do |topic_id|
96
149
  controller.show(topic_id)
@@ -102,7 +155,7 @@ module Karafka
102
155
  end
103
156
 
104
157
  r.on 'explorer' do
105
- controller = Controllers::Explorer.new(params)
158
+ controller = Controllers::ExplorerController.new(params)
106
159
 
107
160
  r.get String, Integer, 'recent' do |topic_id, partition_id|
108
161
  controller.recent(topic_id, partition_id)
@@ -145,7 +198,7 @@ module Karafka
145
198
  end
146
199
 
147
200
  r.on 'messages' do
148
- controller = Controllers::Messages.new(params)
201
+ controller = Controllers::MessagesController.new(params)
149
202
 
150
203
  r.post String, Integer, Integer, 'republish' do |topic_id, partition_id, offset|
151
204
  controller.republish(topic_id, partition_id, offset)
@@ -161,12 +214,16 @@ module Karafka
161
214
  end
162
215
 
163
216
  r.on 'health' do
164
- controller = Controllers::Health.new(params)
217
+ controller = Controllers::HealthController.new(params)
165
218
 
166
219
  r.get 'lags' do
167
220
  controller.lags
168
221
  end
169
222
 
223
+ r.get 'cluster_lags' do
224
+ controller.cluster_lags
225
+ end
226
+
170
227
  r.get 'offsets' do
171
228
  controller.offsets
172
229
  end
@@ -185,21 +242,45 @@ module Karafka
185
242
  end
186
243
 
187
244
  r.on 'cluster' do
188
- controller = Controllers::Cluster.new(params)
245
+ controller = Controllers::ClusterController.new(params)
189
246
 
190
- r.get 'brokers' do
191
- controller.brokers
247
+ r.get 'replication' do
248
+ # We use the non-pro controller here because this action is the same
249
+ controller = Ui::Controllers::ClusterController.new(params)
250
+ controller.replication
192
251
  end
193
252
 
194
- r.get 'topics' do
195
- controller.topics
253
+ r.get String do |broker_id|
254
+ controller.show(broker_id)
196
255
  end
197
256
 
198
- r.redirect root_path('cluster/brokers')
257
+ r.get do
258
+ controller.index
259
+ end
260
+ end
261
+
262
+ r.on 'topics' do
263
+ controller = Controllers::TopicsController.new(params)
264
+
265
+ r.get 'config', String do |topic_name|
266
+ controller.config(topic_name)
267
+ end
268
+
269
+ r.get 'replication', String do |topic_name|
270
+ controller.replication(topic_name)
271
+ end
272
+
273
+ r.get 'distribution', String do |topic_name|
274
+ controller.distribution(topic_name)
275
+ end
276
+
277
+ r.get do
278
+ controller.index
279
+ end
199
280
  end
200
281
 
201
282
  r.on 'errors' do
202
- controller = Controllers::Errors.new(params)
283
+ controller = Controllers::ErrorsController.new(params)
203
284
 
204
285
  r.get Integer, Integer do |partition_id, offset|
205
286
  if params.current_offset != -1
@@ -219,12 +300,12 @@ module Karafka
219
300
  end
220
301
 
221
302
  r.get 'dlq' do
222
- controller = Controllers::Dlq.new(params)
303
+ controller = Controllers::DlqController.new(params)
223
304
  controller.index
224
305
  end
225
306
 
226
307
  r.get 'status' do
227
- controller = Controllers::Status.new(params)
308
+ controller = Controllers::StatusController.new(params)
228
309
  controller.show
229
310
  end
230
311
  end
@@ -13,13 +13,12 @@
13
13
 
14
14
  module Karafka
15
15
  module Web
16
- module Ui
17
- module Pro
16
+ module Pro
17
+ module Ui
18
18
  # Namespace for Pro controllers
19
19
  module Controllers
20
- # Cluster controller
21
- class Cluster < Ui::Controllers::Cluster
22
- self.sortable_attributes = Ui::Controllers::Cluster.sortable_attributes
20
+ # Base Pro controller
21
+ class BaseController < Web::Ui::Controllers::BaseController
23
22
  end
24
23
  end
25
24
  end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Web
16
+ module Pro
17
+ module Ui
18
+ # Namespace for Pro controllers
19
+ module Controllers
20
+ # Cluster details controller
21
+ class ClusterController < Web::Ui::Controllers::ClusterController
22
+ self.sortable_attributes = %w[
23
+ id
24
+ name
25
+ default?
26
+ read_only?
27
+ synonym?
28
+ sensitive?
29
+ port
30
+ ].freeze
31
+
32
+ # Lists available brokers in the cluster
33
+ def index
34
+ @brokers = refine(Models::Broker.all)
35
+
36
+ render
37
+ end
38
+
39
+ # Displays selected broker configuration
40
+ #
41
+ # @param broker_id [String] id of the broker
42
+ def show(broker_id)
43
+ @broker = Models::Broker.find(broker_id)
44
+
45
+ @configs = refine(@broker.configs)
46
+
47
+ render
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Web
16
+ module Pro
17
+ module Ui
18
+ module Controllers
19
+ # Controller responsible for handling requests that should trigger some action on the
20
+ # consumers.
21
+ class CommandingController < BaseController
22
+ # Dispatches the probe request to a given process
23
+ #
24
+ # @param process_id [String]
25
+ def probe(process_id)
26
+ command(:probe, process_id)
27
+
28
+ redirect(
29
+ :back,
30
+ success: dispatched_to_one_msg(:probe, process_id)
31
+ )
32
+ end
33
+
34
+ # Dispatches the quiet request to a given process
35
+ #
36
+ # @param process_id [String]
37
+ def quiet(process_id)
38
+ command(:quiet, process_id)
39
+
40
+ redirect(
41
+ :back,
42
+ success: dispatched_to_one_msg(:quiet, process_id)
43
+ )
44
+ end
45
+
46
+ # Dispatches the stop request to a given process
47
+ #
48
+ # @param process_id [String]
49
+ def stop(process_id)
50
+ command(:stop, process_id)
51
+
52
+ redirect(
53
+ :back,
54
+ success: dispatched_to_one_msg(:stop, process_id)
55
+ )
56
+ end
57
+
58
+ # Dispatches the quiet request that should trigger on all consumers
59
+ def quiet_all
60
+ command(:quiet, '*')
61
+
62
+ redirect(
63
+ :back,
64
+ success: dispatched_to_all(:quiet)
65
+ )
66
+ end
67
+
68
+ # Dispatches the stop request that should trigger on all consumers
69
+ def stop_all
70
+ command(:stop, '*')
71
+
72
+ redirect(
73
+ :back,
74
+ success: dispatched_to_all(:stop)
75
+ )
76
+ end
77
+
78
+ private
79
+
80
+ # Dispatches given command
81
+ # @param command [Symbol] command
82
+ # @param process_id [String] process id
83
+ def command(command, process_id)
84
+ Commanding::Dispatcher.command(command, process_id)
85
+ end
86
+
87
+ # @param process_id [String] find given process
88
+ def find_process(process_id)
89
+ Models::Process.find(
90
+ Models::ConsumersState.current!,
91
+ process_id
92
+ )
93
+ end
94
+
95
+ # Generates a nice flash message about the dispatch
96
+ # @param command [Symbol]
97
+ # @param process_id [String]
98
+ # @return [String] flash message that command has been dispatched to a given process
99
+ def dispatched_to_one_msg(command, process_id)
100
+ command_name = command.to_s.capitalize
101
+
102
+ "The #{command_name} command has been dispatched to the #{process_id} process."
103
+ end
104
+
105
+ # Generates a nice flash message about dispatch of multi-process command
106
+ # @param command [Symbol]
107
+ # @return [String] flash message that command has been dispatched
108
+ def dispatched_to_all(command)
109
+ command_name = command.to_s.capitalize
110
+
111
+ "The #{command_name} command has been dispatched to all active processes."
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Web
16
+ module Pro
17
+ module Ui
18
+ module Controllers
19
+ # Controller for viewing details of dispatched commands and their results
20
+ class CommandsController < BaseController
21
+ # Lists commands from the consumers commands topic
22
+ def index
23
+ @schema_version = Commanding::Dispatcher::SCHEMA_VERSION
24
+ @watermark_offsets = Models::WatermarkOffsets.find(commands_topic, 0)
25
+
26
+ previous_offset, @command_messages, next_offset = current_partition_data
27
+
28
+ # If message is an array, it means it's a compacted dummy offset representation
29
+ mapped_messages = @command_messages.map do |message|
30
+ message.is_a?(Array) ? message.last : message.offset
31
+ end
32
+
33
+ paginate(
34
+ previous_offset,
35
+ @params.current_offset,
36
+ next_offset,
37
+ mapped_messages
38
+ )
39
+
40
+ render
41
+ end
42
+
43
+ # Shows details about given command / result
44
+ #
45
+ # @param offset [Integer] offset of the command message we're interested in
46
+ def show(offset)
47
+ @schema_version = Commanding::Dispatcher::SCHEMA_VERSION
48
+ @command_message = Models::Message.find(
49
+ commands_topic,
50
+ 0,
51
+ offset
52
+ )
53
+
54
+ render
55
+ end
56
+
57
+ # Displays the most recent available command message details
58
+ def recent
59
+ # We read 25 just in case there would be a lot of transactional noise
60
+ messages = ::Karafka::Admin.read_topic(commands_topic, 0, 25)
61
+
62
+ # We find the most recent (last since they are shipped in reverse order)
63
+ recent = messages.reverse.find { |message| !message.is_a?(Array) }
64
+
65
+ return show(recent.offset) if recent
66
+
67
+ # If nothing found, lets redirect user back to the commands list
68
+ redirect(
69
+ 'commands',
70
+ warning: 'No recent commands available.'
71
+ )
72
+ end
73
+
74
+ private
75
+
76
+ # @return [Array] Array with requested messages as well as pagination details and other
77
+ # obtained metadata
78
+ def current_partition_data
79
+ Models::Message.offset_page(
80
+ commands_topic,
81
+ 0,
82
+ @params.current_offset,
83
+ @watermark_offsets
84
+ )
85
+ end
86
+
87
+ # @return [String] consumers commands topic name
88
+ def commands_topic
89
+ ::Karafka::Web.config.topics.consumers.commands
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -13,14 +13,18 @@
13
13
 
14
14
  module Karafka
15
15
  module Web
16
- module Ui
17
- module Pro
16
+ module Pro
17
+ module Ui
18
18
  module Controllers
19
19
  # Controller for displaying consumers states and details about them
20
- class Consumers < Ui::Controllers::Base
20
+ class ConsumersController < BaseController
21
+ include Web::Ui::Lib::Paginations
22
+
21
23
  self.sortable_attributes = %w[
22
24
  id
25
+ process_id
23
26
  name
27
+ status
24
28
  started_at
25
29
  lag_hybrid
26
30
  lag_hybrid_d
@@ -36,6 +40,15 @@ module Karafka
36
40
  first_offset
37
41
  last_offset
38
42
  updated_at
43
+ memory_usage
44
+ threads
45
+ utilization
46
+ busy
47
+ workers
48
+ active
49
+ standby
50
+ running_jobs_count
51
+ pending_jobs_count
39
52
  ].freeze
40
53
 
41
54
  # Consumers list
@@ -43,7 +56,7 @@ module Karafka
43
56
  @current_state = Models::ConsumersState.current!
44
57
  @counters = Models::Counters.new(@current_state)
45
58
 
46
- @processes, last_page = Lib::Paginations::Paginators::Arrays.call(
59
+ @processes, last_page = Paginators::Arrays.call(
47
60
  refine(Models::Processes.active(@current_state)),
48
61
  @params.current_page
49
62
  )
@@ -53,6 +66,20 @@ module Karafka
53
66
  render
54
67
  end
55
68
 
69
+ # Displays per-process performance details
70
+ def performance
71
+ index
72
+
73
+ render
74
+ end
75
+
76
+ # Displays processes with details + ability to manage
77
+ def controls
78
+ index
79
+
80
+ render
81
+ end
82
+
56
83
  # @param process_id [String] id of the process we're interested in
57
84
  def details(process_id)
58
85
  current_state = Models::ConsumersState.current!
@@ -13,11 +13,13 @@
13
13
 
14
14
  module Karafka
15
15
  module Web
16
- module Ui
17
- module Pro
16
+ module Pro
17
+ module Ui
18
18
  module Controllers
19
19
  # Main Karafka Pro Web-Ui dashboard controller
20
- class Dashboard < Ui::Controllers::Base
20
+ class DashboardController < BaseController
21
+ include Web::Ui
22
+
21
23
  # View with statistics dashboard details
22
24
  def index
23
25
  @current_state = Models::ConsumersState.current!
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Web
16
+ module Pro
17
+ module Ui
18
+ module Controllers
19
+ # DLQ topics overview
20
+ class DlqController < BaseController
21
+ # Lists DLQ topics
22
+ def index
23
+ topics = Karafka::App.consumer_groups.flat_map(&:topics).flat_map(&:to_a)
24
+
25
+ dlq_topic_patterns = topics
26
+ .map { |source_topic| source_topic.dead_letter_queue.topic }
27
+ .uniq
28
+ .compact
29
+ .select(&:itself)
30
+
31
+ dlq_topic_patterns += Web.config.ui.dlq_patterns
32
+
33
+ @dlq_topics = Models::ClusterInfo
34
+ .topics
35
+ .select { |topic| dlq?(dlq_topic_patterns, topic[:topic_name]) }
36
+ .sort_by { |topic| topic[:topic_name] }
37
+
38
+ render
39
+ end
40
+
41
+ private
42
+
43
+ # Checks if topic is in topics we consider DLQ or if it matches any predefined regular
44
+ # expressions used for auto-DLQ discovery
45
+ #
46
+ # @param topics_matches [Array<String, Regexp>] array with list of DLQ topics matches
47
+ # from the routing and regular expressions for auto-discovery
48
+ # @param name [String] topic name for which we want to know if it is used in DLQ
49
+ # @return [Boolean] is the given topic a DLQ topic
50
+ def dlq?(topics_matches, name)
51
+ topics_matches.any? do |candidate|
52
+ candidate.match?(name)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -13,13 +13,11 @@
13
13
 
14
14
  module Karafka
15
15
  module Web
16
- module Ui
17
- module Pro
16
+ module Pro
17
+ module Ui
18
18
  module Controllers
19
19
  # Errors details controller
20
- class Errors < Ui::Controllers::Base
21
- include Ui::Lib::Paginations
22
-
20
+ class ErrorsController < BaseController
23
21
  # Lists all the errors from all the partitions
24
22
  def index
25
23
  @topic_id = errors_topic
@@ -41,7 +39,7 @@ module Karafka
41
39
  # @param partition_id [Integer] id of the partition of errors we are interested in
42
40
  def partition(partition_id)
43
41
  @partition_id = partition_id
44
- @watermark_offsets = Ui::Models::WatermarkOffsets.find(errors_topic, @partition_id)
42
+ @watermark_offsets = Models::WatermarkOffsets.find(errors_topic, @partition_id)
45
43
  @partitions_count = Models::ClusterInfo.partitions_count(errors_topic)
46
44
 
47
45
  previous_offset, @error_messages, next_offset = Models::Message.offset_page(
@@ -74,7 +72,7 @@ module Karafka
74
72
  @offset
75
73
  )
76
74
 
77
- watermark_offsets = Ui::Models::WatermarkOffsets.find(errors_topic, partition_id)
75
+ watermark_offsets = Models::WatermarkOffsets.find(errors_topic, partition_id)
78
76
  paginate(offset, watermark_offsets.low, watermark_offsets.high)
79
77
 
80
78
  render