├── .devcontainer.json ├── .github └── workflows │ ├── build_base_docker.yml │ ├── build_package.yml │ ├── codeql.yml │ ├── format_check.yml │ ├── python_file_header_check.yml │ ├── test_command_scene_configHelper.yml │ ├── test_sql_rule.yml │ ├── test_ssh_client.yml │ └── translate.yml ├── .gitignore ├── .secignore ├── Dockerfile.dev ├── Dockerfile.helper ├── LEGAL.md ├── LICENSE ├── README-CN.md ├── README.md ├── build_update_package.sh ├── conf └── inner_config.yml ├── dev_helper.sh ├── example ├── all-components-with-oms.yml ├── all-components.yaml ├── docker_ob_cluster.yml ├── mini.yml ├── ob_cluster.yml ├── obproxy.yml └── operator.yml ├── images ├── obdiag_cn.png ├── obdiag_en.png └── structure.png ├── plugins ├── check │ ├── obproxy_check_package.yaml │ ├── observer_check_package.yaml │ └── tasks │ │ ├── obproxy │ │ ├── parameter │ │ │ └── request_buffer_length.yaml │ │ └── version │ │ │ ├── bad_version.yaml │ │ │ └── old_version.yaml │ │ └── observer │ │ ├── bugs │ │ ├── bug_182.yaml │ │ ├── bug_385.yaml │ │ ├── bug_469.yaml │ │ └── cgroup_kernel_bad_version.py │ │ ├── clog │ │ └── clog_disk_full.yaml │ │ ├── cluster │ │ ├── auto_increment_cache_size.py │ │ ├── autoinc_cache_refresh_interval.py │ │ ├── cgroup.py │ │ ├── clog_sync_time_warn_threshold.py │ │ ├── core_file_find.yaml │ │ ├── cpu_quota_concurrency.py │ │ ├── data_path_settings.yaml │ │ ├── datafile_next.yaml │ │ ├── deadlocks.yaml │ │ ├── default_compress_func.py │ │ ├── enable_lock_priority.py │ │ ├── freeze_trigger_percentage.py │ │ ├── global_indexes_too_much.yaml │ │ ├── large_query_threshold.py │ │ ├── ls_nu.yaml │ │ ├── major.yaml │ │ ├── memory_chunk_cache_size.py │ │ ├── memory_limit_percentage.py │ │ ├── memstore_limit_percentage.py │ │ ├── mod_too_large.yaml │ │ ├── no_leader.yaml │ │ ├── ob_enable_plan_cache_bad_version.yaml │ │ ├── ob_enable_prepared_statement.py │ │ ├── observer_not_active.yaml │ │ ├── observer_port.py │ │ ├── optimizer_better_inlist_costing_parmmeter.yaml │ │ ├── part_trans_action_max.yaml │ │ ├── resource_limit_max_session_num.yaml │ │ ├── server_permanent_offline_time.py │ │ ├── sys_log_level.yaml │ │ ├── sys_obcon_health.py │ │ ├── syslog_io_bandwidth_limit.py │ │ ├── table_history_too_many.yaml │ │ ├── task_opt_stat.yaml │ │ ├── task_opt_stat_gather_fail.yaml │ │ ├── tenant_number.yaml │ │ ├── trace_log_slow_query_watermark.py │ │ ├── upgrade_finished.py │ │ ├── upper_trans_version.py │ │ └── zone_not_active.yaml │ │ ├── column_storage │ │ └── tenant_parameters.yaml │ │ ├── cpu │ │ └── oversold.yaml │ │ ├── disk │ │ ├── clog_abnormal_file.yaml │ │ ├── disk_full.yaml │ │ ├── disk_hole.yaml │ │ ├── disk_iops.yaml │ │ ├── mount_disk_full.py │ │ ├── sstable_abnormal_file.yaml │ │ └── xfs_repair.yaml │ │ ├── err_code │ │ ├── find_err_4000.yaml │ │ ├── find_err_4001.yaml │ │ ├── find_err_4012.yaml │ │ ├── find_err_4013.yaml │ │ ├── find_err_4015.yaml │ │ ├── find_err_4016.yaml │ │ ├── find_err_4103.yaml │ │ ├── find_err_4105.yaml │ │ ├── find_err_4108.yaml │ │ └── find_err_4377.yaml │ │ ├── log │ │ ├── log_size.py │ │ └── log_size_with_ocp.yaml │ │ ├── network │ │ ├── TCP-retransmission.yaml │ │ ├── network_drop.yaml │ │ ├── network_offset.yaml │ │ └── network_speed.yaml │ │ ├── sysbench │ │ ├── sysbench_free_test_cpu_count.yaml │ │ ├── sysbench_free_test_memory_limit.yaml │ │ ├── sysbench_free_test_network_speed.yaml │ │ ├── sysbench_run_test_tenant_cpu_used.yaml │ │ ├── sysbench_run_test_tenant_memory_used.yaml │ │ ├── sysbench_test_cluster_datafile_size.yaml │ │ ├── sysbench_test_cluster_log_disk_size.yaml │ │ ├── sysbench_test_cluster_parameters.yaml │ │ ├── sysbench_test_cpu_quota_concurrency.yaml │ │ ├── sysbench_test_log_level.yaml │ │ ├── sysbench_test_sql_net_thread_count.yaml │ │ ├── sysbench_test_tenant_cpu_parameters.yaml │ │ ├── sysbench_test_tenant_log_disk_size.yaml │ │ └── sysbench_test_tenant_primary_zone.yaml │ │ ├── system │ │ ├── aio.yaml │ │ ├── arm_smmu.yaml │ │ ├── check_command.py │ │ ├── clock_source.yaml │ │ ├── clock_source_check.py │ │ ├── core_pattern.yaml │ │ ├── dependent_software.yaml │ │ ├── dependent_software_swapon.yaml │ │ ├── dmesg_log.py │ │ ├── getenforce.yaml │ │ ├── instruction_set_avx.yaml │ │ ├── instruction_set_avx2.yaml │ │ ├── kernel_bad_version.py │ │ ├── mount_options.py │ │ ├── parameter.yaml │ │ ├── parameter_ip_local_port_range.yaml │ │ ├── parameter_tcp_rmem.yaml │ │ ├── parameter_tcp_wmem.yaml │ │ ├── python_version.py │ │ ├── tcp_tw_reuse.py │ │ └── ulimit_parameter.yaml │ │ ├── table │ │ ├── information_schema_tables_two_data.yaml │ │ └── macroblock_utilization_rate_table.py │ │ ├── tenant │ │ ├── macroblock_utilization_rate_tenant.py │ │ ├── max_stale_time_for_weak_consistency.py │ │ ├── parameters_default.py │ │ ├── tenant_min_resource.yaml │ │ └── writing_throttling_trigger_percentage.yaml │ │ └── version │ │ ├── bad_version.yaml │ │ └── old_version.yaml ├── display │ └── tasks │ │ └── observer │ │ ├── all_tenant.yaml │ │ ├── cluster_info.yaml │ │ ├── cpu.yaml │ │ ├── database_datasize.yaml │ │ ├── event.yaml │ │ ├── index.yaml │ │ ├── inner_table.yaml │ │ ├── leader.yaml │ │ ├── lock_table.yaml │ │ ├── lockholder.yaml │ │ ├── long_transaction.yaml │ │ ├── memory.yaml │ │ ├── plan.yaml │ │ ├── plan_explain.yaml │ │ ├── processlist.yaml │ │ ├── processlist_stat.yaml │ │ ├── rs.yaml │ │ ├── server_info.yaml │ │ ├── slowsql.yaml │ │ ├── storage_method.yaml │ │ ├── table_datasize.yaml │ │ ├── table_info.yaml │ │ ├── table_ndv.yaml │ │ ├── tenant_info.yaml │ │ ├── topsql.yaml │ │ ├── unit_info.yaml │ │ └── zone_info.yaml ├── gather │ ├── redact │ │ └── all_sql.py │ └── tasks │ │ ├── obproxy │ │ └── restart.yaml │ │ ├── observer │ │ ├── backup.yaml │ │ ├── backup_clean.yaml │ │ ├── base.yaml │ │ ├── clog_disk_full.yaml │ │ ├── cluster_down.yaml │ │ ├── compaction.yaml │ │ ├── cpu_high.py │ │ ├── delay_of_primary_and_backup.yaml │ │ ├── io.yaml │ │ ├── log_archive.yaml │ │ ├── long_transaction.yaml │ │ ├── memory.yaml │ │ ├── perf_sql.py │ │ ├── px_collect_log.py │ │ ├── recovery.yaml │ │ ├── restart.yaml │ │ ├── rootservice_switch.yaml │ │ ├── sql_err.py │ │ ├── suspend_transaction.yaml │ │ ├── topsql.yaml │ │ ├── unit_data_imbalance.yaml │ │ └── unknown.yaml │ │ └── other │ │ └── application_error.yaml └── rca │ ├── clog_disk_full.py │ ├── ddl_disk_full.py │ ├── ddl_failure.py │ ├── disconnection.py │ ├── index_ddl_error.py │ ├── lock_conflict.py │ ├── log_error.py │ ├── major_hold.py │ ├── oms_full_trans.py │ ├── oms_obcdc.py │ ├── suspend_transaction.py │ ├── transaction_disconnection.py │ ├── transaction_execute_timeout.py │ ├── transaction_not_ending.py │ ├── transaction_other_error.py │ ├── transaction_rollback.py │ └── transaction_wait_timeout.py ├── requirements3.txt ├── resources └── web │ ├── bootstrap.min.css │ ├── bootstrap.min.js │ ├── jquery-3.2.1.min.js │ └── popper.min.js ├── rpm ├── init.sh ├── init_obdiag_cmd.sh ├── obdiag_backup.sh └── oceanbase-diagnostic-tool.spec ├── src ├── common │ ├── __init__.py │ ├── command.py │ ├── config.py │ ├── config_helper.py │ ├── constant.py │ ├── context.py │ ├── core.py │ ├── diag_cmd.py │ ├── err.py │ ├── import_module.py │ ├── log.py │ ├── ob_connector.py │ ├── ob_log_level.py │ ├── ob_log_parser.py │ ├── obdiag_exception.py │ ├── ocp │ │ ├── __init__.py │ │ ├── ocp_api.py │ │ └── ocp_task.py │ ├── result_type.py │ ├── scene.py │ ├── ssh.py │ ├── ssh_client │ │ ├── __init__.py │ │ ├── base.py │ │ ├── docker_client.py │ │ ├── kubernetes_client.py │ │ ├── local_client.py │ │ ├── remote_client.py │ │ └── ssh.py │ ├── stdio.py │ ├── tool.py │ ├── types.py │ └── version.py ├── handler │ ├── __init__.py │ ├── analyzer │ │ ├── __init__.py │ │ ├── analyze_flt_trace.py │ │ ├── analyze_index_space.py │ │ ├── analyze_log.py │ │ ├── analyze_memory.py │ │ ├── analyze_parameter.py │ │ ├── analyze_queue.py │ │ ├── analyze_sql.py │ │ ├── analyze_sql_review.py │ │ ├── analyze_variable.py │ │ ├── log_parser │ │ │ ├── __init__.py │ │ │ ├── log_entry.py │ │ │ ├── log_enum.py │ │ │ └── tree.py │ │ └── sql │ │ │ ├── __init__.py │ │ │ ├── engine.py │ │ │ ├── meta │ │ │ ├── _init_.py │ │ │ ├── metadata.py │ │ │ └── sys_tenant_meta.py │ │ │ ├── rule_manager.py │ │ │ └── rules │ │ │ ├── __init__.py │ │ │ ├── abstract_rule.py │ │ │ ├── level.py │ │ │ ├── result.py │ │ │ ├── review │ │ │ ├── __init__.py │ │ │ ├── arithmetic.py │ │ │ ├── full_scan.py │ │ │ ├── is_null.py │ │ │ ├── large_in_clause.py │ │ │ ├── multi_table_join.py │ │ │ ├── select_all.py │ │ │ ├── update_delete_multi_table.py │ │ │ └── update_delete_without_where_or_true_condition.py │ │ │ └── tunning │ │ │ ├── __init__.py │ │ │ ├── index_column_fuzzy_match.py │ │ │ └── index_column_implicit_conversion.py │ ├── base_shell_handler.py │ ├── checker │ │ ├── __init__.py │ │ ├── check_exception.py │ │ ├── check_handler.py │ │ ├── check_list.py │ │ ├── check_report.py │ │ ├── check_task.py │ │ ├── result │ │ │ ├── __init__.py │ │ │ ├── result.py │ │ │ └── verify.py │ │ └── step │ │ │ ├── __init__.py │ │ │ ├── data_size.py │ │ │ ├── get_obproxy_parameter.py │ │ │ ├── get_system_parameter.py │ │ │ ├── local_ssh.py │ │ │ ├── sleep.py │ │ │ ├── sql.py │ │ │ ├── ssh.py │ │ │ └── stepbase.py │ ├── display │ │ ├── __init__.py │ │ ├── display_scenes.py │ │ ├── scenes │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── list.py │ │ │ └── register.py │ │ └── step │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── sql.py │ │ │ └── ssh.py │ ├── gather │ │ ├── __init__.py │ │ ├── gather_ash_report.py │ │ ├── gather_awr.py │ │ ├── gather_component_log.py │ │ ├── gather_dbms_xplan.py │ │ ├── gather_obadmin.py │ │ ├── gather_obstack2.py │ │ ├── gather_parameters.py │ │ ├── gather_perf.py │ │ ├── gather_plan_monitor.py │ │ ├── gather_scenes.py │ │ ├── gather_sysstat.py │ │ ├── gather_tabledump.py │ │ ├── gather_variables.py │ │ ├── plugins │ │ │ ├── __init__.py │ │ │ └── redact.py │ │ ├── scenes │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── list.py │ │ │ └── register.py │ │ └── step │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── sql.py │ │ │ └── ssh.py │ ├── meta │ │ ├── __init__.py │ │ ├── check_meta.py │ │ ├── html_meta.py │ │ ├── ob_error.py │ │ └── sql_meta.py │ ├── rca │ │ ├── __init__.py │ │ ├── plugins │ │ │ ├── __init__.py │ │ │ └── gather.py │ │ ├── rca_exception.py │ │ ├── rca_handler.py │ │ └── rca_list.py │ └── update │ │ ├── __init__.py │ │ └── update.py ├── main.py └── telemetry │ ├── __init__.py │ └── telemetry.py ├── test ├── analyzer │ ├── log │ │ └── test_tree.py │ ├── sql │ │ ├── test_arithmetic_rule.py │ │ ├── test_full_scan_rule.py │ │ ├── test_is_null_rule.py │ │ ├── test_large_in_clause_rule.py │ │ ├── test_multi_table_join_rule.py │ │ ├── test_parse.py │ │ ├── test_sellect_all_rule.py │ │ ├── test_update_delete_multi_table_rule.py │ │ └── test_update_delete_without_where_or_true_condition_rule.py │ ├── test_level.py │ └── test_tree.py └── common │ ├── ssh_client │ ├── test_docker_client.py │ ├── test_kubernetes_cilent.yaml │ ├── test_kubernetes_client.py │ ├── test_local_client.py │ └── test_remote_client.py │ ├── test_command.py │ ├── test_config_helper.py │ ├── test_config_parse.py │ ├── test_scene.py │ ├── test_sql_table_extractor.py │ └── test_tool_parse_optimization_info.py └── workflow_data ├── check_py_files.py ├── config.yml ├── config.yml.421 ├── run_obdiag_test.sh └── wait_observer_run.sh /.devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OBDIAG", 3 | "dockerFile": "Dockerfile.dev", 4 | "postAttachCommand": "bash", 5 | "customizations": { 6 | "vscode": { 7 | "extensions": [ 8 | "cschleiden.vscode-github-actions", 9 | "vadimcn.vscode-lldb" 10 | ], 11 | "settings": { 12 | "editor.formatOnSave": true 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /.github/workflows/build_base_docker.yml: -------------------------------------------------------------------------------- 1 | name: build docker helper 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'helper-[0-9]+.[0-9]+.[0-9]+' 7 | 8 | jobs: 9 | build-docker: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v4 14 | 15 | - name: Set up QEMU 16 | uses: docker/setup-qemu-action@v3 17 | 18 | - name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v3 20 | 21 | - name: Log in to Docker hub 22 | uses: docker/login-action@v3 23 | with: 24 | username: ${{ secrets.DOCKER_USERNAME }} 25 | password: ${{ secrets.DOCKER_PASSWORD }} 26 | 27 | - name: Create and push manifests w/o cache 28 | uses: docker/build-push-action@v6 29 | with: 30 | context: . 31 | platforms: linux/amd64 32 | file: Dockerfile.helper 33 | push: true 34 | tags: | 35 | ${{ vars.DOCKER_PUSH_BASE }}/obdiag-builder:latest 36 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | branches: [ "master" ] 19 | schedule: 20 | - cron: '26 11 * * 5' 21 | 22 | jobs: 23 | analyze: 24 | name: Analyze (${{ matrix.language }}) 25 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 26 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 27 | permissions: 28 | # required for all workflows 29 | security-events: write 30 | 31 | # required to fetch internal or private CodeQL packs 32 | packages: read 33 | 34 | # only required for workflows in private repositories 35 | actions: read 36 | contents: read 37 | 38 | strategy: 39 | fail-fast: false 40 | matrix: 41 | include: 42 | - language: python 43 | build-mode: none 44 | steps: 45 | - name: Checkout repository 46 | uses: actions/checkout@v4 47 | 48 | # Initializes the CodeQL tools for scanning. 49 | - name: Initialize CodeQL 50 | uses: github/codeql-action/init@v3 51 | with: 52 | languages: ${{ matrix.language }} 53 | build-mode: ${{ matrix.build-mode }} 54 | - if: matrix.build-mode == 'manual' 55 | run: | 56 | echo 'If you are using a "manual" build mode for one or more of the' \ 57 | 'languages you are analyzing, replace this with the commands to build' \ 58 | 'your code, for example:' 59 | echo ' make bootstrap' 60 | echo ' make release' 61 | exit 1 62 | 63 | - name: Perform CodeQL Analysis 64 | uses: github/codeql-action/analyze@v3 65 | with: 66 | category: "/language:${{matrix.language}}" 67 | -------------------------------------------------------------------------------- /.github/workflows/format_check.yml: -------------------------------------------------------------------------------- 1 | name: Black Code Formatter Check 2 | 3 | on: 4 | pull_request: 5 | branches: "*" 6 | push: 7 | branches: "*" 8 | 9 | jobs: 10 | format_check: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout Code 15 | uses: actions/checkout@v3 16 | 17 | - name: Set up Python 18 | uses: actions/setup-python@v4 19 | with: 20 | python-version: 3.8 21 | 22 | - name: Install Black 23 | run: | 24 | python -m pip install --upgrade pip 25 | pip install black 26 | 27 | - name: Run Black Formatter Check 28 | run: black --check -S -l 256 . 29 | # `--check`选项会让black检查代码而不做实际修改,如果格式不符合black规范,则此步骤会失败 -------------------------------------------------------------------------------- /.github/workflows/python_file_header_check.yml: -------------------------------------------------------------------------------- 1 | name: Python File Header Check 2 | 3 | on: 4 | pull_request: 5 | branches: "*" 6 | push: 7 | branches: "*" 8 | jobs: 9 | check-headers: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout code 13 | uses: actions/checkout@v4 14 | 15 | - name: Set up Python 16 | uses: actions/setup-python@v4 17 | with: 18 | python-version: "3.11" 19 | 20 | 21 | - name: Run header check 22 | run: python workflow_data/check_py_files.py . 23 | working-directory: ${{ github.workspace }} 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | 27 | - name: Set status 28 | if: ${{ failure() }} 29 | run: echo "存在不符合规范的文件!" -------------------------------------------------------------------------------- /.github/workflows/test_command_scene_configHelper.yml: -------------------------------------------------------------------------------- 1 | # common包下command、scene、config_helper的测试用例 2 | name: Test command_scene_configHelper 3 | 4 | on: 5 | push: 6 | branches: "*" 7 | pull_request: 8 | branches: "*" 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 # Fetch all history for proper version detection 19 | 20 | - name: Set up Python 3.11 21 | uses: actions/setup-python@v3 22 | with: 23 | python-version: 3.11 24 | 25 | - name: Install dependencies 26 | run: | 27 | python -m pip install --upgrade pip 28 | pip install -r requirements3.txt 29 | 30 | - name: Run tests 31 | run: python -m unittest discover -s test/common -p 'test_*.py' 32 | -------------------------------------------------------------------------------- /.github/workflows/test_sql_rule.yml: -------------------------------------------------------------------------------- 1 | name: Test Full Scan Rule 2 | 3 | on: 4 | push: 5 | branches: "*" 6 | pull_request: 7 | branches: "*" 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | fetch-depth: 0 # Fetch all history for proper version detection 18 | 19 | - name: Set up Python 3.11 20 | uses: actions/setup-python@v3 21 | with: 22 | python-version: 3.11 23 | 24 | - name: Install dependencies 25 | run: | 26 | python -m pip install --upgrade pip 27 | pip install -r requirements3.txt 28 | 29 | - name: Run tests 30 | run: python -m unittest discover -s test/analyzer/sql -p 'test_*.py' -------------------------------------------------------------------------------- /.github/workflows/test_ssh_client.yml: -------------------------------------------------------------------------------- 1 | name: Test Ssh Client 2 | 3 | on: 4 | push: 5 | branches: "dev*" 6 | pull_request: 7 | branches: "dev*" 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | fetch-depth: 0 # Fetch all history for proper version detection 18 | 19 | - name: Set up Python 3.11 20 | uses: actions/setup-python@v3 21 | with: 22 | python-version: 3.11 23 | 24 | - name: Install dependencies 25 | run: | 26 | python -m pip install --upgrade pip 27 | pip install -r requirements3.txt 28 | 29 | - name: Run tests 30 | run: python -m unittest discover -s test/common/ssh_client -p 'test_*.py' -------------------------------------------------------------------------------- /.github/workflows/translate.yml: -------------------------------------------------------------------------------- 1 | name: 'translator' 2 | on: 3 | issues: 4 | types: [opened, edited] 5 | issue_comment: 6 | types: [created, edited] 7 | discussion: 8 | types: [created, edited] 9 | discussion_comment: 10 | types: [created, edited] 11 | pull_request_target: 12 | types: [opened, edited] 13 | pull_request_review_comment: 14 | types: [created, edited] 15 | 16 | jobs: 17 | translate: 18 | permissions: 19 | issues: write 20 | discussions: write 21 | pull-requests: write 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: lizheming/github-translate-action@1.1.2 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | with: 28 | IS_MODIFY_TITLE: true 29 | APPEND_TRANSLATION: false 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | venv/ 4 | *.pyc 5 | *site-packages/ 6 | dependencies/python2/site-packages 7 | dependencies/python2/libs 8 | dependencies/python3/site-packages 9 | dependencies/python3/libs 10 | obdiag_gather_pack_* 11 | obdiag_analyze_pack_* 12 | obdiag_rca* 13 | 14 | -------------------------------------------------------------------------------- /.secignore: -------------------------------------------------------------------------------- 1 | BFlow Secret Scan Ignore List # 2 | ########################################################## 3 | # Above the segmentation lines there are suspected privacy information # 4 | # Please use the file name as the first line and the igored information # 5 | # should be started with tab. # 6 | # Under the segmentation lines there are the folders which you need to ignore # 7 | ########################################################## 8 | ** 9 | http://license.coscl.org.cn/* 10 | http://xxx.xxx.xxx.xxx:xxxx 11 | http://xx.xx.xx.xx:xx 12 | https://getbootstrap.com/) 13 | https://github.com/twbs/bootstrap/blob/main/LICENSE) 14 | http://www.w3.org/2000/svg 15 | https://www.oceanbase.com/ 16 | https://github.com/* 17 | https://bootstrap.pypa.io/pip/ 18 | http://opensource.org/licenses/* 19 | https://facebook.github.io/* 20 | https://www.oceanbase.com/* 21 | http://mirrors.aliyun.com/pypi/simple/ 22 | https://mirrors.aliyun.com/oceanbase/OceanBase.repo 23 | https://img.shields.io/* 24 | https://github.com/oceanbase/obdiag/issues/* 25 | **/README.md 26 | http://xxx.xxx.xxx.xxx:xxxx 27 | **/dependencies/bin/obstack_x86_64_7 28 | http://llvm.org/): 29 | **/resources/web/bootstrap.min.js 30 | https://getbootstrap.com/) 31 | https://github.com/twbs/bootstrap/graphs/contributors) 32 | https://github.com/twbs/bootstrap/blob/main/LICENSE) 33 | https://popper.js.org/) 34 | https://popper.js.org/) 35 | **/src/common/constant.py 36 | openwebapi-pre.oceanbase.com* 37 | openwebapi.oceanbase.com* 38 | openwebapi-pre.oceanbase.com* 39 | https://obbusiness-private.oss-cn-shanghai.aliyuncs.com* 40 | **/dev_helper.sh 41 | https://obbusiness-private.oss-cn-shanghai.aliyuncs.com* -------------------------------------------------------------------------------- /Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/centos:centos7.9.2009 2 | 3 | ENV PATH="/opt/miniconda/bin:$PATH" 4 | ENV LANGUAGE en_US 5 | ENV LANG en_US.UTF-8 6 | ENV LC_ALL en_US.UTF-8 7 | 8 | 9 | # 基础环境设置 10 | RUN rm -rf /etc/yum.repos.d/* \ 11 | && curl -o /etc/yum.repos.d/CentOS-aliyun.repo http://mirrors.aliyun.com/repo/Centos-7.repo \ 12 | && yum clean all \ 13 | && yum makecache \ 14 | && yum install -y wget gcc git \ 15 | && wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \ 16 | && bash Miniconda3-latest-Linux-x86_64.sh -p /opt/miniconda -b \ 17 | && rm -rf Miniconda3-latest-Linux-x86_64.sh \ 18 | && conda create -n obdiag -y python=3.11 \ 19 | && source /opt/miniconda/bin/activate obdiag \ 20 | && python3 -m pip install --upgrade pip wheel 21 | 22 | COPY ./requirements3.txt /workspaces/obdiag/requirements3.txt 23 | RUN /opt/miniconda/envs/obdiag/bin/pip install -r /workspaces/obdiag/requirements3.txt -i https://pypi.tuna.tsinghua.edu.cn/simple 24 | RUN echo "source /opt/miniconda/bin/activate obdiag" >> ~/.bashrc -------------------------------------------------------------------------------- /Dockerfile.helper: -------------------------------------------------------------------------------- 1 | FROM registry.openanolis.cn/openanolis/anolisos:8.9 2 | 3 | RUN yum install -y wget rpm-build 4 | RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --no-check-certificate 5 | RUN sh Miniconda3-latest-Linux-x86_64.sh -p /opt/miniconda3 -b 6 | RUN export PATH=/opt/miniconda3/bin:$PATH 7 | RUN /opt/miniconda3/bin/conda init 8 | RUN /opt/miniconda3/bin/conda create --name obdiag python=3.11 -y 9 | RUN source /opt/miniconda3/bin/activate obdiag 10 | RUN /opt/miniconda3/envs/obdiag/bin/python3 -m pip install --upgrade pip setuptools wheel 11 | RUN yum install -y gcc gcc-c++ make 12 | -------------------------------------------------------------------------------- /LEGAL.md: -------------------------------------------------------------------------------- 1 | Legal Disclaimer 2 | 3 | Within this source code, the comments in Chinese shall be the original, governing version. Any comment in other languages are for reference only. In the event of any conflict between the Chinese language version comments and other language version comments, the Chinese language version shall prevail. 4 | 5 | 法律免责声明 6 | 7 | 关于代码注释部分,中文注释为官方版本,其它语言注释仅做参考。中文注释可能与其它语言注释存在不一致,当中文注释与其它语言注释存在不一致时,请以中文注释为准。 -------------------------------------------------------------------------------- /build_update_package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Start packaging plugins" 3 | cd plugins && tar -cvf data.tar * 4 | a=$(sha256sum data.tar | awk '{print $1}') 5 | echo "obdiag_version: \"3.5.0\"" > version.yaml 6 | echo "remote_tar_sha: \"$a\"" >> version.yaml 7 | cp -rf version.yaml ../ 8 | cp -rf data.tar ../ 9 | rm -rf version.yaml 10 | rm -rf data.tar -------------------------------------------------------------------------------- /conf/inner_config.yml: -------------------------------------------------------------------------------- 1 | obdiag: 2 | basic: 3 | config_path: ~/.obdiag/config.yml 4 | config_backup_dir: ~/.obdiag/backup_conf 5 | file_number_limit: 50 6 | file_size_limit: 5G 7 | dis_rsa_algorithms: 0 8 | strict_host_key_checking: 0 9 | logger: 10 | log_dir: ~/.obdiag/log 11 | log_filename: obdiag.log 12 | file_handler_log_level: DEBUG 13 | log_level: INFO 14 | mode: obdiag 15 | stdout_handler_log_level: INFO 16 | error_stream: sys.stdout 17 | silent: false 18 | ssh_client: 19 | remote_client_sudo: 0 20 | analyze: 21 | thread_nums: 3 22 | check: 23 | ignore_version: false 24 | work_path: "~/.obdiag/check" 25 | report: 26 | report_path: "./check_report/" 27 | export_type: table 28 | tasks_base_path: "~/.obdiag/check/tasks/" 29 | gather: 30 | scenes_base_path: "~/.obdiag/gather/tasks" 31 | redact_processing_num: 3 32 | thread_nums: 3 33 | rca: 34 | result_path: "./obdiag_rca/" 35 | -------------------------------------------------------------------------------- /example/all-components.yaml: -------------------------------------------------------------------------------- 1 | ocp: 2 | login: 3 | url: http://xx.xx.xx.xx:xx 4 | user: admin 5 | password: '' 6 | obcluster: 7 | ob_cluster_name: test 8 | db_host: 192.168.1.1 9 | db_port: 2881 # default 2881, if the obcluster use obproxy ,please set db_port to obproxy mysql_port 10 | tenant_sys: 11 | user: root@sys # default root@sys 12 | password: "" 13 | servers: 14 | nodes: 15 | - ip: 192.168.1.1 16 | - ip: 192.168.1.2 17 | - ip: 192.168.1.3 18 | global: 19 | ssh_username: '' # your username 20 | ssh_password: '' # password if need 21 | # ssh_port: 22 # your ssh port, default 22 22 | # ssh_key_file: "" # your ssh-key file path if need 23 | # ssh_type: remote # ssh_type choice [remote, docker, kube] default remote 24 | # container_name: xxx # container_name for ssh_type is docker 25 | # The directory for oceanbase installed 26 | home_path: /root/observer 27 | # The directory for data storage. The default value is $home_path/store. 28 | # data_dir: /root/observer/store 29 | # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. 30 | # redo_dir: /root/observer/store 31 | obproxy: 32 | obproxy_cluster_name: obproxy 33 | servers: 34 | nodes: 35 | - ip: 192.168.1.4 36 | - ip: 192.168.1.5 37 | - ip: 192.168.1.6 38 | global: 39 | ssh_username: admin # your username 40 | ssh_password: '' # password if need 41 | # ssh_port: 22 # your ssh port, default 22 42 | # ssh_key_file: "" # your ssh-key file path if need 43 | # ssh_type: remote # ssh_type choice [remote, docker, kube] default remote 44 | # container_name: xxx # container_name for ssh_type is docker 45 | # The directory for obproxy installed 46 | home_path: /root/obproxy 47 | -------------------------------------------------------------------------------- /example/docker_ob_cluster.yml: -------------------------------------------------------------------------------- 1 | obcluster: 2 | ob_cluster_name: test 3 | db_host: 192.168.1.1 4 | db_port: 2881 # default 2881 5 | tenant_sys: 6 | user: root@sys # default root@sys 7 | password: "" 8 | servers: 9 | nodes: 10 | - container_name: testdocker1 # container_name for ssh_type is docker 11 | ssh_type: docker # ssh_type choice [remote, docker, kube] default remote 12 | - container_name: testdocker2 # container_name for ssh_type is docker 13 | ssh_type: docker # ssh_type choice [remote, docker, kube] default remote 14 | - container_name: testdocker3 # container_name for ssh_type is docker 15 | ssh_type: docker # ssh_type choice [remote, docker, kube] default remote 16 | global: 17 | home_path: /root/ob/ 18 | data_dir: /root/observer/store 19 | redo_dir: /root/observer/store 20 | -------------------------------------------------------------------------------- /example/mini.yml: -------------------------------------------------------------------------------- 1 | obcluster: 2 | ob_cluster_name: test 3 | db_host: 127.0.0.1 4 | db_port: 2881 # default 2881 5 | tenant_sys: 6 | user: root@sys # default root@sys 7 | password: "" 8 | servers: 9 | nodes: 10 | - ip: 127.0.0.1 11 | ssh_username: root 12 | ssh_password: '' 13 | home_path: /root/ob 14 | data_dir: /root/ob/store 15 | redo_dir: /root/ob/store 16 | global: 17 | ssh_port: 22 18 | -------------------------------------------------------------------------------- /example/ob_cluster.yml: -------------------------------------------------------------------------------- 1 | obcluster: 2 | ob_cluster_name: test 3 | db_host: 192.168.1.1 4 | db_port: 2881 # default 2881 5 | tenant_sys: 6 | user: root@sys # default root@sys 7 | password: "" 8 | servers: 9 | nodes: 10 | - ip: 192.168.1.1 11 | ssh_username: admin1 12 | ssh_password: '' 13 | home_path: /root/observer1 14 | data_dir: /root/observer/store1 15 | redo_dir: /root/observer/store1 16 | - ip: 192.168.1.2 17 | ssh_username: admin2 18 | ssh_password: '' 19 | home_path: /root/observer2 20 | data_dir: /root/observer/store2 21 | redo_dir: /root/observer/store2 22 | - ip: 192.168.1.3 23 | ssh_username: admin3 24 | ssh_password: '' 25 | home_path: /root/observer3 26 | data_dir: /root/observer/store3 27 | redo_dir: /root/observer/store3 28 | global: 29 | ssh_port: 22 30 | -------------------------------------------------------------------------------- /example/obproxy.yml: -------------------------------------------------------------------------------- 1 | obproxy: 2 | obproxy_cluster_name: testobproxy 3 | servers: 4 | nodes: 5 | - ip: 192.168.1.4 6 | ssh_username: admin4 7 | ssh_password: '' 8 | home_path: /root/obproxy4 9 | - ip: 192.168.1.5 10 | ssh_username: admin4 11 | ssh_password: '' 12 | home_path: /root/obproxy4 13 | - ip: 192.168.1.6 14 | ssh_username: admin4 15 | ssh_password: '' 16 | home_path: /root/obproxy4 17 | global: 18 | # ssh_username: admin # your username 19 | # ssh_password: '' # password if need 20 | ssh_port: 22 # your ssh port, default 22 21 | # ssh_key_file: "" # your ssh-key file path if need 22 | # ssh_type: remote # ssh_type choice [remote, docker, kube] default remote 23 | # container_name: xxx # container_name for ssh_type is docker 24 | # The directory for obproxy installed 25 | # home_path: /root/obproxy 26 | -------------------------------------------------------------------------------- /example/operator.yml: -------------------------------------------------------------------------------- 1 | obcluster: 2 | db_host: 127.0.0.1 3 | db_port: 2881 # default 2881, if the obcluster use obproxy ,please set db_port to obproxy mysql_port 4 | ob_cluster_name: obtest 5 | tenant_sys: 6 | user: root@sys 7 | password: '' 8 | servers: 9 | nodes: 10 | - namespace: oceanbase 11 | ssh_type: "kubernetes" 12 | pod_name: obcluster-1-zone1-xxxx 13 | container_name: observer 14 | home_path: /home/admin/oceanbase 15 | data_dir: /home/admin/oceanbase/store 16 | redo_dir: /home/admin/oceanbase/store 17 | ip: xx.xx.xx.xx 18 | - namespace: oceanbase 19 | ssh_type: "kubernetes" 20 | pod_name: obcluster-1-zone2-xxxx 21 | container_name: observer 22 | home_path: /home/admin/oceanbase 23 | data_dir: /home/admin/oceanbase/store 24 | redo_dir: /home/admin/oceanbase/store 25 | ip: xx.xx.xx.xx 26 | - namespace: oceanbase 27 | ssh_type: "kubernetes" 28 | pod_name: obcluster-1-zone3-xxxx 29 | container_name: observer 30 | home_path: /home/admin/oceanbase 31 | data_dir: /home/admin/oceanbase/store 32 | redo_dir: /home/admin/oceanbase/store 33 | ip: xx.xx.xx.xx 34 | global: 35 | # if running obdiag in kubernetes, please delete the kubernetes_config_file 36 | kubernetes_config_file: "~/.kube/config/config.yaml" 37 | 38 | -------------------------------------------------------------------------------- /images/obdiag_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oceanbase/obdiag/c63293a215000ad326eac6540f31801f86f7272d/images/obdiag_cn.png -------------------------------------------------------------------------------- /images/obdiag_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oceanbase/obdiag/c63293a215000ad326eac6540f31801f86f7272d/images/obdiag_en.png -------------------------------------------------------------------------------- /images/structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oceanbase/obdiag/c63293a215000ad326eac6540f31801f86f7272d/images/structure.png -------------------------------------------------------------------------------- /plugins/check/obproxy_check_package.yaml: -------------------------------------------------------------------------------- 1 | # for obproxy or oms ,cases'name 2 | proxy: 3 | info_en: "obproxy version check" 4 | info_cn: "obproxy 版本检查" 5 | tasks: 6 | - version.bad_version -------------------------------------------------------------------------------- /plugins/check/observer_check_package.yaml: -------------------------------------------------------------------------------- 1 | ad: 2 | info_en: "Test and inspection tasks" 3 | info_cn: "测试巡检任务" 4 | tasks: 5 | - system.* 6 | column_storage_poc: 7 | info_en: "column storage poc" 8 | info_cn: "列存POC检查" 9 | tasks: 10 | - column_storage.* 11 | build_before: 12 | info_en: "Deployment environment check" 13 | info_cn: "部署环境检查" 14 | tasks: 15 | - system.* 16 | sysbench_run: 17 | info_en: "Collection of inspection tasks when executing sysbench" 18 | info_cn: "执行sysbench时的巡检任务集合" 19 | tasks: 20 | - sysbench.sysbench_run_test_tenant_cpu_used 21 | - sysbench.sysbench_run_test_tenant_memory_used 22 | sysbench_free: 23 | info_en: "Collection of inspection tasks before executing sysbench" 24 | info_cn: "执行sysbench前的巡检任务集合" 25 | tasks: 26 | - sysbench.sysbench_free_test_cpu_count 27 | - sysbench.sysbench_free_test_memory_limit 28 | - sysbench.sysbench_free_test_network_speed 29 | - sysbench.sysbench_test_cluster_datafile_size 30 | - sysbench.sysbench_test_cluster_log_disk_size 31 | - sysbench.sysbench_test_cluster_parameters 32 | - sysbench.sysbench_test_cpu_quota_concurrency 33 | - sysbench.sysbench_test_log_level 34 | - sysbench.sysbench_test_sql_net_thread_count 35 | - sysbench.sysbench_test_tenant_cpu_parameters 36 | - sysbench.sysbench_test_tenant_log_disk_size 37 | - sysbench.sysbench_test_tenant_primary_zone 38 | 39 | filter: 40 | info_en: "Inspection that needs to be ignored" 41 | info_cn: "需要忽略的检查" 42 | tasks: 43 | - sysbench.* 44 | - column_storage.* -------------------------------------------------------------------------------- /plugins/check/tasks/obproxy/parameter/request_buffer_length.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check obproxy request_buffer_length' 2 | task: 3 | - version: "[4.0.0,*]" 4 | steps: 5 | - type: get_obproxy_parameter 6 | parameter: 'request_buffer_length' 7 | result: 8 | set_value: request_buffer_length 9 | verify: '[[ $request_buffer_length == "4KB" ]]' 10 | err_msg: "obproxy's parameter request_buffer_length is #{request_buffer_length}, not 4KB" -------------------------------------------------------------------------------- /plugins/check/tasks/obproxy/version/bad_version.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check obproxy version . Some versions of obproxy are not recommended' 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: "export LD_LIBRARY_PATH=#{remote_home_path}/lib && #{remote_home_path}/bin/obproxy --version 2>&1 | grep \"obproxy (\" | awk '{print $3}'" 6 | result: 7 | set_value: obproxy_version 8 | - type: ssh 9 | ssh: '[ "#{obproxy_version}" = "4.2.0.0" ] && echo "0" || echo "1"' 10 | result: 11 | set_value: result 12 | verify_type: equal 13 | verify: 1 14 | err_msg: 'the version is 4.2.0.0 , the observer is not recommended' -------------------------------------------------------------------------------- /plugins/check/tasks/obproxy/version/old_version.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check obproxy version . Some versions of obproxy are not recommended' 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: "export LD_LIBRARY_PATH=#{remote_home_path}/lib && #{remote_home_path}/bin/obproxy --version 2>&1 | grep \"obproxy (\" | awk '{print $3}'" 6 | result: 7 | set_value: obproxy_version 8 | verify: '[[ ! "${obproxy_version}" == "4.0"* ]] && [[ ! "${obproxy_version}" == "4.1"* ]] && [[ ! "${obproxy_version}" == "4.2"* ]] && [[ ! "${obproxy_version}" == "4.3.0"* ]] && [[ ! "${obproxy_version}" == "3"* ]] && [[ ! "${obproxy_version}" == "4.3.1"* ]]' 9 | err_msg: '#{obproxy_version} is not recommended, please upgrade to the bproxy' -------------------------------------------------------------------------------- /plugins/check/tasks/observer/bugs/bug_385.yaml: -------------------------------------------------------------------------------- 1 | info: "OB version [4.2.1.0,4.2.1.3] If tenants have multiple root users. Please consider upgrading the OceanBase version or removing the redundant users. github issue #385" 2 | task: 3 | - version: "[4.2.1.0,4.2.1.3]" 4 | steps: 5 | - type: sql 6 | sql: "SELECT GROUP_CONCAT(TENANT_ID) AS TENANT_ID 7 | FROM oceanbase.CDB_OB_USERS 8 | WHERE USER_NAME = 'root' 9 | GROUP BY TENANT_ID 10 | HAVING COUNT(*) > 1;" 11 | result: 12 | set_value: TENANT_ID 13 | verify: '[ -z "$TENANT_ID" ]' 14 | err_msg: "tenant: #{$TENANT_ID}. These tenants have multiple root users. Please consider upgrading the OceanBase version or removing the redundant users. Please get bug's on https://github.com/oceanbase/obdiag/issues/385" 15 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/bugs/bug_469.yaml: -------------------------------------------------------------------------------- 1 | info: "the ldd version of observer's node must less 2.34. more information: obdiag github issue #469" 2 | task: 3 | - version: "[3.0.0,*]" 4 | steps: 5 | - type: ssh 6 | ssh: "ldd --version | head -n 1 | awk '{print $NF}' | cut -d. -f1" 7 | result: 8 | set_value: ldd_version 9 | verify_type: max 10 | verify: 3 11 | err_msg: "glibc version need less 2.34. This may cause observer crash. More information: https://github.com/oceanbase/obdiag/issues/469" 12 | - type: ssh 13 | ssh: "ldd --version | head -n 1 | awk '{print $NF}' | cut -d. -f2" 14 | result: 15 | set_value: ldd_version 16 | verify_type: max 17 | verify: 34 18 | err_msg: "glibc version need less 2.34. This may cause observer crash. More information: https://github.com/oceanbase/obdiag/issues/469" 19 | 20 | 21 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/clog/clog_disk_full.yaml: -------------------------------------------------------------------------------- 1 | info: "Check if there is a problem with clog disk full" 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'SELECT GROUP_CONCAT(DISTINCT u.tenant_id) FROM oceanbase.gv$ob_units u JOIN ( SELECT SVR_IP, SVR_PORT, TENANT_ID, value/100 AS value FROM oceanbase.GV$OB_PARAMETERS WHERE name = "log_disk_utilization_threshold") as c ON u.SVR_IP = c.SVR_IP AND u.SVR_PORT = c.SVR_PORT AND u.TENANT_ID = c.TENANT_ID WHERE u.LOG_DISK_IN_USE > u.LOG_DISK_SIZE * c.value;' 7 | result: 8 | set_value: tenant_ids 9 | verify: '[ -z "$tenant_ids" ]' 10 | err_msg: "The following tenants have experienced clog disk full: #{tenant_ids}. Please check by obdiag rca --scene=clog_disk_full " 11 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/core_file_find.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether the core file exists.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: ssh 6 | ssh: 'ls #{remote_home_path}| grep "^core" | wc -l' 7 | result: 8 | set_value: core_file_number 9 | verify_type: equal 10 | verify: 0 11 | err_msg: 'The core file exists.' -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/data_path_settings.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether data_dir and log_dir_disk are on the same disk.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: ssh 6 | ssh: 'find #{remote_data_dir}/ -name "sstable"' 7 | result: 8 | set_value: data_dir_path 9 | verify: '[ -n "${data_dir_path}" ]' 10 | err_msg: "data_dir_path is null . Please check your nodes.data_dir need absolute Path" 11 | - type: ssh 12 | ssh: "df -h #{data_dir_path} | grep '/' | awk '{print $6}'" 13 | result: 14 | set_value: data_dir_disk 15 | - type: ssh 16 | ssh: 'find #{remote_redo_dir}/ -name "clog"' 17 | result: 18 | set_value: log_dir_path 19 | verify: '[ -n "${log_dir_path}" ]' 20 | err_msg: "log_dir_path is null . Please check your nodes.redo_dir need absolute Path" 21 | - type: ssh 22 | ssh: "df -h #{log_dir_path} | grep '/' | awk '{print $6}'" 23 | result: 24 | set_value: log_dir_disk 25 | verify: '[ "${data_dir_disk}" != "${log_dir_disk}" ]' 26 | err_msg: "ip:#{remote_ip} ,data_dir and log_dir_disk are on the same disk." 27 | - type: ssh 28 | ssh: "df -T #{data_dir_path} | grep \"/\"|awk '{if ($3 > 17179869184 && $2 != \"xfs\") print \"1\"; else print \"0\"}'" 29 | result: 30 | set_value: file_system 31 | verify_type: equal 32 | verify: 0 33 | err_msg: "the data_dir_path of disk size over 16TB ,the type must be xfs" 34 | 35 | - type: ssh 36 | ssh: "df -Th #{log_dir_path} | grep '/' | awk '{print $2}'" 37 | result: 38 | set_value: file_system 39 | verify: '[ "${file_system}" == "xfs" ] || [ "${file_system}" == "ext4" ] || [ "${file_system}" == "xfs" ]' 40 | err_msg: "ip:#{remote_ip} ,log_dir_path: #{log_dir_path} file_system is not xfs or ext4." 41 | - type: ssh 42 | ssh: "df -T #{log_dir_path} | grep \"/\"|awk '{if ($3 > 17179869184 && $2 != \"xfs\") print \"1\"; else print \"0\"}'" 43 | result: 44 | set_value: file_system 45 | verify_type: equal 46 | verify: 0 47 | err_msg: "the log_dir_path of disk size over 16TB ,the type must be xfs" 48 | - type: ssh 49 | ssh: "df -Th #{data_dir_path} | grep '/' | awk '{print $2}'" 50 | result: 51 | set_value: file_system 52 | verify: '[ "${file_system}" == "xfs" ] || [ "${file_system}" == "ext4" ]' 53 | err_msg: "ip:#{remote_ip} ,data_dir_path: #{data_dir_path} file_system is not xfs or ext4." 54 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/datafile_next.yaml: -------------------------------------------------------------------------------- 1 | info: "Check node'parameter 'datafile_maxsize'. When the datafile_maxsize is set and is greater than datafile_size, check if datafile_next is 0. If this value is 0, then the data file will not grow. issue #573" 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: "SELECT GROUP_CONCAT(DISTINCT p1.SVR_IP) FROM oceanbase.GV$OB_PARAMETERS p1 JOIN oceanbase.GV$OB_PARAMETERS p2 ON p1.SVR_IP = p2.SVR_IP JOIN oceanbase.GV$OB_PARAMETERS p3 ON p1.SVR_IP = p3.SVR_IP WHERE p1.NAME = 'datafile_maxsize' AND p1.VALUE <> '0' AND p2.NAME = 'datafile_size' AND CAST(p1.VALUE AS DECIMAL) > CAST(p2.VALUE AS DECIMAL) AND p3.NAME = 'datafile_next' AND p3.VALUE = '0';" 7 | result: 8 | set_value: ip_list 9 | verify: '[ -z "${ip_list}" ]' 10 | err_msg: "node: #{ip_list} datafile_next is 0, the data file will not grow. More info: https://github.com/oceanbase/obdiag/issues/573" 11 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/deadlocks.yaml: -------------------------------------------------------------------------------- 1 | info: "Check whether there is a deadlock." 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.DBA_OB_DEADLOCK_EVENT_HISTORY;' 7 | result: 8 | set_value: deadlocks_nu 9 | verify_type: equal 10 | report_type: warning 11 | verify: 0 12 | err_msg: "There is a deadlock. Please check on the oceanbase.DBA_OB_DEADLOCK_EVENT_HISTORY" -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/global_indexes_too_much.yaml: -------------------------------------------------------------------------------- 1 | info: "Check whether there is a table with more than 20 global indexes." 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: "SELECT COUNT(*) as count 7 | FROM oceanbase.DBA_PART_INDEXES 8 | WHERE LOCALITY = 'LOCAL' 9 | GROUP BY TABLE_NAME 10 | ORDER BY count DESC limit 1;" 11 | result: 12 | set_value: major_err_nu 13 | report_type: warning 14 | verify_type: max 15 | verify: 20 16 | err_msg: "There is a table with more than 20 global indexes" -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/large_query_threshold.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/04/8 15 | @file: large_query_threshold.py 16 | @desc: 17 | """ 18 | 19 | from src.handler.checker.check_task import TaskBase 20 | 21 | 22 | class LargeQueryThreshold(TaskBase): 23 | 24 | def init(self, context, report): 25 | super().init(context, report) 26 | 27 | def execute(self): 28 | try: 29 | if self.ob_connector is None: 30 | return self.report.add_critical("can't build obcluster connection") 31 | large_query_threshold_data = self.ob_connector.execute_sql_return_cursor_dictionary("select * from oceanbase.GV$OB_PARAMETERS where Name=\"large_query_threshold\";").fetchall() 32 | for large_query_threshold_one in large_query_threshold_data: 33 | large_query_threshold_value = large_query_threshold_one.get("VALUE") 34 | svr_ip = large_query_threshold_one.get("SVR_IP") 35 | if large_query_threshold_value is None: 36 | return self.report.add_fail("get large_query_threshold value error") 37 | if large_query_threshold_value != "5s": 38 | self.report.add_warning("svr_ip: {1}. large_query_threshold is {0}, recommended value is 5s.".format(large_query_threshold_value, svr_ip)) 39 | 40 | except Exception as e: 41 | self.stdio.error("execute error {0}".format(e)) 42 | return self.report.add_fail("execute error {0}".format(e)) 43 | 44 | def get_task_info(self): 45 | return { 46 | "name": "large_query_threshold", 47 | "info": "Check the threshold for query execution time. Requests that exceed the time limit may be paused and automatically judged as large queries after the pause, and the large query scheduling strategy will be executed. Recommended setting is 5s. issue#859", 48 | } 49 | 50 | 51 | large_query_threshold = LargeQueryThreshold() 52 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/ls_nu.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check ls id is not_enough_replica' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: " 7 | WITH LeaderInfo AS ( 8 | SELECT 9 | tenant_id, 10 | ls_id, 11 | paxos_replica_num 12 | FROM 13 | oceanbase.__all_virtual_log_stat 14 | WHERE 15 | role = 'LEADER' 16 | ), 17 | RowCounts AS ( 18 | SELECT 19 | tenant_id, 20 | ls_id, 21 | COUNT(*) as row_count 22 | FROM 23 | oceanbase.__all_virtual_log_stat 24 | GROUP BY 25 | tenant_id, 26 | ls_id 27 | ) 28 | SELECT 29 | GROUP_CONCAT(DISTINCT L.tenant_id) 30 | FROM 31 | LeaderInfo L 32 | JOIN 33 | RowCounts R 34 | ON 35 | L.tenant_id = R.tenant_id AND L.ls_id = R.ls_id 36 | WHERE 37 | R.row_count < L.paxos_replica_num;" 38 | result: 39 | set_value: not_enough_replica 40 | verify: '[ -z "${not_enough_replica}" ]' 41 | err_msg: 'There is not_enough_replica tenant_id: #{not_enough_replica} not_enough_replica, please check as soon as possible.' 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/major.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether there is any suspended major compaction process.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.CDB_OB_MAJOR_COMPACTION where IS_ERROR="YES";' 7 | result: 8 | set_value: major_err_nu 9 | verify_type: equal 10 | verify: 0 11 | err_msg: 'major have error' 12 | - type: sql 13 | sql: 'SELECT COUNT(*) AS count 14 | FROM ( 15 | SELECT START_TIME, TIMESTAMPDIFF(HOUR, START_TIME, CURRENT_TIMESTAMP) AS diff 16 | FROM oceanbase.CDB_OB_MAJOR_COMPACTION 17 | WHERE STATUS = "COMPACTING" AND TIMESTAMPDIFF(HOUR, START_TIME, CURRENT_TIMESTAMP) > 36 18 | ) AS subquery;' 19 | result: 20 | set_value: major_hold_nu 21 | verify_type: equal 22 | verify: 0 23 | err_msg: 'major have hold. please check it. And you can execute "obdiag rca run --scene=major_hold" to check it.' 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/memory_chunk_cache_size.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/05/6 15 | @file: memory_chunk_cache_size.py 16 | @desc: 17 | """ 18 | 19 | from src.handler.checker.check_task import TaskBase 20 | 21 | 22 | class MemoryChunkCacheSize(TaskBase): 23 | 24 | def init(self, context, report): 25 | super().init(context, report) 26 | 27 | def execute(self): 28 | try: 29 | if self.ob_connector is None: 30 | return self.report.add_critical("can't build obcluster connection") 31 | memory_chunk_cache_size_data = self.ob_connector.execute_sql_return_cursor_dictionary("SELECT * FROM oceanbase.__all_virtual_sys_parameter_stat WHERE name='memory_chunk_cache_size';").fetchall() 32 | 33 | for memory_chunk_cache_size_one in memory_chunk_cache_size_data: 34 | memory_chunk_cache_size_value = memory_chunk_cache_size_one.get("value") 35 | svr_ip = memory_chunk_cache_size_one.get("svr_ip") 36 | if memory_chunk_cache_size_value is None: 37 | return self.report.add_fail("get memory_chunk_cache_size value error") 38 | if memory_chunk_cache_size_value.lower() != "0m": 39 | self.report.add_warning("svr_ip: {1}. memory_chunk_cache_size is {0}, recommended value is 0M.".format(memory_chunk_cache_size_value, svr_ip)) 40 | 41 | except Exception as e: 42 | self.stdio.error("execute error {0}".format(e)) 43 | return self.report.add_fail("execute error {0}".format(e)) 44 | 45 | def get_task_info(self): 46 | return {"name": "memory_chunk_cache_size", "info": "Check the memory block capacity of the memory allocator cache. It is recommended to set to 0. issue#843"} 47 | 48 | 49 | memory_chunk_cache_size = MemoryChunkCacheSize() 50 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/memstore_limit_percentage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/04/8 15 | @file: memstore_limit_percentage.py 16 | @desc: 17 | """ 18 | 19 | from src.handler.checker.check_task import TaskBase 20 | 21 | 22 | class MemstoreLimitPercentage(TaskBase): 23 | 24 | def init(self, context, report): 25 | super().init(context, report) 26 | 27 | def execute(self): 28 | try: 29 | if self.ob_connector is None: 30 | return self.report.add_critical("can't build obcluster connection") 31 | memstore_limit_percentage_data = self.ob_connector.execute_sql_return_cursor_dictionary("select * from oceanbase.GV$OB_PARAMETERS where Name=\"memstore_limit_percentage\";").fetchall() 32 | 33 | for memstore_limit_percentage_one in memstore_limit_percentage_data: 34 | memstore_limit_percentage_value = memstore_limit_percentage_one.get("VALUE") 35 | svr_ip = memstore_limit_percentage_one.get("SVR_IP") 36 | if memstore_limit_percentage_value is None: 37 | return self.report.add_fail("get memstore_limit_percentage value error") 38 | memstore_limit_percentage_value = int(memstore_limit_percentage_value) 39 | if memstore_limit_percentage_value != 0 and memstore_limit_percentage_value != 50: 40 | self.report.add_warning("svr_ip: {1}. memstore_limit_percentage is {0}, recommended value is 0 or 50.".format(memstore_limit_percentage_value, svr_ip)) 41 | 42 | except Exception as e: 43 | self.stdio.error("execute error {0}".format(e)) 44 | return self.report.add_fail("execute error {0}".format(e)) 45 | 46 | def get_task_info(self): 47 | return {"name": "memstore_limit_percentage", "info": "Check the percentage of memory used by tenants using memstore to their total available memory. Suggest keeping the default value of 50. issue#871"} 48 | 49 | 50 | memstore_limit_percentage = MemstoreLimitPercentage() 51 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/mod_too_large.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether any module is using more than 10GB of memory.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: ' 7 | SELECT hold/1024/1024/1024 AS hold_g, used/1024/1024/1024 AS used_g 8 | FROM oceanbase.__all_virtual_memory_info 9 | order by hold desc limit 1;' 10 | result: 11 | set_value: mod_max_memory 12 | report_type: warning 13 | verify_type: max 14 | verify: 10 15 | err_msg: 'mod max memory over 10G,Please check on oceanbase.__all_virtual_memory_info to find some large mod' -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/no_leader.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check cluster tenant ls leader.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: "SELECT GROUP_CONCAT(DISTINCT TENANT_ID) 7 | FROM oceanbase.GV$OB_LOG_STAT 8 | HAVING COUNT(CASE WHEN ROLE = 'LEADER' THEN 1 END) = 0;" 9 | result: 10 | set_value: no_leader_tenant_id 11 | verify: '[ -z "${no_leader_tenant_id}" ]' 12 | err_msg: 'there is no leader tenant, please check the cluster. tenant_id: #{no_leader_tenant_id}. You can use "obdiag rca run --scene=log_error" to get more information.' -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/ob_enable_plan_cache_bad_version.yaml: -------------------------------------------------------------------------------- 1 | info: "when the version is between 4.1.0.0 and 4.1.0.1, the ob_enable_plan_cache suggestion to close" 2 | task: 3 | - version: "[4.1.0.0,4.1.0.1]" 4 | steps: 5 | - type: sql 6 | sql: 'select name from oceanbase.__all_virtual_tenant_parameter_stat where name like "%ob_enable_plan_cache%" and value like "%true%";' 7 | result: 8 | set_value: ob_enable_plan_cache 9 | verify: '[ -z "$ob_enable_plan_cache" ]' 10 | err_msg: 'On this version, ob_enable_plan_cache suggestion to close' 11 | 12 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/ob_enable_prepared_statement.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/05/6 15 | @file: ob_enable_prepared_statement.py 16 | @desc: 17 | """ 18 | 19 | from src.handler.checker.check_task import TaskBase 20 | 21 | 22 | class OBEnablePreparedStatement(TaskBase): 23 | 24 | def init(self, context, report): 25 | super().init(context, report) 26 | 27 | def execute(self): 28 | try: 29 | if self.ob_connector is None: 30 | return self.report.add_critical("can't build obcluster connection") 31 | ob_enable_prepared_statement_data = self.ob_connector.execute_sql_return_cursor_dictionary("SELECT * FROM oceanbase.__all_virtual_sys_parameter_stat WHERE name='_ob_enable_prepared_statement';").fetchall() 32 | 33 | for ob_enable_prepared_statement_one in ob_enable_prepared_statement_data: 34 | ob_enable_prepared_statement_value = ob_enable_prepared_statement_one.get("value") 35 | svr_ip = ob_enable_prepared_statement_one.get("svr_ip") 36 | if ob_enable_prepared_statement_value is None: 37 | return self.report.add_fail("get ob_enable_prepared_statement value error") 38 | if ob_enable_prepared_statement_value.lower() != "true": 39 | self.report.add_warning("svr_ip: {1}. ob_enable_prepared_statement is {0}, recommended value is True.".format(ob_enable_prepared_statement_value, svr_ip)) 40 | 41 | except Exception as e: 42 | self.stdio.error("execute error {0}".format(e)) 43 | return self.report.add_fail("execute error {0}".format(e)) 44 | 45 | def get_task_info(self): 46 | return {"name": "ob_enable_prepared_statement", "info": "Check whether prepared statement is enabled. It is recommended to enable it, especially the front end is JAVA application. issue#844"} 47 | 48 | 49 | ob_enable_prepared_statement = OBEnablePreparedStatement() 50 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/observer_not_active.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether there is any observer not in the ACTIVE state.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.DBA_OB_SERVERS where STATUS<>"ACTIVE";' 7 | result: 8 | set_value: not_ACTIVE 9 | verify_type: equal 10 | verify: 0 11 | err_msg: 'There is #{not_ACTIVE} not_ACTIVE observer, please check as soon as possible.' 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/optimizer_better_inlist_costing_parmmeter.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check if the tag parameter for a specific version is enabled.' 2 | task: 3 | - version: "[4.1.0.0,4.1.0.2]" 4 | steps: 5 | - type: sql 6 | sql: 'select name from oceanbase.__all_virtual_tenant_parameter_stat where name like "%_optimizer_better_inlist_costing%" and value like "%true%";' 7 | result: 8 | set_value: optimizer_better_inlist_costing 9 | verify: '[ -z "$optimizer_better_inlist_costing" ]' 10 | err_msg: '_optimizer_better_inlist_costing need close. Triggering this issue can lead to correctness issues, causing random errors or core issues.' 11 | - version: "[4.2.0.0,4.2.0.0]" 12 | steps: 13 | - type: sql 14 | sql: 'select name from oceanbase.__all_virtual_tenant_parameter_stat where name like "%_optimizer_better_inlist_costing%" and value like "%true%";' 15 | result: 16 | set_value: optimizer_better_inlist_costing 17 | verify: '[ -z "$optimizer_better_inlist_costing" ]' 18 | err_msg: '_optimizer_better_inlist_costing need close. Triggering this issue can lead to correctness issues, causing random errors or core issues.' 19 | 20 | 21 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/part_trans_action_max.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether there are more than 200 transaction participants' 2 | task: 3 | - version: "[3.0.0.0,4.0.0.0)" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.__all_virtual_trans_stat where part_trans_action > 2;' 7 | result: 8 | set_value: transaction_participants 9 | verify_type: equal 10 | report_type: execution 11 | verify: 0 12 | err_msg: 'transaction_participants is #{transaction_participants} , need check transaction_participants_max' 13 | - type: sql 14 | sql: 'select count(0) from oceanbase.__all_virtual_trans_stat where part_trans_action > 2 group by trans_id;' 15 | result: 16 | set_value: transaction_participants_max 17 | verify_type: max 18 | verify: 200 19 | err_msg: 'part_trans_action_max is #{transaction_participants_max} , over 200' -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/resource_limit_max_session_num.yaml: -------------------------------------------------------------------------------- 1 | info: "Check if the resourcelimit_max_sessionnum parameter has been changed, as this may result in Too many connections reporting errors." 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: "SELECT GROUP_CONCAT(DISTINCT TENANT_ID) FROM oceanbase.GV$OB_PARAMETERS WHERE NAME LIKE '_resource_limit_max_session_num' and VALUE<>0;" 7 | result: 8 | set_value: resource_limit_max_session_num 9 | verify: '[ -z "${resource_limit_max_session_num}" ]' 10 | err_msg: "_resource_limit_max_session_num is not recommended. Set it within the range of 0. It may result in Too many connections reporting errors. tenant_id : #{resource_limit_max_session_num}" -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/server_permanent_offline_time.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/04/8 15 | @file: server_permanent_offline_time.py 16 | @desc: 17 | """ 18 | from src.handler.checker.check_task import TaskBase 19 | 20 | 21 | class ServerPermanentOfflineTime(TaskBase): 22 | 23 | def init(self, context, report): 24 | super().init(context, report) 25 | self.expected_value = "3600s" # expected_value 26 | self.param_name = "server_permanent_offline_time" # param_name 27 | 28 | def execute(self): 29 | try: 30 | if self.ob_connector is None: 31 | return self.report.add_fail("can't build obcluster connection") 32 | 33 | sql = "select * from oceanbase.GV$OB_PARAMETERS where name='{0}';".format(self.param_name) 34 | result = self.ob_connector.execute_sql_return_cursor_dictionary(sql).fetchall() 35 | 36 | if not result: 37 | return self.report.add_warning("can't find this param_name") 38 | 39 | non_compliant_nodes = [] 40 | 41 | for data_item in result: 42 | svr_ip = data_item['SVR_IP'] 43 | value = data_item['VALUE'] 44 | if value != self.expected_value: 45 | non_compliant_nodes.append(svr_ip) 46 | 47 | if non_compliant_nodes: 48 | nodes_str = ", ".join(non_compliant_nodes) 49 | return self.report.add_warning(f"this server's server_permanent_offline_time!=3600s, please check: {nodes_str}") 50 | 51 | except Exception as e: 52 | self.stdio.error("execute error {0}".format(e)) 53 | return self.report.add_fail("execute error {0}".format(e)) 54 | 55 | def get_task_info(self): 56 | return {"name": "server_permanent_offline_time", "info": "check the cluster parameters of server_permanent_offline_time . issue #816"} 57 | 58 | 59 | server_permanent_offline_time = ServerPermanentOfflineTime() 60 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/sys_log_level.yaml: -------------------------------------------------------------------------------- 1 | info: "Check sys_log_level ." 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'SELECT value FROM oceanbase.__all_virtual_sys_parameter_stat where name like "%syslog_level%";' 7 | result: 8 | set_value: sys_log_level 9 | report_type: warning 10 | verify: '[[ $sys_log_level == "WDIAG" ]]' 11 | err_msg: "sys_log_level: #{sys_log_level}. on 4.x, the recommended value for sys_log_level is WDIAG" 12 | 13 | - version: "[3.0.0,4.0.0.0)" 14 | steps: 15 | - type: sql 16 | sql: 'SELECT value FROM oceanbase.__all_virtual_sys_parameter_stat where name like "%syslog_level%";' 17 | result: 18 | set_value: sys_log_level 19 | report_type: warning 20 | verify: '[[ $sys_log_level == "INFO" ]]' 21 | err_msg: "sys_log_level: #{sys_log_level}. on 3.x, the recommended value for sys_log_level is INFO" 22 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/sys_obcon_health.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/04/8 15 | @file: sys_obcon_health.py 16 | @desc: 17 | """ 18 | 19 | from src.handler.checker.check_task import TaskBase 20 | 21 | 22 | class SysObconHealth(TaskBase): 23 | 24 | def init(self, context, report): 25 | super().init(context, report) 26 | 27 | def execute(self): 28 | try: 29 | pass_tag = True 30 | if self.ob_connector is None: 31 | return self.report.add_critical("can't build obcluster connection") 32 | build_version_data = self.ob_connector.execute_sql_return_cursor_dictionary("select version() ").fetchall() 33 | if len(build_version_data) != 1: 34 | return self.report.add_critical("can not build sys") 35 | except Exception as e: 36 | self.stdio.error("execute error {0}".format(e)) 37 | return self.report.add_fail("execute error {0}".format(e)) 38 | 39 | def get_task_info(self): 40 | return {"name": "sys_obcon_health", "info": "Check if the cluster is connected by connecting to the sys tenant. issue#872"} 41 | 42 | 43 | sys_obcon_health = SysObconHealth() 44 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/table_history_too_many.yaml: -------------------------------------------------------------------------------- 1 | info: "There are too many table histories for a tenant in the cluster, and when the machine restarts, the schema refresh will continue to report -4013, resulting in the inability to refresh the corresponding tenant's schema for a particular machine." 2 | task: 3 | - version: "[4.1.0.1,4.1.0.2]" 4 | steps: 5 | - type: sql 6 | sql: 'select table_name from oceanbase.__all_virtual_table_history group by 1 having count(*) > 4000000;' 7 | result: 8 | set_value: table_name 9 | verify: '[ -z "table_name" ]' 10 | err_msg: "There are too many table histories for a tenant in the cluster, and when the machine restarts, the schema refresh will continue to report -4013, resulting in the inability to refresh the corresponding tenant's schema for a particular machine." 11 | 12 | 13 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/task_opt_stat.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check task opt stat gather history.' 2 | task: 3 | - version: "[4.2.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'SELECT GROUP_CONCAT(DISTINCT TENANT_ID) 7 | FROM oceanbase.__all_tenant t 8 | WHERE NOT EXISTS(SELECT 1 9 | FROM oceanbase.__all_virtual_task_opt_stat_gather_history h 10 | WHERE TYPE = 1 11 | AND start_time > date_sub(now(), interval 1 day) 12 | AND h.tenant_id = t.tenant_id);' 13 | result: 14 | set_value: failed_scheduler_tenant_id 15 | verify: '[ -z "${failed_scheduler_tenant_id}" ]' 16 | err_msg: "The collection of statistical information related to tenants has issues.. Please check the tenant_ids: #{failed_scheduler_tenant_id}" -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/task_opt_stat_gather_fail.yaml: -------------------------------------------------------------------------------- 1 | info: "Check whether there are any failed execution results for history collection tasks" 2 | task: 3 | - version: "[4.2.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'SELECT count(0) FROM oceanbase.DBA_OB_TASK_OPT_STAT_GATHER_HISTORY where STATUS<>"SUCCESS";' 7 | result: 8 | set_value: major_err_nu 9 | verify_type: equal 10 | verify: 0 11 | err_msg: "task_opt_stat_gather_fail" -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/tenant_number.yaml: -------------------------------------------------------------------------------- 1 | info: "Check the number of tenant" 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0)/2 from oceanbase.__all_tenant where tenant_id>1000;' 7 | result: 8 | set_value: tenant_nu 9 | verify_type: max 10 | verify: 100 11 | err_msg: "The number of tenants: #{tenant_nu}.recommended: tenant_nu<50" 12 | - type: sql 13 | sql: 'select count(0)/2 from oceanbase.__all_tenant where tenant_id>1000;' 14 | result: 15 | set_value: tenant_nu 16 | verify_type: max 17 | report_type: warning 18 | verify: 50 19 | err_msg: "The number of tenants: #{tenant_nu}.recommended: tenant_nu<50" -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cluster/zone_not_active.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether there is any zone not in the ACTIVE state.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select GROUP_CONCAT(DISTINCT ZONE) from oceanbase.dba_ob_zones where STATUS<>"ACTIVE";' 7 | result: 8 | set_value: not_ACTIVE 9 | verify: '[ -z "${not_ACTIVE}" ]' 10 | err_msg: 'There is #{not_ACTIVE} not_ACTIVE zone, please check as soon as possible.' 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/cpu/oversold.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether there is any observer have CPU oversold.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: "SELECT GROUP_CONCAT(CONCAT(SVR_IP, ':', SVR_PORT) SEPARATOR ', ') AS IP_PORT_COMBINATIONSFROM from oceanbase.GV$OB_SERVERS WHERE CPU_ASSIGNED > CPU_CAPACITY;" 7 | result: 8 | set_value: CPU_oversold 9 | verify: '[ -z "$CPU_oversold" ]' 10 | report_type: warning 11 | err_msg: 'Some observers have CPU oversold. There are #{CPU_oversold}' 12 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/disk/clog_abnormal_file.yaml: -------------------------------------------------------------------------------- 1 | 2 | info: "Check if there are files in the clog folder that do not belong to the observer" 3 | task: 4 | - version: "[4.0.0.0,*]" 5 | steps: 6 | - type: ssh 7 | ssh: 'find #{remote_redo_dir}/ -name "clog"' 8 | result: 9 | set_value: log_dir_path 10 | verify: '[ -n "${log_dir_path}" ]' 11 | err_msg: "log_dir_path is null . Please check your nodes.redo_dir need absolute Path" 12 | - type: ssh 13 | ssh: "find #{log_dir_path}/ -type f -name '*[^0-9]*' ! -name '*.tmp' ! -name '*.flashback' ! -name 'meta'" 14 | result: 15 | set_value: files 16 | verify: '[ -z "${files}" ]' 17 | err_msg: "Users are not allowed to modify or create in the clog folder, It will be causing observer startup failure. Files need be checked: #{files}" 18 | 19 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/disk/disk_full.yaml: -------------------------------------------------------------------------------- 1 | 2 | info: "Check whether the disk usage has reached the threshold." 3 | task: 4 | - version: "[4.0.0.0,*]" 5 | steps: 6 | - type: sql 7 | sql: 'SELECT count(0) FROM oceanbase.GV$OB_SERVERS where DATA_DISK_IN_USE*100/DATA_DISK_CAPACITY >80;' 8 | result: 9 | set_value: over_nu 10 | report_type: warning 11 | verify_type: equal 12 | verify: 0 13 | err_msg: "data disk usage exceeds 80% of capacity" 14 | - type: sql 15 | sql: 'SELECT count(0) FROM oceanbase.GV$OB_SERVERS where DATA_DISK_IN_USE*100/DATA_DISK_CAPACITY >90;' 16 | result: 17 | set_value: over_nu 18 | verify_type: equal 19 | report_type: warning 20 | verify: 0 21 | err_msg: "data disk usage exceeds 90% of capacity" 22 | - type: sql 23 | sql: 'SELECT count(0) FROM oceanbase.GV$OB_SERVERS where LOG_DISK_IN_USE*100/LOG_DISK_CAPACITY >80;' 24 | result: 25 | set_value: over_nu 26 | report_type: warning 27 | verify_type: equal 28 | verify: 0 29 | err_msg: "log disk usage exceeds 80% of capacity" 30 | - type: sql 31 | sql: 'SELECT count(0) FROM oceanbase.GV$OB_SERVERS where LOG_DISK_IN_USE*100/LOG_DISK_CAPACITY >90;' 32 | result: 33 | set_value: over_nu 34 | verify_type: equal 35 | report_type: warning 36 | verify: 0 37 | err_msg: "log disk usage exceeds 90% of capacity" 38 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/disk/disk_hole.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether there is a disk hole issue.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: "select sum(DATA_SIZE) as da from oceanbase.CDB_OB_TABLET_REPLICAS group by tenant_id ORDER BY da DESC limit 1;" 7 | result: 8 | set_value: not_ACTIVE 9 | report_type: execution 10 | verify_type: equal 11 | verify: 0 12 | err_msg: '[not warning] the DATA_SIZE is not 0 . need check sum(REQUIRED_SIZE)/sum(DATA_SIZE)' 13 | - type: sql 14 | sql: "select sum(REQUIRED_SIZE)/sum(DATA_SIZE) as da from oceanbase.CDB_OB_TABLET_REPLICAS group by tenant_id ORDER BY da DESC limit 1;" 15 | result: 16 | set_value: not_ACTIVE 17 | report_type: warning 18 | verify_type: max 19 | verify: 1000 20 | err_msg: 'There may be a problem of disk holes.Please check oceanbase.CDB_OB_TABLET_REPLICAS group by tenant_id ORDER BY da DESC ' 21 | - version: "[*,3.2.0]" 22 | steps: 23 | - type: sql 24 | sql: "select sum(REQUIRED_SIZE)/sum(DATA_SIZE) as da from oceanbase.__all_virtual_meta_table group by tenant_id ORDER BY da DESC limit 1;" 25 | result: 26 | set_value: not_ACTIVE 27 | report_type: warning 28 | verify_type: max 29 | verify: 1000 30 | err_msg: 'There may be an issue with empty disks' 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/disk/disk_iops.yaml: -------------------------------------------------------------------------------- 1 | info: "Check whether the disk iops." 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: "SELECT GROUP_CONCAT(DISTINCT CONCAT(SVR_IP, ':', SVR_PORT) SEPARATOR ', ') AS unique_server_endpoints 7 | FROM oceanbase.GV$OB_IO_BENCHMARK 8 | WHERE size=16384 AND IOPS<1024;" 9 | result: 10 | set_value: over_server 11 | verify: '[ -z "${over_server}" ]' 12 | err_msg: "These observer 16K IOPS are below 1024, please migrate as soon as possible. #{over_server}" -------------------------------------------------------------------------------- /plugins/check/tasks/observer/disk/sstable_abnormal_file.yaml: -------------------------------------------------------------------------------- 1 | 2 | info: "Check if there are files in the clog folder that do not belong to the observer" 3 | task: 4 | - version: "[4.0.0.0,*]" 5 | steps: 6 | - type: ssh 7 | ssh: 'find #{remote_data_dir}/ -name "sstable"' 8 | result: 9 | set_value: sstable_dir_path 10 | verify: '[ -n "${sstable_dir_path}" ]' 11 | err_msg: "sstable_dir_path is null . Please check your nodes.data_dir need absolute Path" 12 | - type: ssh 13 | ssh: "find #{sstable_dir_path}/ -type f ! -name block_file" 14 | result: 15 | set_value: files 16 | verify: '[ -z "${files}" ]' 17 | err_msg: "Users are not allowed to modify or create in the dir_path folder, It will be causing observer startup failure. Files need be checked: #{files}" 18 | 19 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/disk/xfs_repair.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check dmesg for xfs_repair log. issue #451' 2 | task: 3 | - version: "[4.2.0.0,*]" 4 | steps: 5 | - type: ssh 6 | ssh: 'dmesg -T | grep -m 1 "xfs_repair" ' 7 | result: 8 | set_value: xfs_repair_log 9 | verify: '[ -z "${xfs_repair_log}" ]' 10 | err_msg: "xfs need repair. Please check disk. xfs_repair_log: #{xfs_repair_log}" 11 | 12 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/err_code/find_err_4000.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether Error 4000 is reported when enable_sql_audit is set to True.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where NAME="enable_sql_audit" and VALUE<>"True" ;' 7 | result: 8 | set_value: sql_audit 9 | # report_type: warning 10 | verify_type: equal 11 | verify: 0 12 | err_msg: 'Unable to proceed because enable_sql_audit is set to False' 13 | - type: sql 14 | sql: 'select count(0) from oceanbase.GV$OB_SQL_AUDIT where RET_CODE ="-4000";' 15 | result: 16 | set_value: err_4000 17 | verify_type: equal 18 | verify: 0 19 | err_msg: 'number of sql_error_4000 is #{err_4000}' 20 | 21 | 22 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/err_code/find_err_4001.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether Error 4001 is reported when enable_sql_audit is set to True.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where NAME="enable_sql_audit" and VALUE<>"True" ;' 7 | result: 8 | set_value: sql_audit 9 | # report_type: warning 10 | verify_type: equal 11 | verify: 0 12 | err_msg: 'Unable to proceed because enable_sql_audit is set to False' 13 | - type: sql 14 | sql: 'select count(0) from oceanbase.GV$OB_SQL_AUDIT where RET_CODE ="-4001";' 15 | result: 16 | set_value: err_4001 17 | verify_type: equal 18 | verify: 0 19 | err_msg: 'number of sql_error_4001 is #{err_4001}' 20 | 21 | 22 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/err_code/find_err_4012.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether Error 4012 is reported when enable_sql_audit is set to True.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where NAME="enable_sql_audit" and VALUE<>"True" ;' 7 | result: 8 | set_value: sql_audit 9 | # report_type: warning 10 | verify_type: equal 11 | verify: 0 12 | err_msg: 'Unable to proceed because enable_sql_audit is set to False' 13 | - type: sql 14 | sql: 'select count(0) from oceanbase.GV$OB_SQL_AUDIT where RET_CODE ="-4012";' 15 | result: 16 | set_value: err_4012 17 | report_type: warning 18 | verify_type: max 19 | verify: 100 20 | err_msg: 'number of sql_error_4012 is #{err_4012}' 21 | 22 | 23 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/err_code/find_err_4013.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether Error 4013 is reported when enable_sql_audit is set to True.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where NAME="enable_sql_audit" and VALUE<>"True" ;' 7 | result: 8 | set_value: sql_audit 9 | # report_type: warning 10 | verify_type: equal 11 | verify: 0 12 | err_msg: 'Unable to proceed because enable_sql_audit is set to False' 13 | - type: sql 14 | sql: "select count(0) from oceanbase.GV$OB_SQL_AUDIT where RET_CODE ='-4013';" 15 | result: 16 | set_value: err_4013 17 | report_type: warning 18 | verify_type: max 19 | verify: 100 20 | err_msg: 'number of sql_error_4013 is #{err_4013}' 21 | 22 | 23 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/err_code/find_err_4015.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether Error 4015 is reported when enable_sql_audit is set to True.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where NAME="enable_sql_audit" and VALUE<>"True" ;' 7 | result: 8 | set_value: sql_audit 9 | # report_type: warning 10 | verify_type: equal 11 | verify: 0 12 | err_msg: 'Unable to proceed because enable_sql_audit is set to False' 13 | - type: sql 14 | sql: 'select count(0) from oceanbase.GV$OB_SQL_AUDIT where RET_CODE ="-4015";' 15 | result: 16 | report_type: warning 17 | set_value: err_4015 18 | verify_type: equal 19 | verify: 0 20 | err_msg: 'number of sql_error_4015 is #{err_4015}' 21 | 22 | 23 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/err_code/find_err_4016.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether Error 4016 is reported when enable_sql_audit is set to True.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where NAME="enable_sql_audit" and VALUE<>"True" ;' 7 | result: 8 | set_value: sql_audit 9 | # report_type: warning 10 | verify_type: equal 11 | verify: 0 12 | err_msg: 'Unable to proceed because enable_sql_audit is set to False' 13 | - type: sql 14 | sql: 'select count(0) from oceanbase.GV$OB_SQL_AUDIT where RET_CODE ="-4016";' 15 | result: 16 | report_type: warning 17 | set_value: err_4016 18 | verify_type: equal 19 | verify: 0 20 | err_msg: 'number of sql_error_4016 is #{err_4016}' 21 | 22 | 23 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/err_code/find_err_4103.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether Error 4103 is reported when enable_sql_audit is set to True.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where NAME="enable_sql_audit" and VALUE<>"True" ;' 7 | result: 8 | set_value: sql_audit 9 | # report_type: warning 10 | verify: "[ '0' == ${sql_audit} ]" 11 | err_msg: 'Unable to proceed because enable_sql_audit is set to False' 12 | - type: sql 13 | sql: 'select count(0) from oceanbase.GV$OB_SQL_AUDIT where RET_CODE ="-4103";' 14 | result: 15 | set_value: err_4103 16 | verify_type: equal 17 | verify: 0 18 | err_msg: 'number of sql_error_4103 is #{err_4103}' 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/err_code/find_err_4105.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether Error 4105 is reported when enable_sql_audit is set to True.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where NAME="enable_sql_audit" and VALUE<>"True" ;' 7 | result: 8 | set_value: sql_audit 9 | # report_type: warning 10 | verify: "[ '0' == ${sql_audit} ]" 11 | err_msg: 'Unable to proceed because enable_sql_audit is set to False' 12 | - type: sql 13 | sql: 'select count(0) from oceanbase.GV$OB_SQL_AUDIT where RET_CODE ="-4105";' 14 | result: 15 | set_value: err_4105 16 | verify_type: equal 17 | verify: 0 18 | err_msg: 'number of sql_error_4105 is #{err_4105}' 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/err_code/find_err_4108.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether Error 4108 is reported when enable_sql_audit is set to True.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where NAME="enable_sql_audit" and VALUE<>"True" ;' 7 | result: 8 | set_value: sql_audit 9 | # report_type: warning 10 | verify: "[ '0' == ${sql_audit} ]" 11 | err_msg: 'Unable to proceed because enable_sql_audit is set to False' 12 | - type: sql 13 | sql: 'select count(0) from oceanbase.GV$OB_SQL_AUDIT where RET_CODE ="-4108";' 14 | result: 15 | set_value: err_4108 16 | verify_type: equal 17 | verify: 0 18 | err_msg: 'number of sql_error_4108 is #{err_4108}. maybe the disk is damaged.' 19 | - type: ssh 20 | ssh: "grep \"checksum error\" #{remote_home_path}/log/observer.log | awk '{print $1}'" 21 | result: 22 | set_value: checksum_error_log 23 | verify: '[ -z "$checksum_error_log" ]' 24 | err_msg: "node #{remote_ip} has checksum error log in #{remote_home_path}/log/observer.log . maybe the disk is damaged. please check it." 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/err_code/find_err_4377.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check whether Error 4377 is reported when enable_sql_audit is set to True.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where NAME="enable_sql_audit" and VALUE<>"True" ;' 7 | result: 8 | set_value: sql_audit 9 | # report_type: warning 10 | verify: "[ '0' == ${sql_audit} ]" 11 | err_msg: 'Unable to proceed because enable_sql_audit is set to False' 12 | - type: sql 13 | sql: 'select count(0) from oceanbase.GV$OB_SQL_AUDIT where RET_CODE ="-4377";' 14 | result: 15 | set_value: err_4377 16 | verify_type: equal 17 | verify: 0 18 | err_msg: 'number of sql_error_4377 is #{err_4377}' 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/log/log_size.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/04/8 15 | @file: log_size.py 16 | @desc: 17 | """ 18 | 19 | from src.handler.checker.check_task import TaskBase 20 | 21 | 22 | class LogSize(TaskBase): 23 | 24 | def init(self, context, report): 25 | super().init(context, report) 26 | 27 | def execute(self): 28 | try: 29 | if self.ob_connector is None: 30 | return self.report.add_critical("can't build obcluster connection") 31 | log_size_data = self.ob_connector.execute_sql_return_cursor_dictionary("select * FROM oceanbase.GV$OB_PARAMETERS where name=\"max_syslog_file_count\";").fetchall() 32 | if len(log_size_data) < 1: 33 | return self.report.add_fail("get log_size data error") 34 | for log_size_one in log_size_data: 35 | # check VALUE is exist 36 | log_size_value = log_size_one.get("VALUE") 37 | if log_size_value is None: 38 | return self.report.add_critical("get log_size value error") 39 | SVR_IP = log_size_one.get("SVR_IP") 40 | log_size_value = int(log_size_value) 41 | if log_size_value == 0 or log_size_value > 100: 42 | pass 43 | else: 44 | self.report.add_warning("node: {1} max_syslog_file_count is {0}, please check. the recommended is 0 or over 100".format(log_size_value, SVR_IP)) 45 | 46 | except Exception as e: 47 | self.stdio.error("execute error {0}".format(e)) 48 | return self.report.add_fail("execute error {0}".format(e)) 49 | 50 | def get_task_info(self): 51 | return {"name": "log_size", "info": "check obcluster max_syslog_file_count is 0 or over 100"} 52 | 53 | 54 | log_size = LogSize() 55 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/log/log_size_with_ocp.yaml: -------------------------------------------------------------------------------- 1 | 2 | info: "check log_dir free space is over the size of 100 file" 3 | task: 4 | - version: "[4.0.0.0,*]" 5 | steps: 6 | - type: ssh 7 | ssh: "echo \"/home/admin/ocp_agent/conf/config_properties/ob_logcleaner.yaml\" " 8 | result: 9 | set_value: ob_logcleaner_file_path 10 | verify: '[ ! -e "${ob_logcleaner_file_path}" ]' 11 | report_type: execution 12 | err_msg: "[not warning] ob_logcleaner.yaml is exist . This node is not deployed by ocp." 13 | - type: ssh 14 | ssh: "echo \"/home/admin/ocp_agent/conf/config_properties/ob_logcleaner.yaml\" |grep \"ob.logcleaner.ob_log.disk.threshold\" -A1 | grep -oE '[0-9]+'" 15 | result: 16 | set_value: ob_logcleaner_file_nu 17 | verify: 79 18 | verify_type: min 19 | report_type: warning 20 | err_msg: "ocp ob.logcleaner.ob_log.disk.threshold is less 80%" 21 | - type: ssh 22 | ssh: "df #{home_path}/log/ | awk 'NR==2{print int($4*#{ob_logcleaner_file_nu}/100)}'" 23 | result: 24 | set_value: disk_free_space_KB 25 | - type: ssh 26 | ssh: "find #{home_path}/log/ -type f -name \"*.log*\" | wc -l | xargs -I {} echo {} | awk '{print (100-$1) * 256 * 1024}' " 27 | result: 28 | set_value: log_dir_need_space 29 | verify: '[ $disk_free_space_KB -gt $log_dir_need_space ]' 30 | err_msg: "disk_free_space_KB < log_dir_need_space. disk_free_space_KB:#{disk_free_space_KB}KB, log_dir_need_space:#{log_dir_need_space}KB" 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/network/TCP-retransmission.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check TCP retransmission. From https://github.com/oceanbase/obdiag/issues/348' 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: 'if command -v tsar &>/dev/null; then echo "exist"; fi' 6 | result: 7 | set_value: tsar_exist 8 | verify: '[ "exist" == "${tsar_exist}" ]' 9 | err_msg: 'tsar is not installed. we can not check tcp retransmission.' 10 | - type: ssh 11 | ssh: "tsar --check --tcp -s retran | awk -F '=' '{print $2}'" 12 | result: 13 | set_value: tcp_retransmission 14 | verify_type: max 15 | verify: 10 16 | err_msg: 'tcp retransmission is too high, over 10%.' 17 | 18 | 19 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/network/network_drop.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check cluster info about network_drop' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select VALUE from oceanbase.GV$OB_PARAMETERS where NAME="devname" and SVR_IP="#{remote_ip}" ;' 7 | result: 8 | set_value: network_name 9 | # network error 10 | - type: ssh 11 | ssh: "ip -s link show #{network_name} | awk '/RX:/ {getline; print $3}'" 12 | result: 13 | set_value: rx_error 14 | verify_type: equal 15 | verify: 0 16 | err_msg: 'network: #{network_name} RX error is not 0, please check by ip -s link show #{network_name} ' 17 | - type: ssh 18 | ssh: "ip -s link show #{network_name} | awk '/TX:/ {getline; print $3}'" 19 | result: 20 | set_value: tx_error 21 | verify_type: equal 22 | verify: 0 23 | err_msg: 'network: #{network_name} TX error is not 0, please check by ip -s link show #{network_name} ' 24 | # network drop 25 | - type: ssh 26 | ssh: "ip -s link show #{network_name} | awk '/RX:/ {getline; print $4}'" 27 | result: 28 | set_value: rx_drop 29 | verify_type: equal 30 | verify: 0 31 | err_msg: 'network: #{network_name} RX drop is not 0, please check by ip -s link show #{network_name} ' 32 | - type: ssh 33 | ssh: "ip -s link show #{network_name} | awk '/TX:/ {getline; print $4}'" 34 | result: 35 | set_value: tx_drop 36 | verify_type: equal 37 | verify: 0 38 | err_msg: 'network: #{network_name} TX drop is not 0, please check by ip -s link show #{network_name} ' -------------------------------------------------------------------------------- /plugins/check/tasks/observer/network/network_offset.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check cluster info about network clockdiff offset' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: local_ssh 6 | ssh: 'if command -v clockdiff &>/dev/null; then echo "exist"; fi' 7 | result: 8 | set_value: clockdiff_exist 9 | report_type: execution 10 | verify: '[ "exist" != "${clockdiff_exist}" ]' 11 | err_msg: '[not warning] clockdiff is exist. We will check the clockdiff' 12 | - type: local_ssh 13 | ssh: 'clockdiff -o #{remote_ip}' 14 | result: 15 | set_value: clockdiff 16 | verify: '[[ ! $clockdiff == *"is down"* ]]' 17 | #report_type: warning 18 | err_msg: "node: #{remote_ip} can not get clock offset by 'clockdiff -o #{remote_ip}', doc: https://www.oceanbase.com/knowledge-base/ocp-ee-1000000000346970?back=kb" 19 | - type: local_ssh 20 | ssh: "echo \"#{clockdiff}\" | awk '{print $2}'" 21 | result: 22 | set_value: offset 23 | verify_type: max 24 | verify: 50 25 | err_msg: "node: #{remote_ip} clock offset is #{offset}, it is over 50ms, issue: https://github.com/oceanbase/obdiag/issues/701" 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/network/network_speed.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check cluster info about network_speed' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select VALUE from oceanbase.GV$OB_PARAMETERS where NAME="devname" and SVR_IP="#{remote_ip}" ;' 7 | result: 8 | set_value: network_name 9 | verify: '[[ ! $network_name == "lo" ]]' 10 | err_msg: "check network_name is lo , can not get real speed" 11 | # for k8s 12 | - type: ssh 13 | ssh: "ethtool #{network_name} 2>/dev/null| grep Speed" 14 | result: 15 | set_value: network_speed 16 | verify: '[[ ! -z "$network_speed" ]]' 17 | #report_type: warning 18 | err_msg: "network_speed is null , can not get real speed" 19 | - type: ssh 20 | ssh: "ethtool #{network_name} 2>/dev/null| grep Speed" 21 | result: 22 | set_value: network_speed 23 | verify: '[[ ! $network_speed == *"Unknown"* ]]' 24 | #report_type: warning 25 | err_msg: "network_speed is #{network_speed}, can not get real speed" 26 | - type: ssh 27 | ssh: "ethtool #{network_name} 2>/dev/null | grep Speed | grep -o '[0-9]*'" 28 | result: 29 | set_value: network_speed 30 | verify_type: min 31 | verify: 999 32 | #report_type: warning 33 | err_msg: "network_speed is #{network_speed} , less than 1000" 34 | - type: ssh 35 | ssh: "ethtool #{network_name} 2>/dev/null | grep Speed | grep -o '[0-9]*'" 36 | result: 37 | set_value: network_speed 38 | verify_type: min 39 | verify: 9999 40 | report_type: warning 41 | err_msg: "network_speed is #{network_speed} , less than 10000, Unpredictable anomalies are prone to occur in backup scenarios, it is recommended to upgrade to 10Gbps" 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_free_test_cpu_count.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check when sysbench free , cluster info about memory_limit' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select VALUE from oceanbase.GV$OB_PARAMETERS where Name="cpu_count";' 7 | result: 8 | set_value: cpu_count 9 | verify_type: equal 10 | report_type: execution 11 | verify: 0 12 | err_msg: 'cpu_count is #{cpu_count} , need to calculate the relationship between cpu_count and the number of system CPUs' 13 | - type: ssh 14 | ssh: "lscpu | grep '^CPU(s):' | awk '{print $2}'" 15 | result: 16 | set_value: os_cpu_count 17 | - type: ssh 18 | ssh: 'echo "#{cpu_count}*100/#{os_cpu_count}" | bc' 19 | result: 20 | set_value: result 21 | verify_type: between 22 | verify: "[90,100]" 23 | err_msg: 'cpu_count/os_cpu_count is #{result}%,is not between 80 and 100' 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_free_test_memory_limit.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check when sysbench free , cluster info about memory_limit' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select VALUE from oceanbase.GV$OB_PARAMETERS where NAME="memory_limit" and SVR_IP="#{remote_ip}";' 7 | result: 8 | set_value: memory_limit_data 9 | - type: ssh 10 | ssh: "echo #{memory_limit_data}|awk '{print $1 * 100}'" 11 | result: 12 | set_value: memory_limit 13 | - type: sql 14 | sql: 'select VALUE from oceanbase.GV$OB_PARAMETERS where NAME="memory_limit_percentage" and SVR_IP="#{remote_ip}";' 15 | result: 16 | set_value: memory_limit_percentage 17 | - type: ssh 18 | ssh: "free -m | grep Mem | awk '{print int($2/1024)}'" 19 | result: 20 | set_value: os_memory 21 | # check memory_limit 22 | - type: ssh 23 | ssh: '[ #{memory_limit} -eq 0 ] && echo "#{os_memory} * #{memory_limit_percentage} / 100" | bc || echo #{memory_limit}' 24 | result: 25 | set_value: memory_limit 26 | 27 | - type: ssh 28 | ssh: 'echo "#{memory_limit}/#{os_memory}" | bc' 29 | result: 30 | set_value: result 31 | verify_type: between 32 | verify: "[80,100]" 33 | err_msg: 'memory_limit: #{memory_limit}. os_memory: #{os_memory}. memory_limit/os_memory is #{result}%,is not between 80% and 100%' 34 | 35 | # memory_size 36 | - type: sql 37 | sql: "SELECT GROUP_CONCAT(DISTINCT TENANT_NAME) FROM OCEANBASE.DBA_OB_TENANTS t1,OCEANBASE.DBA_OB_UNITS t2,OCEANBASE.DBA_OB_UNIT_CONFIGS t3,OCEANBASE.DBA_OB_RESOURCE_POOLS t4 38 | where t1.tenant_id = t4.tenant_id 39 | AND t4.resource_pool_id=t2.resource_pool_id 40 | AND t4.unit_config_id=t3.unit_config_id 41 | and t2.svr_ip='#{remote_ip}' 42 | and t1.tenant_id>1000 43 | and t3.MEMORY_SIZE/1024/1024/1024<(#{memory_limit}*0.8) 44 | ORDER BY t1.tenant_name;" 45 | result: 46 | set_value: memory_size_not_check_TENANT_NAME 47 | report_type: warning 48 | verify: '[ -z "${memory_size_not_check_TENANT_NAME}" ]' 49 | err_msg: 'memory_size should over memory_limit*80%. tenant: #{memory_size_not_check_TENANT_NAME} need check' 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_free_test_network_speed.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check when sysbench free , cluster info about network_speed' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select VALUE from oceanbase.GV$OB_PARAMETERS where NAME="devname" and SVR_IP="#{remote_ip}" ;' 7 | result: 8 | set_value: network_name 9 | - type: ssh 10 | ssh: "ethtool #{network_name} 2>/dev/null| grep Speed" 11 | result: 12 | set_value: network_speed 13 | verify: '[[ ! $network_speed == *"Unknown"* ]]' 14 | #report_type: warning 15 | err_msg: "network_speed is #{network_speed}, can not get real speed" 16 | - type: ssh 17 | ssh: "ethtool #{network_name} 2>/dev/null | grep Speed | grep -o '[0-9]*'" 18 | result: 19 | set_value: network_speed 20 | verify_type: min 21 | verify: 999 22 | #report_type: warning 23 | err_msg: "network_speed is #{network_speed} , less than 1000" 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_run_test_tenant_memory_used.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check when sysbench free , cluster info about memory used and memory hold' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: " 7 | SELECT TENANT_ID 8 | FROM oceanbase.DBA_OB_TENANTS 9 | WHERE TENANT_TYPE='USER' limit 1;" 10 | result: 11 | set_value: tenant_id 12 | verify: '[ -n "${tenant_id}" ]' 13 | err_msg: "the tenant_id of TENANT_TYPE='USER' is null. Please check your TENANT." 14 | - type: sql 15 | sql: 'SELECT ROUND(t3.MEMORY_SIZE/1024/1024/1024) FROM OCEANBASE.DBA_OB_TENANTS t1,OCEANBASE.DBA_OB_UNITS t2,OCEANBASE.DBA_OB_UNIT_CONFIGS t3,OCEANBASE.DBA_OB_RESOURCE_POOLS t4 16 | where t1.tenant_id = t4.tenant_id 17 | and t1.tenant_id=#{tenant_id} 18 | AND t4.resource_pool_id=t2.resource_pool_id 19 | AND t4.unit_config_id=t3.unit_config_id 20 | and t2.svr_ip="#{remote_ip}" 21 | ORDER BY t1.tenant_name limit 1;' 22 | result: 23 | set_value: memory_size 24 | 25 | - type: sql 26 | sql: 'select ROUND(SUM(hold/1024/1024/1024)) from oceanbase.__all_virtual_memory_info where tenant_id=#{tenant_id} and svr_ip="#{remote_ip}"' 27 | result: 28 | set_value: memory_hold 29 | verify: "(( memory_hold * 100 / memory_size < 90 ))" 30 | report_type: warning 31 | err_msg: "tenant memory is not enough. memory_hold is #{memory_hold}. memory_size is #{memory_size}" 32 | - type: sql 33 | sql: 'select ROUND(SUM(used/1024/1024/1024)) from oceanbase.__all_virtual_memory_info where tenant_id=#{tenant_id} and svr_ip="#{remote_ip}"' 34 | result: 35 | set_value: memory_used 36 | verify: "(( memory_used * 100 / memory_size < 90 ))" 37 | report_type: warning 38 | err_msg: "tenant memory is not enough. memory_used is #{memory_used}. memory_size is #{memory_size}" 39 | 40 | 41 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_test_cluster_log_disk_size.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check cluster log_disk_size parameters' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | 6 | 7 | - type: sql 8 | sql: 'SELECT GROUP_CONCAT(DISTINCT t1.tenant_name) FROM OCEANBASE.DBA_OB_TENANTS t1,OCEANBASE.DBA_OB_UNITS t2,OCEANBASE.DBA_OB_UNIT_CONFIGS t3,OCEANBASE.DBA_OB_RESOURCE_POOLS t4 9 | where t1.tenant_id = t4.tenant_id 10 | AND t4.resource_pool_id=t2.resource_pool_id 11 | AND t4.unit_config_id=t3.unit_config_id 12 | and t2.svr_ip="#{remote_ip}" 13 | and t3.LOG_DISK_SIZE/1024/1024/1024<20 14 | and t1.tenant_id>1000 15 | ORDER BY t1.tenant_name;' 16 | result: 17 | set_value: log_disk_size_tenant_name 18 | report_type: warning 19 | verify: '[ -z "${log_disk_size_tenant_name}" ]' 20 | err_msg: 'log_disk_size <20G tenant: #{log_disk_size_tenant_name} . log_disk_size need >20G' 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_test_cluster_parameters.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check when running sysbench , cluster paramters' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where Name="enable_record_trace_log" and VALUE <> "False";' 7 | result: 8 | set_value: enable_record_trace_log 9 | verify_type: equal 10 | verify: 0 11 | err_msg: "cluster's enable_record_trace_log is true , need to change False" 12 | - type: sql 13 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where Name="enable_perf_event" and VALUE <> "False";' 14 | result: 15 | set_value: enable_perf_event 16 | verify_type: equal 17 | verify: 0 18 | err_msg: "cluster's enable_perf_event is true , need to change False" 19 | - type: sql 20 | sql: 'select count(0) from oceanbase.GV$OB_PARAMETERS where Name="enable_sql_audit" and VALUE <> "False";' 21 | result: 22 | set_value: enable_sql_audit 23 | verify_type: equal 24 | verify: 0 25 | err_msg: "cluster's enable_sql_audit is true , need to change False" 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_test_cpu_quota_concurrency.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check when running sysbench , cluster info about cpu_quota_concurrency' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from (SELECT DISTINCT tenant_id 7 | FROM oceanbase.__all_virtual_tenant_parameter_info 8 | WHERE name = "cpu_quota_concurrency" 9 | AND value NOT IN (2, 4) and tenant_id>1000);' 10 | result: 11 | set_value: cpu_quota_concurrency_nu 12 | verify_type: equal 13 | report_type: execution 14 | verify: 0 15 | err_msg: "There are #{cpu_quota_concurrency_nu} cpu_quota_concurrency whose concurrency is not equal to 2 or 4. cpu_quota_concurrency should equal to 2 or 4" 16 | 17 | - type: sql 18 | sql: 'SELECT GROUP_CONCAT(DISTINCT tenant_id) 19 | FROM oceanbase.__all_virtual_tenant_parameter_info 20 | WHERE name = "cpu_quota_concurrency" 21 | AND value NOT IN (2, 4) and tenant_id>1000' 22 | result: 23 | set_value: cpu_quota_concurrency_name 24 | verify: '[ -z "${cpu_quota_concurrency_name}" ]' 25 | err_msg: "the tenant_id is #{cpu_quota_concurrency_name}" 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_test_log_level.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check when running sysbench , cluster info about syslog_level' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select VALUE from oceanbase.GV$OB_PARAMETERS where Name="syslog_level";' 7 | result: 8 | set_value: syslog_level 9 | verify_type: base 10 | verify: '[ "$syslog_level" == "INFO" ] || [ "$syslog_level" == "WARN" ] || [ "$syslog_level" == "ERROR" ]' 11 | err_msg: "syslog_level is #{syslog_level} , need to 'INFO'、'WARN'、'ERROR'" 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_test_sql_net_thread_count.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check when running sysbench , cluster info about sql_net_thread_count' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | 6 | - type: sql 7 | sql: 'select VALUE from oceanbase.GV$OB_PARAMETERS where Name="cpu_count";' 8 | result: 9 | set_value: cpu_count 10 | verify_type: min 11 | report_type: warning 12 | verify: 0 13 | err_msg: 'cpu_count of cluster : #{cpu_count} , need to calculate the relationship between cpu_count and the number of system CPUs' 14 | - type: ssh 15 | ssh: "lscpu | grep '^CPU(s):' | awk '{print $2}'" 16 | result: 17 | set_value: os_cpu_count 18 | - type: ssh 19 | ssh: '[ #{cpu_count} -eq 0 ] && echo #{os_cpu_count} || echo #{cpu_count}' 20 | result: 21 | set_value: cpu_count 22 | 23 | - type: sql 24 | sql: 'select GROUP_CONCAT(DISTINCT ZONE) from oceanbase.GV$OB_PARAMETERS where Name="sql_net_thread_count" and VALUE <>0 and VALUE<(#{cpu_count}/8);' 25 | result: 26 | set_value: sql_net_thread_count 27 | report_type: execution 28 | verify: '[ -z "${log_disk_size_tenant_name}" ]' 29 | err_msg: "There is an observer whose sql_net_thread_count is not 0. the zone is #{sql_net_thread_count}" 30 | 31 | - type: sql 32 | sql: " SELECT GROUP_CONCAT(DISTINCT ZONE) 33 | FROM oceanbase.GV$OB_PARAMETERS t1 34 | WHERE Name = 'sql_net_thread_count' 35 | AND Value != 0 36 | AND EXISTS (SELECT 1 37 | FROM oceanbase.GV$OB_PARAMETERS t2 38 | WHERE t2.zone = t1.zone 39 | AND t2.Value != t1.Value);" 40 | result: 41 | set_value: net_thread_count 42 | verify: '[ -z "${net_thread_count}" ]' 43 | err_msg: "There is an observer whose sql_net_thread_count is not 0 .the zone is #{net_thread_count}" 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_test_tenant_log_disk_size.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check tenant log_disk_size parameters' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'SELECT GROUP_CONCAT(DISTINCT t1.tenant_name) FROM OCEANBASE.DBA_OB_TENANTS t1,OCEANBASE.DBA_OB_UNITS t2,OCEANBASE.DBA_OB_UNIT_CONFIGS t3,OCEANBASE.DBA_OB_RESOURCE_POOLS t4 7 | where t1.tenant_id = t4.tenant_id 8 | AND t4.resource_pool_id=t2.resource_pool_id 9 | AND t4.unit_config_id=t3.unit_config_id 10 | and t2.svr_ip="#{remote_ip}" 11 | and t3.LOG_DISK_SIZE/1024/1024/1024<20 12 | and t1.tenant_id>1000 13 | ORDER BY t1.tenant_name;' 14 | result: 15 | set_value: log_disk_size_tenant_name 16 | report_type: warning 17 | verify: '[ -z "${log_disk_size_tenant_name}" ]' 18 | err_msg: 'log_disk_size <20G tenant: #{log_disk_size_tenant_name} . log_disk_size need >20G' 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/sysbench/sysbench_test_tenant_primary_zone.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check when running sysbench, cluster info about tenant primary zone' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: "SELECT GROUP_CONCAT(DISTINCT TENANT_NAME) AS tenant_names 7 | FROM oceanbase.DBA_OB_TENANTS 8 | WHERE TENANT_TYPE='USER' and PRIMARY_ZONE LIKE '%;%';" 9 | result: 10 | set_value: not_RANDOM 11 | verify: '[ -z "$not_RANDOM" ]' 12 | err_msg: "The PRIMARY_ZONE of the existing tenant is not RANDOM : #{not_RANDOM}" 13 | 14 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/aio.yaml: -------------------------------------------------------------------------------- 1 | info: 'To detect aio, refer to: https://www.oceanbase.com/docs/enterprise-oceanbase-ocp-cn-1000000000125643' 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: "ps -ef | grep observer | grep -v grep | wc -l" 6 | result: 7 | set_value: observer_nu 8 | - type: get_system_parameter 9 | parameter: fs.aio-max-nr 10 | result: 11 | set_value: aio_max_nr 12 | report_type: warning 13 | verify: "[ ${aio_max_nr} -ge 1048576 ]" 14 | err_msg: 'fs.aio-max-nr : #{aio_max_nr} . recommended: >1048576' 15 | - type: get_system_parameter 16 | parameter: fs.aio-nr 17 | result: 18 | set_value: aio_nr 19 | report_type: warning 20 | verify: "[ $((aio_max_nr - aio_nr)) -ge $((20000*${observer_nu})) ]" 21 | err_msg: 'fs.aio-nr : #{aio_nr} . recommended: aio-max-nr - aio-nr>20000 * observer_num' 22 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/arm_smmu.yaml: -------------------------------------------------------------------------------- 1 | info: 'If the node is arm architecture, check whether the smmu need to be closed. issue #784' 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: "arch" 6 | result: 7 | set_value: arch 8 | verify: '[ "$arch" == "x86_64" ]' 9 | report_type: execution 10 | err_msg: '[not warning] The observer is not x86_64 architecture, please check the observer architecture.' 11 | - type: ssh 12 | ssh: 'dmesg -T|grep "stuck for"|wc -l' 13 | result: 14 | set_value: smmu_stuck_count 15 | verify_type: equal 16 | verify: 0 17 | err_msg: 'find dmesg stuck for smmu, if the arch of the node is arm, Please close the smmu on bios' 18 | 19 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/clock_source.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check the type of clock_source is tsc' 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: "cat /sys/devices/system/clocksource/clocksource0/current_clocksource" 6 | result: 7 | set_value: clock_source 8 | verify: "[[ \"${clock_source}\" == \"tsc\" || \"${clock_source}\" == \"arch_sys_counter\" || \"${clock_source}\" == \"kvm-clock\" ]]" 9 | err_msg: 'clock_source: #{clock_source}. recommended: tsc. Uneven CPU utilization during pressure testing resulted in low TPS during pressure testing' 10 | 11 | 12 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/core_pattern.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check kernel.core_pattern' 2 | task: 3 | - steps: 4 | - type: get_system_parameter 5 | parameter: kernel.core_pattern 6 | result: 7 | set_value: core_pattern 8 | verify: '[[ $core_pattern != *" "* ]]' 9 | err_msg: 'kernel.core_pattern: #{core_pattern} , is not recommended for configuring functions other than the specified core path' 10 | - type: ssh 11 | ssh: 'dirname "${core_pattern}"' 12 | result: 13 | set_value: core_path 14 | verify: '[ -d "$core_path" ]' 15 | err_msg: 'core_path: #{core_path} is not exist. Please create it.' 16 | - type: ssh 17 | ssh: 'ls #{core_path}| grep "^core" | wc -l' 18 | result: 19 | set_value: core_file_number 20 | verify_type: equal 21 | verify: 0 22 | err_msg: 'The core file exists.' 23 | - type: ssh 24 | ssh: "df \"#{core_path}\" | awk 'NR==2 {print $4}'" 25 | result: 26 | set_value: core_path_free_space 27 | verify_type: min 28 | verify: 10485760 29 | err_msg: 'core_path: #{core_path} free_space: #{core_path_free_space} need > 10485760KB (10GB)' 30 | 31 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/dependent_software.yaml: -------------------------------------------------------------------------------- 1 | info: 'To detect dependent software, refer to: https://www.oceanbase.com/docs/enterprise-oceanbase-ocp-cn-1000000000125643' 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: 'ps aux | grep firewalld | grep -v grep' 6 | result: 7 | set_value: firewalld_switch 8 | report_type: warning 9 | verify: '[ -z "${firewalld_switch}" ]' 10 | err_msg: 'firewalld is running ,It is recommended to disable firewalld or add allow rules for each service in the OceanBase cluster to avoid firewall interception.' 11 | - type: ssh 12 | ssh: 'ps aux | grep crond | grep -v grep' 13 | result: 14 | set_value: crond_switch 15 | report_type: warning 16 | verify: '[ ! -z "${crond_switch}" ]' 17 | err_msg: 'crond is not running.It is recommended to enable it, mainly for setting up scheduled tasks and providing related operation and maintenance capabilities.' 18 | - type: ssh 19 | ssh: 'cat /sys/kernel/mm/transparent_hugepage/enabled |grep "[never]"' 20 | result: 21 | set_value: transparent_hugepage_switch 22 | report_type: warning 23 | verify: '[ -n "${transparent_hugepage_switch}" ]' 24 | err_msg: 'transparent_hugepage need retrun "[never]". Now , it is null.' -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/dependent_software_swapon.yaml: -------------------------------------------------------------------------------- 1 | info: 'To detect dependent software, refer to: https://www.oceanbase.com/docs/enterprise-oceanbase-ocp-cn-1000000000125643' 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: 'if command -v swapon &>/dev/null; then echo "exist"; fi' 6 | result: 7 | set_value: swapon_exist 8 | report_type: execution 9 | verify: '[ "exist" != "${swapon_exist}" ]' 10 | err_msg: '[not warning] swapon is exist. We will check the swap' 11 | - type: ssh 12 | ssh: 'swapon --summary | grep -q "^" && echo "used" || echo "not used"' 13 | result: 14 | set_value: swapon_switch 15 | report_type: warning 16 | verify: '[ "not used" == "${swapon_switch}" ]' 17 | err_msg: 'swapon need be closed. Now , it is #{swapon_switch}.' -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/dmesg_log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/04/23 15 | @file: dmesg_log.py 16 | @desc: 17 | """ 18 | import re 19 | from src.handler.checker.check_task import TaskBase 20 | 21 | 22 | class DmesgLog(TaskBase): 23 | 24 | def init(self, context, report): 25 | super().init(context, report) 26 | 27 | def execute(self): 28 | try: 29 | # check dmesg is exist 30 | for node in self.observer_nodes: 31 | ssh_client = node.get("ssher") 32 | if not super().check_command_exist(ssh_client, "dmesg"): 33 | self.report.add_warning("node:{0}. dmesg command does not exist.".format(ssh_client.get_name())) 34 | continue 35 | # check dmesg log 36 | dmesg_log = ssh_client.exec_cmd("dmesg").strip() 37 | if not dmesg_log: 38 | self.report.add_warning("node:{0}. dmesg log is empty.".format(ssh_client.get_name())) 39 | continue 40 | # check "Hardware Error" is existed 41 | if re.search(r"Hardware Error", dmesg_log): 42 | dmesg_log_lines = dmesg_log.splitlines("\n") 43 | for line in dmesg_log_lines: 44 | if "Hardware Error" in line: 45 | self.report.add_warning("node:{0}. dmesg log has Hardware Error. log:{1}".format(ssh_client.get_name(), line)) 46 | break 47 | 48 | except Exception as e: 49 | return self.report.add_fail(f"Execute error: {e}") 50 | 51 | def get_task_info(self): 52 | return {"name": "dmesg_log", "info": "Confirm whether there is \"Hardware Error\" in dmesg. issue #885 "} 53 | 54 | 55 | dmesg_log = DmesgLog() 56 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/getenforce.yaml: -------------------------------------------------------------------------------- 1 | info: 'check SELinux by getenforce. refer to: https://www.oceanbase.com/docs/enterprise-oceanbase-ocp-cn-1000000000125643' 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: 'if command -v getenforce &>/dev/null; then echo "exist"; fi' 6 | result: 7 | set_value: getenforce_exist 8 | report_type: execution 9 | verify: '[ "exist" != "${getenforce_exist}" ]' 10 | err_msg: '[not warning] getenforce is exist. We will check SELinux by getenforce' 11 | - type: ssh 12 | ssh: "getenforce" 13 | result: 14 | set_value: SELinux_switch 15 | report_type: warning 16 | verify: "[ 'Disabled' == ${SELinux_switch} ]" 17 | err_msg: 'SELinux need Disabled. Now , it is #{SELinux_switch}.' -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/instruction_set_avx.yaml: -------------------------------------------------------------------------------- 1 | info: "Check the flags of cpu" 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: "lscpu |grep Flags" 6 | result: 7 | set_value: cpu_flags 8 | verify: " [[ $cpu_flags == *avx* ]] " 9 | err_msg: "observer need cpu support avx. If the cpu is not support avx, observer will be crash." 10 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/instruction_set_avx2.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check the flags of cpu' 2 | task: 3 | - version: "[4.2.0.0,4.2.0.0]" 4 | steps: 5 | - type: ssh 6 | ssh: "lscpu |grep Flags" 7 | result: 8 | set_value: cpu_flags 9 | verify: " [[ $cpu_flags == *avx2* ]] " 10 | err_msg: 'observer need cpu support avx2. If the cpu is not support avx2, observer will be crash.' 11 | 12 | 13 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/kernel_bad_version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/04/30 15 | @file: kernel_bad_version.py 16 | @desc: 17 | """ 18 | import re 19 | from src.handler.checker.check_task import TaskBase 20 | 21 | 22 | class KernelBadVersion(TaskBase): 23 | 24 | def init(self, context, report): 25 | super().init(context, report) 26 | 27 | def execute(self): 28 | try: 29 | # get kernel version by ssher 30 | for node in self.observer_nodes: 31 | ssh_client = node.get("ssher") 32 | kernel_version = ssh_client.exec_cmd("uname -r") 33 | if not kernel_version: 34 | return self.report.add_fail("get kernel version error") 35 | self.stdio.verbose("node: {0} kernel version is {1}".format(ssh_client.get_name(), kernel_version)) 36 | # check kernel version 37 | if re.match(r"3\.10\.\d+-\d+", kernel_version): 38 | self.report.add_critical( 39 | "node: {0} kernel version is {1}, There is a risk of system downtime when deploying OBServer using cgroup method on an operating system with kernel version 3.10 issue #910".format(ssh_client.get_name(), kernel_version) 40 | ) 41 | continue 42 | except Exception as e: 43 | self.stdio.error("execute error {0}".format(e)) 44 | return self.report.add_fail("execute error {0}".format(e)) 45 | 46 | def get_task_info(self): 47 | return { 48 | "name": "kernel_bad_version", 49 | "info": "There is a risk of system downtime when deploying OBServer using cgroup method on an operating system with kernel version 3.10. issue #910", 50 | } 51 | 52 | 53 | kernel_bad_version = KernelBadVersion() 54 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/parameter_ip_local_port_range.yaml: -------------------------------------------------------------------------------- 1 | 2 | info: | 3 | 'To detect kernel parameters, refer to: https://www.oceanbase.com/docs/enterprise-oceanbase-ocp-cn-1000000000125643' 4 | task: 5 | - steps: 6 | - type: get_system_parameter 7 | parameter: net.ipv4.ip_local_port_range 8 | result: 9 | set_value: ip_local_port_range 10 | verify: '[[ -n "$ip_local_port_range" && "$ip_local_port_range" != "-1" ]]' 11 | err_msg: "ip_local_port_range : #{ip_local_port_range} . Please check net.ipv4.ip_local_port_range on your node" 12 | - type: ssh 13 | ssh: "echo \"#{ip_local_port_range}\" | awk '{print $1}'" 14 | result: 15 | set_value: ip_local_port_range_min 16 | report_type: warning 17 | verify_type: equal 18 | verify: 3500 19 | err_msg: 'ip_local_port_range_min : #{ip_local_port_range_min}. recommended: 3500' 20 | - type: ssh 21 | ssh: "echo \"#{ip_local_port_range}\" | awk '{print $2}'" 22 | result: 23 | set_value: ip_local_port_range_max 24 | report_type: warning 25 | verify_type: equal 26 | verify: 65535 27 | err_msg: 'ip_local_port_range_max : #{ip_local_port_range_max}. recommended: 65535' -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/parameter_tcp_rmem.yaml: -------------------------------------------------------------------------------- 1 | 2 | info: | 3 | 'To detect kernel parameters, refer to: https://www.oceanbase.com/docs/enterprise-oceanbase-ocp-cn-1000000000125643' 4 | task: 5 | - steps: 6 | - type: get_system_parameter 7 | parameter: net.ipv4.tcp_rmem 8 | result: 9 | set_value: tcp_rmem 10 | verify: '[[ -n "$tcp_rmem" && "$tcp_rmem" != "-1" ]]' 11 | err_msg: "net.ipv4.tcp_rmem is #{tcp_rmem} . Please check net.ipv4.tcp_rmem on your node" 12 | - type: ssh 13 | ssh: "echo \"#{tcp_rmem}\" | awk '{print $1}'" 14 | result: 15 | set_value: tcp_rmem_min 16 | report_type: warning 17 | verify_type: between 18 | verify: "[4096,8192]" 19 | err_msg: 'net.ipv4.tcp_rmem_min : #{tcp_rmem_min}. recommended: 4096 ≤ min ≤ 8192' 20 | - type: ssh 21 | ssh: "echo \"#{tcp_rmem}\" | awk '{print $2}'" 22 | result: 23 | set_value: tcp_rmem_default 24 | report_type: warning 25 | verify_type: between 26 | verify: "[65536,131072]" 27 | err_msg: 'net.ipv4.tcp_rmem_default : #{tcp_rmem_default}. net.ipv4.tcp_rmem_default from net.ipv4.tcp_rmem. recommended: is 65536 ≤ default≤ 131072' 28 | - type: ssh 29 | ssh: "echo \"#{tcp_rmem}\" | awk '{print $3}'" 30 | result: 31 | set_value: tcp_rmem_max 32 | report_type: warning 33 | verify_type: between 34 | verify: "[8388608,16777216]" 35 | err_msg: 'net.ipv4.tcp_rmem_max : #{tcp_rmem_max}. net.ipv4.tcp_rmem_max from net.ipv4.tcp_rmem. recommended: 65536 ≤ max≤ 131072' 36 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/parameter_tcp_wmem.yaml: -------------------------------------------------------------------------------- 1 | 2 | info: | 3 | 'To detect kernel parameters, refer to: https://www.oceanbase.com/docs/enterprise-oceanbase-ocp-cn-1000000000125643' 4 | task: 5 | - steps: 6 | - type: get_system_parameter 7 | parameter: net.ipv4.tcp_wmem 8 | result: 9 | set_value: tcp_wmem 10 | - type: ssh 11 | ssh: "echo \"#{tcp_wmem}\" | awk '{print $1}'" 12 | result: 13 | set_value: tcp_wmem_min 14 | report_type: warning 15 | verify_type: between 16 | verify: "[4096,8192]" 17 | err_msg: 'net.ipv4.tcp_wmem_min : #{tcp_wmem_min}. recommended: 4096 ≤ min ≤ 8192' 18 | - type: ssh 19 | ssh: "echo \"#{tcp_wmem}\" | awk '{print $2}'" 20 | result: 21 | set_value: tcp_wmem_default 22 | report_type: warning 23 | verify_type: between 24 | verify: "[65536,131072]" 25 | err_msg: 'net.ipv4.tcp_wmem_default : #{tcp_wmem_default}. recommended: is 65536 ≤ default≤ 131072' 26 | - type: ssh 27 | ssh: "echo \"#{tcp_wmem}\" | awk '{print $3}'" 28 | result: 29 | set_value: tcp_wmem_max 30 | report_type: warning 31 | verify_type: between 32 | verify: "[8388608,16777216]" 33 | err_msg: 'net.ipv4.tcp_wmem_max : #{tcp_wmem_max}. recommended: 8388608 ≤ max≤ 16777216' 34 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/tcp_tw_reuse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/04/8 15 | @file: tcp_tw_reuse.py 16 | @desc: 17 | """ 18 | 19 | from src.handler.checker.check_task import TaskBase 20 | 21 | 22 | class TcpTwReuse(TaskBase): 23 | 24 | def init(self, context, report): 25 | super().init(context, report) 26 | 27 | def execute(self): 28 | try: 29 | for node in self.observer_nodes: 30 | self._execute_node(node) 31 | except Exception as e: 32 | self.stdio.error("execute error {0}".format(e)) 33 | return self.report.add_fail("execute error {0}".format(e)) 34 | 35 | def _execute_node(self, node): 36 | try: 37 | ssh_client = node.get("ssher") 38 | if ssh_client is None: 39 | self.report.add_fail("node: {0} ssh client is None".format(node.get("ip"))) 40 | return 41 | parameter_value = super().get_system_parameter(ssh_client, "net.ipv4.tcp_tw_reuse") 42 | if parameter_value is None: 43 | self.report.add_critical("node: {0} net.ipv4.tcp_tw_reuse is not exist".format(ssh_client.get_name())) 44 | return 45 | if parameter_value != "1": 46 | self.report.add_warning("node: {0} net.ipv4.tcp_tw_reuse is {1}. It is recommended to set it to 1".format(ssh_client.get_name(), parameter_value)) 47 | return 48 | 49 | except Exception as e: 50 | self.stdio.error(f"Command execution error: {e}") 51 | self.report.add_fail(f"Command execution error: {e}") 52 | return None 53 | 54 | def get_task_info(self): 55 | return {"name": "tcp_tw_reuse", "info": "Check if sockets in TIME-WAIT state (TIME-WAIT ports) are allowed to be used for new TCP connections. Need to be set to 1 to ensure system performance. issue#737"} 56 | 57 | 58 | tcp_tw_reuse = TcpTwReuse() 59 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/system/ulimit_parameter.yaml: -------------------------------------------------------------------------------- 1 | info: | 2 | 'To detect ulimit parameters, refer to: https://www.oceanbase.com/docs/enterprise-oceanbase-ocp-cn-1000000000125643' 3 | task: 4 | - steps: 5 | - type: ssh 6 | ssh: ulimit -c 7 | result: 8 | set_value: parameter 9 | report_type: warning 10 | verify: "[ 'unlimited' == ${parameter} ]" 11 | err_msg: 'On ip : #{remote_ip}, ulimit -c as "core file size" is #{parameter} . recommended: unlimited.' 12 | - type: ssh 13 | ssh: ulimit -u 14 | result: 15 | set_value: parameter 16 | report_type: warning 17 | verify: "[ '655360' == ${parameter} ]" 18 | err_msg: 'On ip : #{remote_ip}, ulimit -u as "max user processes" is #{parameter} . recommended: 655360.' 19 | - type: ssh 20 | ssh: ulimit -s 21 | result: 22 | set_value: parameter 23 | report_type: warning 24 | verify: "[ 'unlimited' == ${parameter} ]" 25 | err_msg: 'On ip : #{remote_ip}, ulimit -s as "stack size" is #{parameter} . recommended: unlimited.' 26 | - type: ssh 27 | ssh: ulimit -n 28 | result: 29 | set_value: parameter 30 | report_type: warning 31 | verify_type: equal 32 | verify: 655350 33 | err_msg: 'On ip : #{remote_ip}, ulimit -n as "open files" is #{parameter} . recommended: unlimited.' 34 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/table/information_schema_tables_two_data.yaml: -------------------------------------------------------------------------------- 1 | info: 'A table found two records in information_schema.tables. more: https://github.com/oceanbase/obdiag/issues/390' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: 'select count(0) from oceanbase.__all_virtual_table_stat where table_id = partition_id and (tenant_id,table_id) in (select tenant_id, table_id from oceanbase.__all_virtual_table where part_level != 0);' 7 | result: 8 | set_value: err_table_count 9 | verify_type: equal 10 | verify: 0 11 | err_msg: 'Find have table found two records in information_schema.tables. the number of err_table_count is : #{err_table_count}. Please get more info by "select * from oceanbase.__all_virtual_table_stat where table_id = partition_id and (tenant_id,table_id) in (select tenant_id, table_id from oceanbase.__all_virtual_table where part_level != 0);". And you can by "delete from __all_table_stat where table_id=partition_id and table_id=${partition table table_id};" and "delete from __all_column_stat where table_id=partition_id and table_id=${partition table table_id};" to fix it.' 12 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/tenant/tenant_min_resource.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check tenant resource pool configuration, if the cpu or memory is less than 2C4G, it will be reported.' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: ' SELECT GROUP_CONCAT(DISTINCT T4.TENANT_ID) 7 | FROM oceanbase.DBA_OB_RESOURCE_POOLS T1 8 | JOIN oceanbase.DBA_OB_UNIT_CONFIGS T2 ON T1.UNIT_CONFIG_ID = T2.UNIT_CONFIG_ID 9 | JOIN oceanbase.DBA_OB_UNITS T3 ON T1.RESOURCE_POOL_ID = T3.RESOURCE_POOL_ID 10 | JOIN oceanbase.DBA_OB_TENANTS T4 ON T1.TENANT_ID = T4.TENANT_ID 11 | WHERE T4.TENANT_ID>1 AND T2.MAX_CPU < 2 OR ROUND(T2.MEMORY_SIZE/1024/1024/1024,2) < 4 ;' 12 | result: 13 | set_value: too_small_tenant 14 | verify: '[ -z "$too_small_tenant" ]' 15 | err_msg: 'there tenant resource pool configuration is less than 2C4G, please check it. tenant_id: #{too_small_tenant}' 16 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/tenant/writing_throttling_trigger_percentage.yaml: -------------------------------------------------------------------------------- 1 | info: 'The configuration of writing_throttling_trigger_percentage was set to 100, which turned off the write speed limit and caused the memstore to explode. issue #758' 2 | task: 3 | - version: "[4.0.0.0,*]" 4 | steps: 5 | - type: sql 6 | sql: ' SELECT GROUP_CONCAT(DISTINCT TENANT_ID) from 7 | oceanbase.GV$OB_PARAMETERS WHERE name="writing_throttling_trigger_percentage" and VALUE =100 ; 8 | ' 9 | result: 10 | set_value: writing_throttling_trigger_percentage 11 | verify: '[ -z "$writing_throttling_trigger_percentage" ]' 12 | err_msg: "there tenant's writing_throttling_trigger_percentage equal 100. It will causing memstore to full. tenant_id: #{writing_throttling_trigger_percentage}" 13 | 14 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/version/bad_version.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check observer version . Some versions of observers are not recommended' 2 | task: 3 | - steps: 4 | - type: ssh 5 | ssh: "export LD_LIBRARY_PATH=#{remote_home_path}/lib && #{remote_home_path}/bin/observer --version 2>&1 | grep -oP 'REVISION: \\K\\d+'" 6 | result: 7 | set_value: observer_version 8 | - type: ssh 9 | ssh: '[ "#{observer_version}" = "100000192023032010" ] && echo "0" || echo "1"' 10 | result: 11 | set_value: result 12 | verify_type: equal 13 | verify: 1 14 | err_msg: 'the version is 100000192023032010 , the observer is not recommended' 15 | - type: ssh 16 | ssh: '[ "#{observer_version}" = "103000072023081111" ] && echo "0" || echo "1"' 17 | result: 18 | set_value: result 19 | verify_type: equal 20 | verify: 1 21 | err_msg: 'the version is 103000072023081111 , the observer is not recommended' 22 | - type: ssh 23 | ssh: '[ "#{observer_version}" = "104000032023092120" ] && echo "0" || echo "1"' 24 | result: 25 | set_value: result 26 | verify_type: equal 27 | verify: 1 28 | err_msg: 'the version is 104000032023092120 , the observer is not recommended' 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /plugins/check/tasks/observer/version/old_version.yaml: -------------------------------------------------------------------------------- 1 | info: 'Check observer version . Some versions of observers are not recommended' 2 | task: 3 | - version: "[3.0.0,3.9.0]" 4 | steps: 5 | - type: ssh 6 | ssh: 'export LD_LIBRARY_PATH=#{remote_home_path}/lib && #{remote_home_path}/bin/observer --version 2>&1 | grep "(OceanBase"' 7 | result: 8 | set_value: observer_version 9 | verify: '[[ ! "#{observer_version}" == *"3.1."* ]] || [[ ! "#{observer_version}" == *"CE"* ]]' 10 | err_msg: 'Starting from June 30, 2024, OceanBase Database Community Edition V3.1.x will no longer receive any bug fixes or version updates.Please upgrade as soon as possible' 11 | - version: "[4.0.0.0,*]" 12 | steps: 13 | - type: ssh 14 | ssh: 'export LD_LIBRARY_PATH=#{remote_home_path}/lib && #{remote_home_path}/bin/observer --version 2>&1 | grep "(OceanBase"' 15 | result: 16 | set_value: observer_version 17 | - type: ssh 18 | ssh: "echo \"#{observer_version}\" | grep -oP '\\d+\\.\\d+\\.\\d+\\.\\d+'" 19 | result: 20 | set_value: observer_version 21 | verify: '[[ ! "${observer_version}" == "4.0"* ]] && [[ ! "${observer_version}" == "4.1"* ]] && [[ ! "${observer_version}" == "4.2.2"* ]] && [[ ! "${observer_version}" == "4.3.0"* ]] && [[ ! "${observer_version}" == "4.3.1"* ]]' 22 | err_msg: '#{observer_version} is not recommended, please upgrade to the obcluster' 23 | - type: ssh 24 | ssh: "echo \"#{observer_version}\" | awk -F. '{print $NF}'" 25 | result: 26 | set_value: observer_version_end_str 27 | verify: '[[ "$observer_version" == "4.2.1"* && "$observer_version_end_str" -ge 5 ]] || [[ ! "$observer_version" == "4.2.1"* ]]' 28 | err_msg: '#{observer_version} is not recommended, please upgrade to the obcluster' 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /plugins/display/tasks/observer/all_tenant.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[all_tenant]" 2 | info_cn: "[所有tenant基本信息]" 3 | command: obdiag display scene run --scene=observer.all_tenant 4 | task: 5 | - version: "[*,*]" 6 | steps: 7 | - type: sql 8 | sql: "select tenant_id,tenant_name,zone_list,primary_zone,status from oceanbase.__all_tenant;" 9 | global: true 10 | -------------------------------------------------------------------------------- /plugins/display/tasks/observer/cpu.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[cpu]" 2 | info_cn: "[tenant的cpu信息]" 3 | command: obdiag display scene run --scene=observer.cpu 4 | task: 5 | - version: "[*,*]" 6 | steps: 7 | - type: sql 8 | sql: " select NOW() 'chenck_time', t.tenant_name,t.tenant_id,ca.svr_ip, 9 | round(sum(case when STAT_ID='140006' then ca.VALUE else 0 end)/100,2) 'cpu_usage', 10 | round(sum(case when STAT_ID='140005' then ca.VALUE else 0 end)/100,2) 'cpu_max' , 11 | round(100*(sum(case when STAT_ID='140006' then ca.VALUE else 0 end)/sum(case when STAT_ID='140005' then ca.VALUE else 0 end)),2) 'cpu_percent' 12 | from 13 | (select s.CON_ID, s.svr_ip,s.STAT_ID, sum(s.VALUE) VALUE 14 | from oceanbase.gv$sysstat s where s.STAT_ID in(140005,140006) 15 | group by s.CON_ID, s.svr_ip,s.STAT_ID, s.NAME) ca,oceanbase.__all_tenant t 16 | where t.tenant_id=ca.CON_ID 17 | group by t.tenant_name,ca.svr_ip;" 18 | global: true -------------------------------------------------------------------------------- /plugins/display/tasks/observer/index.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[index]" 2 | info_cn: "[查询表上的index信息]" 3 | command: obdiag display scene run --scene=observer.index --env database_name=test --env table_name=test 4 | task: 5 | - version: "[*,*]" 6 | steps: 7 | - type: sql 8 | sql: "select t1.tenant_name,a.table_id index_id,d.database_name tab_owner,a2.table_name ,d.database_name idx_owner,substr(substring_index(e.table_name,'_',4),7) table_id, substring(e.table_name,length(substring_index(e.table_name,'_',4))+2) index_name, group_concat(distinct a.column_name order by a.rowkey_position separator',') as index_column 9 | from oceanbase.__all_virtual_column a 10 | inner join oceanbase.__all_virtual_table e on a.table_id=e.table_id and e.table_type=5 and a.tenant_id=e.tenant_id 11 | inner join oceanbase.__all_virtual_table a2 on e.data_table_id=a2.table_id and a2.table_name=upper('#{table_name}') And a2.tenant_id=e.tenant_id 12 | inner join oceanbase.__all_tenant t1 on t1.tenant_id=a2.tenant_id 13 | inner join oceanbase.__all_virtual_database d on d.database_id=a2.database_id and d.database_name=upper('#{database_name}') and e.database_id=d.database_id 14 | group by t1.tenant_name,a.table_id,d.database_name,a2.table_name,d.database_name,e.table_name; " 15 | global: true -------------------------------------------------------------------------------- /plugins/display/tasks/observer/inner_table.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[inner_table]" 2 | info_cn: "[内部表信息模糊匹配]" 3 | command: obdiag display scene run --scene=observer.inner_table --env tablename=test 4 | task: 5 | - version: "[*,*]" 6 | steps: 7 | - type: sql 8 | sql: "SELECT distinct table_name FROM oceanbase.__all_virtual_table t1 JOIN oceanbase.__all_virtual_database t2 ON t2.database_id = t1.database_id JOIN oceanbase.__all_tenant t3 ON t3.tenant_id = t1.tenant_id WHERE tenant_name = 'sys' AND database_name = 'oceanbase' AND (table_name LIKE '__all%' OR table_name LIKE '__tenant%' OR table_name LIKE 'gv%' OR table_name LIKE 'v%' OR table_name LIKE 'dba%' OR table_name LIKE 'cdb%') and table_name like '%#{tablename}%' ORDER BY ORA_DECODE(SUBSTR(table_name, 1, 1), 'v', 3, 'g', 4, ORA_DECODE(SUBSTR(table_name, 3, 1), 'a', 2, 1)), table_name;" 9 | global: true 10 | -------------------------------------------------------------------------------- /plugins/display/tasks/observer/leader.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[leader]" 2 | info_cn: "[ob集群的leader信息]" 3 | command: obdiag display scene run --scene=observer.leader --env level=('all' or tenant_id or table_name) 4 | task: 5 | - version: "[4.0.0,*]" 6 | steps: 7 | - type: sql 8 | sql: "select a.tenant_id, b.tenant_name, a.svr_ip, a.role, count(1) part_count from oceanbase.CDB_OB_TABLE_LOCATIONS a, oceanbase.__all_tenant b 9 | where a.role='LEADER' and a.tenant_id = b.tenant_id and b.tenant_name not like 'META$%' and (('all'='#{level}') or (a.tenant_id = '#{level}') or (a.table_name ='#{level}')) group by a.tenant_id, b.tenant_name, a.svr_ip, a.role order by 4,1;" 10 | global: true 11 | - version: "[*,3.9.9.9]" 12 | steps: 13 | - type: sql 14 | sql: "select a.tenant_id, b.tenant_name, a.svr_ip, a.role, count(1) part_count from oceanbase.__all_virtual_meta_table a, oceanbase.__all_tenant b 15 | where a.role='LEADER' and a.tenant_id = b.tenant_id and b.tenant_name not like 'META$%' and (('all'='#{level}') or (a.tenant_id = '#{level}') or (a.table_id in (select table_id from oceanbase.__all_virtual_table where table_name ='#{level}'))) group by a.tenant_id, b.tenant_name, a.svr_ip, a.role order by 4,1;" 16 | global: true -------------------------------------------------------------------------------- /plugins/display/tasks/observer/lock_table.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[lock table]" 2 | info_cn: "[某张表上持有锁的信息]" 3 | command: obdiag display scene run --scene=observer.lock_table --env tablename=test 4 | task: 5 | - version: "[4.0.0.0,*]" 6 | steps: 7 | - type: sql 8 | sql: "select * from (select a.tenant_id,a.svr_ip,a.ls_id,a.table_id,c.table_id table_actual_id,c.table_name,a.tablet_id,a.session_id,a.ctx_create_time,timestampdiff(second,date_format(a.ctx_create_time,'%Y-%m-%d %T'),now()) wait_time_s 9 | from oceanbase.__all_virtual_trans_lock_stat a 10 | left join oceanbase.__all_virtual_tablet_to_ls b on b.tablet_id=a.tablet_id 11 | left join oceanbase.__all_virtual_table c on b.table_id=c.table_id) t where t.table_name = '#{tablename}';" 12 | global: true 13 | - version: "[*,3.9.9.9]" 14 | steps: 15 | - type: sql 16 | sql: "select * from (select a.tenant_id,a.svr_ip,a.table_id,c.table_name,a.session_id,substring_index(substring_index(a.trans_id,',',1),':',-1) hash,a.ctx_create_time,a.expired_time,timestampdiff(second,date_format(a.ctx_create_time,'%Y-%m-%d %T'),now()) wait_time_s 17 | from oceanbase.__all_virtual_trans_lock_stat a 18 | left join oceanbase.__all_virtual_table c on a.table_id=c.table_id ) t where t.table_name = '#{tablename}';" 19 | global: true -------------------------------------------------------------------------------- /plugins/display/tasks/observer/lockholder.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[lock holder info]" 2 | info_cn: "[查看锁等待]" 3 | command: obdiag display scene run --scene=observer.lockholder 4 | task: 5 | - version: "[4.2.0.0,*]" 6 | steps: 7 | - type: sql 8 | sql: "select distinct a.tenant_id,a.svr_ip,c.table_id table_actual_id,c.table_name,a.tablet_id,a.session_id,a.block_session_id,a.trans_id, 9 | a.holder_trans_id,a.lock_mode,a.type 10 | from oceanbase.__all_virtual_lock_wait_stat a 11 | left join oceanbase.__all_virtual_tablet_to_ls b on b.tablet_id=a.tablet_id and a.tenant_id=b.tenant_id 12 | left join oceanbase.__all_virtual_table c on b.table_id=c.table_id order by c.table_name,a.tenant_id;" 13 | global: true 14 | global: true 15 | - version: "[*,3.9.9.9]" 16 | steps: 17 | - type: sql 18 | sql: "select distinct a.svr_ip,c.table_id table_actual_id,c.table_name,a.session_id,a.block_session_id,a.lock_mode,a.type 19 | from oceanbase.__all_virtual_lock_wait_stat a 20 | left join oceanbase.__all_virtual_table c on a.table_id=c.table_id order by c.table_name;" 21 | global: true 22 | -------------------------------------------------------------------------------- /plugins/display/tasks/observer/long_transaction.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[long_transaction]" 2 | info_cn: "[集群的长事务信息]" 3 | command: obdiag display scene run --scene=observer.long_transaction --env wait_time=waittime(s) 4 | task: 5 | - version: "[4.0.0.0,*]" 6 | steps: 7 | - type: sql 8 | sql: "select a.svr_ip,a.session_id,a.ctx_create_time,now(),timestampdiff(second,date_format(ctx_create_time,'%Y-%m-%d %T'),now()) wait_time,a.trans_type,a.trans_id,case when b.trans_id is not null 9 | and part_trans_action > 2 then 'XA_hang' when b.trans_id is null and part_trans_action > 2 then 'nomarl_hang' 10 | when b.trans_id is not null then 'normal_XA_trans' when b.trans_id is null then 'normal_long_trans' end as 'trans_type_info',a.participants from oceanbase.__all_virtual_trans_stat a left join oceanbase.__all_virtual_global_transaction b on a.tenant_id = b.tenant_id and a.trans_id = b.trans_id where 11 | timestampdiff(second,date_format(ctx_create_time,'%Y-%m-%d %T'),now()) > #{wait_time} and a.is_exiting<>1 12 | order by a.ctx_create_time limit 50;" 13 | global: true 14 | - version: "[*,3.9.9.9]" 15 | steps: 16 | - type: sql 17 | sql: "select t.table_name,t.table_id,a.svr_ip,a.session_id,timestampdiff(second,date_format(ctx_create_time,'%Y-%m-%d %T'),now()) wait_time,a.trans_type,a.trans_id,case when b.trans_id is not null and part_trans_action > 2 then 'XA_hang' when b.trans_id is null and part_trans_action > 2 then 'nomarl_hang' when b.trans_id is not null then 'normal_XA_trans' when b.trans_id is null then 'normal_long_trans' end as 'trans_type_info' from oceanbase.__all_virtual_trans_stat a left join oceanbase.gv$table t on substr(a.`partition`,6,16)=t.table_id left join oceanbase.__all_virtual_global_transaction b on a.tenant_id = b.tenant_id and a.trans_id = b.trans_id where 18 | timestampdiff(second,date_format(ctx_create_time,'%Y-%m-%d %T'),now()) > #{wait_time} and a.is_exiting<>1 19 | order by a.ctx_create_time limit 50;" 20 | global: true 21 | -------------------------------------------------------------------------------- /plugins/display/tasks/observer/plan_explain.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[plan_explain]" 2 | info_cn: "[实际执行计划算子信息]" 3 | command: obdiag display scene run --scene=observer.plan_explain --env svr_ip=test --env svr_port=2882 --env tenant_id=test --env plan_id=test 4 | task: 5 | - version: "[*,*]" 6 | steps: 7 | - type: sql 8 | sql: "select plan_id, operator, name, rows, cost 9 | from oceanbase.__all_virtual_plan_cache_plan_explain 10 | where svr_ip = '#{svr_ip}' 11 | and svr_port = '#{svr_port}' 12 | and tenant_id = '#{tenant_id}' 13 | and plan_id = '#{plan_id}'" 14 | global: true -------------------------------------------------------------------------------- /plugins/display/tasks/observer/processlist.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[processlist]" 2 | info_cn: "[查看 processlist]" 3 | command: obdiag display scene run --scene=observer.processlist --env tenant_name=test 4 | task: 5 | - version: "[4.0.0.0, *]" 6 | steps: 7 | - type: sql 8 | sql: "select * from oceanbase.gv$ob_processlist where tenant='#{tenant_name}';" 9 | global: true 10 | - version: "[3.0.0.0, 3.9.9.9]" 11 | steps: 12 | - type: sql 13 | sql: "select * from oceanbase.__all_virtual_processlist where tenant='#{tenant_name}';" 14 | global: true 15 | -------------------------------------------------------------------------------- /plugins/display/tasks/observer/processlist_stat.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[processlist_stat]" 2 | info_cn: "[processlist 实时会话信息汇总]" 3 | command: obdiag display scene run --scene=observer.processlist_stat 4 | task: 5 | - version: "[3.0.0.0,*]" 6 | steps: 7 | - type: sql 8 | sql: "select tenant,user,svr_ip,ifnull(sql_id,''),avg(retry_cnt),avg(time),max(time),count(*),id from oceanbase.__all_virtual_processlist where tenant<>'sys' and sql_id<>'' group by user,svr_ip,sql_id order by count(*) desc limit 10; " 9 | global: true 10 | - type: sql 11 | sql: "select tenant,user,svr_ip,substr(info,1,40) as q_sql,avg(retry_cnt),avg(time),max(time),count(*),id from oceanbase.__all_virtual_processlist where tenant<>'sys' and sql_id<>'' group by user,svr_ip,substr(info,1,40) order by count(*) desc limit 10; " 12 | global: true 13 | - version: "[*,2.9.9.9]" 14 | steps: 15 | - type: sql 16 | sql: " select a.db,a.tenant,a.user,b.svr_ip,ifnull(b.sql_id,''),avg(b.time),max(b.time),count(*),a.id,a.master_sessid from oceanbase.__all_virtual_processlist a 17 | inner join oceanbase.__all_virtual_session_info b on a.id=b.id and a.svr_ip=b.svr_ip 18 | inner join oceanbase.__all_tenant c on a.tenant=c.tenant_name and c.tenant_id>1000 19 | where b.sql_id<>'' and a.state<>'SLEEP' group by a.db,a.tenant,a.user,a.svr_ip,b.sql_id order by count(*) desc limit 10; " 20 | global: true 21 | - type: sql 22 | sql: " select user,svr_ip,replace(substr(info,1,40),char(10),'') as q_sql,avg(time),max(time),count(*),id from oceanbase.__all_virtual_processlist 23 | where tenant in (select b.tenant_name from __all_tenant b where b.tenant_id>1000) 24 | and state<>'SLEEP' group by user,svr_ip,substr(info,1,40) order by count(*) desc limit 10; " 25 | global: true 26 | -------------------------------------------------------------------------------- /plugins/display/tasks/observer/rs.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[rs]" 2 | info_cn: "[查看 rootservice 信息]" 3 | command: obdiag display scene run --scene=observer.rs 4 | task: 5 | - version: "[4.0.0.0, *]" 6 | steps: 7 | - type: sql 8 | sql: "show parameters like '%rootservice_list%';" 9 | global: true 10 | - type: sql 11 | sql: "select * from oceanbase.__all_rootservice_event_history order by 1 desc limit 10;" 12 | global: true 13 | - version: "[3.0.0.0, 3.9.9.9]" 14 | steps: 15 | - type: sql 16 | sql: "show parameters like '%rootservice_list%';" 17 | global: true 18 | - type: sql 19 | sql: "select * from oceanbase.__all_rootservice_event_history order by 1 desc limit 10;" 20 | global: true 21 | -------------------------------------------------------------------------------- /plugins/display/tasks/observer/server_info.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[server info]" 2 | info_cn: "[server 信息展示]" 3 | command: obdiag display scene run --scene=observer.server_info 4 | task: 5 | - version: "[4.2.0.0,*]" 6 | steps: 7 | - type: sql 8 | sql: "select b.info cluster_name,a.svr_ip,a.with_rootserver rs,a.zone, 9 | ora_decode(a.start_service_time,0,null,date_format(usec_to_time(a.start_service_time),'%Y-%m-%d %h:%i:%s')) start_service_time, 10 | ora_decode(a.last_offline_time,0,null,date_format(usec_to_time(a.last_offline_time),'%Y-%m-%d %h:%i:%s')) last_offline_time, 11 | ora_decode(a.stop_time,0,null,date_format(usec_to_time(a.stop_time),'%Y-%m-%d %h:%i:%s')) stop_time, 12 | a.status,SUBSTR(a.build_version, 1, INSTR(build_version, '-') - 1) build_version 13 | from oceanbase.__All_server a ,oceanbase.__all_zone b where b.name='cluster' order by a.zone,a.svr_ip; " 14 | global: true 15 | - version: "[*,4.1.9.9]" 16 | steps: 17 | - type: sql 18 | sql: "select b.info cluster_name,a.svr_ip,a.with_rootserver rs,a.zone, 19 | ora_decode(a.start_service_time,0,null,date_format(usec_to_time(a.start_service_time),'%Y-%m-%d %h:%i:%s')) start_service_time, 20 | ora_decode(a.stop_time,0,null,date_format(usec_to_time(a.stop_time),'%Y-%m-%d %h:%i:%s')) stop_time, 21 | a.status,SUBSTR(a.build_version, 1, INSTR(build_version, '-') - 1) build_version 22 | from oceanbase.__All_server a ,oceanbase.__all_zone b where b.name='cluster' order by a.zone,a.svr_ip; " 23 | global: true 24 | -------------------------------------------------------------------------------- /plugins/display/tasks/observer/slowsql.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[slowsql]" 2 | info_cn: "[查看慢sql]" 3 | command: obdiag display scene run --scene=observer.slowsql --env tenant_name=test --env mtime=10 4 | 5 | task: 6 | - version: "[4.0.0.0, *]" 7 | steps: 8 | - type: sql 9 | sql: "SELECT 10 | /*+READ_CONSISTENCY(WEAK), QUERY_TIMEOUT(100000000)*/ 11 | tenant_id, 12 | tenant_name, 13 | user_name, 14 | db_name, 15 | svr_ip, 16 | plan_id, 17 | plan_type, 18 | affected_rows, 19 | return_rows, 20 | elapsed_time, 21 | execute_time, 22 | sql_id, 23 | usec_to_time(request_time), 24 | substr( 25 | replace(query_sql, '\n', ' '), 26 | 1, 27 | 100 28 | ) 29 | FROM 30 | oceanbase.gv$ob_sql_audit 31 | WHERE 32 | tenant_name='#{tenant_name}' 33 | AND 1 = 1 34 | AND request_time > (time_to_usec(now()) - #{mtime} * 60 * 1000000) 35 | AND is_inner_sql = 0 36 | ORDER BY 37 | elapsed_time DESC 38 | LIMIT 10;" 39 | global: true 40 | - version: "[3.0.0.0, 3.9.9.9]" 41 | steps: 42 | - type: sql 43 | sql: "SELECT 44 | /*+READ_CONSISTENCY(WEAK), QUERY_TIMEOUT(100000000)*/ 45 | tenant_id, 46 | tenant_name, 47 | user_name, 48 | db_name, 49 | svr_ip, 50 | plan_id, 51 | plan_type, 52 | affected_rows, 53 | return_rows, 54 | elapsed_time, 55 | execute_time, 56 | sql_id, 57 | usec_to_time(request_time), 58 | substr( 59 | replace(query_sql, '\n', ' '), 60 | 1, 61 | 100 62 | ) 63 | FROM 64 | oceanbase.gv$sql_audit 65 | WHERE 66 | tenant_name='#{tenant_name}' 67 | AND 1 = 1 68 | AND request_time > (time_to_usec(now()) - #{mtime} * 60 * 1000000) 69 | AND is_inner_sql = 0 70 | ORDER BY 71 | elapsed_time DESC 72 | LIMIT 10;" 73 | global: true 74 | -------------------------------------------------------------------------------- /plugins/display/tasks/observer/zone_info.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[zone info]" 2 | info_cn: "[zone 信息展示]" 3 | command: obdiag display scene run --scene=observer.zone_info 4 | task: 5 | - version: "[4.0.0.0, *]" 6 | steps: 7 | - type: sql 8 | sql: "select * from oceanbase.dba_ob_zones;" 9 | global: true 10 | - version: "[3.0.0.0, 3.9.9.9]" 11 | steps: 12 | - type: sql 13 | sql: "select * from oceanbase.__all_zone;" 14 | global: true 15 | -------------------------------------------------------------------------------- /plugins/gather/redact/all_sql.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/09/19 15 | @file: all_sql.py 16 | @desc: 17 | """ 18 | import re 19 | 20 | 21 | class all_sql: 22 | def __init__(self): 23 | pass 24 | 25 | def redact(self, text): 26 | patterns = [ 27 | (r'stmt:"(.*?[^\\])", stmt_len', 'stmt:"", stmt_len'), 28 | (r'ps_sql:"(.*?[^\\])", is_expired_evicted', 'ps_sql:"", is_expired_evicted'), 29 | (r'ps_sql:"(.*?[^\\])", ref_count:', 'ps_sql:"", ref_count:'), 30 | (r'origin_sql=(.*?[^\\]), ps_stmt_checksum', 'origin_sql=, ps_stmt_checksum'), 31 | (r'get_sql_stmt\(\)=(.*?[^\\]), route_sql_=', 'get_sql_stmt()=, route_sql_='), 32 | (r'multi_stmt_item={(.*?[^\\])\}', 'multi_stmt_item={}'), 33 | ] 34 | log_content = text 35 | # 遍历所有模式并进行替换 36 | for pattern, replacement in patterns: 37 | log_content = re.sub(pattern, replacement, text, flags=re.DOTALL) 38 | return log_content 39 | 40 | 41 | all_sql = all_sql() 42 | -------------------------------------------------------------------------------- /plugins/gather/tasks/obproxy/restart.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[obproxy restart]" 2 | info_cn: "[obproxy无故重启]" 3 | command: obdiag gather scene run --scene=obproxy.restart 4 | task: 5 | - version: "[2.0.0.0, *]" 6 | steps: 7 | - type: ssh 8 | ssh: "ps -ef | grep obproxy" 9 | global: false 10 | - type: ssh 11 | ssh: "cat /proc/sys/kernel/core_pattern" 12 | global: false 13 | - type: ssh 14 | ssh: "ls -lhrt #{obproxy_data_dir}" 15 | global: false 16 | - type: obproxy_log 17 | grep: "" 18 | global: false 19 | -------------------------------------------------------------------------------- /plugins/gather/tasks/observer/cluster_down.yaml: -------------------------------------------------------------------------------- 1 | info_en: "[cluster down]" 2 | info_cn: "[集群无法连接]" 3 | command: obdiag gather scene run --scene=observer.cluster_down 4 | task: 5 | - version: "[2.0.0.0, *]" 6 | steps: 7 | - type: ssh 8 | ssh: "ps -ef | grep observer" 9 | global: false 10 | - type: ssh 11 | ssh: "cat /proc/sys/kernel/core_pattern" 12 | global: false 13 | - type: ssh 14 | ssh: "ls -lhrt #{observer_data_dir}" 15 | global: false 16 | - type: ssh 17 | ssh: "df -h" 18 | global: false 19 | - type: log 20 | grep: "" 21 | global: false 22 | - type: sysstat 23 | global: false 24 | sysstat: "" 25 | -------------------------------------------------------------------------------- /requirements3.txt: -------------------------------------------------------------------------------- 1 | bcrypt==3.2.2 2 | certifi==2024.7.4 3 | cffi==1.15.0 4 | charset-normalizer==2.0.12 5 | constant==0.0.4 6 | cryptography==44.0.1 7 | idna==3.7 8 | Jinja2==3.1.6 9 | MarkupSafe==2.0.1 10 | paramiko==3.4.1 11 | protobuf==4.21.0 12 | pyasn1==0.4.8 13 | pycparser==2.21 14 | PyNaCl==1.5.0 15 | requests==2.32.0 16 | rsa==4.8 17 | six==1.16.0 18 | tabulate==0.8.9 19 | zstandard==0.17.0 20 | pycryptodome~=3.14.1 21 | pick==1.2.0 22 | PyYAML==6.0.2rc1 23 | prettytable==3.5.0 24 | oyaml==1.0 25 | xmltodict==0.13.0 26 | subprocess32==3.5.4 27 | docker==6.1.3 28 | pwinput==1.0.3 29 | pyinstaller>=4.3 30 | colorama==0.4.6 31 | PyMySQL==1.1.1 32 | sqlparse==0.5.0 33 | ruamel.yaml==0.17.4 34 | progressbar==2.5 35 | halo==0.0.31 36 | inspect2==0.1.2 37 | sqlgpt-parser>=0.0.1a5 38 | netifaces==0.11.0 39 | netifaces==0.11.0 40 | kubernetes==30.1.0 41 | setuptools==65.6.3 42 | pyminizip==0.2.6 43 | plotly==5.24.1 44 | -------------------------------------------------------------------------------- /rpm/init.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_USER_ID=$(id -u) 4 | CURRENT_USER_NAME=$(logname 2>/dev/null || echo "$SUDO_USER" | awk -F'[^a-zA-Z0-9_]' '{print $1}') 5 | 6 | if [ "$CURRENT_USER_ID" -eq 0 ]; then 7 | if [ -n "$SUDO_USER" ]; then 8 | USER_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6) 9 | else 10 | USER_HOME=/root 11 | fi 12 | else 13 | USER_HOME="$HOME" 14 | fi 15 | 16 | if [[ $# == 1 && $1 == "-f" ]]; then 17 | FORCE_DEPLOY="1" 18 | else 19 | FORCE_DEPLOY="0" 20 | fi 21 | 22 | WORK_DIR=$(readlink -f "$(dirname ${BASH_SOURCE[0]})") 23 | 24 | if [ ${OBDIAG_HOME} ]; then 25 | OBDIAG_HOME=${OBDIAG_HOME} 26 | else 27 | OBDIAG_HOME="${USER_HOME}/.obdiag" 28 | fi 29 | 30 | mkdir -p ${OBDIAG_HOME} && cd ${OBDIAG_HOME} 31 | mkdir -p ${OBDIAG_HOME}/check 32 | mkdir -p ${OBDIAG_HOME}/log 33 | mkdir -p ${OBDIAG_HOME}/display 34 | 35 | # Clean rca old *scene.py files 36 | find ${OBDIAG_HOME}/rca -maxdepth 1 -name "*_scene.py" -type f -exec rm -f {} + 2>/dev/null 37 | 38 | \cp -rf ${WORK_DIR}/plugins/* ${OBDIAG_HOME}/ 39 | 40 | bashrc_file=~/.bashrc 41 | if [ -e "$bashrc_file" ]; then 42 | ALIAS_OBDIAG_EXIST=$(grep "alias obdiag='sh" ~/.bashrc | head -n 1) 43 | if [[ "${ALIAS_OBDIAG_EXIST}" != "" ]]; then 44 | echo "need update obdiag alias" 45 | echo "alias obdiag='obdiag'" >> ~/.bashrc 46 | fi 47 | fi 48 | 49 | source ${WORK_DIR}/init_obdiag_cmd.sh 50 | 51 | cd - 52 | output_file=${OBDIAG_HOME}/version.yaml 53 | version_line=$(/opt/oceanbase-diagnostic-tool/obdiag --version 2>&1 | grep -oP 'OceanBase Diagnostic Tool: \K[\d.]+') 54 | if [ -n "$version_line" ]; then 55 | content="obdiag_version: \"$version_line\"" 56 | 57 | # Write or update the version information to the file 58 | echo "$content" > "$output_file" 59 | 60 | echo "obdiag version information has been successfully written to $output_file" 61 | else 62 | echo "failed to retrieve obdiag version information." 63 | fi 64 | 65 | chown -R ${CURRENT_USER_NAME}: ${OBDIAG_HOME} 66 | 67 | echo "Init obdiag finished" 68 | -------------------------------------------------------------------------------- /src/common/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2022/6/20 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/common/import_module.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/09/19 15 | @file: import_modules.py 16 | @desc: 17 | """ 18 | import os 19 | 20 | from src.common.tool import DynamicLoading 21 | 22 | 23 | class ImportModulesException(Exception): 24 | pass 25 | 26 | 27 | # 实现模块导入,要求module_name为模块名和需要导入的对象名,module_file_path为模块文件路径 28 | 29 | 30 | def import_modules(module_file_dir, stdio): 31 | stdio.verbose("import_modules input: module_file_dir->{0}".format(module_file_dir)) 32 | try: 33 | module_files = [] 34 | module_list = {} 35 | for root, dirs, files in os.walk(module_file_dir): 36 | if root == module_file_dir: 37 | module_files = files 38 | for module_file in module_files: 39 | module_name = os.path.basename(module_file)[:-3] 40 | DynamicLoading.add_lib_path(module_file_dir) 41 | module = DynamicLoading.import_module(os.path.basename(module_file)[:-3], None) 42 | if not hasattr(module, module_name): 43 | stdio.error("{0} import_module failed".format(module_name)) 44 | continue 45 | module_list[module_name] = getattr(module, module_name) 46 | return module_list 47 | except Exception as e: 48 | stdio.error("import_modules failed: {0}".format(e)) 49 | raise ImportModulesException("import_modules failed: {0}".format(e)) 50 | -------------------------------------------------------------------------------- /src/common/log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @file: log.py 15 | @desc: 16 | """ 17 | 18 | from __future__ import absolute_import, division, print_function 19 | import locale 20 | 21 | try: 22 | locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') 23 | except Exception: 24 | # Fallback to the default locale if setting fails 25 | pass 26 | 27 | import logging 28 | 29 | 30 | class Logger(logging.Logger): 31 | 32 | def __init__(self, name, level=logging.DEBUG): 33 | super(Logger, self).__init__(name, level) 34 | self.buffer = [] 35 | self.buffer_size = 0 36 | 37 | def _log(self, level, msg, args, end='\n', **kwargs): 38 | return super(Logger, self)._log(level, msg, args, **kwargs) 39 | -------------------------------------------------------------------------------- /src/common/ob_log_level.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/10/20 15 | @file: ob_log_level.log 16 | @desc: 17 | """ 18 | 19 | 20 | class OBLogLevel(object): 21 | CRITICAL = 50 22 | FATAL = 50 23 | ERROR = 40 24 | EDIAG = 35 25 | WARN = 30 26 | WDIAG = 25 27 | INFO = 20 28 | TRACE = 15 29 | DEBUG = 10 30 | NOTSET = 0 31 | 32 | def get_log_level(self, level_str): 33 | if level_str == "CRITICAL": 34 | return self.CRITICAL 35 | elif level_str == "FATAL": 36 | return self.FATAL 37 | elif level_str == "ERROR": 38 | return self.ERROR 39 | elif level_str == "EDIAG": 40 | return self.EDIAG 41 | elif level_str == "WARN": 42 | return self.WARN 43 | elif level_str == "WDIAG": 44 | return self.WDIAG 45 | elif level_str == "INFO": 46 | return self.INFO 47 | elif level_str == "TRACE": 48 | return self.TRACE 49 | elif level_str == "DEBUG": 50 | return self.DEBUG 51 | else: 52 | return self.NOTSET 53 | -------------------------------------------------------------------------------- /src/common/ocp/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2022/6/20 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/common/ocp/ocp_api.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | 14 | """ 15 | @time: 2022/6/24 16 | # File : ocp_api.py 17 | # Description: 18 | """ 19 | # login 20 | login = "/api/v2/iam/login" 21 | 22 | # host 23 | host = "/api/v2/compute/hosts" 24 | region = "/api/v2/compute/regions" 25 | idc = "/api/v2/compute/idcs" 26 | host_type = "/api/v2/compute/hostTypes" 27 | host_agent = "/api/v2/compute/hosts/%s/agent" 28 | host_remote_info = "/api/v2/compute/hosts/%s/remoteHostInfo" 29 | host_by_idc = "/api/v2/compute/stats/hostByIdc" 30 | 31 | # cluster 32 | cluster = "/api/v2/ob/clusters" 33 | cluster_resource_status = "/api/v2/ob/clusters/stats" 34 | cluster_parameters = "/api/v2/ob/clusters/parameterInfo" 35 | 36 | # task 37 | task = "/api/v2/tasks/instances" 38 | -------------------------------------------------------------------------------- /src/common/result_type.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """ 13 | @time: 2024/08/21 14 | @file: result_type.py 15 | @desc: 16 | """ 17 | import json 18 | 19 | 20 | class ObdiagResult: 21 | # ObdiagResult is the result of obdiag. 22 | # It contains the code and result of obdiag. 23 | 24 | # SERVER_ERROR_CODE(5xx) is the code of server error. 25 | SERVER_ERROR_CODE = 500 26 | # INPUT_ERROR_CODE(4xx) is the code of input error. 27 | INPUT_ERROR_CODE = 400 28 | # SUCCESS_CODE(200) is the code of success. 29 | SUCCESS_CODE = 200 30 | 31 | def __init__(self, code, data=None, error_data=None): 32 | self.command = None 33 | self.trace_id = None 34 | self.data = data 35 | self.error_data = error_data 36 | if code is None: 37 | raise TypeError("ObdiagResult code is None. Please contact the Oceanbase community. ") 38 | self.code = code 39 | if data is not None: 40 | if isinstance(data, dict): 41 | self.data = data 42 | else: 43 | raise TypeError("ObdiagResult data is not dict. Please contact the Oceanbase community. ") 44 | if error_data is not None: 45 | if isinstance(error_data, str): 46 | self.error_data = error_data 47 | else: 48 | raise TypeError("ObdiagResult error_data is not str. Please contact the Oceanbase community. ") 49 | 50 | def set_trace_id(self, trace_id): 51 | self.trace_id = "{0}".format(trace_id) 52 | 53 | def set_command(self, command): 54 | self.command = command 55 | 56 | def get_result(self): 57 | result = {"code": self.code, "data": self.data, "error_data": self.error_data, "trace_id": self.trace_id, "command": self.command} 58 | return json.dumps(result, ensure_ascii=False) 59 | 60 | def get_code(self): 61 | return self.code 62 | 63 | def is_success(self): 64 | return self.code == self.SUCCESS_CODE 65 | -------------------------------------------------------------------------------- /src/common/ssh_client/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/6/24 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/common/version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2022/6/22 15 | @file: version.py 16 | @desc: 17 | """ 18 | 19 | # obdiag version 20 | OBDIAG_VERSION = '' 21 | # obdiag build time 22 | OBDIAG_BUILD_TIME = '' 23 | 24 | 25 | def get_obdiag_version(): 26 | version = '''OceanBase Diagnostic Tool: %s 27 | BUILD_TIME: %s 28 | Copyright (C) 2022 OceanBase 29 | License Mulan PSL v2: http://license.coscl.org.cn/MulanPSL2. 30 | You can use this software according to the terms and conditions of the Mulan PSL v2. 31 | There is NO WARRANTY, to the extent permitted by law.''' % ( 32 | OBDIAG_VERSION, 33 | OBDIAG_BUILD_TIME, 34 | ) 35 | return version 36 | -------------------------------------------------------------------------------- /src/handler/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2022/6/20 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/analyzer/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/9/20 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/analyzer/log_parser/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/11/07 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/analyzer/log_parser/log_enum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/11/07 15 | @file: log_enum.py 16 | @desc: 17 | """ 18 | import os 19 | 20 | 21 | class OBLogRoleConst(object): 22 | OBLOG_ROLE_ROOTSERVICE = 'RS' 23 | OBLOG_ROLE_OBSERVER = 'OBS' 24 | OBLOG_ROLE_SUPPORT_LIST = [OBLOG_ROLE_OBSERVER, OBLOG_ROLE_ROOTSERVICE] 25 | 26 | 27 | class LogTypeConst(object): 28 | LOG_TYPE_REGULAR = 1 29 | LOG_TYPE_WF = 2 30 | 31 | 32 | class AttrRuleTypeConst(object): 33 | RULE_TYPE_EQUAL = 1 34 | RULE_TYPE_RANGE = 2 35 | VALID_RULE_TYPE = [RULE_TYPE_EQUAL, RULE_TYPE_RANGE] 36 | 37 | 38 | class AttrRuleBracOrBareConst(object): 39 | IN_BRAC_ATTR = 1 # 日志中在括号内的attr 40 | BARE_ATTR = 2 # 日志中在括号外的attr 41 | 42 | 43 | AttrBracOrBareDict = { 44 | "log_level": AttrRuleBracOrBareConst.BARE_ATTR, 45 | "component": AttrRuleBracOrBareConst.IN_BRAC_ATTR, 46 | "th_id": AttrRuleBracOrBareConst.IN_BRAC_ATTR, 47 | "co_id": AttrRuleBracOrBareConst.IN_BRAC_ATTR, 48 | "trace_id": AttrRuleBracOrBareConst.IN_BRAC_ATTR, 49 | } 50 | 51 | 52 | class AgentRuntimeGlobalVars(object): 53 | AgentRuntimeDir = os.getcwd() 54 | 55 | 56 | # dir name in pack 57 | class DirNameInPackConst(object): 58 | TRIMMED_LOG_DIR_NAME_IN_PACK = 'trimmed_log' 59 | OS_STATE_LOG_DIR_NAME_IN_PACK = 'os_state' 60 | 61 | 62 | class PackCompressConst(object): 63 | COMPRESS_ZIP = 'zip' 64 | COMPRESS_ZSTD = 'zstd' 65 | CompressSuffixDict = { 66 | COMPRESS_ZIP: '.zip', 67 | COMPRESS_ZSTD: '.tar.zst', 68 | } 69 | COMPRESS_VALID_LIST = [COMPRESS_ZIP, COMPRESS_ZSTD] 70 | # 当前使用的压缩类型 71 | PACK_COMPRESS_TYPE = COMPRESS_ZIP 72 | 73 | 74 | LOG_LEVEL_LIST = ["DEBUG", "INFO", "WARN", "ERROR", "FATAL", "TRACE"] 75 | 76 | LOG_TYPE = ["observer", "election", "rootservice"] 77 | -------------------------------------------------------------------------------- /src/handler/analyzer/sql/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/5/21 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/analyzer/sql/engine.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/5/21 15 | @file: engine.py 16 | @desc: 17 | """ 18 | 19 | from sqlgpt_parser.parser.oceanbase_parser import parser as oceanbase_parser 20 | 21 | 22 | class Engine(object): 23 | def __new__(cls): 24 | singleton = cls.__dict__.get('__singleton__') 25 | if singleton is not None: 26 | return singleton 27 | 28 | cls.__singleton__ = singleton = object.__new__(cls) 29 | 30 | return singleton 31 | 32 | def parse(self, sql, tracking=False): 33 | return oceanbase_parser.parse(sql, tracking=tracking) 34 | -------------------------------------------------------------------------------- /src/handler/analyzer/sql/meta/_init_.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/5/21 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/analyzer/sql/rules/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/5/21 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/analyzer/sql/rules/abstract_rule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/5/22 15 | @file: abstract_rule.py 16 | @desc: 17 | """ 18 | 19 | from abc import ABCMeta, abstractmethod 20 | 21 | from sqlgpt_parser.parser.tree.statement import Statement 22 | 23 | 24 | class AbstractRule(metaclass=ABCMeta): 25 | def match(self, root: Statement, context=None) -> bool: 26 | return True 27 | 28 | @abstractmethod 29 | def suggestion(self, root: Statement, context=None): 30 | pass 31 | -------------------------------------------------------------------------------- /src/handler/analyzer/sql/rules/level.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/5/22 15 | @file: level.py 16 | @desc: 17 | """ 18 | 19 | from enum import Enum, unique 20 | 21 | 22 | @unique 23 | class Level(Enum): 24 | OK = (1, 'ok') 25 | NOTICE = (2, 'notice') 26 | WARN = (3, 'warn') 27 | CRITICAL = (4, 'critical') 28 | 29 | def __lt__(self, other): 30 | if self.__class__ is other.__class__: 31 | return self.value[0] < other.value[0] 32 | return NotImplemented 33 | 34 | def __le__(self, other): 35 | if self.__class__ is other.__class__: 36 | return self.value[0] <= other.value[0] 37 | return NotImplemented 38 | 39 | def __gt__(self, other): 40 | if self.__class__ is other.__class__: 41 | return self.value[0] > other.value[0] 42 | return NotImplemented 43 | 44 | def __ge__(self, other): 45 | if self.__class__ is other.__class__: 46 | return self.value[0] >= other.value[0] 47 | return NotImplemented 48 | 49 | @classmethod 50 | def from_string(cls, s): 51 | for member in cls: 52 | if member.value[1] == s: 53 | return member 54 | raise ValueError(f"No such level: {s}") 55 | 56 | @property 57 | def string(self): 58 | return self.value[1] 59 | -------------------------------------------------------------------------------- /src/handler/analyzer/sql/rules/result.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/5/20 15 | @file: result.py 16 | @desc: 17 | """ 18 | import json 19 | 20 | 21 | class Result(object): 22 | def __init__(self, name, level, suggestion, description): 23 | self.class_name = name 24 | self.rule_name = name 25 | self.level = level 26 | self.suggestion = suggestion 27 | self.description = description 28 | 29 | def __str__(self): 30 | return json.dumps({"class_name": self.rule_name, "rule_name": self.rule_name, "level": self.level.value, "suggestion": self.suggestion, "description": self.description}, indent=5) 31 | -------------------------------------------------------------------------------- /src/handler/analyzer/sql/rules/review/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/5/21 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/analyzer/sql/rules/review/arithmetic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/5/20 15 | @file: arithmetic.py 16 | @desc: 17 | """ 18 | from src.handler.analyzer.sql.rules.level import Level 19 | from sqlgpt_parser.parser.tree.expression import QualifiedNameReference 20 | from sqlgpt_parser.parser.tree.statement import Statement 21 | from sqlgpt_parser.parser.tree.visitor import DefaultTraversalVisitor 22 | from src.handler.analyzer.sql.rules.abstract_rule import AbstractRule 23 | from src.handler.analyzer.sql.rules.result import Result 24 | 25 | 26 | class ArithmeticRule(AbstractRule): 27 | rule_name = "arithmetic_rule" 28 | rule_description = """ 29 | Field operations are not recommended. 30 | Example: a + 1 > 2 => a > 2 - 1 31 | """ 32 | 33 | def match(self, root: Statement, catalog=None) -> bool: 34 | class Visitor(DefaultTraversalVisitor): 35 | def __init__(self): 36 | self.match = False 37 | 38 | def visit_arithmetic_binary(self, node, context): 39 | if isinstance(node.left, QualifiedNameReference) or isinstance(node.right, QualifiedNameReference): 40 | self.match = True 41 | 42 | try: 43 | visitor = Visitor() 44 | visitor.process(root, None) 45 | except Exception as e: 46 | pass 47 | 48 | return visitor.match 49 | 50 | def suggestion(self, root: Statement, catalog=None): 51 | suggest_text = 'Consider simplifying your expressions by moving constants out of comparisons.' 52 | if not self.match(root, catalog): 53 | return Result(self.rule_name, Level.OK, "No improper field operations detected, query is optimized.", self.rule_description) 54 | else: 55 | return Result(self.rule_name, Level.NOTICE, suggest_text, self.rule_description) 56 | -------------------------------------------------------------------------------- /src/handler/analyzer/sql/rules/tunning/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/5/21 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/base_shell_handler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2022/6/21 15 | @file: base_handler.py 16 | @desc: 17 | """ 18 | 19 | 20 | # 所有需要连接到各个节点执行ssh命令的继承自该handler,通过 paramiko 到目标机器上执行shell命令来来得到结果 21 | 22 | 23 | class BaseShellHandler(object): 24 | def __init__(self) -> None: 25 | self._stdio_func = None 26 | 27 | def _call_stdio(self, func, msg, *arg, **kwarg): 28 | if func not in self._stdio_func: 29 | return None 30 | return self._stdio_func[func](msg, *arg, **kwarg) 31 | -------------------------------------------------------------------------------- /src/handler/checker/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/9/26 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/checker/check_exception.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/9/26 15 | @file: check_exception.py 16 | @desc: 17 | """ 18 | import pprint 19 | 20 | 21 | class CheckException(Exception): 22 | def __init__(self, msg=None, obj=None): 23 | self.msg, self.obj = msg, obj 24 | 25 | def __repr__(self): 26 | return '%s %s' % (self.msg, self.obj is not None and pprint.pformat(self.obj) or '') 27 | 28 | def __str__(self): 29 | return repr(self) 30 | 31 | 32 | class StepVerifyException(CheckException): 33 | def __init__(self, msg=None, obj=None): 34 | super(StepVerifyException, self).__init__(msg, obj) 35 | 36 | 37 | # for step to task 38 | class StepExecuteFailException(CheckException): 39 | def __init__(self, msg=None, obj=None): 40 | super(StepExecuteFailException, self).__init__(msg, obj) 41 | 42 | 43 | class StepResultFalseException(CheckException): 44 | def __init__(self, msg=None, obj=None): 45 | super(StepResultFalseException, self).__init__(msg, obj) 46 | 47 | 48 | class StepResultFailException(CheckException): 49 | def __init__(self, msg=None, obj=None): 50 | super(StepResultFailException, self).__init__(msg, obj) 51 | 52 | 53 | class ResultFalseException(CheckException): 54 | def __init__(self, msg=None, obj=None): 55 | super(ResultFalseException, self).__init__(msg, obj) 56 | 57 | 58 | class ResultFailException(CheckException): 59 | def __init__(self, msg=None, obj=None): 60 | super(ResultFailException, self).__init__(msg, obj) 61 | 62 | 63 | class VerifyFalseException(CheckException): 64 | def __init__(self, msg=None, obj=None): 65 | super(VerifyFalseException, self).__init__(msg, obj) 66 | 67 | 68 | class VerifyFailException(CheckException): 69 | def __init__(self, msg=None, obj=None): 70 | super(VerifyFailException, self).__init__(msg, obj) 71 | 72 | 73 | class TaskException(CheckException): 74 | def __init__(self, msg=None, obj=None): 75 | super(TaskException, self).__init__(msg, obj) 76 | -------------------------------------------------------------------------------- /src/handler/checker/result/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/9/26 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/checker/step/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/9/26 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/display/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/9/20 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/display/scenes/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/08/31 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/display/scenes/register.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/08/31 15 | @file: register.py 16 | @desc: 17 | """ 18 | 19 | from dataclasses import dataclass 20 | import datetime 21 | 22 | 23 | @dataclass 24 | class RegisteredHardCodeScene: 25 | name: str 26 | command: str 27 | info_en: str 28 | info_cn: str 29 | 30 | 31 | # 对于不适合通过yaml编排的复杂场景可以用这个类注册,注册后通过代码实现采集逻辑 32 | db_connect = '-h127.0.0.1 -P2881 -utest@test -p****** -Dtest' 33 | trace_id = 'Yxx' 34 | estimated_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') 35 | 36 | hardcode_scene_list = [] 37 | -------------------------------------------------------------------------------- /src/handler/display/step/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/08/31 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/gather/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/9/20 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/gather/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/09/18 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/gather/scenes/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/12/26 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/gather/scenes/register.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/01/10 15 | @file: register.py 16 | @desc: 17 | """ 18 | 19 | from dataclasses import dataclass 20 | import datetime 21 | 22 | 23 | @dataclass 24 | class RegisteredHardCodeScene: 25 | name: str 26 | command: str 27 | info_en: str 28 | info_cn: str 29 | 30 | 31 | # 对于不适合通过yaml编排的复杂场景可以用这个类注册,注册后通过代码实现采集逻辑 32 | db_connect = '-h127.0.0.1 -P2881 -utest@test -p****** -Dtest' 33 | trace_id = 'Yxx' 34 | estimated_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') 35 | 36 | hardcode_scene_list = [ 37 | RegisteredHardCodeScene('observer.perf_sql', f'''obdiag gather scene run --scene=observer.perf_sql --env "{{db_connect='{db_connect}', trace_id='{trace_id}'}}"''', '[SQL performance problem]', '[SQL性能问题]'), 38 | RegisteredHardCodeScene('observer.sql_err', f'''obdiag gather scene run --scene=observer.sql_err --env "{{db_connect='{db_connect}', trace_id='{trace_id}'}}"''', '[SQL execution error]', '[SQL 执行出错]'), 39 | RegisteredHardCodeScene('observer.cpu_high', 'obdiag gather scene run --scene=observer.cpu_high --env "{perf_count=100000000}"', '[High CPU]', '[CPU高]'), 40 | RegisteredHardCodeScene( 41 | 'observer.px_collect_log', f'''obdiag gather scene run --scene=observer.px_collect_log --env "{{trace_id='{trace_id}', estimated_time='{estimated_time}'}}"''', '[Collect error source node logs for SQL PX]', '[SQL PX 收集报错源节点日志]' 42 | ), 43 | ] 44 | -------------------------------------------------------------------------------- /src/handler/gather/step/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/01/05 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/meta/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/9/20 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/meta/check_meta.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/9/20 15 | @file: check_meta.py 16 | @desc: 17 | """ 18 | 19 | 20 | class GlobalCheckMeta: 21 | _check_dict = {} 22 | 23 | def _init(self): 24 | global _check_dict 25 | self._check_dict = {} 26 | 27 | def set_value(self, key, value): 28 | self._check_dict[key] = value 29 | 30 | def get_value(self, key): 31 | try: 32 | return self._check_dict[key] 33 | except: 34 | print('get' + key + 'failed\r\n') 35 | 36 | def rm_value(self, key): 37 | try: 38 | return self._check_dict.pop(key) 39 | except: 40 | print('delete' + key + 'failed\r\n') 41 | 42 | 43 | check_dict = GlobalCheckMeta() 44 | check_dict.set_value( 45 | "check_verify_shell", 46 | ''' 47 | if ${new_expr}; then 48 | echo "true" 49 | else 50 | echo "false" 51 | fi 52 | ''', 53 | ) 54 | -------------------------------------------------------------------------------- /src/handler/rca/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/03/08 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/rca/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/03/08 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/handler/rca/rca_exception.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/12/22 15 | @file: rca_exception.py 16 | @desc: 17 | """ 18 | import pprint 19 | 20 | 21 | # rca 22 | class RCAInitException(Exception): 23 | def __init__(self, msg=None, obj=None): 24 | self.msg, self.obj = msg, obj 25 | 26 | def __repr__(self): 27 | return '%s %s' % (self.msg, self.obj is not None and pprint.pformat(self.obj) or '') 28 | 29 | def __str__(self): 30 | return repr(self) 31 | 32 | 33 | class RCAExecuteException(Exception): 34 | def __init__(self, msg=None, obj=None): 35 | self.msg, self.obj = msg, obj 36 | 37 | def __repr__(self): 38 | return '%s %s' % (self.msg, self.obj is not None and pprint.pformat(self.obj) or '') 39 | 40 | def __str__(self): 41 | return repr(self) 42 | 43 | 44 | class RCANotNeedExecuteException(Exception): 45 | def __init__(self, msg=None, obj=None): 46 | self.msg, self.obj = msg, obj 47 | 48 | def __repr__(self): 49 | return '%s %s' % (self.msg, self.obj is not None and pprint.pformat(self.obj) or '') 50 | 51 | def __str__(self): 52 | return repr(self) 53 | 54 | 55 | class RCAReportException(Exception): 56 | def __init__(self, msg=None, obj=None): 57 | super(RCAReportException, self).__init__(msg, obj) 58 | -------------------------------------------------------------------------------- /src/handler/update/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/01/30 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /src/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @file: main.py 15 | @desc: 16 | """ 17 | 18 | import sys 19 | from src.common.diag_cmd import MainCommand 20 | from src.common.stdio import IO 21 | 22 | ROOT_IO = IO(1) 23 | 24 | if __name__ == '__main__': 25 | defaultencoding = 'utf-8' 26 | if sys.getdefaultencoding() != defaultencoding: 27 | try: 28 | from imp import reload 29 | except: 30 | pass 31 | reload(sys) 32 | sys.setdefaultencoding(defaultencoding) 33 | ROOT_IO.track_limit += 2 34 | if MainCommand().init(sys.argv[0], sys.argv[1:]).do_command(): 35 | ROOT_IO.exit(0) 36 | else: 37 | ROOT_IO.exit(1) 38 | -------------------------------------------------------------------------------- /src/telemetry/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2023/11/24 15 | @file: __init__.py 16 | @desc: 17 | """ 18 | -------------------------------------------------------------------------------- /test/analyzer/sql/test_large_in_clause_rule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/06/05 15 | @file: test_large_in_clause_rule.py 16 | @desc: 17 | """ 18 | 19 | import unittest 20 | from src.handler.analyzer.sql.rules.review.large_in_clause import LargeInClauseAdjustedRule 21 | from sqlgpt_parser.parser.oceanbase_parser import parser 22 | from src.handler.analyzer.sql.rules.level import Level 23 | 24 | 25 | class TestLargeInClauseAdjustedRule(unittest.TestCase): 26 | 27 | def setUp(self): 28 | self.rule = LargeInClauseAdjustedRule() 29 | 30 | def test_large_in_clause(self): 31 | # 构建一个超过200个元素的IN子句的SQL语句 32 | large_in_clause_sql = "SELECT * FROM table1 WHERE id IN (" + ','.join(['?'] * 201) + ")" 33 | parsed_stmt = parser.parse(large_in_clause_sql) 34 | 35 | self.assertTrue(self.rule.match(parsed_stmt), "Expected to match for SQL with over 200 IN elements") 36 | suggestion = self.rule.suggestion(parsed_stmt) 37 | self.assertEqual(suggestion.level, Level.WARN) 38 | 39 | def test_small_in_clause(self): 40 | # 构建一个少于200个元素的IN子句的SQL语句 41 | small_in_clause_sql = "SELECT * FROM table1 WHERE id IN (" + ','.join(['?'] * 199) + ")" 42 | parsed_stmt = parser.parse(small_in_clause_sql) 43 | 44 | self.assertFalse(self.rule.match(parsed_stmt), "Should not match for SQL within the limit of 200 IN elements") 45 | suggestion = self.rule.suggestion(parsed_stmt) 46 | self.assertEqual(suggestion.level, Level.OK) 47 | 48 | def test_no_in_clause(self): 49 | # 构建一个不包含IN子句的SQL语句 50 | no_in_clause_sql = "SELECT * FROM table1 WHERE column = 'value'" 51 | parsed_stmt = parser.parse(no_in_clause_sql) 52 | 53 | self.assertFalse(self.rule.match(parsed_stmt), "Should not match for SQL without an IN clause") 54 | suggestion = self.rule.suggestion(parsed_stmt) 55 | self.assertEqual(suggestion.level, Level.OK) 56 | 57 | 58 | if __name__ == '__main__': 59 | unittest.main() 60 | -------------------------------------------------------------------------------- /test/analyzer/test_level.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2024/07/02 15 | @file: test_level.py 16 | @desc: 17 | """ 18 | import unittest 19 | from src.handler.analyzer.sql.rules.level import Level 20 | 21 | 22 | class TestLevelEnum(unittest.TestCase): 23 | 24 | def test_enum_creation_and_access(self): 25 | self.assertEqual(Level.OK.name, 'OK') 26 | self.assertEqual(Level.OK.value, (1, 'ok')) 27 | self.assertEqual(Level.CRITICAL.string, 'critical') 28 | 29 | def test_comparison_operators(self): 30 | self.assertTrue(Level.OK < Level.NOTICE) 31 | self.assertTrue(Level.NOTICE <= Level.NOTICE) 32 | self.assertFalse(Level.WARN <= Level.OK) 33 | self.assertTrue(Level.CRITICAL > Level.WARN) 34 | self.assertTrue(Level.CRITICAL >= Level.CRITICAL) 35 | 36 | def test_from_string(self): 37 | self.assertEqual(Level.from_string('ok'), Level.OK) 38 | self.assertEqual(Level.from_string('warn'), Level.WARN) 39 | 40 | with self.assertRaises(ValueError) as context: 41 | Level.from_string('error') 42 | self.assertEqual(str(context.exception), "No such level: error") 43 | 44 | def test_invalid_string(self): 45 | with self.assertRaises(ValueError) as context: 46 | Level.from_string('unknown') 47 | self.assertEqual(str(context.exception), "No such level: unknown") 48 | 49 | 50 | if __name__ == '__main__': 51 | unittest.main() 52 | -------------------------------------------------------------------------------- /test/common/ssh_client/test_kubernetes_cilent.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Config 3 | clusters: 4 | - cluster: 5 | certificate-authority-data: DATA+OMITTED 6 | server: https://127.0.0.1:8443 7 | name: dev-cluster 8 | users: 9 | - user: 10 | client-certificate-data: DATA+OMITTED 11 | client-key-data: DATA+OMITTED 12 | name: dev-user 13 | contexts: 14 | - context: 15 | cluster: dev-cluster 16 | user: dev-user 17 | name: dev-context 18 | current-context: dev-context -------------------------------------------------------------------------------- /test/common/test_sql_table_extractor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """ 14 | @time: 2025/2/19 15 | @file: test_sql_table_extractor.py 16 | @desc: 17 | """ 18 | 19 | import unittest 20 | from src.common.tool import SQLTableExtractor 21 | 22 | 23 | class TestSQLTableExtractor(unittest.TestCase): 24 | 25 | def setUp(self): 26 | self.parser = SQLTableExtractor() 27 | 28 | def test_select_with_db(self): 29 | result = self.parser.parse("SELECT * FROM db1.table1 WHERE id > 10;") 30 | self.assertEqual(result, [('db1', 'table1')]) 31 | 32 | def test_insert_with_db(self): 33 | result = self.parser.parse("INSERT INTO db2.table2 (id, name) VALUES (1, 'test')") 34 | self.assertEqual(result, [('db2', 'table2')]) 35 | 36 | def test_update_with_db(self): 37 | result = self.parser.parse("UPDATE db3.table3 SET status='active' WHERE id=1;") 38 | self.assertEqual(result, [('db3', 'table3')]) 39 | 40 | def test_delete_with_db(self): 41 | result = self.parser.parse("DELETE FROM db4.table4 WHERE created_at < '2025-01-01';") 42 | self.assertEqual(result, [('db4', 'table4')]) 43 | 44 | def test_no_db_name(self): 45 | result = self.parser.parse("SELECT * FROM table_no_db;") 46 | self.assertEqual(result, [(None, 'table_no_db')]) 47 | 48 | def test_complex_query_with_aliases(self): 49 | sql = "SELECT t1.id, t2.name FROM db5.table1 AS t1 JOIN db5.table2 AS t2 ON t1.id = t2.user_id;" 50 | result = self.parser.parse(sql) 51 | self.assertEqual(result, [('db5', 'table1'), ('db5', 'table2')]) 52 | 53 | def test_unsupported_statement(self): 54 | result = self.parser.parse("DROP TABLE IF EXISTS db12.table11;") 55 | self.assertEqual(result, []) 56 | 57 | 58 | if __name__ == '__main__': 59 | unittest.main() 60 | -------------------------------------------------------------------------------- /workflow_data/check_py_files.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -* 3 | # Copyright (c) 2022 OceanBase 4 | # OceanBase Diagnostic Tool is licensed under Mulan PSL v2. 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """ 13 | @time: 2025/04/14 14 | @file: check_py_files.py 15 | @desc: for check python files header 16 | """ 17 | 18 | import os 19 | 20 | EXPECTED_LINES = ["#!/usr/bin/env python", "# -*- coding: UTF-8 -*", "# Copyright (c) 2022 OceanBase"] 21 | 22 | 23 | def check_file(file_path): 24 | try: 25 | with open(file_path, 'r', encoding='utf-8') as f: 26 | lines = [f.readline().rstrip('\n') for _ in range(3)] 27 | return lines == EXPECTED_LINES 28 | except Exception: 29 | return False 30 | 31 | 32 | def main(): 33 | import sys 34 | 35 | target_dir = sys.argv[1] if len(sys.argv) > 1 else '.' 36 | failed = [] 37 | for root, _, files in os.walk(target_dir): 38 | for file in files: 39 | if file.endswith('.py'): 40 | path = os.path.join(root, file) 41 | if not check_file(path): 42 | failed.append(path) 43 | 44 | if failed: 45 | print(f"❌ The following files do not comply with the specifications. Please add copyright related information:{failed}") 46 | sys.exit(1) 47 | else: 48 | print("✅ all pass!") 49 | 50 | 51 | if __name__ == "__main__": 52 | main() 53 | -------------------------------------------------------------------------------- /workflow_data/config.yml: -------------------------------------------------------------------------------- 1 | obcluster: 2 | ob_cluster_name: test 3 | db_host: 127.0.0.1 4 | db_port: 2881 # default 2881 5 | tenant_sys: 6 | user: root@sys # default root@sys 7 | password: "" 8 | servers: 9 | nodes: 10 | - ip: 127.0.0.1 11 | ssh_username: root 12 | ssh_password: '' 13 | home_path: /root/ob/observer 14 | data_dir: /root/ob/observer/store 15 | redo_dir: /root/ob/observer/store 16 | global: 17 | ssh_port: 22 18 | -------------------------------------------------------------------------------- /workflow_data/config.yml.421: -------------------------------------------------------------------------------- 1 | obcluster: 2 | ob_cluster_name: test 3 | db_host: 127.0.0.1 4 | db_port: 2881 # default 2881 5 | tenant_sys: 6 | user: root@sys # default root@sys 7 | password: "" 8 | servers: 9 | nodes: 10 | - ip: 127.0.0.1 11 | ssh_username: root 12 | ssh_password: '' 13 | home_path: /root/ob 14 | data_dir: /root/ob/store 15 | redo_dir: /root/ob/store 16 | global: 17 | ssh_port: 22 18 | -------------------------------------------------------------------------------- /workflow_data/wait_observer_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SUCCESS_MSG="boot success!" 4 | FAILURE_MSG="boot failed!" 5 | 6 | LOG_FILE=$(mktemp) 7 | 8 | function cleanup { 9 | kill "$LOG_PID" 2>/dev/null 10 | rm -f "$LOG_FILE" 11 | } 12 | 13 | trap cleanup EXIT 14 | 15 | docker logs -f "obdiag_ob" >"$LOG_FILE" 2>&1 & 16 | 17 | LOG_PID=$! 18 | 19 | while true; do 20 | while IFS= read -r line; do 21 | echo "$line" 22 | if [[ "$line" == *"$SUCCESS_MSG"* || "$line" == *"$FAILURE_MSG"* ]]; then 23 | cleanup 24 | exit 0 25 | fi 26 | done < <(tail -f "$LOG_FILE") 27 | done --------------------------------------------------------------------------------