#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
完整的插件脚本,能够检测并报告所有类型的错误,按问题类型分组,并将连续时间戳合并为时间段
"""
import os
import Hubble.utils.basic.HiviewLogger as HiviewLogger
import re
import datetime
from datetime import datetime, timedelta
import json
class PluginClass:
def __init__(self):
self.logger = HiviewLogger.HiviewLogger().get_logger()
self.plugin_result = {
"conclusion": {
"level_one": "",
"level_two": "",
"reason_info": "",
"solution": "",
"weight_level": "",
},
"analysis_process": {
"show_order": ["1", "2"],
"detailed_process": {
"1": {"details": "", "CN": ""},
"2": {"details": "", "CN": ""}
}
},
"feature_data": {"": []}
}
def log_str_to_datetime(self, time_str):
try:
issue_time = datetime.strptime(time_str, '%m-%d %H:%M:%S.%f')
current_year = datetime.now().year
return issue_time.replace(year=current_year)
except ValueError:
try:
issue_time = datetime.strptime(time_str, '%m-%d %H:%M:%S')
current_year = datetime.now().year
return issue_time.replace(year=current_year)
except Exception:
return datetime.now()
def merge_time_ranges(self, events, max_gap_minutes=5):
"""修复的时间段合并函数"""
if not events:
return []
# 按时间戳排序
sorted_events = sorted(events, key=lambda x: self.log_str_to_datetime(x["timestamp"]))
merged_ranges = []
# 初始化第一个时间段
current_start = self.log_str_to_datetime(sorted_events[0]["timestamp"])
current_end = current_start
current_events = [sorted_events[0]] # 存储当前时间段的事件
for i in range(1, len(sorted_events)):
event = sorted_events[i]
event_time = self.log_str_to_datetime(event["timestamp"])
# 计算与前一个事件的时间间隔
gap = event_time - current_end
# 如果间隔小于阈值,则扩展当前时间段
if gap.total_seconds() <= max_gap_minutes * 60:
current_end = event_time
current_events.append(event)
else:
# 保存当前时间段
merged_ranges.append({
"start": current_start,
"end": current_end,
"count": len(current_events),
"events": current_events.copy() # 复制当前事件列表
})
# 开始新的时间段
current_start = event_time
current_end = event_time
current_events = [event]
# 添加最后一个时间段
merged_ranges.append({
"start": current_start,
"end": current_end,
"count": len(current_events),
"events": current_events
})
return merged_ranges
# 以下是各种问题检测函数(保持不变)
def memAvailable(self, hilog):
results = []
pattern = r'(?P<timestamp>\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*curBufKB=(?P<curBufKB>\d+)'
for line in hilog:
match = re.search(pattern, line)
if match:
timestamp = match.group("timestamp")
memAvailable_value = int(match.group('curBufKB'))
if memAvailable_value < 819200:
results.append({"type": "memAvailable", "timestamp": timestamp, "value": memAvailable_value})
return results
def am_kill(self, hilog):
results = []
pattern = r'(?P<timestamp>\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*KillOneProc kill_reason=LowMemoryKill.*procName=(?P<package>[a-zA-Z0-9._]+)'
for line in hilog:
match = re.search(pattern, line)
if match:
timestamp = match.group("timestamp")
kill_proc_name = match.group("package")
results.append({"type": "am_kill", "timestamp": timestamp, "proc_name": kill_proc_name})
return results
def temperature(self, hilog):
results = []
pattern = r'(?P<timestamp>\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*new temp: (?P<new_temp>\d+)'
for line in hilog:
match = re.search(pattern, line)
if match:
timestamp = match.group("timestamp")
temp_value = int(match.group("new_temp"))
if temp_value > 43:
results.append({"type": "temperature", "timestamp": timestamp, "value": temp_value})
return results
def storage(self, hilog):
results = []
pattern = r'(?P<timestamp>\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*roundSize=(?P<round_size>\d+),.*freeSize=(?P<free_size>\d+)'
for line in hilog:
match = re.search(pattern, line)
if match:
timestamp = match.group("timestamp")
round_size = int(match.group("round_size"))
free_size = int(match.group("free_size"))
if round_size > 0:
ratio = free_size / round_size
if ratio <= 0.15:
results.append({"type": "storage", "timestamp": timestamp, "ratio": ratio})
return results
def free_sec(self, hilog_kmsg):
results = []
pattern = r'(?P<timestamp>\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*free_sec=(?P<free_sec>\d+).*Free =(?P<free>\d+)MB'
for line in hilog_kmsg:
match = re.search(pattern, line)
if match:
timestamp = match.group("timestamp")
free_sec_value = int(match.group("free_sec"))
free_value = int(match.group("free"))
if free_value > 0:
ratio = 1 - (free_sec_value * 2) / free_value
if ratio > 0.8:
results.append({"type": "free_sec", "timestamp": timestamp, "ratio": ratio})
return results
def ps_slow(self, hilog):
results = []
pattern = r'(?P<timestamp>\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*CHR name=(PS_SLOW_EVENT), type'
for line in hilog:
match = re.search(pattern, line)
if match:
timestamp = match.group("timestamp")
results.append({"type": "ps_slow", "timestamp": timestamp})
return results
def power_low(self, hilog):
results = []
pattern = r'(?P<timestamp>\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*powermgr/BatteryInfo: capacity=(?P<capacity>\d+), voltage'
for line in hilog:
match = re.search(pattern, line)
if match:
timestamp = match.group("timestamp")
capacity_value = int(match.group("capacity"))
if capacity_value < 10:
results.append({"type": "power_low", "timestamp": timestamp, "value": capacity_value})
return results
def voltage(self, hilog):
results = []
pattern = r'(?P<timestamp>\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*powermgr/BatteryInfo: .*voltage=(?P<voltage>\d+), temperature'
for line in hilog:
match = re.search(pattern, line)
if match:
timestamp = match.group("timestamp")
voltage_value = int(match.group("voltage"))
if voltage_value < 3500000:
results.append({"type": "voltage", "timestamp": timestamp, "value": voltage_value})
return results
def cup_load(self, hilog):
results = []
pattern = r'(?P<timestamp>\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*cpuLoadPercent:(?P<cpuLoadPercent>\d+), thermalLevel'
for line in hilog:
match = re.search(pattern, line)
if match:
timestamp = match.group("timestamp")
try:
cpu_value = int(match.group("cpuLoadPercent"))
if cpu_value > 600000:
results.append({"type": "cup_load", "timestamp": timestamp, "value": cpu_value})
except ValueError:
continue
return results
def gpu_load(self, hilog):
results = []
pattern = r'(?P<timestamp>\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*Get GpuTotalUsed value is (?P<gpuUsed>\d+)'
for line in hilog:
match = re.search(pattern, line)
if match:
timestamp = match.group("timestamp")
try:
gpu_value = int(match.group("gpuUsed"))
if gpu_value > 600000:
results.append({"type": "gpu_load", "timestamp": timestamp, "value": gpu_value})
except ValueError:
continue
return results
def plugin_preprocess(self, info_dict=None):
self.logger.info("预处理函数执行中...")
task_list = []
download_list = info_dict["common_info"]["log_download_list"]
max_analysis_num = 1
if len(download_list) > max_analysis_num:
download_list = download_list[:max_analysis_num]
for download_item in download_list:
task_dict = {"download_addr": [], "task_params": {}}
task_dict["download_addr"] = download_item
task_list.append(task_dict)
return task_list
def run_plugin_single(self, uuid_log_path=None, log_path=None, param_dict=None):
self.logger.info("分析脚本执行中...uuid_log_path=[%s]", uuid_log_path)
error_mapping = {
"memAvailable": {"reason": "整机低内存(RAM)",
"solution": "1、清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面)2、长按电源键关机重启"},
"am_kill": {"reason": "应用因低内存被查杀",
"solution": "1、清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面)2、长按电源键关机重启"},
"temperature": {"reason": "整机温度过高", "solution": "建议参考手机/平板使用过程中设备发热相关知识排查"},
"storage": {"reason": "整机可用存储空间不足",
"solution": "建议参考'华为手机/平板内存占用多,提示内存不足如何处理?'知识中场景一:存储剩余空间不足排查方案处理。"},
"free_sec": {"reason": "整机碎片化过高",
"solution": "1、建议引导用户进入设置>存储,进行整机清理加速,清理不需要的垃圾文件、联网缓存及不常用的应用;2、建议用户尝试夜间熄屏充电,持续此操作2-3晚上清理碎片化,促进系统优化"},
"ps_slow": {"reason": "整机网络不佳",
"solution": "当前所处网络环境覆盖较弱或干扰较大,建议引导用户更换网络环境"},
"power_low": {"reason": "整机低电量", "solution": "建议在电量充足情况下使用"},
"voltage": {"reason": "整机低电压", "solution": "建议检查电池健康度并在电量充足情况下继续使用体验"},
"cup_load": {"reason": "整机CPU高负载",
"solution": "1、清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面);2、引导用户排查是否存在高速下载、 数据传输、多悬浮窗口使用等场景,以上高负载场景会导致设备卡顿,建议用户避免长时间使用上述场景;3、长按电源键关机重启;"},
"gpu_load": {"reason": "整机GPU高负载",
"solution": "1、清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面);2、引导用户排查是否存在高速下载、 数据传输、多悬浮窗口使用等场景,以上高负载场景会导致设备卡顿,建议用户避免长时间使用上述场景;3、长按电源键关机重启;"}
}
app_path = []
kmsg_path = []
for root, dirs, files in os.walk(uuid_log_path):
for file in files:
if "hilog." in file:
app_path.append(os.path.join(root, file))
if "hilog_kmsg" in file:
kmsg_path.append(os.path.join(root, file))
app_list = []
for app in app_path:
try:
with open(app, "r", encoding="utf-8", errors='ignore') as app_reader:
app_list += app_reader.readlines()
except Exception as e:
self.logger.error(f"读取日志文件失败: {e}")
kmsg_list = []
for kmsg in kmsg_path:
try:
with open(kmsg, "r", encoding="utf-8", errors='ignore') as kmsg_reader:
kmsg_list += kmsg_reader.readlines()
except Exception as e:
self.logger.error(f"读取kmsg日志失败: {e}")
detected_issues = {
"memAvailable": self.memAvailable(app_list),
"am_kill": self.am_kill(app_list),
"temperature": self.temperature(app_list),
"storage": self.storage(app_list),
"free_sec": self.free_sec(kmsg_list),
"ps_slow": self.ps_slow(app_list),
"power_low": self.power_low(app_list),
"voltage": self.voltage(app_list),
"cup_load": self.cup_load(app_list),
"gpu_load": self.gpu_load(app_list)
}
merged_issues = {}
for issue_type, issues in detected_issues.items():
if issues:
merged_issues[issue_type] = self.merge_time_ranges(issues)
report_by_type = {}
solutions = set()
for issue_type, time_ranges in merged_issues.items():
if not time_ranges:
continue
issue_report = []
for time_range in time_ranges:
start_time = time_range["start"].strftime("%m-%d %H:%M:%S")
end_time = time_range["end"].strftime("%m-%d %H:%M:%S")
if time_range["count"] == 1:
time_info = f"{start_time}"
else:
time_info = f"{start_time} 至 {end_time} ({time_range['count']}次)"
details = error_mapping[issue_type]["reason"]
if issue_type == "am_kill":
apps = list(set(event.get("proc_name", "未知应用") for event in time_range["events"]))
details += f" ({', '.join(apps)})"
elif issue_type in ["memAvailable", "temperature", "power_low", "voltage", "cup_load", "gpu_load"]:
values = [event.get("value", 0) for event in time_range["events"]]
min_val = min(values)
max_val = max(values)
avg_val = sum(values) / len(values)
unit = ""
if issue_type == "memAvailable":
unit = "KB"
elif issue_type == "temperature":
unit = "°C"
elif issue_type == "power_low":
unit = "%"
elif issue_type == "voltage":
unit = "mV"
details += f" (值范围: {min_val}-{max_val}{unit}, 平均: {avg_val:.1f}{unit})"
elif issue_type in ["storage", "free_sec"]:
ratios = [event.get("ratio", 0) for event in time_range["events"]]
avg_ratio = sum(ratios) / len(ratios) * 100
details += f" (平均: {avg_ratio:.1f}%)"
issue_report.append(f"{time_info}: {details}")
report_by_type[issue_type] = issue_report
solutions.add(error_mapping[issue_type]["solution"])
reason_info = []
if not report_by_type:
reason_info.append("当前整机各项指标未诊断出异常")
else:
for issue_type, issue_list in report_by_type.items():
reason_info.append(f"<b>{error_mapping[issue_type]['reason']}</b>")
reason_info.extend(issue_list)
reason_info.append("")
solution_str = "<br>".join(solutions) if solutions else"建议引导用户重新复现问题反馈日志"
self.plugin_result["conclusion"]["reason_info"] = "<br>".join(reason_info)
self.plugin_result["conclusion"]["solution"] = solution_str
self.plugin_result["conclusion"]["level_one"] = "稳定性问题"
self.plugin_result["conclusion"]["weight_level"] = "medium"
return self.plugin_result
def plugin_result_refinement(self, result):
return result
目前整机温度过高显示的是 09-15 12:53:28: 整机温度过高 (值范围: 44-69°C, 平均: 48.7°C),这个数值收集的有点问题,日志是这样的
16598: 04-17 18:33:07.767 636 60287 I C02D15/hiview/XPower: [task_148]#ThermalDaemon:[shell_frame] new temp: 36 old temp: 37
需要收集的值是[shell_frame] new temp:后面的数字,但是[shell_front] new temp:后面的也一块收集了,现在只收集[shell_frame] new temp:后面的数字,43度以上显示显示方式原封不动,48度以上的不要显示温度是多少,直接显示温度异常
顺便帮我加一下注释,这个是我最开始的脚本,根据这个注释帮我加上,然后帮我返回完整代码:
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
说明:此文件是插件脚本的入口Py文件模板,任何其他插件脚本要加入Hubble,需以此模板为基础进行扩展开发
注意事项:
1. 插件文件命名和所在文件夹相同,例如DemoPlugin下面的DemoPlugin.py
2. 在HubblePlatform.py的trigger_plugin函数中,要更新配置变量plugin_property_dict(以后会放到线上去)
3. 新引入的Python3模块需要告知Hubble开发团队的后台部署人员 WX601464,pip3 install NewPackage.py后才能正常运行,否则会导致后台程序错误!
4. 任何问题请联系?WX601464/w30016103
"""
import os
import Hubble.utils.basic.HiviewLogger as HiviewLogger
import re
import datetime
from datetime import datetime, timedelta
import json
class PluginClass():
"""
Hubble程序会自动检测PluginClass名称的类,进行加工
1. self.logger: Hubble日志打印模块变量,可打印详细日志信息,便于后期调试,推荐使用self.logger.info("xxx"),本地调试时请注释self.logger相关命令。
2. self.plugin_result: Hubble能识别到的输出接口,最小填写量"conclusion""reason_info",具体解释请见变量定义处
3. plugin_preprocess: 预处理Hubble传入的info_dict,包含程序运行的基本信息
4. run_plugin_single: 单日志分析函数,插件脚本的分析能力体现于此
5. plugin_result_refinement: 对于批量处理多日志情况,run_plugin_single的单日志处理结果会汇总成一个结果列表,
基于此列表,用户可以进行二次精细化汇总,例如统计平均值等
"""
def __init__(self):
"""
初始化函数
"""
self.logger = HiviewLogger.HiviewLogger().get_logger()
self.plugin_result = { # 填好对应项,会在Hubble单任务分析报告里看见结果展示
"conclusion": { # 分析结论(定界结论)展示
"level_one": "", # 一级定界
"level_two": "", # 二级定界
"reason_info": "", # 根因信息
"solution": "",
"weight_level": "" # 脚本权重,界面展示时作为排序依据,有效值范围[5,10]
},
"analysis_process": { # 分析结论(定界过程)展示,列表中每一个dict元素代表定界过程中的一步
"show_order": [ # 展示顺序, 定义"1", "2", ...步骤
"1", "2"
],
"detailed_process": { # 按show_order的步骤取出过程
"1": {
"details": "", # 第一步详细信息(做了哪些处理总结下,例如在applogcat中找到Hubble关键字)
"CN": "" # 步骤名称(例如找到applogcat文件)
},
"2": {
"details": "", # 第二步详细信息
"CN": "" # 步骤名称
}
}
},
"feature_data": { # 调用相似问题识别能力,需先填好此变量,可能有多个识别到的故障及其特征
"": [] # key值代表发现的故障类型,value值是list of string,由识别到的特征字符串组成
}
}
# 将'05-12 14:51:55'的时间格式转换成时间2024-05-12 14:51:55
def log_str_to_datetime(self, time_str):
issue_time = datetime.strptime(time_str, '%m-%d %H:%M:%S')
current_year = datetime.now().year
issue_time_with_current_year = issue_time.replace(year=current_year)
return issue_time_with_current_year
def extract_datetime(self, string):
pattern = r"_(\d{8})_(\d{4})"
match = re.search(pattern, string)
if match:
return match.group(1) + "_" + match.group(2)
else:
return None
# 1整机低内存
def memAvailable(self, hilog):
for line in hilog:
monsc_re = re.compile('curBufKB=(.*), targetBufKB').search(line)
if monsc_re:
monsc_tuples = monsc_re.groups()
memAvailable_vale = monsc_tuples[0]
if int(memAvailable_vale) < 819200:
return 1
return 0
# 2杀后台
def am_kill(self, hilog):
for line in hilog:
if ('KillOneProc kill_reason=LowMemoryKill' in line):
return 1
return 0
# 4整机温度过高
def temperature(self, hilog):
target_frame = ''
for line in hilog:
frame_re = re.compile('shell_frame] new temp: (.*) old temp').search(line)
if frame_re:
frame_tuples = frame_re.groups()
frame_value = frame_tuples[0]
if int(frame_value) > 43:
return 1
return 0
#5整机存储不足
def storage(self,hilog):
round_size = 0
free_size = 0
for line in hilog:
round_se = re.compile('roundSize=(.*),').search(line)
free_se = re.compile('freeSize=(.*)').search(line)
if round_se:
round_tuples_first = round_se.groups()
round_tuples = round_tuples_first[0].split(',')
round_value = int(round_tuples[0])
round_size = round_value
if free_se:
free_tuple = free_se.groups()
free_value = int(free_tuple[0])
free_size = free_value
if round_size and free_size:
tmp = free_size / round_size
if tmp <= 0.15:
return 1
return 0
# 6整机碎片化过高
def free_sec(self, hilog_kmsg):
for line in hilog_kmsg:
free_sec_re = re.compile('free_sec=(.*),reserved_sec').search(line)
free_re = re.compile(',Free =(.*)MB').search(line)
if free_sec_re and free_re:
free_sec_tuples = free_sec_re.groups()
free_sec_value = free_sec_tuples[0]
free_tuples = free_re.groups()
free_value = free_tuples[0]
res_value = 1 - (int(free_sec_value) * 2) / int(free_value)
if res_value > 0.8:
return 1
return 0
# 7网络不佳
def ps_slow(self, hilog):
num_chr = 0
for line in hilog:
slow_re = re.compile('CHR name=(.*), type').search(line)
if slow_re:
slow_tuples = slow_re.groups()
slow_value = slow_tuples[0]
if slow_value == 'PS_SLOW_EVENT':
num_chr += 1
if num_chr >= 5:
return 1
return 0
# 8电池电量过低
def power_low(self, hilog):
for line in hilog:
power_re = re.compile('powermgr/BatteryInfo: capacity=(.*), voltage').search(line)
if power_re:
power_tuples = power_re.groups()
power_value = power_tuples[0]
if int(power_value) < 10:
return 1
return 0
# 9电池电压过低
def voltage(self, hilog):
for line in hilog:
voltage_re = re.compile('powermgr/BatteryInfo: (.*), voltage=(.*), temperature').search(line)
if voltage_re:
voltage_tuples = voltage_re.groups()
voltage_value = voltage_tuples[1]
if int(voltage_value) < 3500000:
return 1
return 0
#10 整机CPU高负载
def cup_load(self, hilog):
for line in hilog:
cpu_re = re.compile('cpuLoadPercent:(.*), thermalLevel').search(line)
if cpu_re:
cpu_tuples = cpu_re.groups()
cpu_value = cpu_tuples[0]
if int(cpu_value) > 60:
return 1
return 0
#11 整机GPU高负载
def gpu_load(self, hilog):
for line in hilog:
gpu_re = re.compile('Get GpuTotalUsed value is (.*)').search(line)
if gpu_re:
gpu_tuples = gpu_re.groups()
gpu_value = gpu_tuples[0]
if int(gpu_value) > 600000:
return 1
return 0
def plugin_preprocess(self, info_dict=None):
"""
预处理Hubble传入的info_dict,包含程序运行的基本信息
此函数的基础操作是获取下载日志列表地址,形成task_list任务分析列表,供Hubble调用
"""
self.logger.info("这是预处理函数?")
task_list = []
download_list = info_dict["common_info"]["log_download_list"]
max_analysis_num = 1 # 最多处理几个日志
if len(download_list) > max_analysis_num:
download_list = download_list[:max_analysis_num]
for download_item in download_list:
task_dict = {"download_addr": [], "task_params": {}}
task_dict["download_addr"] = download_item
task_list.append(task_dict)
return task_list
def run_plugin_single(self, uuid_log_path=None, log_path=None, param_dict=None):
"""
主脚本分析逻辑,分析单日志中存在的故障,存入self.plugin_result
1. uuid_log_path: Hubble单任务的顶级分析路径,包含生成的基本信息文件、结果文件和递归解压的日志文件夹
2. log_path: 递归解压的顶级日志文件夹,一般是uuid_log_path的子文件
3. param_dict: 脚本程序所需的参数信息,例如日志来源、领域等,
---------------------------------------------------
参数示例
BetaClub的param_dict示例:
param_dict = {"common_info":{'happen_time': '20230225182000', 'betano': '2103539765',
'version': 'FCO-AL00 3.1.0.115(SP2C00E110R2P3log)', 'product': 'FCO-AL00',
'logsource': 'BetaClub', 'beta_info': {'quesDetail': '图库退出卡顿。',
'faultNameLv1': '性能', 'faultNameLv2': '整机操作各种卡',
'activityName': '【旗舰手机PDU】【关键】FCO-AL00 Beta测试', 'faultCode': '1008_1002'},
'happen_time_unixtime': 1677320400000, 'label': '动效卡顿', 'l_pkgs': ['com.huawei.photos']}}
APR的param_dict示例:
param_dict = {'common_info': {'version': 'MNA-AL00 3.1.0.125(SP1DEMC735E126R2P2)',
'eventid': '901001002','errorcode2': '', 'errorcode4': '', 'logsource': 'AresOcean',
'errorcode3': '', 'product': 'MNA-AL00', 'datetime_str': '20230327112414'}}
建议通过字典的get方法进行取值,如可通过下述语句获取用户描述和产品名称:
brief = param_dict.get("common_info", {}).get("beta_info", {}).get("quesDetail", "")
product = param_dict.get("common_info", {}).get("product", "")
"""
self.logger.info("这是测试插件!uuid_log_path=[%s], log_path=[%s], param_dict=[%s]",
uuid_log_path, log_path, param_dict) # 此句为DemoPlugin.py独有,可删除
# 此代码块为文件路径的遍历方法,以hiapplogcat-log为例
app_path = []
kmsg_path = []
for root, dirs, files in os.walk(uuid_log_path):
for file in files:
if "hilog." in file: # 可替换为其它日志类型
app_path.append(os.path.join(root, file))
if "hilog_kmsg" in file :
kmsg_path.append(os.path.join(root, file))
level_one = "稳定与流畅" # 临时二级定界字符串
conclusion = '详情请看根因分析'
# 打开app日志
app_list = []
for app in app_path:
with open(app, "r", encoding="utf-8", errors='ignore') as app_reader:
app_line = app_reader.readlines()
app_list += app_line
#打开kmgs日志
#梧桐加
memAvailable = self.memAvailable(app_list)
am_kill = self.am_kill(app_list)
temperature = self.temperature(app_list)
storage = self.storage(app_list)
free_sec = self.free_sec(app_list)
ps_slow = self.ps_slow(app_list)
power_low = self.power_low(app_list)
voltage = self.voltage(app_list)
cup_load = self.cup_load(app_list)
gpu_load = self.gpu_load(app_list)
memAvailable_result = ['整机低内存(RAM)', '1、清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面)2、长按电源键关机重启']
am_kill_result = ['因低内存被查杀', '1、清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面)2、长按电源键关机重启']
temperature_result = ['整机温度过高', '建议参考手机/平板使用过程中设备发热相关知识排查']
storage_result = ['整机可用存储空间不足', '建议参考“华为手机/平板内存占用多,提示内存不足如何处理? ”知识中场景一:存储剩余空间不足排查方案处理。']
free_sec_result = ['整机碎片化过高', '1、建议引导用户进入设置>存储,进行整机清理加速,清理不需要的垃圾文件、联网缓存及不常用的应用;2、建议用户尝试夜间熄屏充电,持续此操作2-3晚上清理碎片化,促进系统优化']
ps_slow_result = ['整机网络不佳', '当前所处网络环境覆盖较弱或干扰较大,建议引导用户更换网络环境']
power_low_result = ['整机低电量', '建议保证在电量充足情况下继续使用体验']
voltage_result = ['整机低电压', '建议检查电池健康度并在电量充足情况下继续使用体验']
cup_load_result = ['整机CPU高负载', '1、清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面);2、引导用户排查是否存在高速下载、 数据传输、多悬浮窗口使用等场景,以上高负载场景会导致设备卡顿,建议用户避免长时间使用上述场景;3、长按电源键关机重启;']
gpu_load_result = ['整机GPU高负载', '1、清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面);2、引导用户排查是否存在高速下载、 数据传输、多悬浮窗口使用等场景,以上高负载场景会导致设备卡顿,建议用户避免长时间使用上述场景;3、长按电源键关机重启;']
con_res = ''
solu_res = ''
if memAvailable:
con_res += memAvailable_result[0] + '<br>'
if memAvailable_result[1] not in solu_res:
solu_res += memAvailable_result[1] + '<br>'
if am_kill:
con_res += am_kill_result[0] + '<br>'
if am_kill_result[1] not in solu_res:
solu_res += am_kill_result[1] + '<br>'
if temperature:
con_res += temperature_result[0] + '<br>'
if temperature_result[1] not in solu_res:
solu_res += temperature_result[1] + '<br>'
if storage:
con_res += storage_result[0] + '<br>'
if storage_result[1] not in solu_res:
solu_res += storage_result[1] + '<br>'
if free_sec:
con_res += free_sec_result[0] + '<br>'
if free_sec_result[1] not in solu_res:
solu_res += free_sec_result[1] + '<br>'
if ps_slow:
con_res += ps_slow_result[0] + '<br>'
if ps_slow_result[1] not in solu_res:
solu_res += ps_slow_result[1] + '<br>'
if power_low:
con_res += power_low_result[0] + '<br>'
if power_low_result[1] not in solu_res:
solu_res += power_low_result[1] + '<br>'
if voltage:
con_res += voltage_result[0] + '<br>'
if voltage_result[1] not in solu_res:
solu_res += voltage_result[1] + '<br>'
if cup_load:
con_res += cup_load_result[0] + '<br>'
if cup_load_result[1] not in solu_res:
solu_res += cup_load_result[1] + '<br>'
if gpu_load:
con_res += gpu_load_result[0] + '<br>'
if gpu_load_result[1] not in solu_res:
solu_res += gpu_load_result[1] + '<>'
if not con_res:
self.plugin_result["conclusion"]['level_one'] = level_one # 一级定界,反映插件功能
self.plugin_result["conclusion"]['level_two'] = '整机卡顿' # 二级定界,根据插件得到的不同结论进行调整
self.plugin_result["conclusion"]['reason_info'] = '当前整机各项指标未诊断出异常' # 二级定界,根据插件得到的不同结论进行调整
self.plugin_result["conclusion"]['solution'] = '建议引导用户重新复现问题反馈日志' # 二级定界,根据插件得到的不同结论进行调整
return self.plugin_result # 如果想直接利用Hubble前端分析报告的展示项,请按定义填写好self.plugin_result变量
else:
self.plugin_result["conclusion"]['level_one'] = level_one # 一级定界,反映插件功能
self.plugin_result["conclusion"]['level_two'] = '整机卡顿' # 二级定界,根据插件得到的不同结论进行调整
self.plugin_result["conclusion"]['reason_info'] = con_res # 二级定界,根据插件得到的不同结论进行调整
self.plugin_result["conclusion"]['solution'] = solu_res # 二级定界,根据插件得到的不同结论进行调整
self.logger.info(self.plugin_result)
return self.plugin_result # 如果想直接利用Hubble前端分析报告的展示项,请按定义填写好self.plugin_result变量
def plugin_result_refinement(self, result_list=None):
"""
二次精细化加工产生的此脚本分析结果列表?
result_list中是self.plugin_result元素的列表集合
也即result_list = [self.plugin_result_1, self.plugin_result_2,...]
"""
self.logger.info("这是分析结果精加工函数")
return result_list # 如果是此分析脚本定制化的分析结果数据结构,需要和Hubble对齐前端取数逻辑才能将分析结论显示在分析报告内