karafka-web 0.7.9 → 0.8.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +21 -6
- data/.ruby-version +1 -1
- data/CHANGELOG.md +66 -0
- data/Gemfile.lock +22 -22
- data/docker-compose.yml +3 -1
- data/karafka-web.gemspec +2 -2
- data/lib/karafka/web/config.rb +16 -3
- data/lib/karafka/web/contracts/config.rb +7 -2
- data/lib/karafka/web/errors.rb +12 -0
- data/lib/karafka/web/inflector.rb +33 -0
- data/lib/karafka/web/installer.rb +20 -11
- data/lib/karafka/web/management/actions/base.rb +36 -0
- data/lib/karafka/web/management/actions/clean_boot_file.rb +33 -0
- data/lib/karafka/web/management/actions/create_initial_states.rb +77 -0
- data/lib/karafka/web/management/actions/create_topics.rb +139 -0
- data/lib/karafka/web/management/actions/delete_topics.rb +30 -0
- data/lib/karafka/web/management/actions/enable.rb +117 -0
- data/lib/karafka/web/management/actions/extend_boot_file.rb +39 -0
- data/lib/karafka/web/management/actions/migrate_states_data.rb +18 -0
- data/lib/karafka/web/management/migrations/0_base.rb +58 -0
- data/lib/karafka/web/management/migrations/0_set_initial_consumers_metrics.rb +36 -0
- data/lib/karafka/web/management/migrations/0_set_initial_consumers_state.rb +43 -0
- data/lib/karafka/web/management/migrations/1699543515_fill_missing_received_and_sent_bytes_in_consumers_metrics.rb +26 -0
- data/lib/karafka/web/management/migrations/1699543515_fill_missing_received_and_sent_bytes_in_consumers_state.rb +23 -0
- data/lib/karafka/web/management/migrations/1700234522_introduce_waiting_in_consumers_metrics.rb +24 -0
- data/lib/karafka/web/management/migrations/1700234522_introduce_waiting_in_consumers_state.rb +20 -0
- data/lib/karafka/web/management/migrations/1700234522_remove_processing_from_consumers_metrics.rb +24 -0
- data/lib/karafka/web/management/migrations/1700234522_remove_processing_from_consumers_state.rb +20 -0
- data/lib/karafka/web/management/migrations/1704722380_split_listeners_into_active_and_paused_in_metrics.rb +36 -0
- data/lib/karafka/web/management/migrations/1704722380_split_listeners_into_active_and_paused_in_states.rb +32 -0
- data/lib/karafka/web/management/migrator.rb +117 -0
- data/lib/karafka/web/processing/consumer.rb +39 -38
- data/lib/karafka/web/processing/consumers/aggregators/metrics.rb +15 -7
- data/lib/karafka/web/processing/consumers/aggregators/state.rb +8 -3
- data/lib/karafka/web/processing/consumers/contracts/aggregated_stats.rb +5 -1
- data/lib/karafka/web/processing/publisher.rb +59 -0
- data/lib/karafka/web/tracking/consumers/contracts/job.rb +3 -2
- data/lib/karafka/web/tracking/consumers/contracts/partition.rb +1 -0
- data/lib/karafka/web/tracking/consumers/contracts/report.rb +6 -1
- data/lib/karafka/web/tracking/consumers/contracts/subscription_group.rb +10 -1
- data/lib/karafka/web/tracking/consumers/listeners/connections.rb +49 -0
- data/lib/karafka/web/tracking/consumers/listeners/pausing.rb +7 -4
- data/lib/karafka/web/tracking/consumers/listeners/processing.rb +78 -70
- data/lib/karafka/web/tracking/consumers/listeners/statistics.rb +40 -13
- data/lib/karafka/web/tracking/consumers/sampler.rb +82 -25
- data/lib/karafka/web/tracking/helpers/ttls/array.rb +72 -0
- data/lib/karafka/web/tracking/helpers/ttls/hash.rb +34 -0
- data/lib/karafka/web/tracking/helpers/ttls/stats.rb +49 -0
- data/lib/karafka/web/tracking/helpers/ttls/windows.rb +32 -0
- data/lib/karafka/web/tracking/reporter.rb +1 -0
- data/lib/karafka/web/ui/app.rb +22 -4
- data/lib/karafka/web/ui/base.rb +18 -2
- data/lib/karafka/web/ui/controllers/base.rb +34 -4
- data/lib/karafka/web/ui/controllers/become_pro.rb +1 -1
- data/lib/karafka/web/ui/controllers/cluster.rb +33 -9
- data/lib/karafka/web/ui/controllers/consumers.rb +8 -2
- data/lib/karafka/web/ui/controllers/dashboard.rb +2 -2
- data/lib/karafka/web/ui/controllers/errors.rb +2 -2
- data/lib/karafka/web/ui/controllers/jobs.rb +55 -5
- data/lib/karafka/web/ui/controllers/requests/params.rb +5 -0
- data/lib/karafka/web/ui/controllers/responses/deny.rb +15 -0
- data/lib/karafka/web/ui/controllers/responses/file.rb +23 -0
- data/lib/karafka/web/ui/controllers/responses/{data.rb → render.rb} +3 -3
- data/lib/karafka/web/ui/controllers/routing.rb +11 -2
- data/lib/karafka/web/ui/controllers/status.rb +1 -1
- data/lib/karafka/web/ui/helpers/application_helper.rb +70 -0
- data/lib/karafka/web/ui/lib/hash_proxy.rb +29 -14
- data/lib/karafka/web/ui/lib/sorter.rb +170 -0
- data/lib/karafka/web/ui/models/counters.rb +6 -0
- data/lib/karafka/web/ui/models/health.rb +23 -2
- data/lib/karafka/web/ui/models/jobs.rb +48 -0
- data/lib/karafka/web/ui/models/metrics/charts/aggregated.rb +33 -0
- data/lib/karafka/web/ui/models/metrics/charts/topics.rb +1 -10
- data/lib/karafka/web/ui/models/process.rb +2 -1
- data/lib/karafka/web/ui/models/status.rb +23 -7
- data/lib/karafka/web/ui/models/topic.rb +3 -1
- data/lib/karafka/web/ui/models/visibility_filter.rb +16 -0
- data/lib/karafka/web/ui/pro/app.rb +44 -6
- data/lib/karafka/web/ui/pro/controllers/cluster.rb +1 -0
- data/lib/karafka/web/ui/pro/controllers/consumers.rb +52 -6
- data/lib/karafka/web/ui/pro/controllers/dashboard.rb +1 -1
- data/lib/karafka/web/ui/pro/controllers/dlq.rb +1 -1
- data/lib/karafka/web/ui/pro/controllers/errors.rb +3 -3
- data/lib/karafka/web/ui/pro/controllers/explorer.rb +8 -8
- data/lib/karafka/web/ui/pro/controllers/health.rb +34 -2
- data/lib/karafka/web/ui/pro/controllers/jobs.rb +11 -0
- data/lib/karafka/web/ui/pro/controllers/messages.rb +42 -0
- data/lib/karafka/web/ui/pro/controllers/routing.rb +11 -2
- data/lib/karafka/web/ui/pro/views/consumers/_breadcrumbs.erb +8 -2
- data/lib/karafka/web/ui/pro/views/consumers/_consumer.erb +14 -8
- data/lib/karafka/web/ui/pro/views/consumers/_counters.erb +8 -6
- data/lib/karafka/web/ui/pro/views/consumers/consumer/_job.erb +4 -1
- data/lib/karafka/web/ui/pro/views/consumers/consumer/_no_jobs.erb +1 -1
- data/lib/karafka/web/ui/pro/views/consumers/consumer/_partition.erb +1 -3
- data/lib/karafka/web/ui/pro/views/consumers/consumer/_subscription_group.erb +28 -11
- data/lib/karafka/web/ui/pro/views/consumers/consumer/_tabs.erb +10 -3
- data/lib/karafka/web/ui/pro/views/consumers/index.erb +3 -3
- data/lib/karafka/web/ui/pro/views/consumers/pending_jobs.erb +43 -0
- data/lib/karafka/web/ui/pro/views/consumers/{jobs.erb → running_jobs.erb} +11 -10
- data/lib/karafka/web/ui/pro/views/dashboard/index.erb +7 -1
- data/lib/karafka/web/ui/pro/views/explorer/message/_message_actions.erb +18 -0
- data/lib/karafka/web/ui/pro/views/explorer/message/_metadata.erb +43 -0
- data/lib/karafka/web/ui/pro/views/explorer/message/_payload.erb +21 -0
- data/lib/karafka/web/ui/pro/views/explorer/message/_payload_actions.erb +19 -0
- data/lib/karafka/web/ui/pro/views/explorer/show.erb +9 -84
- data/lib/karafka/web/ui/pro/views/health/_breadcrumbs.erb +8 -0
- data/lib/karafka/web/ui/pro/views/health/_partition.erb +1 -3
- data/lib/karafka/web/ui/pro/views/health/_partition_offset.erb +4 -4
- data/lib/karafka/web/ui/pro/views/health/_partition_times.erb +32 -0
- data/lib/karafka/web/ui/pro/views/health/_tabs.erb +9 -0
- data/lib/karafka/web/ui/pro/views/health/changes.erb +66 -0
- data/lib/karafka/web/ui/pro/views/health/offsets.erb +14 -14
- data/lib/karafka/web/ui/pro/views/health/overview.erb +11 -11
- data/lib/karafka/web/ui/pro/views/jobs/_job.erb +1 -1
- data/lib/karafka/web/ui/pro/views/jobs/_no_jobs.erb +1 -1
- data/lib/karafka/web/ui/pro/views/jobs/pending.erb +39 -0
- data/lib/karafka/web/ui/pro/views/jobs/running.erb +39 -0
- data/lib/karafka/web/ui/pro/views/routing/_consumer_group.erb +2 -2
- data/lib/karafka/web/ui/pro/views/routing/_topic.erb +9 -0
- data/lib/karafka/web/ui/pro/views/routing/show.erb +12 -0
- data/lib/karafka/web/ui/pro/views/shared/_navigation.erb +1 -1
- data/lib/karafka/web/ui/public/javascripts/application.js +10 -0
- data/lib/karafka/web/ui/public/stylesheets/application.css +4 -0
- data/lib/karafka/web/ui/views/cluster/_breadcrumbs.erb +16 -0
- data/lib/karafka/web/ui/views/cluster/_tabs.erb +27 -0
- data/lib/karafka/web/ui/views/cluster/brokers.erb +27 -0
- data/lib/karafka/web/ui/views/cluster/topics.erb +35 -0
- data/lib/karafka/web/ui/views/consumers/_counters.erb +8 -6
- data/lib/karafka/web/ui/views/consumers/_summary.erb +2 -2
- data/lib/karafka/web/ui/views/consumers/index.erb +3 -3
- data/lib/karafka/web/ui/views/dashboard/_ranges_selector.erb +23 -7
- data/lib/karafka/web/ui/views/dashboard/index.erb +19 -8
- data/lib/karafka/web/ui/views/errors/show.erb +2 -23
- data/lib/karafka/web/ui/views/jobs/_breadcrumbs.erb +17 -1
- data/lib/karafka/web/ui/views/jobs/_job.erb +1 -1
- data/lib/karafka/web/ui/views/jobs/_no_jobs.erb +1 -1
- data/lib/karafka/web/ui/views/jobs/_tabs.erb +27 -0
- data/lib/karafka/web/ui/views/jobs/{index.erb → pending.erb} +9 -7
- data/lib/karafka/web/ui/{pro/views/jobs/index.erb → views/jobs/running.erb} +9 -11
- data/lib/karafka/web/ui/views/routing/_consumer_group.erb +14 -12
- data/lib/karafka/web/ui/views/shared/_navigation.erb +1 -1
- data/lib/karafka/web/ui/views/shared/_pagination.erb +1 -1
- data/lib/karafka/web/ui/views/shared/exceptions/not_allowed.erb +37 -0
- data/lib/karafka/web/ui/views/status/show.erb +17 -2
- data/lib/karafka/web/ui/views/status/warnings/_routing_topics_presence.erb +15 -0
- data/lib/karafka/web/version.rb +1 -1
- data/lib/karafka/web.rb +6 -2
- data.tar.gz.sig +0 -0
- metadata +61 -26
- metadata.gz.sig +0 -0
- data/lib/karafka/web/management/base.rb +0 -34
- data/lib/karafka/web/management/clean_boot_file.rb +0 -31
- data/lib/karafka/web/management/create_initial_states.rb +0 -101
- data/lib/karafka/web/management/create_topics.rb +0 -133
- data/lib/karafka/web/management/delete_topics.rb +0 -28
- data/lib/karafka/web/management/enable.rb +0 -102
- data/lib/karafka/web/management/extend_boot_file.rb +0 -37
- data/lib/karafka/web/tracking/ttl_array.rb +0 -59
- data/lib/karafka/web/tracking/ttl_hash.rb +0 -16
- data/lib/karafka/web/ui/pro/views/dashboard/_ranges_selector.erb +0 -39
- data/lib/karafka/web/ui/views/cluster/index.erb +0 -74
@@ -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">
|
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,35 @@
|
|
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">
|
8
|
+
<% if @partitions.empty? && params.current_page <= 1 %>
|
9
|
+
<%== partial 'cluster/no_partitions' %>
|
10
|
+
<% elsif @partitions.empty? %>
|
11
|
+
<%== partial 'shared/no_paginated_data' %>
|
12
|
+
<% else %>
|
13
|
+
<table class="processes bg-white table table-hover table-bordered table-striped">
|
14
|
+
<thead>
|
15
|
+
<tr class="align-middle">
|
16
|
+
<th><%== sort_link(:topic_name) %></th>
|
17
|
+
<th><%== sort_link(:partition_id) %></th>
|
18
|
+
<th><%== sort_link(:leader) %></th>
|
19
|
+
<th><%== sort_link(:replica_count) %></th>
|
20
|
+
<th><%== sort_link('In sync brokers', :in_sync_replica_brokers) %></th>
|
21
|
+
</tr>
|
22
|
+
</thead>
|
23
|
+
<tbody>
|
24
|
+
<%==
|
25
|
+
each_partial(
|
26
|
+
@partitions,
|
27
|
+
'cluster/partition'
|
28
|
+
)
|
29
|
+
%>
|
30
|
+
</tbody>
|
31
|
+
</table>
|
32
|
+
<% end %>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</div>
|
@@ -24,18 +24,20 @@
|
|
24
24
|
<div class="desc">Lag stored</div>
|
25
25
|
</li>
|
26
26
|
<li class="col-sm">
|
27
|
-
<a href="<%= root_path('jobs') %>">
|
27
|
+
<a href="<%= root_path('jobs/running') %>">
|
28
28
|
<div class="count mb-1">
|
29
29
|
<%= number_with_delimiter @counters.busy, ' ' %>
|
30
30
|
</div>
|
31
|
-
<div class="desc">
|
31
|
+
<div class="desc">Running</div>
|
32
32
|
</a>
|
33
33
|
</li>
|
34
34
|
<li class="col-sm">
|
35
|
-
<
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
<a href="<%= root_path('jobs/pending') %>">
|
36
|
+
<div class="count mb-1">
|
37
|
+
<%= number_with_delimiter @counters.pending, ' ' %>
|
38
|
+
</div>
|
39
|
+
<div class="desc">Pending</div>
|
40
|
+
</a>
|
39
41
|
</li>
|
40
42
|
<li class="col-sm">
|
41
43
|
<a href="<%= root_path('errors') %>">
|
@@ -12,11 +12,11 @@
|
|
12
12
|
<table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
|
13
13
|
<thead>
|
14
14
|
<tr class="align-middle">
|
15
|
-
<th
|
16
|
-
<th class="col-sm-2"
|
15
|
+
<th><%== sort_link(:name) %></th>
|
16
|
+
<th class="col-sm-2"><%== sort_link('Started', :started_at, rev: true) %></th>
|
17
17
|
<th class="col-sm-1">Memory</th>
|
18
18
|
<th class="col-sm-1">Utilization</th>
|
19
|
-
<th class="col-sm-1"
|
19
|
+
<th class="col-sm-1"><%== sort_link(:lag_stored) %></th>
|
20
20
|
</tr>
|
21
21
|
</thead>
|
22
22
|
<tbody>
|
@@ -2,20 +2,36 @@
|
|
2
2
|
<div class="row">
|
3
3
|
<div class="col-sm-12 text-end">
|
4
4
|
<div class="btn-group btn-group-sm" role="group" aria-label="Small button group">
|
5
|
-
|
5
|
+
<%
|
6
|
+
path = root_path('dashboard?range=seconds')
|
7
|
+
active = params.current_range == :seconds ? 'active' : false
|
8
|
+
%>
|
9
|
+
<a type="button" href="<%= path %>" class="btn btn-outline-primary <%= active %>">
|
6
10
|
5 minutes
|
7
11
|
</a>
|
8
12
|
|
9
|
-
|
10
|
-
|
13
|
+
<%
|
14
|
+
path = root_path('dashboard?range=minutes')
|
15
|
+
active = params.current_range == :minutes ? 'active' : false
|
16
|
+
%>
|
17
|
+
<a type="button" href="<%= path %>" class="btn btn-outline-primary <%= active %>">
|
18
|
+
1 hour
|
11
19
|
</a>
|
12
20
|
|
13
|
-
|
14
|
-
|
21
|
+
<%
|
22
|
+
path = root_path('dashboard?range=hours')
|
23
|
+
active = params.current_range == :hours ? 'active' : false
|
24
|
+
%>
|
25
|
+
<a type="button" href="<%= path %>" class="btn btn-outline-primary <%= active %>">
|
26
|
+
24 hours
|
15
27
|
</a>
|
16
28
|
|
17
|
-
|
18
|
-
|
29
|
+
<%
|
30
|
+
path = root_path('dashboard?range=days')
|
31
|
+
active = params.current_range == :days ? 'active' : false
|
32
|
+
%>
|
33
|
+
<a type="button" href="<%= path %>" class="btn btn-outline-primary <%= active %>">
|
34
|
+
7 days
|
19
35
|
</a>
|
20
36
|
</div>
|
21
37
|
</div>
|
@@ -25,6 +25,7 @@
|
|
25
25
|
<%== partial 'shared/tab_nav', locals: { title: 'Batches', id: 'batches' } %>
|
26
26
|
<%== partial 'shared/tab_nav', locals: { title: 'Lags stored', id: 'lags-stored' } %>
|
27
27
|
<%== partial 'shared/tab_nav', locals: { title: 'Topics pace', id: 'topics-pace' } %>
|
28
|
+
<%== partial 'shared/tab_nav', locals: { title: 'Max LSO time', id: 'max-lso-time' } %>
|
28
29
|
</ul>
|
29
30
|
|
30
31
|
<div class="tab-content">
|
@@ -34,9 +35,8 @@
|
|
34
35
|
</div>
|
35
36
|
|
36
37
|
<div class="tab-pane" id="batches" role="tabpanel">
|
37
|
-
|
38
|
-
|
39
|
-
<%== partial 'shared/chart', locals: { data: data, id: 'batches', blurred: true } %>
|
38
|
+
<% data = @aggregated_charts.with(:batches, :errors, :dead, :retries) %>
|
39
|
+
<%== partial 'shared/chart', locals: { data: data, id: 'batches' } %>
|
40
40
|
</div>
|
41
41
|
|
42
42
|
<div class="tab-pane" id="lags-stored" role="tabpanel">
|
@@ -50,6 +50,12 @@
|
|
50
50
|
<% data = { topic1: set.call(20), topic2: set.call(10), topic3: set.call(100) }.to_json %>
|
51
51
|
<%== partial 'shared/chart', locals: { data: data, id: 'topics-pace', blurred: true } %>
|
52
52
|
</div>
|
53
|
+
|
54
|
+
<div class="tab-pane" id="max-lso-time" role="tabpanel">
|
55
|
+
<%== partial 'dashboard/feature_pro' %>
|
56
|
+
<% data = { max_lso: set.call(2, 0..5) }.to_json %>
|
57
|
+
<%== partial 'shared/chart', locals: { data: data, id: 'max-lso-time', blurred: true } %>
|
58
|
+
</div>
|
53
59
|
</div>
|
54
60
|
</div>
|
55
61
|
</div>
|
@@ -66,13 +72,13 @@
|
|
66
72
|
<%== partial 'shared/tab_nav', locals: { title: 'Utilization', id: 'utilization', active: true } %>
|
67
73
|
<%== partial 'shared/tab_nav', locals: { title: 'RSS', id: 'rss' } %>
|
68
74
|
<%== partial 'shared/tab_nav', locals: { title: 'Concurrency', id: 'concurrency' } %>
|
75
|
+
<%== partial 'shared/tab_nav', locals: { title: 'Data transfers', id: 'data-transfers' } %>
|
69
76
|
</ul>
|
70
77
|
|
71
78
|
<div class="tab-content">
|
72
79
|
<div class="tab-pane show active" id="utilization" role="tabpanel">
|
73
|
-
|
74
|
-
|
75
|
-
<%== partial 'shared/chart', locals: { data: data, id: 'utilization', blurred: true } %>
|
80
|
+
<% data = @aggregated_charts.with(:utilization) %>
|
81
|
+
<%== partial 'shared/chart', locals: { data: data, id: 'utilization', label_type_y: 'percentage' } %>
|
76
82
|
</div>
|
77
83
|
|
78
84
|
<div class="tab-pane show" id="rss" role="tabpanel">
|
@@ -82,9 +88,14 @@
|
|
82
88
|
</div>
|
83
89
|
|
84
90
|
<div class="tab-pane show" id="concurrency" role="tabpanel">
|
91
|
+
<% data = @aggregated_charts.with(:processes, :workers, :active_listeners, :standby_listeners) %>
|
92
|
+
<%== partial 'shared/chart', locals: { data: data, id: 'concurrency' } %>
|
93
|
+
</div>
|
94
|
+
|
95
|
+
<div class="tab-pane show" id="data-transfers" role="tabpanel">
|
85
96
|
<%== partial 'dashboard/feature_pro' %>
|
86
|
-
<% data = {
|
87
|
-
<%== partial 'shared/chart', locals: { data: data, id: '
|
97
|
+
<% data = { bytes_received: set.call(4, 10..15), bytes_sent: set.call(2, 0..5) }.to_json %>
|
98
|
+
<%== partial 'shared/chart', locals: { data: data, id: 'data-transfers', blurred: true } %>
|
88
99
|
</div>
|
89
100
|
</div>
|
90
101
|
</div>
|
@@ -36,7 +36,7 @@
|
|
36
36
|
</div>
|
37
37
|
</div>
|
38
38
|
|
39
|
-
<div class="row mb-
|
39
|
+
<div class="row mb-4">
|
40
40
|
<div class="col-sm-12">
|
41
41
|
<h5 class="mb-2">
|
42
42
|
Backtrace
|
@@ -45,32 +45,11 @@
|
|
45
45
|
</div>
|
46
46
|
</div>
|
47
47
|
|
48
|
-
<div class="mb-4">
|
49
|
-
<%== partial 'shared/feature_pro' %>
|
50
|
-
</div>
|
51
|
-
|
52
48
|
<div class="row mb-5">
|
53
49
|
<div class="col-sm-12">
|
54
50
|
<div class="card">
|
55
51
|
<div class="card-body">
|
56
|
-
<pre class="m-0 p-0
|
57
|
-
please subscribe to our Pro offering to be able to view the real one
|
58
|
-
gems/karafka-rdkafka/lib/rdkafka/consumer.rb:255:in `query_watermark_offsets'
|
59
|
-
gems/karafka/lib/karafka/admin.rb:56:in `block in read_topic'
|
60
|
-
gems/karafka/lib/karafka/admin.rb:184:in `with_consumer'
|
61
|
-
gems/karafka/lib/karafka/admin.rb:55:in `read_topic'
|
62
|
-
/mnt/software/Karafka/karafka-web/lib/karafka/web/processing/consumers/state.rb:19:in `current'
|
63
|
-
/mnt/software/Karafka/karafka-web/lib/karafka/web/processing/consumers/aggregator.rb:45:in `state'
|
64
|
-
/mnt/software/Karafka/karafka-web/lib/karafka/web/processing/consumers/aggregator.rb:38:in `to_json'
|
65
|
-
gems/karafka/lib/karafka/processing/strategies/default.rb:136:in `block in handle_shutdown'
|
66
|
-
gems/karafka-core/lib/karafka/core/monitoring/notifications.rb:118:in `measure_time_taken'
|
67
|
-
gems/karafka-core/lib/karafka/core/monitoring/notifications.rb:94:in `instrument'
|
68
|
-
gems/karafka-core/lib/karafka/core/monitoring/monitor.rb:34:in `instrument'
|
69
|
-
gems/karafka/lib/karafka/processing/strategies/default.rb:135:in `handle_shutdown'
|
70
|
-
gems/karafka/lib/karafka/base_consumer.rb:134:in `on_shutdown'
|
71
|
-
gems/karafka/lib/karafka/processing/executor.rb:123:in `shutdown'
|
72
|
-
gems/karafka/lib/karafka/processing/jobs/shutdown.rb:18:in `call'
|
73
|
-
gems/karafka/lib/karafka/helpers/async.rb:28:in `block in async_call'</code></pre>
|
52
|
+
<pre class="m-0 p-0"><code class="wrapped json p-0 m-0"><%= @error_message.payload[:backtrace] %></code></pre>
|
74
53
|
</div>
|
75
54
|
</div>
|
76
55
|
</div>
|
@@ -1,5 +1,21 @@
|
|
1
1
|
<li class="breadcrumb-item">
|
2
2
|
<a href="<%= root_path('jobs') %>">
|
3
|
-
|
3
|
+
Jobs
|
4
4
|
</a>
|
5
5
|
</li>
|
6
|
+
|
7
|
+
<% if current_path.include?('/running') %>
|
8
|
+
<li class="breadcrumb-item">
|
9
|
+
<a href="<%= root_path('jobs/running') %>">
|
10
|
+
Running
|
11
|
+
</a>
|
12
|
+
</li>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% if current_path.include?('/pending') %>
|
16
|
+
<li class="breadcrumb-item">
|
17
|
+
<a href="<%= root_path('jobs/pending') %>">
|
18
|
+
Pending
|
19
|
+
</a>
|
20
|
+
</li>
|
21
|
+
<% end %>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<div class="container">
|
2
|
+
<div class="row mb-5">
|
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(include: 'running') %>"
|
9
|
+
href="<%= root_path('jobs', 'running') %>"
|
10
|
+
>
|
11
|
+
Running (<%= @jobs_counters.running %>)
|
12
|
+
</a>
|
13
|
+
</li>
|
14
|
+
|
15
|
+
<li class="nav-item">
|
16
|
+
<a
|
17
|
+
class="nav-link <%= nav_class(include: 'pending') %>"
|
18
|
+
href="<%= root_path('jobs', 'pending') %>"
|
19
|
+
>
|
20
|
+
Pending (<%= @jobs_counters.pending %>)
|
21
|
+
</a>
|
22
|
+
</li>
|
23
|
+
</ul>
|
24
|
+
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
</div>
|
@@ -1,7 +1,9 @@
|
|
1
|
-
<%== view_title('
|
1
|
+
<%== view_title('Pending jobs', hr: false) %>
|
2
|
+
|
3
|
+
<%== partial 'jobs/tabs' %>
|
2
4
|
|
3
5
|
<% if @jobs.empty? && params.current_page <= 1 %>
|
4
|
-
<%== partial 'jobs/no_jobs' %>
|
6
|
+
<%== partial 'jobs/no_jobs', locals: { type: 'pending' } %>
|
5
7
|
<% elsif @jobs.empty? %>
|
6
8
|
<%== partial 'shared/no_paginated_data' %>
|
7
9
|
<% else %>
|
@@ -11,11 +13,11 @@
|
|
11
13
|
<table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
|
12
14
|
<thead>
|
13
15
|
<tr class="align-middle">
|
14
|
-
<th
|
15
|
-
<th
|
16
|
-
<th
|
17
|
-
<th
|
18
|
-
<th
|
16
|
+
<th><%== sort_link('Process', :name) %></th>
|
17
|
+
<th><%== sort_link(:topic) %></th>
|
18
|
+
<th><%== sort_link(:consumer) %></th>
|
19
|
+
<th><%== sort_link(:type) %></th>
|
20
|
+
<th><%== sort_link('Created at', :updated_at, rev: true) %></th>
|
19
21
|
</tr>
|
20
22
|
</thead>
|
21
23
|
<tbody>
|
@@ -1,7 +1,9 @@
|
|
1
|
-
<%== view_title('Running jobs', hr:
|
1
|
+
<%== view_title('Running jobs', hr: false) %>
|
2
|
+
|
3
|
+
<%== partial 'jobs/tabs' %>
|
2
4
|
|
3
5
|
<% if @jobs.empty? && params.current_page <= 1 %>
|
4
|
-
<%== partial 'jobs/no_jobs' %>
|
6
|
+
<%== partial 'jobs/no_jobs', locals: { type: 'running' } %>
|
5
7
|
<% elsif @jobs.empty? %>
|
6
8
|
<%== partial 'shared/no_paginated_data' %>
|
7
9
|
<% else %>
|
@@ -11,15 +13,11 @@
|
|
11
13
|
<table class="processes bg-white table table-hover table-bordered table-striped mb-0 align-middle">
|
12
14
|
<thead>
|
13
15
|
<tr class="align-middle">
|
14
|
-
<th
|
15
|
-
<th
|
16
|
-
<th
|
17
|
-
<th
|
18
|
-
<th
|
19
|
-
<th>First offset</th>
|
20
|
-
<th>Last offset</th>
|
21
|
-
<th>Committed offset</th>
|
22
|
-
<th>Started at</th>
|
16
|
+
<th><%== sort_link('Process', :name) %></th>
|
17
|
+
<th><%== sort_link(:topic) %></th>
|
18
|
+
<th><%== sort_link(:consumer) %></th>
|
19
|
+
<th><%== sort_link(:type) %></th>
|
20
|
+
<th><%== sort_link('Started at', :updated_at, rev: true) %></th>
|
23
21
|
</tr>
|
24
22
|
</thead>
|
25
23
|
<tbody>
|
@@ -13,22 +13,24 @@
|
|
13
13
|
<thead>
|
14
14
|
<tr class="align-middle">
|
15
15
|
<th>Subscription group</th>
|
16
|
-
<th
|
17
|
-
<th
|
16
|
+
<th><%== sort_link('Topic', :name) %></th>
|
17
|
+
<th><%== sort_link('Active', :active?) %></th>
|
18
18
|
<th></th>
|
19
19
|
</tr>
|
20
20
|
</thead>
|
21
21
|
<tbody>
|
22
|
-
<% consumer_group.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
<% consumer_group.subscription_groups.each do |subscription_group| %>
|
23
|
+
<% subscription_group.topics.each do |topic| %>
|
24
|
+
<%==
|
25
|
+
partial(
|
26
|
+
'routing/topic',
|
27
|
+
locals: {
|
28
|
+
subscription_group: subscription_group,
|
29
|
+
topic: topic
|
30
|
+
}
|
31
|
+
)
|
32
|
+
%>
|
33
|
+
<% end %>
|
32
34
|
<% end %>
|
33
35
|
</tbody>
|
34
36
|
</table>
|
@@ -15,7 +15,7 @@
|
|
15
15
|
</a>
|
16
16
|
</li>
|
17
17
|
<li class="nav-item ms-3">
|
18
|
-
<a class="nav-link <%= nav_class(start_with: '/jobs') %>" href="<%= root_path('jobs') %>">
|
18
|
+
<a class="nav-link <%= nav_class(start_with: '/jobs') %>" href="<%= root_path('jobs/running') %>">
|
19
19
|
Jobs
|
20
20
|
</a>
|
21
21
|
</li>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<nav>
|
5
5
|
<ul class="pagination justify-content-center">
|
6
6
|
<li class="page-item <%= 'disabled' unless @pagination.first_offset? %>">
|
7
|
-
<a class="page-link" href="<%= current_path(@pagination.offset_key => @pagination.first_offset) %>">
|
7
|
+
<a class="page-link" href="<%= current_path(@pagination.offset_key => @pagination.first_offset || 1) %>">
|
8
8
|
<span>«</span>
|
9
9
|
</a>
|
10
10
|
</li>
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<main>
|
2
|
+
<div id="content">
|
3
|
+
<div class="d-flex align-items-center justify-content-center vh-100">
|
4
|
+
<div class="error-message text-center">
|
5
|
+
<h1 class="display-1 fw-bold">403</h1>
|
6
|
+
|
7
|
+
<p class="fs-3 md-5">
|
8
|
+
<span class="text-danger">
|
9
|
+
Oops!
|
10
|
+
</span>
|
11
|
+
Not permitted.
|
12
|
+
</p>
|
13
|
+
|
14
|
+
<div class="lead">
|
15
|
+
<p class="mb-5">
|
16
|
+
You don't have permission to view this page.
|
17
|
+
</p>
|
18
|
+
|
19
|
+
<p>
|
20
|
+
Please make sure, that:
|
21
|
+
</p>
|
22
|
+
|
23
|
+
<ul class="mb-5 text-start">
|
24
|
+
<li>You have visited the <a href="<%= root_path('status') %>">Status</a> page to troubleshoot any potential issues</li>
|
25
|
+
<li>You are authorized to access the resource you requested</li>
|
26
|
+
<li>Web UI configuration permits the action you requested</li>
|
27
|
+
</ul>
|
28
|
+
|
29
|
+
<p>
|
30
|
+
<a href="<%= root_path %>" class="btn btn-primary">Go Home</a>
|
31
|
+
<a href="<%= root_path('status') %>" class="btn btn-success">Status page</a>
|
32
|
+
</p>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
</main>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
partial(
|
8
8
|
"status/#{@status.enabled.to_s}",
|
9
9
|
locals: {
|
10
|
-
title: 'Web
|
10
|
+
title: 'Web UI setup in karafka.rb',
|
11
11
|
description: partial(
|
12
12
|
"status/#{@status.enabled.partial_namespace}/enabled",
|
13
13
|
locals: {
|
@@ -37,7 +37,7 @@
|
|
37
37
|
partial(
|
38
38
|
"status/#{@status.topics.to_s}",
|
39
39
|
locals: {
|
40
|
-
title: '
|
40
|
+
title: 'Web UI topics presence',
|
41
41
|
description: partial(
|
42
42
|
'status/failures/topics',
|
43
43
|
locals: {
|
@@ -165,6 +165,21 @@
|
|
165
165
|
)
|
166
166
|
%>
|
167
167
|
|
168
|
+
<%==
|
169
|
+
partial(
|
170
|
+
"status/#{@status.routing_topics_presence.to_s}",
|
171
|
+
locals: {
|
172
|
+
title: 'Routing topics presence',
|
173
|
+
description: partial(
|
174
|
+
'status/warnings/routing_topics_presence',
|
175
|
+
locals: {
|
176
|
+
details: @status.routing_topics_presence.details
|
177
|
+
}
|
178
|
+
)
|
179
|
+
}
|
180
|
+
)
|
181
|
+
%>
|
182
|
+
|
168
183
|
<%==
|
169
184
|
partial(
|
170
185
|
"status/#{@status.pro_subscription.to_s}",
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<p>
|
2
|
+
The following active topics present in your <code>karafka.rb</code> file were not located in the Kafka cluster:
|
3
|
+
</p>
|
4
|
+
|
5
|
+
<ul>
|
6
|
+
<% details.each do |topic_name| %>
|
7
|
+
<li>
|
8
|
+
<code><%= topic_name %></code>
|
9
|
+
</li>
|
10
|
+
<% end %>
|
11
|
+
</ul>
|
12
|
+
|
13
|
+
<p>
|
14
|
+
Although not an error, having topics in <code>karafka.rb</code> that still needs to be added to Kafka could lead to issues. It's better to create these topics beforehand to avoid potential errors.
|
15
|
+
</p>
|
data/lib/karafka/web/version.rb
CHANGED
data/lib/karafka/web.rb
CHANGED
@@ -53,7 +53,10 @@ module Karafka
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
require_relative 'web/inflector'
|
57
|
+
|
56
58
|
loader = Zeitwerk::Loader.new
|
59
|
+
|
57
60
|
# Make sure pro is not loaded unless Pro
|
58
61
|
loader.ignore(Karafka::Web.gem_root.join('lib/karafka/web/ui/pro'))
|
59
62
|
|
@@ -62,9 +65,10 @@ Karafka::Licenser.detect do
|
|
62
65
|
loader = Zeitwerk::Loader.new
|
63
66
|
end
|
64
67
|
|
65
|
-
root = File.expand_path('..', __dir__)
|
66
68
|
loader.tag = 'karafka-web'
|
67
|
-
|
69
|
+
# Use our custom inflector to support migrations
|
70
|
+
root = File.expand_path('..', __dir__)
|
71
|
+
loader.inflector = Karafka::Web::Inflector.new("#{root}/karafka/web.rb")
|
68
72
|
loader.push_dir(root)
|
69
73
|
|
70
74
|
loader.setup
|
data.tar.gz.sig
CHANGED
Binary file
|