karafka-web 0.11.0.rc2 → 0.11.0.rc3

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/Gemfile.lock +5 -5
  4. data/config/locales/slogans.yml +1 -1
  5. data/docker-compose.yml +1 -1
  6. data/lib/karafka/web/pro/ui/controllers/errors_controller.rb +8 -4
  7. data/lib/karafka/web/pro/ui/controllers/explorer/explorer_controller.rb +19 -9
  8. data/lib/karafka/web/pro/ui/views/consumers/jobs/_job.erb +1 -2
  9. data/lib/karafka/web/pro/ui/views/consumers/jobs/_no_jobs.erb +2 -6
  10. data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/edit.erb +5 -1
  11. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/edit.erb +5 -1
  12. data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/new.erb +5 -1
  13. data/lib/karafka/web/pro/ui/views/errors/_breadcrumbs.erb +1 -6
  14. data/lib/karafka/web/pro/ui/views/errors/_error.erb +6 -1
  15. data/lib/karafka/web/pro/ui/views/errors/show.erb +39 -33
  16. data/lib/karafka/web/pro/ui/views/explorer/explorer/show.erb +76 -71
  17. data/lib/karafka/web/pro/ui/views/jobs/_job.erb +1 -2
  18. data/lib/karafka/web/ui/base.rb +2 -0
  19. data/lib/karafka/web/ui/controllers/errors_controller.rb +12 -3
  20. data/lib/karafka/web/ui/helpers/application_helper.rb +0 -70
  21. data/lib/karafka/web/ui/helpers/time_helper.rb +82 -0
  22. data/lib/karafka/web/ui/helpers/topics_helper.rb +156 -0
  23. data/lib/karafka/web/ui/models/message.rb +20 -2
  24. data/lib/karafka/web/ui/public/stylesheets/application.min.css +10 -35
  25. data/lib/karafka/web/ui/public/stylesheets/application.min.css.br +0 -0
  26. data/lib/karafka/web/ui/public/stylesheets/application.min.css.gz +0 -0
  27. data/lib/karafka/web/ui/routes/errors.rb +5 -1
  28. data/lib/karafka/web/ui/views/consumers/_assignments_badges.erb +2 -7
  29. data/lib/karafka/web/ui/views/errors/_breadcrumbs.erb +3 -8
  30. data/lib/karafka/web/ui/views/errors/_error.erb +6 -1
  31. data/lib/karafka/web/ui/views/errors/show.erb +39 -33
  32. data/lib/karafka/web/ui/views/jobs/_job.erb +1 -2
  33. data/lib/karafka/web/ui/views/shared/_compacted_message_info.erb +16 -0
  34. data/lib/karafka/web/version.rb +1 -1
  35. data/package-lock.json +71 -71
  36. data/package.json +4 -4
  37. metadata +4 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dab1b6de37ef1345cf4882f8c24e02f4fef947c9ca16efd0269acc0a66b8e911
4
- data.tar.gz: 3259ecc90d8130c1e6c68e9d9712a40b47b72c305ca1154c69dc1b60da24874f
3
+ metadata.gz: 5263c3a83f8cbd944097fb7889c936836fc0dc09880f4d14e87783a1ea55142b
4
+ data.tar.gz: 5a4ae04fb60f88132ca5855879a689471969f9c1b3d957ef2d9798d112c81ef3
5
5
  SHA512:
6
- metadata.gz: ebecc3ab736556d83202ab6f874d49ae7475c73e2dce6f26c99f6bffaa8043cdca996f01a213fa336c4d162df7a0a5e36f29b2cdf21cbfb3a1e25dc2311c19d9
7
- data.tar.gz: 55bc665b159ff2fd47e737726b44a4b6f26f4f64e211b8a6cf6f662e2f8217c8919e6e0416102e32303523d5995f8612ab0bc0c9df04148657dd0d3f8f12ee48
6
+ metadata.gz: 7d22123886f177f58f20783e6abe09fd84fc8d7554ac6f47a7103176f2c48a700c7e9ec90f38e72859dc54e51c959c7486b2f7b43512f6e3f649ca87498c3bd8
7
+ data.tar.gz: 33eb094a22870bb238016b018aa986f9914523eda62587f9d3cfc462249a62bbd88e66d2cb605c2fb6309fc5c7d1a03412c7cc3b1db9a5560a6d9ea7e11aa205
data/CHANGELOG.md CHANGED
@@ -28,6 +28,7 @@
28
28
  - [Enhancement] Inject `.action-NAME` and `.controller-NAME` body classes for usage with custom CSS and JS.
29
29
  - [Enhancement] Improve error handling in the commanding iterator listener (Pro).
30
30
  - [Enhancement] Introduce `trace_id` to the errors tracked for DLQ correlation (if in use) (Pro).
31
+ - [Enhancement] Normalize how topics with partitions data is being displayed (`topic-[0,1,2]` etc).
31
32
  - [Change] Do not fully hide config-disabled features but make them disabled.
32
33
  - [Change] Remove per-consumer process duplicated details from Subscriptions and Jobs tabs.
33
34
  - [Change] Move to trusted-publishers and remove signing since no longer needed.
@@ -54,6 +55,10 @@
54
55
  - [Fix] Ensure that when flashes or alerts are visible, pages are not auto-refreshed (would cause them to dissapear).
55
56
  - [Fix] Time selector in the explorer does not disappear after clicking out.
56
57
  - [Fix] Tombstone message presentation epoch doesn't make sense.
58
+ - [Fix] Fix incorrectly displayed "No jobs" alert info.
59
+ - [Fix] Previous / next navigation in the explorer does not work when moving to transactional checkpoints.
60
+ - [Fix] Errors explorer does not work with transactional produced data.
61
+ - [Fix] Errors explorer in OSS does not have pagination.
57
62
  - [Maintenance] Require `karafka-core` `>= 2.4.8` and `karafka` `>= 2.4.16`.
58
63
  - [Maintenance] Update `AirDatepicker` to `3.6.0`.
59
64
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- karafka-web (0.11.0.rc2)
4
+ karafka-web (0.11.0.rc3)
5
5
  erubi (~> 1.4)
6
6
  karafka (>= 2.5.0.rc1, < 2.6.0)
7
7
  karafka-core (>= 2.5.0, < 2.6.0)
@@ -35,7 +35,7 @@ GEM
35
35
  erubi (1.13.1)
36
36
  et-orbi (1.2.11)
37
37
  tzinfo
38
- factory_bot (6.5.3)
38
+ factory_bot (6.5.4)
39
39
  activesupport (>= 6.1.0)
40
40
  ffi (1.17.2)
41
41
  ffi (1.17.2-aarch64-linux-gnu)
@@ -53,13 +53,13 @@ GEM
53
53
  raabro (~> 1.4)
54
54
  i18n (1.14.7)
55
55
  concurrent-ruby (~> 1.0)
56
- karafka (2.5.0.rc1)
56
+ karafka (2.5.0.rc2)
57
57
  base64 (~> 0.2)
58
- karafka-core (>= 2.5.0, < 2.6.0)
58
+ karafka-core (>= 2.5.2, < 2.6.0)
59
59
  karafka-rdkafka (>= 0.19.5)
60
60
  waterdrop (>= 2.8.3, < 3.0.0)
61
61
  zeitwerk (~> 2.3)
62
- karafka-core (2.5.1)
62
+ karafka-core (2.5.2)
63
63
  karafka-rdkafka (>= 0.19.2, < 0.21.0)
64
64
  logger (>= 1.6.0)
65
65
  karafka-rdkafka (0.19.5)
@@ -43,7 +43,7 @@ en:
43
43
  - "Are you concerned about managing large data flows? Virtual Partitions in Karafka Pro simplify data processing, offering unparalleled efficiency and scalability."
44
44
  - "Looking for flexible scheduling solutions? Karafka's Pro Periodic Jobs feature allows precise task timing and execution, enhancing your application's performance and reliability."
45
45
  - "Need advanced routing capabilities? Routing Patterns in Karafka Pro provide dynamic message routing, improving your system's adaptability and efficiency."
46
- - "Are you Seeking to control your workload? With Rate Limiting in Karafka Pro, you can effectively manage and balance your system's load, ensuring optimal performance under any conditions."
46
+ - "Are you seeking to control your workload? With Rate Limiting in Karafka Pro, you can effectively manage and balance your system's load, ensuring optimal performance under any conditions."
47
47
  - "Need quick data access methods? The Iterator API in Karafka Pro provides efficient data retrieval methods."
48
48
  - "Want more nuanced error handling? Discover Granular Backoffs in Karafka Pro, which allows for detailed control over retry mechanisms and error recovery processes."
49
49
  - "Need a boost in data processing speed? Multiplexing in Karafka Pro enables parallel processing, significantly increasing throughput and reducing processing times."
data/docker-compose.yml CHANGED
@@ -3,7 +3,7 @@ version: '2'
3
3
  services:
4
4
  kafka:
5
5
  container_name: kafka
6
- image: confluentinc/cp-kafka:7.9.1
6
+ image: confluentinc/cp-kafka:8.0.0
7
7
 
8
8
  ports:
9
9
  - 9092:9092
@@ -46,7 +46,8 @@ module Karafka
46
46
  previous_offset,
47
47
  @params.current_offset,
48
48
  next_offset,
49
- @error_messages.map(&:offset)
49
+ # If message is an array, it means it's a compacted dummy offset representation
50
+ @error_messages.map { |message| message.is_a?(Array) ? message.last : message.offset }
50
51
  )
51
52
 
52
53
  render
@@ -59,13 +60,16 @@ module Karafka
59
60
  def show(partition_id, offset)
60
61
  @partition_id = partition_id
61
62
  @offset = offset
63
+
64
+ watermark_offsets = Models::WatermarkOffsets.find(errors_topic, partition_id)
65
+
62
66
  @error_message = Models::Message.find(
63
67
  errors_topic,
64
- @partition_id,
65
- @offset
68
+ partition_id,
69
+ offset,
70
+ watermark_offsets: watermark_offsets
66
71
  )
67
72
 
68
- watermark_offsets = Models::WatermarkOffsets.find(errors_topic, partition_id)
69
73
  paginate(offset, watermark_offsets.low, watermark_offsets.high)
70
74
 
71
75
  render
@@ -91,20 +91,30 @@ module Karafka
91
91
  @topic_id = topic_id
92
92
  @partition_id = partition_id
93
93
  @offset = offset
94
- @message = Models::Message.find(@topic_id, @partition_id, @offset)
95
94
 
96
- @safe_key = Web::Pro::Ui::Lib::SafeRunner.new { @message.key }.tap(&:call)
97
- @safe_headers = Web::Pro::Ui::Lib::SafeRunner.new { @message.headers }.tap(&:call)
98
- @safe_payload = Web::Pro::Ui::Lib::SafeRunner.new { @message.payload }.tap(&:call)
95
+ watermark_offsets = Models::WatermarkOffsets.find(topic_id, partition_id)
96
+
97
+ @message = Models::Message.find(
98
+ @topic_id,
99
+ @partition_id,
100
+ @offset,
101
+ watermark_offsets: watermark_offsets
102
+ )
103
+
104
+ # Only if it is not a compacted message we can deserialize stuff
105
+ if @message
106
+ @safe_key = Web::Pro::Ui::Lib::SafeRunner.new { @message.key }.tap(&:call)
107
+ @safe_headers = Web::Pro::Ui::Lib::SafeRunner.new { @message.headers }.tap(&:call)
108
+ @safe_payload = Web::Pro::Ui::Lib::SafeRunner.new { @message.payload }.tap(&:call)
109
+ end
99
110
 
100
111
  # This may be off for certain views like recent view where we are interested only
101
112
  # in the most recent all the time. It does not make any sense to display pagination
102
113
  # there
103
- if paginate
104
- # We need watermark offsets to decide if we can paginate left and right
105
- watermark_offsets = Models::WatermarkOffsets.find(topic_id, partition_id)
106
- paginate(offset, watermark_offsets.low, watermark_offsets.high)
107
- end
114
+ #
115
+ # We need watermark offsets to decide if we can paginate left and right
116
+ # We check that because it may have got here via the transactional flow
117
+ paginate(offset, watermark_offsets.low, watermark_offsets.high) if paginate
108
118
 
109
119
  render
110
120
  end
@@ -4,8 +4,7 @@
4
4
  <tr>
5
5
  <td>
6
6
  <span class="badge badge-secondary" title="Consumer group: <%= job.consumer_group %>">
7
- <%= job.topic %>:
8
- <%= job.partition %>
7
+ <%= topics_partition_identifier(job.topic, job.partition) %>
9
8
  </span>
10
9
  </td>
11
10
  <td>
@@ -1,10 +1,6 @@
1
1
  <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
2
  <%# See LICENSE for details. %>
3
3
 
4
- <div class="container mb-4">
5
- <div class="row">
6
- <div class="col-lg-12">
7
- <%== alert_info("This process has no #{type} jobs at the moment.") %>
8
- </div>
9
- </div>
4
+ <div class="col-lg-12">
5
+ <%== alert_info("This process has no #{type} jobs at the moment.") %>
10
6
  </div>
@@ -1,7 +1,11 @@
1
1
  <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
2
  <%# See LICENSE for details. %>
3
3
 
4
- <% view_title "#{@process.id} - Offset Adjustment - #{@subscription_group_id} - #{@topic}##{@partition_id}" %>
4
+ <%
5
+ tpi = topics_partition_identifier(@topic, @partition_id)
6
+
7
+ view_title "#{@process.id} - Offset Adjustment - #{@subscription_group_id} - #{tpi}"
8
+ %>
5
9
 
6
10
  <% if @process.status != 'running' %>
7
11
  <%== partial 'consumers/partitions/offsets/not_running_error' %>
@@ -1,7 +1,11 @@
1
1
  <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
2
  <%# See LICENSE for details. %>
3
3
 
4
- <% view_title "#{@process.id} - Pause Adjustment - #{@subscription_group_id} - #{@topic}##{@partition_id}" %>
4
+ <%
5
+ tpi = topics_partition_identifier(@topic, @partition_id)
6
+
7
+ view_title "#{@process.id} - Pause Adjustment - #{@subscription_group_id} - #{tpi}"
8
+ %>
5
9
 
6
10
  <% if @topic_lrj %>
7
11
  <%== partial 'consumers/partitions/pauses/lrj_not_manageable' %>
@@ -1,7 +1,11 @@
1
1
  <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
2
  <%# See LICENSE for details. %>
3
3
 
4
- <% view_title "#{@process.id} - Pause Adjustment - #{@subscription_group_id} - #{@topic}##{@partition_id}" %>
4
+ <%
5
+ tpi = topics_partition_identifier(@topic, @partition_id)
6
+
7
+ view_title "#{@process.id} - Pause Adjustment - #{@subscription_group_id} - #{tpi}"
8
+ %>
5
9
 
6
10
  <% if @topic_lrj %>
7
11
  <%== partial 'consumers/partitions/pauses/lrj_not_manageable' %>
@@ -18,12 +18,7 @@
18
18
  <% if @offset %>
19
19
  <li>
20
20
  <a href="<%= root_path('errors', @partition_id, @offset) %>">
21
- <%=
22
- type = @error_message.payload[:type]
23
- error_class = @error_message.payload[:error_class]
24
-
25
- "#{type}: #{error_class}"
26
- %>
21
+ <%= "Offset #{@offset}" %>
27
22
  </a>
28
23
  </li>
29
24
  <% end %>
@@ -10,7 +10,12 @@
10
10
  <td>
11
11
  <span class="badge badge-secondary">
12
12
  <% if error[:details].key?(:topic) %>
13
- <%= error[:details][:topic] %>: <%= error[:details][:partition] %>
13
+ <%=
14
+ topic = error[:details][:topic]
15
+ partition = error[:details][:partition]
16
+
17
+ topics_partition_identifier(topic, partition)
18
+ %>
14
19
  <% else %>
15
20
  <%= error[:type] %>
16
21
  <% end %>
@@ -1,42 +1,48 @@
1
1
  <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
2
  <%# See LICENSE for details. %>
3
3
 
4
- <%
5
- type = @error_message.payload[:type]
6
- error_class = @error_message.payload[:error_class]
4
+ <% if @error_message %>
5
+ <%
6
+ type = @error_message.payload[:type]
7
+ error_class = @error_message.payload[:error_class]
7
8
 
8
- view_title("#{type}: #{error_class}")
9
- %>
9
+ view_title("#{type}: #{error_class}")
10
+ %>
10
11
 
11
- <div class="col-span-12 mb-3">
12
- <h2 class="h2">
13
- Metadata
14
- </h2>
12
+ <div class="col-span-12 mb-3">
13
+ <h2 class="h2">
14
+ Metadata
15
+ </h2>
15
16
 
16
- <div class="data-table-wrapper">
17
- <table class="data-table">
18
- <tbody>
19
- <% @error_message.payload.each do |k, v| %>
20
- <% next if k == :backtrace %>
21
- <%==
22
- partial(
23
- 'errors/detail',
24
- locals: {
25
- k: k,
26
- v: v
27
- }
28
- )
29
- %>
30
- <% end %>
31
- </tbody>
32
- </table>
17
+ <div class="data-table-wrapper">
18
+ <table class="data-table">
19
+ <tbody>
20
+ <% @error_message.payload.each do |k, v| %>
21
+ <% next if k == :backtrace %>
22
+ <%==
23
+ partial(
24
+ 'errors/detail',
25
+ locals: {
26
+ k: k,
27
+ v: v
28
+ }
29
+ )
30
+ %>
31
+ <% end %>
32
+ </tbody>
33
+ </table>
34
+ </div>
33
35
  </div>
34
- </div>
35
36
 
36
- <div class="col-span-12 mb-3">
37
- <h2 class="h2">
38
- Backtrace
39
- </h2>
37
+ <div class="col-span-12 mb-3">
38
+ <h2 class="h2">
39
+ Backtrace
40
+ </h2>
40
41
 
41
- <pre class="mb-5 p-0 border border-gray-300 text-sm"><code class="wrapped json p-0 m-0"><%= @error_message.payload[:backtrace] %></code></pre>
42
- </div>
42
+ <pre class="mb-5 p-0 border border-gray-300 text-sm"><code class="wrapped json p-0 m-0"><%= @error_message.payload[:backtrace] %></code></pre>
43
+ </div>
44
+ <% else %>
45
+ <% view_title "Offset #{@offset}" %>
46
+
47
+ <%== partial 'shared/compacted_message_info' %>
48
+ <% end %>
@@ -1,95 +1,100 @@
1
1
  <%# This code is part of Karafka Pro, a commercial component not licensed under LGPL. %>
2
2
  <%# See LICENSE for details. %>
3
3
 
4
- <% view_title "Message with offset #{@message.offset} from partition #{@message.partition}" %>
4
+ <% if @message %>
5
+ <% view_title "Message with offset #{@offset} from partition #{@partition_id}" %>
5
6
 
6
- <%
7
- republish_path = explorer_messages_path(@message.topic, @message.partition, @message.offset, 'republish')
8
- surrounding_path = explorer_topics_path(@message.topic, @message.partition, @message.offset, 'surrounding')
9
- %>
7
+ <%
8
+ republish_path = explorer_messages_path(@message.topic, @message.partition, @message.offset, 'republish')
9
+ surrounding_path = explorer_topics_path(@message.topic, @message.partition, @message.offset, 'surrounding')
10
+ %>
11
+ <div class="col-span-12">
12
+ <section class="actions">
13
+ <% if @visibility_filter.republish?(@message) %>
14
+ <a
15
+ href="<%= explorer_messages_path(@message.topic, @message.partition, @message.offset, 'forward') %>"
16
+ class="btn-action"
17
+ title="Republish this message"
18
+ >
19
+ <%== icon(:arrow_uturn_right) %>
20
+ </a>
21
+ <% end %>
10
22
 
11
- <div class="col-span-12">
12
- <section class="actions">
13
- <% if @visibility_filter.republish?(@message) %>
14
23
  <a
15
- href="<%= explorer_messages_path(@message.topic, @message.partition, @message.offset, 'forward') %>"
24
+ href="<%= surrounding_path %>"
16
25
  class="btn-action"
17
- title="Republish this message"
26
+ title="Go to this message surrounding position"
18
27
  >
19
- <%== icon(:arrow_uturn_right) %>
28
+ <%== icon(:arrows_right_left) %>
20
29
  </a>
21
- <% end %>
22
30
 
23
- <a
24
- href="<%= surrounding_path %>"
25
- class="btn-action"
26
- title="Go to this message surrounding position"
27
- >
28
- <%== icon(:arrows_right_left) %>
29
- </a>
31
+ <% if @visibility_filter.download?(@message) %>
32
+ <a
33
+ href="<%= explorer_messages_path(@message.topic, @message.partition, @message.offset, 'download') %>"
34
+ class="btn-action"
35
+ title="Download raw payload"
36
+ data-turbo="false"
37
+ >
38
+ <%== icon(:arrow_down_tray) %>
39
+ </a>
40
+ <% end %>
30
41
 
31
- <% if @visibility_filter.download?(@message) %>
32
- <a
33
- href="<%= explorer_messages_path(@message.topic, @message.partition, @message.offset, 'download') %>"
34
- class="btn-action"
35
- title="Download raw payload"
36
- data-turbo="false"
42
+ <% if @visibility_filter.export?(@message) && @safe_payload.success? %>
43
+ <a
44
+ href="<%= explorer_messages_path(@message.topic, @message.partition, @message.offset, 'export') %>"
45
+ class="btn-action"
46
+ title="Export as JSON"
47
+ data-turbo="false"
48
+ >
49
+ <%== icon(:arrow_down_on_square) %>
50
+ </a>
51
+ <% end %>
52
+
53
+ <button
54
+ class="btn-action btn-toggle"
55
+ title="Show the message metadata details"
56
+ id="metadata-button"
57
+ data-toggle-target="metadata-details"
37
58
  >
38
- <%== icon(:arrow_down_tray) %>
39
- </a>
40
- <% end %>
59
+ <%== icon(:circle_stack) %>
60
+ </button>
41
61
 
42
- <% if @visibility_filter.export?(@message) && @safe_payload.success? %>
43
- <a
44
- href="<%= explorer_messages_path(@message.topic, @message.partition, @message.offset, 'export') %>"
45
- class="btn-action"
46
- title="Export as JSON"
47
- data-turbo="false"
62
+ <button
63
+ class="btn-action btn-toggle"
64
+ title="Show the message utilization details"
65
+ id="utilization-button"
66
+ data-toggle-target="utilization-details"
48
67
  >
49
- <%== icon(:arrow_down_on_square) %>
50
- </a>
51
- <% end %>
68
+ <%== icon(:cpu) %>
69
+ </button>
70
+ </section>
71
+ </div>
52
72
 
53
- <button
54
- class="btn-action btn-toggle"
55
- title="Show the message metadata details"
56
- id="metadata-button"
57
- data-toggle-target="metadata-details"
58
- >
59
- <%== icon(:circle_stack) %>
60
- </button>
73
+ <div class="col-span-12 mb-6">
74
+ <div id="utilization-details" class="hidden">
75
+ <h2 class="h2">
76
+ Utilization
77
+ </h2>
61
78
 
62
- <button
63
- class="btn-action btn-toggle"
64
- title="Show the message utilization details"
65
- id="utilization-button"
66
- data-toggle-target="utilization-details"
67
- >
68
- <%== icon(:cpu) %>
69
- </button>
70
- </section>
71
- </div>
79
+ <%== partial 'explorer/explorer/message/resources_utilization' %>
80
+ </div>
72
81
 
73
- <div class="col-span-12 mb-6">
74
- <div id="utilization-details" class="hidden">
75
- <h2 class="h2">
76
- Utilization
77
- </h2>
82
+ <div id="metadata-details">
83
+ <h2 class="h2">
84
+ Metadata
85
+ </h2>
78
86
 
79
- <%== partial 'explorer/explorer/message/resources_utilization' %>
80
- </div>
87
+ <%== partial 'explorer/explorer/message/metadata' %>
88
+ </div>
81
89
 
82
- <div id="metadata-details">
83
90
  <h2 class="h2">
84
- Metadata
91
+ Payload
85
92
  </h2>
86
93
 
87
- <%== partial 'explorer/explorer/message/metadata' %>
94
+ <%== partial 'explorer/explorer/message/payload' %>
88
95
  </div>
96
+ <% else %>
97
+ <% view_title "Message with offset #{@offset} from partition #{@partition_id} (No Data)" %>
89
98
 
90
- <h2 class="h2">
91
- Payload
92
- </h2>
93
-
94
- <%== partial 'explorer/explorer/message/payload' %>
95
- </div>
99
+ <%== partial 'shared/compacted_message_info' %>
100
+ <% end %>
@@ -9,8 +9,7 @@
9
9
  </td>
10
10
  <td>
11
11
  <span class="badge badge-secondary" title="Consumer group: <%= job.consumer_group %>">
12
- <%= job.topic %>:
13
- <%= job.partition %>
12
+ <%= topics_partition_identifier(job.topic, job.partition) %>
14
13
  </span>
15
14
  </td>
16
15
  <td>
@@ -7,6 +7,8 @@ module Karafka
7
7
  class Base < Roda
8
8
  include Helpers::PathsHelper
9
9
  include Helpers::ApplicationHelper
10
+ include Helpers::TimeHelper
11
+ include Helpers::TopicsHelper
10
12
  include Helpers::TailwindHelper
11
13
 
12
14
  # Details that need to be evaluated in the context of OSS or Pro web UI.
@@ -17,7 +17,8 @@ module Karafka
17
17
  previous_offset,
18
18
  @params.current_offset,
19
19
  next_offset,
20
- @error_messages.map(&:offset)
20
+ # If message is an array, it means it's a compacted dummy offset representation
21
+ @error_messages.map { |message| message.is_a?(Array) ? message.last : message.offset }
21
22
  )
22
23
 
23
24
  render
@@ -25,12 +26,20 @@ module Karafka
25
26
 
26
27
  # @param offset [Integer] given error message offset
27
28
  def show(offset)
29
+ @partition_id = 0
30
+ @offset = offset
31
+
32
+ watermark_offsets = Models::WatermarkOffsets.find(errors_topic, @partition_id)
33
+
28
34
  @error_message = Models::Message.find(
29
35
  errors_topic,
30
- 0,
31
- offset
36
+ @partition_id,
37
+ offset,
38
+ watermark_offsets: watermark_offsets
32
39
  )
33
40
 
41
+ paginate(offset, watermark_offsets.low, watermark_offsets.high)
42
+
34
43
  render
35
44
  end
36
45
 
@@ -129,76 +129,6 @@ module Karafka
129
129
  parts.join('.')
130
130
  end
131
131
 
132
- # @param time [Float] UTC time float
133
- # @return [String] relative time tag for timeago.js
134
- def relative_time(time)
135
- stamp = Time.at(time).getutc.iso8601(3)
136
- %(<time class="ltr" dir="ltr" title="#{stamp}" datetime="#{stamp}">#{time}</time>)
137
- end
138
-
139
- # @param time [Time] time object we want to present with detailed ms label
140
- # @return [String] span tag with raw timestamp as a title and time as a value
141
- def time_with_label(time)
142
- stamp = (time.to_f * 1000).to_i
143
-
144
- %(<span title="#{stamp}">#{time}</span>)
145
- end
146
-
147
- # Converts raw second count into human readable form like "12.2 minutes". etc based on
148
- # number of seconds
149
- #
150
- # @param seconds [Numeric] number of seconds
151
- # @return [String] human readable time
152
- def human_readable_time(seconds)
153
- case seconds
154
- when 0..59
155
- "#{seconds.round(2)} seconds"
156
- when 60..3_599
157
- minutes = seconds / 60.0
158
- "#{minutes.round(2)} minutes"
159
- when 3_600..86_399
160
- hours = seconds / 3_600.0
161
- "#{hours.round(2)} hours"
162
- else
163
- days = seconds / 86_400.0
164
- "#{days.round(2)} days"
165
- end
166
- end
167
-
168
- # @param state [String] poll state
169
- # @param state_ch [Integer] time until next change of the poll state
170
- # (from paused to active)
171
- # @return [String] span tag with label and title with change time if present
172
- def poll_state_with_change_time_label(state, state_ch)
173
- year_in_seconds = 131_556_926
174
- state_ch_in_seconds = state_ch / 1_000.0
175
-
176
- # If state is active, there is no date of change
177
- if state == 'active'
178
- %(
179
- <span class="badge #{kafka_state_badge(state)}">#{state}</span>
180
- )
181
- elsif state_ch_in_seconds > year_in_seconds
182
- %(
183
- <span
184
- class="badge #{kafka_state_badge(state)}"
185
- title="until manual resume"
186
- >
187
- #{state}
188
- </span>
189
- )
190
- else
191
- %(
192
- <span
193
- class="badge #{kafka_state_badge(state)} time-title"
194
- title="#{Time.now + state_ch_in_seconds}"
195
- >
196
- #{state}
197
- </span>
198
- )
199
- end
200
- end
201
-
202
132
  # @param lag [Integer] lag
203
133
  # @return [String] lag if correct or `N/A` with labeled explanation
204
134
  # @see #offset_with_label