| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| # This script tool is for generate table-level rocksdb perf counters based on replica-level perf counter. |
| # Since many rocksdb perf counters need to be aggregated into total value, the code is usually repeated, |
| # for example, `put_qps` and `get_qps`, this tool generates these codes. you need: |
| # ``` |
| #python3 ./collector_table_counter_gen.py put_qps, get_qps |
| # ``` |
| # |
| # Notice: The tool is only for generating `total-aggregate` type code. If you want to get `average-aggregate` |
| # or other type code, please modify the generated code |
| |
| import os |
| import sys |
| |
| root = os.path.split(os.path.realpath(__file__))[0].split("scripts")[0] |
| |
| info_collector_header_path = root + "/src/server/info_collector.h" |
| info_collector_cpp_path = root + "./src/server/info_collector.cpp" |
| command_helper_header_path = root + "./src/shell/command_helper.h" |
| |
| |
| class Appender(object): |
| def __init__(self, seek_line, new_line): |
| self.seek_line = seek_line |
| self.new_line = new_line |
| self.seek_match = False |
| |
| def __str__(self): |
| return "%s=>%s in %d\n" % ( |
| self.seek_line, self.new_line, self.seek_pos) |
| |
| |
| def fatal_error(error): |
| print("ERROR: " + error) |
| sys.exit(1) |
| |
| |
| def append_line(filePath, appends): |
| if not os.path.exists(filePath): |
| fatal_error("no such file: %s" % filePath) |
| |
| lines = [] |
| with open(filePath, 'r+') as fp: |
| for line in fp.readlines(): |
| lines.append(line) |
| for append in appends: |
| if append.new_line in line: |
| fatal_error( |
| "has added the counter for table, new_line = %s" % |
| append.new_line) |
| if append.seek_match: |
| continue |
| if append.seek_line in line: |
| lines.append(append.new_line) |
| append.seek_match = True |
| |
| for append in appends: |
| if not append.seek_match: |
| fatal_error( |
| "can't match the seek_line(%s), please check the file" % |
| append.seek_line) |
| with open(filePath, 'w+') as fp: |
| fp.write("".join(lines)) |
| |
| |
| def generate_code_in_info_collector_header(replica_counter): |
| table_counter = replica_counter.replace(".", "_") |
| appends = [ |
| Appender( |
| "write_bytes->set(row_stats.get_total_write_bytes());", |
| "%s->set(row_stats.%s);" % |
| (table_counter, table_counter)), |
| Appender( |
| "::dsn::perf_counter_wrapper write_bytes;", |
| "::dsn::perf_counter_wrapper %s;" % |
| table_counter)] |
| append_line(info_collector_header_path, appends) |
| |
| |
| def generate_code_in_info_collector_cpp(replica_counter): |
| table_counter = replica_counter.replace(".", "_") |
| appends = [Appender( |
| "INIT_COUNTER(write_bytes);", |
| "INIT_COUNTER(%s);" % |
| table_counter)] |
| append_line(info_collector_cpp_path, appends) |
| |
| |
| def generate_code_in_command_helper_header(replica_counter): |
| table_counter = replica_counter.replace(".", "_") |
| appends = [Appender( |
| "check_and_mutate_bytes += row.check_and_mutate_bytes;", |
| "%s += row.%s;" % (table_counter, table_counter)), Appender( |
| "double check_and_mutate_bytes = 0;", |
| "double %s = 0;" % |
| table_counter), |
| Appender( |
| "row.check_and_mutate_bytes += value;", |
| " else if (counter_name == \"%s\") row.%s += value;" % |
| (replica_counter, table_counter))] |
| append_line(command_helper_header_path, appends) |
| |
| |
| # python3 ./collector_table_counter_gen.py counter1,counter2 |
| # please use `./scripts/format_files.sh` to format after generate code |
| if __name__ == '__main__': |
| if len(sys.argv) != 2: |
| print("python3 ./collector_table_counter_gen.py {counter1,counter2..}") |
| |
| counter_list = sys.argv[1].split(",") |
| for counter in counter_list: |
| generate_code_in_info_collector_header(counter) |
| generate_code_in_info_collector_cpp(counter) |
| generate_code_in_command_helper_header(counter) |