karafka-web 0.10.4 → 0.11.0.beta1
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +54 -176
- data/Gemfile +4 -0
- data/Gemfile.lock +87 -43
- data/LICENSE +6 -2
- data/bin/verify_kafka_warnings +35 -0
- data/bin/verify_topics_naming +35 -0
- data/config/locales/pro_errors.yml +1 -0
- data/docker-compose.yml +1 -1
- data/gulpfile.js +0 -2
- data/karafka-web.gemspec +2 -2
- data/lib/karafka/web/config.rb +80 -9
- data/lib/karafka/web/contracts/config.rb +44 -5
- data/lib/karafka/web/errors.rb +10 -0
- data/lib/karafka/web/management/actions/create_initial_states.rb +6 -6
- data/lib/karafka/web/management/actions/create_topics.rb +30 -64
- data/lib/karafka/web/management/actions/delete_topics.rb +5 -5
- data/lib/karafka/web/management/actions/enable.rb +5 -5
- data/lib/karafka/web/pro/commanding/commands/base.rb +37 -13
- data/lib/karafka/web/pro/commanding/commands/consumers/quiet.rb +33 -0
- data/lib/karafka/web/pro/commanding/commands/consumers/stop.rb +32 -0
- data/lib/karafka/web/pro/commanding/commands/consumers/trace.rb +37 -0
- data/lib/karafka/web/pro/commanding/commands/partitions/pause.rb +30 -0
- data/lib/karafka/web/pro/commanding/commands/partitions/resume.rb +30 -0
- data/lib/karafka/web/pro/commanding/commands/partitions/seek.rb +30 -0
- data/lib/karafka/web/pro/commanding/config.rb +6 -10
- data/lib/karafka/web/pro/commanding/contracts/config.rb +2 -10
- data/lib/karafka/web/pro/commanding/dispatcher.rb +45 -24
- data/lib/karafka/web/pro/commanding/handlers/partitions/commands/base.rb +67 -0
- data/lib/karafka/web/pro/commanding/handlers/partitions/commands/pause.rb +44 -0
- data/lib/karafka/web/pro/commanding/handlers/partitions/commands/resume.rb +29 -0
- data/lib/karafka/web/pro/commanding/handlers/partitions/commands/seek.rb +86 -0
- data/lib/karafka/web/pro/commanding/handlers/partitions/executor.rb +56 -0
- data/lib/karafka/web/pro/commanding/handlers/partitions/listener.rb +55 -0
- data/lib/karafka/web/pro/commanding/handlers/partitions/tracker.rb +62 -0
- data/lib/karafka/web/pro/commanding/listener.rb +4 -12
- data/lib/karafka/web/pro/commanding/manager.rb +36 -24
- data/lib/karafka/web/pro/commanding/matcher.rb +7 -17
- data/lib/karafka/web/pro/commanding/request.rb +39 -0
- data/lib/karafka/web/pro/commanding.rb +2 -10
- data/lib/karafka/web/pro/loader.rb +13 -10
- data/lib/karafka/web/pro/ui/app.rb +31 -390
- data/lib/karafka/web/pro/ui/controllers/base_controller.rb +8 -10
- data/lib/karafka/web/pro/ui/controllers/cluster_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/controllers/consumers/base_controller.rb +21 -0
- data/lib/karafka/web/pro/ui/controllers/consumers/commanding_controller.rb +148 -0
- data/lib/karafka/web/pro/ui/controllers/consumers/commands_controller.rb +96 -0
- data/lib/karafka/web/pro/ui/controllers/consumers/consumers_controller.rb +101 -0
- data/lib/karafka/web/pro/ui/controllers/consumers/controls_controller.rb +36 -0
- data/lib/karafka/web/pro/ui/controllers/consumers/jobs_controller.rb +57 -0
- data/lib/karafka/web/pro/ui/controllers/consumers/partitions/base_controller.rb +86 -0
- data/lib/karafka/web/pro/ui/controllers/consumers/partitions/offsets_controller.rb +75 -0
- data/lib/karafka/web/pro/ui/controllers/consumers/partitions/pauses_controller.rb +110 -0
- data/lib/karafka/web/pro/ui/controllers/dashboard_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/controllers/dlq_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/controllers/errors_controller.rb +3 -11
- data/lib/karafka/web/pro/ui/controllers/explorer/base_controller.rb +21 -0
- data/lib/karafka/web/pro/ui/controllers/explorer/explorer_controller.rb +215 -0
- data/lib/karafka/web/pro/ui/controllers/explorer/messages_controller.rb +145 -0
- data/lib/karafka/web/pro/ui/controllers/explorer/search_controller.rb +68 -0
- data/lib/karafka/web/pro/ui/controllers/health_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/controllers/jobs_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/controllers/recurring_tasks_controller.rb +12 -13
- data/lib/karafka/web/pro/ui/controllers/routing_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/controllers/scheduled_messages/base_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/controllers/scheduled_messages/explorer_controller.rb +8 -16
- data/lib/karafka/web/pro/ui/controllers/scheduled_messages/messages_controller.rb +9 -15
- data/lib/karafka/web/pro/ui/controllers/scheduled_messages/schedules_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/controllers/status_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/controllers/support_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/controllers/topics/base_controller.rb +21 -0
- data/lib/karafka/web/pro/ui/controllers/topics/configs_controller.rb +86 -0
- data/lib/karafka/web/pro/ui/controllers/topics/distributions_controller.rb +91 -0
- data/lib/karafka/web/pro/ui/controllers/topics/offsets_controller.rb +55 -0
- data/lib/karafka/web/pro/ui/controllers/topics/replications_controller.rb +37 -0
- data/lib/karafka/web/pro/ui/controllers/topics/topics_controller.rb +101 -0
- data/lib/karafka/web/pro/ui/controllers/ux_controller.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/branding/config.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/branding/contracts/config.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/branding.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/features.rb +53 -0
- data/lib/karafka/web/pro/ui/lib/patterns_detector.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/policies/config.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/policies/contracts/config.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/policies/messages.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/policies/requests.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/policies.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/safe_runner.rb +5 -0
- data/lib/karafka/web/pro/ui/lib/search/config.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/search/contracts/config.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/search/contracts/form.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/search/matchers/base.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/search/matchers/raw_header_includes.rb +10 -11
- data/lib/karafka/web/pro/ui/lib/search/matchers/raw_key_includes.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/search/matchers/raw_payload_includes.rb +23 -11
- data/lib/karafka/web/pro/ui/lib/search/normalizer.rb +2 -10
- data/lib/karafka/web/pro/ui/lib/search/runner.rb +3 -11
- data/lib/karafka/web/pro/ui/lib/search.rb +2 -10
- data/lib/karafka/web/pro/ui/routes/base.rb +19 -0
- data/lib/karafka/web/pro/ui/routes/cluster.rb +37 -0
- data/lib/karafka/web/pro/ui/routes/consumers.rb +145 -0
- data/lib/karafka/web/pro/ui/routes/dashboard.rb +25 -0
- data/lib/karafka/web/pro/ui/routes/dlq.rb +24 -0
- data/lib/karafka/web/pro/ui/routes/errors.rb +39 -0
- data/lib/karafka/web/pro/ui/routes/explorer.rb +118 -0
- data/lib/karafka/web/pro/ui/routes/health.rb +47 -0
- data/lib/karafka/web/pro/ui/routes/jobs.rb +33 -0
- data/lib/karafka/web/pro/ui/routes/recurring_tasks.rb +59 -0
- data/lib/karafka/web/pro/ui/routes/routing.rb +31 -0
- data/lib/karafka/web/pro/ui/routes/scheduled_messages.rb +75 -0
- data/lib/karafka/web/pro/ui/routes/status.rb +24 -0
- data/lib/karafka/web/pro/ui/routes/support.rb +24 -0
- data/lib/karafka/web/pro/ui/routes/topics.rb +90 -0
- data/lib/karafka/web/pro/ui/routes/ux.rb +24 -0
- data/lib/karafka/web/pro/ui/views/cluster/_breadcrumbs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/cluster/_broker.erb +3 -0
- data/lib/karafka/web/pro/ui/views/cluster/_config.erb +3 -0
- data/lib/karafka/web/pro/ui/views/cluster/_tabs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/cluster/index.erb +4 -1
- data/lib/karafka/web/pro/ui/views/cluster/show.erb +3 -0
- data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_backtrace.erb +3 -0
- data/lib/karafka/web/pro/ui/views/consumers/commands/_breadcrumbs.erb +24 -0
- data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_command.erb +22 -6
- data/lib/karafka/web/pro/ui/views/consumers/commands/_command_details.erb +4 -0
- data/lib/karafka/web/pro/ui/views/consumers/commands/_empty.erb +6 -0
- data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_incompatible_schema.erb +3 -0
- data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_metadata.erb +4 -1
- data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/_table.erb +5 -2
- data/lib/karafka/web/pro/ui/views/{commands → consumers/commands}/index.erb +7 -4
- data/lib/karafka/web/pro/ui/views/consumers/commands/show.erb +32 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumers/_breadcrumbs.erb +46 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumers/_consumer.erb +59 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumers/_consumer_performance.erb +71 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumers/_tabs.erb +38 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_commands.erb +80 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_consumer_group.erb +11 -0
- data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_metrics.erb +3 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_no_subscriptions.erb +10 -0
- data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_partition.erb +16 -0
- data/lib/karafka/web/pro/ui/views/consumers/consumers/consumer/_partition_edit_options.erb +33 -0
- data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_stopped.erb +3 -0
- data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_subscription_group.erb +7 -3
- data/lib/karafka/web/pro/ui/views/consumers/{consumer → consumers/consumer}/_tabs.erb +7 -4
- data/lib/karafka/web/pro/ui/views/consumers/consumers/details.erb +15 -0
- data/lib/karafka/web/pro/ui/views/consumers/{index.erb → consumers/index.erb} +6 -3
- data/lib/karafka/web/pro/ui/views/consumers/{performance.erb → consumers/performance.erb} +6 -3
- data/lib/karafka/web/pro/ui/views/consumers/consumers/subscriptions.erb +24 -0
- data/lib/karafka/web/pro/ui/views/consumers/controls/_breadcrumbs.erb +16 -0
- data/lib/karafka/web/pro/ui/views/consumers/controls/_controls.erb +107 -0
- data/lib/karafka/web/pro/ui/views/consumers/{controls.erb → controls/index.erb} +8 -5
- data/lib/karafka/web/pro/ui/views/consumers/jobs/_breadcrumbs.erb +36 -0
- data/lib/karafka/web/pro/ui/views/consumers/{consumer → jobs}/_job.erb +3 -0
- data/lib/karafka/web/pro/ui/views/consumers/{consumer → jobs}/_no_jobs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/consumers/{pending_jobs.erb → jobs/pending.erb} +7 -8
- data/lib/karafka/web/pro/ui/views/consumers/{running_jobs.erb → jobs/running.erb} +7 -8
- data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_basics.erb +77 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_breadcrumbs.erb +58 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_form.erb +109 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_not_running_error.erb +16 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/_running_warning.erb +15 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/offsets/edit.erb +12 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_active_not_editable.erb +22 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_adjusting_warning.erb +27 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_breadcrumbs.erb +60 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_edit_form.erb +59 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_lrj_not_manageable.erb +24 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_new_form.erb +78 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/_not_running.erb +16 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/edit.erb +20 -0
- data/lib/karafka/web/pro/ui/views/consumers/partitions/pauses/new.erb +16 -0
- data/lib/karafka/web/pro/ui/views/dashboard/index.erb +4 -1
- data/lib/karafka/web/pro/ui/views/dlq/_breadcrumbs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/dlq/_no_topics.erb +3 -0
- data/lib/karafka/web/pro/ui/views/dlq/_topic.erb +4 -1
- data/lib/karafka/web/pro/ui/views/dlq/index.erb +3 -0
- data/lib/karafka/web/pro/ui/views/errors/_breadcrumbs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/errors/_error.erb +3 -0
- data/lib/karafka/web/pro/ui/views/errors/_partition_option.erb +3 -0
- data/lib/karafka/web/pro/ui/views/errors/_selector.erb +3 -0
- data/lib/karafka/web/pro/ui/views/errors/_table.erb +4 -1
- data/lib/karafka/web/pro/ui/views/errors/index.erb +6 -3
- data/lib/karafka/web/pro/ui/views/errors/partition.erb +5 -2
- data/lib/karafka/web/pro/ui/views/errors/show.erb +3 -0
- data/lib/karafka/web/pro/ui/views/explorer/{_breadcrumbs.erb → explorer/_breadcrumbs.erb} +7 -4
- data/lib/karafka/web/pro/ui/views/explorer/{_failed_deserialization.erb → explorer/_failed_deserialization.erb} +3 -0
- data/lib/karafka/web/pro/ui/views/explorer/{_filtered.erb → explorer/_filtered.erb} +3 -0
- data/lib/karafka/web/pro/ui/views/explorer/{_message.erb → explorer/_message.erb} +4 -1
- data/lib/karafka/web/pro/ui/views/explorer/explorer/_no_topics.erb +4 -0
- data/lib/karafka/web/pro/ui/views/explorer/{_partition_option.erb → explorer/_partition_option.erb} +4 -1
- data/lib/karafka/web/pro/ui/views/explorer/{_selector.erb → explorer/_selector.erb} +4 -1
- data/lib/karafka/web/pro/ui/views/explorer/explorer/_topic.erb +13 -0
- data/lib/karafka/web/pro/ui/views/explorer/explorer/index.erb +17 -0
- data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_metadata.erb +10 -7
- data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_payload.erb +6 -3
- data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_resources_utilization.erb +7 -4
- data/lib/karafka/web/pro/ui/views/explorer/{message → explorer/message}/_too_big_to_be_displayed.erb +3 -0
- data/lib/karafka/web/pro/ui/views/explorer/{messages → explorer/messages}/_detail.erb +3 -0
- data/lib/karafka/web/pro/ui/views/explorer/explorer/messages/_headers.erb +51 -0
- data/lib/karafka/web/pro/ui/views/explorer/{messages → explorer/messages}/_key.erb +3 -0
- data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_cleaned.erb +6 -0
- data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_empty.erb +6 -0
- data/lib/karafka/web/pro/ui/views/explorer/{partition → explorer/partition}/_messages.erb +4 -1
- data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_time_selector.erb +16 -0
- data/lib/karafka/web/pro/ui/views/explorer/explorer/partition/_timestamp_selector.erb +33 -0
- data/lib/karafka/web/pro/ui/views/explorer/{partition.erb → explorer/partition.erb} +24 -17
- data/lib/karafka/web/pro/ui/views/explorer/{show.erb → explorer/show.erb} +17 -19
- data/lib/karafka/web/pro/ui/views/explorer/{topic → explorer/topic}/_actions.erb +5 -2
- data/lib/karafka/web/pro/ui/views/explorer/explorer/topic/_empty.erb +6 -0
- data/lib/karafka/web/pro/ui/views/explorer/{topic → explorer/topic}/_limited.erb +3 -0
- data/lib/karafka/web/pro/ui/views/explorer/{topic.erb → explorer/topic.erb} +7 -4
- data/lib/karafka/web/pro/ui/views/explorer/messages/_breadcrumbs.erb +32 -0
- data/lib/karafka/web/pro/ui/views/explorer/messages/forward.erb +143 -0
- data/lib/karafka/web/pro/ui/views/explorer/search/_breadcrumbs.erb +4 -0
- data/lib/karafka/web/pro/ui/views/explorer/search/_fix_errors.erb +6 -0
- data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_metadata.erb +3 -0
- data/lib/karafka/web/pro/ui/views/explorer/search/_no_results.erb +6 -0
- data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_no_search_criteria.erb +3 -0
- data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_search_criteria.erb +3 -0
- data/lib/karafka/web/pro/ui/views/{search → explorer/search}/_search_modal.erb +5 -2
- data/lib/karafka/web/pro/ui/views/explorer/search/_timeout.erb +6 -0
- data/lib/karafka/web/pro/ui/views/explorer/search/index.erb +32 -0
- data/lib/karafka/web/pro/ui/views/health/_breadcrumbs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/health/_no_data.erb +3 -0
- data/lib/karafka/web/pro/ui/views/health/_partition.erb +16 -1
- data/lib/karafka/web/pro/ui/views/health/_partition_lags.erb +3 -0
- data/lib/karafka/web/pro/ui/views/health/_partition_offset.erb +3 -0
- data/lib/karafka/web/pro/ui/views/health/_partition_times.erb +3 -0
- data/lib/karafka/web/pro/ui/views/health/_table_metadata.erb +4 -1
- data/lib/karafka/web/pro/ui/views/health/_tabs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/health/changes.erb +4 -1
- data/lib/karafka/web/pro/ui/views/health/cluster_lags.erb +3 -0
- data/lib/karafka/web/pro/ui/views/health/lags.erb +5 -2
- data/lib/karafka/web/pro/ui/views/health/offsets.erb +4 -1
- data/lib/karafka/web/pro/ui/views/health/overview.erb +8 -3
- data/lib/karafka/web/pro/ui/views/jobs/_job.erb +50 -38
- data/lib/karafka/web/pro/ui/views/jobs/_no_jobs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/jobs/pending.erb +4 -1
- data/lib/karafka/web/pro/ui/views/jobs/running.erb +4 -1
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_actions.erb +3 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_batch_actions.erb +3 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_breadcrumbs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_log.erb +3 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_not_active.erb +3 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_tabs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/_task.erb +3 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/logs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/recurring_tasks/schedule.erb +3 -0
- data/lib/karafka/web/pro/ui/views/routing/_consumer_group.erb +3 -0
- data/lib/karafka/web/pro/ui/views/routing/_detail.erb +3 -0
- data/lib/karafka/web/pro/ui/views/routing/_topic.erb +3 -0
- data/lib/karafka/web/pro/ui/views/routing/index.erb +3 -0
- data/lib/karafka/web/pro/ui/views/routing/show.erb +3 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_breadcrumbs.erb +6 -3
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_key.erb +3 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_message.erb +4 -1
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/_messages.erb +3 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/partition.erb +23 -16
- data/lib/karafka/web/pro/ui/views/scheduled_messages/explorer/topic.erb +6 -3
- data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/_breadcrumbs.erb +3 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/_no_groups.erb +3 -0
- data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/index.erb +4 -1
- data/lib/karafka/web/pro/ui/views/scheduled_messages/schedules/show.erb +3 -0
- data/lib/karafka/web/pro/ui/views/shared/_navigation.erb +25 -17
- data/lib/karafka/web/pro/ui/views/shared/_rdkafka_form_error_alert_box.erb +16 -0
- data/lib/karafka/web/pro/ui/views/shared/branding/_label.erb +3 -0
- data/lib/karafka/web/pro/ui/views/shared/branding/_notice.erb +3 -0
- data/lib/karafka/web/pro/ui/views/topics/configs/_breadcrumbs.erb +34 -0
- data/lib/karafka/web/pro/ui/views/topics/configs/_config.erb +26 -0
- data/lib/karafka/web/pro/ui/views/topics/configs/_delete_button.erb +13 -0
- data/lib/karafka/web/pro/ui/views/topics/configs/_edit_form.erb +50 -0
- data/lib/karafka/web/pro/ui/views/topics/configs/_edit_plan.erb +16 -0
- data/lib/karafka/web/pro/ui/views/topics/configs/_edit_warning.erb +12 -0
- data/lib/karafka/web/pro/ui/views/topics/configs/edit.erb +16 -0
- data/lib/karafka/web/pro/ui/views/topics/{config.erb → configs/index.erb} +9 -3
- data/lib/karafka/web/pro/ui/views/topics/distributions/_add_partitions_button.erb +13 -0
- data/lib/karafka/web/pro/ui/views/topics/{distribution → distributions}/_badges.erb +3 -0
- data/lib/karafka/web/pro/ui/views/topics/distributions/_breadcrumbs.erb +28 -0
- data/lib/karafka/web/pro/ui/views/topics/{distribution → distributions}/_chart.erb +3 -0
- data/lib/karafka/web/pro/ui/views/topics/distributions/_edit_form.erb +47 -0
- data/lib/karafka/web/pro/ui/views/topics/distributions/_edit_hints.erb +15 -0
- data/lib/karafka/web/pro/ui/views/topics/distributions/_edit_warnings.erb +14 -0
- data/lib/karafka/web/pro/ui/views/topics/distributions/_empty_partitions.erb +4 -0
- data/lib/karafka/web/pro/ui/views/topics/{distribution → distributions}/_limited.erb +3 -0
- data/lib/karafka/web/pro/ui/views/topics/distributions/_partition.erb +13 -0
- data/lib/karafka/web/pro/ui/views/topics/distributions/edit.erb +16 -0
- data/lib/karafka/web/pro/ui/views/topics/{distribution.erb → distributions/show.erb} +11 -7
- data/lib/karafka/web/pro/ui/views/topics/offsets/_breadcrumbs.erb +20 -0
- data/lib/karafka/web/pro/ui/views/topics/offsets/_partition.erb +13 -0
- data/lib/karafka/web/pro/ui/views/topics/{offsets.erb → offsets/show.erb} +6 -3
- data/lib/karafka/web/pro/ui/views/topics/replications/_breadcrumbs.erb +20 -0
- data/lib/karafka/web/pro/ui/views/topics/{_partition.erb → replications/_partition.erb} +4 -1
- data/lib/karafka/web/pro/ui/views/topics/{replication.erb → replications/show.erb} +6 -3
- data/lib/karafka/web/pro/ui/views/topics/topics/_breadcrumbs.erb +32 -0
- data/lib/karafka/web/pro/ui/views/topics/topics/_create_button.erb +13 -0
- data/lib/karafka/web/pro/ui/views/topics/topics/_create_hints.erb +15 -0
- data/lib/karafka/web/pro/ui/views/topics/topics/_delete_form.erb +36 -0
- data/lib/karafka/web/pro/ui/views/topics/topics/_delete_hints.erb +15 -0
- data/lib/karafka/web/pro/ui/views/topics/topics/_delete_warning.erb +13 -0
- data/lib/karafka/web/pro/ui/views/topics/topics/_new_form.erb +80 -0
- data/lib/karafka/web/pro/ui/views/topics/{_tabs.erb → topics/_tabs.erb} +7 -4
- data/lib/karafka/web/pro/ui/views/topics/topics/_topic.erb +12 -0
- data/lib/karafka/web/pro/ui/views/topics/topics/edit.erb +10 -0
- data/lib/karafka/web/pro/ui/views/topics/topics/index.erb +19 -0
- data/lib/karafka/web/pro/ui/views/topics/topics/new.erb +12 -0
- data/lib/karafka/web/processing/consumers/metrics.rb +1 -1
- data/lib/karafka/web/processing/consumers/state.rb +1 -1
- data/lib/karafka/web/processing/publisher.rb +4 -4
- data/lib/karafka/web/tracking/consumers/contracts/partition.rb +1 -0
- data/lib/karafka/web/tracking/consumers/listeners/pausing.rb +2 -2
- data/lib/karafka/web/tracking/consumers/listeners/transactions.rb +44 -0
- data/lib/karafka/web/tracking/consumers/reporter.rb +2 -2
- data/lib/karafka/web/tracking/consumers/sampler.rb +81 -14
- data/lib/karafka/web/tracking/helpers/sysconf.rb +33 -0
- data/lib/karafka/web/tracking/producers/reporter.rb +1 -1
- data/lib/karafka/web/ui/app.rb +19 -112
- data/lib/karafka/web/ui/base.rb +63 -4
- data/lib/karafka/web/ui/controllers/base_controller.rb +43 -1
- data/lib/karafka/web/ui/controllers/cluster_controller.rb +5 -2
- data/lib/karafka/web/ui/controllers/errors_controller.rb +1 -1
- data/lib/karafka/web/ui/controllers/requests/execution_wrapper.rb +52 -0
- data/lib/karafka/web/ui/controllers/requests/hookable.rb +99 -0
- data/lib/karafka/web/ui/controllers/requests/params.rb +39 -1
- data/lib/karafka/web/ui/controllers/responses/redirect.rb +0 -5
- data/lib/karafka/web/ui/controllers/status_controller.rb +3 -0
- data/lib/karafka/web/ui/helpers/application_helper.rb +10 -1
- data/lib/karafka/web/ui/helpers/paths_helper.rb +54 -10
- data/lib/karafka/web/ui/lib/admin.rb +1 -1
- data/lib/karafka/web/ui/lib/cache.rb +135 -0
- data/lib/karafka/web/ui/models/broker.rb +1 -2
- data/lib/karafka/web/ui/models/cluster_info.rb +15 -21
- data/lib/karafka/web/ui/models/consumers_metrics.rb +1 -1
- data/lib/karafka/web/ui/models/consumers_state.rb +1 -1
- data/lib/karafka/web/ui/models/counters.rb +1 -1
- data/lib/karafka/web/ui/models/health.rb +9 -7
- data/lib/karafka/web/ui/models/process.rb +14 -0
- data/lib/karafka/web/ui/models/processes.rb +2 -2
- data/lib/karafka/web/ui/models/recurring_tasks/schedule.rb +1 -1
- data/lib/karafka/web/ui/models/status.rb +27 -8
- data/lib/karafka/web/ui/models/topic.rb +1 -2
- data/lib/karafka/web/ui/public/javascripts/application.js +8 -98
- data/lib/karafka/web/ui/public/javascripts/application.min.js +12 -4
- data/lib/karafka/web/ui/public/javascripts/application.min.js.br +0 -0
- data/lib/karafka/web/ui/public/javascripts/application.min.js.gz +0 -0
- data/lib/karafka/web/ui/public/javascripts/components/action_confirmation_manager.js +30 -0
- data/lib/karafka/web/ui/public/javascripts/components/alerts.js +39 -0
- data/lib/karafka/web/ui/public/javascripts/components/button_lock_manager.js +50 -0
- data/lib/karafka/web/ui/public/javascripts/components/live_poll.js +71 -19
- data/lib/karafka/web/ui/public/javascripts/components/message_republish_manager.js +50 -0
- data/lib/karafka/web/ui/public/javascripts/components/page_title_tracker.js +21 -0
- data/lib/karafka/web/ui/public/javascripts/components/partition_redirect_manager.js +21 -0
- data/lib/karafka/web/ui/public/javascripts/components/time_ago_manager.js +25 -0
- data/lib/karafka/web/ui/public/javascripts/components/timestamp_selector.js +30 -0
- data/lib/karafka/web/ui/public/javascripts/libs/datepicker.js +2 -2
- data/lib/karafka/web/ui/public/stylesheets/application.css +30 -0
- data/lib/karafka/web/ui/public/stylesheets/application.min.css +5122 -13
- 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/public/stylesheets/libs/tailwind.css +512 -213
- data/lib/karafka/web/ui/routes/assets.rb +53 -0
- data/lib/karafka/web/ui/routes/base.rb +36 -0
- data/lib/karafka/web/ui/routes/cluster.rb +28 -0
- data/lib/karafka/web/ui/routes/consumers.rb +35 -0
- data/lib/karafka/web/ui/routes/dashboard.rb +20 -0
- data/lib/karafka/web/ui/routes/errors.rb +26 -0
- data/lib/karafka/web/ui/routes/jobs.rb +28 -0
- data/lib/karafka/web/ui/routes/pro_only.rb +27 -0
- data/lib/karafka/web/ui/routes/routing.rb +26 -0
- data/lib/karafka/web/ui/routes/status.rb +19 -0
- data/lib/karafka/web/ui/routes/support.rb +19 -0
- data/lib/karafka/web/ui/routes/ux.rb +19 -0
- data/lib/karafka/web/ui/views/cluster/_partition.erb +2 -2
- data/lib/karafka/web/ui/views/cluster/brokers.erb +1 -1
- data/lib/karafka/web/ui/views/consumers/_breadcrumbs.erb +7 -1
- data/lib/karafka/web/ui/views/consumers/_consumer.erb +39 -30
- data/lib/karafka/web/ui/views/consumers/_incompatible.erb +13 -0
- data/lib/karafka/web/ui/views/consumers/_no_consumers.erb +2 -2
- data/lib/karafka/web/ui/views/consumers/_tabs.erb +4 -4
- data/lib/karafka/web/ui/views/consumers/index.erb +1 -1
- data/lib/karafka/web/ui/views/dashboard/_feature_pro.erb +1 -1
- data/lib/karafka/web/ui/views/dashboard/_not_enough_data.erb +2 -2
- data/lib/karafka/web/ui/views/dashboard/_ranges_selector.erb +1 -1
- data/lib/karafka/web/ui/views/dashboard/index.erb +6 -49
- data/lib/karafka/web/ui/views/errors/_detail.erb +3 -3
- data/lib/karafka/web/ui/views/errors/index.erb +1 -1
- data/lib/karafka/web/ui/views/jobs/_job.erb +38 -29
- data/lib/karafka/web/ui/views/jobs/pending.erb +1 -1
- data/lib/karafka/web/ui/views/jobs/running.erb +1 -1
- data/lib/karafka/web/ui/views/layout.erb +7 -5
- data/lib/karafka/web/ui/views/shared/_become_pro.erb +1 -1
- data/lib/karafka/web/ui/views/shared/_brand.erb +1 -1
- data/lib/karafka/web/ui/views/shared/_breadcrumbs.erb +1 -1
- data/lib/karafka/web/ui/views/shared/_content.erb +1 -1
- data/lib/karafka/web/ui/views/shared/_controls.erb +10 -3
- data/lib/karafka/web/ui/views/shared/_custom_nav.erb +9 -0
- data/lib/karafka/web/ui/views/shared/_flashes.erb +3 -5
- data/lib/karafka/web/ui/views/shared/_header.erb +25 -2
- data/lib/karafka/web/ui/views/shared/_navigation.erb +17 -15
- data/lib/karafka/web/ui/views/shared/alerts/_error.erb +8 -0
- data/lib/karafka/web/ui/views/shared/alerts/_info.erb +8 -0
- data/lib/karafka/web/ui/views/shared/alerts/_primary.erb +8 -0
- data/lib/karafka/web/ui/views/shared/alerts/_secondary.erb +8 -0
- data/lib/karafka/web/ui/views/shared/alerts/_success.erb +8 -0
- data/lib/karafka/web/ui/views/shared/alerts/_warning.erb +8 -0
- data/lib/karafka/web/ui/views/shared/exceptions/incompatible_schema.erb +34 -0
- data/lib/karafka/web/ui/views/shared/exceptions/not_allowed.erb +4 -0
- data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +5 -1
- data/lib/karafka/web/ui/views/shared/exceptions/pro_only.erb +4 -0
- data/lib/karafka/web/ui/views/shared/icons/_arrow_left.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_arrow_up_tray.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_clock.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_pencil.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_pencil_square.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_play_pause.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_plus.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_trash.erb +3 -0
- data/lib/karafka/web/ui/views/status/failures/_live_reporting.erb +1 -1
- data/lib/karafka/web/ui/views/status/failures/_partitions.erb +3 -3
- data/lib/karafka/web/ui/views/status/failures/_state_calculation.erb +2 -2
- data/lib/karafka/web/ui/views/status/info/_components.erb +6 -6
- data/lib/karafka/web/ui/views/status/show.erb +15 -0
- data/lib/karafka/web/ui/views/status/warnings/_consumers_schemas.erb +31 -0
- data/lib/karafka/web/ui/views/ux/_icons.erb +1 -1
- data/lib/karafka/web/ui/views/ux/_status_rows.erb +6 -0
- data/lib/karafka/web/version.rb +1 -1
- data/lib/karafka/web.rb +3 -0
- data/package-lock.json +776 -1208
- data/package.json +3 -4
- data/postcss.config.js +1 -2
- data/renovate.json +13 -1
- data/tailwind.config.js +0 -4
- data.tar.gz.sig +0 -0
- metadata +232 -108
- metadata.gz.sig +0 -0
- data/lib/karafka/web/pro/commanding/commands/quiet.rb +0 -34
- data/lib/karafka/web/pro/commanding/commands/stop.rb +0 -34
- data/lib/karafka/web/pro/commanding/commands/trace.rb +0 -41
- data/lib/karafka/web/pro/ui/controllers/commanding_controller.rb +0 -118
- data/lib/karafka/web/pro/ui/controllers/commands_controller.rb +0 -96
- data/lib/karafka/web/pro/ui/controllers/consumers_controller.rb +0 -138
- data/lib/karafka/web/pro/ui/controllers/explorer_controller.rb +0 -220
- data/lib/karafka/web/pro/ui/controllers/messages_controller.rb +0 -107
- data/lib/karafka/web/pro/ui/controllers/search_controller.rb +0 -73
- data/lib/karafka/web/pro/ui/controllers/topics_controller.rb +0 -130
- data/lib/karafka/web/pro/ui/views/commands/_breadcrumbs.erb +0 -21
- data/lib/karafka/web/pro/ui/views/commands/_command_details.erb +0 -1
- data/lib/karafka/web/pro/ui/views/commands/_empty.erb +0 -3
- data/lib/karafka/web/pro/ui/views/commands/show.erb +0 -33
- data/lib/karafka/web/pro/ui/views/consumers/_breadcrumbs.erb +0 -55
- data/lib/karafka/web/pro/ui/views/consumers/_consumer.erb +0 -47
- data/lib/karafka/web/pro/ui/views/consumers/_consumer_controls.erb +0 -95
- data/lib/karafka/web/pro/ui/views/consumers/_consumer_performance.erb +0 -59
- data/lib/karafka/web/pro/ui/views/consumers/_tabs.erb +0 -33
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_commands.erb +0 -72
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_consumer_group.erb +0 -8
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_no_subscriptions.erb +0 -7
- data/lib/karafka/web/pro/ui/views/consumers/details.erb +0 -13
- data/lib/karafka/web/pro/ui/views/consumers/subscriptions.erb +0 -25
- data/lib/karafka/web/pro/ui/views/explorer/_no_topics.erb +0 -1
- data/lib/karafka/web/pro/ui/views/explorer/_topic.erb +0 -10
- data/lib/karafka/web/pro/ui/views/explorer/index.erb +0 -14
- data/lib/karafka/web/pro/ui/views/explorer/messages/_headers.erb +0 -33
- data/lib/karafka/web/pro/ui/views/explorer/partition/_cleaned.erb +0 -3
- data/lib/karafka/web/pro/ui/views/explorer/partition/_empty.erb +0 -3
- data/lib/karafka/web/pro/ui/views/explorer/topic/_empty.erb +0 -3
- data/lib/karafka/web/pro/ui/views/search/_breadcrumbs.erb +0 -1
- data/lib/karafka/web/pro/ui/views/search/_fix_errors.erb +0 -3
- data/lib/karafka/web/pro/ui/views/search/_no_results.erb +0 -3
- data/lib/karafka/web/pro/ui/views/search/_timeout.erb +0 -3
- data/lib/karafka/web/pro/ui/views/search/index.erb +0 -29
- data/lib/karafka/web/pro/ui/views/topics/_breadcrumbs.erb +0 -45
- data/lib/karafka/web/pro/ui/views/topics/_partition_offsets.erb +0 -10
- data/lib/karafka/web/pro/ui/views/topics/_topic.erb +0 -9
- data/lib/karafka/web/pro/ui/views/topics/distribution/_empty_partitions.erb +0 -1
- data/lib/karafka/web/pro/ui/views/topics/distribution/_partition.erb +0 -10
- data/lib/karafka/web/pro/ui/views/topics/index.erb +0 -14
- data/lib/karafka/web/ui/lib/ttl_cache.rb +0 -82
@@ -0,0 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Web
|
5
|
+
module Ui
|
6
|
+
module Lib
|
7
|
+
# Thread-safe in-memory cache with metadata tracking.
|
8
|
+
#
|
9
|
+
# This cache supports storing computed values, tracking the last update time,
|
10
|
+
# and computing a hash of the contents for change detection.
|
11
|
+
# It's designed for ephemeral, per-instance caching in Karafka Web controllers or libs.
|
12
|
+
#
|
13
|
+
# The cache ensures safe concurrent access via a mutex and provides utilities
|
14
|
+
# for cache invalidation based on external session state (timestamp + hash).
|
15
|
+
#
|
16
|
+
# @note All cache operations are mutex-synchronized for thread safety.
|
17
|
+
#
|
18
|
+
# @note We do not have granular level caching because our Web UI cache is fairly simple
|
19
|
+
# and we do not want to overcomplicate things.
|
20
|
+
class Cache
|
21
|
+
# Initializes an empty cache instance
|
22
|
+
# @param ttl_ms [Integer] time to live of the whole cache. After this time cache will be
|
23
|
+
# cleaned whether or not it is expired.
|
24
|
+
def initialize(ttl_ms)
|
25
|
+
@ttl_ms = ttl_ms
|
26
|
+
@values = {}
|
27
|
+
@timestamp = nil
|
28
|
+
@hash = nil
|
29
|
+
@mutex = Mutex.new
|
30
|
+
end
|
31
|
+
|
32
|
+
# Fetches or computes and stores a value under the given key.
|
33
|
+
#
|
34
|
+
# If the key already exists, returns the cached value.
|
35
|
+
# Otherwise, computes it via the provided block, stores it,
|
36
|
+
# and updates metadata (timestamp + hash).
|
37
|
+
#
|
38
|
+
# @param key [Object] key to retrieve
|
39
|
+
# @yield block to compute the value if key is not present
|
40
|
+
# @return [Object] cached or computed value
|
41
|
+
def fetch(key)
|
42
|
+
@mutex.synchronize do
|
43
|
+
return @values[key] if @values.key?(key)
|
44
|
+
|
45
|
+
@values[key] = yield
|
46
|
+
@hash = Digest::SHA256.hexdigest(
|
47
|
+
@values.sort.to_h.to_json
|
48
|
+
)
|
49
|
+
@timestamp = Time.now.to_f
|
50
|
+
@values[key]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Clears the cache and resets metadata (timestamp and hash).
|
55
|
+
#
|
56
|
+
# If the mutex is already owned by the current thread, clears immediately.
|
57
|
+
# Otherwise, synchronizes first.
|
58
|
+
#
|
59
|
+
# @return [void]
|
60
|
+
def clear
|
61
|
+
cleaning = lambda do
|
62
|
+
@values.clear
|
63
|
+
@timestamp = nil
|
64
|
+
@hash = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
return cleaning.call if @mutex.owned?
|
68
|
+
|
69
|
+
@mutex.synchronize do
|
70
|
+
cleaning.call
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Checks whether any values have been cached yet
|
75
|
+
#
|
76
|
+
# @return [Boolean] true if the cache has been written to
|
77
|
+
def exist?
|
78
|
+
!timestamp.nil?
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns the last update timestamp of the cache
|
82
|
+
#
|
83
|
+
# @return [Integer, nil] Unix timestamp or nil if never set
|
84
|
+
def timestamp
|
85
|
+
@mutex.synchronize { @timestamp }
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the hash representing the current cached data state
|
89
|
+
#
|
90
|
+
# @return [String, nil] SHA256 hex digest or nil if never set
|
91
|
+
def hash
|
92
|
+
@mutex.synchronize { @hash }
|
93
|
+
end
|
94
|
+
|
95
|
+
# Clears the cache if the provided session hash and timestamp differ
|
96
|
+
#
|
97
|
+
# This is used to invalidate the cache if the external session data indicates
|
98
|
+
# a newer or inconsistent state.
|
99
|
+
#
|
100
|
+
# @param session_hash [String, nil] hash from the session or remote side
|
101
|
+
# @param session_timestamp [Integer, nil] timestamp from the session
|
102
|
+
# @return [Boolean] true if the cache was cleared, false otherwise
|
103
|
+
def clear_if_needed(session_hash, session_timestamp)
|
104
|
+
@mutex.synchronize do
|
105
|
+
return unless should_refresh?(session_hash, session_timestamp)
|
106
|
+
|
107
|
+
clear
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
# Determines whether the cache should be refreshed based on session data
|
114
|
+
#
|
115
|
+
# @param session_hash [String, nil]
|
116
|
+
# @param session_timestamp [Integer, nil]
|
117
|
+
# @return [Boolean] true if cache should be refreshed
|
118
|
+
def should_refresh?(session_hash, session_timestamp)
|
119
|
+
return true if @hash.nil? || @timestamp.nil?
|
120
|
+
return true if session_hash.nil? || session_timestamp.nil?
|
121
|
+
|
122
|
+
now = (Time.now.to_f * 1_000).to_i
|
123
|
+
|
124
|
+
return true if now - (@timestamp * 1_000) > @ttl_ms
|
125
|
+
|
126
|
+
return false if @hash == session_hash
|
127
|
+
return false if @timestamp > session_timestamp
|
128
|
+
|
129
|
+
true
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -9,8 +9,7 @@ module Karafka
|
|
9
9
|
class << self
|
10
10
|
# @return [Array<Broker>] all brokers in the cluster
|
11
11
|
def all
|
12
|
-
|
13
|
-
ClusterInfo.fetch(cached: false).brokers.map do |broker|
|
12
|
+
ClusterInfo.fetch.brokers.map do |broker|
|
14
13
|
new(broker)
|
15
14
|
end
|
16
15
|
end
|
@@ -10,26 +10,18 @@ module Karafka
|
|
10
10
|
class << self
|
11
11
|
# Gets us all the cluster metadata info
|
12
12
|
#
|
13
|
-
# @param cached [Boolean] should we use cached data (true by default)
|
14
13
|
# @return [Rdkafka::Metadata] cluster metadata info
|
15
|
-
def fetch
|
16
|
-
|
17
|
-
|
18
|
-
cluster_info = cache.read(:cluster_info)
|
19
|
-
|
20
|
-
if cluster_info.nil? || !cached
|
21
|
-
cluster_info = cache.write(:cluster_info, Lib::Admin.cluster_info)
|
14
|
+
def fetch
|
15
|
+
Karafka::Web.config.ui.cache.fetch(:cluster_info) do
|
16
|
+
Lib::Admin.cluster_info
|
22
17
|
end
|
23
|
-
|
24
|
-
cluster_info
|
25
18
|
end
|
26
19
|
|
27
20
|
# Returns us all the info about available topics from the cluster
|
28
21
|
#
|
29
|
-
# @param cached [Boolean] should we use cached data (true by default)
|
30
22
|
# @return [Array<Ui::Models::Topic>] topics details
|
31
|
-
def topics
|
32
|
-
fetch
|
23
|
+
def topics
|
24
|
+
fetch
|
33
25
|
.topics
|
34
26
|
.map { |topic| Topic.new(topic) }
|
35
27
|
end
|
@@ -37,19 +29,21 @@ module Karafka
|
|
37
29
|
# Fetches us details about particular topic
|
38
30
|
#
|
39
31
|
# @param topic_name [String] name of the topic we are looking for
|
40
|
-
# @param cached [Boolean] should we use cached data (true by default)
|
41
32
|
# @return [Ui::Models::Topic] topic details
|
42
|
-
def topic(topic_name
|
43
|
-
|
44
|
-
.
|
45
|
-
.
|
33
|
+
def topic(topic_name)
|
34
|
+
Lib::Admin
|
35
|
+
.topic_info(topic_name)
|
36
|
+
.then { |topic| Topic.new(topic) }
|
37
|
+
rescue Rdkafka::RdkafkaError => e
|
38
|
+
raise e unless e.code == :unknown_topic_or_part
|
39
|
+
|
40
|
+
raise(Web::Errors::Ui::NotFoundError, topic_name)
|
46
41
|
end
|
47
42
|
|
48
43
|
# @param topic_name [String] name of the topic we are looking for
|
49
|
-
# @param cached [Boolean] should we use cached data (true by default)
|
50
44
|
# @return [Integer] number of partitions in a given topic
|
51
|
-
def partitions_count(topic_name
|
52
|
-
topic(topic_name
|
45
|
+
def partitions_count(topic_name)
|
46
|
+
topic(topic_name).partition_count
|
53
47
|
end
|
54
48
|
end
|
55
49
|
end
|
@@ -33,7 +33,7 @@ module Karafka
|
|
33
33
|
# @return [::Karafka::Messages::Message, nil] most recent state or nil if none
|
34
34
|
def fetch
|
35
35
|
Lib::Admin.read_topic(
|
36
|
-
Karafka::Web.config.topics.consumers.metrics,
|
36
|
+
Karafka::Web.config.topics.consumers.metrics.name,
|
37
37
|
0,
|
38
38
|
# We need to take last two and not the last because in case of a transactional
|
39
39
|
# producer, the last one will match the transaction commit message
|
@@ -42,7 +42,7 @@ module Karafka
|
|
42
42
|
# @return [::Karafka::Messages::Message, nil] most recent state or nil if none
|
43
43
|
def fetch
|
44
44
|
Lib::Admin.read_topic(
|
45
|
-
Karafka::Web.config.topics.consumers.states,
|
45
|
+
Karafka::Web.config.topics.consumers.states.name,
|
46
46
|
0,
|
47
47
|
# We need to take last two and not the last because in case of a transactional
|
48
48
|
# producer, the last one will match the transaction commit message
|
@@ -32,7 +32,7 @@ module Karafka
|
|
32
32
|
MAX_ERROR_PARTITIONS.times do |partition|
|
33
33
|
begin
|
34
34
|
offsets = Lib::Admin.read_watermark_offsets(
|
35
|
-
::Karafka::Web.config.topics.errors,
|
35
|
+
::Karafka::Web.config.topics.errors.name,
|
36
36
|
partition
|
37
37
|
)
|
38
38
|
# We estimate that way instead of using `#cluster_info` to get the partitions count
|
@@ -50,15 +50,17 @@ module Karafka
|
|
50
50
|
# @param state [Hash]
|
51
51
|
# @param stats [Hash] hash where we will store all the aggregated data
|
52
52
|
def fetch_topics_data(state, stats)
|
53
|
-
iterate_partitions(state) do |process, consumer_group, topic, partition|
|
54
|
-
|
53
|
+
iterate_partitions(state) do |process, consumer_group, subscription_group, topic, partition|
|
54
|
+
cg_id = consumer_group.id
|
55
|
+
sg_id = subscription_group.id
|
55
56
|
t_name = topic.name
|
56
57
|
pt_id = partition.id
|
57
58
|
|
58
|
-
stats[
|
59
|
-
stats[
|
60
|
-
stats[
|
61
|
-
stats[
|
59
|
+
stats[cg_id] ||= { topics: {} }
|
60
|
+
stats[cg_id][:topics][t_name] ||= {}
|
61
|
+
stats[cg_id][:topics][t_name][pt_id] = partition
|
62
|
+
stats[cg_id][:topics][t_name][pt_id][:process] = process
|
63
|
+
stats[cg_id][:topics][t_name][pt_id][:subscription_group_id] = sg_id
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
@@ -99,7 +101,7 @@ module Karafka
|
|
99
101
|
consumer_group.subscription_groups.each do |subscription_group|
|
100
102
|
subscription_group.topics.each do |topic|
|
101
103
|
topic.partitions.each do |partition|
|
102
|
-
yield(process, consumer_group, topic, partition)
|
104
|
+
yield(process, consumer_group, subscription_group, topic, partition)
|
103
105
|
end
|
104
106
|
end
|
105
107
|
end
|
@@ -74,6 +74,20 @@ module Karafka
|
|
74
74
|
.flat_map(&:partitions)
|
75
75
|
.count
|
76
76
|
end
|
77
|
+
|
78
|
+
# @return [Boolean] consumer process data is only compatible if the version of its schema
|
79
|
+
# matches the Web UI version of the schema. Some users have gradual deployment where
|
80
|
+
# they slowly rollout new versions of consumers and for this time, we want to indicate
|
81
|
+
# which instances have incompatible schema. This will allow us to show those processes
|
82
|
+
# to indicate they exist, so users are not confused with them missing, but will also
|
83
|
+
# block all capabilities until the full update of all components.
|
84
|
+
#
|
85
|
+
# @note We do not differentiate between reporting older or newer against Web UI Puma
|
86
|
+
# instance. Any incompatibility will cause reporting of incompatible. That's for the
|
87
|
+
# sake of simplicity as the long term goal for user is anyhow to align those.
|
88
|
+
def schema_compatible?
|
89
|
+
schema_version == ::Karafka::Web::Tracking::Consumers::Sampler::SCHEMA_VERSION
|
90
|
+
end
|
77
91
|
end
|
78
92
|
end
|
79
93
|
end
|
@@ -45,7 +45,7 @@ module Karafka
|
|
45
45
|
.sort
|
46
46
|
|
47
47
|
Lib::Admin.read_topic(
|
48
|
-
::Karafka::Web.config.topics.consumers.reports,
|
48
|
+
::Karafka::Web.config.topics.consumers.reports.name,
|
49
49
|
0,
|
50
50
|
# We set 10k here because we start from the latest offset of the reports, hence
|
51
51
|
# we will never get this much. Do do not know however exactly how many reports
|
@@ -83,7 +83,7 @@ module Karafka
|
|
83
83
|
# @param processes [Array<Hash>]
|
84
84
|
# @return [Array<Hash>] sorted processes data
|
85
85
|
def sort_processes(processes)
|
86
|
-
processes.sort_by { |consumer| consumer[:process]
|
86
|
+
processes.sort_by { |consumer| consumer[:process].fetch(:id) }
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
@@ -22,7 +22,7 @@ module Karafka
|
|
22
22
|
# get it because requested topic/partition does not exist or nothing was present
|
23
23
|
def current
|
24
24
|
messages = Karafka::Admin.read_topic(
|
25
|
-
config.topics.schedules,
|
25
|
+
config.topics.schedules.name,
|
26
26
|
0,
|
27
27
|
# We work here with the assumption that users won't click so fast to load
|
28
28
|
# more than 20 commands prior to a state flush. If that happens, this will
|
@@ -16,7 +16,7 @@ module Karafka
|
|
16
16
|
Step = Struct.new(:status, :details) do
|
17
17
|
# @return [Boolean] is the given step successfully configured and working
|
18
18
|
def success?
|
19
|
-
|
19
|
+
%i[success warning].include?(status)
|
20
20
|
end
|
21
21
|
|
22
22
|
# @return [String] local namespace for partial of a given type
|
@@ -209,6 +209,27 @@ module Karafka
|
|
209
209
|
)
|
210
210
|
end
|
211
211
|
|
212
|
+
# @return [Status::Step] are there any consumer processes with incompatible schema that
|
213
|
+
# does not match exactly the one used by the Web UI.
|
214
|
+
#
|
215
|
+
# @note It issues a warning, not an error.
|
216
|
+
def consumers_schemas
|
217
|
+
details = { incompatible: [] }
|
218
|
+
|
219
|
+
status = if consumers_reports.success?
|
220
|
+
incompatible = @processes.reject(&:schema_compatible?)
|
221
|
+
details[:incompatible] = incompatible
|
222
|
+
incompatible.empty? ? :success : :warning
|
223
|
+
else
|
224
|
+
:halted
|
225
|
+
end
|
226
|
+
|
227
|
+
Step.new(
|
228
|
+
status,
|
229
|
+
details
|
230
|
+
)
|
231
|
+
end
|
232
|
+
|
212
233
|
# @return [Status::Step] Is there a significant lag in the reporting of aggregated data
|
213
234
|
# back to the Kafka. If yes, it means that the results in the Web UI will be delayed
|
214
235
|
# against the reality. Often it means, that there is over-saturation on the consumer
|
@@ -307,22 +328,22 @@ module Karafka
|
|
307
328
|
|
308
329
|
# @return [String] consumers states topic name
|
309
330
|
def topics_consumers_states
|
310
|
-
::Karafka::Web.config.topics.consumers.states.to_s
|
331
|
+
::Karafka::Web.config.topics.consumers.states.name.to_s
|
311
332
|
end
|
312
333
|
|
313
334
|
# @return [String] consumers reports topic name
|
314
335
|
def topics_consumers_reports
|
315
|
-
::Karafka::Web.config.topics.consumers.reports.to_s
|
336
|
+
::Karafka::Web.config.topics.consumers.reports.name.to_s
|
316
337
|
end
|
317
338
|
|
318
339
|
# @return [String] consumers metrics topic name
|
319
340
|
def topics_consumers_metrics
|
320
|
-
::Karafka::Web.config.topics.consumers.metrics.to_s
|
341
|
+
::Karafka::Web.config.topics.consumers.metrics.name.to_s
|
321
342
|
end
|
322
343
|
|
323
344
|
# @return [String] errors topic name
|
324
345
|
def topics_errors
|
325
|
-
::Karafka::Web.config.topics.errors
|
346
|
+
::Karafka::Web.config.topics.errors.name
|
326
347
|
end
|
327
348
|
|
328
349
|
# @return [Hash] hash with topics with which we work details (even if don't exist)
|
@@ -355,9 +376,7 @@ module Karafka
|
|
355
376
|
# @note If fails, `connection_time` will be 1_000_000
|
356
377
|
def connect
|
357
378
|
started = Time.now.to_f
|
358
|
-
|
359
|
-
# info
|
360
|
-
@cluster_info = Models::ClusterInfo.fetch(cached: false)
|
379
|
+
@cluster_info = Models::ClusterInfo.fetch
|
361
380
|
@connection_time = (Time.now.to_f - started) * 1_000
|
362
381
|
rescue ::Rdkafka::RdkafkaError
|
363
382
|
@connection_time = 1_000_000
|
@@ -20,7 +20,7 @@ module Karafka
|
|
20
20
|
# @return [Topic]
|
21
21
|
# @raise [::Karafka::Web::Errors::Ui::NotFoundError]
|
22
22
|
def find(topic_name)
|
23
|
-
found =
|
23
|
+
found = ClusterInfo.topic(topic_name)
|
24
24
|
|
25
25
|
return found if found
|
26
26
|
|
@@ -56,7 +56,6 @@ module Karafka
|
|
56
56
|
# aggregated statistics and then the second value is an array with per partition data
|
57
57
|
def distribution(partitions)
|
58
58
|
sum = 0.0
|
59
|
-
avg = 0.0
|
60
59
|
|
61
60
|
counts = partitions.map do |partition_id|
|
62
61
|
offsets = Admin.read_watermark_offsets(topic_name, partition_id)
|
@@ -1,121 +1,31 @@
|
|
1
|
-
// Nicer display of time distance from a given event
|
2
|
-
function updateTimeAgo() {
|
3
|
-
var selection = document.querySelectorAll('time');
|
4
|
-
|
5
|
-
if (selection.length != 0) {
|
6
|
-
timeago.render(selection);
|
7
|
-
timeago.cancel()
|
8
|
-
}
|
9
|
-
|
10
|
-
var selection = document.getElementsByClassName('time-title')
|
11
|
-
var title = null
|
12
|
-
|
13
|
-
for (var i = 0; i < selection.length; i++) {
|
14
|
-
let element = selection[i]
|
15
|
-
|
16
|
-
title = element.getAttribute('title')
|
17
|
-
element.setAttribute('title', timeago.format(title))
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
// Cheap way to do breadcrumbs
|
22
|
-
function refreshTitle() {
|
23
|
-
const breadcrumbs = document.querySelectorAll('.breadcrumbs a');
|
24
|
-
let breadcrumbTexts = Array.from(breadcrumbs).slice(1).map(crumb => crumb.textContent.trim());
|
25
|
-
|
26
|
-
if (breadcrumbTexts.length > 0) {
|
27
|
-
document.title = breadcrumbTexts.join(' > ') + ' - Karafka Web UI';
|
28
|
-
} else {
|
29
|
-
document.title = 'Karafka Web UI';
|
30
|
-
}
|
31
|
-
}
|
32
|
-
|
33
|
-
// When using explorer, we can select the desired partition. This code redirects without having
|
34
|
-
// to press a button after a select
|
35
|
-
function redirectToPartition() {
|
36
|
-
var selector = document.getElementById('current-partition');
|
37
|
-
|
38
|
-
if (selector == null) { return }
|
39
|
-
|
40
|
-
selector.addEventListener('change', function(){
|
41
|
-
Turbo.visit(this.value);
|
42
|
-
});
|
43
|
-
}
|
44
|
-
|
45
|
-
// Binds to links and forms to make sure action is what user wants
|
46
|
-
function bindActionsConfirmations() {
|
47
|
-
var elements = document.getElementsByClassName('confirm-action')
|
48
|
-
var confirmation = 'Are you sure?'
|
49
|
-
|
50
|
-
for (var i = 0; i < elements.length; i++) {
|
51
|
-
let element = elements[i]
|
52
|
-
let action = 'click'
|
53
|
-
|
54
|
-
if (element.nodeName === 'FORM') {
|
55
|
-
action = 'submit'
|
56
|
-
}
|
57
|
-
|
58
|
-
element.addEventListener(action, function(event) {
|
59
|
-
if (!window.confirm(confirmation)) {
|
60
|
-
event.preventDefault();
|
61
|
-
}
|
62
|
-
})
|
63
|
-
}
|
64
|
-
}
|
65
|
-
|
66
|
-
function bindLockableButtons() {
|
67
|
-
document.querySelectorAll('.btn-lockable').forEach(function(button) {
|
68
|
-
button.addEventListener('click', function(event) {
|
69
|
-
// Find the form element the button is within
|
70
|
-
const form = button.closest('form');
|
71
|
-
|
72
|
-
// If the button is part of a form, add a submit event listener to the form
|
73
|
-
if (form) {
|
74
|
-
form.addEventListener('submit', function() {
|
75
|
-
button.disabled = true;
|
76
|
-
button.textContent += '...';
|
77
|
-
// also lock any modal that is open as the form is submitted
|
78
|
-
var modals = document.querySelectorAll('.modal');
|
79
|
-
|
80
|
-
// Add 'modal-locked' class to each modal
|
81
|
-
modals.forEach(function (modal) {
|
82
|
-
modal.classList.add('modal-locked');
|
83
|
-
});
|
84
|
-
}, { once: true });
|
85
|
-
} else {
|
86
|
-
// If the button is not part of a form, disable it immediately
|
87
|
-
button.disabled = true;
|
88
|
-
button.textContent += '...';
|
89
|
-
}
|
90
|
-
});
|
91
|
-
});
|
92
|
-
}
|
93
|
-
|
94
1
|
function addListeners() {
|
95
2
|
initLivePolling();
|
96
3
|
bindPollingButtonClick();
|
97
|
-
bindLockableButtons();
|
98
4
|
setLivePollButton();
|
99
5
|
setPollingListener();
|
100
6
|
|
101
7
|
hljs.highlightAll();
|
102
|
-
|
103
|
-
|
8
|
+
new TimeAgoManager();
|
9
|
+
new PartitionRedirectManager();
|
104
10
|
|
105
11
|
const tabsManager = new TabsManager();
|
106
12
|
tabsManager.manageTabs();
|
107
13
|
|
108
14
|
manageCharts();
|
109
|
-
bindActionsConfirmations();
|
110
15
|
loadOffsetLookupDatePicker();
|
111
16
|
|
112
17
|
new BtnToggleManager();
|
113
18
|
new BtnToggleManager('.btn-toggle-nav-collapsed', 'collapsed');
|
114
19
|
new ThemeManager();
|
115
20
|
|
116
|
-
|
21
|
+
new ButtonLockManager();
|
22
|
+
new ActionConfirmationManager();
|
23
|
+
new PageTitleTracker();
|
117
24
|
new SearchMetadataVisibilityManager();
|
118
25
|
new SearchModalManager();
|
26
|
+
new TimestampSelector();
|
27
|
+
new AlertsManager();
|
28
|
+
new MessageRepublishManager();
|
119
29
|
}
|
120
30
|
|
121
31
|
document.addEventListener('turbo:load', addListeners);
|