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
@@ -0,0 +1,10 @@
1
+ <div class="mb-4">
2
+ <%==
3
+ alert_info(
4
+ '
5
+ Due to the number of partitions, distribution results are computed based only on
6
+ data from partitions visible on this page.
7
+ '
8
+ )
9
+ %>
10
+ </div>
@@ -0,0 +1,10 @@
1
+ <tr>
2
+ <td>
3
+ <a href="<%= explorer_path(@topic.topic_name, partition.partition_id) %>">
4
+ <%= partition.partition_id %>
5
+ </a>
6
+ </td>
7
+ <td><%= partition.count %></td>
8
+ <td><%= partition.share %>%</td>
9
+ <td><%= partition.diff.round(2) %>%</td>
10
+ </tr>
@@ -0,0 +1,47 @@
1
+ <%== view_title(@topic.topic_name, hr: false) %>
2
+
3
+ <%== partial 'topics/tabs' %>
4
+
5
+ <div class="container">
6
+ <div class="row">
7
+ <div class="col-lg-12">
8
+ <% if @limited %>
9
+ <%== partial 'topics/distribution/limited' %>
10
+ <% end %>
11
+
12
+ <% if @aggregated.sum.zero? %>
13
+ <%== partial 'topics/distribution/empty_partitions' %>
14
+ <% else %>
15
+ <% if @active_partitions.size >= 2 %>
16
+ <%== partial 'topics/distribution/chart' %>
17
+ <% end %>
18
+
19
+ <div id="refreshable" class="mt-4">
20
+ <%== partial 'topics/distribution/badges' %>
21
+
22
+ <div class="table-responsive">
23
+ <table class="bg-white table table-hover table-bordered table-striped mt-4 mb-4">
24
+ <thead>
25
+ <tr class="align-middle">
26
+ <th><%== sort_link(:partition_id) %></th>
27
+ <th><%== sort_link('Estimated count', :count) %></th>
28
+ <th><%== sort_link('Total share', :share) %></th>
29
+ <th><%== sort_link(:diff) %></th>
30
+ </tr>
31
+ </thead>
32
+ <tbody>
33
+ <%==
34
+ each_partial(
35
+ @distribution,
36
+ 'topics/distribution/partition'
37
+ )
38
+ %>
39
+ </tbody>
40
+ </table>
41
+ </div>
42
+ </div>
43
+ <% end %>
44
+
45
+ </div>
46
+ </div>
47
+ </div>
@@ -0,0 +1,16 @@
1
+ <%== view_title('Topics', hr: true) %>
2
+
3
+ <div class="container">
4
+ <% if @topics.empty? %>
5
+ <%== partial 'explorer/no_topics' %>
6
+ <% else %>
7
+ <div class="row mb-5 row-cols-1 row-cols-md-4 g-4">
8
+ <%==
9
+ each_partial(
10
+ @topics,
11
+ 'topics/topic'
12
+ )
13
+ %>
14
+ </div>
15
+ <% end %>
16
+ </div>
@@ -0,0 +1,28 @@
1
+ <%== view_title(@topic.topic_name, hr: false) %>
2
+
3
+ <%== partial 'topics/tabs' %>
4
+
5
+ <div class="container mb-5">
6
+ <div class="row">
7
+ <div class="col-lg-12 table-responsive">
8
+ <table class="processes bg-white table table-hover table-bordered table-striped">
9
+ <thead>
10
+ <tr class="align-middle">
11
+ <th><%== sort_link(:partition_id) %></th>
12
+ <th><%== sort_link(:leader) %></th>
13
+ <th><%== sort_link(:replica_count) %></th>
14
+ <th><%== sort_link('In sync brokers', :in_sync_replica_brokers) %></th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ <%==
19
+ each_partial(
20
+ @partitions,
21
+ 'topics/partition'
22
+ )
23
+ %>
24
+ </tbody>
25
+ </table>
26
+ </div>
27
+ </div>
28
+ </div>
@@ -36,7 +36,7 @@ module Karafka
36
36
  # Updates the report for given process in memory
37
37
  # @param report [Hash]
38
38
  def memoize_process_report(report)
39
- @active_reports[report[:process][:name]] = report
39
+ @active_reports[report[:process][:id]] = report
40
40
  end
41
41
 
42
42
  # Updates the time of the aggregation
@@ -70,7 +70,7 @@ module Karafka
70
70
  def evict_expired_processes
71
71
  max_ttl = @aggregated_from - ::Karafka::Web.config.ttl / 1_000
72
72
 
73
- @active_reports.delete_if do |_name, report|
73
+ @active_reports.delete_if do |_id, report|
74
74
  report[:dispatched_at] < max_ttl || report[:process][:status] == 'stopped'
75
75
  end
76
76
  end
@@ -89,9 +89,9 @@ module Karafka
89
89
  # @param report [Hash]
90
90
  # @param offset [Integer]
91
91
  def update_process_state(report, offset)
92
- process_name = report[:process][:name]
92
+ process_id = report[:process][:id]
93
93
 
94
- state[:processes][process_name] = {
94
+ state[:processes][process_id] = {
95
95
  dispatched_at: report[:dispatched_at],
96
96
  offset: offset
97
97
  }
@@ -105,11 +105,11 @@ module Karafka
105
105
  def evict_expired_processes
106
106
  max_ttl = @aggregated_from - ::Karafka::Web.config.ttl / 1_000
107
107
 
108
- state[:processes].delete_if do |_name, details|
108
+ state[:processes].delete_if do |_id, details|
109
109
  details[:dispatched_at] < max_ttl
110
110
  end
111
111
 
112
- @active_reports.delete_if do |_name, details|
112
+ @active_reports.delete_if do |_id, details|
113
113
  details[:dispatched_at] < max_ttl
114
114
  end
115
115
  end
@@ -20,7 +20,7 @@ module Karafka
20
20
 
21
21
  nested(:process) do
22
22
  required(:started_at) { |val| val.is_a?(Numeric) && val.positive? }
23
- required(:name) { |val| val.is_a?(String) && val.count(':') >= 2 }
23
+ required(:id) { |val| val.is_a?(String) && val.count(':') >= 2 }
24
24
  required(:cpus) { |val| val.is_a?(Integer) && val >= 1 }
25
25
  required(:memory_usage) { |val| val.is_a?(Integer) && val >= 0 }
26
26
  required(:memory_total_usage) { |val| val.is_a?(Integer) && val >= 0 }
@@ -14,7 +14,9 @@ module Karafka
14
14
  #
15
15
  # @param _event [Karafka::Core::Monitoring::Event]
16
16
  def on_app_running(_event)
17
- ::Karafka::Web.config.tracking.scheduler.async_call
17
+ ::Karafka::Web.config.tracking.scheduler.async_call(
18
+ 'karafka.web.tracking.scheduler'
19
+ )
18
20
  end
19
21
 
20
22
  # Updates the web producer after fork if needed and adds ppid to nodes
@@ -10,7 +10,7 @@ module Karafka
10
10
  include Tracking::Helpers::ErrorInfo
11
11
 
12
12
  # Schema used by consumers error reporting
13
- SCHEMA_VERSION = '1.0.0'
13
+ SCHEMA_VERSION = '1.1.0'
14
14
 
15
15
  private_constant :SCHEMA_VERSION
16
16
 
@@ -37,7 +37,7 @@ module Karafka
37
37
  backtrace: backtrace,
38
38
  details: details,
39
39
  occurred_at: float_now,
40
- process: sampler.to_report[:process].slice(:name, :tags)
40
+ process: sampler.to_report[:process].slice(:id, :tags)
41
41
  }
42
42
 
43
43
  sampler.counters[:errors] += 1
@@ -65,14 +65,14 @@ module Karafka
65
65
 
66
66
  @report_contract.validate!(report)
67
67
 
68
- process_name = report[:process][:name]
68
+ process_id = report[:process][:id]
69
69
 
70
70
  # Report consumers statuses
71
71
  messages = [
72
72
  {
73
73
  topic: ::Karafka::Web.config.topics.consumers.reports,
74
74
  payload: Zlib::Deflate.deflate(report.to_json),
75
- key: process_name,
75
+ key: process_id,
76
76
  partition: 0,
77
77
  headers: { 'zlib' => 'true' }
78
78
  }
@@ -86,7 +86,7 @@ module Karafka
86
86
  topic: Karafka::Web.config.topics.errors,
87
87
  payload: Zlib::Deflate.deflate(error.to_json),
88
88
  # Always dispatch errors from the same process to the same partition
89
- key: process_name,
89
+ key: process_id,
90
90
  headers: { 'zlib' => 'true' }
91
91
  }
92
92
  end
@@ -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.2.9'
18
+ SCHEMA_VERSION = '1.3.0'
19
19
 
20
20
  # Counters that count events occurrences during the given window
21
21
  COUNTERS_BASE = {
@@ -70,8 +70,8 @@ module Karafka
70
70
  dispatched_at: float_now,
71
71
 
72
72
  process: {
73
+ id: process_id,
73
74
  started_at: started_at,
74
- name: process_name,
75
75
  status: ::Karafka::App.config.internal.status.to_s,
76
76
  listeners: listeners,
77
77
  workers: workers,
@@ -20,7 +20,7 @@ module Karafka
20
20
  required(:occurred_at) { |val| val.is_a?(Float) }
21
21
 
22
22
  nested(:process) do
23
- required(:name) { |val| val.is_a?(String) && !val.empty? }
23
+ required(:id) { |val| val.is_a?(String) && !val.empty? }
24
24
  # Tags may not be present for producers because they may operate from outside of
25
25
  # karafka taggable process
26
26
  optional(:tags) { |val| val.is_a?(Karafka::Core::Taggable::Tags) }
@@ -14,7 +14,9 @@ module Karafka
14
14
  #
15
15
  # @param _event [Karafka::Core::Monitoring::Event]
16
16
  def on_producer_connected(_event)
17
- ::Karafka::Web.config.tracking.scheduler.async_call
17
+ ::Karafka::Web.config.tracking.scheduler.async_call(
18
+ 'karafka.web.tracking.scheduler'
19
+ )
18
20
  end
19
21
  end
20
22
  end
@@ -10,7 +10,7 @@ module Karafka
10
10
  include Tracking::Helpers::ErrorInfo
11
11
 
12
12
  # Schema used by producers error reporting
13
- SCHEMA_VERSION = '1.0.0'
13
+ SCHEMA_VERSION = '1.1.0'
14
14
 
15
15
  private_constant :SCHEMA_VERSION
16
16
 
@@ -42,7 +42,7 @@ module Karafka
42
42
  details: build_details(type, event.payload),
43
43
  occurred_at: float_now,
44
44
  process: {
45
- name: sampler.process_name
45
+ id: sampler.process_id
46
46
  }
47
47
  }
48
48
  end
@@ -43,7 +43,7 @@ module Karafka
43
43
  topic: Karafka::Web.config.topics.errors,
44
44
  payload: error.to_json,
45
45
  # Always dispatch errors from the same process to the same partition
46
- key: error[:process][:name]
46
+ key: error[:process][:id]
47
47
  }
48
48
  end
49
49
 
@@ -14,7 +14,7 @@ module Karafka
14
14
  # Current schema version
15
15
  # This can be used in the future for detecting incompatible changes and writing
16
16
  # migrations
17
- SCHEMA_VERSION = '1.0.0'
17
+ SCHEMA_VERSION = '1.1.0'
18
18
 
19
19
  def initialize
20
20
  super
@@ -7,9 +7,9 @@ module Karafka
7
7
  # This sampler should store **only** collectors that can be used for producers, consumers and
8
8
  # the Web-UI itself. All specific to a given aspect of operations should be moved out.
9
9
  class Sampler
10
- # @return [String] Unique process name
11
- def process_name
12
- @process_name ||= "#{Socket.gethostname}:#{::Process.pid}:#{SecureRandom.hex(6)}"
10
+ # @return [String] Unique process identifier
11
+ def process_id
12
+ @process_id ||= "#{Socket.gethostname}:#{::Process.pid}:#{SecureRandom.hex(6)}"
13
13
  end
14
14
 
15
15
  # @return [String] currently used ruby version with details
@@ -22,7 +22,7 @@ module Karafka
22
22
 
23
23
  r.get 'dashboard' do
24
24
  @breadcrumbs = false
25
- controller = Controllers::Dashboard.new(params)
25
+ controller = Controllers::DashboardController.new(params)
26
26
  controller.index
27
27
  end
28
28
 
@@ -33,7 +33,7 @@ module Karafka
33
33
 
34
34
  r.get do
35
35
  @breadcrumbs = false
36
- controller = Controllers::Consumers.new(params)
36
+ controller = Controllers::ConsumersController.new(params)
37
37
  controller.index
38
38
  end
39
39
  end
@@ -49,7 +49,7 @@ module Karafka
49
49
  end
50
50
 
51
51
  r.on 'jobs' do
52
- controller = Controllers::Jobs.new(params)
52
+ controller = Controllers::JobsController.new(params)
53
53
 
54
54
  r.get 'running' do
55
55
  controller.running
@@ -63,7 +63,7 @@ module Karafka
63
63
  end
64
64
 
65
65
  r.on 'routing' do
66
- controller = Controllers::Routing.new(params)
66
+ controller = Controllers::RoutingController.new(params)
67
67
 
68
68
  r.get String do |topic_id|
69
69
  controller.show(topic_id)
@@ -75,21 +75,25 @@ module Karafka
75
75
  end
76
76
 
77
77
  r.on 'cluster' do
78
- controller = Controllers::Cluster.new(params)
78
+ controller = Controllers::ClusterController.new(params)
79
79
 
80
80
  r.get 'brokers' do
81
81
  controller.brokers
82
82
  end
83
83
 
84
- r.get 'topics' do
85
- controller.topics
84
+ r.get 'replication' do
85
+ controller.replication
86
86
  end
87
87
 
88
88
  r.redirect root_path('cluster/brokers')
89
89
  end
90
90
 
91
+ r.on 'topics' do
92
+ raise Errors::Ui::ProOnlyError
93
+ end
94
+
91
95
  r.on 'errors' do
92
- controller = Controllers::Errors.new(params)
96
+ controller = Controllers::ErrorsController.new(params)
93
97
 
94
98
  r.get Integer do |offset|
95
99
  controller.show(offset)
@@ -101,7 +105,7 @@ module Karafka
101
105
  end
102
106
 
103
107
  r.get 'status' do
104
- controller = Controllers::Status.new(params)
108
+ controller = Controllers::StatusController.new(params)
105
109
  controller.show
106
110
  end
107
111
  end
@@ -7,6 +7,7 @@ module Karafka
7
7
  class Base < Roda
8
8
  include Helpers::PathsHelper
9
9
  include Helpers::ApplicationHelper
10
+ include Helpers::AlertsHelper
10
11
 
11
12
  # Details that need to be evaluated in the context of OSS or Pro web UI.
12
13
  # If those would be evaluated in the base, they would not be initialized as expected
@@ -6,7 +6,12 @@ module Karafka
6
6
  # Namespace for controller related components in the Web UI app.
7
7
  module Controllers
8
8
  # Base controller from which all the controllers should inherit.
9
- class Base
9
+ class BaseController
10
+ include Web::Ui::Lib::Paginations
11
+
12
+ # Alias for easier referencing
13
+ Models = Web::Ui::Models
14
+
10
15
  class << self
11
16
  # Attributes on which we can sort in a given controller
12
17
  attr_accessor :sortable_attributes
@@ -27,7 +32,7 @@ module Karafka
27
32
  def render
28
33
  attributes = {}
29
34
 
30
- scope = self.class.to_s.split('::').last.gsub(/(.)([A-Z])/, '\1_\2').downcase
35
+ scope = self.class.to_s.split('::').last.gsub(/(.)([A-Z])/, '\1_\2').downcase.gsub('_controller', '')
31
36
  action = caller_locations(1, 1)[0].label
32
37
 
33
38
  instance_variables.each do |iv|
@@ -91,6 +96,14 @@ module Karafka
91
96
 
92
97
  @pagination = engine.new(*args)
93
98
  end
99
+
100
+ # Raises the not found error
101
+ #
102
+ # @param resource_id [String] resource id that was not found
103
+ # @raise [::Karafka::Web::Errors::Ui::NotFoundError]
104
+ def not_found!(resource_id = '')
105
+ raise(::Karafka::Web::Errors::Ui::NotFoundError, resource_id)
106
+ end
94
107
  end
95
108
  end
96
109
  end
@@ -5,7 +5,7 @@ module Karafka
5
5
  module Ui
6
6
  module Controllers
7
7
  # Pro message reporting info controller
8
- class BecomePro < Base
8
+ class BecomeProController < BaseController
9
9
  # Display a message, that a given feature is available only in Pro
10
10
  def show
11
11
  render
@@ -5,7 +5,7 @@ module Karafka
5
5
  module Ui
6
6
  module Controllers
7
7
  # Selects cluster info and topics basic info
8
- class Cluster < Base
8
+ class ClusterController < BaseController
9
9
  self.sortable_attributes = %w[
10
10
  broker_id
11
11
  broker_name
@@ -24,8 +24,8 @@ module Karafka
24
24
  render
25
25
  end
26
26
 
27
- # List topics and partitions with details
28
- def topics
27
+ # List partitions replication details
28
+ def replication
29
29
  partitions_total = []
30
30
 
31
31
  displayable_topics(cluster_info).each do |topic|
@@ -38,7 +38,7 @@ module Karafka
38
38
  end
39
39
  end
40
40
 
41
- @partitions, last_page = Ui::Lib::Paginations::Paginators::Arrays.call(
41
+ @partitions, last_page = Paginators::Arrays.call(
42
42
  refine(partitions_total),
43
43
  @params.current_page
44
44
  )
@@ -5,9 +5,9 @@ module Karafka
5
5
  module Ui
6
6
  module Controllers
7
7
  # Consumers (consuming processes - `karafka server`) processes display consumer
8
- class Consumers < Base
8
+ class ConsumersController < BaseController
9
9
  self.sortable_attributes = %w[
10
- name
10
+ id
11
11
  started_at
12
12
  lag_hybrid
13
13
  ].freeze
@@ -17,7 +17,7 @@ module Karafka
17
17
  def index
18
18
  @current_state = Models::ConsumersState.current!
19
19
  @counters = Models::Counters.new(@current_state)
20
- @processes, last_page = Ui::Lib::Paginations::Paginators::Arrays.call(
20
+ @processes, last_page = Paginators::Arrays.call(
21
21
  refine(Models::Processes.active(@current_state)),
22
22
  @params.current_page
23
23
  )
@@ -5,7 +5,7 @@ module Karafka
5
5
  module Ui
6
6
  module Controllers
7
7
  # Main Karafka Pro Web-Ui dashboard controller
8
- class Dashboard < Ui::Controllers::Base
8
+ class DashboardController < Ui::Controllers::BaseController
9
9
  # View with statistics dashboard details
10
10
  def index
11
11
  @current_state = Models::ConsumersState.current!
@@ -7,10 +7,10 @@ module Karafka
7
7
  # Errors displaying controller
8
8
  # It supports only scenarios with a single partition for errors
9
9
  # If you have high load of errors, consider going Pro
10
- class Errors < Base
10
+ class ErrorsController < BaseController
11
11
  # Lists first page of the errors
12
12
  def index
13
- @watermark_offsets = Ui::Models::WatermarkOffsets.find(errors_topic, 0)
13
+ @watermark_offsets = Models::WatermarkOffsets.find(errors_topic, 0)
14
14
  previous_offset, @error_messages, next_offset, = current_page_data
15
15
 
16
16
  paginate(
@@ -5,9 +5,9 @@ module Karafka
5
5
  module Ui
6
6
  module Controllers
7
7
  # Active jobs (work) reporting controller
8
- class Jobs < Base
8
+ class JobsController < BaseController
9
9
  self.sortable_attributes = %w[
10
- name
10
+ id
11
11
  topic
12
12
  consumer
13
13
  type
@@ -29,7 +29,7 @@ module Karafka
29
29
  end
30
30
  end
31
31
 
32
- @jobs, last_page = Ui::Lib::Paginations::Paginators::Arrays.call(
32
+ @jobs, last_page = Paginators::Arrays.call(
33
33
  refine(jobs_total),
34
34
  @params.current_page
35
35
  )
@@ -54,7 +54,7 @@ module Karafka
54
54
  end
55
55
  end
56
56
 
57
- @jobs, last_page = Ui::Lib::Paginations::Paginators::Arrays.call(
57
+ @jobs, last_page = Paginators::Arrays.call(
58
58
  refine(jobs_total),
59
59
  @params.current_page
60
60
  )
@@ -66,7 +66,7 @@ module Karafka
66
66
 
67
67
  private
68
68
 
69
- # @param processes [Array<Models::Process>]
69
+ # @param processes [Array<Process>]
70
70
  # @return [Lib::HashProxy] particular type jobs count
71
71
  def count_jobs_types(processes)
72
72
  counts = { running: 0, pending: 0 }
@@ -5,7 +5,7 @@ module Karafka
5
5
  module Ui
6
6
  module Controllers
7
7
  # Routing presentation controller
8
- class Routing < Base
8
+ class RoutingController < BaseController
9
9
  self.sortable_attributes = %w[
10
10
  name
11
11
  active?
@@ -28,7 +28,7 @@ module Karafka
28
28
  def show(topic_id)
29
29
  @topic = Karafka::Routing::Router.find_by(id: topic_id)
30
30
 
31
- @topic || raise(::Karafka::Web::Errors::Ui::NotFoundError, topic_id)
31
+ @topic || not_found!(topic_id)
32
32
 
33
33
  render
34
34
  end
@@ -9,7 +9,7 @@ module Karafka
9
9
  # While all of the things are documented, people are lazy. Hence we provide a status
10
10
  # page where we check that everything is as expected and if not, we can provide some
11
11
  # helpful instructions on how to fix the issues.
12
- class Status < Base
12
+ class StatusController < BaseController
13
13
  # Displays the Web UI setup status
14
14
  def show
15
15
  @status = Models::Status.new
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Web
5
+ module Ui
6
+ module Helpers
7
+ # Helper for generating general alerts
8
+ module AlertsHelper
9
+ # @param message [String] alert message
10
+ # @return [String] html with alert info
11
+ def alert_info(message)
12
+ partial(
13
+ 'shared/alerts/info',
14
+ locals: {
15
+ message: message
16
+ }
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end