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
data/lib/karafka/web/ui/base.rb
CHANGED
@@ -40,6 +40,7 @@ module Karafka
|
|
40
40
|
plugin :capture_erb
|
41
41
|
plugin :content_for
|
42
42
|
plugin :inject_erb
|
43
|
+
plugin :all_verbs
|
43
44
|
|
44
45
|
# Based on
|
45
46
|
# https://github.com/sidekiq/sidekiq/blob/ae6ca119/lib/sidekiq/web/application.rb#L8
|
@@ -70,7 +71,16 @@ module Karafka
|
|
70
71
|
# Map redirect flashes (if any) to Roda flash messages
|
71
72
|
result.flashes.each { |key, value| flash[key] = value }
|
72
73
|
|
73
|
-
|
74
|
+
path = case result.path
|
75
|
+
when :back
|
76
|
+
session[:current_path]
|
77
|
+
when :previous
|
78
|
+
session[:previous_path]
|
79
|
+
else
|
80
|
+
root_path(result.path)
|
81
|
+
end
|
82
|
+
|
83
|
+
response.redirect path || root_path
|
74
84
|
end
|
75
85
|
|
76
86
|
handle_block_result Controllers::Responses::File do |result|
|
@@ -84,7 +94,8 @@ module Karafka
|
|
84
94
|
::Rdkafka::RdkafkaError,
|
85
95
|
Errors::Ui::NotFoundError,
|
86
96
|
Errors::Ui::ProOnlyError,
|
87
|
-
Errors::Ui::ForbiddenError
|
97
|
+
Errors::Ui::ForbiddenError,
|
98
|
+
Errors::Ui::IncompatibleSchemaError
|
88
99
|
] do |e|
|
89
100
|
@error = true
|
90
101
|
|
@@ -95,6 +106,9 @@ module Karafka
|
|
95
106
|
when Errors::Ui::ForbiddenError
|
96
107
|
response.status = 403
|
97
108
|
view 'shared/exceptions/not_allowed'
|
109
|
+
when Errors::Ui::IncompatibleSchemaError
|
110
|
+
response.status = 422
|
111
|
+
view 'shared/exceptions/incompatible_schema'
|
98
112
|
else
|
99
113
|
response.status = 404
|
100
114
|
view 'shared/exceptions/not_found'
|
@@ -109,9 +123,11 @@ module Karafka
|
|
109
123
|
|
110
124
|
before do
|
111
125
|
check_csrf!
|
126
|
+
store_paths_history(request, session)
|
112
127
|
end
|
113
128
|
|
114
129
|
plugin :class_matchers
|
130
|
+
plugin :symbol_matchers
|
115
131
|
|
116
132
|
# Time matcher with optional hours, minutes and seconds
|
117
133
|
TIME_MATCHER = %r{(\d{4}-\d{2}-\d{2}/?(\d{2})?(:\d{2})?(:\d{2})?)}
|
@@ -122,12 +138,22 @@ module Karafka
|
|
122
138
|
# @note In case the date-time is invalid, raise and render 404
|
123
139
|
# @note The time component is optional as `Time#parse` will fallback to lowest time
|
124
140
|
# available, so we can build only date based lookups
|
125
|
-
class_matcher(Time, TIME_MATCHER) do
|
126
|
-
[Time.parse(datetime)]
|
141
|
+
class_matcher(Time, TIME_MATCHER) do |*datetime|
|
142
|
+
[Time.parse(datetime[0])]
|
127
143
|
rescue ArgumentError
|
128
144
|
raise Errors::Ui::NotFoundError
|
129
145
|
end
|
130
146
|
|
147
|
+
# Partitions ids cannot be bigger than 32 bit C int. We use this matcher to ensure we
|
148
|
+
# only support that big partition numbers. Otherwise librdkafka would crash.
|
149
|
+
symbol_matcher :partition_id, /(\d{1,14})/ do |value|
|
150
|
+
int_value = value.to_i
|
151
|
+
|
152
|
+
raise Errors::Ui::NotFoundError unless int_value.between?(0, 2_147_483_647)
|
153
|
+
|
154
|
+
[int_value]
|
155
|
+
end
|
156
|
+
|
131
157
|
# Allows us to build current path with additional params + it merges existing params into
|
132
158
|
# the query data. Query data takes priority over request params.
|
133
159
|
# @param query_data [Hash] query params we want to add to the current path
|
@@ -145,6 +171,14 @@ module Karafka
|
|
145
171
|
[request.path, query_string].compact.join('?')
|
146
172
|
end
|
147
173
|
|
174
|
+
# Builds a consumer instance with all needed details
|
175
|
+
# @param consumer_class [Class]
|
176
|
+
def build(consumer_class)
|
177
|
+
Controllers::Requests::ExecutionWrapper.new(
|
178
|
+
consumer_class.new(params, session)
|
179
|
+
)
|
180
|
+
end
|
181
|
+
|
148
182
|
# Sets appropriate template variables based on the response object and renders the
|
149
183
|
# expected view
|
150
184
|
# @param response [Karafka::Web::Ui::Controllers::Responses::Data] response data object
|
@@ -162,6 +196,31 @@ module Karafka
|
|
162
196
|
def params
|
163
197
|
Controllers::Requests::Params.new(request.params)
|
164
198
|
end
|
199
|
+
|
200
|
+
private
|
201
|
+
|
202
|
+
# Stores history about visited paths. Useful for redirecting users back when needed.
|
203
|
+
# @param request [Karafka::Web::Ui::App::RodaRequest]
|
204
|
+
# @param session [Object] session object (Rails or Rack)
|
205
|
+
def store_paths_history(request, session)
|
206
|
+
# Code below tracks previous paths so we can use it to redirect users back
|
207
|
+
return unless request.get?
|
208
|
+
return unless request.env['HTTP_ACCEPT']&.include?('text/html')
|
209
|
+
|
210
|
+
requested_path = request.path
|
211
|
+
|
212
|
+
if session[:current_path].nil?
|
213
|
+
session[:current_path] = requested_path
|
214
|
+
|
215
|
+
return
|
216
|
+
end
|
217
|
+
|
218
|
+
return if request.path == session[:current_path]
|
219
|
+
|
220
|
+
# When navigating to a different page
|
221
|
+
session[:previous_path] = session[:current_path]
|
222
|
+
session[:current_path] = requested_path
|
223
|
+
end
|
165
224
|
end
|
166
225
|
end
|
167
226
|
end
|
@@ -8,6 +8,9 @@ module Karafka
|
|
8
8
|
# Base controller from which all the controllers should inherit.
|
9
9
|
class BaseController
|
10
10
|
include Web::Ui::Lib::Paginations
|
11
|
+
include Requests::Hookable
|
12
|
+
|
13
|
+
attr_reader :params, :session
|
11
14
|
|
12
15
|
# Alias for easier referencing
|
13
16
|
Models = Web::Ui::Models
|
@@ -19,9 +22,31 @@ module Karafka
|
|
19
22
|
|
20
23
|
self.sortable_attributes = []
|
21
24
|
|
25
|
+
# Detect that the state of the cache has changed
|
26
|
+
before do
|
27
|
+
cache.clear_if_needed(
|
28
|
+
session[:cache_hash],
|
29
|
+
session[:cache_timestamp].to_i
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
next unless cache.exist?
|
35
|
+
|
36
|
+
session[:cache_hash] = cache.hash
|
37
|
+
session[:cache_timestamp] = cache.timestamp.to_i
|
38
|
+
end
|
39
|
+
|
22
40
|
# @param params [Karafka::Web::Ui::Controllers::Requests::Params] request parameters
|
23
|
-
|
41
|
+
# @param session [Request::Session] request session (Rails or other framework)
|
42
|
+
def initialize(params, session)
|
24
43
|
@params = params
|
44
|
+
@session = session
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Karafka::Web::Ui::Lib::Cache] per-process cache instance
|
48
|
+
def cache
|
49
|
+
Karafka::Web.config.ui.cache
|
25
50
|
end
|
26
51
|
|
27
52
|
private
|
@@ -50,6 +75,9 @@ module Karafka
|
|
50
75
|
|
51
76
|
attributes[:breadcrums_scope] = scope
|
52
77
|
|
78
|
+
@current_action_name = action.to_sym
|
79
|
+
@current_controller_name = base.join('-')
|
80
|
+
|
53
81
|
instance_variables.each do |iv|
|
54
82
|
next if iv.to_s.start_with?('@_')
|
55
83
|
next if iv.to_s.start_with?('@params')
|
@@ -72,6 +100,20 @@ module Karafka
|
|
72
100
|
Responses::Redirect.new(path, flashes)
|
73
101
|
end
|
74
102
|
|
103
|
+
# Wraps the provided arguments inside a message with a `<strong>` tag to simplify flash
|
104
|
+
# messages building.
|
105
|
+
#
|
106
|
+
# @param message [String] message with `?` to be replaced.
|
107
|
+
# @param args [Array<Object>] arguments to use to replace `?` with strong
|
108
|
+
# @return [String] formatted string
|
109
|
+
def format_flash(message, *args)
|
110
|
+
args.each do |arg|
|
111
|
+
message = message.sub('?', "<strong>#{arg}</strong>")
|
112
|
+
end
|
113
|
+
|
114
|
+
message
|
115
|
+
end
|
116
|
+
|
75
117
|
# Builds a file response object that will be used as a base to dispatch the file
|
76
118
|
#
|
77
119
|
# @param content [String] Payload we want to dispatch as a file
|
@@ -17,6 +17,9 @@ module Karafka
|
|
17
17
|
in_sync_replica_brokers
|
18
18
|
].freeze
|
19
19
|
|
20
|
+
# Cluster state should always be fresh and not from cache
|
21
|
+
before { cache.clear }
|
22
|
+
|
20
23
|
# Lists available brokers in the cluster
|
21
24
|
def brokers
|
22
25
|
@brokers = refine(cluster_info.brokers)
|
@@ -50,9 +53,9 @@ module Karafka
|
|
50
53
|
|
51
54
|
private
|
52
55
|
|
53
|
-
#
|
56
|
+
# @return [Array] whole cluster info
|
54
57
|
def cluster_info
|
55
|
-
@cluster_info ||= Models::ClusterInfo.fetch
|
58
|
+
@cluster_info ||= Models::ClusterInfo.fetch
|
56
59
|
end
|
57
60
|
|
58
61
|
# @param cluster_info [Rdkafka::Metadata] cluster metadata
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Web
|
5
|
+
module Ui
|
6
|
+
module Controllers
|
7
|
+
module Requests
|
8
|
+
# @note This class is used internally by the Web UI to wrap controllers
|
9
|
+
# and inject execution hooks around any method call (before/after filters).
|
10
|
+
#
|
11
|
+
# ExecutionWrapper delegates all method calls to the provided controller instance.
|
12
|
+
# Before and after each invocation, it runs the controller's registered hooks.
|
13
|
+
#
|
14
|
+
# This allows for cleaner separation of concerns and reusable hook logic.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# controller = SomeController.new
|
18
|
+
# wrapper = ExecutionWrapper.new(controller)
|
19
|
+
# wrapper.call # will run before(:call), call, then after(:call)
|
20
|
+
class ExecutionWrapper
|
21
|
+
# @param controller [Object] a controller instance responding to method calls
|
22
|
+
def initialize(controller)
|
23
|
+
@controller = controller
|
24
|
+
end
|
25
|
+
|
26
|
+
# Delegates any method call to the controller and wraps it with before/after hooks
|
27
|
+
#
|
28
|
+
# @param method_name [Symbol] the name of the method being called
|
29
|
+
# @param args [Array] arguments passed to the method
|
30
|
+
# @param block [Proc] optional block passed to the method
|
31
|
+
# @return [Object] the result of the delegated controller method for Roda to operate on
|
32
|
+
def method_missing(method_name, *args, &block)
|
33
|
+
@controller.run_before_hooks(method_name)
|
34
|
+
result = @controller.public_send(method_name, *args, &block)
|
35
|
+
@controller.run_after_hooks(method_name)
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
# Properly supports respond_to? checks by delegating to the controller
|
40
|
+
#
|
41
|
+
# @param method_name [Symbol] the method name to check
|
42
|
+
# @param include_private [Boolean] whether to include private methods
|
43
|
+
# @return [Boolean] true if controller responds to the method
|
44
|
+
def respond_to_missing?(method_name, include_private = false)
|
45
|
+
@controller.respond_to?(method_name, include_private)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Web
|
5
|
+
module Ui
|
6
|
+
module Controllers
|
7
|
+
module Requests
|
8
|
+
# Adds before/after hook support for controller methods.
|
9
|
+
#
|
10
|
+
# This module allows registering callbacks that run before and after
|
11
|
+
# any named method (e.g., `call`, `show`) or for all methods.
|
12
|
+
#
|
13
|
+
# Hooks are inherited from parent controllers, making it easy to
|
14
|
+
# define shared behavior across a hierarchy.
|
15
|
+
#
|
16
|
+
# @example Adding hooks to a controller
|
17
|
+
# class MyController
|
18
|
+
# include Hookable
|
19
|
+
#
|
20
|
+
# before(:call) { puts "before call" }
|
21
|
+
# after(:call) { puts "after call" }
|
22
|
+
#
|
23
|
+
# def call
|
24
|
+
# run_before_hooks(:call)
|
25
|
+
# # actual logic
|
26
|
+
# run_after_hooks(:call)
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
module Hookable
|
30
|
+
# Hook into class inclusion to extend DSL
|
31
|
+
#
|
32
|
+
# @param base [Class] the class including this module
|
33
|
+
def self.included(base)
|
34
|
+
base.extend(ClassMethods)
|
35
|
+
end
|
36
|
+
|
37
|
+
# DSL methods for defining and inheriting hooks
|
38
|
+
module ClassMethods
|
39
|
+
# Inherit parent hooks into subclass
|
40
|
+
#
|
41
|
+
# @param subclass [Class] the subclass inheriting from base controller
|
42
|
+
def inherited(subclass)
|
43
|
+
super
|
44
|
+
subclass.before_hooks.concat(before_hooks)
|
45
|
+
subclass.after_hooks.concat(after_hooks)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Array] accumulated before hooks
|
49
|
+
def before_hooks
|
50
|
+
@before_hooks ||= []
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [Array] accumulated after hooks
|
54
|
+
def after_hooks
|
55
|
+
@after_hooks ||= []
|
56
|
+
end
|
57
|
+
|
58
|
+
# Register a before hook
|
59
|
+
#
|
60
|
+
# @param actions [Array<Symbol>] optional action names to match (e.g., :call)
|
61
|
+
# @param block [Proc]
|
62
|
+
# @yield a block to execute before matched actions
|
63
|
+
def before(*actions, &block)
|
64
|
+
before_hooks << [actions, block]
|
65
|
+
end
|
66
|
+
|
67
|
+
# Register an after hook
|
68
|
+
#
|
69
|
+
# @param actions [Array<Symbol>] optional action names to match (e.g., :call)
|
70
|
+
# @param block [Proc]
|
71
|
+
# @yield a block to execute after matched actions
|
72
|
+
def after(*actions, &block)
|
73
|
+
after_hooks << [actions, block]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Run all before hooks matching the action
|
78
|
+
#
|
79
|
+
# @param action_name [Symbol] the method name being invoked
|
80
|
+
def run_before_hooks(action_name)
|
81
|
+
self.class.before_hooks.each do |actions, block|
|
82
|
+
instance_exec(&block) if actions.empty? || actions.include?(action_name)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Run all after hooks matching the action
|
87
|
+
#
|
88
|
+
# @param action_name [Symbol] the method name being invoked
|
89
|
+
def run_after_hooks(action_name)
|
90
|
+
self.class.after_hooks.each do |actions, block|
|
91
|
+
instance_exec(&block) if actions.empty? || actions.include?(action_name)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -17,13 +17,51 @@ module Karafka
|
|
17
17
|
days
|
18
18
|
].freeze
|
19
19
|
|
20
|
-
|
20
|
+
# What string values true can be in params
|
21
|
+
ALLOWED_BOOLEAN_TRUE = %w[
|
22
|
+
on
|
23
|
+
yes
|
24
|
+
true
|
25
|
+
].freeze
|
26
|
+
|
27
|
+
private_constant :ALLOWED_RANGES, :ALLOWED_BOOLEAN_TRUE
|
21
28
|
|
22
29
|
# @param request_params [Hash] raw hash with params
|
23
30
|
def initialize(request_params)
|
24
31
|
@request_params = request_params
|
25
32
|
end
|
26
33
|
|
34
|
+
# @param key [String, Symbol] params key
|
35
|
+
# @return [Object] value of the requested param
|
36
|
+
def [](key)
|
37
|
+
fetch(key.to_s)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param args [Symbol, Object] key we want to fetch and other args for `Hash#fetch`
|
41
|
+
# @return [Object] fetched object
|
42
|
+
def fetch(*args)
|
43
|
+
args[0] = args[0].to_s
|
44
|
+
@request_params.fetch(*args)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param key [String, Symbol] params key
|
48
|
+
# @return [Integer] integer value of the key
|
49
|
+
def int(key)
|
50
|
+
self[key].to_i
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param key [String, Symbol] params key
|
54
|
+
# @return [Boolean] boolean key value
|
55
|
+
def bool(key)
|
56
|
+
ALLOWED_BOOLEAN_TRUE.include?(self[key])
|
57
|
+
end
|
58
|
+
|
59
|
+
# @param key [String, Symbol] params key
|
60
|
+
# @return [String] stringified key value
|
61
|
+
def str(key)
|
62
|
+
self[key].to_s
|
63
|
+
end
|
64
|
+
|
27
65
|
# @return [Hash] current search or empty if no search query present
|
28
66
|
def current_search
|
29
67
|
return @current_search if @current_search
|
@@ -10,6 +10,9 @@ module Karafka
|
|
10
10
|
# page where we check that everything is as expected and if not, we can provide some
|
11
11
|
# helpful instructions on how to fix the issues.
|
12
12
|
class StatusController < BaseController
|
13
|
+
# Fresh state is needed to generate always correct status
|
14
|
+
before { cache.clear }
|
15
|
+
|
13
16
|
# Displays the Web UI setup status
|
14
17
|
def show
|
15
18
|
@status = Models::Status.new
|
@@ -223,13 +223,22 @@ module Karafka
|
|
223
223
|
title = 'Not available until first offset commit'
|
224
224
|
%(<span class="badge badge-secondary" title="#{title}">N/A</span>)
|
225
225
|
elsif explore
|
226
|
-
path =
|
226
|
+
path = explorer_topics_path(topic_name, partition_id, offset)
|
227
227
|
%(<a href="#{path}">#{offset}</a>)
|
228
228
|
else
|
229
229
|
offset.to_s
|
230
230
|
end
|
231
231
|
end
|
232
232
|
|
233
|
+
# Normalizes the metric value for display. Negative values coming from statistics usually
|
234
|
+
# mean, that the value is not (yet) available.
|
235
|
+
#
|
236
|
+
# @param value [Integer]
|
237
|
+
# @return [String] input value if not negative or N/A
|
238
|
+
def normalized_metric(value)
|
239
|
+
value.negative? ? 'N/A' : value.to_s
|
240
|
+
end
|
241
|
+
|
233
242
|
# @param details [::Karafka::Web::Ui::Models::Partition] partition information with
|
234
243
|
# lso risk state info
|
235
244
|
# @return [String] background classes for row marking
|
@@ -6,6 +6,15 @@ module Karafka
|
|
6
6
|
module Helpers
|
7
7
|
# Helper for web ui paths builders
|
8
8
|
module PathsHelper
|
9
|
+
# Method that can be used to have conditions in breadcrumbs, etc based on the action
|
10
|
+
# we're in
|
11
|
+
#
|
12
|
+
# @param args [Array<Symbol>] action names we want to check
|
13
|
+
# @return [Boolean] true if any matches the current action name
|
14
|
+
def action?(*args)
|
15
|
+
args.include?(@current_action_name)
|
16
|
+
end
|
17
|
+
|
9
18
|
# Helper method to flatten nested hashes and arrays
|
10
19
|
# @param prefix [String] The prefix for nested keys, initially an empty string.
|
11
20
|
# @param hash [Hash, Array] The nested hash or array to be flattened.
|
@@ -54,16 +63,51 @@ module Karafka
|
|
54
63
|
|
55
64
|
# Helps build explorer paths. We often link offsets to proper messages, etc so this
|
56
65
|
# allows us to short-track this
|
57
|
-
# @param
|
58
|
-
# explorer or nil if we want to just go to the explorer root
|
59
|
-
# @param partition_id [Integer, nil] partition we want to display in the explorer or nil
|
60
|
-
# if we want to go to the topic root
|
61
|
-
# @param offset [Integer, nil] offset of particular message or nil of we want to just go
|
62
|
-
# to the partition root
|
63
|
-
# @param action [String, nil] specific routed action or nil
|
66
|
+
# @param args [Array<String>] sub-paths
|
64
67
|
# @return [String] path to the expected location
|
65
|
-
def explorer_path(
|
66
|
-
root_path(*['explorer',
|
68
|
+
def explorer_path(*args)
|
69
|
+
root_path(*['explorer', args.compact].flatten)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Generates routes for explorer topics paths
|
73
|
+
#
|
74
|
+
# @param args [Array<String>] sub-paths
|
75
|
+
# @return explorer topics path
|
76
|
+
def explorer_topics_path(*args)
|
77
|
+
explorer_path(*['topics', args.compact].flatten)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Generates routes for explorer messages paths
|
81
|
+
#
|
82
|
+
# @param args [Array<String>] sub-paths
|
83
|
+
# @return [String] explorer messages path
|
84
|
+
def explorer_messages_path(*args)
|
85
|
+
explorer_path(*['messages', args.compact].flatten)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Helps build topics paths
|
89
|
+
#
|
90
|
+
# @param args [Array<String>] path params for the topics scope
|
91
|
+
# @return [String] topics scope path
|
92
|
+
def topics_path(*args)
|
93
|
+
root_path('topics', *args)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Helps build consumers paths
|
97
|
+
#
|
98
|
+
# @param args [Array<String>] path params for consumers scope
|
99
|
+
# @return [String] consumers scope path
|
100
|
+
def consumers_path(*args)
|
101
|
+
root_path('consumers', *args)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Helps build per-consumer scope paths
|
105
|
+
#
|
106
|
+
# @param consumer_id [String] consumer process id
|
107
|
+
# @param args [Array<String>] other path components
|
108
|
+
# @return [String] per consumer specific path
|
109
|
+
def consumer_path(consumer_id, *args)
|
110
|
+
consumers_path(consumer_id, *args)
|
67
111
|
end
|
68
112
|
|
69
113
|
# Helps build scheduled messages paths.
|
@@ -80,7 +124,7 @@ module Karafka
|
|
80
124
|
action = nil
|
81
125
|
)
|
82
126
|
root_path(
|
83
|
-
*['scheduled_messages', 'explorer', topic_name, partition_id, offset, action].compact
|
127
|
+
*['scheduled_messages', 'explorer', 'topics', topic_name, partition_id, offset, action].compact
|
84
128
|
)
|
85
129
|
end
|
86
130
|
end
|
@@ -17,7 +17,7 @@ module Karafka
|
|
17
17
|
class << self
|
18
18
|
extend Forwardable
|
19
19
|
|
20
|
-
def_delegators ::Karafka::Admin, :read_watermark_offsets, :cluster_info
|
20
|
+
def_delegators ::Karafka::Admin, :read_watermark_offsets, :cluster_info, :topic_info
|
21
21
|
|
22
22
|
# Allows us to read messages from the topic
|
23
23
|
#
|