karafka-web 0.10.3 → 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 +64 -176
- data/Gemfile +4 -0
- data/Gemfile.lock +88 -44
- 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 +3 -5
- data/lib/karafka/web/config.rb +86 -10
- data/lib/karafka/web/contracts/config.rb +45 -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 +32 -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/errors.rb +38 -9
- 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 +2 -9
- 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 +15 -6
- 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/btn_toggle_manager.js +17 -7
- 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 +5123 -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 +9 -1
- data/package-lock.json +799 -1226
- 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 +233 -109
- 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
@@ -63,7 +63,7 @@ module Karafka
|
|
63
63
|
# Report consumers statuses
|
64
64
|
messages = [
|
65
65
|
{
|
66
|
-
topic: ::Karafka::Web.config.topics.consumers.reports,
|
66
|
+
topic: ::Karafka::Web.config.topics.consumers.reports.name,
|
67
67
|
payload: Zlib::Deflate.deflate(report.to_json),
|
68
68
|
key: process_id,
|
69
69
|
partition: 0,
|
@@ -76,7 +76,7 @@ module Karafka
|
|
76
76
|
@error_contract.validate!(error)
|
77
77
|
|
78
78
|
{
|
79
|
-
topic: Karafka::Web.config.topics.errors,
|
79
|
+
topic: Karafka::Web.config.topics.errors.name,
|
80
80
|
payload: Zlib::Deflate.deflate(error.to_json),
|
81
81
|
# Always dispatch errors from the same process to the same partition
|
82
82
|
key: process_id,
|
@@ -15,7 +15,7 @@ module Karafka
|
|
15
15
|
# Current schema version
|
16
16
|
# This is used for detecting incompatible changes and not using outdated data during
|
17
17
|
# upgrades
|
18
|
-
SCHEMA_VERSION = '1.4.
|
18
|
+
SCHEMA_VERSION = '1.4.1'
|
19
19
|
|
20
20
|
# Counters that count events occurrences during the given window
|
21
21
|
COUNTERS_BASE = {
|
@@ -51,7 +51,17 @@ module Karafka
|
|
51
51
|
@subscription_groups = Hash.new do |h, sg_id|
|
52
52
|
h[sg_id] = {
|
53
53
|
id: sg_id,
|
54
|
-
polled_at: monotonic_now
|
54
|
+
polled_at: monotonic_now,
|
55
|
+
topics: Hash.new do |h1, topic|
|
56
|
+
h1[topic] = Hash.new do |h2, partition|
|
57
|
+
# We track those details in case we need to fill statistical gaps for
|
58
|
+
# transactional consumers
|
59
|
+
h2[partition] = {
|
60
|
+
seek_offset: -1,
|
61
|
+
transactional: false
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
55
65
|
}
|
56
66
|
end
|
57
67
|
|
@@ -223,11 +233,9 @@ module Karafka
|
|
223
233
|
def memory_size
|
224
234
|
@memory_size ||= case RUBY_PLATFORM
|
225
235
|
when /linux/
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
.to_s
|
230
|
-
.to_i
|
236
|
+
mem_info = File.read('/proc/meminfo')
|
237
|
+
mem_total_line = mem_info.match(/MemTotal:\s*(?<total>\d+)/)
|
238
|
+
mem_total_line['total'].to_i
|
231
239
|
when /darwin|bsd/
|
232
240
|
@shell
|
233
241
|
.call('sysctl -a')
|
@@ -245,7 +253,13 @@ module Karafka
|
|
245
253
|
# @return [Array<Float>] load averages for last 1, 5 and 15 minutes
|
246
254
|
def cpu_usage
|
247
255
|
case RUBY_PLATFORM
|
248
|
-
when /
|
256
|
+
when /linux/
|
257
|
+
File
|
258
|
+
.read('/proc/loadavg')
|
259
|
+
.split(' ')
|
260
|
+
.first(3)
|
261
|
+
.map(&:to_f)
|
262
|
+
when /darwin|bsd/
|
249
263
|
@shell
|
250
264
|
.call('w | head -1')
|
251
265
|
.strip
|
@@ -280,10 +294,21 @@ module Karafka
|
|
280
294
|
def memory_threads_ps
|
281
295
|
@memory_threads_ps = case RUBY_PLATFORM
|
282
296
|
when /linux/
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
297
|
+
page_size = Karafka::Web::Tracking::Helpers::Sysconf.page_size
|
298
|
+
status_file = "/proc/#{::Process.pid}/status"
|
299
|
+
|
300
|
+
pid = status_file.match(%r{/proc/(\d+)/status})[1]
|
301
|
+
|
302
|
+
# Extract thread count from /proc/<pid>/status
|
303
|
+
thcount = File.read(status_file)[/^Threads:\s+(\d+)/, 1].to_i
|
304
|
+
|
305
|
+
# Extract RSS from /proc/<pid>/statm (second field)
|
306
|
+
statm_file = "/proc/#{pid}/statm"
|
307
|
+
rss_pages = File.read(statm_file).split[1].to_i rescue 0
|
308
|
+
# page size is retrieved from Sysconf
|
309
|
+
rss_kb = (rss_pages * page_size) / 1024
|
310
|
+
|
311
|
+
[[rss_kb, thcount, pid.to_i]]
|
287
312
|
# thcount is not available on macos ps
|
288
313
|
# because of that we inject 0 as threads count similar to how
|
289
314
|
# we do on windows
|
@@ -308,9 +333,51 @@ module Karafka
|
|
308
333
|
# This should be always available, since the subscription group polled at time
|
309
334
|
# is first initialized before we start polling, there should be no case where
|
310
335
|
# we have statistics about a given subscription group but we do not have the
|
311
|
-
#
|
312
|
-
|
336
|
+
# sg reference
|
337
|
+
sg_tracking = subscription_groups.fetch(sg_id)
|
338
|
+
|
339
|
+
polled_at = sg_tracking.fetch(:polled_at)
|
313
340
|
sg_details[:state][:poll_age] = (monotonic_now - polled_at).round(2)
|
341
|
+
|
342
|
+
sg_details[:topics].each do |topic_name, topic_details|
|
343
|
+
topic_details[:partitions].each do |partition_id, partition_details|
|
344
|
+
# Always assume non-transactional as default. Will be overwritten by the
|
345
|
+
# consumer level details if collected
|
346
|
+
partition_details[:transactional] ||= false
|
347
|
+
|
348
|
+
# If we have stored offset or stored lag, it means it's not a transactional
|
349
|
+
# consumer at all so we can skip enrichment
|
350
|
+
next if partition_details[:lag_stored].positive?
|
351
|
+
next if partition_details[:stored_offset].positive?
|
352
|
+
next unless sg_tracking[:topics].key?(topic_name)
|
353
|
+
next unless sg_tracking[:topics][topic_name].key?(partition_id)
|
354
|
+
|
355
|
+
k_partition_details = sg_tracking[:topics][topic_name][partition_id]
|
356
|
+
|
357
|
+
# If seek offset was not yey set, nothing to enrich
|
358
|
+
next unless k_partition_details[:seek_offset].positive?
|
359
|
+
|
360
|
+
partition_details[:transactional] = k_partition_details[:transactional]
|
361
|
+
|
362
|
+
# Seek offset is always +1 from the last stored in Karafka
|
363
|
+
seek_offset = k_partition_details[:seek_offset]
|
364
|
+
stored_offset = seek_offset - 1
|
365
|
+
|
366
|
+
# In case of transactions we have to compute the lag ourselves
|
367
|
+
# -1 because ls offset (or high watermark) is last + 1
|
368
|
+
lag = partition_details[:ls_offset] - seek_offset
|
369
|
+
# This can happen if ls_offset is refreshed slower than our stored offset
|
370
|
+
# fetching from Karafka transactional layer
|
371
|
+
lag = 0 if lag.negative?
|
372
|
+
|
373
|
+
partition_details[:lag] = lag
|
374
|
+
partition_details[:lag_d] = 0
|
375
|
+
partition_details[:lag_stored] = lag
|
376
|
+
partition_details[:lag_stored_d] = 0
|
377
|
+
partition_details[:stored_offset] = stored_offset
|
378
|
+
partition_details[:committed_offset] = stored_offset
|
379
|
+
end
|
380
|
+
end
|
314
381
|
end
|
315
382
|
end
|
316
383
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Karafka
|
4
|
+
module Web
|
5
|
+
module Tracking
|
6
|
+
# Namespace for tracking related helpers
|
7
|
+
module Helpers
|
8
|
+
# Namespace for unix-based helper methods used to fetch OS details
|
9
|
+
module Sysconf
|
10
|
+
extend FFI::Library
|
11
|
+
|
12
|
+
case RUBY_PLATFORM
|
13
|
+
when /linux/
|
14
|
+
ffi_lib 'libc.so.6' # Standard C library on Linux
|
15
|
+
SC_PAGESIZE = 30 # _SC_PAGESIZE constant
|
16
|
+
when /darwin/
|
17
|
+
ffi_lib 'libSystem.B.dylib' # Standard C library on macOS
|
18
|
+
SC_PAGESIZE = 29 # _SC_PAGESIZE constant
|
19
|
+
end
|
20
|
+
|
21
|
+
attach_function :sysconf, [:int], :long
|
22
|
+
|
23
|
+
class << self
|
24
|
+
# @return [Integer]
|
25
|
+
def page_size
|
26
|
+
sysconf(SC_PAGESIZE)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -10,13 +10,6 @@ module Karafka
|
|
10
10
|
# because there is no expectation on immediate status updates for producers and their
|
11
11
|
# dispatch flow is always periodic based.
|
12
12
|
class Reporter < Tracking::Reporter
|
13
|
-
# Minimum number of messages to produce to produce them in sync mode
|
14
|
-
# This acts as a small back-off not to overload the system in case we would have
|
15
|
-
# extremely big number of errors happening
|
16
|
-
PRODUCE_SYNC_THRESHOLD = 25
|
17
|
-
|
18
|
-
private_constant :PRODUCE_SYNC_THRESHOLD
|
19
|
-
|
20
13
|
# This mutex is shared between tracker and samplers so there is no case where metrics
|
21
14
|
# would be collected same time tracker reports
|
22
15
|
MUTEX = Mutex.new
|
@@ -40,7 +33,7 @@ module Karafka
|
|
40
33
|
@error_contract.validate!(error)
|
41
34
|
|
42
35
|
{
|
43
|
-
topic: Karafka::Web.config.topics.errors,
|
36
|
+
topic: Karafka::Web.config.topics.errors.name,
|
44
37
|
payload: error.to_json,
|
45
38
|
# Always dispatch errors from the same process to the same partition
|
46
39
|
key: error[:process][:id]
|
@@ -82,7 +75,7 @@ module Karafka
|
|
82
75
|
# normal operations we should not have that many messages to dispatch and it should not
|
83
76
|
# slowdown any processing.
|
84
77
|
def produce(messages)
|
85
|
-
if messages.count >=
|
78
|
+
if messages.count >= ::Karafka::Web.config.tracking.producers.sync_threshold
|
86
79
|
::Karafka::Web.producer.produce_many_sync(messages)
|
87
80
|
else
|
88
81
|
::Karafka::Web.producer.produce_many_async(messages)
|
data/lib/karafka/web/ui/app.rb
CHANGED
@@ -11,122 +11,29 @@ module Karafka
|
|
11
11
|
|
12
12
|
instance_exec(&CONTEXT_DETAILS)
|
13
13
|
|
14
|
+
# Sub-routes for given pieces of the Web UI
|
15
|
+
SUB_ROUTES = [
|
16
|
+
Routes::Assets,
|
17
|
+
Routes::Dashboard,
|
18
|
+
Routes::Consumers,
|
19
|
+
Routes::ProOnly,
|
20
|
+
Routes::Jobs,
|
21
|
+
Routes::Routing,
|
22
|
+
Routes::Cluster,
|
23
|
+
Routes::Errors,
|
24
|
+
Routes::Status,
|
25
|
+
Routes::Support,
|
26
|
+
Routes::Ux
|
27
|
+
].freeze
|
28
|
+
|
29
|
+
private_constant :SUB_ROUTES
|
30
|
+
|
14
31
|
route do |r|
|
15
32
|
r.root { r.redirect root_path('dashboard') }
|
16
33
|
|
17
|
-
|
18
|
-
# after upgrade
|
19
|
-
r.on 'assets', Karafka::Web::VERSION do
|
20
|
-
r.public
|
21
|
-
end
|
22
|
-
|
23
|
-
r.get 'dashboard' do
|
24
|
-
@breadcrumbs = false
|
25
|
-
controller = Controllers::DashboardController.new(params)
|
26
|
-
controller.index
|
27
|
-
end
|
28
|
-
|
29
|
-
r.on 'consumers' do
|
30
|
-
%w[
|
31
|
-
performance
|
32
|
-
controls
|
33
|
-
commands
|
34
|
-
].each do |path|
|
35
|
-
r.get path do |_process_id|
|
36
|
-
raise Errors::Ui::ProOnlyError
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
r.get String, 'subscriptions' do |_process_id|
|
41
|
-
raise Errors::Ui::ProOnlyError
|
42
|
-
end
|
43
|
-
|
44
|
-
r.get do
|
45
|
-
controller = Controllers::ConsumersController.new(params)
|
46
|
-
controller.index
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
%w[
|
51
|
-
health
|
52
|
-
explorer
|
53
|
-
dlq
|
54
|
-
].each do |route|
|
55
|
-
r.get route, [String, true], [String, true] do
|
56
|
-
raise Errors::Ui::ProOnlyError
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
r.on 'jobs' do
|
61
|
-
controller = Controllers::JobsController.new(params)
|
62
|
-
|
63
|
-
r.get 'running' do
|
64
|
-
controller.running
|
65
|
-
end
|
66
|
-
|
67
|
-
r.get 'pending' do
|
68
|
-
controller.pending
|
69
|
-
end
|
70
|
-
|
71
|
-
r.redirect root_path('jobs/running')
|
72
|
-
end
|
73
|
-
|
74
|
-
r.on 'routing' do
|
75
|
-
controller = Controllers::RoutingController.new(params)
|
76
|
-
|
77
|
-
r.get String do |topic_id|
|
78
|
-
controller.show(topic_id)
|
79
|
-
end
|
80
|
-
|
81
|
-
r.get do
|
82
|
-
controller.index
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
r.on 'cluster' do
|
87
|
-
controller = Controllers::ClusterController.new(params)
|
88
|
-
|
89
|
-
r.get 'brokers' do
|
90
|
-
controller.brokers
|
91
|
-
end
|
92
|
-
|
93
|
-
r.get 'replication' do
|
94
|
-
controller.replication
|
95
|
-
end
|
96
|
-
|
97
|
-
r.redirect root_path('cluster/brokers')
|
98
|
-
end
|
99
|
-
|
100
|
-
r.on 'topics' do
|
101
|
-
raise Errors::Ui::ProOnlyError
|
102
|
-
end
|
103
|
-
|
104
|
-
r.on 'errors' do
|
105
|
-
controller = Controllers::ErrorsController.new(params)
|
106
|
-
|
107
|
-
r.get Integer do |offset|
|
108
|
-
controller.show(offset)
|
109
|
-
end
|
110
|
-
|
111
|
-
r.get do
|
112
|
-
controller.index
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
r.get 'status' do
|
117
|
-
controller = Controllers::StatusController.new(params)
|
118
|
-
controller.show
|
119
|
-
end
|
120
|
-
|
121
|
-
r.get 'ux' do
|
122
|
-
controller = Controllers::UxController.new(params)
|
123
|
-
controller.show
|
124
|
-
end
|
34
|
+
SUB_ROUTES.each { |sub_route| sub_route.bind(self, r) }
|
125
35
|
|
126
|
-
|
127
|
-
controller = Controllers::SupportController.new(params)
|
128
|
-
controller.show
|
129
|
-
end
|
36
|
+
nil
|
130
37
|
end
|
131
38
|
end
|
132
39
|
end
|
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
|