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,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
  # Data explorer controller
20
- class Explorer < Ui::Controllers::Base
21
- include Ui::Lib::Paginations
22
-
20
+ class ExplorerController < BaseController
23
21
  # Lists all the topics we can explore
24
22
  def index
25
23
  @topics = Models::ClusterInfo
@@ -71,7 +69,7 @@ module Karafka
71
69
  @visibility_filter = ::Karafka::Web.config.ui.visibility.filter
72
70
  @topic_id = topic_id
73
71
  @partition_id = partition_id
74
- @watermark_offsets = Ui::Models::WatermarkOffsets.find(topic_id, partition_id)
72
+ @watermark_offsets = Models::WatermarkOffsets.find(topic_id, partition_id)
75
73
  @partitions_count = Models::ClusterInfo.partitions_count(topic_id)
76
74
 
77
75
  previous_offset, @messages, next_offset = current_partition_data
@@ -94,17 +92,24 @@ module Karafka
94
92
  # @param offset [Integer] offset of the message we want to display
95
93
  # @param paginate [Boolean] do we want to have pagination
96
94
  def show(topic_id, partition_id, offset, paginate: true)
95
+ Lib::PatternsDetector.new.call
96
+
97
97
  @visibility_filter = ::Karafka::Web.config.ui.visibility.filter
98
98
  @topic_id = topic_id
99
99
  @partition_id = partition_id
100
100
  @offset = offset
101
- @message = Ui::Models::Message.find(@topic_id, @partition_id, @offset)
102
- @payload_error = false
101
+ @message = Models::Message.find(@topic_id, @partition_id, @offset)
102
+
103
+ @safe_payload = Web::Ui::Lib::SafeRunner.new do
104
+ JSON.pretty_generate(@message.payload)
105
+ end
106
+
107
+ @safe_key = Web::Ui::Lib::SafeRunner.new do
108
+ @message.key
109
+ end
103
110
 
104
- begin
105
- @pretty_payload = JSON.pretty_generate(@message.payload)
106
- rescue StandardError => e
107
- @payload_error = e
111
+ @safe_headers = Web::Ui::Lib::SafeRunner.new do
112
+ @message.headers
108
113
  end
109
114
 
110
115
  # This may be off for certain views like recent view where we are interested only
@@ -112,7 +117,7 @@ module Karafka
112
117
  # there
113
118
  if paginate
114
119
  # We need watermark offsets to decide if we can paginate left and right
115
- watermark_offsets = Ui::Models::WatermarkOffsets.find(topic_id, partition_id)
120
+ watermark_offsets = Models::WatermarkOffsets.find(topic_id, partition_id)
116
121
  paginate(offset, watermark_offsets.low, watermark_offsets.high)
117
122
  end
118
123
 
@@ -149,7 +154,7 @@ module Karafka
149
154
  break if recent
150
155
  end
151
156
 
152
- recent || raise(::Karafka::Web::Errors::Ui::NotFoundError)
157
+ recent || not_found!
153
158
 
154
159
  show(topic_id, recent.partition, recent.offset, paginate: false)
155
160
  end
@@ -162,10 +167,10 @@ module Karafka
162
167
  # @param partition_id [Integer]
163
168
  # @param offset [Integer] offset of the message we want to display
164
169
  def surrounding(topic_id, partition_id, offset)
165
- watermark_offsets = Ui::Models::WatermarkOffsets.find(topic_id, partition_id)
170
+ watermark_offsets = Models::WatermarkOffsets.find(topic_id, partition_id)
166
171
 
167
- raise ::Karafka::Web::Errors::Ui::NotFoundError if offset < watermark_offsets.low
168
- raise ::Karafka::Web::Errors::Ui::NotFoundError if offset >= watermark_offsets.high
172
+ not_found! if offset < watermark_offsets.low
173
+ not_found! if offset >= watermark_offsets.high
169
174
 
170
175
  # Assume we start from this offset
171
176
  shift = 0
@@ -195,7 +200,7 @@ module Karafka
195
200
  # @param partition_id [Integer]
196
201
  # @param time [Time] time of the message
197
202
  def closest(topic_id, partition_id, time)
198
- target = Lib::Admin.read_topic(topic_id, partition_id, 1, time).first
203
+ target = Web::Ui::Lib::Admin.read_topic(topic_id, partition_id, 1, time).first
199
204
 
200
205
  partition_path = "explorer/#{topic_id}/#{partition_id}"
201
206
  partition_path += "?offset=#{target.offset}" if target
@@ -208,7 +213,7 @@ module Karafka
208
213
  # Fetches current page data
209
214
  # @return [Array] fetched data with pagination information for the requested partition
210
215
  def current_partition_data
211
- Ui::Models::Message.offset_page(
216
+ Models::Message.offset_page(
212
217
  @topic_id,
213
218
  @partition_id,
214
219
  @params.current_offset,
@@ -13,11 +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
  # Health state controller
20
- class Health < Ui::Controllers::Base
20
+ class HealthController < BaseController
21
21
  self.sortable_attributes = %w[
22
22
  id
23
23
  lag
@@ -62,6 +62,19 @@ module Karafka
62
62
  render
63
63
  end
64
64
 
65
+ # Displays lags for routing defined consumer groups taken from the cluster and not
66
+ # the metrics reported. This is useful when we don't have any consumers running but
67
+ # still want to check lags because it shows what Kafka sees
68
+ def cluster_lags
69
+ @stats = Models::Health.cluster_lags_with_offsets
70
+
71
+ @stats.each_value do |cg_details|
72
+ cg_details.each_value { |topic_details| refine(topic_details) }
73
+ end
74
+
75
+ render
76
+ end
77
+
65
78
  # Displays details about offsets and their progression/statuses
66
79
  def offsets
67
80
  # Same data as overview but presented differently
@@ -13,13 +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
  # Displays list of active jobs
20
- class Jobs < Ui::Controllers::Jobs
20
+ class JobsController < Web::Ui::Controllers::JobsController
21
21
  self.sortable_attributes = %w[
22
- name
22
+ id
23
23
  topic
24
24
  consumer
25
25
  type
@@ -13,20 +13,20 @@
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 working with messages
20
20
  # While part of messages operations is done via explorer (exploring), this controller
21
21
  # handles other cases not related to viewing data
22
- class Messages < Ui::Controllers::Base
22
+ class MessagesController < BaseController
23
23
  # Takes a requested message content and republishes it again
24
24
  #
25
25
  # @param topic_id [String]
26
26
  # @param partition_id [Integer]
27
27
  # @param offset [Integer] offset of the message we want to republish
28
28
  def republish(topic_id, partition_id, offset)
29
- message = Ui::Models::Message.find(topic_id, partition_id, offset)
29
+ message = Models::Message.find(topic_id, partition_id, offset)
30
30
 
31
31
  delivery = ::Karafka::Web.producer.produce_sync(
32
32
  topic: topic_id,
@@ -48,7 +48,7 @@ module Karafka
48
48
  # @param partition_id [Integer]
49
49
  # @param offset [Integer] offset of the message we want to download
50
50
  def download(topic_id, partition_id, offset)
51
- message = Ui::Models::Message.find(topic_id, partition_id, offset)
51
+ message = Models::Message.find(topic_id, partition_id, offset)
52
52
 
53
53
  # Check if downloads are allowed
54
54
  return deny unless visibility_filter.download?(message)
@@ -68,7 +68,9 @@ module Karafka
68
68
  # @param partition_id [Integer]
69
69
  # @param offset [Integer] offset of the message we want to export
70
70
  def export(topic_id, partition_id, offset)
71
- message = Ui::Models::Message.find(topic_id, partition_id, offset)
71
+ Lib::PatternsDetector.new.call
72
+
73
+ message = Models::Message.find(topic_id, partition_id, offset)
72
74
 
73
75
  # Check if exports are allowed
74
76
  return deny unless visibility_filter.export?(message)
@@ -13,11 +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
  # Routing details - same as in OSS
20
- class Routing < Ui::Controllers::Routing
20
+ class RoutingController < BaseController
21
21
  self.sortable_attributes = %w[
22
22
  name
23
23
  active?
@@ -44,32 +44,16 @@ module Karafka
44
44
 
45
45
  @topic = Karafka::Routing::Router.find_by(id: topic_id)
46
46
 
47
- @topic || raise(::Karafka::Web::Errors::Ui::NotFoundError, topic_id)
47
+ @topic || not_found!(topic_id)
48
48
 
49
49
  render
50
50
  end
51
51
 
52
52
  private
53
53
 
54
- # Checks list of topics and tries to match them against the available patterns
55
- # Uses the Pro detector to expand routes in the Web-UI so we include topics that are
56
- # or will be matched using our regular expressions
54
+ # Detect routes defined as patterns
57
55
  def detect_patterns_routes
58
- detector = ::Karafka::Pro::Routing::Features::Patterns::Detector.new
59
- topics_names = Models::ClusterInfo.topics.map(&:topic_name)
60
-
61
- Karafka::App
62
- .routes
63
- .flat_map(&:subscription_groups)
64
- .each do |subscription_group|
65
- sg_topics = subscription_group.topics
66
-
67
- # Reject topics that are already part of routing for given subscription groups
68
- # and then for remaining try to apply patterns and expand routes
69
- topics_names
70
- .reject { |t_name| sg_topics.any? { |rtopic| rtopic.name == t_name } }
71
- .each { |t_name| detector.expand(sg_topics, t_name) }
72
- end
56
+ Lib::PatternsDetector.new.call
73
57
  end
74
58
  end
75
59
  end
@@ -13,11 +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
  # Status details - same as in OSS
20
- class Status < Ui::Controllers::Status
20
+ class StatusController < Web::Ui::Controllers::StatusController
21
21
  end
22
22
  end
23
23
  end
@@ -0,0 +1,99 @@
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
+ # Topics management controller
20
+ # Allows for exploration of settings and replication details
21
+ class TopicsController < BaseController
22
+ self.sortable_attributes = %w[
23
+ name
24
+ value
25
+ default?
26
+ read_only?
27
+ synonym?
28
+ sensitive?
29
+ partition_id
30
+ leader
31
+ replica_count
32
+ in_sync_replica_brokers
33
+ count
34
+ share
35
+ diff
36
+ ].freeze
37
+
38
+ # Lists available topics in the cluster
39
+ def index
40
+ @topics = Models::Topic.all.sort_by(&:topic_name)
41
+
42
+ unless ::Karafka::Web.config.ui.visibility.internal_topics
43
+ @topics.delete_if { |topic| topic[:topic_name].start_with?('__') }
44
+ end
45
+
46
+ render
47
+ end
48
+
49
+ # Displays requested topic config details
50
+ #
51
+ # @param topic_name [String] topic we're interested in
52
+ def config(topic_name)
53
+ @topic = Models::Topic.find(topic_name)
54
+
55
+ @configs = refine(@topic.configs)
56
+
57
+ render
58
+ end
59
+
60
+ # Displays requested topic replication details
61
+ #
62
+ # @param topic_name [String] topic we're interested in
63
+ def replication(topic_name)
64
+ @topic = Models::Topic.find(topic_name)
65
+
66
+ @partitions = refine(@topic[:partitions])
67
+
68
+ render
69
+ end
70
+
71
+ # Displays the messages distribution across various partitions
72
+ #
73
+ # @param topic_name [String] topic we're interested in
74
+ #
75
+ # @note Because computing distribution is fairly expensive, we paginate this. While
76
+ # because of that results may not be exact, this allows us to support topics with
77
+ # many partitions.
78
+ def distribution(topic_name)
79
+ @topic = Models::Topic.find(topic_name)
80
+
81
+ @active_partitions, _materialized_page, @limited = Paginators::Partitions.call(
82
+ @topic.partition_count, @params.current_page
83
+ )
84
+
85
+ @aggregated, distribution = @topic.distribution(@active_partitions)
86
+
87
+ @distribution = refine(distribution)
88
+
89
+ next_page = @active_partitions.last < @topic.partition_count - 1
90
+ paginate(@params.current_page, next_page)
91
+
92
+ render
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,50 @@
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 extra libs used by the Pro UI components
19
+ module Lib
20
+ # Checks list of topics and tries to match them against the available patterns
21
+ # Uses the Pro detector to expand routes in the Web-UI so we include topics that are
22
+ # or will be matched using our regular expressions
23
+ #
24
+ # This code **needs** to run when using deserializers of messages from patterns.
25
+ # Otherwise default deserializer will be used instead.
26
+ class PatternsDetector
27
+ # Run the detection
28
+ def call
29
+ detector = ::Karafka::Pro::Routing::Features::Patterns::Detector.new
30
+ topics_names = Web::Ui::Models::ClusterInfo.topics.map(&:topic_name)
31
+
32
+ Karafka::App
33
+ .routes
34
+ .flat_map(&:subscription_groups)
35
+ .each do |subscription_group|
36
+ sg_topics = subscription_group.topics
37
+
38
+ # Reject topics that are already part of routing for given subscription groups
39
+ # and then for remaining try to apply patterns and expand routes
40
+ topics_names
41
+ .reject { |t_name| sg_topics.any? { |rtopic| rtopic.name == t_name } }
42
+ .each { |t_name| detector.expand(sg_topics, t_name) }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,29 @@
1
+ <li class="breadcrumb-item">
2
+ <a href="<%= root_path('cluster') %>">
3
+ Cluster informations
4
+ </a>
5
+ </li>
6
+
7
+ <% unless @partitions %>
8
+ <li class="breadcrumb-item">
9
+ <a href="<%= root_path('cluster') %>">
10
+ Brokers
11
+ </a>
12
+ </li>
13
+ <% end %>
14
+
15
+ <% if @broker %>
16
+ <li class="breadcrumb-item">
17
+ <a href="<%= root_path('cluster', @broker.id) %>">
18
+ <%= @broker.full_name %>
19
+ </a>
20
+ </li>
21
+ <% end %>
22
+
23
+ <% if @partitions %>
24
+ <li class="breadcrumb-item">
25
+ <a href="<%= root_path('cluster', 'replication') %>">
26
+ Replication
27
+ </a>
28
+ </li>
29
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <tr>
2
+ <td>
3
+ <a href="<%= root_path('cluster', broker.id) %>">
4
+ <%= broker.id %>
5
+ </a>
6
+ </td>
7
+ <td>
8
+ <a href="<%= root_path('cluster', broker.id) %>">
9
+ <%= broker.name %>
10
+ </a>
11
+ </td>
12
+ <td><%= broker.port %></td>
13
+ </tr>
@@ -0,0 +1,13 @@
1
+ <tr>
2
+ <td class="wrap-text">
3
+ <% all_names = ([config.name] + config.synonyms.map(&:name)).uniq %>
4
+ <% all_names.each do |name| %>
5
+ <%= name %>
6
+ <br/>
7
+ <% end %>
8
+ </td>
9
+ <td class="wrap-text"><%= config.value %></td>
10
+ <td><%= config.default? %></td>
11
+ <td><%= config.sensitive? %></td>
12
+ <td><%= config.read_only? %></td>
13
+ </tr>
@@ -0,0 +1,27 @@
1
+ <div class="container">
2
+ <div class="row mb-4">
3
+ <div class="col-sm-12">
4
+
5
+ <ul class="nav nav-tabs">
6
+ <li class="nav-item">
7
+ <a
8
+ class="nav-link <%= nav_class(end_with: 'cluster') %>"
9
+ href="<%= root_path('cluster') %>"
10
+ >
11
+ Brokers
12
+ </a>
13
+ </li>
14
+
15
+ <li class="nav-item">
16
+ <a
17
+ class="nav-link <%= nav_class(include: 'replication') %>"
18
+ href="<%= root_path('cluster', 'replication') %>"
19
+ >
20
+ Replication
21
+ </a>
22
+ </li>
23
+ </ul>
24
+
25
+ </div>
26
+ </div>
27
+ </div>
@@ -0,0 +1,27 @@
1
+ <%== view_title('Cluster Informations') %>
2
+
3
+ <%== partial 'cluster/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('Id', :broker_id) %></th>
12
+ <th><%== sort_link('Name', :broker_name) %></th>
13
+ <th><%== sort_link('Port', :broker_port) %></th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <%==
18
+ each_partial(
19
+ @brokers,
20
+ 'cluster/broker'
21
+ )
22
+ %>
23
+ </tbody>
24
+ </table>
25
+ </div>
26
+ </div>
27
+ </div>
@@ -0,0 +1,27 @@
1
+ <%== view_title('Cluster Informations', hr: false) %>
2
+
3
+ <%== partial 'cluster/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(:id) %></th>
12
+ <th><%== sort_link(:name) %></th>
13
+ <th><%== sort_link(:port) %></th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <%==
18
+ each_partial(
19
+ @brokers,
20
+ 'cluster/broker'
21
+ )
22
+ %>
23
+ </tbody>
24
+ </table>
25
+ </div>
26
+ </div>
27
+ </div>
@@ -0,0 +1,27 @@
1
+ <%== view_title(@broker.full_name, hr: true) %>
2
+
3
+ <div class="container mb-5">
4
+ <div class="row">
5
+ <div class="col-lg-12 table-responsive">
6
+ <table class="processes bg-white table table-hover table-bordered table-striped">
7
+ <thead>
8
+ <tr class="align-middle">
9
+ <th><%== sort_link(:name) %></th>
10
+ <th><%== sort_link(:value) %></th>
11
+ <th><%== sort_link(:default?) %></th>
12
+ <th><%== sort_link(:sensitive?) %></th>
13
+ <th><%== sort_link(:read_only?) %></th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <%==
18
+ each_partial(
19
+ @configs,
20
+ 'cluster/config'
21
+ )
22
+ %>
23
+ </tbody>
24
+ </table>
25
+ </div>
26
+ </div>
27
+ </div>
@@ -0,0 +1,20 @@
1
+ <div class="container">
2
+ <div class="row mb-4">
3
+ <div class="col-sm-12">
4
+ <h5 class="mb-2">
5
+ <%= backtrace[:label] %>
6
+ </h5>
7
+ <hr/>
8
+ </div>
9
+ </div>
10
+
11
+ <div class="row mb-5">
12
+ <div class="col-sm-12">
13
+ <div class="card">
14
+ <div class="card-body">
15
+ <pre class="m-0 p-0"><code class="wrapped json p-0 m-0"><%= backtrace[:backtrace] %></code></pre>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ </div>
@@ -0,0 +1,21 @@
1
+ <li class="breadcrumb-item">
2
+ <a href="<%= root_path('consumers/overview') %>">
3
+ Consumers
4
+ </a>
5
+ </li>
6
+
7
+ <% if current_path.include?('/commands') %>
8
+ <li class="breadcrumb-item">
9
+ <a href="<%= root_path('commands') %>">
10
+ Commands
11
+ </a>
12
+ </li>
13
+ <% end %>
14
+
15
+ <% if @command_message %>
16
+ <li class="breadcrumb-item">
17
+ <a href="<%= root_path('commands', @command_message.offset) %>">
18
+ <%= @command_message.offset %>
19
+ </a>
20
+ </li>
21
+ <% end %>