enh: rename

This commit is contained in:
jiajingbin 2025-01-23 13:45:56 +08:00
parent 7c083234f7
commit 4504f5a6fd
4 changed files with 369 additions and 369 deletions

View File

@ -1,26 +1,45 @@
from datetime import date from datetime import date
from datetime import timedelta from datetime import timedelta
import os import os
import json
import re import re
import requests import requests
import subprocess
from dotenv import load_dotenv from dotenv import load_dotenv
# load .env # load .env
# You should have a .env file in the same directory as this script
# You can exec: cp .env.example .env
load_dotenv() load_dotenv()
# define version # define version
version = "3.3.*" version = "3.3.2.*"
version_pattern_str = version.replace('.', r'\.').replace('*', r'\d+')
version_pattern = re.compile(rf'^{version_pattern_str}$')
version_stack_list = list()
# define ip
ip = os.getenv("EXCLUDE_IP") ip = os.getenv("EXCLUDE_IP")
server_ip = os.getenv("SERVER_IP") server_ip = os.getenv("SERVER_IP")
http_serv_ip = os.getenv("HTTP_SERV_IP")
http_serv_port = os.getenv("HTTP_SERV_PORT")
owner = os.getenv("OWNER") owner = os.getenv("OWNER")
# feishu-msg url # feishu-msg url
feishu_msg_url = os.getenv("FEISHU_MSG_URL") feishu_msg_url = os.getenv("FEISHU_MSG_URL")
# get today
today = date.today() today = date.today()
#today = date(2023,8,7)
# Define the file and parameters
path="/data/telemetry/crash-report/" path="/data/telemetry/crash-report/"
trace_report_path = path + "trace_report"
os.makedirs(path, exist_ok=True)
os.makedirs(trace_report_path, exist_ok=True)
assert_script_path = path + "filter_assert.sh"
nassert_script_path = path + "filter_nassert.sh"
# get files for the past 7 days # get files for the past 7 days
def get_files(): def get_files():
@ -28,30 +47,161 @@ def get_files():
for i in range(1,8): for i in range(1,8):
#print ((today - timedelta(days=i)).strftime("%Y%m%d")) #print ((today - timedelta(days=i)).strftime("%Y%m%d"))
files = files + path + (today - timedelta(days=i)).strftime("%Y%m%d") + ".txt " files = files + path + (today - timedelta(days=i)).strftime("%Y%m%d") + ".txt "
return files.strip().split(" ")
return files # Define the AWK script as a string with proper escaping
def get_res(file_path):
# Execute the script
command = ['bash', file_path, version, ip] + get_files()
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
# for none-taosAssertDebug # Capture the output and errors
filter1_cmd = '''grep '"version":"%s"' %s \ output, errors = process.communicate()
| grep "taosd(" \
| awk -F "stackInfo" '{print $2}' \
| grep -v "taosAssertDebug" \
| grep -v %s \
| awk -F "taosd" '{print $3}' \
| cut -d")" -f 1 \
| cut -d"(" -f 2 \
| sort | uniq -c ''' % (version, get_files(), ip)
# for taosAssertDebug # Check for errors
filter2_cmd = '''grep '"version":"%s"' %s \ if process.returncode != 0:
| grep "taosd(" \ return errors
| awk -F "stackInfo" '{print $2}' \ else:
| grep "taosAssertDebug" \ return output.rstrip()
| grep -v %s \
| awk -F "taosd" '{print $3}' \ def get_sum(output):
| cut -d")" -f 1 \ # Split the output into lines
| cut -d"(" -f 2 \ lines = output.strip().split('\n')
| sort | uniq -c ''' % (version, get_files(), ip)
# Initialize the sum
total_sum = 0
# Iterate over each line
for line in lines:
# Split each line by space to separate the columns
parts = line.split()
# The first part of the line is the number, convert it to integer
if parts: # Check if there are any elements in the parts list
number = int(parts[0])
total_sum += number
return total_sum
def convert_html(data):
# convert data to json
start_time = get_files()[6].split("/")[-1].split(".")[0]
end_time = get_files()[0].split("/")[-1].split(".")[0]
html_report_file = f'{start_time}_{end_time}.html'
json_data = json.dumps(data)
# Create HTML content
html_content = f'''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stack Trace Report</title>
<style>
body {{
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f0f0f5;
}}
h1 {{
color: #2c3e50;
text-align: center;
}}
table {{
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}}
th, td {{
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}}
th {{
background-color: #3498db;
color: white;
}}
tr:nth-child(even) {{
background-color: #ecf0f1;
}}
tr:hover {{
background-color: #d1e7fd;
}}
pre {{
background-color: #f7f7f7;
padding: 10px;
border: 1px solid #ddd;
overflow-x: auto;
white-space: pre-wrap;
border-radius: 5px;
}}
</style>
</head>
<body>
<h1>Stack Trace Report From {start_time} To {end_time} </h1>
<table>
<thead>
<tr>
<th>Key Stack Info</th>
<th>Versions</th>
<th>Num Of Crashes</th>
<th>Full Stack Info</th>
</tr>
</thead>
<tbody id="report">
</tbody>
</table>
<script>
const data = {json_data};
const reportBody = document.getElementById('report');
data.forEach(entry => {{
const row = document.createElement('tr');
row.innerHTML = `
<td>${{entry.key_stack_info}}</td>
<td>${{entry.version_list.join('<br>')}}</td>
<td>${{entry.count}}</td>
<td><pre>${{entry.full_stack_info}}</pre></td>
`;
reportBody.appendChild(row);
}});
</script>
</body>
</html>
'''
# Write the HTML content to a file
with open(f'{trace_report_path}/{html_report_file}', 'w') as f:
f.write(html_content)
return html_report_file
def get_version_stack_list(res):
for line in res.strip().split('\n'):
version_list = list()
version_stack_dict = dict()
count = line.split()[0]
key_stack_info = line.split()[1]
for file in get_files():
with open(file, 'r') as infile:
for line in infile:
line = line.strip()
data = json.loads(line)
# print(line)
if ip not in line and version_pattern.search(data["version"]) and key_stack_info in line:
if data["version"] not in version_list:
version_list.append(data["version"])
full_stack_info = data["stackInfo"]
version_stack_dict["key_stack_info"] = key_stack_info
version_stack_dict["full_stack_info"] = full_stack_info
version_stack_dict["version_list"] = version_list
version_stack_dict["count"] = count
# print(version_stack_dict)
version_stack_list.append(version_stack_dict)
return version_stack_list
# get msg info # get msg info
def get_msg(text): def get_msg(text):
@ -78,51 +228,81 @@ def send_msg(json):
'Content-Type': 'application/json' 'Content-Type': 'application/json'
} }
req = requests.post(url=group_url, headers=headers, json=json) req = requests.post(url=feishu_msg_url, headers=headers, json=json)
inf = req.json() inf = req.json()
if "StatusCode" in inf and inf["StatusCode"] == 0: if "StatusCode" in inf and inf["StatusCode"] == 0:
pass pass
else: else:
print(inf) print(inf)
# exec cmd and return res
def get_output(cmd): def format_results(results):
text = os.popen(cmd) # Split the results into lines
lines = text.read() lines = results.strip().split('\n')
text.close()
return lines # Parse lines into a list of tuples (number, rest_of_line)
parsed_lines = []
for line in lines:
parts = line.split(maxsplit=1)
if len(parts) == 2:
number = int(parts[0]) # Convert the number part to an integer
parsed_lines.append((number, parts[1]))
# Sort the parsed lines by the first element (number) in descending order
parsed_lines.sort(reverse=True, key=lambda x: x[0])
# Determine the maximum width of the first column for alignment
# max_width = max(len(str(item[0])) for item in parsed_lines)
if parsed_lines:
max_width = max(len(str(item[0])) for item in parsed_lines)
else:
max_width = 0
# Format each line to align the numbers and function names with indentation
formatted_lines = []
for number, text in parsed_lines:
formatted_line = f" {str(number).rjust(max_width)} {text}"
formatted_lines.append(formatted_line)
# Join the formatted lines into a single string
return '\n'.join(formatted_lines)
# # send report to feishu
def send_report(res, sum, html_report_file):
content = f'''
version: v{version}
from: {get_files()[6].split("/")[-1].split(".")[0]}
to: {get_files()[0].split("/")[-1].split(".")[0]}
ip: {server_ip}
owner: {owner}
result: \n{format_results(res)}\n
total crashes: {sum}\n
details: http://{http_serv_ip}:{http_serv_port}/{html_report_file}
'''
print(get_msg(content))
send_msg(get_msg(content))
# print(content)
# for none-taosAssertDebug
nassert_res = get_res(nassert_script_path)
# print(nassert_res)
# for taosAssertDebug
assert_res = get_res(assert_script_path)
# print(assert_res)
# combine the results
res = nassert_res + assert_res
# get version stack list
version_stack_list = get_version_stack_list(res) if len(res) > 0 else list()
# convert to html
html_report_file = convert_html(version_stack_list)
# get sum # get sum
def get_count(output): sum = get_sum(res)
res = re.findall(" \d+ ", output)
sum1 = 0
for r in res:
sum1 = sum1 + int(r.strip())
return sum1
# print total crash count # send report
def print_result(): send_report(res, sum, html_report_file)
#print(f"Files for statistics: {get_files()}\n")
sum1 = get_count(get_output(filter1_cmd))
sum2 = get_count(get_output(filter2_cmd))
total = sum1 + sum2
#print(f"total crashes: {total}")
return total
# send report to feishu
def send_report():
content = f'''
test scope: Telemetry Statistics
owner: {owner}
ip: {server_ip}
from: {get_files().split(" ")[6].split("/")[4].split(".")[0]}
to: {get_files().split(" ")[0].split("/")[4].split(".")[0]}
filter1 result: {get_output(filter1_cmd)}
filter2 result: {get_output(filter2_cmd)}
total crashes: {print_result()}
'''
#send_msg(get_msg(content))
print(content)
print_result()
send_report()

View File

@ -0,0 +1,128 @@
from datetime import date
from datetime import timedelta
import os
import re
import requests
from dotenv import load_dotenv
# load .env
load_dotenv()
# define version
version = "3.3.*"
ip = os.getenv("EXCLUDE_IP")
server_ip = os.getenv("SERVER_IP")
owner = os.getenv("OWNER")
# feishu-msg url
feishu_msg_url = os.getenv("FEISHU_MSG_URL")
today = date.today()
#today = date(2023,8,7)
path="/data/telemetry/crash-report/"
# get files for the past 7 days
def get_files():
files = ""
for i in range(1,8):
#print ((today - timedelta(days=i)).strftime("%Y%m%d"))
files = files + path + (today - timedelta(days=i)).strftime("%Y%m%d") + ".txt "
return files
# for none-taosAssertDebug
filter1_cmd = '''grep '"version":"%s"' %s \
| grep "taosd(" \
| awk -F "stackInfo" '{print $2}' \
| grep -v "taosAssertDebug" \
| grep -v %s \
| awk -F "taosd" '{print $3}' \
| cut -d")" -f 1 \
| cut -d"(" -f 2 \
| sort | uniq -c ''' % (version, get_files(), ip)
# for taosAssertDebug
filter2_cmd = '''grep '"version":"%s"' %s \
| grep "taosd(" \
| awk -F "stackInfo" '{print $2}' \
| grep "taosAssertDebug" \
| grep -v %s \
| awk -F "taosd" '{print $3}' \
| cut -d")" -f 1 \
| cut -d"(" -f 2 \
| sort | uniq -c ''' % (version, get_files(), ip)
# get msg info
def get_msg(text):
return {
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": "Telemetry Statistics",
"content": [
[{
"tag": "text",
"text": text
}
]]
}
}
}
}
# post msg
def send_msg(json):
headers = {
'Content-Type': 'application/json'
}
req = requests.post(url=group_url, headers=headers, json=json)
inf = req.json()
if "StatusCode" in inf and inf["StatusCode"] == 0:
pass
else:
print(inf)
# exec cmd and return res
def get_output(cmd):
text = os.popen(cmd)
lines = text.read()
text.close()
return lines
# get sum
def get_count(output):
res = re.findall(" \d+ ", output)
sum1 = 0
for r in res:
sum1 = sum1 + int(r.strip())
return sum1
# print total crash count
def print_result():
#print(f"Files for statistics: {get_files()}\n")
sum1 = get_count(get_output(filter1_cmd))
sum2 = get_count(get_output(filter2_cmd))
total = sum1 + sum2
#print(f"total crashes: {total}")
return total
# send report to feishu
def send_report():
content = f'''
test scope: Telemetry Statistics
owner: {owner}
ip: {server_ip}
from: {get_files().split(" ")[6].split("/")[4].split(".")[0]}
to: {get_files().split(" ")[0].split("/")[4].split(".")[0]}
filter1 result: {get_output(filter1_cmd)}
filter2 result: {get_output(filter2_cmd)}
total crashes: {print_result()}
'''
#send_msg(get_msg(content))
print(content)
print_result()
send_report()

View File

@ -1,308 +0,0 @@
from datetime import date
from datetime import timedelta
import os
import json
import re
import requests
import subprocess
from dotenv import load_dotenv
# load .env
# You should have a .env file in the same directory as this script
# You can exec: cp .env.example .env
load_dotenv()
# define version
version = "3.3.2.*"
version_pattern_str = version.replace('.', r'\.').replace('*', r'\d+')
version_pattern = re.compile(rf'^{version_pattern_str}$')
version_stack_list = list()
# define ip
ip = os.getenv("EXCLUDE_IP")
server_ip = os.getenv("SERVER_IP")
http_serv_ip = os.getenv("HTTP_SERV_IP")
http_serv_port = os.getenv("HTTP_SERV_PORT")
owner = os.getenv("OWNER")
# feishu-msg url
feishu_msg_url = os.getenv("FEISHU_MSG_URL")
# get today
today = date.today()
# Define the file and parameters
path="/data/telemetry/crash-report/"
trace_report_path = path + "trace_report"
os.makedirs(path, exist_ok=True)
os.makedirs(trace_report_path, exist_ok=True)
assert_script_path = path + "filter_assert.sh"
nassert_script_path = path + "filter_nassert.sh"
# get files for the past 7 days
def get_files():
files = ""
for i in range(1,8):
#print ((today - timedelta(days=i)).strftime("%Y%m%d"))
files = files + path + (today - timedelta(days=i)).strftime("%Y%m%d") + ".txt "
return files.strip().split(" ")
# Define the AWK script as a string with proper escaping
def get_res(file_path):
# Execute the script
command = ['bash', file_path, version, ip] + get_files()
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
# Capture the output and errors
output, errors = process.communicate()
# Check for errors
if process.returncode != 0:
return errors
else:
return output.rstrip()
def get_sum(output):
# Split the output into lines
lines = output.strip().split('\n')
# Initialize the sum
total_sum = 0
# Iterate over each line
for line in lines:
# Split each line by space to separate the columns
parts = line.split()
# The first part of the line is the number, convert it to integer
if parts: # Check if there are any elements in the parts list
number = int(parts[0])
total_sum += number
return total_sum
def convert_html(data):
# convert data to json
start_time = get_files()[6].split("/")[-1].split(".")[0]
end_time = get_files()[0].split("/")[-1].split(".")[0]
html_report_file = f'{start_time}_{end_time}.html'
json_data = json.dumps(data)
# Create HTML content
html_content = f'''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stack Trace Report</title>
<style>
body {{
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f0f0f5;
}}
h1 {{
color: #2c3e50;
text-align: center;
}}
table {{
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}}
th, td {{
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}}
th {{
background-color: #3498db;
color: white;
}}
tr:nth-child(even) {{
background-color: #ecf0f1;
}}
tr:hover {{
background-color: #d1e7fd;
}}
pre {{
background-color: #f7f7f7;
padding: 10px;
border: 1px solid #ddd;
overflow-x: auto;
white-space: pre-wrap;
border-radius: 5px;
}}
</style>
</head>
<body>
<h1>Stack Trace Report From {start_time} To {end_time} </h1>
<table>
<thead>
<tr>
<th>Key Stack Info</th>
<th>Versions</th>
<th>Num Of Crashes</th>
<th>Full Stack Info</th>
</tr>
</thead>
<tbody id="report">
</tbody>
</table>
<script>
const data = {json_data};
const reportBody = document.getElementById('report');
data.forEach(entry => {{
const row = document.createElement('tr');
row.innerHTML = `
<td>${{entry.key_stack_info}}</td>
<td>${{entry.version_list.join('<br>')}}</td>
<td>${{entry.count}}</td>
<td><pre>${{entry.full_stack_info}}</pre></td>
`;
reportBody.appendChild(row);
}});
</script>
</body>
</html>
'''
# Write the HTML content to a file
with open(f'{trace_report_path}/{html_report_file}', 'w') as f:
f.write(html_content)
return html_report_file
def get_version_stack_list(res):
for line in res.strip().split('\n'):
version_list = list()
version_stack_dict = dict()
count = line.split()[0]
key_stack_info = line.split()[1]
for file in get_files():
with open(file, 'r') as infile:
for line in infile:
line = line.strip()
data = json.loads(line)
# print(line)
if ip not in line and version_pattern.search(data["version"]) and key_stack_info in line:
if data["version"] not in version_list:
version_list.append(data["version"])
full_stack_info = data["stackInfo"]
version_stack_dict["key_stack_info"] = key_stack_info
version_stack_dict["full_stack_info"] = full_stack_info
version_stack_dict["version_list"] = version_list
version_stack_dict["count"] = count
# print(version_stack_dict)
version_stack_list.append(version_stack_dict)
return version_stack_list
# get msg info
def get_msg(text):
return {
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": "Telemetry Statistics",
"content": [
[{
"tag": "text",
"text": text
}
]]
}
}
}
}
# post msg
def send_msg(json):
headers = {
'Content-Type': 'application/json'
}
req = requests.post(url=feishu_msg_url, headers=headers, json=json)
inf = req.json()
if "StatusCode" in inf and inf["StatusCode"] == 0:
pass
else:
print(inf)
def format_results(results):
# Split the results into lines
lines = results.strip().split('\n')
# Parse lines into a list of tuples (number, rest_of_line)
parsed_lines = []
for line in lines:
parts = line.split(maxsplit=1)
if len(parts) == 2:
number = int(parts[0]) # Convert the number part to an integer
parsed_lines.append((number, parts[1]))
# Sort the parsed lines by the first element (number) in descending order
parsed_lines.sort(reverse=True, key=lambda x: x[0])
# Determine the maximum width of the first column for alignment
# max_width = max(len(str(item[0])) for item in parsed_lines)
if parsed_lines:
max_width = max(len(str(item[0])) for item in parsed_lines)
else:
max_width = 0
# Format each line to align the numbers and function names with indentation
formatted_lines = []
for number, text in parsed_lines:
formatted_line = f" {str(number).rjust(max_width)} {text}"
formatted_lines.append(formatted_line)
# Join the formatted lines into a single string
return '\n'.join(formatted_lines)
# # send report to feishu
def send_report(res, sum, html_report_file):
content = f'''
version: v{version}
from: {get_files()[6].split("/")[-1].split(".")[0]}
to: {get_files()[0].split("/")[-1].split(".")[0]}
ip: {server_ip}
owner: {owner}
result: \n{format_results(res)}\n
total crashes: {sum}\n
details: http://{http_serv_ip}:{http_serv_port}/{html_report_file}
'''
print(get_msg(content))
send_msg(get_msg(content))
# print(content)
# for none-taosAssertDebug
nassert_res = get_res(nassert_script_path)
# print(nassert_res)
# for taosAssertDebug
assert_res = get_res(assert_script_path)
# print(assert_res)
# combine the results
res = nassert_res + assert_res
# get version stack list
version_stack_list = get_version_stack_list(res) if len(res) > 0 else list()
# convert to html
html_report_file = convert_html(version_stack_list)
# get sum
sum = get_sum(res)
# send report
send_report(res, sum, html_report_file)