karafka-web 0.8.0 → 0.8.1
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/CHANGELOG.md +8 -0
- data/Gemfile.lock +1 -1
- data/lib/karafka/web/config.rb +4 -0
- data/lib/karafka/web/contracts/config.rb +1 -0
- data/lib/karafka/web/installer.rb +3 -2
- data/lib/karafka/web/management/actions/enable.rb +5 -0
- data/lib/karafka/web/management/actions/extend_boot_file.rb +3 -1
- data/lib/karafka/web/management/migrations/1706607960_introduce_lag_total_in_metrics.rb +38 -0
- data/lib/karafka/web/management/migrations/1706607960_introduce_lag_total_in_states.rb +22 -0
- data/lib/karafka/web/management/migrations/1706611396_rename_lag_total_to_lag_hybrid_in_metrics.rb +36 -0
- data/lib/karafka/web/management/migrations/1706611396_rename_lag_total_to_lag_hybrid_in_states.rb +21 -0
- data/lib/karafka/web/processing/consumers/aggregators/metrics.rb +7 -9
- data/lib/karafka/web/processing/consumers/aggregators/state.rb +8 -9
- data/lib/karafka/web/processing/consumers/contracts/aggregated_stats.rb +1 -2
- data/lib/karafka/web/processing/consumers/contracts/topic_stats.rb +1 -2
- data/lib/karafka/web/ui/controllers/consumers.rb +1 -1
- data/lib/karafka/web/ui/models/metrics/charts/topics.rb +5 -5
- data/lib/karafka/web/ui/models/partition.rb +22 -0
- data/lib/karafka/web/ui/models/process.rb +3 -14
- data/lib/karafka/web/ui/pro/app.rb +4 -0
- data/lib/karafka/web/ui/pro/controllers/consumers.rb +10 -4
- data/lib/karafka/web/ui/pro/controllers/health.rb +12 -0
- data/lib/karafka/web/ui/pro/views/consumers/_consumer.erb +1 -1
- data/lib/karafka/web/ui/pro/views/consumers/_counters.erb +2 -2
- data/lib/karafka/web/ui/pro/views/consumers/consumer/_partition.erb +3 -3
- data/lib/karafka/web/ui/pro/views/consumers/consumer/_subscription_group.erb +2 -2
- data/lib/karafka/web/ui/pro/views/consumers/index.erb +1 -1
- data/lib/karafka/web/ui/pro/views/dashboard/index.erb +3 -3
- data/lib/karafka/web/ui/pro/views/health/_breadcrumbs.erb +8 -0
- data/lib/karafka/web/ui/pro/views/health/_consumer_group_header.erb +14 -0
- data/lib/karafka/web/ui/pro/views/health/_partition.erb +1 -9
- data/lib/karafka/web/ui/pro/views/health/_partition_lags.erb +24 -0
- data/lib/karafka/web/ui/pro/views/health/_partition_offset.erb +1 -1
- data/lib/karafka/web/ui/pro/views/health/_tabs.erb +9 -0
- data/lib/karafka/web/ui/pro/views/health/changes.erb +1 -15
- data/lib/karafka/web/ui/pro/views/health/lags.erb +52 -0
- data/lib/karafka/web/ui/pro/views/health/offsets.erb +2 -15
- data/lib/karafka/web/ui/pro/views/health/overview.erb +2 -17
- data/lib/karafka/web/ui/views/consumers/_counters.erb +2 -2
- data/lib/karafka/web/ui/views/consumers/index.erb +1 -1
- data/lib/karafka/web/ui/views/dashboard/index.erb +3 -3
- data/lib/karafka/web/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +9 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69148848d89de8a7c5a1cebec7d3f5c0c60e3bd85caa41eedea8b5082dd6bf85
|
4
|
+
data.tar.gz: c0f6acfdd3e732ebfc29a6e954cd8a1f8d2c75dff77eba28978a99d6394d4087
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a89e22500fc5fedf8e432b666a84cf092d13c9b2747a4d08dc983d8ffba2f077781f06a131631b6315c64764bc00b7d06265a4d9fcd8c11bdd74d47eda5041f9
|
7
|
+
data.tar.gz: 7d29af2874b1df83af78fee69af89021bdcd1fa705686370f59ab276ee6808eef98e4a0b98dd273158888b472cea203bcca84f494e84c178f7733404b080166a
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Karafka Web changelog
|
2
2
|
|
3
|
+
## 0.8.1 (2024-02-01)
|
4
|
+
- [Enhancement] Introduce "Lags" health view.
|
5
|
+
- [Enhancement] Remove "Stored Lag" and "Committed Offset" from Health Overview due to Lags Tab.
|
6
|
+
- [Enhancement] Report lag on consumers that did not yet marked offsets.
|
7
|
+
- [Enhancement] Use more accurate lag reporting that compensates for lack of stored lag.
|
8
|
+
- [Fix] When first message after process start is crashed without DLQ lag is not reported.
|
9
|
+
- [Fix] Wrong order of enabled injection causes fresh install to crash.
|
10
|
+
|
3
11
|
## 0.8.0 (2024-01-26)
|
4
12
|
- **[Feature]** Provide ability to sort table data for part of the views (note: not all attributes can be sorted due to technical limitations of sub-components fetching from Kafka).
|
5
13
|
- **[Feature]** Track and report pause timeouts via "Changes" view in Health.
|
data/Gemfile.lock
CHANGED
data/lib/karafka/web/config.rb
CHANGED
@@ -6,6 +6,10 @@ module Karafka
|
|
6
6
|
class Config
|
7
7
|
include ::Karafka::Core::Configurable
|
8
8
|
|
9
|
+
# Is the Web UI enabled and things were configured.
|
10
|
+
# Automatically set to true in case things got enabled.
|
11
|
+
setting :enabled, default: false
|
12
|
+
|
9
13
|
# How long do we consider the process alive without receiving status info about it
|
10
14
|
# For this long we also display dead processes (shutdown) in the UI
|
11
15
|
# This is used both in the processing for eviction and in the UI
|
@@ -10,6 +10,7 @@ module Karafka
|
|
10
10
|
# Use the same regexp as Karafka for topics validation
|
11
11
|
TOPIC_REGEXP = ::Karafka::Contracts::TOPIC_REGEXP
|
12
12
|
|
13
|
+
required(:enabled) { |val| [true, false, nil].include?(val) }
|
13
14
|
required(:ttl) { |val| val.is_a?(Numeric) && val.positive? }
|
14
15
|
|
15
16
|
nested(:topics) do
|
@@ -15,17 +15,18 @@ module Karafka
|
|
15
15
|
puts
|
16
16
|
puts 'Installing Karafka Web UI...'
|
17
17
|
puts
|
18
|
+
Management::Actions::ExtendBootFile.new.call
|
19
|
+
puts
|
18
20
|
puts 'Creating necessary topics and populating state data...'
|
19
21
|
puts
|
20
22
|
Management::Actions::CreateTopics.new.call(replication_factor)
|
21
23
|
wait_for_topics
|
24
|
+
enable!
|
22
25
|
Management::Actions::CreateInitialStates.new.call
|
23
26
|
puts
|
24
27
|
puts 'Running data migrations...'
|
25
28
|
Management::Actions::MigrateStatesData.new.call
|
26
29
|
puts
|
27
|
-
Management::Actions::ExtendBootFile.new.call
|
28
|
-
puts
|
29
30
|
puts("Installation #{green('completed')}. Have fun!")
|
30
31
|
puts
|
31
32
|
end
|
@@ -10,6 +10,11 @@ module Karafka
|
|
10
10
|
class Enable < Base
|
11
11
|
# Enables routing consumer group and subscribes Web-UI listeners
|
12
12
|
def call
|
13
|
+
# Prevent double enabling
|
14
|
+
return if ::Karafka::Web.config.enabled
|
15
|
+
|
16
|
+
::Karafka::Web.config.enabled = true
|
17
|
+
|
13
18
|
extend_routing
|
14
19
|
setup_tracking_activity
|
15
20
|
|
@@ -22,7 +22,9 @@ module Karafka
|
|
22
22
|
|
23
23
|
# Adds needed code
|
24
24
|
def call
|
25
|
-
|
25
|
+
# We detect this that way so in case our template or user has enabled as a comment
|
26
|
+
# it still adds the template and runs install
|
27
|
+
if File.readlines(Karafka.boot_file).any? { |line| line.start_with?(ENABLER_CODE) }
|
26
28
|
puts "Web UI #{already} installed."
|
27
29
|
else
|
28
30
|
puts 'Updating the Karafka boot file...'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Web
|
5
|
+
module Management
|
6
|
+
module Migrations
|
7
|
+
# Moves to using lag total as a normalization for both lags
|
8
|
+
class IntroduceLagTotalInMetrics < Base
|
9
|
+
self.versions_until = '1.2.0'
|
10
|
+
self.type = :consumers_metrics
|
11
|
+
|
12
|
+
# @param state [Hash]
|
13
|
+
def migrate(state)
|
14
|
+
state[:aggregated].each_value do |metrics|
|
15
|
+
metrics.each do |metric|
|
16
|
+
metric.last[:lag_total] = metric.last[:lag_stored]
|
17
|
+
metric.last.delete(:lag_stored)
|
18
|
+
metric.last.delete(:lag)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
state[:consumer_groups].each_value do |metrics|
|
23
|
+
metrics.each do |metric_group|
|
24
|
+
metric_group.last.each_value do |metric|
|
25
|
+
metric.each_value do |sample|
|
26
|
+
sample[:lag_total] = sample[:lag_stored]
|
27
|
+
sample.delete(:lag_stored)
|
28
|
+
sample.delete(:lag)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Web
|
5
|
+
module Management
|
6
|
+
module Migrations
|
7
|
+
# Moves to using lag total as a normalization for both lags
|
8
|
+
class IntroduceLagTotalInStates < Base
|
9
|
+
self.versions_until = '1.3.0'
|
10
|
+
self.type = :consumers_state
|
11
|
+
|
12
|
+
# @param state [Hash]
|
13
|
+
def migrate(state)
|
14
|
+
state[:stats][:lag_total] = state[:stats][:lag_stored]
|
15
|
+
state[:stats].delete(:lag)
|
16
|
+
state[:stats].delete(:lag_stored)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/karafka/web/management/migrations/1706611396_rename_lag_total_to_lag_hybrid_in_metrics.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Web
|
5
|
+
module Management
|
6
|
+
module Migrations
|
7
|
+
# Renames total lag to hybrid to better represent what it is
|
8
|
+
class RenameLagTotalToLagHybridInMetrics < Base
|
9
|
+
self.versions_until = '1.2.1'
|
10
|
+
self.type = :consumers_metrics
|
11
|
+
|
12
|
+
# @param state [Hash]
|
13
|
+
def migrate(state)
|
14
|
+
state[:aggregated].each_value do |metrics|
|
15
|
+
metrics.each do |metric|
|
16
|
+
metric.last[:lag_hybrid] = metric.last[:lag_total] || 0
|
17
|
+
metric.last.delete(:lag_total)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
state[:consumer_groups].each_value do |metrics|
|
22
|
+
metrics.each do |metric_group|
|
23
|
+
metric_group.last.each_value do |metric|
|
24
|
+
metric.each_value do |sample|
|
25
|
+
sample[:lag_hybrid] = sample[:lag_total]
|
26
|
+
sample.delete(:lag_total)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/karafka/web/management/migrations/1706611396_rename_lag_total_to_lag_hybrid_in_states.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Web
|
5
|
+
module Management
|
6
|
+
module Migrations
|
7
|
+
# Renames total lag to hybrid to better represent what it is
|
8
|
+
class RenameLagTotalToLagHybridInStates < Base
|
9
|
+
self.versions_until = '1.3.1'
|
10
|
+
self.type = :consumers_state
|
11
|
+
|
12
|
+
# @param state [Hash]
|
13
|
+
def migrate(state)
|
14
|
+
state[:stats][:lag_hybrid] = state[:stats][:lag_total] || 0
|
15
|
+
state[:stats].delete(:lag_total)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -11,7 +11,7 @@ module Karafka
|
|
11
11
|
class Metrics < Base
|
12
12
|
# Current schema version
|
13
13
|
# This is used for detecting incompatible changes and writing migrations
|
14
|
-
SCHEMA_VERSION = '1.1
|
14
|
+
SCHEMA_VERSION = '1.2.1'
|
15
15
|
|
16
16
|
def initialize
|
17
17
|
super
|
@@ -92,12 +92,11 @@ module Karafka
|
|
92
92
|
cgs = {}
|
93
93
|
|
94
94
|
iterate_partitions_data do |group_name, topic_name, partitions_data|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
.map { |p_details| p_details.fetch(:lag_stored, -1) }
|
95
|
+
lags_hybrid = partitions_data
|
96
|
+
.map do |p_details|
|
97
|
+
lag_stored = p_details.fetch(:lag_stored, -1)
|
98
|
+
lag_stored.negative? ? p_details.fetch(:lag, -1) : lag_stored
|
99
|
+
end
|
101
100
|
.reject(&:negative?)
|
102
101
|
|
103
102
|
offsets_hi = partitions_data
|
@@ -121,8 +120,7 @@ module Karafka
|
|
121
120
|
|
122
121
|
cgs[group_name] ||= {}
|
123
122
|
cgs[group_name][topic_name] = {
|
124
|
-
|
125
|
-
lag: lags.sum,
|
123
|
+
lag_hybrid: lags_hybrid.sum,
|
126
124
|
pace: offsets_hi.sum,
|
127
125
|
# Take max last stable offset duration without any change. This can
|
128
126
|
# indicate a hanging transaction, because the offset will not move forward
|
@@ -20,7 +20,7 @@ module Karafka
|
|
20
20
|
# Current schema version
|
21
21
|
# This can be used in the future for detecting incompatible changes and writing
|
22
22
|
# migrations
|
23
|
-
SCHEMA_VERSION = '1.
|
23
|
+
SCHEMA_VERSION = '1.3.1'
|
24
24
|
|
25
25
|
# @param schema_manager [Karafka::Web::Processing::Consumers::SchemaManager] schema
|
26
26
|
# manager that tracks the compatibility of schemas.
|
@@ -127,8 +127,7 @@ module Karafka
|
|
127
127
|
stats[:processes] = 0
|
128
128
|
stats[:rss] = 0
|
129
129
|
stats[:listeners] = { active: 0, standby: 0 }
|
130
|
-
stats[:
|
131
|
-
stats[:lag_stored] = 0
|
130
|
+
stats[:lag_hybrid] = 0
|
132
131
|
stats[:bytes_received] = 0
|
133
132
|
stats[:bytes_sent] = 0
|
134
133
|
utilization = 0
|
@@ -140,12 +139,13 @@ module Karafka
|
|
140
139
|
report_stats = report[:stats]
|
141
140
|
report_process = report[:process]
|
142
141
|
|
143
|
-
|
144
|
-
lags_stored = []
|
142
|
+
lags_hybrid = []
|
145
143
|
|
146
144
|
iterate_partitions(report) do |partition_stats|
|
147
|
-
|
148
|
-
|
145
|
+
lag_stored = partition_stats[:lag_stored]
|
146
|
+
lag = partition_stats[:lag]
|
147
|
+
|
148
|
+
lags_hybrid << (lag_stored.negative? ? lag : lag_stored)
|
149
149
|
end
|
150
150
|
|
151
151
|
stats[:busy] += report_stats[:busy]
|
@@ -157,8 +157,7 @@ module Karafka
|
|
157
157
|
stats[:listeners][:standby] += report_process[:listeners][:standby]
|
158
158
|
stats[:processes] += 1
|
159
159
|
stats[:rss] += report_process[:memory_usage]
|
160
|
-
stats[:
|
161
|
-
stats[:lag_stored] += lags_stored.compact.reject(&:negative?).sum
|
160
|
+
stats[:lag_hybrid] += lags_hybrid.compact.reject(&:negative?).sum
|
162
161
|
utilization += report_stats[:utilization]
|
163
162
|
end
|
164
163
|
|
@@ -21,8 +21,7 @@ module Karafka
|
|
21
21
|
required(:processes) { |val| val.is_a?(Integer) && val >= 0 }
|
22
22
|
required(:rss) { |val| val.is_a?(Numeric) && val >= 0 }
|
23
23
|
required(:utilization) { |val| val.is_a?(Numeric) && val >= 0 }
|
24
|
-
required(:
|
25
|
-
required(:lag) { |val| val.is_a?(Integer) }
|
24
|
+
required(:lag_hybrid) { |val| val.is_a?(Integer) }
|
26
25
|
|
27
26
|
nested(:listeners) do
|
28
27
|
required(:active) { |val| val.is_a?(Integer) && val >= 0 }
|
@@ -9,8 +9,7 @@ module Karafka
|
|
9
9
|
class TopicStats < Web::Contracts::Base
|
10
10
|
configure
|
11
11
|
|
12
|
-
required(:
|
13
|
-
required(:lag) { |val| val.is_a?(Integer) }
|
12
|
+
required(:lag_hybrid) { |val| val.is_a?(Integer) }
|
14
13
|
required(:pace) { |val| val.is_a?(Integer) }
|
15
14
|
required(:ls_offset_fd) { |val| val.is_a?(Integer) && val >= 0 }
|
16
15
|
end
|
@@ -16,17 +16,17 @@ module Karafka
|
|
16
16
|
|
17
17
|
# @return [String] JSON with lags of each of the topics + total lag of all the topics
|
18
18
|
# from all the consumer groups.
|
19
|
-
def
|
19
|
+
def lags_hybrid
|
20
20
|
total = Hash.new { |h, v| h[v] = 0 }
|
21
21
|
|
22
22
|
@data.to_h.each_value do |metrics|
|
23
23
|
metrics.each do |metric|
|
24
24
|
time = metric.first
|
25
|
-
|
25
|
+
lag_hybrid = metric.last[:lag_hybrid]
|
26
26
|
|
27
|
-
if
|
27
|
+
if lag_hybrid
|
28
28
|
total[time] ||= 0
|
29
|
-
total[time] +=
|
29
|
+
total[time] += lag_hybrid
|
30
30
|
else
|
31
31
|
next if total.key?(time)
|
32
32
|
|
@@ -37,7 +37,7 @@ module Karafka
|
|
37
37
|
|
38
38
|
# Extract the lag stored only from all the data
|
39
39
|
per_topic = @data.to_h.map do |topic, metrics|
|
40
|
-
extracted = metrics.map { |metric| [metric.first, metric.last[:
|
40
|
+
extracted = metrics.map { |metric| [metric.first, metric.last[:lag_hybrid]] }
|
41
41
|
|
42
42
|
[topic, extracted]
|
43
43
|
end.to_h
|
@@ -6,6 +6,28 @@ module Karafka
|
|
6
6
|
module Models
|
7
7
|
# Single topic partition data representation model
|
8
8
|
class Partition < Lib::HashProxy
|
9
|
+
# @param args [Object] anything hash proxy accepts
|
10
|
+
def initialize(*args)
|
11
|
+
super
|
12
|
+
|
13
|
+
# We initialize those here because we want to have them stored in the internal has
|
14
|
+
# for sorting
|
15
|
+
lag_hybrid
|
16
|
+
lag_hybrid_d
|
17
|
+
end
|
18
|
+
|
19
|
+
# Because `lag_stored` is not available until first marking, we fallback to the lag
|
20
|
+
# value that may be behind but is always available until stored lag is available.
|
21
|
+
# @return [Integer] hybrid log value
|
22
|
+
def lag_hybrid
|
23
|
+
self[:lag_hybrid] ||= lag_stored.negative? ? lag : lag_stored
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Integer] hybrid log delta
|
27
|
+
def lag_hybrid_d
|
28
|
+
self[:lag_hybrid_d] ||= lag_stored.negative? ? lag_d : lag_stored_d
|
29
|
+
end
|
30
|
+
|
9
31
|
# @return [Symbol] one of three states in which LSO can be in the correlation to given
|
10
32
|
# partition in the context of a consumer group.
|
11
33
|
#
|
@@ -41,24 +41,13 @@ module Karafka
|
|
41
41
|
.then { |jobs| Jobs.new(jobs) }
|
42
42
|
end
|
43
43
|
|
44
|
-
# @return [Integer] collective
|
45
|
-
def
|
44
|
+
# @return [Integer] collective hybrid lag on this process
|
45
|
+
def lag_hybrid
|
46
46
|
consumer_groups
|
47
47
|
.flat_map(&:subscription_groups)
|
48
48
|
.flat_map(&:topics)
|
49
49
|
.flat_map(&:partitions)
|
50
|
-
.map(&:
|
51
|
-
.delete_if(&:negative?)
|
52
|
-
.sum
|
53
|
-
end
|
54
|
-
|
55
|
-
# @return [Integer] collective lag on this process
|
56
|
-
def lag
|
57
|
-
consumer_groups
|
58
|
-
.flat_map(&:subscription_groups)
|
59
|
-
.flat_map(&:topics)
|
60
|
-
.flat_map(&:partitions)
|
61
|
-
.map(&:lag)
|
50
|
+
.map(&:lag_hybrid)
|
62
51
|
.delete_if(&:negative?)
|
63
52
|
.sum
|
64
53
|
end
|
@@ -19,11 +19,11 @@ module Karafka
|
|
19
19
|
# Controller for displaying consumers states and details about them
|
20
20
|
class Consumers < Ui::Controllers::Base
|
21
21
|
self.sortable_attributes = %w[
|
22
|
+
id
|
22
23
|
name
|
23
24
|
started_at
|
24
|
-
|
25
|
-
|
26
|
-
lag_stored_d
|
25
|
+
lag_hybrid
|
26
|
+
lag_hybrid_d
|
27
27
|
committed_offset
|
28
28
|
stored_offset
|
29
29
|
fetch_state
|
@@ -93,7 +93,13 @@ module Karafka
|
|
93
93
|
|
94
94
|
# We want to have sorting but on a per subscription group basis and not to sort
|
95
95
|
# everything
|
96
|
-
@process.consumer_groups.each
|
96
|
+
@process.consumer_groups.each do |consumer_group|
|
97
|
+
# We need to initialize the whole structure so dynamic fields are also built into
|
98
|
+
# the underlying hashes for sorting
|
99
|
+
consumer_group.subscription_groups.flat_map(&:topics).flat_map(&:partitions)
|
100
|
+
|
101
|
+
refine(consumer_group)
|
102
|
+
end
|
97
103
|
|
98
104
|
render
|
99
105
|
end
|
@@ -20,8 +20,12 @@ module Karafka
|
|
20
20
|
class Health < Ui::Controllers::Base
|
21
21
|
self.sortable_attributes = %w[
|
22
22
|
id
|
23
|
+
lag
|
24
|
+
lag_d
|
23
25
|
lag_stored
|
24
26
|
lag_stored_d
|
27
|
+
lag_hybrid
|
28
|
+
lag_hybrid_d
|
25
29
|
committed_offset
|
26
30
|
committed_offset_fd
|
27
31
|
stored_offset
|
@@ -50,6 +54,14 @@ module Karafka
|
|
50
54
|
render
|
51
55
|
end
|
52
56
|
|
57
|
+
# Displays details about lags and their progression/statuses
|
58
|
+
def lags
|
59
|
+
# Same data as overview but presented differently
|
60
|
+
overview
|
61
|
+
|
62
|
+
render
|
63
|
+
end
|
64
|
+
|
53
65
|
# Displays details about offsets and their progression/statuses
|
54
66
|
def offsets
|
55
67
|
# Same data as overview but presented differently
|
@@ -19,9 +19,9 @@
|
|
19
19
|
</li>
|
20
20
|
<li class="col-sm">
|
21
21
|
<div class="count mb-1">
|
22
|
-
<%= number_with_delimiter @counters.
|
22
|
+
<%= number_with_delimiter @counters.lag_hybrid, ' ' %>
|
23
23
|
</div>
|
24
|
-
<div class="desc">
|
24
|
+
<div class="desc">Total lag</div>
|
25
25
|
</li>
|
26
26
|
<li class="col-sm">
|
27
27
|
<a href="<%= root_path('jobs/running') %>">
|
@@ -3,11 +3,11 @@
|
|
3
3
|
<%= partition.id %>
|
4
4
|
</td>
|
5
5
|
<td>
|
6
|
-
<%== lag_with_label partition.
|
6
|
+
<%== lag_with_label partition.lag_hybrid %>
|
7
7
|
</td>
|
8
8
|
<td>
|
9
|
-
<span class="badge <%= lag_trend_bg(partition.
|
10
|
-
<%= partition.
|
9
|
+
<span class="badge <%= lag_trend_bg(partition.lag_hybrid_d) %>">
|
10
|
+
<%= partition.lag_hybrid_d %>
|
11
11
|
</span>
|
12
12
|
</td>
|
13
13
|
<td>
|
@@ -104,8 +104,8 @@
|
|
104
104
|
<tr class="align-middle">
|
105
105
|
</tr>
|
106
106
|
<th><%== sort_link('Partition', :id) %></th>
|
107
|
-
<th><%== sort_link(:
|
108
|
-
<th><%== sort_link('Lag
|
107
|
+
<th><%== sort_link('Lag', :lag_hybrid) %></th>
|
108
|
+
<th><%== sort_link('Lag trend', :lag_hybrid_d) %></th>
|
109
109
|
<th><%== sort_link(:committed_offset) %></th>
|
110
110
|
<th><%== sort_link(:stored_offset) %></th>
|
111
111
|
<th><%== sort_link(:fetch_state) %></th>
|
@@ -17,7 +17,7 @@
|
|
17
17
|
<th class="col-sm-1">Memory</th>
|
18
18
|
<th class="col-sm-1">Performance</th>
|
19
19
|
<th class="col-sm-1">Load</th>
|
20
|
-
<th class="col-sm-1"><%== sort_link(:
|
20
|
+
<th class="col-sm-1"><%== sort_link('Lag', :lag_hybrid) %></th>
|
21
21
|
</tr>
|
22
22
|
</thead>
|
23
23
|
<tbody>
|
@@ -13,7 +13,7 @@
|
|
13
13
|
<ul class="nav nav-tabs" id="graphs1" role="tablist">
|
14
14
|
<%== partial 'shared/tab_nav', locals: { title: 'Messages', id: 'messages', active: true } %>
|
15
15
|
<%== partial 'shared/tab_nav', locals: { title: 'Batches', id: 'batches' } %>
|
16
|
-
<%== partial 'shared/tab_nav', locals: { title: '
|
16
|
+
<%== partial 'shared/tab_nav', locals: { title: 'Topics lags', id: 'topics-lags' } %>
|
17
17
|
<%== partial 'shared/tab_nav', locals: { title: 'Topics pace', id: 'topics-pace' } %>
|
18
18
|
<%== partial 'shared/tab_nav', locals: { title: 'Max LSO time', id: 'max-lso-time' } %>
|
19
19
|
</ul>
|
@@ -29,8 +29,8 @@
|
|
29
29
|
<%== partial 'shared/chart', locals: { data: data, id: 'batches' } %>
|
30
30
|
</div>
|
31
31
|
|
32
|
-
<div class="tab-pane" id="lags
|
33
|
-
<%== partial 'shared/chart', locals: { data: @topics_charts.
|
32
|
+
<div class="tab-pane" id="topics-lags" role="tabpanel">
|
33
|
+
<%== partial 'shared/chart', 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">
|
@@ -4,6 +4,14 @@
|
|
4
4
|
</a>
|
5
5
|
</li>
|
6
6
|
|
7
|
+
<% if current_path.include?('/lags') %>
|
8
|
+
<li class="breadcrumb-item">
|
9
|
+
<a href="<%= root_path('health', 'lags') %>">
|
10
|
+
Lags
|
11
|
+
</a>
|
12
|
+
</li>
|
13
|
+
<% end %>
|
14
|
+
|
7
15
|
<% if current_path.include?('/overview') %>
|
8
16
|
<li class="breadcrumb-item">
|
9
17
|
<a href="<%= root_path('health', 'overview') %>">
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div class="row mb-4">
|
2
|
+
<div class="col-sm-8">
|
3
|
+
<h4 class="mb-4"><%= cg_name %></h4>
|
4
|
+
</div>
|
5
|
+
|
6
|
+
<div class="col-sm-4">
|
7
|
+
<span class="float-end">
|
8
|
+
Last rebalance:
|
9
|
+
<span class="badge bg-secondary">
|
10
|
+
<%== relative_time(details[:rebalanced_at]) %>
|
11
|
+
</span>
|
12
|
+
</span>
|
13
|
+
</div>
|
14
|
+
</div>
|
@@ -3,15 +3,7 @@
|
|
3
3
|
<%= partition_id %>
|
4
4
|
</td>
|
5
5
|
<td>
|
6
|
-
<%== lag_with_label details.
|
7
|
-
</td>
|
8
|
-
<td>
|
9
|
-
<span class="badge <%= lag_trend_bg(details.lag_stored_d) %>">
|
10
|
-
<%= details.lag_stored_d %>
|
11
|
-
</span>
|
12
|
-
</td>
|
13
|
-
<td>
|
14
|
-
<%== offset_with_label topic_name, partition_id, details.committed_offset %>
|
6
|
+
<%== lag_with_label details.lag_hybrid %>
|
15
7
|
</td>
|
16
8
|
<td>
|
17
9
|
<%== offset_with_label topic_name, partition_id, details.stored_offset %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<tr class="align-middle <%= lso_risk_state_bg(details) %> status-row-<%= details.process.status %>">
|
2
|
+
<td>
|
3
|
+
<%= partition_id %>
|
4
|
+
</td>
|
5
|
+
<td>
|
6
|
+
<%== lag_with_label details.lag %>
|
7
|
+
</td>
|
8
|
+
<td>
|
9
|
+
<span class="badge <%= lag_trend_bg(details.lag_d) %>">
|
10
|
+
<%= details.lag_d %>
|
11
|
+
</span>
|
12
|
+
</td>
|
13
|
+
<td>
|
14
|
+
<%== lag_with_label details.lag_stored %>
|
15
|
+
</td>
|
16
|
+
<td>
|
17
|
+
<span class="badge <%= lag_trend_bg(details.lag_stored_d) %>">
|
18
|
+
<%= details.lag_stored_d %>
|
19
|
+
</span>
|
20
|
+
</td>
|
21
|
+
<td>
|
22
|
+
<%== poll_state_with_change_time_label(details.poll_state, details.poll_state_ch) %>
|
23
|
+
</td>
|
24
|
+
</tr>
|
@@ -12,6 +12,15 @@
|
|
12
12
|
</a>
|
13
13
|
</li>
|
14
14
|
|
15
|
+
<li class="nav-item">
|
16
|
+
<a
|
17
|
+
class="nav-link <%= nav_class(include: 'lags') %>"
|
18
|
+
href="<%= root_path('health', 'lags') %>"
|
19
|
+
>
|
20
|
+
Lags
|
21
|
+
</a>
|
22
|
+
</li>
|
23
|
+
|
15
24
|
<li class="nav-item">
|
16
25
|
<a
|
17
26
|
class="nav-link <%= nav_class(include: 'offsets') %>"
|
@@ -6,23 +6,9 @@
|
|
6
6
|
<%== partial 'health/tabs' %>
|
7
7
|
<% end %>
|
8
8
|
|
9
|
-
|
10
9
|
<% @stats.each_with_index do |(cg_name, details), index| %>
|
11
10
|
<div class="container mb-5">
|
12
|
-
|
13
|
-
<div class="col-sm-8">
|
14
|
-
<h4 class="mb-4"><%= cg_name %></h4>
|
15
|
-
</div>
|
16
|
-
|
17
|
-
<div class="col-sm-4">
|
18
|
-
<span class="float-end">
|
19
|
-
Last rebalance:
|
20
|
-
<span class="badge bg-secondary">
|
21
|
-
<%== relative_time(details[:rebalanced_at]) %>
|
22
|
-
</span>
|
23
|
-
</span>
|
24
|
-
</div>
|
25
|
-
</div>
|
11
|
+
<%== partial 'health/consumer_group_header', locals: { cg_name: cg_name, details: details } %>
|
26
12
|
|
27
13
|
<div class="row mb-3">
|
28
14
|
<div class="col-sm-12">
|
@@ -0,0 +1,52 @@
|
|
1
|
+
<%== view_title('Consumers groups lags details') %>
|
2
|
+
|
3
|
+
<% if @stats.empty? %>
|
4
|
+
<%== partial 'health/no_data' %>
|
5
|
+
<% else %>
|
6
|
+
<%== partial 'health/tabs' %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% @stats.each_with_index do |(cg_name, details), index| %>
|
10
|
+
<div class="container mb-5">
|
11
|
+
<%== partial 'health/consumer_group_header', locals: { cg_name: cg_name, details: details } %>
|
12
|
+
|
13
|
+
<div class="row mb-3">
|
14
|
+
<div class="col-sm-12">
|
15
|
+
<% topics = details[:topics] %>
|
16
|
+
<% topics.each_with_index do |(topic_name, partitions), index| %>
|
17
|
+
<table class="processes bg-white table table-hover table-bordered table-striped align-middle <%= (index+1 < topics.size) ? 'mb-5' : 'mb-3' %>">
|
18
|
+
<thead>
|
19
|
+
<tr class="align-middle">
|
20
|
+
<th colspan="12">
|
21
|
+
<h5 class="mb-0"><%= topic_name %></h4>
|
22
|
+
</th>
|
23
|
+
</tr>
|
24
|
+
<tr class="align-middle">
|
25
|
+
<th><%== sort_link('Partition', :id) %></th>
|
26
|
+
<th><%== sort_link('Lag', :lag) %></th>
|
27
|
+
<th><%== sort_link('Lag trend', :lag_d) %></th>
|
28
|
+
<th><%== sort_link('Lag stored', :lag_stored) %></th>
|
29
|
+
<th><%== sort_link('Lag stored trend', :lag_stored_d) %></th>
|
30
|
+
<th><%== sort_link(:poll_state) %></th>
|
31
|
+
</tr>
|
32
|
+
</thead>
|
33
|
+
<tbody>
|
34
|
+
<% partitions.each do |partition_id, details| %>
|
35
|
+
<%==
|
36
|
+
partial(
|
37
|
+
'health/partition_lags',
|
38
|
+
locals: {
|
39
|
+
topic_name: topic_name,
|
40
|
+
partition_id: partition_id,
|
41
|
+
details: details
|
42
|
+
}
|
43
|
+
)
|
44
|
+
%>
|
45
|
+
<% end %>
|
46
|
+
</tbody>
|
47
|
+
</table>
|
48
|
+
<% end %>
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
<% end %>
|
@@ -8,20 +8,7 @@
|
|
8
8
|
|
9
9
|
<% @stats.each_with_index do |(cg_name, details), index| %>
|
10
10
|
<div class="container mb-5">
|
11
|
-
|
12
|
-
<div class="col-sm-8">
|
13
|
-
<h4 class="mb-4"><%= cg_name %></h4>
|
14
|
-
</div>
|
15
|
-
|
16
|
-
<div class="col-sm-4">
|
17
|
-
<span class="float-end">
|
18
|
-
Last rebalance:
|
19
|
-
<span class="badge bg-secondary">
|
20
|
-
<%== relative_time(details[:rebalanced_at]) %>
|
21
|
-
</span>
|
22
|
-
</span>
|
23
|
-
</div>
|
24
|
-
</div>
|
11
|
+
<%== partial 'health/consumer_group_header', locals: { cg_name: cg_name, details: details } %>
|
25
12
|
|
26
13
|
<div class="row mb-3">
|
27
14
|
<div class="col-sm-12">
|
@@ -36,7 +23,7 @@
|
|
36
23
|
</tr>
|
37
24
|
<tr class="align-middle">
|
38
25
|
<th><%== sort_link('Partition', :id) %></th>
|
39
|
-
<th><%== sort_link(:
|
26
|
+
<th><%== sort_link('Lag', :lag_hybrid) %></th>
|
40
27
|
<th><%== sort_link(:committed_offset) %></th>
|
41
28
|
<th><%== sort_link('Committed offset change', :committed_offset_fd) %></th>
|
42
29
|
<th><%== sort_link(:stored_offset) %></th>
|
@@ -8,20 +8,7 @@
|
|
8
8
|
|
9
9
|
<% @stats.each_with_index do |(cg_name, details), index| %>
|
10
10
|
<div class="container mb-5">
|
11
|
-
|
12
|
-
<div class="col-sm-8">
|
13
|
-
<h4 class="mb-4"><%= cg_name %></h4>
|
14
|
-
</div>
|
15
|
-
|
16
|
-
<div class="col-sm-4">
|
17
|
-
<span class="float-end">
|
18
|
-
Last rebalance:
|
19
|
-
<span class="badge bg-secondary">
|
20
|
-
<%== relative_time(details[:rebalanced_at]) %>
|
21
|
-
</span>
|
22
|
-
</span>
|
23
|
-
</div>
|
24
|
-
</div>
|
11
|
+
<%== partial 'health/consumer_group_header', locals: { cg_name: cg_name, details: details } %>
|
25
12
|
|
26
13
|
<div class="row mb-3">
|
27
14
|
<div class="col-sm-12">
|
@@ -36,9 +23,7 @@
|
|
36
23
|
</tr>
|
37
24
|
<tr class="align-middle">
|
38
25
|
<th><%== sort_link('Partition', :id) %></th>
|
39
|
-
<th><%== sort_link(:
|
40
|
-
<th><%== sort_link('Lag stored trend', :lag_stored_d) %></th>
|
41
|
-
<th><%== sort_link(:committed_offset) %></th>
|
26
|
+
<th><%== sort_link('Lag', :lag_hybrid) %></th>
|
42
27
|
<th><%== sort_link(:stored_offset) %></th>
|
43
28
|
<th><%== sort_link(:fetch_state) %></th>
|
44
29
|
<th><%== sort_link(:poll_state) %></th>
|
@@ -19,9 +19,9 @@
|
|
19
19
|
</li>
|
20
20
|
<li class="col-sm">
|
21
21
|
<div class="count mb-1">
|
22
|
-
<%= number_with_delimiter @counters.
|
22
|
+
<%= number_with_delimiter @counters.lag_hybrid, ' ' %>
|
23
23
|
</div>
|
24
|
-
<div class="desc">
|
24
|
+
<div class="desc">Total lag</div>
|
25
25
|
</li>
|
26
26
|
<li class="col-sm">
|
27
27
|
<a href="<%= root_path('jobs/running') %>">
|
@@ -16,7 +16,7 @@
|
|
16
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"><%== sort_link(:
|
19
|
+
<th class="col-sm-1"><%== sort_link('Lag', :lag_hybrid) %></th>
|
20
20
|
</tr>
|
21
21
|
</thead>
|
22
22
|
<tbody>
|
@@ -23,7 +23,7 @@
|
|
23
23
|
<ul class="nav nav-tabs" id="graphs1" role="tablist">
|
24
24
|
<%== partial 'shared/tab_nav', locals: { title: 'Messages', id: 'messages', active: true } %>
|
25
25
|
<%== partial 'shared/tab_nav', locals: { title: 'Batches', id: 'batches' } %>
|
26
|
-
<%== partial 'shared/tab_nav', locals: { title: 'Lags
|
26
|
+
<%== partial 'shared/tab_nav', locals: { title: 'Topics Lags', id: 'topics-lags' } %>
|
27
27
|
<%== partial 'shared/tab_nav', locals: { title: 'Topics pace', id: 'topics-pace' } %>
|
28
28
|
<%== partial 'shared/tab_nav', locals: { title: 'Max LSO time', id: 'max-lso-time' } %>
|
29
29
|
</ul>
|
@@ -39,10 +39,10 @@
|
|
39
39
|
<%== partial 'shared/chart', locals: { data: data, id: 'batches' } %>
|
40
40
|
</div>
|
41
41
|
|
42
|
-
<div class="tab-pane" id="lags
|
42
|
+
<div class="tab-pane" id="topics-lags" role="tabpanel">
|
43
43
|
<%== partial 'dashboard/feature_pro' %>
|
44
44
|
<% data = { enqueued: set.call, busy: set.call }.to_json %>
|
45
|
-
<%== partial 'shared/chart', locals: { data: data, id: 'lags
|
45
|
+
<%== partial 'shared/chart', locals: { data: data, id: 'topics-lags', blurred: true } %>
|
46
46
|
</div>
|
47
47
|
|
48
48
|
<div class="tab-pane" id="topics-pace" role="tabpanel">
|
data/lib/karafka/web/version.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: karafka-web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maciej Mensfeld
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
AnG1dJU+yL2BK7vaVytLTstJME5mepSZ46qqIJXMuWob/YPDmVaBF39TDSG9e34s
|
36
36
|
msG3BiCqgOgHAnL23+CN3Rt8MsuRfEtoTKpJVcCfoEoNHOkc
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2024-01
|
38
|
+
date: 2024-02-01 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: erubi
|
@@ -205,6 +205,10 @@ files:
|
|
205
205
|
- lib/karafka/web/management/migrations/1700234522_remove_processing_from_consumers_state.rb
|
206
206
|
- lib/karafka/web/management/migrations/1704722380_split_listeners_into_active_and_paused_in_metrics.rb
|
207
207
|
- lib/karafka/web/management/migrations/1704722380_split_listeners_into_active_and_paused_in_states.rb
|
208
|
+
- lib/karafka/web/management/migrations/1706607960_introduce_lag_total_in_metrics.rb
|
209
|
+
- lib/karafka/web/management/migrations/1706607960_introduce_lag_total_in_states.rb
|
210
|
+
- lib/karafka/web/management/migrations/1706611396_rename_lag_total_to_lag_hybrid_in_metrics.rb
|
211
|
+
- lib/karafka/web/management/migrations/1706611396_rename_lag_total_to_lag_hybrid_in_states.rb
|
208
212
|
- lib/karafka/web/management/migrator.rb
|
209
213
|
- lib/karafka/web/processing/consumer.rb
|
210
214
|
- lib/karafka/web/processing/consumers/aggregators/base.rb
|
@@ -369,12 +373,15 @@ files:
|
|
369
373
|
- lib/karafka/web/ui/pro/views/explorer/topic/_empty.erb
|
370
374
|
- lib/karafka/web/ui/pro/views/explorer/topic/_limited.erb
|
371
375
|
- lib/karafka/web/ui/pro/views/health/_breadcrumbs.erb
|
376
|
+
- lib/karafka/web/ui/pro/views/health/_consumer_group_header.erb
|
372
377
|
- lib/karafka/web/ui/pro/views/health/_no_data.erb
|
373
378
|
- lib/karafka/web/ui/pro/views/health/_partition.erb
|
379
|
+
- lib/karafka/web/ui/pro/views/health/_partition_lags.erb
|
374
380
|
- lib/karafka/web/ui/pro/views/health/_partition_offset.erb
|
375
381
|
- lib/karafka/web/ui/pro/views/health/_partition_times.erb
|
376
382
|
- lib/karafka/web/ui/pro/views/health/_tabs.erb
|
377
383
|
- lib/karafka/web/ui/pro/views/health/changes.erb
|
384
|
+
- lib/karafka/web/ui/pro/views/health/lags.erb
|
378
385
|
- lib/karafka/web/ui/pro/views/health/offsets.erb
|
379
386
|
- lib/karafka/web/ui/pro/views/health/overview.erb
|
380
387
|
- lib/karafka/web/ui/pro/views/jobs/_job.erb
|
metadata.gz.sig
CHANGED
Binary file
|