karafka-web 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +13 -13
- data/lib/karafka/web/management/actions/enable.rb +74 -10
- data/lib/karafka/web/pro/ui/app.rb +13 -0
- data/lib/karafka/web/pro/ui/controllers/base_controller.rb +4 -0
- data/lib/karafka/web/pro/ui/controllers/cluster_controller.rb +66 -4
- data/lib/karafka/web/pro/ui/controllers/consumers/consumers_controller.rb +9 -2
- data/lib/karafka/web/pro/ui/controllers/consumers/controls_controller.rb +6 -0
- data/lib/karafka/web/pro/ui/controllers/consumers/jobs_controller.rb +8 -2
- data/lib/karafka/web/pro/ui/controllers/dlq_controller.rb +6 -0
- data/lib/karafka/web/pro/ui/controllers/explorer/explorer_controller.rb +6 -0
- data/lib/karafka/web/pro/ui/controllers/health_controller.rb +19 -3
- data/lib/karafka/web/pro/ui/controllers/jobs_controller.rb +25 -0
- data/lib/karafka/web/pro/ui/controllers/recurring_tasks_controller.rb +10 -1
- data/lib/karafka/web/pro/ui/controllers/requests/params.rb +67 -0
- data/lib/karafka/web/pro/ui/controllers/routing_controller.rb +23 -1
- data/lib/karafka/web/pro/ui/controllers/scheduled_messages/schedules_controller.rb +6 -0
- data/lib/karafka/web/pro/ui/controllers/topics/configs_controller.rb +6 -1
- data/lib/karafka/web/pro/ui/controllers/topics/distributions_controller.rb +1 -1
- data/lib/karafka/web/pro/ui/controllers/topics/offsets_controller.rb +1 -1
- data/lib/karafka/web/pro/ui/controllers/topics/replications_controller.rb +1 -1
- data/lib/karafka/web/pro/ui/controllers/topics/topics_controller.rb +6 -0
- data/lib/karafka/web/pro/ui/helpers/filtering_helper.rb +173 -0
- data/lib/karafka/web/pro/ui/helpers/topics_filtering_helper.rb +80 -0
- data/lib/karafka/web/pro/ui/lib/filtering.rb +128 -0
- data/lib/karafka/web/pro/ui/lib/search/matchers/base.rb +2 -2
- data/lib/karafka/web/pro/ui/routes/cluster.rb +0 -2
- data/lib/karafka/web/pro/ui/views/cluster/_brokers_table.erb +41 -0
- data/lib/karafka/web/pro/ui/views/cluster/_configs_table.erb +41 -0
- data/lib/karafka/web/pro/ui/views/cluster/_partition.erb +2 -2
- data/lib/karafka/web/pro/ui/views/cluster/index.erb +12 -20
- data/lib/karafka/web/pro/ui/views/cluster/replication.erb +39 -0
- data/lib/karafka/web/pro/ui/views/cluster/show.erb +13 -21
- data/lib/karafka/web/pro/ui/views/consumers/consumers/_consumer_performances_table.erb +56 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumers/_consumers_table.erb +43 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_subscription_group.erb +10 -2
- data/lib/karafka/web/pro/ui/views/consumers/consumers/index.erb +8 -24
- data/lib/karafka/web/pro/ui/views/consumers/consumers/performance.erb +8 -37
- data/lib/karafka/web/pro/ui/views/consumers/consumers/subscriptions.erb +20 -6
- data/lib/karafka/web/pro/ui/views/consumers/controls/_processes_table.erb +45 -0
- data/lib/karafka/web/pro/ui/views/consumers/controls/index.erb +14 -27
- data/lib/karafka/web/pro/ui/views/consumers/jobs/_jobs_table.erb +48 -0
- data/lib/karafka/web/pro/ui/views/consumers/jobs/pending.erb +8 -29
- data/lib/karafka/web/pro/ui/views/consumers/jobs/running.erb +8 -29
- data/lib/karafka/web/pro/ui/views/dlq/index.erb +9 -1
- data/lib/karafka/web/pro/ui/views/explorer/explorer/index.erb +9 -1
- data/lib/karafka/web/pro/ui/views/health/_changes_table.erb +59 -0
- data/lib/karafka/web/pro/ui/views/health/_cluster_lags_table.erb +43 -0
- data/lib/karafka/web/pro/ui/views/health/_lags_table.erb +60 -0
- data/lib/karafka/web/pro/ui/views/health/_no_data.erb +5 -1
- data/lib/karafka/web/pro/ui/views/health/_offsets_table.erb +63 -0
- data/lib/karafka/web/pro/ui/views/health/_overview_table.erb +83 -0
- data/lib/karafka/web/pro/ui/views/health/_tabs.erb +6 -0
- data/lib/karafka/web/pro/ui/views/health/changes.erb +13 -43
- data/lib/karafka/web/pro/ui/views/health/cluster_lags.erb +11 -25
- data/lib/karafka/web/pro/ui/views/health/lags.erb +13 -44
- data/lib/karafka/web/pro/ui/views/health/offsets.erb +13 -47
- data/lib/karafka/web/pro/ui/views/health/overview.erb +13 -67
- data/lib/karafka/web/pro/ui/views/jobs/_jobs_table.erb +48 -0
- data/lib/karafka/web/pro/ui/views/jobs/pending.erb +8 -30
- data/lib/karafka/web/pro/ui/views/jobs/running.erb +8 -30
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_tasks_table.erb +43 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/schedule.erb +8 -24
- data/lib/karafka/web/pro/ui/views/routing/_consumer_group.erb +36 -32
- data/lib/karafka/web/pro/ui/views/routing/_details_table.erb +43 -0
- data/lib/karafka/web/pro/ui/views/routing/index.erb +18 -6
- data/lib/karafka/web/pro/ui/views/routing/show.erb +12 -40
- data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/index.erb +7 -1
- data/lib/karafka/web/pro/ui/views/shared/_filter_box.erb +61 -0
- data/lib/karafka/web/pro/ui/views/topics/configs/_configs_table.erb +42 -0
- data/lib/karafka/web/pro/ui/views/topics/configs/index.erb +13 -22
- data/lib/karafka/web/pro/ui/views/topics/replications/_partition.erb +2 -2
- data/lib/karafka/web/pro/ui/views/topics/replications/show.erb +12 -2
- data/lib/karafka/web/pro/ui/views/topics/topics/index.erb +9 -1
- data/lib/karafka/web/tracking/consumers/listeners/errors.rb +80 -14
- data/lib/karafka/web/ui/base.rb +4 -0
- data/lib/karafka/web/ui/controllers/base_controller.rb +1 -1
- data/lib/karafka/web/ui/controllers/cluster_controller.rb +21 -22
- data/lib/karafka/web/ui/controllers/consumers_controller.rb +1 -1
- data/lib/karafka/web/ui/controllers/jobs_controller.rb +23 -27
- data/lib/karafka/web/ui/controllers/requests/hookable.rb +5 -0
- data/lib/karafka/web/ui/controllers/routing_controller.rb +15 -1
- data/lib/karafka/web/ui/helpers/application_helper.rb +3 -278
- data/lib/karafka/web/ui/helpers/badges_helper.rb +66 -0
- data/lib/karafka/web/ui/helpers/formatting_helper.rb +77 -0
- data/lib/karafka/web/ui/helpers/partitions_helper.rb +167 -0
- data/lib/karafka/web/ui/helpers/sorting_helper.rb +78 -0
- data/lib/karafka/web/ui/lib/filter.rb +377 -0
- data/lib/karafka/web/ui/lib/hash_flattener.rb +37 -0
- data/lib/karafka/web/ui/lib/sorter.rb +3 -1
- data/lib/karafka/web/ui/models/jobs.rb +3 -2
- data/lib/karafka/web/ui/models/process.rb +12 -0
- data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
- data/lib/karafka/web/ui/public/stylesheets/application.css +9 -0
- data/lib/karafka/web/ui/public/stylesheets/application.min.css +4230 -1258
- data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
- data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
- data/lib/karafka/web/ui/public/stylesheets/libs/highlight_dark.min.css.gz +0 -0
- data/lib/karafka/web/ui/public/stylesheets/libs/highlight_light.min.css.gz +0 -0
- data/lib/karafka/web/ui/views/cluster/_brokers_table.erb +21 -0
- data/lib/karafka/web/ui/views/cluster/_partition.erb +2 -2
- data/lib/karafka/web/ui/views/cluster/_partitions_table.erb +31 -0
- data/lib/karafka/web/ui/views/cluster/brokers.erb +1 -21
- data/lib/karafka/web/ui/views/cluster/replication.erb +1 -23
- data/lib/karafka/web/ui/views/consumers/_consumers_table.erb +22 -0
- data/lib/karafka/web/ui/views/consumers/index.erb +1 -22
- data/lib/karafka/web/ui/views/errors/_table.erb +28 -0
- data/lib/karafka/web/ui/views/errors/index.erb +1 -28
- data/lib/karafka/web/ui/views/jobs/_jobs_table.erb +22 -0
- data/lib/karafka/web/ui/views/jobs/pending.erb +1 -22
- data/lib/karafka/web/ui/views/jobs/running.erb +1 -22
- data/lib/karafka/web/ui/views/routing/_consumer_group.erb +18 -12
- data/lib/karafka/web/ui/views/routing/_details_table.erb +23 -0
- data/lib/karafka/web/ui/views/routing/show.erb +1 -29
- data/lib/karafka/web/ui/views/shared/_no_filter_results.erb +6 -0
- data/lib/karafka/web/version.rb +1 -1
- data/package-lock.json +98 -61
- metadata +35 -1
|
@@ -22,27 +22,18 @@
|
|
|
22
22
|
|
|
23
23
|
<%== partial 'topics/topics/tabs' %>
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<%==
|
|
39
|
-
each_partial(
|
|
40
|
-
@configs,
|
|
41
|
-
'topics/configs/config'
|
|
42
|
-
)
|
|
43
|
-
%>
|
|
44
|
-
</tbody>
|
|
45
|
-
</table>
|
|
46
|
-
</div>
|
|
25
|
+
<% if filtering? || !@configs.empty? %>
|
|
26
|
+
<div class="col-span-12 mb-3">
|
|
27
|
+
<%== filter_box %>
|
|
28
|
+
</div>
|
|
29
|
+
<% end %>
|
|
30
|
+
|
|
31
|
+
<% if filtering? && @configs.empty? %>
|
|
32
|
+
<div class="col-span-12">
|
|
33
|
+
<%== partial 'shared/no_filter_results' %>
|
|
34
|
+
</div>
|
|
35
|
+
<% else %>
|
|
36
|
+
<%== partial 'topics/configs/configs_table' %>
|
|
37
|
+
<% end %>
|
|
47
38
|
|
|
48
39
|
<%== partial 'topics/configs/delete_button' %>
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
<%= partition[:leader] %>
|
|
29
29
|
</td>
|
|
30
30
|
<td>
|
|
31
|
-
|
|
31
|
+
<%== partition_replica_brokers(partition, link: true) %>
|
|
32
32
|
</td>
|
|
33
33
|
<td>
|
|
34
|
-
|
|
34
|
+
<%== partition_in_sync_brokers(partition, link: true) %>
|
|
35
35
|
</td>
|
|
36
36
|
</tr>
|
|
@@ -24,14 +24,24 @@
|
|
|
24
24
|
|
|
25
25
|
<%== partial 'topics/replications/replication_info' %>
|
|
26
26
|
|
|
27
|
+
<div class="mb-3 flex justify-end">
|
|
28
|
+
<small class="text-muted">
|
|
29
|
+
Broker roles:
|
|
30
|
+
<span class="badge badge-primary">leader</span>
|
|
31
|
+
<span class="badge badge-info">replica</span>
|
|
32
|
+
<span class="badge badge-success">in-sync</span>
|
|
33
|
+
<span class="badge badge-warning">out-of-sync</span>
|
|
34
|
+
</small>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
27
37
|
<div class="data-table-wrapper">
|
|
28
38
|
<table class="data-table">
|
|
29
39
|
<thead>
|
|
30
40
|
<tr>
|
|
31
41
|
<th><%== sort_link(:partition_id) %></th>
|
|
32
42
|
<th><%== sort_link(:leader) %></th>
|
|
33
|
-
<th><%== sort_link(:replica_count) %></th>
|
|
34
|
-
<th><%== sort_link('In
|
|
43
|
+
<th><%== sort_link('Replicas', :replica_count) %></th>
|
|
44
|
+
<th><%== sort_link('In-Sync (ISR)', :in_sync_replica_brokers) %></th>
|
|
35
45
|
</tr>
|
|
36
46
|
</thead>
|
|
37
47
|
<tbody>
|
|
@@ -22,8 +22,16 @@
|
|
|
22
22
|
|
|
23
23
|
<%== partial 'topics/topics/create_button' %>
|
|
24
24
|
|
|
25
|
-
<% if
|
|
25
|
+
<% if filtering? || !@topics.empty? %>
|
|
26
|
+
<div class="col-span-12 mb-3">
|
|
27
|
+
<%== filter_box %>
|
|
28
|
+
</div>
|
|
29
|
+
<% end %>
|
|
30
|
+
|
|
31
|
+
<% if @topics.empty? && !filtering? %>
|
|
26
32
|
<%== partial 'explorer/explorer/no_topics' %>
|
|
33
|
+
<% elsif @topics.empty? %>
|
|
34
|
+
<%== partial 'shared/no_filter_results' %>
|
|
27
35
|
<% else %>
|
|
28
36
|
<div class="topic-tiles">
|
|
29
37
|
<%==
|
|
@@ -18,20 +18,11 @@ module Karafka
|
|
|
18
18
|
#
|
|
19
19
|
# @param event [Karafka::Core::Monitoring::Event]
|
|
20
20
|
def on_error_occurred(event)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
when Karafka::BaseConsumer
|
|
27
|
-
extract_consumer_info(caller_ref)
|
|
28
|
-
when Karafka::Connection::Client
|
|
29
|
-
extract_client_info(caller_ref)
|
|
30
|
-
when Karafka::Connection::Listener
|
|
31
|
-
extract_listener_info(caller_ref)
|
|
32
|
-
else
|
|
33
|
-
{}
|
|
34
|
-
end
|
|
21
|
+
# Error details come from two independent sources that we merge together:
|
|
22
|
+
# - the caller: the user code context in which the error happened
|
|
23
|
+
# - the error type: extra diagnostics some error types carry in the event payload
|
|
24
|
+
details = extract_caller_details(event[:caller])
|
|
25
|
+
.merge(extract_type_details(event))
|
|
35
26
|
|
|
36
27
|
error_class, error_message, backtrace = extract_error_info(event[:error])
|
|
37
28
|
|
|
@@ -72,6 +63,38 @@ module Karafka
|
|
|
72
63
|
|
|
73
64
|
private
|
|
74
65
|
|
|
66
|
+
# Collects error details based on who reported the error, that is the user code
|
|
67
|
+
# context in which it happened (consumer, client or listener).
|
|
68
|
+
#
|
|
69
|
+
# @param caller_ref [Object] object that reported the error
|
|
70
|
+
# @return [Hash] hash with caller specific info for details of error
|
|
71
|
+
def extract_caller_details(caller_ref)
|
|
72
|
+
case caller_ref
|
|
73
|
+
when Karafka::BaseConsumer
|
|
74
|
+
extract_consumer_info(caller_ref)
|
|
75
|
+
when Karafka::Connection::Client
|
|
76
|
+
extract_client_info(caller_ref)
|
|
77
|
+
when Karafka::Connection::Listener
|
|
78
|
+
extract_listener_info(caller_ref)
|
|
79
|
+
else
|
|
80
|
+
{}
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Collects error details based on the error type. Some error types carry extra
|
|
85
|
+
# diagnostics in the event payload that do not come from the caller.
|
|
86
|
+
#
|
|
87
|
+
# @param event [Karafka::Core::Monitoring::Event]
|
|
88
|
+
# @return [Hash] hash with type specific info for details of error
|
|
89
|
+
def extract_type_details(event)
|
|
90
|
+
case event[:type]
|
|
91
|
+
when "app.stopping.error"
|
|
92
|
+
extract_forceful_shutdown_info(event)
|
|
93
|
+
else
|
|
94
|
+
{}
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
75
98
|
# @param consumer [::Karafka::BaseConsumer]
|
|
76
99
|
# @return [Hash] hash with consumer specific info for details of error
|
|
77
100
|
def extract_consumer_info(consumer)
|
|
@@ -111,6 +134,49 @@ module Karafka
|
|
|
111
134
|
id: listener.id
|
|
112
135
|
}
|
|
113
136
|
end
|
|
137
|
+
|
|
138
|
+
# Extracts details about what was still blocking when Karafka forcefully terminated.
|
|
139
|
+
# Karafka publishes the listeners that were still active and the jobs that were still
|
|
140
|
+
# in the processing pipeline alongside the forceful shutdown error.
|
|
141
|
+
#
|
|
142
|
+
# The lists are formatted into readable strings so they render as regular rows in the
|
|
143
|
+
# generic error details table (same presentation as every other error).
|
|
144
|
+
#
|
|
145
|
+
# @param event [Karafka::Core::Monitoring::Event]
|
|
146
|
+
# @return [Hash] hash with forceful shutdown diagnostics for details of error
|
|
147
|
+
def extract_forceful_shutdown_info(event)
|
|
148
|
+
active_listeners = event[:active_listeners] || []
|
|
149
|
+
alive_workers = event[:alive_workers] || []
|
|
150
|
+
in_processing = event[:in_processing] || {}
|
|
151
|
+
|
|
152
|
+
listeners = active_listeners.map do |listener|
|
|
153
|
+
"#{listener.id} (#{listener.subscription_group.id})"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
jobs = in_processing.flat_map do |group_id, group_jobs|
|
|
157
|
+
group_jobs.map { |job| format_in_processing_job(group_id, job) }
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Only include the listener/job lists when there is something to show, so we do not
|
|
161
|
+
# render empty rows in the error details table
|
|
162
|
+
details = { alive_workers: alive_workers.size }
|
|
163
|
+
details[:active_listeners] = listeners.join(", ") unless listeners.empty?
|
|
164
|
+
details[:in_processing] = jobs.join("; ") unless jobs.empty?
|
|
165
|
+
details
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Formats a single job that was still in processing into a readable description.
|
|
169
|
+
#
|
|
170
|
+
# @param group_id [String] subscription group id the job belongs to
|
|
171
|
+
# @param job [Object] job that was still in the processing pipeline
|
|
172
|
+
# @return [String] readable job description
|
|
173
|
+
def format_in_processing_job(group_id, job)
|
|
174
|
+
status = job.non_blocking? ? "non-blocking" : "blocking"
|
|
175
|
+
job_type = job.class.name.split("::").last
|
|
176
|
+
|
|
177
|
+
"#{job_type} #{job.executor.topic.name}/#{job.executor.partition} " \
|
|
178
|
+
"(#{group_id}, #{status})"
|
|
179
|
+
end
|
|
114
180
|
end
|
|
115
181
|
end
|
|
116
182
|
end
|
data/lib/karafka/web/ui/base.rb
CHANGED
|
@@ -7,6 +7,10 @@ module Karafka
|
|
|
7
7
|
class Base < Roda
|
|
8
8
|
include Helpers::PathsHelper
|
|
9
9
|
include Helpers::ApplicationHelper
|
|
10
|
+
include Helpers::BadgesHelper
|
|
11
|
+
include Helpers::FormattingHelper
|
|
12
|
+
include Helpers::PartitionsHelper
|
|
13
|
+
include Helpers::SortingHelper
|
|
10
14
|
include Helpers::TimeHelper
|
|
11
15
|
include Helpers::TopicsHelper
|
|
12
16
|
include Helpers::TailwindHelper
|
|
@@ -132,7 +132,7 @@ module Karafka
|
|
|
132
132
|
|
|
133
133
|
# @param resources [Hash, Array, Lib::HashProxy] object for sorting
|
|
134
134
|
# @return [Hash, Array, Lib::HashProxy] sorted results
|
|
135
|
-
def
|
|
135
|
+
def sort(resources)
|
|
136
136
|
Lib::Sorter.new(
|
|
137
137
|
@params.current_sort,
|
|
138
138
|
allowed_attributes: self.class.sortable_attributes
|
|
@@ -22,27 +22,15 @@ module Karafka
|
|
|
22
22
|
|
|
23
23
|
# Lists available brokers in the cluster
|
|
24
24
|
def brokers
|
|
25
|
-
@brokers =
|
|
25
|
+
@brokers = sort(Models::ClusterInfo.fetch.brokers)
|
|
26
26
|
|
|
27
27
|
render
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# List partitions replication details
|
|
31
31
|
def replication
|
|
32
|
-
partitions_total = []
|
|
33
|
-
|
|
34
|
-
displayable_topics(cluster_info).each do |topic|
|
|
35
|
-
topic[:partitions].each do |partition|
|
|
36
|
-
partitions_total << partition.merge(
|
|
37
|
-
topic: topic,
|
|
38
|
-
# Will allow sorting by name
|
|
39
|
-
topic_name: topic.fetch(:topic_name)
|
|
40
|
-
)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
32
|
@partitions, last_page = Paginators::Arrays.call(
|
|
45
|
-
|
|
33
|
+
sort(replication_partitions),
|
|
46
34
|
@params.current_page
|
|
47
35
|
)
|
|
48
36
|
|
|
@@ -53,16 +41,27 @@ module Karafka
|
|
|
53
41
|
|
|
54
42
|
private
|
|
55
43
|
|
|
56
|
-
#
|
|
57
|
-
|
|
58
|
-
|
|
44
|
+
# Expands the displayable cluster topics into one flat row per partition, which the
|
|
45
|
+
# replication table renders, sorts and paginates. Each row is a partition carrying its
|
|
46
|
+
# topic (and topic name, so it can be sorted/filtered by name).
|
|
47
|
+
#
|
|
48
|
+
# @return [Array<Hash>] partition rows
|
|
49
|
+
def replication_partitions
|
|
50
|
+
displayable_topics.flat_map do |topic|
|
|
51
|
+
topic[:partitions].map do |partition|
|
|
52
|
+
partition.merge(
|
|
53
|
+
topic: topic,
|
|
54
|
+
topic_name: topic.fetch(:topic_name)
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
59
58
|
end
|
|
60
59
|
|
|
61
|
-
# @
|
|
62
|
-
#
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
# @return [Array<Hash>] cluster topics to display in an alphabetical order, with internal
|
|
61
|
+
# topics excluded unless the visibility config allows them
|
|
62
|
+
def displayable_topics
|
|
63
|
+
all = Models::ClusterInfo
|
|
64
|
+
.fetch
|
|
66
65
|
.topics
|
|
67
66
|
.sort_by { |topic| topic[:topic_name] }
|
|
68
67
|
|
|
@@ -18,7 +18,7 @@ module Karafka
|
|
|
18
18
|
@current_state = Models::ConsumersState.current!
|
|
19
19
|
@counters = Models::Counters.new(@current_state)
|
|
20
20
|
@processes, last_page = Paginators::Arrays.call(
|
|
21
|
-
|
|
21
|
+
sort(Models::Processes.active(@current_state)),
|
|
22
22
|
@params.current_page
|
|
23
23
|
)
|
|
24
24
|
|
|
@@ -16,56 +16,52 @@ module Karafka
|
|
|
16
16
|
|
|
17
17
|
# Lists running jobs
|
|
18
18
|
def running
|
|
19
|
-
|
|
20
|
-
processes = Models::Processes.active(current_state)
|
|
21
|
-
|
|
22
|
-
@jobs_counters = count_jobs_types(processes)
|
|
23
|
-
|
|
24
|
-
# Aggregate jobs and inject the process info into them for better reporting
|
|
25
|
-
jobs_total = processes.flat_map do |process|
|
|
26
|
-
process.jobs.running.map do |job|
|
|
27
|
-
job.to_h[:process] = process
|
|
28
|
-
job
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
@jobs, last_page = Paginators::Arrays.call(
|
|
33
|
-
refine(jobs_total),
|
|
34
|
-
@params.current_page
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
paginate(@params.current_page, !last_page)
|
|
19
|
+
paginate_jobs(build_jobs(:running))
|
|
38
20
|
|
|
39
21
|
render
|
|
40
22
|
end
|
|
41
23
|
|
|
42
24
|
# Lists pending jobs
|
|
43
25
|
def pending
|
|
26
|
+
paginate_jobs(build_jobs(:pending))
|
|
27
|
+
|
|
28
|
+
render
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
# Aggregates jobs of a given type across all active processes, injecting the process info
|
|
34
|
+
# into each job for better reporting.
|
|
35
|
+
#
|
|
36
|
+
# @param type [Symbol] `:running` or `:pending`
|
|
37
|
+
# @return [Array] aggregated jobs
|
|
38
|
+
def build_jobs(type)
|
|
44
39
|
current_state = Models::ConsumersState.current!
|
|
45
40
|
processes = Models::Processes.active(current_state)
|
|
46
41
|
|
|
47
42
|
@jobs_counters = count_jobs_types(processes)
|
|
48
43
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
process.jobs.pending.map do |job|
|
|
44
|
+
processes.flat_map do |process|
|
|
45
|
+
process.jobs.public_send(type).map do |job|
|
|
52
46
|
job.to_h[:process] = process
|
|
53
47
|
job
|
|
54
48
|
end
|
|
55
49
|
end
|
|
50
|
+
end
|
|
56
51
|
|
|
52
|
+
# Sorts and paginates the aggregated jobs into `@jobs`. This is the seam a Pro subclass
|
|
53
|
+
# overrides to also apply filtering (a Pro-only feature); OSS only sorts.
|
|
54
|
+
#
|
|
55
|
+
# @param jobs_total [Array] aggregated jobs
|
|
56
|
+
def paginate_jobs(jobs_total)
|
|
57
57
|
@jobs, last_page = Paginators::Arrays.call(
|
|
58
|
-
|
|
58
|
+
sort(jobs_total),
|
|
59
59
|
@params.current_page
|
|
60
60
|
)
|
|
61
61
|
|
|
62
62
|
paginate(@params.current_page, !last_page)
|
|
63
|
-
|
|
64
|
-
render
|
|
65
63
|
end
|
|
66
64
|
|
|
67
|
-
private
|
|
68
|
-
|
|
69
65
|
# @param processes [Array<Process>]
|
|
70
66
|
# @return [Lib::HashProxy] particular type jobs count
|
|
71
67
|
def count_jobs_types(processes)
|
|
@@ -78,6 +78,11 @@ module Karafka
|
|
|
78
78
|
#
|
|
79
79
|
# @param action_name [Symbol] the method name being invoked
|
|
80
80
|
def run_before_hooks(action_name)
|
|
81
|
+
# Track the dispatched action so controllers can resolve per-action configuration
|
|
82
|
+
# (e.g. `filterable_attributes`) from within the hooks and their action body, before
|
|
83
|
+
# `render` is ever reached
|
|
84
|
+
@current_action_name = action_name
|
|
85
|
+
|
|
81
86
|
self.class.before_hooks.each do |actions, block|
|
|
82
87
|
instance_exec(&block) if actions.empty? || actions.include?(action_name)
|
|
83
88
|
end
|
|
@@ -9,6 +9,7 @@ module Karafka
|
|
|
9
9
|
self.sortable_attributes = %w[
|
|
10
10
|
name
|
|
11
11
|
active?
|
|
12
|
+
value
|
|
12
13
|
].freeze
|
|
13
14
|
|
|
14
15
|
# Routing list
|
|
@@ -16,7 +17,7 @@ module Karafka
|
|
|
16
17
|
@routes = Karafka::App.routes
|
|
17
18
|
|
|
18
19
|
@routes.each do |consumer_group|
|
|
19
|
-
|
|
20
|
+
sort(consumer_group.topics)
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
render
|
|
@@ -30,8 +31,21 @@ module Karafka
|
|
|
30
31
|
|
|
31
32
|
@topic || not_found!(topic_id)
|
|
32
33
|
|
|
34
|
+
# Present the routing settings as a flat, sortable list of name/value rows
|
|
35
|
+
@details = sort(topic_detail_rows(@topic))
|
|
36
|
+
|
|
33
37
|
render
|
|
34
38
|
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# @param topic [Karafka::Routing::Topic] topic we present the routing details for
|
|
43
|
+
# @return [Array<Hash>] `{ name:, value: }` rows for every routing setting
|
|
44
|
+
def topic_detail_rows(topic)
|
|
45
|
+
rows = Lib::HashFlattener.call(topic.subscription_group.kafka, "kafka")
|
|
46
|
+
rows.merge!(Lib::HashFlattener.call(topic.to_h.except(:kafka)))
|
|
47
|
+
rows.map { |name, value| { name: name.to_s, value: value } }
|
|
48
|
+
end
|
|
35
49
|
end
|
|
36
50
|
end
|
|
37
51
|
end
|