karafka-web 0.1.3 → 0.2.0

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +9 -0
  4. data/Gemfile +1 -0
  5. data/Gemfile.lock +23 -11
  6. data/karafka-web.gemspec +2 -2
  7. data/lib/karafka/web/config.rb +5 -0
  8. data/lib/karafka/web/installer.rb +1 -2
  9. data/lib/karafka/web/processing/consumer.rb +2 -1
  10. data/lib/karafka/web/tracking/consumers/contracts/job.rb +1 -0
  11. data/lib/karafka/web/tracking/consumers/contracts/report.rb +1 -0
  12. data/lib/karafka/web/tracking/consumers/listeners/errors.rb +1 -1
  13. data/lib/karafka/web/tracking/consumers/listeners/processing.rb +2 -1
  14. data/lib/karafka/web/tracking/consumers/sampler.rb +9 -3
  15. data/lib/karafka/web/tracking/reporter.rb +2 -1
  16. data/lib/karafka/web/ui/app.rb +5 -0
  17. data/lib/karafka/web/ui/controllers/status.rb +23 -0
  18. data/lib/karafka/web/ui/models/process.rb +7 -0
  19. data/lib/karafka/web/ui/models/status.rb +169 -0
  20. data/lib/karafka/web/ui/pro/app.rb +5 -0
  21. data/lib/karafka/web/ui/pro/controllers/status.rb +26 -0
  22. data/lib/karafka/web/ui/pro/views/consumers/_consumer.erb +15 -7
  23. data/lib/karafka/web/ui/pro/views/consumers/consumer/_job.erb +4 -0
  24. data/lib/karafka/web/ui/pro/views/consumers/consumer/_metrics.erb +10 -0
  25. data/lib/karafka/web/ui/pro/views/jobs/_job.erb +4 -0
  26. data/lib/karafka/web/ui/pro/views/shared/_navigation.erb +5 -0
  27. data/lib/karafka/web/ui/views/consumers/_consumer.erb +15 -7
  28. data/lib/karafka/web/ui/views/jobs/_job.erb +4 -0
  29. data/lib/karafka/web/ui/views/shared/_navigation.erb +5 -0
  30. data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +2 -0
  31. data/lib/karafka/web/ui/views/status/_breadcrumbs.erb +5 -0
  32. data/lib/karafka/web/ui/views/status/_failure.erb +14 -0
  33. data/lib/karafka/web/ui/views/status/_halted.erb +11 -0
  34. data/lib/karafka/web/ui/views/status/_success.erb +11 -0
  35. data/lib/karafka/web/ui/views/status/failures/_connection.erb +7 -0
  36. data/lib/karafka/web/ui/views/status/failures/_initial_state.erb +20 -0
  37. data/lib/karafka/web/ui/views/status/failures/_live_reporting.erb +7 -0
  38. data/lib/karafka/web/ui/views/status/failures/_partitions.erb +19 -0
  39. data/lib/karafka/web/ui/views/status/failures/_state_calculation.erb +8 -0
  40. data/lib/karafka/web/ui/views/status/failures/_topics.erb +20 -0
  41. data/lib/karafka/web/ui/views/status/show.erb +94 -0
  42. data/lib/karafka/web/version.rb +1 -1
  43. data.tar.gz.sig +0 -0
  44. metadata +20 -6
  45. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a70fc5cb35d0e6e60a348e3efe91113b54d0c62310b7c3af4e7584aa70cfb70
4
- data.tar.gz: 43a96b7e7a4622721dbc6ba144852335aecbfe907049bc47ab563ea07f40eb54
3
+ metadata.gz: eb17bd9d46e6fa0d0125bc665bff74a9d4277be394f1bf29223b6d49ef09e054
4
+ data.tar.gz: 2f1da7d4fa79116a67ae3300863b56c3ac2215d80dccba89520e33e78c3b1a84
5
5
  SHA512:
6
- metadata.gz: db0b153569ca93f1164a851216e0f224acc56e6a7533a35a86a44f6f2f8bffc1630e5ccf7c2e53a14455206401c45b59b1728eb266c59360be8f952794d3011b
7
- data.tar.gz: 794c77edb27f7f9a397c3de891b146f9020653b84bad46e1f1b537a1d547ffc793211e7bd5ffb0f426c0b8fa9b6359230bb3fe3ee8fa5ec668cb0e1d39782d5a
6
+ metadata.gz: cc9f331aa0b9276c1b3c2d6d4f400b9d8600da174123d472b1699554e0cd95de14ff60b7c4effbb0c4f86a423f24ff27f5facc282ff8215863c146a4b1c0bb41
7
+ data.tar.gz: 1f638b2ca877b1b34612654a19f0fb8d04ab88e5dc6b560a7090e74a6d1202da0257d4f941f8f182b6b874d8a099db30772a1ab9517b32ebae76161d9314797a
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Karafka Web changelog
2
2
 
3
+ ## 0.2.0 (2023-02-24)
4
+ - **[Feature]** Introduce ability to tag `Karafka::Process` to display process-centric tags in the Web UI.
5
+ - **[Feature]** Introduce ability to tag consumer instances to display consumption-centric tags in the Web UI.
6
+ - **[Feature]** Introduce a /status page that can validate the setup and tell what is missing (#1318)
7
+ - [Improvement] Allow for disabling the consumer subscription from Web for multi-tenant Web UI usage (#1331)
8
+ - [Improvement] Make sure that states and reports are always dispatched to the partition `0`. This should prevent UI from not fully working when someone accidentally creates more partitions than expected.
9
+ - [Fix] Fix a bug where bootstrapping would create two initial states.
10
+ - [Fix] Fix a case, where errors listener would try to force encoding on a frozen error message.
11
+
3
12
  ## 0.1.3 (2023-02-14)
4
13
  - Skip topics creation if web topics already exist (do not raise error)
5
14
  - Support ability to provide replication factor in the install command
data/Gemfile CHANGED
@@ -8,6 +8,7 @@ gemspec
8
8
 
9
9
  group :test do
10
10
  gem 'byebug'
11
+ gem 'factory_bot'
11
12
  gem 'rspec'
12
13
  gem 'simplecov'
13
14
  end
data/Gemfile.lock CHANGED
@@ -1,41 +1,51 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- karafka-web (0.1.3)
4
+ karafka-web (0.2.0)
5
5
  erubi (~> 1.4)
6
- karafka (>= 2.0.29, < 3.0.0)
7
- karafka-core (>= 2.0.10, < 3.0.0)
6
+ karafka (>= 2.0.33, < 3.0.0)
7
+ karafka-core (>= 2.0.12, < 3.0.0)
8
8
  roda (~> 3.63)
9
9
  tilt (~> 2.0)
10
10
 
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
+ activesupport (7.0.4.2)
15
+ concurrent-ruby (~> 1.0, >= 1.0.2)
16
+ i18n (>= 1.6, < 2)
17
+ minitest (>= 5.1)
18
+ tzinfo (~> 2.0)
14
19
  byebug (11.1.3)
15
20
  concurrent-ruby (1.2.0)
16
21
  diff-lcs (1.5.0)
17
22
  docile (1.4.0)
18
23
  erubi (1.12.0)
24
+ factory_bot (6.2.1)
25
+ activesupport (>= 5.0.0)
19
26
  ffi (1.15.5)
20
- karafka (2.0.30)
21
- karafka-core (>= 2.0.9, < 3.0.0)
27
+ i18n (1.12.0)
28
+ concurrent-ruby (~> 1.0)
29
+ karafka (2.0.33)
30
+ karafka-core (>= 2.0.12, < 3.0.0)
22
31
  thor (>= 0.20)
23
32
  waterdrop (>= 2.4.10, < 3.0.0)
24
33
  zeitwerk (~> 2.3)
25
- karafka-core (2.0.10)
34
+ karafka-core (2.0.12)
26
35
  concurrent-ruby (>= 1.1)
27
- karafka-rdkafka (>= 0.12)
28
- karafka-rdkafka (0.12.0)
36
+ karafka-rdkafka (>= 0.12.1)
37
+ karafka-rdkafka (0.12.1)
29
38
  ffi (~> 1.15)
30
39
  mini_portile2 (~> 2.6)
31
40
  rake (> 12)
32
41
  mini_portile2 (2.8.1)
42
+ minitest (5.17.0)
33
43
  rack (3.0.4.1)
34
44
  rackup (0.2.3)
35
45
  rack (>= 3.0.0.beta1)
36
46
  webrick
37
47
  rake (13.0.6)
38
- roda (3.64.0)
48
+ roda (3.65.0)
39
49
  rack
40
50
  rspec (3.12.0)
41
51
  rspec-core (~> 3.12.0)
@@ -57,7 +67,9 @@ GEM
57
67
  simplecov-html (0.12.3)
58
68
  simplecov_json_formatter (0.1.4)
59
69
  thor (1.2.1)
60
- tilt (2.0.11)
70
+ tilt (2.1.0)
71
+ tzinfo (2.0.6)
72
+ concurrent-ruby (~> 1.0)
61
73
  waterdrop (2.4.10)
62
74
  karafka-core (>= 2.0.9, < 3.0.0)
63
75
  zeitwerk (~> 2.3)
@@ -65,11 +77,11 @@ GEM
65
77
  zeitwerk (2.6.7)
66
78
 
67
79
  PLATFORMS
68
- arm64-darwin-21
69
80
  x86_64-linux
70
81
 
71
82
  DEPENDENCIES
72
83
  byebug
84
+ factory_bot
73
85
  karafka-web!
74
86
  rackup (~> 0.2)
75
87
  rspec
data/karafka-web.gemspec CHANGED
@@ -17,8 +17,8 @@ Gem::Specification.new do |spec|
17
17
  spec.licenses = %w[LGPL-3.0 Commercial]
18
18
 
19
19
  spec.add_dependency 'erubi', '~> 1.4'
20
- spec.add_dependency 'karafka', '>= 2.0.29', '< 3.0.0'
21
- spec.add_dependency 'karafka-core', '>= 2.0.10', '< 3.0.0'
20
+ spec.add_dependency 'karafka', '>= 2.0.33', '< 3.0.0'
21
+ spec.add_dependency 'karafka-core', '>= 2.0.12', '< 3.0.0'
22
22
  spec.add_dependency 'roda', '~> 3.63'
23
23
  spec.add_dependency 'tilt', '~> 2.0'
24
24
 
@@ -56,6 +56,11 @@ module Karafka
56
56
 
57
57
  # States processing related settings
58
58
  setting :processing do
59
+ # Should we actively process reports
60
+ # This can be disabled in case of using a multi-tenant approach where only one of the
61
+ # apps should materialize the state
62
+ setting :active, default: true
63
+
59
64
  # What should be the consumer group name for web consumer
60
65
  setting :consumer_group, default: 'karafka_web'
61
66
 
@@ -45,6 +45,7 @@ module Karafka
45
45
  consumer_group ::Karafka::Web.config.processing.consumer_group do
46
46
  # Topic we listen on to materialize the states
47
47
  topic ::Karafka::Web.config.topics.consumers.reports do
48
+ active ::Karafka::Web.config.processing.active
48
49
  # Since we materialize state in intervals, we can poll for half of this time without
49
50
  # impacting the reporting responsiveness
50
51
  max_wait_time ::Karafka::Web.config.processing.interval / 2
@@ -128,8 +129,6 @@ module Karafka
128
129
  replication_factor
129
130
  )
130
131
  end
131
-
132
- bootstrap_state!
133
132
  end
134
133
 
135
134
  # Creates the initial state record with all values being empty
@@ -57,7 +57,8 @@ module Karafka
57
57
  topic: Karafka::Web.config.topics.consumers.states,
58
58
  payload: @consumers_aggregator.to_json,
59
59
  # This will ensure that the consumer states are compacted
60
- key: Karafka::Web.config.topics.consumers.states
60
+ key: Karafka::Web.config.topics.consumers.states,
61
+ partition: 0
61
62
  )
62
63
  end
63
64
  end
@@ -18,6 +18,7 @@ module Karafka
18
18
  required(:last_offset) { |val| val.is_a?(Integer) && val >= 0 }
19
19
  required(:comitted_offset) { |val| val.is_a?(Integer) }
20
20
  required(:type) { |val| %w[consume revoked shutdown].include?(val) }
21
+ required(:tags) { |val| val.is_a?(Karafka::Core::Taggable::Tags) }
21
22
  end
22
23
  end
23
24
  end
@@ -27,6 +27,7 @@ module Karafka
27
27
  required(:status) { |val| ::Karafka::Status::STATES.key?(val.to_sym) }
28
28
  required(:listeners) { |val| val.is_a?(Integer) && val >= 0 }
29
29
  required(:concurrency) { |val| val.is_a?(Integer) && val.positive? }
30
+ required(:tags) { |val| val.is_a?(Karafka::Core::Taggable::Tags) }
30
31
 
31
32
  required(:cpu_usage) do |val|
32
33
  val.is_a?(Array) &&
@@ -74,7 +74,7 @@ module Karafka
74
74
  # @param error [StandardError] error that occurred
75
75
  # @return [Array<String, String, String>] array with error name, message and backtrace
76
76
  def extract_error_info(error)
77
- error_message = error.message.to_s
77
+ error_message = error.message.to_s.dup
78
78
  error_message.force_encoding('utf-8')
79
79
  error_message.scrub!
80
80
 
@@ -146,7 +146,8 @@ module Karafka
146
146
  comitted_offset: consumer.coordinator.seek_offset - 1,
147
147
  consumer: consumer.class.to_s,
148
148
  consumer_group: consumer.topic.consumer_group.id,
149
- type: type
149
+ type: type,
150
+ tags: consumer.tags
150
151
  }
151
152
  end
152
153
  end
@@ -11,13 +11,18 @@ module Karafka
11
11
 
12
12
  attr_reader :counters, :consumer_groups, :errors, :times, :pauses, :jobs
13
13
 
14
+ # Current schema version
15
+ # This can be used in the future for detecting incompatible changes and writing
16
+ # migrations
17
+ SCHEMA_VERSION = '1.0.1'
18
+
14
19
  # 60 seconds window for time tracked window-based metrics
15
20
  TIMES_TTL = 60
16
21
 
17
22
  # Times ttl in ms
18
23
  TIMES_TTL_MS = TIMES_TTL * 1_000
19
24
 
20
- private_constant :TIMES_TTL, :TIMES_TTL_MS
25
+ private_constant :TIMES_TTL, :TIMES_TTL_MS, :SCHEMA_VERSION
21
26
 
22
27
  def initialize
23
28
  @counters = {
@@ -47,7 +52,7 @@ module Karafka
47
52
  # @return [Hash] report hash with all the details about consumer operations
48
53
  def to_report
49
54
  {
50
- schema_version: '1.0.0',
55
+ schema_version: SCHEMA_VERSION,
51
56
  type: 'consumer',
52
57
  dispatched_at: float_now,
53
58
 
@@ -61,7 +66,8 @@ module Karafka
61
66
  memory_total_usage: memory_total_usage,
62
67
  memory_size: memory_size,
63
68
  cpu_count: cpu_count,
64
- cpu_usage: cpu_usage
69
+ cpu_usage: cpu_usage,
70
+ tags: Karafka::Process.tags
65
71
  },
66
72
 
67
73
  versions: {
@@ -49,7 +49,8 @@ module Karafka
49
49
  {
50
50
  topic: ::Karafka::Web.config.topics.consumers.reports,
51
51
  payload: consumer_report.to_json,
52
- key: consumer_report[:process][:name]
52
+ key: consumer_report[:process][:name],
53
+ partition: 0
53
54
  }
54
55
  ]
55
56
 
@@ -71,6 +71,11 @@ module Karafka
71
71
  render_response controller.index
72
72
  end
73
73
  end
74
+
75
+ r.get 'status' do
76
+ controller = Controllers::Status.new(params)
77
+ render_response controller.show
78
+ end
74
79
  end
75
80
  end
76
81
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Web
5
+ module Ui
6
+ module Controllers
7
+ # View that helps understand the status of the Web UI
8
+ # Many people reported problems understanding the requirements or misconfigured things.
9
+ # While all of the things are documented, people are lazy. Hence we provide a status
10
+ # page where we check that everything is as expected and if not, we can provide some
11
+ # helpful instructions on how to fix the issues.
12
+ class Status < Base
13
+ # Displays the Web UI setup status
14
+ def show
15
+ @status = Models::Status.new
16
+
17
+ respond
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -40,6 +40,13 @@ module Karafka
40
40
  .sort_by(&:started_at)
41
41
  end
42
42
 
43
+ # @return [Array<String>] tags of this consuming process
44
+ # @note We use direct reference here and a fallback for users that come from the versions
45
+ # that did not report tags
46
+ def tags
47
+ @hash[:process][:tags] || []
48
+ end
49
+
43
50
  # @return [Integer] collective lag on this process
44
51
  def lag_stored
45
52
  consumer_groups
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Web
5
+ module Ui
6
+ module Models
7
+ # Model that represents the general status of the Web UI.
8
+ # We use this data to display a status page that helps with debugging on what is missing
9
+ # in the overall setup of the Web UI.
10
+ #
11
+ # People have various problems like too many partitions, not created topics, etc. and this
12
+ # data and view aims to help them with understanding the current status of the setup
13
+ class Status
14
+ # Status of a single step of setup
15
+ Step = Struct.new(:status, :details) do
16
+ # @return [Boolean] is the given step successfully configured and working
17
+ def success?
18
+ status == :success
19
+ end
20
+
21
+ # @return [String] stringified status
22
+ def to_s
23
+ status.to_s
24
+ end
25
+ end
26
+
27
+ # Initializes the status object and tries to connect to Kafka
28
+ def initialize
29
+ connect
30
+ end
31
+
32
+ # @return [Status::Step] were we able to connect to Kafka or not
33
+ def connection
34
+ Step.new(
35
+ @connected ? :success : :failure,
36
+ nil
37
+ )
38
+ end
39
+
40
+ # @return [Status::Step] do all the needed topics exist
41
+ def topics
42
+ if connection.success?
43
+ details = topics_details
44
+ status = details.all? { |_, detail| detail[:present] } ? :success : :failure
45
+ else
46
+ status = :halted
47
+ details = {}
48
+ end
49
+
50
+ Step.new(
51
+ status,
52
+ details
53
+ )
54
+ end
55
+
56
+ # @return [Status::Step] do we have all topics with expected number of partitions
57
+ def partitions
58
+ if topics.success?
59
+ status = :success
60
+ status = :failure if topics_details[topics_consumers_states][:partitions] != 1
61
+ status = :failure if topics_details[topics_consumers_reports][:partitions] != 1
62
+ details = topics_details
63
+ else
64
+ status = :halted
65
+ details = {}
66
+ end
67
+
68
+ Step.new(
69
+ status,
70
+ details
71
+ )
72
+ end
73
+
74
+ # @return [Status::Step] Is the initial state present in the setup or not
75
+ def initial_state
76
+ if partitions.success?
77
+ @current_state ||= Models::State.current
78
+ status = @current_state ? :success : :failure
79
+ else
80
+ status = :halted
81
+ end
82
+
83
+ Step.new(
84
+ status,
85
+ nil
86
+ )
87
+ end
88
+
89
+ # @return [Status::Step] Is there at least one active karafka server reporting to the
90
+ # Web UI
91
+ def live_reporting
92
+ if initial_state.success?
93
+ @processes ||= Models::Processes.active(@current_state)
94
+ status = @processes.empty? ? :failure : :success
95
+ else
96
+ status = :halted
97
+ end
98
+
99
+ Step.new(
100
+ status,
101
+ nil
102
+ )
103
+ end
104
+
105
+ # @return [Status::Step] is there a subscription to our reports topic that is being
106
+ # consumed actively.
107
+ def state_calculation
108
+ if live_reporting.success?
109
+ @subscriptions ||= Models::Health.current(@current_state).values.flat_map(&:keys)
110
+ status = @subscriptions.include?(topics_consumers_reports) ? :success : :failure
111
+ else
112
+ status = :halted
113
+ end
114
+
115
+ Step.new(
116
+ status,
117
+ nil
118
+ )
119
+ end
120
+
121
+ private
122
+
123
+ # @return [String] consumers states topic name
124
+ def topics_consumers_states
125
+ ::Karafka::Web.config.topics.consumers.states.to_s
126
+ end
127
+
128
+ # @return [String] consumers reports topic name
129
+ def topics_consumers_reports
130
+ ::Karafka::Web.config.topics.consumers.reports.to_s
131
+ end
132
+
133
+ # @return [String] errors topic name
134
+ def topics_errors
135
+ ::Karafka::Web.config.topics.errors
136
+ end
137
+
138
+ # @return [Hash] hash with topics with which we work details (even if don't exist)
139
+ def topics_details
140
+ topics = {
141
+ topics_consumers_states => { present: false, partitions: 0 },
142
+ topics_consumers_reports => { present: false, partitions: 0 },
143
+ topics_errors => { present: false, partitions: 0 }
144
+ }
145
+
146
+ @cluster_info.topics.each do |topic|
147
+ name = topic[:topic_name]
148
+
149
+ next unless topics.key?(name)
150
+
151
+ topics[name][:present] = true
152
+ topics[name][:partitions] = topic[:partition_count]
153
+ end
154
+
155
+ topics
156
+ end
157
+
158
+ # Tries connecting with the cluster and sets the connection state
159
+ def connect
160
+ @cluster_info = ::Karafka::Admin.cluster_info
161
+ @connected = true
162
+ rescue ::Rdkafka::RdkafkaError
163
+ @connected = false
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -112,6 +112,11 @@ module Karafka
112
112
  controller = Controllers::Dlq.new(params)
113
113
  render_response controller.index
114
114
  end
115
+
116
+ r.get 'status' do
117
+ controller = Controllers::Status.new(params)
118
+ render_response controller.show
119
+ end
115
120
  end
116
121
  end
117
122
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This Karafka component is a Pro component under a commercial license.
4
+ # This Karafka component is NOT licensed under LGPL.
5
+ #
6
+ # All of the commercial components are present in the lib/karafka/pro directory of this
7
+ # repository and their usage requires commercial license agreement.
8
+ #
9
+ # Karafka has also commercial-friendly license, commercial support and commercial components.
10
+ #
11
+ # By sending a pull request to the pro components, you are agreeing to transfer the copyright of
12
+ # your code to Maciej Mensfeld.
13
+
14
+ module Karafka
15
+ module Web
16
+ module Ui
17
+ module Pro
18
+ module Controllers
19
+ # Status details - same as in OSS
20
+ class Status < Ui::Controllers::Status
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -8,16 +8,24 @@
8
8
  <%= process.name %>
9
9
  </a>
10
10
 
11
- <br/>
11
+ <p class="mt-0 mb-1">
12
+ <% process.consumer_groups.each do |consumer_group| %>
13
+ <% consumer_group.topics.each do |topic| %>
14
+ <span class="badge bg-secondary badge-topic" title="Consumer group: <%= consumer_group.id %>">
15
+ <%= topic.name %>:
16
+ <%= topic.partitions.map(&:id).join(',') %>
17
+ </span>
18
+ <% end %>
19
+ <% end %>
20
+ </p>
12
21
 
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(',') %>
22
+ <p class="mt-0 mb-1">
23
+ <% process.tags.each do |tag| %>
24
+ <span class="badge bg-info badge-topic">
25
+ <%= tag %>
18
26
  </span>
19
27
  <% end %>
20
- <% end %>
28
+ </p>
21
29
  </td>
22
30
 
23
31
  <td>
@@ -1,6 +1,10 @@
1
1
  <tr>
2
2
  <td>
3
3
  <code><%= job.consumer %></code>
4
+
5
+ <% job.tags.each do |tag| %>
6
+ <span class="badge bg-info"><%= tag %></span>
7
+ <% end %>
4
8
  </td>
5
9
  <td>
6
10
  <span class="badge bg-secondary badge-topic" title="Consumer group: <%= job.consumer_group %>">
@@ -27,6 +27,16 @@
27
27
  </li>
28
28
  </ul>
29
29
  </p>
30
+
31
+ <% unless @process.tags.empty? %>
32
+ <p class="mb-0 text-end">
33
+ <% @process.tags.each do |tag| %>
34
+ <span class="badge bg-info badge-topic">
35
+ <%= tag %>
36
+ </span>
37
+ <% end %>
38
+ </p>
39
+ <% end %>
30
40
  </div>
31
41
  </div>
32
42
  <div class="card">
@@ -12,6 +12,10 @@
12
12
  </td>
13
13
  <td>
14
14
  <code><%= job.consumer %></code>
15
+
16
+ <% job.tags.each do |tag| %>
17
+ <span class="badge bg-info"><%= tag %></span>
18
+ <% end %>
15
19
  </td>
16
20
  <td>
17
21
  <code>#<%= job.type %></code>
@@ -45,6 +45,11 @@
45
45
  Cluster
46
46
  </a>
47
47
  </li>
48
+ <li class="nav-item ms-3">
49
+ <a class="nav-link <%= nav_class(start_with: '/status') %>" href="<%= root_path('Status') %>">
50
+ Status
51
+ </a>
52
+ </li>
48
53
  </ul>
49
54
  </div>
50
55
 
@@ -8,16 +8,24 @@
8
8
  <%= process.name %>
9
9
  </a>
10
10
 
11
- <br/>
11
+ <p class="mt-0 mb-1">
12
+ <% process.consumer_groups.each do |consumer_group| %>
13
+ <% consumer_group.topics.each do |topic| %>
14
+ <span class="badge bg-secondary badge-topic" title="Consumer group: <%= consumer_group.id %>">
15
+ <%= topic.name %>:
16
+ <%= topic.partitions.map(&:id).join(',') %>
17
+ </span>
18
+ <% end %>
19
+ <% end %>
20
+ </p>
12
21
 
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(',') %>
22
+ <p class="mt-0 mb-1">
23
+ <% process.tags.each do |tag| %>
24
+ <span class="badge bg-info badge-topic">
25
+ <%= tag %>
18
26
  </span>
19
27
  <% end %>
20
- <% end %>
28
+ </p>
21
29
  </td>
22
30
 
23
31
  <td>
@@ -12,6 +12,10 @@
12
12
  </td>
13
13
  <td>
14
14
  <code><%= job.consumer %></code>
15
+
16
+ <% job.tags.each do |tag| %>
17
+ <span class="badge bg-info"><%= tag %></span>
18
+ <% end %>
15
19
  </td>
16
20
  <td>
17
21
  <code>#<%= job.type %></code>
@@ -45,6 +45,11 @@
45
45
  Cluster
46
46
  </a>
47
47
  </li>
48
+ <li class="nav-item ms-3">
49
+ <a class="nav-link <%= nav_class(start_with: '/status') %>" href="<%= root_path('status') %>">
50
+ Status
51
+ </a>
52
+ </li>
48
53
  </ul>
49
54
  </div>
50
55
 
@@ -20,6 +20,7 @@
20
20
  </p>
21
21
 
22
22
  <ul class="mb-5 text-start">
23
+ <li>You have visited the <a href="<%= root_path('status') %>">Status</a> page to troubleshoot any potential issues</li>
23
24
  <li>All the topics required by Karafka Web exist</li>
24
25
  <li>You have used <code>bundle exec karafka-web install</code> to initialize the Web UI</li>
25
26
  <li>You have a working connection with your Kafka cluster</li>
@@ -32,6 +33,7 @@
32
33
 
33
34
  <p>
34
35
  <a href="<%= root_path %>" class="btn btn-primary">Go Home</a>
36
+ <a href="<%= root_path('status') %>" class="btn btn-success">Status page</a>
35
37
  </p>
36
38
  </div>
37
39
  </div>
@@ -0,0 +1,5 @@
1
+ <li class="breadcrumb-item">
2
+ <a href="<%= root_path('status') %>">
3
+ Web UI status details
4
+ </a>
5
+ </li>
@@ -0,0 +1,14 @@
1
+ <div class="card border-danger mb-3">
2
+ <div class="card-header text-bg-danger">
3
+ <span>
4
+ <%= title %>
5
+ </span>
6
+
7
+ <span class="float-end">
8
+ <span class="badge text-bg-light">Failure</span>
9
+ </span>
10
+ </div>
11
+ <div class="card-body">
12
+ <%== description %>
13
+ </div>
14
+ </div>
@@ -0,0 +1,11 @@
1
+ <div class="card text-bg-secondary mb-3">
2
+ <div class="card-header">
3
+ <span>
4
+ <%= title %>
5
+ </span>
6
+
7
+ <span class="float-end">
8
+ <span class="badge text-bg-light">Halted</span>
9
+ </span>
10
+ </div>
11
+ </div>
@@ -0,0 +1,11 @@
1
+ <div class="card text-bg-success mb-3">
2
+ <div class="card-header">
3
+ <span>
4
+ <%= title %>
5
+ </span>
6
+
7
+ <span class="float-end">
8
+ <span class="badge text-bg-light">Successful</span>
9
+ </span>
10
+ </div>
11
+ </div>
@@ -0,0 +1,7 @@
1
+ <p>
2
+ Web UI was not able to establish a connection with the Kafka cluster.
3
+ </p>
4
+
5
+ <p class="mb-0">
6
+ Please make sure that Web UI can reach Kafka.
7
+ </p>
@@ -0,0 +1,20 @@
1
+ <p>
2
+ The initial state for the Web UI was not created.
3
+ </p>
4
+
5
+ <p>
6
+ It means that the <code>bundle exec karafka-web install</code> was not executed or failed.
7
+ </p>
8
+
9
+ <p>
10
+ To fix this, you can either:
11
+ </p>
12
+
13
+ <ul>
14
+ <li>Run <code>bundle exec karafka-web install</code></li>
15
+ <li>Run at least one Karafka consumer process</li>
16
+ </ul>
17
+
18
+ <p class="mb-0">
19
+ Any of the above, when successful, will bootstrap the initial state.
20
+ </p>
@@ -0,0 +1,7 @@
1
+ <p>
2
+ There are no Karafka consumer processes actively reporting to the Web UI.
3
+ </p>
4
+
5
+ <p class="mb-0">
6
+ If you are sure you are running at least one <code>karafka server</code> instance, please make sure that it can report to the <code><%= Karafka::Web.config.topics.consumers.reports %></code> topic.
7
+ </p>
@@ -0,0 +1,19 @@
1
+ <p>
2
+ Both
3
+ <code><%= Karafka::Web.config.topics.consumers.states %></code>
4
+ and
5
+ <code><%= Karafka::Web.config.topics.consumers.reports %></code>
6
+ topics need to be configured with <strong>exactly</strong> one partition.
7
+ </p>
8
+
9
+ <p>
10
+ Your current setup contains the following:
11
+ </p>
12
+
13
+ <ul class="mb-0">
14
+ <% details.each do |name, details| %>
15
+ <li>
16
+ <code><%= name %> </code> with <code><%= details[:partitions] %> </code> partitions.
17
+ </li>
18
+ <% end %>
19
+ </ul>
@@ -0,0 +1,8 @@
1
+ <p>
2
+ None of the <code>karafka server</code> processes is subscribed to handle the
3
+ <code><%= Karafka::Web.config.topics.consumers.reports %></code> topic data aggregations.
4
+ </p>
5
+
6
+ <p class="mb-0">
7
+ If you are limiting the topics you consume using the <a href="https://karafka.io/docs/CLI/#limiting-consumer-groups-used-per-process" target="_blank">limiting API</a>, please include the Karafka Web consumer group and the <code><%= Karafka::Web.config.topics.consumers.reports %></code> topic.
8
+ </p>
@@ -0,0 +1,20 @@
1
+ <p>
2
+ Web UI requires the following topics to exist:
3
+ </p>
4
+
5
+ <ul>
6
+ <% details.each do |name, details| %>
7
+ <li>
8
+ <code><%= name %></code> - <%= details[:present] ? 'Exists' : 'Missing' %>
9
+ </li>
10
+ <% end %>
11
+ </ul>
12
+
13
+ <p>
14
+ Please ensure all those topics exist and are accessible to your Karafka user.
15
+ </p>
16
+
17
+ <p class="mb-0">
18
+ You can read more about their setup and configuration
19
+ <a href="https://karafka.io/docs/Web-UI-Getting-Started/" target="_blank">here</a>.
20
+ </p>
@@ -0,0 +1,94 @@
1
+ <%== view_title('Web UI status details') %>
2
+
3
+ <div class="container mb-5">
4
+ <div class="row">
5
+ <div class="col-lg-10 offset-md-1">
6
+
7
+ <%==
8
+ partial(
9
+ "status/#{@status.connection.to_s}",
10
+ locals: {
11
+ title: 'Connection to Kafka',
12
+ description: partial('status/failures/connection')
13
+ }
14
+ )
15
+ %>
16
+
17
+ <%==
18
+ partial(
19
+ "status/#{@status.topics.to_s}",
20
+ locals: {
21
+ title: 'Topics presence',
22
+ description: partial(
23
+ 'status/failures/topics',
24
+ locals: {
25
+ details: @status.topics.details
26
+ }
27
+ )
28
+ }
29
+ )
30
+ %>
31
+
32
+ <%==
33
+ partial(
34
+ "status/#{@status.partitions.to_s}",
35
+ locals: {
36
+ title: 'Partitions count',
37
+ description: partial(
38
+ 'status/failures/partitions',
39
+ locals: {
40
+ details: @status.partitions.details
41
+ }
42
+ )
43
+ }
44
+ )
45
+ %>
46
+
47
+ <%==
48
+ partial(
49
+ "status/#{@status.initial_state.to_s}",
50
+ locals: {
51
+ title: 'Initial state presence',
52
+ description: partial(
53
+ 'status/failures/initial_state',
54
+ locals: {
55
+ details: @status.initial_state.details
56
+ }
57
+ )
58
+ }
59
+ )
60
+ %>
61
+
62
+ <%==
63
+ partial(
64
+ "status/#{@status.live_reporting.to_s}",
65
+ locals: {
66
+ title: 'Live reporting',
67
+ description: partial(
68
+ 'status/failures/live_reporting',
69
+ locals: {
70
+ details: @status.live_reporting.details
71
+ }
72
+ )
73
+ }
74
+ )
75
+ %>
76
+
77
+ <%==
78
+ partial(
79
+ "status/#{@status.state_calculation.to_s}",
80
+ locals: {
81
+ title: 'State calculation subscription',
82
+ description: partial(
83
+ 'status/failures/state_calculation',
84
+ locals: {
85
+ details: @status.state_calculation.details
86
+ }
87
+ )
88
+ }
89
+ )
90
+ %>
91
+
92
+ </div>
93
+ </div>
94
+ </div>
@@ -3,6 +3,6 @@
3
3
  module Karafka
4
4
  module Web
5
5
  # Current gem version
6
- VERSION = '0.1.3'
6
+ VERSION = '0.2.0'
7
7
  end
8
8
  end
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.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -35,7 +35,7 @@ cert_chain:
35
35
  Qf04B9ceLUaC4fPVEz10FyobjaFoY4i32xRto3XnrzeAgfEe4swLq8bQsR3w/EF3
36
36
  MGU0FeSV2Yj7Xc2x/7BzLK8xQn5l7Yy75iPF+KP3vVmDHnNl
37
37
  -----END CERTIFICATE-----
38
- date: 2023-02-14 00:00:00.000000000 Z
38
+ date: 2023-02-24 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: erubi
@@ -57,7 +57,7 @@ dependencies:
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 2.0.29
60
+ version: 2.0.33
61
61
  - - "<"
62
62
  - !ruby/object:Gem::Version
63
63
  version: 3.0.0
@@ -67,7 +67,7 @@ dependencies:
67
67
  requirements:
68
68
  - - ">="
69
69
  - !ruby/object:Gem::Version
70
- version: 2.0.29
70
+ version: 2.0.33
71
71
  - - "<"
72
72
  - !ruby/object:Gem::Version
73
73
  version: 3.0.0
@@ -77,7 +77,7 @@ dependencies:
77
77
  requirements:
78
78
  - - ">="
79
79
  - !ruby/object:Gem::Version
80
- version: 2.0.10
80
+ version: 2.0.12
81
81
  - - "<"
82
82
  - !ruby/object:Gem::Version
83
83
  version: 3.0.0
@@ -87,7 +87,7 @@ dependencies:
87
87
  requirements:
88
88
  - - ">="
89
89
  - !ruby/object:Gem::Version
90
- version: 2.0.10
90
+ version: 2.0.12
91
91
  - - "<"
92
92
  - !ruby/object:Gem::Version
93
93
  version: 3.0.0
@@ -199,6 +199,7 @@ files:
199
199
  - lib/karafka/web/ui/controllers/requests/params.rb
200
200
  - lib/karafka/web/ui/controllers/responses/data.rb
201
201
  - lib/karafka/web/ui/controllers/routing.rb
202
+ - lib/karafka/web/ui/controllers/status.rb
202
203
  - lib/karafka/web/ui/helpers/application_helper.rb
203
204
  - lib/karafka/web/ui/lib/hash_proxy.rb
204
205
  - lib/karafka/web/ui/lib/paginate_array.rb
@@ -210,6 +211,7 @@ files:
210
211
  - lib/karafka/web/ui/models/process.rb
211
212
  - lib/karafka/web/ui/models/processes.rb
212
213
  - lib/karafka/web/ui/models/state.rb
214
+ - lib/karafka/web/ui/models/status.rb
213
215
  - lib/karafka/web/ui/models/topic.rb
214
216
  - lib/karafka/web/ui/pro/app.rb
215
217
  - lib/karafka/web/ui/pro/controllers/cluster.rb
@@ -220,6 +222,7 @@ files:
220
222
  - lib/karafka/web/ui/pro/controllers/health.rb
221
223
  - lib/karafka/web/ui/pro/controllers/jobs.rb
222
224
  - lib/karafka/web/ui/pro/controllers/routing.rb
225
+ - lib/karafka/web/ui/pro/controllers/status.rb
223
226
  - lib/karafka/web/ui/pro/views/consumers/_breadcrumbs.erb
224
227
  - lib/karafka/web/ui/pro/views/consumers/_consumer.erb
225
228
  - lib/karafka/web/ui/pro/views/consumers/_counters.erb
@@ -315,6 +318,17 @@ files:
315
318
  - lib/karafka/web/ui/views/shared/_pagination.erb
316
319
  - lib/karafka/web/ui/views/shared/exceptions/not_found.erb
317
320
  - lib/karafka/web/ui/views/shared/exceptions/pro_only.erb
321
+ - lib/karafka/web/ui/views/status/_breadcrumbs.erb
322
+ - lib/karafka/web/ui/views/status/_failure.erb
323
+ - lib/karafka/web/ui/views/status/_halted.erb
324
+ - lib/karafka/web/ui/views/status/_success.erb
325
+ - lib/karafka/web/ui/views/status/failures/_connection.erb
326
+ - lib/karafka/web/ui/views/status/failures/_initial_state.erb
327
+ - lib/karafka/web/ui/views/status/failures/_live_reporting.erb
328
+ - lib/karafka/web/ui/views/status/failures/_partitions.erb
329
+ - lib/karafka/web/ui/views/status/failures/_state_calculation.erb
330
+ - lib/karafka/web/ui/views/status/failures/_topics.erb
331
+ - lib/karafka/web/ui/views/status/show.erb
318
332
  - lib/karafka/web/version.rb
319
333
  homepage: https://karafka.io
320
334
  licenses:
metadata.gz.sig CHANGED
Binary file