karafka-web 0.8.2 → 0.9.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
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,67 @@
1
+ <%== view_title('Consumers Controls') %>
2
+
3
+ <%== partial 'consumers/tabs' %>
4
+
5
+ <% unless @processes.empty? %>
6
+ <div class="container">
7
+ <div class="row mb-4">
8
+ <div class="col-sm-12">
9
+ <div class="d-flex flex-nowrap float-end">
10
+ <%
11
+ quiet_all_path = root_path('commanding', 'quiet_all')
12
+ %>
13
+ <form action="<%= quiet_all_path %>" method="post" class="d-inline-flex align-items-center mx-1">
14
+ <%== csrf_tag(quiet_all_path) %>
15
+ <input type="submit" value="&#x23F8; Quiet All" class="btn btn-warning btn-sm"/>
16
+ </form>
17
+
18
+ <%
19
+ stop_all_path = root_path('commanding', 'stop_all')
20
+ %>
21
+ <form action="<%= stop_all_path %>" method="post" class="d-inline-flex align-items-center mx-1">
22
+ <%== csrf_tag(stop_all_path) %>
23
+ <input type="submit" value="&#x25A0; Stop All" class="btn btn-danger btn-sm"/>
24
+ </form>
25
+ </div>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ <% end %>
30
+
31
+ <div class="container">
32
+ <div class="row">
33
+ <div class="col-sm-12">
34
+ <% if @processes.empty? && params.current_page <= 1 %>
35
+ <%== partial 'consumers/no_consumers' %>
36
+ <% elsif @processes.empty? %>
37
+ <%== partial 'shared/no_paginated_data' %>
38
+ <% else %>
39
+ <div class="table-responsive">
40
+ <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
41
+ <thead>
42
+ <tr class="align-middle">
43
+ <th><%== sort_link(:id) %></th>
44
+ <th><%== sort_link(:status) %></th>
45
+ <th>Subscriptions</th>
46
+ <th><%== sort_link(:started_at, rev: true) %></th>
47
+ <th><%== sort_link(:memory_usage) %></th>
48
+ <th>Performance</th>
49
+ <th><%== sort_link(:lag_hybrid) %></th>
50
+ <th></th>
51
+ </tr>
52
+ </thead>
53
+ <tbody>
54
+ <%==
55
+ render_each(
56
+ @processes,
57
+ 'consumers/_consumer_controls',
58
+ local: :process
59
+ )
60
+ %>
61
+ </tbody>
62
+ </table>
63
+ </div>
64
+ <% end %>
65
+ </div>
66
+ </div>
67
+ </div>
@@ -1,4 +1,9 @@
1
- <%== view_title(@process.name) %>
1
+ <div class="container mb-5">
2
+ <div class="row">
3
+ <%== partial 'consumers/consumer/title' %>
4
+ <%== partial 'consumers/consumer/commands', locals: { process: @process } %>
5
+ </div>
6
+ </div>
2
7
 
3
8
  <% if @process.status == 'stopped' %>
4
9
  <%== partial 'consumers/consumer/stopped' %>
@@ -0,0 +1,39 @@
1
+ <%== partial 'consumers/counters' %>
2
+ <%== partial 'consumers/summary' %>
3
+ <%== partial 'consumers/tabs' %>
4
+
5
+ <div class="container">
6
+ <div class="row">
7
+ <div class="col-sm-12">
8
+ <% if @processes.empty? && params.current_page <= 1 %>
9
+ <%== partial 'consumers/no_consumers' %>
10
+ <% elsif @processes.empty? %>
11
+ <%== partial 'shared/no_paginated_data' %>
12
+ <% else %>
13
+ <div class="table-responsive">
14
+ <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
15
+ <thead>
16
+ <tr class="align-middle">
17
+ <th><%== sort_link(:id) %></th>
18
+ <th class="col-sm-2"><%== sort_link(:started_at, rev: true) %></th>
19
+ <th class="col-sm-1">Memory</th>
20
+ <th class="col-sm-1">Performance</th>
21
+ <th class="col-sm-1">Load</th>
22
+ <th class="col-sm-1"><%== sort_link(:lag_hybrid) %></th>
23
+ </tr>
24
+ </thead>
25
+ <tbody>
26
+ <%==
27
+ render_each(
28
+ @processes,
29
+ 'consumers/_consumer',
30
+ local: :process
31
+ )
32
+ %>
33
+ </tbody>
34
+ </table>
35
+ </div>
36
+ <% end %>
37
+ </div>
38
+ </div>
39
+ </div>
@@ -1,4 +1,9 @@
1
- <%== view_title(@process.name) %>
1
+ <div class="container mb-5">
2
+ <div class="row">
3
+ <%== partial 'consumers/consumer/title' %>
4
+ <%== partial 'consumers/consumer/commands', locals: { process: @process } %>
5
+ </div>
6
+ </div>
2
7
 
3
8
  <% if @process.status == 'stopped' %>
4
9
  <%== partial 'consumers/consumer/stopped' %>
@@ -13,18 +18,21 @@
13
18
  <% else %>
14
19
  <div class="container">
15
20
  <div class="row mb-5">
16
- <div class="col-sm-12">
21
+ <div class="col-sm-12 table-responsive">
17
22
  <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
18
23
  <thead>
19
24
  <tr class="align-middle">
20
- <th><%== sort_link(:topic) %></th>
21
- <th><%== sort_link(:consumer) %></th>
22
- <th><%== sort_link(:type) %></th>
23
- <th><%== sort_link(:messages) %></th>
25
+ <th rowspan="2"><%== sort_link(:topic) %></th>
26
+ <th rowspan="2"><%== sort_link(:consumer) %></th>
27
+ <th rowspan="2"><%== sort_link(:type) %></th>
28
+ <th rowspan="2"><%== sort_link(:messages) %></th>
29
+ <th colspan="3" class="text-center">Offsets</th>
30
+ <th rowspan="2"><%== sort_link('Started', :updated_at, rev: true) %></th>
31
+ </tr>
32
+ <tr class="align-middle">
24
33
  <th><%== sort_link(:first_offset) %></th>
25
34
  <th><%== sort_link(:last_offset) %></th>
26
35
  <th><%== sort_link(:committed_offset) %></th>
27
- <th><%== sort_link('Scheduled at', :updated_at, rev: true) %></th>
28
36
  </tr>
29
37
  </thead>
30
38
  <tbody>
@@ -0,0 +1,52 @@
1
+ <%== view_title('Consumers Performance Details') %>
2
+
3
+ <%== partial 'consumers/tabs' %>
4
+
5
+ <div class="container">
6
+ <div class="row">
7
+ <div class="col-sm-12">
8
+ <% if @processes.empty? && params.current_page <= 1 %>
9
+ <%== partial 'consumers/no_consumers' %>
10
+ <% elsif @processes.empty? %>
11
+ <%== partial 'shared/no_paginated_data' %>
12
+ <% else %>
13
+ <div class="table-responsive">
14
+ <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
15
+ <thead>
16
+ <tr class="align-middle">
17
+ <th colspan="1" rowspan="2"><%== sort_link(:id) %></th>
18
+ <th colspan="1" rowspan="2"><%== sort_link(:memory_usage) %></th>
19
+ <th colspan="1" rowspan="2"><%== sort_link(:utilization) %></th>
20
+ <th colspan="1" rowspan="2"><%== sort_link(:threads) %></th>
21
+ <th colspan="3" rowspan="1" class="text-center">Load</th>
22
+ <th colspan="2" class="text-center">Workers</th>
23
+ <th colspan="2" class="text-center">Listeners</th>
24
+ <th colspan="2" class="text-center">Jobs</th>
25
+ </tr>
26
+ <tr class="align-middle">
27
+ <th>1m</th>
28
+ <th>5m</th>
29
+ <th>15m</th>
30
+ <th><%== sort_link('Total', :workers) %></th>
31
+ <th><%== sort_link(:busy) %></th>
32
+ <th><%== sort_link(:active) %></th>
33
+ <th><%== sort_link(:standby) %></th>
34
+ <th><%== sort_link('Running', :running_jobs_count) %></th>
35
+ <th><%== sort_link('Pending', :pending_jobs_count) %></th>
36
+ </tr>
37
+ </thead>
38
+ <tbody>
39
+ <%==
40
+ render_each(
41
+ @processes,
42
+ 'consumers/_consumer_performance',
43
+ local: :process
44
+ )
45
+ %>
46
+ </tbody>
47
+ </table>
48
+ </div>
49
+ <% end %>
50
+ </div>
51
+ </div>
52
+ </div>
@@ -1,4 +1,9 @@
1
- <%== view_title(@process.name) %>
1
+ <div class="container mb-5">
2
+ <div class="row">
3
+ <%== partial 'consumers/consumer/title' %>
4
+ <%== partial 'consumers/consumer/commands', locals: { process: @process } %>
5
+ </div>
6
+ </div>
2
7
 
3
8
  <% if @process.status == 'stopped' %>
4
9
  <%== partial 'consumers/consumer/stopped' %>
@@ -13,18 +18,21 @@
13
18
  <% else %>
14
19
  <div class="container">
15
20
  <div class="row mb-5">
16
- <div class="col-sm-12">
21
+ <div class="col-sm-12 table-responsive">
17
22
  <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
18
23
  <thead>
19
24
  <tr class="align-middle">
20
- <th><%== sort_link(:topic) %></th>
21
- <th><%== sort_link(:consumer) %></th>
22
- <th><%== sort_link(:type) %></th>
23
- <th><%== sort_link(:messages) %></th>
25
+ <th rowspan="2"><%== sort_link(:topic) %></th>
26
+ <th rowspan="2"><%== sort_link(:consumer) %></th>
27
+ <th rowspan="2"><%== sort_link(:type) %></th>
28
+ <th rowspan="2"><%== sort_link(:messages) %></th>
29
+ <th colspan="3" class="text-center">Offsets</th>
30
+ <th rowspan="2"><%== sort_link('Started', :updated_at, rev: true) %></th>
31
+ </tr>
32
+ <tr class="align-middle">
24
33
  <th><%== sort_link(:first_offset) %></th>
25
34
  <th><%== sort_link(:last_offset) %></th>
26
35
  <th><%== sort_link(:committed_offset) %></th>
27
- <th><%== sort_link('Started at', :updated_at, rev: true) %></th>
28
36
  </tr>
29
37
  </thead>
30
38
  <tbody>
@@ -1,4 +1,9 @@
1
- <%== view_title(@process.name) %>
1
+ <div class="container mb-5">
2
+ <div class="row">
3
+ <%== partial 'consumers/consumer/title' %>
4
+ <%== partial 'consumers/consumer/commands', locals: { process: @process } %>
5
+ </div>
6
+ </div>
2
7
 
3
8
  <% if @process.status == 'stopped' %>
4
9
  <%== partial 'consumers/consumer/stopped' %>
@@ -3,7 +3,7 @@
3
3
  <% if @aggregated.sufficient? %>
4
4
  <%== partial 'dashboard/ranges_selector' %>
5
5
 
6
- <div class="container">
6
+ <div class="container mb-3 mt-4 mt-md-2 mt-lg-0">
7
7
  <div class="row">
8
8
  <div class="col-sm-12">
9
9
  <h5 class="mb-3">Processing metrics</h5>
@@ -21,24 +21,24 @@
21
21
  <div class="tab-content">
22
22
  <div class="tab-pane show active" id="messages" role="tabpanel">
23
23
  <% data = @aggregated_charts.with(:messages, :errors, :dead, :retries, :batch_size) %>
24
- <%== partial 'shared/chart', locals: { data: data, id: 'messages' } %>
24
+ <%== partial 'shared/charts/line', locals: { data: data, id: 'messages' } %>
25
25
  </div>
26
26
 
27
27
  <div class="tab-pane" id="batches" role="tabpanel">
28
28
  <% data = @aggregated_charts.with(:batches, :errors, :dead, :retries) %>
29
- <%== partial 'shared/chart', locals: { data: data, id: 'batches' } %>
29
+ <%== partial 'shared/charts/line', locals: { data: data, id: 'batches' } %>
30
30
  </div>
31
31
 
32
32
  <div class="tab-pane" id="topics-lags" role="tabpanel">
33
- <%== partial 'shared/chart', locals: { data: @topics_charts.lags_hybrid, id: 'topics-lags' } %>
33
+ <%== partial 'shared/charts/line', locals: { data: @topics_charts.lags_hybrid, id: 'topics-lags' } %>
34
34
  </div>
35
35
 
36
36
  <div class="tab-pane" id="topics-pace" role="tabpanel">
37
- <%== partial 'shared/chart', locals: { data: @topics_charts.topics_pace, id: 'topics-pace' } %>
37
+ <%== partial 'shared/charts/line', locals: { data: @topics_charts.topics_pace, id: 'topics-pace' } %>
38
38
  </div>
39
39
 
40
40
  <div class="tab-pane" id="max-lso-time" role="tabpanel">
41
- <%== partial 'shared/chart', locals: { data: @topics_charts.max_lso_time, id: 'max-lso-time' } %>
41
+ <%== partial 'shared/charts/line', locals: { data: @topics_charts.max_lso_time, id: 'max-lso-time' } %>
42
42
  </div>
43
43
  </div>
44
44
  </div>
@@ -62,22 +62,22 @@
62
62
  <div class="tab-content">
63
63
  <div class="tab-pane show active" id="utilization" role="tabpanel">
64
64
  <% data = @aggregated_charts.with(:utilization) %>
65
- <%== partial 'shared/chart', locals: { data: data, id: 'utilization', label_type_y: 'percentage' } %>
65
+ <%== partial 'shared/charts/line', locals: { data: data, id: 'utilization', label_type_y: 'percentage' } %>
66
66
  </div>
67
67
 
68
68
  <div class="tab-pane show" id="rss" role="tabpanel">
69
69
  <% data = @aggregated_charts.with(:rss, :process_rss) %>
70
- <%== partial 'shared/chart', locals: { data: data, id: 'rss', label_type_y: 'memory' } %>
70
+ <%== partial 'shared/charts/line', locals: { data: data, id: 'rss', label_type_y: 'memory' } %>
71
71
  </div>
72
72
 
73
73
  <div class="tab-pane show" id="concurrency" role="tabpanel">
74
74
  <% data = @aggregated_charts.with(:processes, :workers, :active_listeners, :standby_listeners) %>
75
- <%== partial 'shared/chart', locals: { data: data, id: 'concurrency' } %>
75
+ <%== partial 'shared/charts/line', locals: { data: data, id: 'concurrency' } %>
76
76
  </div>
77
77
 
78
78
  <div class="tab-pane show" id="data-transfers" role="tabpanel">
79
79
  <% data = @aggregated_charts.data_transfers %>
80
- <%== partial 'shared/chart', locals: { data: data, id: 'data-transfers', label_type_y: 'memory' } %>
80
+ <%== partial 'shared/charts/line', locals: { data: data, id: 'data-transfers', label_type_y: 'memory' } %>
81
81
  </div>
82
82
  </div>
83
83
  </div>
@@ -0,0 +1,7 @@
1
+ <div class="container mb-4">
2
+ <div class="row">
3
+ <div class="col-lg-12">
4
+ <%== alert_info('No Dead Letter Queue topics exist in Kafka.') %>
5
+ </div>
6
+ </div>
7
+ </div>
@@ -1,4 +1,4 @@
1
- <%== view_title('Dead Letter Queue topics', hr: true) %>
1
+ <%== view_title('Dead Letter Queue Topics', hr: true) %>
2
2
 
3
3
  <% if @dlq_topics.empty? %>
4
4
  <%== partial 'dlq/no_topics' %>
@@ -1,9 +1,5 @@
1
1
  <% if error_msg.is_a?(Array) %>
2
- <tr>
3
- <td colspan="5" class="text-center text-muted">
4
- This offset does not contain error data. The message may have been compacted or is a system entry.
5
- </td>
6
- </tr>
2
+ <%== partial 'shared/not_a_message' %>
7
3
  <% else %>
8
4
  <% error = error_msg.payload %>
9
5
 
@@ -18,7 +14,7 @@
18
14
  </span>
19
15
  </td>
20
16
  <td>
21
- <%== error[:process][:name] %>
17
+ <%== error[:process][:id] %>
22
18
  </td>
23
19
  <td>
24
20
  <%= error[:error_class] %>:
@@ -0,0 +1,23 @@
1
+ <div class="table-responsive">
2
+ <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
3
+ <thead>
4
+ <tr class="align-middle">
5
+ <th>Origin</th>
6
+ <th>ID</th>
7
+ <th>Error</th>
8
+ <th>Occurred</th>
9
+ <th></th>
10
+ </tr>
11
+ </thead>
12
+
13
+ <tbody>
14
+ <%==
15
+ each_partial(
16
+ @error_messages,
17
+ 'errors/error',
18
+ local: :error_msg
19
+ )
20
+ %>
21
+ </tbody>
22
+ </table>
23
+ </div>
@@ -0,0 +1,4 @@
1
+ <div class="alert alert-warning" role="alert">
2
+ We could not deserialize the <%= attribute %> due to the following error:
3
+ <code><%= error.class %></code>. Raw <%= attribute %> displayed instead.
4
+ </div>
@@ -1,3 +1,5 @@
1
+ <% safe_key = ::Karafka::Web::Ui::Lib::SafeRunner.new { message.key } %>
2
+
1
3
  <% if message.is_a?(Array) %>
2
4
  <tr>
3
5
  <td class="text-muted">
@@ -23,7 +25,11 @@
23
25
  </td>
24
26
  <td>
25
27
  <% if @visibility_filter.key?(message) %>
26
- <%= message.key %>
28
+ <% if safe_key.success? %>
29
+ <%= safe_key.result %>
30
+ <% else %>
31
+ <span class="text-muted">[Deserialization Failed]</span>
32
+ <% end %>
27
33
  <% else %>
28
34
  <span class="text-muted">[Filtered]</span>
29
35
  <% end %>
@@ -0,0 +1,5 @@
1
+ <div class="row">
2
+ <div class="col-lg-12">
3
+ <%== alert_info('There are no available topics in the current cluster.') %>
4
+ </div>
5
+ </div>
@@ -1,9 +1,4 @@
1
- <div class="container mb-5">
2
- <div class="row">
3
- <h3>Explorer</h3>
4
- </div>
5
- <hr>
6
- </div>
1
+ <%== view_title('Explorer', hr: true) %>
7
2
 
8
3
  <div class="container">
9
4
  <% if @topics.empty? %>
@@ -1,8 +1,39 @@
1
+ <% if @safe_key.failure? %>
2
+ <%==
3
+ partial(
4
+ 'explorer/failed_deserialization',
5
+ locals: {
6
+ attribute: 'key',
7
+ error: @safe_key.error
8
+ }
9
+ )
10
+ %>
11
+ <% end %>
12
+
13
+ <% if @safe_headers.failure? %>
14
+ <%==
15
+ partial(
16
+ 'explorer/failed_deserialization',
17
+ locals: {
18
+ attribute: 'headers',
19
+ error: @safe_headers.error
20
+ }
21
+ )
22
+ %>
23
+ <% end %>
24
+
1
25
  <div class="row mb-5">
2
- <div class="col-sm-12">
26
+ <div class="col-sm-12 table-responsive">
3
27
  <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
4
28
  <tbody>
5
- <% @message.metadata.to_h.except(:received_at, :key, :headers).each do |k, v| %>
29
+ <%==
30
+ partial(
31
+ 'explorer/messages/key',
32
+ locals: { message: @message }
33
+ )
34
+ %>
35
+
36
+ <% @message.metadata.to_h.except(:received_at, :raw_key, :raw_headers, :message).each do |k, v| %>
6
37
  <%==
7
38
  partial(
8
39
  'explorer/messages/detail',
@@ -24,13 +55,6 @@
24
55
  )
25
56
  %>
26
57
 
27
- <%==
28
- partial(
29
- 'explorer/messages/key',
30
- locals: { message: @message }
31
- )
32
- %>
33
-
34
58
  <%==
35
59
  partial(
36
60
  'explorer/messages/headers',
@@ -1,16 +1,16 @@
1
1
  <% if @visibility_filter.payload?(@message) %>
2
2
  <div class="row">
3
3
  <div class="col-sm-12 mb-4">
4
- <% if @payload_error %>
5
- <%== partial 'explorer/failed_deserialization' %>
4
+ <% if @safe_payload.failure? %>
5
+ <%== partial 'explorer/failed_deserialization', locals: { attribute: 'payload', error: @safe_payload.error } %>
6
6
  <% end %>
7
7
 
8
8
  <div class="card">
9
9
  <div class="card-body">
10
- <% if @payload_error %>
10
+ <% if @safe_payload.failure? %>
11
11
  <pre class="m-0 p-0"><code class="wrapped json p-0 m-0"><%= @message.raw_payload %></code></pre>
12
12
  <% else %>
13
- <pre class="m-0 p-0"><code class="wrapped json p-0 m-0"><%= @pretty_payload %></code></pre>
13
+ <pre class="m-0 p-0"><code class="wrapped json p-0 m-0"><%= @safe_payload.result %></code></pre>
14
14
  <% end %>
15
15
  </div>
16
16
  </div>
@@ -8,7 +8,7 @@
8
8
  </a>
9
9
  <% end %>
10
10
 
11
- <% if @visibility_filter.export?(@message) && !@payload_error %>
11
+ <% if @visibility_filter.export?(@message) && @safe_payload.success? %>
12
12
  <a
13
13
  href="<%= root_path('messages', @message.topic, @message.partition, @message.offset, 'export') %>"
14
14
  class="btn btn-secondary btn-sm"
@@ -0,0 +1,33 @@
1
+ <% if @safe_headers.success? %>
2
+ <% visible = @visibility_filter.headers?(message) %>
3
+ <% message.metadata.headers.each do |k, v| %>
4
+ <tr>
5
+ <td>
6
+ <%= "headers.#{k}" %>
7
+ </td>
8
+ <td>
9
+ <% if visible %>
10
+ <%= object_value_to_s(v) %>
11
+ <% else %>
12
+ <span class="text-muted">[Filtered]</span>
13
+ <% end %>
14
+ </td>
15
+ </tr>
16
+ <% end %>
17
+ <% else %>
18
+ <% visible = @visibility_filter.headers?(message) %>
19
+ <% message.metadata[:raw_headers].each do |k, v| %>
20
+ <tr>
21
+ <td>
22
+ <%= "raw_headers.#{k}" %>
23
+ </td>
24
+ <td>
25
+ <% if visible %>
26
+ <%= object_value_to_s(v) %>
27
+ <% else %>
28
+ <span class="text-muted">[Filtered]</span>
29
+ <% end %>
30
+ </td>
31
+ </tr>
32
+ <% end %>
33
+ <% end %>
@@ -0,0 +1,20 @@
1
+ <tr>
2
+ <td>
3
+ <% if @safe_key.success? %>
4
+ key
5
+ <% else %>
6
+ raw_key
7
+ <% end %>
8
+ </td>
9
+ <td>
10
+ <% if @visibility_filter.key?(message) %>
11
+ <% if @safe_key.success? %>
12
+ <%= @safe_key.result %>
13
+ <% else %>
14
+ <%= message.raw_key %>
15
+ <% end %>
16
+ <% else %>
17
+ <span class="text-muted">[Filtered]</span>
18
+ <% end %>
19
+ </td>
20
+ </tr>
@@ -0,0 +1,5 @@
1
+ <div class="mt-4">
2
+ <%==
3
+ alert_info('This partition no longer contains any data and has been fully compacted.')
4
+ %>
5
+ </div>
@@ -0,0 +1,5 @@
1
+ <div class="mt-4">
2
+ <%==
3
+ alert_info('This partition is empty and does not contain any data.')
4
+ %>
5
+ </div>
@@ -0,0 +1,21 @@
1
+ <div class="table-responsive">
2
+ <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
3
+ <thead>
4
+ <tr class="align-middle">
5
+ <th>Partition</th>
6
+ <th>Offset</th>
7
+ <th>Timestamp</th>
8
+ <th>Key</th>
9
+ <th></th>
10
+ </tr>
11
+ </thead>
12
+ <tbody>
13
+ <%==
14
+ each_partial(
15
+ @messages,
16
+ 'explorer/message'
17
+ )
18
+ %>
19
+ </tbody>
20
+ </table>
21
+ </div>
@@ -0,0 +1,5 @@
1
+ <div class="mt-4">
2
+ <%==
3
+ alert_info('This topic is empty and does not contain any data in any of the partitions.')
4
+ %>
5
+ </div>
@@ -0,0 +1,10 @@
1
+ <div class="mt-4 mb-4">
2
+ <%==
3
+ alert_info(
4
+ '
5
+ Due to many partitions, only part of the data is visible on each page.
6
+ Please navigate through the pages to view all data.
7
+ '
8
+ )
9
+ %>
10
+ </div>
@@ -35,3 +35,11 @@
35
35
  </a>
36
36
  </li>
37
37
  <% end %>
38
+
39
+ <% if current_path.include?('/cluster_lags') %>
40
+ <li class="breadcrumb-item">
41
+ <a href="<%= root_path('health', 'cluster_lags') %>">
42
+ Cluster Lags
43
+ </a>
44
+ </li>
45
+ <% end %>