karafka-web 0.9.2 → 0.10.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/.github/workflows/ci.yml +30 -0
- data/.gitignore +2 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +84 -3
- data/Gemfile +1 -0
- data/Gemfile.lock +30 -25
- data/LICENSE +1 -1
- data/bin/build_assets +51 -0
- data/bin/release +6 -0
- data/config/locales/pro_errors.yml +18 -0
- data/docker-compose.yml +1 -1
- data/gulpfile.js +73 -0
- data/karafka-web.gemspec +7 -2
- data/lib/karafka/web/config.rb +9 -10
- data/lib/karafka/web/contracts/base.rb +2 -0
- data/lib/karafka/web/contracts/config.rb +2 -1
- data/lib/karafka/web/errors.rb +12 -0
- data/lib/karafka/web/inflector.rb +1 -1
- data/lib/karafka/web/management/actions/enable.rb +11 -0
- data/lib/karafka/web/management/migrations/consumers_metrics/0_set_initial.rb +39 -0
- data/lib/karafka/web/management/migrations/consumers_metrics/1699543515_fill_missing_received_and_sent_bytes.rb +28 -0
- data/lib/karafka/web/management/migrations/consumers_metrics/1700234522_introduce_waiting.rb +26 -0
- data/lib/karafka/web/management/migrations/consumers_metrics/1700234522_remove_processing.rb +26 -0
- data/lib/karafka/web/management/migrations/consumers_metrics/1704722380_split_listeners_into_active_and_paused.rb +38 -0
- data/lib/karafka/web/management/migrations/consumers_metrics/1706607960_introduce_lag_total.rb +40 -0
- data/lib/karafka/web/management/migrations/consumers_metrics/1706611396_rename_lag_total_to_lag_hybrid.rb +38 -0
- data/lib/karafka/web/management/migrations/consumers_metrics/1716218393_populate_jobs_metrics.rb +26 -0
- data/lib/karafka/web/management/migrations/consumers_states/0_set_initial.rb +46 -0
- data/lib/karafka/web/management/migrations/consumers_states/1699543515_fill_missing_received_and_sent_bytes.rb +25 -0
- data/lib/karafka/web/management/migrations/consumers_states/1700234522_introduce_waiting.rb +22 -0
- data/lib/karafka/web/management/migrations/consumers_states/1700234522_remove_processing.rb +22 -0
- data/lib/karafka/web/management/migrations/consumers_states/1704722380_split_listeners_into_active_and_paused.rb +34 -0
- data/lib/karafka/web/management/migrations/consumers_states/1706607960_introduce_lag_total.rb +24 -0
- data/lib/karafka/web/management/migrations/consumers_states/1706611396_rename_lag_total_to_lag_hybrid.rb +23 -0
- data/lib/karafka/web/management/migrations/consumers_states/1716218393_add_jobs_counter.rb +24 -0
- data/lib/karafka/web/management/migrator.rb +5 -5
- data/lib/karafka/web/pro/commanding/commands/base.rb +8 -0
- data/lib/karafka/web/pro/commanding/commands/quiet.rb +4 -1
- data/lib/karafka/web/pro/commanding/commands/stop.rb +4 -1
- data/lib/karafka/web/pro/loader.rb +8 -0
- data/lib/karafka/web/pro/ui/app.rb +44 -7
- data/lib/karafka/web/pro/ui/controllers/dlq_controller.rb +1 -1
- data/lib/karafka/web/pro/ui/controllers/errors_controller.rb +1 -0
- data/lib/karafka/web/pro/ui/controllers/explorer_controller.rb +6 -14
- data/lib/karafka/web/pro/ui/controllers/messages_controller.rb +5 -4
- data/lib/karafka/web/pro/ui/controllers/search_controller.rb +73 -0
- data/lib/karafka/web/pro/ui/controllers/support_controller.rb +26 -0
- data/lib/karafka/web/pro/ui/controllers/topics_controller.rb +31 -0
- data/lib/karafka/web/pro/ui/controllers/ux_controller.rb +26 -0
- data/lib/karafka/web/pro/ui/lib/policies/config.rb +39 -0
- data/lib/karafka/web/pro/ui/lib/policies/contracts/config.rb +46 -0
- data/lib/karafka/web/pro/ui/lib/policies/messages.rb +76 -0
- data/lib/karafka/web/pro/ui/lib/policies/requests.rb +36 -0
- data/lib/karafka/web/pro/ui/lib/policies.rb +34 -0
- data/lib/karafka/web/pro/ui/lib/safe_runner.rb +98 -0
- data/lib/karafka/web/pro/ui/lib/search/config.rb +53 -0
- data/lib/karafka/web/pro/ui/lib/search/contracts/config.rb +101 -0
- data/lib/karafka/web/pro/ui/lib/search/contracts/form.rb +111 -0
- data/lib/karafka/web/pro/ui/lib/search/matchers/base.rb +59 -0
- data/lib/karafka/web/pro/ui/lib/search/matchers/raw_header_includes.rb +57 -0
- data/lib/karafka/web/pro/ui/lib/search/matchers/raw_key_includes.rb +41 -0
- data/lib/karafka/web/pro/ui/lib/search/matchers/raw_payload_includes.rb +45 -0
- data/lib/karafka/web/pro/ui/lib/search/normalizer.rb +47 -0
- data/lib/karafka/web/pro/ui/lib/search/runner.rb +230 -0
- data/lib/karafka/web/pro/ui/lib/search.rb +36 -0
- data/lib/karafka/web/pro/ui/views/cluster/_breadcrumbs.erb +4 -4
- data/lib/karafka/web/pro/ui/views/cluster/_tabs.erb +14 -24
- data/lib/karafka/web/pro/ui/views/cluster/index.erb +20 -22
- data/lib/karafka/web/pro/ui/views/cluster/show.erb +21 -25
- data/lib/karafka/web/pro/ui/views/commands/_backtrace.erb +4 -19
- data/lib/karafka/web/pro/ui/views/commands/_breadcrumbs.erb +3 -3
- data/lib/karafka/web/pro/ui/views/commands/_command.erb +6 -6
- data/lib/karafka/web/pro/ui/views/commands/_command_details.erb +1 -11
- data/lib/karafka/web/pro/ui/views/commands/_incompatible_schema.erb +3 -14
- data/lib/karafka/web/pro/ui/views/commands/_metadata.erb +33 -42
- data/lib/karafka/web/pro/ui/views/commands/_table.erb +9 -3
- data/lib/karafka/web/pro/ui/views/commands/index.erb +18 -12
- data/lib/karafka/web/pro/ui/views/commands/show.erb +24 -29
- data/lib/karafka/web/pro/ui/views/consumers/_breadcrumbs.erb +8 -8
- data/lib/karafka/web/pro/ui/views/consumers/_consumer.erb +13 -23
- data/lib/karafka/web/pro/ui/views/consumers/_consumer_controls.erb +51 -35
- data/lib/karafka/web/pro/ui/views/consumers/_consumer_performance.erb +1 -1
- data/lib/karafka/web/pro/ui/views/consumers/_tabs.erb +28 -30
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_commands.erb +68 -28
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_job.erb +1 -1
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_metrics.erb +114 -133
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_partition.erb +4 -4
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_stopped.erb +6 -9
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_subscription_group.erb +116 -126
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_tabs.erb +26 -31
- data/lib/karafka/web/pro/ui/views/consumers/controls.erb +53 -57
- data/lib/karafka/web/pro/ui/views/consumers/details.erb +4 -17
- data/lib/karafka/web/pro/ui/views/consumers/index.erb +31 -34
- data/lib/karafka/web/pro/ui/views/consumers/pending_jobs.erb +41 -46
- data/lib/karafka/web/pro/ui/views/consumers/performance.erb +43 -47
- data/lib/karafka/web/pro/ui/views/consumers/running_jobs.erb +41 -46
- data/lib/karafka/web/pro/ui/views/consumers/subscriptions.erb +14 -17
- data/lib/karafka/web/pro/ui/views/dashboard/index.erb +67 -76
- data/lib/karafka/web/pro/ui/views/dlq/_breadcrumbs.erb +1 -1
- data/lib/karafka/web/pro/ui/views/dlq/_no_topics.erb +1 -7
- data/lib/karafka/web/pro/ui/views/dlq/_topic.erb +7 -10
- data/lib/karafka/web/pro/ui/views/dlq/index.erb +8 -10
- data/lib/karafka/web/pro/ui/views/errors/_breadcrumbs.erb +3 -3
- data/lib/karafka/web/pro/ui/views/errors/_error.erb +8 -5
- data/lib/karafka/web/pro/ui/views/errors/_selector.erb +12 -0
- data/lib/karafka/web/pro/ui/views/errors/_table.erb +5 -4
- data/lib/karafka/web/pro/ui/views/errors/index.erb +50 -15
- data/lib/karafka/web/pro/ui/views/errors/partition.erb +61 -14
- data/lib/karafka/web/pro/ui/views/errors/show.erb +28 -46
- data/lib/karafka/web/pro/ui/views/explorer/_breadcrumbs.erb +11 -3
- data/lib/karafka/web/pro/ui/views/explorer/_failed_deserialization.erb +8 -3
- data/lib/karafka/web/pro/ui/views/explorer/_message.erb +12 -6
- data/lib/karafka/web/pro/ui/views/explorer/_no_topics.erb +1 -5
- data/lib/karafka/web/pro/ui/views/explorer/_selector.erb +12 -0
- data/lib/karafka/web/pro/ui/views/explorer/_topic.erb +6 -8
- data/lib/karafka/web/pro/ui/views/explorer/index.erb +13 -15
- data/lib/karafka/web/pro/ui/views/explorer/message/_metadata.erb +68 -32
- data/lib/karafka/web/pro/ui/views/explorer/message/_payload.erb +17 -16
- data/lib/karafka/web/pro/ui/views/explorer/message/_resources_utilization.erb +127 -0
- data/lib/karafka/web/pro/ui/views/explorer/message/_too_big_to_be_displayed.erb +20 -0
- data/lib/karafka/web/pro/ui/views/explorer/messages/_detail.erb +1 -1
- data/lib/karafka/web/pro/ui/views/explorer/partition/_cleaned.erb +3 -5
- data/lib/karafka/web/pro/ui/views/explorer/partition/_empty.erb +3 -5
- data/lib/karafka/web/pro/ui/views/explorer/partition/_messages.erb +6 -3
- data/lib/karafka/web/pro/ui/views/explorer/partition.erb +67 -46
- data/lib/karafka/web/pro/ui/views/explorer/show.erb +85 -21
- data/lib/karafka/web/pro/ui/views/explorer/topic/_actions.erb +27 -0
- data/lib/karafka/web/pro/ui/views/explorer/topic/_empty.erb +3 -5
- data/lib/karafka/web/pro/ui/views/explorer/topic/_limited.erb +8 -10
- data/lib/karafka/web/pro/ui/views/explorer/topic.erb +24 -44
- data/lib/karafka/web/pro/ui/views/health/_breadcrumbs.erb +7 -7
- data/lib/karafka/web/pro/ui/views/health/_no_data.erb +1 -7
- data/lib/karafka/web/pro/ui/views/health/_partition.erb +3 -3
- data/lib/karafka/web/pro/ui/views/health/_partition_lags.erb +3 -3
- data/lib/karafka/web/pro/ui/views/health/_partition_offset.erb +2 -2
- data/lib/karafka/web/pro/ui/views/health/_partition_times.erb +3 -7
- data/lib/karafka/web/pro/ui/views/health/_table_metadata.erb +8 -0
- data/lib/karafka/web/pro/ui/views/health/_tabs.erb +32 -49
- data/lib/karafka/web/pro/ui/views/health/changes.erb +51 -51
- data/lib/karafka/web/pro/ui/views/health/cluster_lags.erb +28 -41
- data/lib/karafka/web/pro/ui/views/health/lags.erb +52 -52
- data/lib/karafka/web/pro/ui/views/health/offsets.erb +55 -55
- data/lib/karafka/web/pro/ui/views/health/overview.erb +60 -60
- data/lib/karafka/web/pro/ui/views/jobs/_job.erb +1 -1
- data/lib/karafka/web/pro/ui/views/jobs/_no_jobs.erb +1 -7
- data/lib/karafka/web/pro/ui/views/jobs/pending.erb +36 -38
- data/lib/karafka/web/pro/ui/views/jobs/running.erb +36 -38
- data/lib/karafka/web/pro/ui/views/routing/_consumer_group.erb +7 -12
- data/lib/karafka/web/pro/ui/views/routing/_topic.erb +13 -11
- data/lib/karafka/web/pro/ui/views/routing/index.erb +7 -9
- data/lib/karafka/web/pro/ui/views/routing/show.erb +41 -33
- data/lib/karafka/web/pro/ui/views/search/_fix_errors.erb +3 -0
- data/lib/karafka/web/pro/ui/views/search/_metadata.erb +71 -0
- data/lib/karafka/web/pro/ui/views/search/_no_results.erb +3 -0
- data/lib/karafka/web/pro/ui/views/search/_no_search_criteria.erb +5 -0
- data/lib/karafka/web/pro/ui/views/search/_search_criteria.erb +37 -0
- data/lib/karafka/web/pro/ui/views/search/_search_modal.erb +139 -0
- data/lib/karafka/web/pro/ui/views/search/_timeout.erb +3 -0
- data/lib/karafka/web/pro/ui/views/search/index.erb +29 -0
- data/lib/karafka/web/pro/ui/views/shared/_navigation.erb +80 -28
- data/lib/karafka/web/pro/ui/views/topics/_breadcrumbs.erb +14 -6
- data/lib/karafka/web/pro/ui/views/topics/_partition_offsets.erb +10 -0
- data/lib/karafka/web/pro/ui/views/topics/_tabs.erb +26 -32
- data/lib/karafka/web/pro/ui/views/topics/_topic.erb +7 -10
- data/lib/karafka/web/pro/ui/views/topics/config.erb +21 -25
- data/lib/karafka/web/pro/ui/views/topics/distribution/_badges.erb +10 -5
- data/lib/karafka/web/pro/ui/views/topics/distribution/_chart.erb +3 -1
- data/lib/karafka/web/pro/ui/views/topics/distribution/_limited.erb +1 -1
- data/lib/karafka/web/pro/ui/views/topics/distribution.erb +34 -39
- data/lib/karafka/web/pro/ui/views/topics/index.erb +13 -15
- data/lib/karafka/web/pro/ui/views/topics/offsets.erb +24 -0
- data/lib/karafka/web/pro/ui/views/topics/replication.erb +20 -24
- data/lib/karafka/web/processing/consumers/aggregators/metrics.rb +1 -1
- data/lib/karafka/web/processing/consumers/aggregators/state.rb +1 -1
- data/lib/karafka/web/processing/consumers/contracts/aggregated_stats.rb +1 -0
- data/lib/karafka/web/tracking/consumers/contracts/report.rb +6 -0
- data/lib/karafka/web/tracking/consumers/listeners/connections.rb +8 -6
- data/lib/karafka/web/tracking/consumers/listeners/processing.rb +2 -0
- data/lib/karafka/web/tracking/consumers/listeners/tags.rb +1 -1
- data/lib/karafka/web/tracking/consumers/reporter.rb +6 -8
- data/lib/karafka/web/tracking/consumers/sampler.rb +16 -5
- data/lib/karafka/web/ui/app.rb +20 -1
- data/lib/karafka/web/ui/base.rb +26 -20
- data/lib/karafka/web/ui/controllers/base_controller.rb +6 -4
- data/lib/karafka/web/ui/controllers/dashboard_controller.rb +8 -0
- data/lib/karafka/web/ui/controllers/requests/params.rb +16 -2
- data/lib/karafka/web/ui/controllers/support_controller.rb +17 -0
- data/lib/karafka/web/ui/controllers/ux_controller.rb +17 -0
- data/lib/karafka/web/ui/helpers/application_helper.rb +75 -42
- data/lib/karafka/web/ui/helpers/paths_helper.rb +24 -0
- data/lib/karafka/web/ui/helpers/tailwind_helper.rb +90 -0
- data/lib/karafka/web/ui/lib/sorter.rb +1 -1
- data/lib/karafka/web/ui/models/metrics/aggregated.rb +1 -0
- data/lib/karafka/web/ui/models/metrics/charts/topics.rb +36 -20
- data/lib/karafka/web/ui/models/status.rb +28 -1
- data/lib/karafka/web/ui/public/images/calendar.svg +3 -0
- data/lib/karafka/web/ui/public/javascripts/application.js +39 -15
- data/lib/karafka/web/ui/public/javascripts/application.min.js +64 -0
- 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/charts/types/line.js +41 -9
- data/lib/karafka/web/ui/public/javascripts/components/btn_toggle_manager.js +37 -0
- data/lib/karafka/web/ui/public/javascripts/{live_poll.js → components/live_poll.js} +44 -8
- data/lib/karafka/web/ui/public/javascripts/{offset_datetime.js → components/offset_datetime.js} +1 -1
- data/lib/karafka/web/ui/public/javascripts/components/search.js +102 -0
- data/lib/karafka/web/ui/public/javascripts/components/tabs_manager.js +84 -0
- data/lib/karafka/web/ui/public/javascripts/components/theme_manager.js +59 -0
- data/lib/karafka/web/ui/public/javascripts/components/turbo_tracker.js +30 -0
- data/lib/karafka/web/ui/public/javascripts/libs/datepicker.js +2 -2
- data/lib/karafka/web/ui/public/javascripts/libs/turbo.js +6618 -0
- data/lib/karafka/web/ui/public/stylesheets/application.css +16 -113
- data/lib/karafka/web/ui/public/stylesheets/application.min.css +13 -0
- 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 +8 -0
- data/lib/karafka/web/ui/public/stylesheets/libs/highlight_dark.min.css.br +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.br +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 +391 -0
- data/lib/karafka/web/ui/views/cluster/_breadcrumbs.erb +3 -3
- data/lib/karafka/web/ui/views/cluster/_tabs.erb +14 -24
- data/lib/karafka/web/ui/views/cluster/brokers.erb +20 -22
- data/lib/karafka/web/ui/views/cluster/replication.erb +28 -32
- data/lib/karafka/web/ui/views/consumers/_assignments_badges.erb +1 -1
- data/lib/karafka/web/ui/views/consumers/_breadcrumbs.erb +5 -0
- data/lib/karafka/web/ui/views/consumers/_consumer.erb +9 -13
- data/lib/karafka/web/ui/views/consumers/_no_consumers.erb +2 -8
- data/lib/karafka/web/ui/views/consumers/_summary.erb +34 -45
- data/lib/karafka/web/ui/views/consumers/_tabs.erb +35 -0
- data/lib/karafka/web/ui/views/consumers/index.erb +31 -33
- data/lib/karafka/web/ui/views/dashboard/_counters.erb +76 -0
- data/lib/karafka/web/ui/views/dashboard/_feature_pro.erb +6 -2
- data/lib/karafka/web/ui/views/dashboard/_not_enough_data.erb +3 -15
- data/lib/karafka/web/ui/views/dashboard/_ranges_selector.erb +12 -12
- data/lib/karafka/web/ui/views/dashboard/index.erb +78 -52
- data/lib/karafka/web/ui/views/errors/_breadcrumbs.erb +2 -2
- data/lib/karafka/web/ui/views/errors/_detail.erb +1 -3
- data/lib/karafka/web/ui/views/errors/_error.erb +3 -5
- data/lib/karafka/web/ui/views/errors/index.erb +34 -44
- data/lib/karafka/web/ui/views/errors/show.erb +29 -47
- data/lib/karafka/web/ui/views/jobs/_breadcrumbs.erb +3 -3
- data/lib/karafka/web/ui/views/jobs/_job.erb +1 -1
- data/lib/karafka/web/ui/views/jobs/_no_jobs.erb +1 -7
- data/lib/karafka/web/ui/views/jobs/_tabs.erb +14 -24
- data/lib/karafka/web/ui/views/jobs/pending.erb +30 -32
- data/lib/karafka/web/ui/views/jobs/running.erb +30 -32
- data/lib/karafka/web/ui/views/layout.erb +37 -21
- data/lib/karafka/web/ui/views/routing/_breadcrumbs.erb +2 -2
- data/lib/karafka/web/ui/views/routing/_consumer_group.erb +7 -12
- data/lib/karafka/web/ui/views/routing/_topic.erb +3 -5
- data/lib/karafka/web/ui/views/routing/index.erb +7 -9
- data/lib/karafka/web/ui/views/routing/show.erb +30 -22
- data/lib/karafka/web/ui/views/shared/_become_pro.erb +8 -8
- data/lib/karafka/web/ui/views/shared/_brand.erb +2 -2
- data/lib/karafka/web/ui/views/shared/_breadcrumbs.erb +23 -0
- data/lib/karafka/web/ui/views/shared/_content.erb +2 -28
- data/lib/karafka/web/ui/views/shared/_controls.erb +15 -0
- data/lib/karafka/web/ui/views/shared/_flashes.erb +5 -7
- data/lib/karafka/web/ui/views/shared/_header.erb +14 -19
- data/lib/karafka/web/ui/views/shared/_navigation.erb +84 -28
- data/lib/karafka/web/ui/views/shared/_no_paginated_data.erb +5 -9
- data/lib/karafka/web/ui/views/shared/_pagination.erb +11 -11
- data/lib/karafka/web/ui/views/shared/_tab_nav.erb +4 -5
- data/lib/karafka/web/ui/views/shared/_title.erb +5 -0
- data/lib/karafka/web/ui/views/shared/alerts/_box_error.erb +15 -0
- data/lib/karafka/web/ui/views/shared/alerts/_box_info.erb +15 -0
- data/lib/karafka/web/ui/views/shared/alerts/_box_primary.erb +15 -0
- data/lib/karafka/web/ui/views/shared/alerts/_box_secondary.erb +15 -0
- data/lib/karafka/web/ui/views/shared/alerts/_box_success.erb +15 -0
- data/lib/karafka/web/ui/views/shared/alerts/_box_warning.erb +15 -0
- data/lib/karafka/web/ui/views/shared/alerts/_error.erb +4 -0
- data/lib/karafka/web/ui/views/shared/alerts/_info.erb +5 -2
- data/lib/karafka/web/ui/views/shared/alerts/_primary.erb +4 -0
- data/lib/karafka/web/ui/views/shared/alerts/_secondary.erb +4 -0
- data/lib/karafka/web/ui/views/shared/alerts/_success.erb +4 -0
- data/lib/karafka/web/ui/views/shared/alerts/_warning.erb +4 -0
- data/lib/karafka/web/ui/views/shared/charts/_line.erb +1 -1
- data/lib/karafka/web/ui/views/shared/exceptions/not_allowed.erb +14 -19
- data/lib/karafka/web/ui/views/shared/exceptions/not_found.erb +16 -21
- data/lib/karafka/web/ui/views/shared/exceptions/pro_only.erb +16 -28
- data/lib/karafka/web/ui/views/shared/icons/_arrow_down_on_square.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_arrow_down_tray.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_arrow_on_squares.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_arrow_path_rounded.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_arrow_uturn_right.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_arrows_right_left.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_blocks.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_book_open.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_bug.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_burger.erb +14 -0
- data/lib/karafka/web/ui/views/shared/icons/_calendar_days.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_chart_bar.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_check_badge.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_check_circle.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_circle_stack.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_cpu.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_document_glass.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_exclamation_triangle.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_eye.erb +4 -0
- data/lib/karafka/web/ui/views/shared/icons/_gear.erb +4 -0
- data/lib/karafka/web/ui/views/shared/icons/_github.erb +13 -0
- data/lib/karafka/web/ui/views/shared/icons/_globe.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_heart.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_home.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_info_circle.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_lifebuoy.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_light_bulb.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_list_bullets.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_magnifying_glass.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_moon.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_offices.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_pause.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_pause_circle.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_play_circle.erb +4 -0
- data/lib/karafka/web/ui/views/shared/icons/_question_circle.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_queue_list.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_refresh.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_slack.erb +16 -0
- data/lib/karafka/web/ui/views/shared/icons/_stop.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_sun.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_x_circle.erb +3 -0
- data/lib/karafka/web/ui/views/shared/icons/_x_mark.erb +3 -0
- data/lib/karafka/web/ui/views/status/_breadcrumbs.erb +1 -1
- data/lib/karafka/web/ui/views/status/_failure.erb +2 -13
- data/lib/karafka/web/ui/views/status/_halted.erb +2 -10
- data/lib/karafka/web/ui/views/status/_info.erb +2 -13
- data/lib/karafka/web/ui/views/status/_success.erb +2 -10
- data/lib/karafka/web/ui/views/status/_warning.erb +2 -13
- data/lib/karafka/web/ui/views/status/failures/_connection.erb +2 -2
- data/lib/karafka/web/ui/views/status/failures/_consumers_reports.erb +3 -3
- data/lib/karafka/web/ui/views/status/failures/_consumers_reports_schema_state.erb +4 -4
- data/lib/karafka/web/ui/views/status/failures/_enabled.erb +2 -2
- data/lib/karafka/web/ui/views/status/failures/_initial_consumers_metrics.erb +6 -6
- data/lib/karafka/web/ui/views/status/failures/_initial_consumers_state.erb +6 -6
- data/lib/karafka/web/ui/views/status/failures/_live_reporting.erb +2 -2
- data/lib/karafka/web/ui/views/status/failures/_materializing_lag.erb +11 -0
- 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/failures/_topics.erb +3 -3
- data/lib/karafka/web/ui/views/status/info/_components.erb +14 -41
- data/lib/karafka/web/ui/views/status/show.erb +165 -154
- data/lib/karafka/web/ui/views/status/warnings/_connection.erb +3 -3
- data/lib/karafka/web/ui/views/status/warnings/_pro_subscription.erb +2 -2
- data/lib/karafka/web/ui/views/status/warnings/_replication.erb +2 -2
- data/lib/karafka/web/ui/views/status/warnings/_routing_topics_presence.erb +1 -1
- data/lib/karafka/web/ui/views/support/_breadcrumbs.erb +5 -0
- data/lib/karafka/web/ui/views/support/show.erb +71 -0
- data/lib/karafka/web/ui/views/ux/_alerts.erb +25 -0
- data/lib/karafka/web/ui/views/ux/_badges.erb +21 -0
- data/lib/karafka/web/ui/views/ux/_breadcrumbs.erb +5 -0
- data/lib/karafka/web/ui/views/ux/_buttons.erb +47 -0
- data/lib/karafka/web/ui/views/ux/_card_detail.erb +15 -0
- data/lib/karafka/web/ui/views/ux/_card_metric.erb +123 -0
- data/lib/karafka/web/ui/views/ux/_card_summary.erb +72 -0
- data/lib/karafka/web/ui/views/ux/_card_support.erb +39 -0
- data/lib/karafka/web/ui/views/ux/_code.erb +9 -0
- data/lib/karafka/web/ui/views/ux/_data_table.erb +52 -0
- data/lib/karafka/web/ui/views/ux/_headers.erb +2 -0
- data/lib/karafka/web/ui/views/ux/_icons.erb +9 -0
- data/lib/karafka/web/ui/views/ux/_pagination.erb +32 -0
- data/lib/karafka/web/ui/views/ux/_row_table.erb +52 -0
- data/lib/karafka/web/ui/views/ux/_status_rows.erb +53 -0
- data/lib/karafka/web/ui/views/ux/_tabs.erb +14 -0
- data/lib/karafka/web/ui/views/ux/_text.erb +2 -0
- data/lib/karafka/web/ui/views/ux/_topic_tiles.erb +42 -0
- data/lib/karafka/web/ui/views/ux/show.erb +19 -0
- data/lib/karafka/web/version.rb +1 -1
- data/lib/karafka/web.rb +2 -0
- data/package-lock.json +4158 -0
- data/package.json +15 -0
- data/postcss.config.js +6 -0
- data/tailwind.config.js +16 -0
- data.tar.gz.sig +4 -0
- metadata +203 -51
- metadata.gz.sig +0 -0
- data/lib/karafka/web/management/migrations/0_set_initial_consumers_metrics.rb +0 -36
- data/lib/karafka/web/management/migrations/0_set_initial_consumers_state.rb +0 -43
- data/lib/karafka/web/management/migrations/1699543515_fill_missing_received_and_sent_bytes_in_consumers_metrics.rb +0 -26
- data/lib/karafka/web/management/migrations/1699543515_fill_missing_received_and_sent_bytes_in_consumers_state.rb +0 -23
- data/lib/karafka/web/management/migrations/1700234522_introduce_waiting_in_consumers_metrics.rb +0 -24
- data/lib/karafka/web/management/migrations/1700234522_introduce_waiting_in_consumers_state.rb +0 -20
- data/lib/karafka/web/management/migrations/1700234522_remove_processing_from_consumers_metrics.rb +0 -24
- data/lib/karafka/web/management/migrations/1700234522_remove_processing_from_consumers_state.rb +0 -20
- data/lib/karafka/web/management/migrations/1704722380_split_listeners_into_active_and_paused_in_metrics.rb +0 -36
- data/lib/karafka/web/management/migrations/1704722380_split_listeners_into_active_and_paused_in_states.rb +0 -32
- data/lib/karafka/web/management/migrations/1706607960_introduce_lag_total_in_metrics.rb +0 -38
- data/lib/karafka/web/management/migrations/1706607960_introduce_lag_total_in_states.rb +0 -22
- data/lib/karafka/web/management/migrations/1706611396_rename_lag_total_to_lag_hybrid_in_metrics.rb +0 -36
- data/lib/karafka/web/management/migrations/1706611396_rename_lag_total_to_lag_hybrid_in_states.rb +0 -21
- data/lib/karafka/web/pro/ui/views/cluster/brokers.erb +0 -27
- data/lib/karafka/web/pro/ui/views/commands/_details.erb +0 -26
- data/lib/karafka/web/pro/ui/views/consumers/_counters.erb +0 -72
- data/lib/karafka/web/pro/ui/views/consumers/consumer/_title.erb +0 -5
- data/lib/karafka/web/pro/ui/views/errors/_title_with_select.erb +0 -31
- data/lib/karafka/web/pro/ui/views/explorer/message/_message_actions.erb +0 -18
- data/lib/karafka/web/pro/ui/views/explorer/message/_payload_actions.erb +0 -19
- data/lib/karafka/web/pro/ui/views/explorer/partition/_details.erb +0 -35
- data/lib/karafka/web/pro/ui/views/explorer/topic/_details.erb +0 -23
- data/lib/karafka/web/pro/ui/views/health/_consumer_group_header.erb +0 -14
- data/lib/karafka/web/ui/controllers/responses/deny.rb +0 -15
- data/lib/karafka/web/ui/helpers/alerts_helper.rb +0 -23
- data/lib/karafka/web/ui/lib/safe_runner.rb +0 -59
- data/lib/karafka/web/ui/models/visibility_filter.rb +0 -49
- data/lib/karafka/web/ui/public/javascripts/libs/bootstrap.min.js +0 -6
- data/lib/karafka/web/ui/public/javascripts/tabs_manager.js +0 -57
- data/lib/karafka/web/ui/public/stylesheets/libs/bootstrap.min.css +0 -6
- data/lib/karafka/web/ui/views/consumers/_counters.erb +0 -62
- data/lib/karafka/web/ui/views/errors/_watermark_offsets.erb +0 -10
- data/lib/karafka/web/ui/views/shared/_feature_pro.erb +0 -4
- data/lib/karafka/web/ui/views/shared/_footer.erb +0 -22
- data/lib/karafka/web/ui/views/shared/_live_poll.erb +0 -7
- /data/lib/karafka/web/management/migrations/{0_base.rb → base.rb} +0 -0
- /data/lib/karafka/web/ui/public/javascripts/{charts.js → components/charts.js} +0 -0
- /data/lib/karafka/web/ui/public/stylesheets/libs/{highlight.min.css → highlight_light.min.css} +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Karafka
|
|
4
|
+
module Web
|
|
5
|
+
module Pro
|
|
6
|
+
module Ui
|
|
7
|
+
module Lib
|
|
8
|
+
# Class used to execute code that can fail but we do not want to fail the whole
|
|
9
|
+
# operation. The primary use-case is for displaying deserialized data. We always need to
|
|
10
|
+
# assume, that part of the data can be corrupted and it should not crash the whole UI.
|
|
11
|
+
#
|
|
12
|
+
# It caches the result and does not run the code twice (only once). Additionally, it
|
|
13
|
+
# measures the CPU usage and total time during the execution of the code block.
|
|
14
|
+
class SafeRunner
|
|
15
|
+
include Karafka::Core::Helpers::Time
|
|
16
|
+
|
|
17
|
+
attr_reader :error, :result, :cpu_time, :total_time, :allocations
|
|
18
|
+
|
|
19
|
+
# @param block [Proc] code we want to safe-guard
|
|
20
|
+
def initialize(&block)
|
|
21
|
+
@code = block
|
|
22
|
+
@executed = false
|
|
23
|
+
@success = false
|
|
24
|
+
@error = nil
|
|
25
|
+
@result = nil
|
|
26
|
+
@cpu_time = 0
|
|
27
|
+
@total_time = 0
|
|
28
|
+
@allocations = false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [Boolean] was the code execution successful or not
|
|
32
|
+
def success?
|
|
33
|
+
return @success if executed?
|
|
34
|
+
|
|
35
|
+
call
|
|
36
|
+
|
|
37
|
+
@success
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [Boolean] was the code execution failed or not
|
|
41
|
+
def failure?
|
|
42
|
+
!success?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Runs the execution and returns block result
|
|
46
|
+
def call
|
|
47
|
+
return @result if executed?
|
|
48
|
+
|
|
49
|
+
@executed = true
|
|
50
|
+
|
|
51
|
+
if objspace?
|
|
52
|
+
ObjectSpace.trace_object_allocations_start
|
|
53
|
+
before = ObjectSpace.each_object.count
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# We measure time as close to the process as possible so it is not impacted by the
|
|
57
|
+
# objects allocations count (if applicable)
|
|
58
|
+
start_time = monotonic_now
|
|
59
|
+
start_cpu = ::Process.times
|
|
60
|
+
@result = @code.call
|
|
61
|
+
@success = true
|
|
62
|
+
|
|
63
|
+
@result
|
|
64
|
+
rescue StandardError => e
|
|
65
|
+
@error = e
|
|
66
|
+
@success = false
|
|
67
|
+
ensure
|
|
68
|
+
end_time = monotonic_now
|
|
69
|
+
end_cpu = ::Process.times
|
|
70
|
+
|
|
71
|
+
@cpu_time = (
|
|
72
|
+
(end_cpu.utime - start_cpu.utime) + (end_cpu.stime - start_cpu.stime)
|
|
73
|
+
) * 1_000
|
|
74
|
+
@total_time = (end_time - start_time)
|
|
75
|
+
|
|
76
|
+
if objspace?
|
|
77
|
+
@allocations = ObjectSpace.each_object.count - before
|
|
78
|
+
ObjectSpace.trace_object_allocations_stop
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# @return [Boolean] was the code executed already or not yet
|
|
83
|
+
def executed?
|
|
84
|
+
@executed
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
# @return [Boolean] true if tracing is available
|
|
90
|
+
def objspace?
|
|
91
|
+
ObjectSpace.respond_to?(:trace_object_allocations_start)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
|
5
|
+
#
|
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
|
7
|
+
# repository and their usage requires commercial license agreement.
|
|
8
|
+
#
|
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
|
10
|
+
#
|
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
|
12
|
+
# your code to Maciej Mensfeld.
|
|
13
|
+
|
|
14
|
+
module Karafka
|
|
15
|
+
module Web
|
|
16
|
+
module Pro
|
|
17
|
+
module Ui
|
|
18
|
+
module Lib
|
|
19
|
+
module Search
|
|
20
|
+
# Extra configuration for pro UI
|
|
21
|
+
class Config
|
|
22
|
+
extend ::Karafka::Core::Configurable
|
|
23
|
+
|
|
24
|
+
# Matches for messages
|
|
25
|
+
setting :matchers, default: [
|
|
26
|
+
Matchers::RawPayloadIncludes,
|
|
27
|
+
Matchers::RawKeyIncludes,
|
|
28
|
+
Matchers::RawHeaderIncludes
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
# How long should we at most search before stopping (in ms)
|
|
32
|
+
# This prevents us from having a search that would basically hang the browser and
|
|
33
|
+
# never finish
|
|
34
|
+
setting :timeout, default: 30_000
|
|
35
|
+
|
|
36
|
+
# Search limits as the search runs in Puma
|
|
37
|
+
# Too big value will make the scan really slow
|
|
38
|
+
# We do not put a max limit here because those values are used in a select in
|
|
39
|
+
# the Web UI.
|
|
40
|
+
setting :limits, default: [
|
|
41
|
+
1_000,
|
|
42
|
+
10_000,
|
|
43
|
+
100_000
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
configure
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
|
5
|
+
#
|
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
|
7
|
+
# repository and their usage requires commercial license agreement.
|
|
8
|
+
#
|
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
|
10
|
+
#
|
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
|
12
|
+
# your code to Maciej Mensfeld.
|
|
13
|
+
|
|
14
|
+
module Karafka
|
|
15
|
+
module Web
|
|
16
|
+
module Pro
|
|
17
|
+
module Ui
|
|
18
|
+
module Lib
|
|
19
|
+
# Search related contracts
|
|
20
|
+
module Search
|
|
21
|
+
# Namespace with search related contracts
|
|
22
|
+
module Contracts
|
|
23
|
+
# Makes sure, all the expected UI search config is defined as it should be
|
|
24
|
+
class Config < ::Karafka::Contracts::Base
|
|
25
|
+
configure do |config|
|
|
26
|
+
config.error_messages = YAML.safe_load(
|
|
27
|
+
File.read(
|
|
28
|
+
File.join(Karafka::Web.gem_root, 'config', 'locales', 'pro_errors.yml')
|
|
29
|
+
)
|
|
30
|
+
).fetch('en').fetch('validations').fetch('config')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
nested(:ui) do
|
|
34
|
+
nested(:search) do
|
|
35
|
+
required(:matchers) { |val| val.is_a?(Array) && !val.empty? }
|
|
36
|
+
|
|
37
|
+
required(:timeout) { |val| val.is_a?(Integer) && val.positive? }
|
|
38
|
+
|
|
39
|
+
# Users can define their own search limits and we just make sure they do not
|
|
40
|
+
# do something weird like negative numbers
|
|
41
|
+
required(:limits) do |val|
|
|
42
|
+
next false unless val.is_a?(Array)
|
|
43
|
+
next false if val.empty?
|
|
44
|
+
next false unless val.all? { |count| count.is_a?(Integer) }
|
|
45
|
+
next false unless val.all?(&:positive?)
|
|
46
|
+
|
|
47
|
+
true
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Ensure all matchers respond to name and are callable
|
|
53
|
+
virtual do |data, errors|
|
|
54
|
+
next unless errors.empty?
|
|
55
|
+
|
|
56
|
+
detected_errors = []
|
|
57
|
+
|
|
58
|
+
data.dig(:ui, :search, :matchers).each do |matcher|
|
|
59
|
+
next if matcher.respond_to?(:name) && matcher.public_method_defined?(:call)
|
|
60
|
+
|
|
61
|
+
detected_errors << [%i[ui search matchers], :must_have_name_and_call]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
detected_errors
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Make sure that all matchers names are unique
|
|
68
|
+
virtual do |data, errors|
|
|
69
|
+
next unless errors.empty?
|
|
70
|
+
|
|
71
|
+
names = data.dig(:ui, :search, :matchers).map(&:name)
|
|
72
|
+
|
|
73
|
+
next if names.uniq.size == names.size
|
|
74
|
+
|
|
75
|
+
[[%i[ui search matchers], :must_have_unique_names]]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Make sure that all matchers names are strings and not empty
|
|
79
|
+
virtual do |data, errors|
|
|
80
|
+
next unless errors.empty?
|
|
81
|
+
|
|
82
|
+
detected_errors = []
|
|
83
|
+
|
|
84
|
+
data.dig(:ui, :search, :matchers).map(&:name).each do |name|
|
|
85
|
+
next if name.is_a?(String) && !name.empty?
|
|
86
|
+
|
|
87
|
+
detected_errors << [%i[ui search matchers], :name_must_be_valid]
|
|
88
|
+
|
|
89
|
+
break
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
detected_errors
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
|
5
|
+
#
|
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
|
7
|
+
# repository and their usage requires commercial license agreement.
|
|
8
|
+
#
|
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
|
10
|
+
#
|
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
|
12
|
+
# your code to Maciej Mensfeld.
|
|
13
|
+
|
|
14
|
+
module Karafka
|
|
15
|
+
module Web
|
|
16
|
+
module Pro
|
|
17
|
+
module Ui
|
|
18
|
+
module Lib
|
|
19
|
+
module Search
|
|
20
|
+
module Contracts
|
|
21
|
+
# Validates the search input
|
|
22
|
+
# This is not a complex validator with error handling, etc
|
|
23
|
+
# Since we use HTML5 validations that are good enough, here we check all the
|
|
24
|
+
# consistency of the data but without providing sophisticated user error reporting as
|
|
25
|
+
# it is the final checking that should not happen often.
|
|
26
|
+
#
|
|
27
|
+
# @note This does not validate the raw input from the HTML but one that was slightly
|
|
28
|
+
# normalized to simplify the flow.
|
|
29
|
+
class Form < Web::Contracts::Base
|
|
30
|
+
configure do |config|
|
|
31
|
+
config.error_messages = YAML.safe_load(
|
|
32
|
+
File.read(
|
|
33
|
+
File.join(Karafka::Web.gem_root, 'config', 'locales', 'pro_errors.yml')
|
|
34
|
+
)
|
|
35
|
+
).fetch('en').fetch('validations').fetch('search_form')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Minimum timestamp value when timestamps are used
|
|
39
|
+
# 2001-09-09. This value selected because it is older than Kafka and it looks nice
|
|
40
|
+
MIN_TIMESTAMP = 1_000_000_000
|
|
41
|
+
|
|
42
|
+
private_constant :MIN_TIMESTAMP
|
|
43
|
+
|
|
44
|
+
# What are we looking for
|
|
45
|
+
required(:phrase) { |val| val.is_a?(String) && !val.empty? }
|
|
46
|
+
|
|
47
|
+
# How many messages in total should we scan. In case of many partitions, this is
|
|
48
|
+
# distributed evenly across them. So 100 000 in 5 partitions, means scanning
|
|
49
|
+
# 20 000 per partition.
|
|
50
|
+
required(:limit) do |val|
|
|
51
|
+
Web.config.ui.search.limits.include?(val)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# What matcher should we use when matching phrase and message
|
|
55
|
+
# It allows only matchers that we have declared in search
|
|
56
|
+
required(:matcher) do |val|
|
|
57
|
+
Web.config.ui.search.matchers.map(&:name).include?(val)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Where should we start looking in the data
|
|
61
|
+
# - latest means we move back the needed per partition number of messages and we look
|
|
62
|
+
# - offset means we start from the same offset on all the partitions
|
|
63
|
+
# - timestamp means we start from a given time moment on all the partitions
|
|
64
|
+
required(:offset_type) { |val| %w[latest offset timestamp].include?(val) }
|
|
65
|
+
|
|
66
|
+
# Offset from which to start. We can always require it even if we do not start from
|
|
67
|
+
# a certain offset because we work on a normalized data
|
|
68
|
+
required(:offset) { |val| val.is_a?(Integer) && val >= 0 }
|
|
69
|
+
|
|
70
|
+
# Similar as above but for timestamp.
|
|
71
|
+
required(:timestamp) do |val|
|
|
72
|
+
next false unless val.is_a?(Integer)
|
|
73
|
+
next false if val.negative?
|
|
74
|
+
next false if val > ((Time.now.to_f + 60) * 1_000).to_i
|
|
75
|
+
|
|
76
|
+
true
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# We do not check here that partitions actually exist because when searching we just
|
|
80
|
+
# reject non-existing partitions
|
|
81
|
+
required(:partitions) do |val|
|
|
82
|
+
next false unless val.is_a?(Array)
|
|
83
|
+
next false if val.empty?
|
|
84
|
+
|
|
85
|
+
val.all? { |ar_val| ar_val.is_a?(String) }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Special validation for timestamp to make sure it is not older than 2010
|
|
89
|
+
# Since Kafka is not that old, timestamps should never be less than that.
|
|
90
|
+
# While all the others will use standard "is invalid" because they also have a
|
|
91
|
+
# frontend HTML5 validation. This one is specific because we want to allow setting
|
|
92
|
+
# 0 as long as we don't select the timestamp as a value. Then we want to make sure
|
|
93
|
+
# that user provides the message timestamp which is in ms
|
|
94
|
+
virtual do |data, errors|
|
|
95
|
+
next unless errors.empty?
|
|
96
|
+
# Validate only if we decide to go with timestamp. Otherwise this value is
|
|
97
|
+
# irrelevant
|
|
98
|
+
next unless data[:offset_type] == 'timestamp'
|
|
99
|
+
|
|
100
|
+
next if data[:timestamp] >= MIN_TIMESTAMP
|
|
101
|
+
|
|
102
|
+
[[%i[timestamp], :key_must_be_large_enough]]
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
|
5
|
+
#
|
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
|
7
|
+
# repository and their usage requires commercial license agreement.
|
|
8
|
+
#
|
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
|
10
|
+
#
|
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
|
12
|
+
# your code to Maciej Mensfeld.
|
|
13
|
+
|
|
14
|
+
module Karafka
|
|
15
|
+
module Web
|
|
16
|
+
module Pro
|
|
17
|
+
module Ui
|
|
18
|
+
module Lib
|
|
19
|
+
module Search
|
|
20
|
+
# Namespace for search matchers
|
|
21
|
+
# Matcher is what "searches" a message or its parts for a given phrase
|
|
22
|
+
module Matchers
|
|
23
|
+
# Base class for all the search matchers
|
|
24
|
+
# Each matcher needs to have a class `#name` method and needs to respond to `#call`
|
|
25
|
+
class Base
|
|
26
|
+
# @param phrase [String] string phrase for search
|
|
27
|
+
# @param message [Karafka::Messages::Message] message in which we search
|
|
28
|
+
# @return [Boolean] true if found, otherwise false
|
|
29
|
+
def call(phrase, message)
|
|
30
|
+
raise NotImplementedError, 'Implement in a subclass'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class << self
|
|
34
|
+
# @return [String] name of the matcher based on the class name
|
|
35
|
+
def name
|
|
36
|
+
# Insert a space before each uppercase letter, except the first one
|
|
37
|
+
spaced_string = to_s.split('::').last.gsub(/(?<!^)([A-Z])/, ' \1')
|
|
38
|
+
|
|
39
|
+
# Convert the first letter to uppercase and the rest to lowercase
|
|
40
|
+
spaced_string[0].upcase + spaced_string[1..].downcase
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Allows to disable/enable certain matches that may be specific to certain types
|
|
44
|
+
# of data per topic. By default matchers are always active
|
|
45
|
+
#
|
|
46
|
+
# @param _topic_name [String] name of the topic in the explorer
|
|
47
|
+
# @return [Boolean] should this matcher be active in the given topic
|
|
48
|
+
def active?(_topic_name)
|
|
49
|
+
true
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
|
5
|
+
#
|
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
|
7
|
+
# repository and their usage requires commercial license agreement.
|
|
8
|
+
#
|
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
|
10
|
+
#
|
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
|
12
|
+
# your code to Maciej Mensfeld.
|
|
13
|
+
|
|
14
|
+
module Karafka
|
|
15
|
+
module Web
|
|
16
|
+
module Pro
|
|
17
|
+
module Ui
|
|
18
|
+
module Lib
|
|
19
|
+
module Search
|
|
20
|
+
module Matchers
|
|
21
|
+
# Matcher that searches in the raw headers. If any header key or value matches
|
|
22
|
+
# the phrase, it is true. Otherwise false.
|
|
23
|
+
#
|
|
24
|
+
# @note It is case sensitive
|
|
25
|
+
# @note Ignores encoding issues
|
|
26
|
+
class RawHeaderIncludes < Base
|
|
27
|
+
# @param message [Karafka::Messages::Message]
|
|
28
|
+
# @param phrase [String]
|
|
29
|
+
# @return [Boolean] does message raw headers contain the phrase
|
|
30
|
+
def call(message, phrase)
|
|
31
|
+
message.raw_headers.each do |raw_header_key, raw_header_value|
|
|
32
|
+
return true if safe_include?(raw_header_key, phrase)
|
|
33
|
+
return true if safe_include?(raw_header_value, phrase)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# Checks the inclusion ignoring encoding issues
|
|
42
|
+
# @param string [String] String in which we look
|
|
43
|
+
# @param phrase [String] string for which we look
|
|
44
|
+
# @return [Boolean] true if found, otherwise false
|
|
45
|
+
def safe_include?(string, phrase)
|
|
46
|
+
string.include?(phrase)
|
|
47
|
+
rescue Encoding::CompatibilityError
|
|
48
|
+
false
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
|
5
|
+
#
|
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
|
7
|
+
# repository and their usage requires commercial license agreement.
|
|
8
|
+
#
|
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
|
10
|
+
#
|
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
|
12
|
+
# your code to Maciej Mensfeld.
|
|
13
|
+
|
|
14
|
+
module Karafka
|
|
15
|
+
module Web
|
|
16
|
+
module Pro
|
|
17
|
+
module Ui
|
|
18
|
+
module Lib
|
|
19
|
+
module Search
|
|
20
|
+
module Matchers
|
|
21
|
+
# Checks if the key contains requested phrase
|
|
22
|
+
#
|
|
23
|
+
# @note It is case sensitive
|
|
24
|
+
# @note Ignores encoding issues
|
|
25
|
+
class RawKeyIncludes < Base
|
|
26
|
+
# @param message [Karafka::Messages::Message]
|
|
27
|
+
# @param phrase [String]
|
|
28
|
+
# @return [Boolean] does message raw key contain the phrase
|
|
29
|
+
def call(message, phrase)
|
|
30
|
+
message.raw_key.to_s.include?(phrase)
|
|
31
|
+
rescue Encoding::CompatibilityError
|
|
32
|
+
false
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
|
5
|
+
#
|
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
|
7
|
+
# repository and their usage requires commercial license agreement.
|
|
8
|
+
#
|
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
|
10
|
+
#
|
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
|
12
|
+
# your code to Maciej Mensfeld.
|
|
13
|
+
|
|
14
|
+
module Karafka
|
|
15
|
+
module Web
|
|
16
|
+
module Pro
|
|
17
|
+
module Ui
|
|
18
|
+
module Lib
|
|
19
|
+
module Search
|
|
20
|
+
module Matchers
|
|
21
|
+
# Checks for phrase existence in the raw payload
|
|
22
|
+
#
|
|
23
|
+
# @note It is case sensitive
|
|
24
|
+
# @note Ignores encoding issues
|
|
25
|
+
class RawPayloadIncludes < Base
|
|
26
|
+
# @param message [Karafka::Messages::Message]
|
|
27
|
+
# @param phrase [String]
|
|
28
|
+
# @return [Boolean] does message raw payload contain the phrase
|
|
29
|
+
def call(message, phrase)
|
|
30
|
+
# raw payload can be nil for tombstone events
|
|
31
|
+
return false unless message.raw_payload
|
|
32
|
+
|
|
33
|
+
message.raw_payload.include?(phrase)
|
|
34
|
+
# String matching on compressed data may fail
|
|
35
|
+
rescue Encoding::CompatibilityError
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This Karafka component is a Pro component under a commercial license.
|
|
4
|
+
# This Karafka component is NOT licensed under LGPL.
|
|
5
|
+
#
|
|
6
|
+
# All of the commercial components are present in the lib/karafka/pro directory of this
|
|
7
|
+
# repository and their usage requires commercial license agreement.
|
|
8
|
+
#
|
|
9
|
+
# Karafka has also commercial-friendly license, commercial support and commercial components.
|
|
10
|
+
#
|
|
11
|
+
# By sending a pull request to the pro components, you are agreeing to transfer the copyright of
|
|
12
|
+
# your code to Maciej Mensfeld.
|
|
13
|
+
|
|
14
|
+
module Karafka
|
|
15
|
+
module Web
|
|
16
|
+
module Pro
|
|
17
|
+
module Ui
|
|
18
|
+
module Lib
|
|
19
|
+
module Search
|
|
20
|
+
# Takes basic search parameters and normalizes the data a bit
|
|
21
|
+
# Since we have fairly simple search input argument types, we can cast them easily
|
|
22
|
+
# into format that we can accept further down the pipeline.
|
|
23
|
+
# This module provides this normalization, so we do not have to worry about weird
|
|
24
|
+
# edge cases.
|
|
25
|
+
module Normalizer
|
|
26
|
+
class << self
|
|
27
|
+
# @param search_query [Hash] hash with expected data
|
|
28
|
+
# @return [Hash] normalized search query hash
|
|
29
|
+
def call(search_query)
|
|
30
|
+
{
|
|
31
|
+
phrase: search_query['phrase'].to_s,
|
|
32
|
+
limit: search_query['limit'].to_i,
|
|
33
|
+
matcher: search_query['matcher'].to_s,
|
|
34
|
+
partitions: Array(search_query['partitions']).flatten.compact.uniq,
|
|
35
|
+
offset_type: search_query['offset_type'].to_s,
|
|
36
|
+
timestamp: search_query['timestamp'].to_i,
|
|
37
|
+
offset: search_query['offset'].to_i
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|