PowerApps - 尝试一下在PowerApps中打印数据

1.简单介绍

在应用程序中开发中,调用打印机进行打印是比较常见的功能,如果是.NET应用程序,会有BarTender,Fastreport等框架。

PowerApps是微软低代码平台Power Platform的一款产品,一般用来制作App供用户进行信息交互。在PowerApps中,查看了一下和打印(print)相关的组件,好像只有如下的两个icon,

        

如果要实现一下打印功能,则也可以借助一些别的方式,PowerApps Component Framework(简称PCF)允许用户进行组件的制作,导入和添加。发现Power Platform社区有一个开源的PCF组件 PrintIt-Component 。

这边将在PowerApps中尝试使用一下这个开源的组件进行数据的打印

2. 具体说明

2.1 准备阶段

首先需要开启PowerApps所在environment的Power Apps component framework for canvas apps 功能,同时从github平台上下载PrintIt组件。

2.1.1 开启PCF功能

1) 打开Power Platform admin center , 选择对应的environment,然后点击上方的Settings按钮,

         

2) 在 Settings界面中,点击如下Features链接 

         

3) 打开Power Apps component framework for canvas apps开关,如下图所示, 

        

2.1.2 下载打印组件

地址是 https://github.com/yashag2255/PrintIt-Component

        

note, 发现这个开源组件是用Typescript制作的

2.2 使用PCF组件

2.2.1 导入PrintIt solution

1) 点击Import solution 

         

 2) 在 Import a solution 界面中,点击Browse按钮,选择打印solution的zip文件

        

 3) 导入成功后,打印solution将显示在界面中,

        

2.2.2 制作PowerApps

假定有一个SharePoint online list,存放了2024年巴黎奥运会奖牌数据,如下图,

         

2.2.2.1 添加打印组件 

1) 创建一个blank canvas app,然后点击左侧的添加组件按钮,同时点击右侧的Get more components按钮,如下图所示 

        

note, 当前Get more components按钮的位置和以前是不一样的。

2)在右侧弹出的面板中,点击Code tab,然后选择特定的打印组件,

        

3) 添加了component后,在控件栏中将多出一个打印组件出来

        

2.2.2.2 添加list数据源

在PowerApps中,添加巴黎奥运会奖牌数据所在的SharePoint online list, 

        

2.2.2.3 Canvas界面

1) 在Canvas中,添加一个Vertical Gallery,然后设定Items属性如下

        

2)添加打印组件到界面中,最后Canvas app界面是下图这样子的,

        

3) 设定打印组件的DataToPrint属性

        

Substitute(
    Concatenate(
        "[",
        Concat(
            Gallery1.AllItems,
            "{" & Char(34) & "Country Name" & Char(34) & ":" & Char(34) & Title & Char(34) & "," & Char(34) & "Continent" & Char(34) & ":" & Char(34) & Continent & Char(34) & "," & Char(34) & "Gold" & Char(34) & ":" & Char(34) & Gold & Char(34) & "," & Char(34) & "Silver" & Char(34) & ":" & Char(34) & Silver & Char(34) & "," & Char(34) & "Bronze" & Char(34) & ":" & Char(34) & Bronze & Char(34) & "},"
        ),
        "]"
    ),
    ",]",
    "]"
)

5)保存并发布canvas app

2.2.2.3 运行一下

1) 运行canvas app,点击Print it按钮,如下图所示,

         

 2)出现的打印界面如下图所示,

        

         

这样的话,PowerApps就有了一个简单的打印功能了,样式可能需要改进一些。

3.总结

本文简单记录了一下在PowerApps中使用开源打印组件PrintIt-Component的过程,具体的细节相对多一些。有了开源社区的组件,我们可以制作出功能更丰富的PowerApps。

本文如果哪里有错误,麻烦告之,谢谢谢谢!

#!/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对齐前端取数逻辑才能将分析结论显示在分析报告内
09-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值