karafka-web 0.8.2 → 0.9.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (269) 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 +39 -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/karafka-web.gemspec +4 -2
  11. data/lib/karafka/web/app.rb +1 -1
  12. data/lib/karafka/web/config.rb +17 -0
  13. data/lib/karafka/web/contracts/config.rb +6 -0
  14. data/lib/karafka/web/management/actions/create_topics.rb +21 -0
  15. data/lib/karafka/web/management/actions/delete_topics.rb +1 -0
  16. data/lib/karafka/web/management/actions/enable.rb +11 -5
  17. data/lib/karafka/web/management/migrations/0_base.rb +1 -1
  18. data/lib/karafka/web/pro/commanding/commands/base.rb +33 -0
  19. data/lib/karafka/web/pro/commanding/commands/probe.rb +41 -0
  20. data/lib/karafka/web/pro/commanding/commands/quiet.rb +31 -0
  21. data/lib/karafka/web/pro/commanding/commands/stop.rb +31 -0
  22. data/lib/karafka/web/pro/commanding/config.rb +57 -0
  23. data/lib/karafka/web/pro/commanding/contracts/config.rb +60 -0
  24. data/lib/karafka/web/pro/commanding/dispatcher.rb +93 -0
  25. data/lib/karafka/web/pro/commanding/listener.rb +97 -0
  26. data/lib/karafka/web/pro/commanding/manager.rb +98 -0
  27. data/lib/karafka/web/pro/commanding/matcher.rb +50 -0
  28. data/lib/karafka/web/pro/commanding.rb +40 -0
  29. data/lib/karafka/web/pro/loader.rb +40 -0
  30. data/lib/karafka/web/{ui/pro → pro/ui}/app.rb +103 -22
  31. data/lib/karafka/web/{ui/pro/controllers/cluster.rb → pro/ui/controllers/base_controller.rb} +4 -5
  32. data/lib/karafka/web/pro/ui/controllers/cluster_controller.rb +54 -0
  33. data/lib/karafka/web/pro/ui/controllers/commanding_controller.rb +118 -0
  34. data/lib/karafka/web/pro/ui/controllers/commands_controller.rb +96 -0
  35. data/lib/karafka/web/{ui/pro/controllers/consumers.rb → pro/ui/controllers/consumers_controller.rb} +31 -4
  36. data/lib/karafka/web/{ui/pro/controllers/dashboard.rb → pro/ui/controllers/dashboard_controller.rb} +5 -3
  37. data/lib/karafka/web/pro/ui/controllers/dlq_controller.rb +60 -0
  38. data/lib/karafka/web/{ui/pro/controllers/errors.rb → pro/ui/controllers/errors_controller.rb} +5 -7
  39. data/lib/karafka/web/{ui/pro/controllers/explorer.rb → pro/ui/controllers/explorer_controller.rb} +24 -19
  40. data/lib/karafka/web/{ui/pro/controllers/health.rb → pro/ui/controllers/health_controller.rb} +16 -3
  41. data/lib/karafka/web/{ui/pro/controllers/jobs.rb → pro/ui/controllers/jobs_controller.rb} +4 -4
  42. data/lib/karafka/web/{ui/pro/controllers/messages.rb → pro/ui/controllers/messages_controller.rb} +8 -6
  43. data/lib/karafka/web/{ui/pro/controllers/routing.rb → pro/ui/controllers/routing_controller.rb} +6 -22
  44. data/lib/karafka/web/{ui/pro/controllers/status.rb → pro/ui/controllers/status_controller.rb} +3 -3
  45. data/lib/karafka/web/pro/ui/controllers/topics_controller.rb +99 -0
  46. data/lib/karafka/web/pro/ui/lib/patterns_detector.rb +50 -0
  47. data/lib/karafka/web/pro/ui/views/cluster/_breadcrumbs.erb +29 -0
  48. data/lib/karafka/web/pro/ui/views/cluster/_broker.erb +13 -0
  49. data/lib/karafka/web/pro/ui/views/cluster/_config.erb +13 -0
  50. data/lib/karafka/web/pro/ui/views/cluster/_tabs.erb +27 -0
  51. data/lib/karafka/web/pro/ui/views/cluster/brokers.erb +27 -0
  52. data/lib/karafka/web/pro/ui/views/cluster/index.erb +27 -0
  53. data/lib/karafka/web/pro/ui/views/cluster/show.erb +27 -0
  54. data/lib/karafka/web/pro/ui/views/commands/_backtrace.erb +20 -0
  55. data/lib/karafka/web/pro/ui/views/commands/_breadcrumbs.erb +21 -0
  56. data/lib/karafka/web/pro/ui/views/commands/_command.erb +60 -0
  57. data/lib/karafka/web/pro/ui/views/commands/_command_details.erb +11 -0
  58. data/lib/karafka/web/pro/ui/views/commands/_details.erb +26 -0
  59. data/lib/karafka/web/pro/ui/views/commands/_empty.erb +3 -0
  60. data/lib/karafka/web/pro/ui/views/commands/_incompatible_schema.erb +14 -0
  61. data/lib/karafka/web/pro/ui/views/commands/_metadata.erb +50 -0
  62. data/lib/karafka/web/pro/ui/views/commands/_table.erb +23 -0
  63. data/lib/karafka/web/pro/ui/views/commands/index.erb +17 -0
  64. data/lib/karafka/web/pro/ui/views/commands/show.erb +38 -0
  65. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/_breadcrumbs.erb +20 -4
  66. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/_consumer.erb +2 -21
  67. data/lib/karafka/web/pro/ui/views/consumers/_consumer_controls.erb +78 -0
  68. data/lib/karafka/web/pro/ui/views/consumers/_consumer_performance.erb +59 -0
  69. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/_counters.erb +7 -5
  70. data/lib/karafka/web/pro/ui/views/consumers/_tabs.erb +35 -0
  71. data/lib/karafka/web/pro/ui/views/consumers/consumer/_commands.erb +32 -0
  72. data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_jobs.erb +7 -0
  73. data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_subscriptions.erb +7 -0
  74. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_subscription_group.erb +13 -8
  75. data/lib/karafka/web/pro/ui/views/consumers/consumer/_title.erb +5 -0
  76. data/lib/karafka/web/pro/ui/views/consumers/controls.erb +67 -0
  77. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/details.erb +6 -1
  78. data/lib/karafka/web/pro/ui/views/consumers/index.erb +39 -0
  79. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/pending_jobs.erb +15 -7
  80. data/lib/karafka/web/pro/ui/views/consumers/performance.erb +52 -0
  81. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/running_jobs.erb +15 -7
  82. data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/subscriptions.erb +6 -1
  83. data/lib/karafka/web/{ui/pro → pro/ui}/views/dashboard/index.erb +10 -10
  84. data/lib/karafka/web/pro/ui/views/dlq/_no_topics.erb +7 -0
  85. data/lib/karafka/web/{ui/pro → pro/ui}/views/dlq/index.erb +1 -1
  86. data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_error.erb +2 -6
  87. data/lib/karafka/web/pro/ui/views/errors/_table.erb +23 -0
  88. data/lib/karafka/web/pro/ui/views/explorer/_failed_deserialization.erb +4 -0
  89. data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_message.erb +7 -1
  90. data/lib/karafka/web/pro/ui/views/explorer/_no_topics.erb +5 -0
  91. data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/index.erb +1 -6
  92. data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_metadata.erb +33 -9
  93. data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_payload.erb +4 -4
  94. data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_payload_actions.erb +1 -1
  95. data/lib/karafka/web/pro/ui/views/explorer/messages/_headers.erb +33 -0
  96. data/lib/karafka/web/pro/ui/views/explorer/messages/_key.erb +20 -0
  97. data/lib/karafka/web/pro/ui/views/explorer/partition/_cleaned.erb +5 -0
  98. data/lib/karafka/web/pro/ui/views/explorer/partition/_empty.erb +5 -0
  99. data/lib/karafka/web/pro/ui/views/explorer/partition/_messages.erb +21 -0
  100. data/lib/karafka/web/pro/ui/views/explorer/topic/_empty.erb +5 -0
  101. data/lib/karafka/web/pro/ui/views/explorer/topic/_limited.erb +10 -0
  102. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_breadcrumbs.erb +8 -0
  103. data/lib/karafka/web/pro/ui/views/health/_no_data.erb +7 -0
  104. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition.erb +1 -1
  105. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition_lags.erb +6 -3
  106. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_tabs.erb +11 -1
  107. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/changes.erb +13 -8
  108. data/lib/karafka/web/pro/ui/views/health/cluster_lags.erb +54 -0
  109. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/lags.erb +14 -8
  110. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/offsets.erb +15 -12
  111. data/lib/karafka/web/{ui/pro → pro/ui}/views/health/overview.erb +21 -7
  112. data/lib/karafka/web/{ui/pro → pro/ui}/views/jobs/_job.erb +1 -1
  113. data/lib/karafka/web/pro/ui/views/jobs/_no_jobs.erb +7 -0
  114. data/lib/karafka/web/{ui/pro → pro/ui}/views/jobs/pending.erb +12 -8
  115. data/lib/karafka/web/{ui/pro → pro/ui}/views/jobs/running.erb +12 -8
  116. data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/_consumer_group.erb +2 -2
  117. data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/index.erb +1 -1
  118. data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/show.erb +1 -1
  119. data/lib/karafka/web/{ui/pro → pro/ui}/views/shared/_navigation.erb +14 -0
  120. data/lib/karafka/web/pro/ui/views/topics/_breadcrumbs.erb +37 -0
  121. data/lib/karafka/web/pro/ui/views/topics/_partition.erb +16 -0
  122. data/lib/karafka/web/pro/ui/views/topics/_tabs.erb +37 -0
  123. data/lib/karafka/web/pro/ui/views/topics/_topic.erb +12 -0
  124. data/lib/karafka/web/pro/ui/views/topics/config.erb +29 -0
  125. data/lib/karafka/web/pro/ui/views/topics/distribution/_badges.erb +7 -0
  126. data/lib/karafka/web/pro/ui/views/topics/distribution/_chart.erb +2 -0
  127. data/lib/karafka/web/pro/ui/views/topics/distribution/_empty_partitions.erb +1 -0
  128. data/lib/karafka/web/pro/ui/views/topics/distribution/_limited.erb +10 -0
  129. data/lib/karafka/web/pro/ui/views/topics/distribution/_partition.erb +10 -0
  130. data/lib/karafka/web/pro/ui/views/topics/distribution.erb +47 -0
  131. data/lib/karafka/web/pro/ui/views/topics/index.erb +16 -0
  132. data/lib/karafka/web/pro/ui/views/topics/replication.erb +28 -0
  133. data/lib/karafka/web/processing/consumers/aggregators/base.rb +1 -1
  134. data/lib/karafka/web/processing/consumers/aggregators/metrics.rb +1 -1
  135. data/lib/karafka/web/processing/consumers/aggregators/state.rb +4 -4
  136. data/lib/karafka/web/tracking/consumers/contracts/report.rb +1 -1
  137. data/lib/karafka/web/tracking/consumers/listeners/booting.rb +3 -1
  138. data/lib/karafka/web/tracking/consumers/listeners/errors.rb +2 -2
  139. data/lib/karafka/web/tracking/consumers/reporter.rb +3 -3
  140. data/lib/karafka/web/tracking/consumers/sampler.rb +2 -2
  141. data/lib/karafka/web/tracking/contracts/error.rb +1 -1
  142. data/lib/karafka/web/tracking/producers/listeners/booting.rb +3 -1
  143. data/lib/karafka/web/tracking/producers/listeners/errors.rb +2 -2
  144. data/lib/karafka/web/tracking/producers/reporter.rb +1 -1
  145. data/lib/karafka/web/tracking/producers/sampler.rb +1 -1
  146. data/lib/karafka/web/tracking/sampler.rb +3 -3
  147. data/lib/karafka/web/ui/app.rb +13 -9
  148. data/lib/karafka/web/ui/base.rb +1 -0
  149. data/lib/karafka/web/ui/controllers/{base.rb → base_controller.rb} +15 -2
  150. data/lib/karafka/web/ui/controllers/{become_pro.rb → become_pro_controller.rb} +1 -1
  151. data/lib/karafka/web/ui/controllers/{cluster.rb → cluster_controller.rb} +4 -4
  152. data/lib/karafka/web/ui/controllers/{consumers.rb → consumers_controller.rb} +3 -3
  153. data/lib/karafka/web/ui/controllers/{dashboard.rb → dashboard_controller.rb} +1 -1
  154. data/lib/karafka/web/ui/controllers/{errors.rb → errors_controller.rb} +2 -2
  155. data/lib/karafka/web/ui/controllers/{jobs.rb → jobs_controller.rb} +5 -5
  156. data/lib/karafka/web/ui/controllers/{routing.rb → routing_controller.rb} +2 -2
  157. data/lib/karafka/web/ui/controllers/{status.rb → status_controller.rb} +1 -1
  158. data/lib/karafka/web/ui/helpers/alerts_helper.rb +23 -0
  159. data/lib/karafka/web/ui/helpers/application_helper.rb +53 -1
  160. data/lib/karafka/web/ui/lib/paginations/offset_based.rb +3 -4
  161. data/lib/karafka/web/ui/lib/safe_runner.rb +59 -0
  162. data/lib/karafka/web/ui/models/broker.rb +66 -0
  163. data/lib/karafka/web/ui/models/health.rb +28 -2
  164. data/lib/karafka/web/ui/models/message.rb +9 -3
  165. data/lib/karafka/web/ui/models/process.rb +10 -5
  166. data/lib/karafka/web/ui/models/processes.rb +2 -2
  167. data/lib/karafka/web/ui/models/topic.rb +78 -0
  168. data/lib/karafka/web/ui/public/javascripts/application.js +18 -1
  169. data/lib/karafka/web/ui/public/javascripts/charts/data_formatting_utility.js +71 -0
  170. data/lib/karafka/web/ui/public/javascripts/charts/dataset_state_manager.js +49 -0
  171. data/lib/karafka/web/ui/public/javascripts/charts/types/bar.js +123 -0
  172. data/lib/karafka/web/ui/public/javascripts/charts/types/line.js +143 -0
  173. data/lib/karafka/web/ui/public/javascripts/charts.js +10 -325
  174. data/lib/karafka/web/ui/public/javascripts/live_poll.js +5 -5
  175. data/lib/karafka/web/ui/public/javascripts/tabs_manager.js +57 -0
  176. data/lib/karafka/web/ui/public/stylesheets/application.css +7 -6
  177. data/lib/karafka/web/ui/views/cluster/_breadcrumbs.erb +3 -3
  178. data/lib/karafka/web/ui/views/cluster/_no_partitions.erb +1 -3
  179. data/lib/karafka/web/ui/views/cluster/_tabs.erb +3 -3
  180. data/lib/karafka/web/ui/views/cluster/brokers.erb +19 -19
  181. data/lib/karafka/web/ui/views/cluster/replication.erb +37 -0
  182. data/lib/karafka/web/ui/views/consumers/_assignments_badges.erb +24 -0
  183. data/lib/karafka/web/ui/views/consumers/_consumer.erb +2 -15
  184. data/lib/karafka/web/ui/views/consumers/_counters.erb +1 -1
  185. data/lib/karafka/web/ui/views/consumers/_summary.erb +5 -5
  186. data/lib/karafka/web/ui/views/consumers/index.erb +22 -20
  187. data/lib/karafka/web/ui/views/dashboard/index.erb +9 -9
  188. data/lib/karafka/web/ui/views/errors/_cleaned.erb +1 -3
  189. data/lib/karafka/web/ui/views/errors/_error.erb +2 -6
  190. data/lib/karafka/web/ui/views/errors/_no_errors.erb +1 -3
  191. data/lib/karafka/web/ui/views/errors/index.erb +22 -20
  192. data/lib/karafka/web/ui/views/jobs/_job.erb +4 -1
  193. data/lib/karafka/web/ui/views/jobs/_no_jobs.erb +1 -3
  194. data/lib/karafka/web/ui/views/jobs/pending.erb +4 -3
  195. data/lib/karafka/web/ui/views/jobs/running.erb +4 -3
  196. data/lib/karafka/web/ui/views/routing/_consumer_group.erb +2 -2
  197. data/lib/karafka/web/ui/views/routing/index.erb +1 -1
  198. data/lib/karafka/web/ui/views/routing/show.erb +1 -1
  199. data/lib/karafka/web/ui/views/shared/_become_pro.erb +3 -3
  200. data/lib/karafka/web/ui/views/shared/_header.erb +16 -10
  201. data/lib/karafka/web/ui/views/shared/_navigation.erb +17 -3
  202. data/lib/karafka/web/ui/views/shared/_not_a_message.erb +5 -0
  203. data/lib/karafka/web/ui/views/shared/alerts/_info.erb +3 -0
  204. data/lib/karafka/web/ui/views/shared/charts/_bar.erb +7 -0
  205. data/lib/karafka/web/ui/views/shared/{_chart.erb → charts/_line.erb} +1 -1
  206. data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +1 -1
  207. data/lib/karafka/web/ui/views/status/show.erb +1 -1
  208. data/lib/karafka/web/version.rb +1 -1
  209. data/lib/karafka/web.rb +17 -1
  210. data.tar.gz.sig +0 -0
  211. metadata +189 -120
  212. metadata.gz.sig +0 -0
  213. data/lib/karafka/web/ui/pro/controllers/dlq.rb +0 -43
  214. data/lib/karafka/web/ui/pro/views/consumers/consumer/_no_jobs.erb +0 -9
  215. data/lib/karafka/web/ui/pro/views/consumers/consumer/_no_subscriptions.erb +0 -9
  216. data/lib/karafka/web/ui/pro/views/consumers/index.erb +0 -36
  217. data/lib/karafka/web/ui/pro/views/dlq/_no_topics.erb +0 -9
  218. data/lib/karafka/web/ui/pro/views/errors/_table.erb +0 -21
  219. data/lib/karafka/web/ui/pro/views/explorer/_failed_deserialization.erb +0 -4
  220. data/lib/karafka/web/ui/pro/views/explorer/_no_topics.erb +0 -7
  221. data/lib/karafka/web/ui/pro/views/explorer/messages/_headers.erb +0 -15
  222. data/lib/karafka/web/ui/pro/views/explorer/messages/_key.erb +0 -12
  223. data/lib/karafka/web/ui/pro/views/explorer/partition/_cleaned.erb +0 -3
  224. data/lib/karafka/web/ui/pro/views/explorer/partition/_empty.erb +0 -3
  225. data/lib/karafka/web/ui/pro/views/explorer/partition/_messages.erb +0 -19
  226. data/lib/karafka/web/ui/pro/views/explorer/topic/_empty.erb +0 -3
  227. data/lib/karafka/web/ui/pro/views/explorer/topic/_limited.erb +0 -4
  228. data/lib/karafka/web/ui/pro/views/health/_no_data.erb +0 -9
  229. data/lib/karafka/web/ui/pro/views/jobs/_no_jobs.erb +0 -9
  230. data/lib/karafka/web/ui/public/javascripts/tabs.js +0 -59
  231. data/lib/karafka/web/ui/views/cluster/topics.erb +0 -35
  232. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_consumer_group.erb +0 -0
  233. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_job.erb +0 -0
  234. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_metrics.erb +0 -0
  235. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_partition.erb +0 -0
  236. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_stopped.erb +0 -0
  237. /data/lib/karafka/web/{ui/pro → pro/ui}/views/consumers/consumer/_tabs.erb +0 -0
  238. /data/lib/karafka/web/{ui/pro → pro/ui}/views/dlq/_breadcrumbs.erb +0 -0
  239. /data/lib/karafka/web/{ui/pro → pro/ui}/views/dlq/_topic.erb +0 -0
  240. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_breadcrumbs.erb +0 -0
  241. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_partition_option.erb +0 -0
  242. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/_title_with_select.erb +0 -0
  243. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/index.erb +0 -0
  244. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/partition.erb +0 -0
  245. /data/lib/karafka/web/{ui/pro → pro/ui}/views/errors/show.erb +0 -0
  246. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_breadcrumbs.erb +0 -0
  247. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_filtered.erb +0 -0
  248. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_partition_option.erb +0 -0
  249. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/_topic.erb +0 -0
  250. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/message/_message_actions.erb +0 -0
  251. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/messages/_detail.erb +0 -0
  252. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/partition/_details.erb +0 -0
  253. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/partition.erb +0 -0
  254. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/show.erb +0 -0
  255. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/topic/_details.erb +0 -0
  256. /data/lib/karafka/web/{ui/pro → pro/ui}/views/explorer/topic.erb +0 -0
  257. /data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_consumer_group_header.erb +0 -0
  258. /data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition_offset.erb +0 -0
  259. /data/lib/karafka/web/{ui/pro → pro/ui}/views/health/_partition_times.erb +0 -0
  260. /data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/_detail.erb +0 -0
  261. /data/lib/karafka/web/{ui/pro → pro/ui}/views/routing/_topic.erb +0 -0
  262. /data/lib/karafka/web/ui/public/javascripts/{bootstrap.min.js → libs/bootstrap.min.js} +0 -0
  263. /data/lib/karafka/web/ui/public/javascripts/{chart.min.js → libs/chart.min.js} +0 -0
  264. /data/lib/karafka/web/ui/public/javascripts/{datepicker.js → libs/datepicker.js} +0 -0
  265. /data/lib/karafka/web/ui/public/javascripts/{highlight.min.js → libs/highlight.min.js} +0 -0
  266. /data/lib/karafka/web/ui/public/javascripts/{timeago.min.js → libs/timeago.min.js} +0 -0
  267. /data/lib/karafka/web/ui/public/stylesheets/{bootstrap.min.css → libs/bootstrap.min.css} +0 -0
  268. /data/lib/karafka/web/ui/public/stylesheets/{datepicker.min.css → libs/datepicker.min.css} +0 -0
  269. /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 %>