karafka-web 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +3 -0
  3. data/.coditsu/ci.yml +3 -0
  4. data/.diffend.yml +3 -0
  5. data/.github/FUNDING.yml +1 -0
  6. data/.github/ISSUE_TEMPLATE/bug_report.md +50 -0
  7. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  8. data/.github/workflows/ci.yml +49 -0
  9. data/.gitignore +69 -0
  10. data/.ruby-gemset +1 -0
  11. data/.ruby-version +1 -0
  12. data/CHANGELOG.md +9 -0
  13. data/CODE_OF_CONDUCT.md +46 -0
  14. data/Gemfile +7 -0
  15. data/Gemfile.lock +52 -0
  16. data/LICENSE +17 -0
  17. data/README.md +29 -0
  18. data/bin/karafka-web +33 -0
  19. data/certs/cert_chain.pem +26 -0
  20. data/config/locales/errors.yml +9 -0
  21. data/karafka-web.gemspec +44 -0
  22. data/lib/karafka/web/app.rb +17 -0
  23. data/lib/karafka/web/config.rb +80 -0
  24. data/lib/karafka/web/deserializer.rb +20 -0
  25. data/lib/karafka/web/errors.rb +25 -0
  26. data/lib/karafka/web/installer.rb +124 -0
  27. data/lib/karafka/web/processing/consumer.rb +66 -0
  28. data/lib/karafka/web/processing/consumers/aggregator.rb +130 -0
  29. data/lib/karafka/web/processing/consumers/state.rb +32 -0
  30. data/lib/karafka/web/tracking/base_contract.rb +31 -0
  31. data/lib/karafka/web/tracking/consumers/contracts/consumer_group.rb +33 -0
  32. data/lib/karafka/web/tracking/consumers/contracts/job.rb +26 -0
  33. data/lib/karafka/web/tracking/consumers/contracts/partition.rb +22 -0
  34. data/lib/karafka/web/tracking/consumers/contracts/report.rb +95 -0
  35. data/lib/karafka/web/tracking/consumers/contracts/topic.rb +29 -0
  36. data/lib/karafka/web/tracking/consumers/listeners/base.rb +33 -0
  37. data/lib/karafka/web/tracking/consumers/listeners/errors.rb +107 -0
  38. data/lib/karafka/web/tracking/consumers/listeners/pausing.rb +45 -0
  39. data/lib/karafka/web/tracking/consumers/listeners/processing.rb +157 -0
  40. data/lib/karafka/web/tracking/consumers/listeners/statistics.rb +123 -0
  41. data/lib/karafka/web/tracking/consumers/listeners/status.rb +58 -0
  42. data/lib/karafka/web/tracking/consumers/sampler.rb +216 -0
  43. data/lib/karafka/web/tracking/memoized_shell.rb +48 -0
  44. data/lib/karafka/web/tracking/reporter.rb +144 -0
  45. data/lib/karafka/web/tracking/ttl_array.rb +59 -0
  46. data/lib/karafka/web/tracking/ttl_hash.rb +16 -0
  47. data/lib/karafka/web/ui/app.rb +78 -0
  48. data/lib/karafka/web/ui/base.rb +77 -0
  49. data/lib/karafka/web/ui/controllers/base.rb +40 -0
  50. data/lib/karafka/web/ui/controllers/become_pro.rb +17 -0
  51. data/lib/karafka/web/ui/controllers/cluster.rb +24 -0
  52. data/lib/karafka/web/ui/controllers/consumers.rb +27 -0
  53. data/lib/karafka/web/ui/controllers/errors.rb +43 -0
  54. data/lib/karafka/web/ui/controllers/jobs.rb +33 -0
  55. data/lib/karafka/web/ui/controllers/requests/params.rb +30 -0
  56. data/lib/karafka/web/ui/controllers/responses/data.rb +26 -0
  57. data/lib/karafka/web/ui/controllers/routing.rb +30 -0
  58. data/lib/karafka/web/ui/helpers/application_helper.rb +144 -0
  59. data/lib/karafka/web/ui/lib/hash_proxy.rb +66 -0
  60. data/lib/karafka/web/ui/lib/paginate_array.rb +38 -0
  61. data/lib/karafka/web/ui/models/consumer_group.rb +20 -0
  62. data/lib/karafka/web/ui/models/health.rb +44 -0
  63. data/lib/karafka/web/ui/models/job.rb +13 -0
  64. data/lib/karafka/web/ui/models/message.rb +99 -0
  65. data/lib/karafka/web/ui/models/partition.rb +13 -0
  66. data/lib/karafka/web/ui/models/process.rb +56 -0
  67. data/lib/karafka/web/ui/models/processes.rb +86 -0
  68. data/lib/karafka/web/ui/models/state.rb +67 -0
  69. data/lib/karafka/web/ui/models/topic.rb +19 -0
  70. data/lib/karafka/web/ui/pro/app.rb +120 -0
  71. data/lib/karafka/web/ui/pro/controllers/cluster.rb +16 -0
  72. data/lib/karafka/web/ui/pro/controllers/consumers.rb +54 -0
  73. data/lib/karafka/web/ui/pro/controllers/dlq.rb +44 -0
  74. data/lib/karafka/web/ui/pro/controllers/errors.rb +57 -0
  75. data/lib/karafka/web/ui/pro/controllers/explorer.rb +79 -0
  76. data/lib/karafka/web/ui/pro/controllers/health.rb +33 -0
  77. data/lib/karafka/web/ui/pro/controllers/jobs.rb +26 -0
  78. data/lib/karafka/web/ui/pro/controllers/routing.rb +26 -0
  79. data/lib/karafka/web/ui/pro/views/consumers/_breadcrumbs.erb +27 -0
  80. data/lib/karafka/web/ui/pro/views/consumers/_consumer.erb +60 -0
  81. data/lib/karafka/web/ui/pro/views/consumers/_counters.erb +50 -0
  82. data/lib/karafka/web/ui/pro/views/consumers/_summary.erb +81 -0
  83. data/lib/karafka/web/ui/pro/views/consumers/consumer/_consumer_group.erb +109 -0
  84. data/lib/karafka/web/ui/pro/views/consumers/consumer/_job.erb +26 -0
  85. data/lib/karafka/web/ui/pro/views/consumers/consumer/_metrics.erb +126 -0
  86. data/lib/karafka/web/ui/pro/views/consumers/consumer/_no_jobs.erb +9 -0
  87. data/lib/karafka/web/ui/pro/views/consumers/consumer/_no_subscriptions.erb +9 -0
  88. data/lib/karafka/web/ui/pro/views/consumers/consumer/_partition.erb +32 -0
  89. data/lib/karafka/web/ui/pro/views/consumers/consumer/_stopped.erb +10 -0
  90. data/lib/karafka/web/ui/pro/views/consumers/consumer/_tabs.erb +20 -0
  91. data/lib/karafka/web/ui/pro/views/consumers/index.erb +30 -0
  92. data/lib/karafka/web/ui/pro/views/consumers/jobs.erb +42 -0
  93. data/lib/karafka/web/ui/pro/views/consumers/subscriptions.erb +23 -0
  94. data/lib/karafka/web/ui/pro/views/dlq/_breadcrumbs.erb +5 -0
  95. data/lib/karafka/web/ui/pro/views/dlq/_no_topics.erb +9 -0
  96. data/lib/karafka/web/ui/pro/views/dlq/_topic.erb +12 -0
  97. data/lib/karafka/web/ui/pro/views/dlq/index.erb +16 -0
  98. data/lib/karafka/web/ui/pro/views/errors/_breadcrumbs.erb +25 -0
  99. data/lib/karafka/web/ui/pro/views/errors/_detail.erb +29 -0
  100. data/lib/karafka/web/ui/pro/views/errors/_error.erb +26 -0
  101. data/lib/karafka/web/ui/pro/views/errors/_partition_option.erb +7 -0
  102. data/lib/karafka/web/ui/pro/views/errors/index.erb +58 -0
  103. data/lib/karafka/web/ui/pro/views/errors/show.erb +56 -0
  104. data/lib/karafka/web/ui/pro/views/explorer/_breadcrumbs.erb +29 -0
  105. data/lib/karafka/web/ui/pro/views/explorer/_detail.erb +21 -0
  106. data/lib/karafka/web/ui/pro/views/explorer/_encryption_enabled.erb +18 -0
  107. data/lib/karafka/web/ui/pro/views/explorer/_failed_deserialization.erb +4 -0
  108. data/lib/karafka/web/ui/pro/views/explorer/_message.erb +16 -0
  109. data/lib/karafka/web/ui/pro/views/explorer/_partition_option.erb +7 -0
  110. data/lib/karafka/web/ui/pro/views/explorer/_topic.erb +12 -0
  111. data/lib/karafka/web/ui/pro/views/explorer/index.erb +17 -0
  112. data/lib/karafka/web/ui/pro/views/explorer/partition.erb +56 -0
  113. data/lib/karafka/web/ui/pro/views/explorer/show.erb +65 -0
  114. data/lib/karafka/web/ui/pro/views/health/_breadcrumbs.erb +5 -0
  115. data/lib/karafka/web/ui/pro/views/health/_partition.erb +35 -0
  116. data/lib/karafka/web/ui/pro/views/health/index.erb +60 -0
  117. data/lib/karafka/web/ui/pro/views/jobs/_breadcrumbs.erb +5 -0
  118. data/lib/karafka/web/ui/pro/views/jobs/_job.erb +31 -0
  119. data/lib/karafka/web/ui/pro/views/jobs/_no_jobs.erb +9 -0
  120. data/lib/karafka/web/ui/pro/views/jobs/index.erb +34 -0
  121. data/lib/karafka/web/ui/pro/views/shared/_navigation.erb +57 -0
  122. data/lib/karafka/web/ui/public/images/favicon.ico +0 -0
  123. data/lib/karafka/web/ui/public/images/logo.svg +28 -0
  124. data/lib/karafka/web/ui/public/javascripts/application.js +41 -0
  125. data/lib/karafka/web/ui/public/javascripts/bootstrap.min.js +7 -0
  126. data/lib/karafka/web/ui/public/javascripts/highlight.min.js +337 -0
  127. data/lib/karafka/web/ui/public/javascripts/live_poll.js +124 -0
  128. data/lib/karafka/web/ui/public/javascripts/timeago.min.js +1 -0
  129. data/lib/karafka/web/ui/public/stylesheets/application.css +106 -0
  130. data/lib/karafka/web/ui/public/stylesheets/bootstrap.min.css +7 -0
  131. data/lib/karafka/web/ui/public/stylesheets/bootstrap.min.css.map +1 -0
  132. data/lib/karafka/web/ui/public/stylesheets/highlight.min.css +10 -0
  133. data/lib/karafka/web/ui/views/cluster/_breadcrumbs.erb +5 -0
  134. data/lib/karafka/web/ui/views/cluster/_broker.erb +5 -0
  135. data/lib/karafka/web/ui/views/cluster/_partition.erb +22 -0
  136. data/lib/karafka/web/ui/views/cluster/index.erb +72 -0
  137. data/lib/karafka/web/ui/views/consumers/_breadcrumbs.erb +27 -0
  138. data/lib/karafka/web/ui/views/consumers/_consumer.erb +43 -0
  139. data/lib/karafka/web/ui/views/consumers/_counters.erb +44 -0
  140. data/lib/karafka/web/ui/views/consumers/_summary.erb +81 -0
  141. data/lib/karafka/web/ui/views/consumers/consumer/_consumer_group.erb +109 -0
  142. data/lib/karafka/web/ui/views/consumers/consumer/_job.erb +26 -0
  143. data/lib/karafka/web/ui/views/consumers/consumer/_metrics.erb +126 -0
  144. data/lib/karafka/web/ui/views/consumers/consumer/_no_jobs.erb +9 -0
  145. data/lib/karafka/web/ui/views/consumers/consumer/_no_subscriptions.erb +9 -0
  146. data/lib/karafka/web/ui/views/consumers/consumer/_partition.erb +32 -0
  147. data/lib/karafka/web/ui/views/consumers/consumer/_stopped.erb +10 -0
  148. data/lib/karafka/web/ui/views/consumers/consumer/_tabs.erb +20 -0
  149. data/lib/karafka/web/ui/views/consumers/index.erb +29 -0
  150. data/lib/karafka/web/ui/views/errors/_breadcrumbs.erb +19 -0
  151. data/lib/karafka/web/ui/views/errors/_detail.erb +29 -0
  152. data/lib/karafka/web/ui/views/errors/_error.erb +26 -0
  153. data/lib/karafka/web/ui/views/errors/index.erb +38 -0
  154. data/lib/karafka/web/ui/views/errors/show.erb +30 -0
  155. data/lib/karafka/web/ui/views/jobs/_breadcrumbs.erb +5 -0
  156. data/lib/karafka/web/ui/views/jobs/_job.erb +22 -0
  157. data/lib/karafka/web/ui/views/jobs/_no_jobs.erb +9 -0
  158. data/lib/karafka/web/ui/views/jobs/index.erb +31 -0
  159. data/lib/karafka/web/ui/views/layout.erb +23 -0
  160. data/lib/karafka/web/ui/views/routing/_breadcrumbs.erb +15 -0
  161. data/lib/karafka/web/ui/views/routing/_consumer_group.erb +34 -0
  162. data/lib/karafka/web/ui/views/routing/_detail.erb +25 -0
  163. data/lib/karafka/web/ui/views/routing/_topic.erb +18 -0
  164. data/lib/karafka/web/ui/views/routing/index.erb +10 -0
  165. data/lib/karafka/web/ui/views/routing/show.erb +26 -0
  166. data/lib/karafka/web/ui/views/shared/_become_pro.erb +13 -0
  167. data/lib/karafka/web/ui/views/shared/_brand.erb +3 -0
  168. data/lib/karafka/web/ui/views/shared/_content.erb +31 -0
  169. data/lib/karafka/web/ui/views/shared/_header.erb +20 -0
  170. data/lib/karafka/web/ui/views/shared/_navigation.erb +57 -0
  171. data/lib/karafka/web/ui/views/shared/_pagination.erb +21 -0
  172. data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +39 -0
  173. data/lib/karafka/web/ui/views/shared/exceptions/pro_only.erb +52 -0
  174. data/lib/karafka/web/version.rb +8 -0
  175. data/lib/karafka/web.rb +60 -0
  176. data.tar.gz.sig +0 -0
  177. metadata +328 -0
  178. metadata.gz.sig +0 -0
@@ -0,0 +1,27 @@
1
+ <% if @process %>
2
+ <li class="breadcrumb-item">
3
+ <a href="<%= root_path('consumers') %>">
4
+ Consumers
5
+ </a>
6
+ </li>
7
+
8
+ <li class="breadcrumb-item">
9
+ <a href="<%= root_path('consumers', @process.id, 'subscriptions') %>">
10
+ <%= @process.name %>
11
+ </a>
12
+ </li>
13
+
14
+ <% if current_path.include?('/jobs') %>
15
+ <li class="breadcrumb-item">
16
+ <a href="<%= root_path('consumers', @process.id, 'jobs') %>">
17
+ Running jobs
18
+ </a>
19
+ </li>
20
+ <% else %>
21
+ <li class="breadcrumb-item">
22
+ <a href="<%= root_path('consumers', @process.id, 'subscriptions') %>">
23
+ Active subscriptions
24
+ </a>
25
+ </li>
26
+ <% end %>
27
+ <% end %>
@@ -0,0 +1,60 @@
1
+ <tr class="status-row-<%= process.status %>">
2
+ <td>
3
+ <div class="badge badge-topic <%= status_bg(process.status) %> float-end">
4
+ <%= process.status %>
5
+ </div>
6
+
7
+ <a href="<%= root_path('consumers', process.id, 'subscriptions') %>">
8
+ <%= process.name %>
9
+ </a>
10
+
11
+ <br/>
12
+
13
+ <% process.consumer_groups.each do |consumer_group| %>
14
+ <% consumer_group.topics.each do |topic| %>
15
+ <span class="badge bg-secondary badge-topic" title="Consumer group: <%= consumer_group.id %>">
16
+ <%= topic.name %>:
17
+ <%= topic.partitions.map(&:id).join(',') %>
18
+ </span>
19
+ <% end %>
20
+ <% end %>
21
+ </td>
22
+
23
+ <td>
24
+ <%== relative_time process.started_at %>
25
+ </td>
26
+
27
+ <td>
28
+ <span class="badge bg-primary badge-topic">
29
+ <%= format_memory process.memory_usage %>
30
+ </span>
31
+ <span class="badge bg-primary badge-topic">
32
+ <%= format_memory process.memory_total_usage %>
33
+ </span>
34
+ <span class="badge bg-primary badge-topic">
35
+ <%= format_memory process.memory_size %>
36
+ </span>
37
+ </td>
38
+
39
+ <td>
40
+ <span class="badge bg-primary badge-topic">
41
+ <%= process.utilization.round(1) %>%
42
+ </span>
43
+ <span class="badge bg-primary badge-topic">
44
+ <%= process.concurrency %> /
45
+ <%= process.busy %>
46
+ </span>
47
+ </td>
48
+
49
+ <td>
50
+ <% process.cpu_usage.each do |metric| %>
51
+ <span class="badge bg-primary badge-topic">
52
+ <%= metric %>
53
+ </span>
54
+ <% end %>
55
+ </td>
56
+
57
+ <td>
58
+ <%= process.lag_stored %>
59
+ </td>
60
+ </tr>
@@ -0,0 +1,50 @@
1
+ <div id="counters" class="container mb-5">
2
+ <div class="row">
3
+ <div class="col-sm-12">
4
+ <div class="card">
5
+ <div class="card-body p-2 small">
6
+ <div class="col-sm-12">
7
+ <ul class="list-unstyled row text-center mb-0 mt-0">
8
+ <li class="col-sm">
9
+ <div class="count mb-1"><%= @counters.messages %></div>
10
+ <div class="desc">Messages</div>
11
+ </li>
12
+ <li class="col-sm">
13
+ <div class="count mb-1"><%= @counters.batches %></div>
14
+ <div class="desc">Batches</div>
15
+ </li>
16
+ <li class="col-sm">
17
+ <div class="count mb-1"><%= @processes.sum(&:lag_stored) %></div>
18
+ <div class="desc">Lag</div>
19
+ </li>
20
+ <li class="col-sm">
21
+ <div class="count mb-1"><%= @counters.busy %></div>
22
+ <div class="desc">Busy</div>
23
+ </li>
24
+ <li class="col-sm">
25
+ <div class="count mb-1"><%= @counters.enqueued %></div>
26
+ <div class="desc">Enqueued</div>
27
+ </li>
28
+ <li class="col-sm">
29
+ <a href="<%= root_path('errors/0') %>">
30
+ <div class="count mb-1"><%= @counters.errors %></div>
31
+ <div class="desc">Errors</div>
32
+ </a>
33
+ </li>
34
+ <li class="col-sm">
35
+ <div class="count mb-1"><%= @counters.retries %></div>
36
+ <div class="desc">Retries</div>
37
+ </li>
38
+ <li class="col-sm">
39
+ <a href="<%= root_path('dlq') %>">
40
+ <div class="count mb-1"><%= @counters.dead %></div>
41
+ <div class="desc">Dead</div>
42
+ </a>
43
+ </li>
44
+ </ul>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ </div>
@@ -0,0 +1,81 @@
1
+ <div id="summary" class="container text-center mb-5">
2
+ <div class="row">
3
+
4
+ <div class="col-lg-2 offset-md-1">
5
+ <div class="card mb-0">
6
+ <div class="card-body">
7
+ <p class="card-text">
8
+ <div class="stat mb-1">
9
+ <%= @counters.processes %>
10
+ </div>
11
+ <div class="desc">
12
+ Processes
13
+ </div>
14
+ </p>
15
+ </div>
16
+ </div>
17
+ </div>
18
+
19
+ <div class="col-lg-2">
20
+ <div class="card mb-0">
21
+ <div class="card-body">
22
+ <p class="card-text">
23
+ <div class="stat mb-1">
24
+ <%= @counters.threads_count %>
25
+ </div>
26
+ <div class="desc">
27
+ Worker threads
28
+ </div>
29
+ </p>
30
+ </div>
31
+ </div>
32
+ </div>
33
+
34
+ <div class="col-lg-2">
35
+ <div class="card mb-0">
36
+ <div class="card-body">
37
+ <p class="card-text">
38
+ <div class="stat mb-1">
39
+ <%= @counters.listeners_count %>
40
+ </div>
41
+ <div class="desc">
42
+ Listeners
43
+ </div>
44
+ </p>
45
+ </div>
46
+ </div>
47
+ </div>
48
+
49
+ <div class="col-lg-2">
50
+ <div class="card mb-0">
51
+ <div class="card-body">
52
+ <p class="card-text">
53
+ <div class="stat mb-1">
54
+ <%= @counters.utilization.round(2) %>
55
+ %
56
+ </div>
57
+ <div class="desc">
58
+ Utilization
59
+ </div>
60
+ </p>
61
+ </div>
62
+ </div>
63
+ </div>
64
+
65
+ <div class="col-lg-2">
66
+ <div class="card mb-0">
67
+ <div class="card-body">
68
+ <p class="card-text">
69
+ <div class="stat mb-1">
70
+ <%= format_memory @counters.rss %>
71
+ </div>
72
+ <div class="desc">
73
+ RSS
74
+ </div>
75
+ </p>
76
+ </div>
77
+ </div>
78
+ </div>
79
+
80
+ </div>
81
+ </div>
@@ -0,0 +1,109 @@
1
+ <div class="row mb-4">
2
+ <div class="col-sm-12">
3
+ <h5 class="mb-4">
4
+ <%= consumer_group.id %>
5
+ </h5>
6
+
7
+ <div class="card-group text-center">
8
+ <div class="card">
9
+ <div class="card-body d-flex flex-column align-items-center justify-content-center p-2">
10
+ State:&nbsp;
11
+ <span class="badge <%= kafka_state_bg(consumer_group[:state][:state]) %> mt-1 mb-1">
12
+ <%= consumer_group[:state][:state] %>
13
+ </span>
14
+ </div>
15
+ </div>
16
+ <div class="card">
17
+ <div class="card-body d-flex flex-column align-items-center justify-content-center p-2">
18
+ Join state:&nbsp;
19
+ <span class="badge <%= kafka_state_bg(consumer_group.join_state) %> mt-1 mb-1">
20
+ <%= consumer_group.join_state %>
21
+ </span>
22
+ </div>
23
+ </div>
24
+ <div class="card">
25
+ <div class="card-body d-flex flex-column align-items-center justify-content-center p-2">
26
+ State change:&nbsp;
27
+ <span class="badge bg-secondary mt-1 mb-1">
28
+ <%==
29
+ relative_time(
30
+ Time.at(@process.dispatched_at) - (consumer_group.stateage / 1_000)
31
+ )
32
+ %>
33
+ </span>
34
+ </div>
35
+ </div>
36
+ <div class="card">
37
+ <div class="card-body d-flex flex-column align-items-center justify-content-center p-2">
38
+ Last rebalance:&nbsp;
39
+ <span class="badge bg-secondary mt-1 mb-1">
40
+ <%==
41
+ relative_time(
42
+ Time.at(@process.dispatched_at) - (consumer_group.rebalance_age / 1_000)
43
+ )
44
+ %>
45
+ </span>
46
+ </div>
47
+ </div>
48
+ <div class="card">
49
+ <div class="card-body d-flex flex-column align-items-center justify-content-center p-2">
50
+ Rebalance count:&nbsp;
51
+ <span class="badge bg-secondary mt-1 mb-1">
52
+ <%= consumer_group.rebalance_cnt %>
53
+ </span>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ </div>
58
+
59
+ <span class="text-end mt-3">
60
+ <small>
61
+ Last rebalance reason: <%= consumer_group.rebalance_reason %>
62
+ </small>
63
+ </span>
64
+ </div>
65
+
66
+ <% if consumer_group.topics.empty? %>
67
+ <div class="row">
68
+ <div class="col-lg-12">
69
+ <div class="alert alert-info" role="alert">
70
+ This process does not consume any messages from any topics of this consumer group.
71
+ </div>
72
+ </div>
73
+ </div>
74
+ <% else %>
75
+ <div class="row mb-5">
76
+ <div class="col-sm-12">
77
+ <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
78
+ <thead>
79
+ <tr class="align-middle">
80
+ <th>Topic</th>
81
+ <th>Partition</th>
82
+ <th>Lag stored</th>
83
+ <th>Lag trend</th>
84
+ <th>Committed offset</th>
85
+ <th>Stored offset</th>
86
+ <th>Fetch state</th>
87
+ <th>Poll state</th>
88
+ </tr>
89
+ </thead>
90
+ <tbody>
91
+ <% consumer_group.topics.each do |topic| %>
92
+ <% topic.partitions.each do |partition| %>
93
+ <%==
94
+ partial(
95
+ 'consumers/consumer/partition',
96
+ locals: {
97
+ topic: topic,
98
+ partition: partition,
99
+ consumer_group: consumer_group
100
+ }
101
+ )
102
+ %>
103
+ <% end %>
104
+ <% end %>
105
+ </tbody>
106
+ </table>
107
+ </div>
108
+ </div>
109
+ <% end %>
@@ -0,0 +1,26 @@
1
+ <tr>
2
+ <td>
3
+ <code><%= job.consumer %></code>
4
+ </td>
5
+ <td>
6
+ <span class="badge bg-secondary badge-topic" title="Consumer group: <%= job.consumer_group %>">
7
+ <%= job.topic %>:
8
+ <%= job.partition %>
9
+ </span>
10
+ </td>
11
+ <td>
12
+ <code>#<%= job.type %></code>
13
+ </td>
14
+ <td>
15
+ <%= job.first_offset %>
16
+ </td>
17
+ <td>
18
+ <%= job.last_offset %>
19
+ </td>
20
+ <td>
21
+ <%= job.comitted_offset %>
22
+ </td>
23
+ <td>
24
+ <%== relative_time job.started_at %>
25
+ </td>
26
+ </tr>
@@ -0,0 +1,126 @@
1
+ <div class="container mb-5">
2
+ <div class="row" id="metrics">
3
+ <div class="col-lg-12">
4
+ <div class="card-group">
5
+ <div class="card">
6
+ <div class="card-body">
7
+ <h5 class="card-title">Process</h5>
8
+ <p class="card-text">
9
+ <ul style="list-style: square !important;">
10
+ <li class="align-items-center d-flex justify-content-between">
11
+ Status:
12
+ <span class="badge <%= status_bg @process.status %>">
13
+ <%= @process.status %>
14
+ </span>
15
+ </li>
16
+ <li class="align-items-center d-flex justify-content-between">
17
+ Started:
18
+ <span class="badge bg-secondary">
19
+ <%== relative_time @process.started_at %>
20
+ </span>
21
+ </li>
22
+ <li class="align-items-center d-flex justify-content-between">
23
+ State from:
24
+ <span class="badge bg-secondary">
25
+ <%== relative_time @process.dispatched_at %>
26
+ </span>
27
+ </li>
28
+ </ul>
29
+ </p>
30
+ </div>
31
+ </div>
32
+ <div class="card">
33
+ <div class="card-body">
34
+ <h5 class="card-title">Utilization</h5>
35
+ <p class="card-text">
36
+ <ul style="list-style: square !important;">
37
+ <li class="align-items-center d-flex justify-content-between">
38
+ Threads:
39
+ <span class="badge bg-primary">
40
+ <%= @process.concurrency %>
41
+ </span>
42
+ </li>
43
+ <li class="align-items-center d-flex justify-content-between">
44
+ Threads utilization:
45
+ <span class="badge bg-primary">
46
+ <%= @process.utilization.round(2) %>%
47
+ </span>
48
+ </li>
49
+ <li class="align-items-center d-flex justify-content-between">
50
+ CPUs:
51
+ <span class="badge bg-primary">
52
+ <%= @process.cpu_count %>
53
+ </span>
54
+ </li>
55
+ <li class="align-items-center d-flex justify-content-between">
56
+ CPU usage:
57
+ <% @process.cpu_usage.each_with_index do |usage, i| %>
58
+ <span class="badge bg-primary">
59
+ <%= usage %>
60
+ </span>
61
+
62
+ <%= i < 2 ? '/' : '' %>
63
+ <% end %>
64
+ </li>
65
+ </ul>
66
+ </p>
67
+ </div>
68
+ </div>
69
+ <div class="card">
70
+ <div class="card-body">
71
+ <h5 class="card-title">Memory usage</h5>
72
+ <p class="card-text">
73
+ <ul style="list-style: square !important;">
74
+ <li class="align-items-center d-flex justify-content-between">
75
+ RSS:
76
+ <span class="badge bg-primary">
77
+ <%= format_memory @process.memory_usage %>
78
+ </span>
79
+ </li>
80
+ <li class="align-items-center d-flex justify-content-between">
81
+ OS memory used:
82
+ <span class="badge bg-primary">
83
+ <%= format_memory @process.memory_total_usage %>
84
+ </span>
85
+ </li>
86
+ <li class="align-items-center d-flex justify-content-between">
87
+ OS memory available:
88
+ <span class="badge bg-primary">
89
+ <%= format_memory @process.memory_size %>
90
+ </span>
91
+ </li>
92
+ </ul>
93
+ </p>
94
+ </div>
95
+ </div>
96
+ <div class="card">
97
+ <div class="card-body">
98
+ <h5 class="card-title">Versions</h5>
99
+ <p class="card-text">
100
+ <ul style="list-style: square !important;">
101
+ <li class="align-items-center d-flex justify-content-between">
102
+ Ruby:
103
+ <span class="badge bg-secondary">
104
+ <%= @process.ruby %>
105
+ </span>
106
+ </li>
107
+ <li class="align-items-center d-flex justify-content-between">
108
+ Karafka:
109
+ <span class="badge bg-secondary">
110
+ <%= @process.karafka %>
111
+ </span>
112
+ </li>
113
+ <li class="align-items-center d-flex justify-content-between">
114
+ WaterDrop version:
115
+ <span class="badge bg-secondary">
116
+ <%= @process.waterdrop %>
117
+ </span>
118
+ </li>
119
+ </ul>
120
+ </p>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </div>
126
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="container mb-4">
2
+ <div class="row">
3
+ <div class="col-lg-12">
4
+ <div class="alert alert-info" role="alert">
5
+ This process is not running any jobs at the moment.
6
+ </div>
7
+ </div>
8
+ </div>
9
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="container mb-4">
2
+ <div class="row">
3
+ <div class="col-lg-12">
4
+ <div class="alert alert-info" role="alert">
5
+ This process is not subscribed to any topics.
6
+ </div>
7
+ </div>
8
+ </div>
9
+ </div>
@@ -0,0 +1,32 @@
1
+ <tr>
2
+ <td>
3
+ <%= topic.name %>
4
+ </td>
5
+ <td>
6
+ <%= partition.id %>
7
+ </td>
8
+ <td>
9
+ <%= partition.lag_stored %>
10
+ </td>
11
+ <td>
12
+ <span class="badge <%= lag_trend_bg(partition.lag_stored_d) %>">
13
+ <%= partition.lag_stored_d %>
14
+ </span>
15
+ </td>
16
+ <td>
17
+ <%= partition.committed_offset %>
18
+ </td>
19
+ <td>
20
+ <%= partition.stored_offset %>
21
+ </td>
22
+ <td>
23
+ <span class="badge <%= kafka_state_bg(partition.fetch_state) %> mt-1 mb-1">
24
+ <%= partition.fetch_state %>
25
+ </span>
26
+ </td>
27
+ <td>
28
+ <span class="badge <%= kafka_state_bg(partition.poll_state) %> mt-1 mb-1">
29
+ <%= partition.poll_state %>
30
+ </span>
31
+ </td>
32
+ </tr>
@@ -0,0 +1,10 @@
1
+ <div class="container mb-4">
2
+ <div class="row">
3
+ <div class="col-lg-12">
4
+ <div class="alert alert-danger" role="alert">
5
+ This process has been stopped.
6
+ The state presented here shows the last report available.
7
+ </div>
8
+ </div>
9
+ </div>
10
+ </div>
@@ -0,0 +1,20 @@
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 class="nav-link <%= nav_class(include: 'subscriptions') %>" href="<%= root_path('consumers', @process.id, 'subscriptions') %>">
8
+ Active subscriptions
9
+ </a>
10
+ </li>
11
+ <li class="nav-item">
12
+ <a class="nav-link <%= nav_class(include: 'jobs') %>" href="<%= root_path('consumers', @process.id, 'jobs') %>">
13
+ Running jobs
14
+ </a>
15
+ </li>
16
+ </ul>
17
+
18
+ </div>
19
+ </div>
20
+ </div>
@@ -0,0 +1,30 @@
1
+ <%== partial 'consumers/counters' %>
2
+ <%== partial 'consumers/summary' %>
3
+
4
+ <div class="container">
5
+ <div class="row">
6
+ <div class="col-sm-12">
7
+ <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
8
+ <thead>
9
+ <tr class="align-middle">
10
+ <th>Name</th>
11
+ <th class="col-sm-2">Started</th>
12
+ <th class="col-sm-1">Memory</th>
13
+ <th class="col-sm-1">Performance</th>
14
+ <th class="col-sm-1">Load</th>
15
+ <th class="col-sm-1">Total lag</th>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ <%==
20
+ render_each(
21
+ @processes,
22
+ 'consumers/_consumer',
23
+ local: :process
24
+ )
25
+ %>
26
+ </tbody>
27
+ </table>
28
+ </div>
29
+ </div>
30
+ </div>
@@ -0,0 +1,42 @@
1
+ <%== view_title(@process.name) %>
2
+
3
+ <% if @process.status == 'stopped' %>
4
+ <%== partial 'consumers/consumer/stopped' %>
5
+ <% end %>
6
+
7
+ <%== partial 'consumers/consumer/metrics' %>
8
+
9
+ <%== partial 'consumers/consumer/tabs' %>
10
+
11
+ <% if @process.jobs.empty? %>
12
+ <%== partial 'consumers/consumer/no_jobs' %>
13
+ <% else %>
14
+ <div class="container">
15
+ <div class="row mb-5">
16
+ <div class="col-sm-12">
17
+ <table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
18
+ <thead>
19
+ <tr class="align-middle">
20
+ <th>Consumer</th>
21
+ <th>Topic</th>
22
+ <th>Type</th>
23
+ <th>First offset</th>
24
+ <th>Last offset</th>
25
+ <th>Committed offset</th>
26
+ <th>Started at</th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <%==
31
+ render_each(
32
+ @process.jobs,
33
+ 'consumers/consumer/_job',
34
+ local: :job
35
+ )
36
+ %>
37
+ </tbody>
38
+ </table>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <%== view_title(@process.name) %>
2
+
3
+ <% if @process.status == 'stopped' %>
4
+ <%== partial 'consumers/consumer/stopped' %>
5
+ <% end %>
6
+
7
+ <%== partial 'consumers/consumer/metrics' %>
8
+
9
+ <%== partial 'consumers/consumer/tabs' %>
10
+
11
+ <% if @process.consumer_groups.empty? %>
12
+ <%== partial 'consumers/consumer/no_subscriptions' %>
13
+ <% end %>
14
+
15
+ <div class="container">
16
+ <%==
17
+ render_each(
18
+ @process.consumer_groups,
19
+ 'consumers/consumer/_consumer_group',
20
+ local: :consumer_group
21
+ )
22
+ %>
23
+ </div>
@@ -0,0 +1,5 @@
1
+ <li class="breadcrumb-item">
2
+ <a href="<%= root_path('dlq') %>">
3
+ Dead Letter Queue topics
4
+ </a>
5
+ </li>