import time import taos import csv import numpy as np import random import os import requests import json import sys """ 需要第三方库: taos,requests,numpy 当前机器已经启动taosd服务 使用方法见底部示例 """ class Ding: """ 发送消息到钉钉, urls: 钉钉群的token组成的list,可以发多个钉钉群,需要提前加白名单或其他放行策略 at_mobiles: 需要@的人的手机号组成的list msg: 要发送的str """ def __init__(self, url_list, at_mobiles): self.urls = url_list self.at_mobiles = at_mobiles def send_message(self, msg): data1 = { "msgtype": "text", "text": { "content": msg }, "at": { "atMobiles": self.at_mobiles, "isAtAll": False } } header = {'Content-Type': 'application/json; charset=utf-8'} for url in self.urls: requests.post(url=url, data=json.dumps(data1), headers=header) class TDConn: def __init__(self, config:dict): self.host = config['host'] self.user = config['user'] self.password = config['password'] self.config = config['config'] self.conn = None self.cursor = None def connect(self): conn = taos.connect(host=self.host, user=self.user, password=self.password, config=self.config) cursor = conn.cursor() self.conn = conn self.cursor = cursor print('connect ...') return self.cursor def close(self): self.cursor.close() self.conn.close() print('close ... ') class Tool: """ 可能有用 """ @staticmethod def str_gen(num): return ''.join(random.sample('abcdefghijklmnopqrstuvwxyz', num)) @staticmethod def float_gen(n, m): return random.uniform(n, m) @staticmethod def int_gen(n, m): return random.randint(n, m) class Demo: def __init__(self, engine): self.engine = engine['engine'](engine['config']) self.cursor = self.engine.connect() def date_gen(self, db, number_per_table, type_of_cols, num_of_cols_per_record, num_of_tables): """ :目前都是 taosdemo 的参数 :return: """ sql = 'yes | sudo taosdemo -d {db} -n {number_per_table} -b {type_of_cols} -l {num_of_cols_per_record} ' \ '-t {num_of_tables}'.format(db=db, number_per_table=number_per_table, type_of_cols=type_of_cols, num_of_cols_per_record=num_of_cols_per_record, num_of_tables=num_of_tables) os.system(sql) print('insert data completed') # def main(self, db, circle, csv_name, case_func, result_csv, nums, ding_flag): def main(self, every_num_per_table, result_csv, all_result_csv, values): db = values['db_name'] number_per_table = every_num_per_table type_of_cols = values['col_type'] num_of_cols_per_record = values['col_num'] num_of_tables = values['table_num'] self.date_gen(db=db, number_per_table=number_per_table, type_of_cols=type_of_cols, num_of_cols_per_record=num_of_cols_per_record, num_of_tables=num_of_tables) circle = values['circle'] # print(every_num_per_table, result_csv, values) csv_name = result_csv case_func = values['sql_func'] nums = num_of_tables * number_per_table ding_flag = values['ding_flag'] _data = [] f = open(csv_name,'w',encoding='utf-8') f1 = open(all_result_csv,'a',encoding='utf-8') csv_writer = csv.writer(f) csv_writer1 = csv.writer(f1) csv_writer.writerow(["number", "elapse", 'sql']) self.cursor.execute('use {db};'.format(db=db)) for i in range(circle): self.cursor.execute('reset query cache;') sql = case_func() start = time.time() self.cursor.execute(sql) self.cursor.fetchall() end = time.time() _data.append(end-start) elapse = '%.4f' %(end -start) print(sql, i, elapse, '\n') csv_writer.writerow([i+1, elapse, sql]) # time.sleep(1) _list = [nums, np.mean(_data)] _str = '总数据: %s 条 , table数: %s , 每个table数据数: %s , 数据类型: %s \n' % \ (nums, num_of_tables, number_per_table, type_of_cols) # print('avg : ', np.mean(_data), '\n') _str += '平均值 : %.4f 秒\n' % np.mean(_data) for each in (50, 80, 90, 95): _list.append(np.percentile(_data,each)) _str += ' %d 分位数 : %.4f 秒\n' % (each , np.percentile(_data,each)) print(_str) if ding_flag: ding = Ding(values['ding_config']['urls'], values['ding_config']['at_mobiles']) ding.send_message(_str) csv_writer1.writerow(_list) f.close() f1.close() self.engine.close() def run(engine, test_cases: dict, result_dir): for each_case, values in test_cases.items(): for every_num_per_table in values['number_per_table']: result_csv = result_dir + '{case}_table{table_num}_{number_per_table}.csv'.\ format(case=each_case, table_num=values['table_num'], number_per_table=every_num_per_table) all_result_csv = result_dir + '{case_all}_result.csv'.format(case_all=each_case) d = Demo(engine) # print(each_case, result_csv) d.main(every_num_per_table, result_csv, all_result_csv, values) if __name__ == '__main__': """ 测试用例在test_cases中添加。 result_dir: 报告生成目录,会生成每次测试结果,和具体某一用例的统计结果.需注意目录权限需要执行用户可写。 case1、case2 : 具体用例名称 engine: 数据库引擎,目前只有taosd。使用时需开启taosd服务。 table_num: 造数据时的table数目 circle: 循环测试次数,求平均值 number_per_table:需要传list,多个数值代表会按照list内的数值逐个测试 col_num:table col的数目 col_type: 表中数据类型 db_name: 造数据的db名,默认用test sql_func: 当前测试的sql方法,需要自己定义 ding_flag: 如果需要钉钉发送数据,flag设置真值, ding_config: 如ding_flag 设置为真值,此项才有意义。ding_flag为假时此项可以为空。urls传入一list,内容为要发送的群的token, 需提前设置白名单,at_mobiles传入一list,内容为在群内需要@的人的手机号 """ engine_dict = { 'taosd': {'engine': TDConn, 'config': {'host': '127.0.0.1', 'user': 'root', 'password': 'taosdata', 'config':'/etc/taos'}} } def case1(): return 'select * from meters where f1 = {n};'.format(n=random.randint(1,30)) def case2(): return 'select * from meters where f1 = %.4f;' %random.uniform(1,30) result_dir = '/usr/local/demo/benchmarktestdata/' test_cases = { 'case1': {'engine':'taosd', 'table_num': 10, 'circle': 100, 'number_per_table':[10, 100], 'col_num': 5, 'col_type': 'INT', 'db_name': 'test', 'sql_func': case1, 'ding_flag': True, 'ding_config': {'urls': [r'https://oapi.dingtalk.com/robot/send?access_token=xxxxxxx0cd93'], 'at_mobiles':[17000000000,],}}, 'case2': {'engine':'taosd', 'table_num': 10, 'circle': 50, 'number_per_table':[10, 100], 'col_num': 5, 'col_type': 'FLOAT', 'db_name': 'test', 'sql_func': case2, 'ding_flag': False, 'ding_config': None } } run(engine_dict['taosd'], test_cases, result_dir)