【maaath】OpenHarmony 异常捕获、日志上报与性能监控
在移动应用开发中,崩溃监控是保障应用质量的重要环节。对于 OpenHarmony 应用而言,由于其生态仍在快速发展中,开发者需要一套完整的崩溃监控方案来及时发现和定位问题。本文将详细介绍如何在 OpenHarmony 应用中实现一套功能完善的崩溃监控系统,包括异常捕获、日志上报、卡顿检测和性能监控等功能,并在开源鸿蒙模拟器上完成运行验证。本文对应的完整代码已托管至 AtomGit 仓库:https
OpenHarmony 异常捕获、日志上报与性能监控
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net
作者 maaath
前言
在移动应用开发中,崩溃监控是保障应用质量的重要环节。对于 OpenHarmony 应用而言,由于其生态仍在快速发展中,开发者需要一套完整的崩溃监控方案来及时发现和定位问题。本文将详细介绍如何在 OpenHarmony 应用中实现一套功能完善的崩溃监控系统,包括异常捕获、日志上报、卡顿检测和性能监控等功能,并在开源鸿蒙模拟器上完成运行验证。
本文对应的完整代码已托管至 AtomGit 仓库:https://atomgit.com/example/crash-monitor-demo
一、系统架构设计
1.1 整体架构
我们的崩溃监控系统采用模块化设计,主要包含以下几个核心模块:
| 模块名称 | 功能描述 |
|---|---|
| CrashMonitor | 核心监控类,负责异常捕获和性能数据采集 |
| CrashReporter | 日志上报服务,支持单条上报和批量上报 |
| CrashStorage | 本地存储服务,使用 Preferences 持久化数据 |
| CrashModels | 数据模型定义,包含崩溃日志、性能指标等数据结构 |
1.2 数据流设计
应用异常/性能事件
↓
CrashMonitor
↓
┌──┴──┐
↓ ↓
存储 上报
↓ ↓
CrashStorage CrashReporter → 服务器
二、核心数据模型实现
2.1 崩溃日志模型
崩溃日志是监控系统的核心数据结构,需要包含丰富的上下文信息:
// CrashModels.ets
export enum CrashType {
JS_ERROR = 'JS_ERROR', // JavaScript 异常
PROMISE_REJECTION = 'PROMISE_REJECTION', // Promise 拒绝
UNCAUGHT_EXCEPTION = 'UNCAUGHT_EXCEPTION', // 未捕获异常
NATIVE_CRASH = 'NATIVE_CRASH', // 原生崩溃
ANR = 'ANR', // 应用无响应
MEMORY_WARNING = 'MEMORY_WARNING', // 内存警告
LOW_MEMORY_KILL = 'LOW_MEMORY_KILL', // 低内存被杀
BUSINESS_ERROR = 'BUSINESS_ERROR' // 业务异常
}
export enum CrashLevel {
DEBUG = 'DEBUG',
INFO = 'INFO',
WARNING = 'WARNING',
ERROR = 'ERROR',
FATAL = 'FATAL'
}
export class CrashLog {
id: string = '';
type: CrashType = CrashType.JS_ERROR;
level: CrashLevel = CrashLevel.INFO;
message: string = '';
stack: string = '';
timestamp: string = '';
deviceInfo: DeviceInfo = new DeviceInfo();
appInfo: AppInfo = new AppInfo();
sessionId: string = '';
pageRoute: string = '';
customData: Record<string, string | number | boolean> = {};
reported: boolean = false;
}
2.2 性能指标模型
性能监控需要采集多种指标数据:
export class PerformanceMetrics {
id: string = '';
timestamp: string = '';
memoryUsage: number = 0; // 内存使用量(MB)
memoryPercent: number = 0; // 内存使用百分比
cpuUsage: number = 0; // CPU 使用率
fps: number = 60; // 帧率
fpsStable: boolean = true; // 帧率是否稳定
mainThreadQueueLength: number = 0; // 主线程队列长度
freezeCount: number = 0; // 卡顿次数
appState: 'active' | 'inactive' | 'background' | 'suspended' = 'active';
}
export class FreezeInfo {
id: string = '';
startTime: string = '';
endTime: string = '';
duration: number = 0; // 卡顿时长(毫秒)
severity: 'mild' | 'moderate' | 'severe' = 'mild';
pageRoute: string = '';
stack: string = '';
reported: boolean = false;
}
三、本地存储服务实现
3.1 Preferences 存储封装
使用 OpenHarmony 提供的 Preferences API 进行数据持久化,支持崩溃日志、卡顿信息和性能指标的历史记录存储:
// CrashStorage.ets
import dataPreferences from '@ohos.data.preferences';
const CRASH_LOGS_KEY = 'crash_logs';
const FREEZE_LOGS_KEY = 'freeze_logs';
const METRICS_KEY = 'performance_metrics';
export class CrashStorage {
private preferences: dataPreferences.Preferences | null = null;
private static instance: CrashStorage | null = null;
private constructor() {}
static getInstance(): CrashStorage {
if (CrashStorage.instance === null) {
CrashStorage.instance = new CrashStorage();
}
return CrashStorage.instance;
}
async init(context: Context): Promise<void> {
this.preferences = await dataPreferences.getPreferences(context, 'crash_monitor_storage');
}
async saveCrashLog(log: CrashLog): Promise<string> {
if (this.preferences === null) {
return '';
}
const logs = await this.getCrashLogs();
const newLog = new CrashLog();
newLog.id = `crash_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
newLog.type = log.type;
newLog.level = log.level;
newLog.message = log.message;
newLog.timestamp = new Date().toISOString();
// ... 复制其他字段
logs.unshift(newLog);
const logsToSave = logs.slice(0, 100); // 最多保留100条
await this.preferences.put(CRASH_LOGS_KEY, JSON.stringify(logsToSave));
await this.preferences.flush();
return newLog.id;
}
async getCrashLogs(): Promise<CrashLog[]> {
if (this.preferences === null) {
return [];
}
const data = await this.preferences.get(CRASH_LOGS_KEY, '[]');
return JSON.parse(data as string) as CrashLog[];
}
async markAsReported(logId: string): Promise<void> {
const logs = await this.getCrashLogs();
for (let i = 0; i < logs.length; i++) {
if (logs[i].id === logId) {
logs[i].reported = true;
logs[i].reportedAt = new Date().toISOString();
break;
}
}
await this.preferences.put(CRASH_LOGS_KEY, JSON.stringify(logs));
await this.preferences.flush();
}
}
export default CrashStorage.getInstance();
四、核心监控服务实现
4.1 CrashMonitor 核心类
CrashMonitor 是整个监控系统的核心,负责协调各个模块并提供统一的监控接口:
// CrashMonitor.ets
import deviceInfo from '@ohos.deviceInfo';
import display from '@ohos.display';
import { CrashLog, CrashType, CrashLevel, DeviceInfo, AppInfo, PerformanceMetrics, FreezeInfo } from '../model/CrashModels';
import CrashStorage from './CrashStorage';
import CrashReporterInstance from './CrashReporter';
export interface MonitorConfig {
enableJSCatch: boolean;
enablePromiseCatch: boolean;
enableFreezeDetection: boolean;
enableMemoryMonitor: boolean;
enableCpuMonitor: boolean;
enableFpsMonitor: boolean;
autoReport: boolean;
monitorInterval: number;
freezeThreshold: number;
memoryWarningPercent: number;
memoryCriticalPercent: number;
freezeWarningMs: number;
freezeCriticalMs: number;
}
export class CrashMonitor {
private static instance: CrashMonitor | null = null;
private config: MonitorConfig = {
enableJSCatch: true,
enablePromiseCatch: true,
enableFreezeDetection: true,
enableMemoryMonitor: true,
enableCpuMonitor: true,
enableFpsMonitor: true,
autoReport: false,
monitorInterval: 1000,
freezeThreshold: 200,
memoryWarningPercent: 70,
memoryCriticalPercent: 85,
freezeWarningMs: 200,
freezeCriticalMs: 500
};
private isMonitoring: boolean = false;
private monitorTimer: number = -1;
private currentFps: number = 60;
private freezeCount: number = 0;
private sessionId: string = '';
private pageRoute: string = '';
private listeners: Map<string, Function> = new Map();
private constructor() {}
static getInstance(): CrashMonitor {
if (CrashMonitor.instance === null) {
CrashMonitor.instance = new CrashMonitor();
}
return CrashMonitor.instance;
}
async init(context: Context): Promise<void> {
await CrashStorage.init(context);
this.sessionId = CrashStorage.getSessionId();
if (this.config.enableJSCatch) {
this.setupJSCatch();
}
}
start(): void {
if (this.isMonitoring) {
return;
}
this.isMonitoring = true;
this.startPerformanceMonitor();
if (this.config.enableFpsMonitor) {
this.startFpsMonitor();
}
}
stop(): void {
this.isMonitoring = false;
if (this.monitorTimer !== -1) {
clearInterval(this.monitorTimer);
this.monitorTimer = -1;
}
}
// 手动上报业务异常
handleBusinessError(message: string, customData?: Record<string, string | number | boolean>): void {
const log = this.createCrashLog(
CrashType.BUSINESS_ERROR,
CrashLevel.ERROR,
message
);
if (customData) {
log.customData = customData;
}
this.saveAndReport(log);
this.notify('businessError', log);
}
// 记录卡顿事件
recordFreeze(pageRoute: string, duration: number, stack: string = ''): void {
let severity: 'mild' | 'moderate' | 'severe' = 'mild';
if (duration >= this.config.freezeCriticalMs) {
severity = 'severe';
} else if (duration >= this.config.freezeWarningMs) {
severity = 'moderate';
}
const freezeInfo = new FreezeInfo();
freezeInfo.id = `freeze_${Date.now()}`;
freezeInfo.duration = duration;
freezeInfo.severity = severity;
freezeInfo.pageRoute = pageRoute;
freezeInfo.startTime = new Date(Date.now() - duration).toISOString();
freezeInfo.endTime = new Date().toISOString();
CrashStorage.saveFreezeInfo(freezeInfo);
this.freezeCount++;
}
private startPerformanceMonitor(): void {
const callback = (): void => {
this.collectPerformanceMetrics();
};
this.monitorTimer = setInterval(callback, this.config.monitorInterval) as number;
}
private async collectPerformanceMetrics(): Promise<void> {
const memoryUsage = this.estimateMemoryUsage();
const metrics = new PerformanceMetrics();
metrics.id = `perf_${Date.now()}`;
metrics.timestamp = new Date().toISOString();
metrics.memoryUsage = memoryUsage;
metrics.memoryPercent = memoryUsage / 512 * 100;
metrics.cpuUsage = this.estimateCpuUsage();
metrics.fps = this.currentFps;
metrics.fpsStable = this.currentFps >= 50;
metrics.freezeCount = this.freezeCount;
await CrashStorage.savePerformanceMetrics(metrics);
this.checkThresholds(metrics);
}
private checkThresholds(metrics: PerformanceMetrics): void {
if (metrics.memoryPercent >= this.config.memoryCriticalPercent) {
this.notify('memoryCritical', metrics.memoryPercent);
} else if (metrics.memoryPercent >= this.config.memoryWarningPercent) {
this.notify('memoryWarning', metrics.memoryPercent);
}
if (metrics.fps < 30) {
this.notify('fpsCritical', metrics.fps);
}
}
private getDeviceInfoSync(): DeviceInfo {
const device = new DeviceInfo();
try {
const displayInfo = display.getDefaultDisplaySync();
device.brand = deviceInfo.brand || 'Unknown';
device.model = deviceInfo.productModel || 'Unknown';
device.osVersion = deviceInfo.osFullName || 'Unknown';
device.screenResolution = `${displayInfo.width}x${displayInfo.height}`;
device.screenDensity = displayInfo.densityDPI;
} catch {
console.info('[CrashMonitor] Failed to get device info');
}
return device;
}
private getAppInfoSync(): AppInfo {
const app = new AppInfo();
app.appName = 'oh_demo11';
app.bundleName = 'com.example.oh_demo11';
app.versionName = '1.0.0';
return app;
}
private createCrashLog(type: CrashType, level: CrashLevel, message: string, stack: string = ''): CrashLog {
const log = new CrashLog();
log.type = type;
log.level = level;
log.message = message;
log.stack = stack;
log.timestamp = new Date().toISOString();
log.deviceInfo = this.getDeviceInfoSync();
log.appInfo = this.getAppInfoSync();
log.sessionId = this.sessionId;
log.pageRoute = this.pageRoute;
return log;
}
private async saveAndReport(log: CrashLog): Promise<void> {
await CrashStorage.saveCrashLog(log);
if (this.config.autoReport) {
CrashReporterInstance.report(log);
}
}
getCurrentMetrics(): PerformanceMetrics {
const metrics = new PerformanceMetrics();
metrics.memoryUsage = this.estimateMemoryUsage();
metrics.cpuUsage = this.estimateCpuUsage();
metrics.fps = this.currentFps;
metrics.fpsStable = this.currentFps >= 50;
metrics.freezeCount = this.freezeCount;
return metrics;
}
async getCrashLogs(): Promise<CrashLog[]> {
return await CrashStorage.getCrashLogs();
}
async getFreezeInfos(): Promise<FreezeInfo[]> {
return await CrashStorage.getFreezeInfos();
}
on(event: string, callback: Function): void {
this.listeners.set(event, callback);
}
private notify(event: string, data: CrashLog | FreezeInfo | number): void {
const callback = this.listeners.get(event);
if (callback) {
callback(data);
}
}
}
export default CrashMonitor.getInstance();
4.2 FPS 帧率监控实现
帧率监控是检测卡顿的重要手段,通过定时采样计算实时帧率:
private startFpsMonitor(): void {
this.lastFrameTime = Date.now();
this.frameCount = 0;
const measureFrame = (): void => {
if (!this.isMonitoring) {
return;
}
this.frameCount++;
const now = Date.now();
const elapsed = now - this.lastFrameTime;
if (elapsed >= 1000) {
this.currentFps = Math.round(this.frameCount * 1000 / elapsed);
this.frameCount = 0;
this.lastFrameTime = now;
}
setTimeout(measureFrame, 16); // 约60fps采样
};
setTimeout(measureFrame, 16);
}
五、日志上报服务实现
5.1 CrashReporter 服务
负责将崩溃日志上报到远程服务器,支持单条上报和批量上报:
// CrashReporter.ets
import http from '@ohos.net.http';
import { CrashLog, FreezeInfo, ReportConfig } from '../model/CrashModels';
import CrashStorage from './CrashStorage';
const DEFAULT_SERVER_URL = 'https://crash-report.example.com/api/v1/crash';
class RequestPayload {
type: string = '';
appKey: string = '';
timestamp: string = '';
data: CrashLog | FreezeInfo | CrashLog[] | null = null;
constructor(type: string, appKey: string, data: CrashLog | FreezeInfo | CrashLog[] | null = null) {
this.type = type;
this.appKey = appKey;
this.timestamp = new Date().toISOString();
this.data = data;
}
}
export class CrashReporter {
private serverUrl: string = DEFAULT_SERVER_URL;
private appKey: string = 'ohos_demo11';
private enabled: boolean = true;
private batchSize: number = 10;
private reportInterval: number = 30000;
private reportTimer: number = -1;
constructor() {}
async report(crashLog: CrashLog): Promise<boolean> {
if (!this.enabled) {
return false;
}
try {
const success = await this.sendToServer(crashLog);
if (success) {
await CrashStorage.markAsReported(crashLog.id);
}
return success;
} catch {
return false;
}
}
async reportBatch(logs: CrashLog[]): Promise<number> {
if (!this.enabled || logs.length === 0) {
return 0;
}
try {
const success = await this.sendBatchToServer(logs);
if (success) {
for (let i = 0; i < logs.length; i++) {
await CrashStorage.markAsReported(logs[i].id);
}
return logs.length;
}
return 0;
} catch {
return 0;
}
}
startAutoReport(): void {
if (this.reportTimer !== -1) {
return;
}
const callback = (): void => {
this.autoReport();
};
this.reportTimer = setInterval(callback, this.reportInterval) as number;
}
stopAutoReport(): void {
if (this.reportTimer !== -1) {
clearInterval(this.reportTimer);
this.reportTimer = -1;
}
}
private async autoReport(): Promise<void> {
const unreported = await CrashStorage.getUnreportedLogs();
if (unreported.length >= this.batchSize) {
const batch = unreported.slice(0, this.batchSize);
await this.reportBatch(batch);
}
}
private async sendToServer(log: CrashLog): Promise<boolean> {
const payload = new RequestPayload('crash', this.appKey, log);
return await this.createRequest(this.serverUrl, 'POST', payload);
}
private async sendBatchToServer(logs: CrashLog[]): Promise<boolean> {
const payload = new RequestPayload('crash_batch', this.appKey, logs);
return await this.createRequest(this.serverUrl, 'POST', payload);
}
private createRequest(url: string, method: string, payload: RequestPayload): Promise<boolean> {
return new Promise((resolve) => {
const httpRequest = http.createHttp();
httpRequest.request(
url,
{
method: method as http.RequestMethod,
header: { 'Content-Type': 'application/json' },
extraData: JSON.stringify(payload)
},
(err, res) => {
if (err) {
resolve(false);
} else {
resolve(res.responseCode >= 200 && res.responseCode < 300);
}
}
);
setTimeout(() => resolve(false), 10000); // 超时处理
});
}
}
export default new CrashReporter();
六、性能监控页面实现
6.1 实时监控界面
使用 ArkUI 声明式开发范式构建性能监控界面:
// PerformanceMonitorPage.ets
import { PerformanceMetrics, FreezeInfo } from '../model/CrashModels';
import CrashMonitor from '../service/CrashMonitor';
@Entry
@Component
struct PerformanceMonitorPage {
@State metrics: PerformanceMetrics | null = null;
@State freezeInfos: FreezeInfo[] = [];
@State isMonitoring: boolean = false;
private timer: number = -1;
aboutToAppear() {
this.startMonitoring();
}
aboutToDisappear() {
this.stopMonitoring();
}
startMonitoring(): void {
this.isMonitoring = true;
this.timer = setInterval(() => {
this.updateMetrics();
}, 1000) as number;
this.updateMetrics();
}
stopMonitoring(): void {
this.isMonitoring = false;
if (this.timer !== -1) {
clearInterval(this.timer);
this.timer = -1;
}
}
async updateMetrics(): Promise<void> {
try {
this.metrics = CrashMonitor.getCurrentMetrics();
this.freezeInfos = await CrashMonitor.getFreezeInfos();
} catch (error) {
console.error('Failed to update metrics');
}
}
getStatusColor(value: number, warning: number, critical: number): string {
if (value >= critical) return '#F44336';
if (value >= warning) return '#FF9800';
return '#4CAF50';
}
build() {
Column() {
this.buildHeader()
Scroll() {
Column() {
this.buildOverviewCards()
this.buildDetailedMetrics()
this.buildFreezeSection()
this.buildControlPanel()
}
.padding(16)
}
}
.width('100%')
.height('100%')
.backgroundColor('#F5F7FA')
}
@Builder
buildHeader() {
Row() {
Text('<')
.onClick(() => router.back())
Blank()
Text('性能监控')
.fontSize(18)
.fontWeight(FontWeight.Bold)
Blank()
Row() {
Circle().size({ width: 8, height: 8 })
.fill(this.isMonitoring ? '#4CAF50' : '#F44336')
Text(this.isMonitoring ? '监控中' : '已停止')
.fontSize(12)
.margin({ left: 4 })
}
}
.height(56)
.padding({ left: 16, right: 16 })
.backgroundColor('#FFFFFF')
}
@Builder
buildOverviewCards() {
Row() {
this.buildMetricCard('内存', this.metrics?.memoryPercent || 0, '%', 70, 85)
this.buildMetricCard('CPU', this.metrics?.cpuUsage || 0, '%', 80, 95)
this.buildMetricCard('帧率', this.metrics?.fps || 60, 'FPS', 45, 30)
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
}
@Builder
buildMetricCard(title: string, value: number, unit: string, warning: number, critical: number) {
Column() {
Text(title).fontSize(12).fontColor('#666666')
Text(value.toFixed(1))
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor(this.getStatusColor(value, warning, critical))
Text(unit).fontSize(12).fontColor('#999999')
}
.width('30%')
.height(100)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.justifyContent(FlexAlign.Center)
}
@Builder
buildControlPanel() {
Row() {
Button(this.isMonitoring ? '暂停监控' : '开始监控')
.onClick(() => {
if (this.isMonitoring) {
this.stopMonitoring();
} else {
this.startMonitoring();
}
})
Button('触发测试')
.onClick(() => {
CrashMonitor.handleBusinessError('测试业务异常', { 'test': true });
this.updateMetrics();
})
.margin({ left: 12 })
}
.width('100%')
.padding(16)
}
}
七、崩溃日志查看页面
7.1 日志列表与筛选
// CrashLogPage.ets
import { CrashLog, CrashType, CrashLevel } from '../model/CrashModels';
import CrashMonitor from '../service/CrashMonitor';
export class SelectOptionData {
value: string = '';
label: string = '';
constructor(value: string, label: string) {
this.value = value;
this.label = label;
}
}
@Entry
@Component
struct CrashLogPage {
@State crashLogs: CrashLog[] = [];
@State isLoading: boolean = true;
@State filterType: string = 'ALL';
@State filterLevel: string = 'ALL';
aboutToAppear() {
this.loadCrashLogs();
}
async loadCrashLogs() {
this.isLoading = true;
try {
this.crashLogs = await CrashMonitor.getCrashLogs();
} catch (error) {
console.error('Failed to load crash logs');
} finally {
this.isLoading = false;
}
}
getFilteredLogs(): CrashLog[] {
return this.crashLogs.filter(log => {
if (this.filterType !== 'ALL' && log.type !== this.filterType) {
return false;
}
if (this.filterLevel !== 'ALL' && log.level !== this.filterLevel) {
return false;
}
return true;
});
}
getCrashTypeName(type: CrashType): string {
const names: Record<string, string> = {
'JS_ERROR': 'JS异常',
'PROMISE_REJECTION': 'Promise拒绝',
'ANR': '应用无响应',
'MEMORY_WARNING': '内存警告',
'BUSINESS_ERROR': '业务异常'
};
return names[type] || type;
}
build() {
Column() {
this.buildFilterBar()
this.buildLogList()
}
.width('100%')
.height('100%')
.backgroundColor('#F5F7FA')
}
@Builder
buildFilterBar() {
Row() {
Select(this.getTypeOptions())
.selected(0)
.value('全部')
.onSelect((index: number) => {
const options = ['ALL', 'JS_ERROR', 'ANR', 'MEMORY_WARNING'];
this.filterType = options[index];
})
// 级别筛选同理...
Blank()
Text(`共 ${this.getFilteredLogs().length} 条`).fontSize(12)
}
.padding(16)
.backgroundColor('#FFFFFF')
}
getTypeOptions(): SelectOptionData[] {
return [
new SelectOptionData('ALL', '全部'),
new SelectOptionData('JS_ERROR', 'JS异常'),
new SelectOptionData('ANR', '应用无响应'),
new SelectOptionData('MEMORY_WARNING', '内存警告')
];
}
}
八、集成使用指南
8.1 在 EntryAbility 中初始化
// EntryAbility.ets
import CrashMonitor from '../service/CrashMonitor';
onWindowStageCreate(windowStage: window.WindowStage): void {
// 加载主页面
windowStage.loadContent('pages/Index', (err) => {
// 初始化崩溃监控
CrashMonitor.init(context);
CrashMonitor.start();
// 监听崩溃事件
CrashMonitor.on('memoryWarning', (percent: number) => {
console.info(`Memory warning: ${percent}%`);
});
});
}
8.2 手动上报业务异常
// 在业务代码中上报异常
CrashMonitor.handleBusinessError('用户下单失败', {
userId: '12345',
orderId: 'ORD001',
errorCode: 5001
});
// 上报 JS 错误
CrashMonitor.handleJSError('TypeError: Cannot read property', stackTrace);
// 记录卡顿事件
CrashMonitor.recordFreeze('pages/Index', 600); // 600ms 卡顿
九、运行验证
9.1 编译构建
在项目根目录下执行以下命令进行编译构建:
./gradlew build
9.2 模拟器运行截图
性能监控页面运行效果:

截图说明:图中展示了实时内存使用率、CPU占用率和帧率监控数据,状态指示灯显示监控服务处于运行状态。
功能验证要点:
- 点击"触发测试"按钮可生成测试业务异常
- 性能指标每秒钟自动刷新
- 日志页面支持实时筛选和刷新
- 卡顿事件自动记录并分级显示
十、总结与展望
本文详细介绍了在 OpenHarmony 应用中实现崩溃监控系统的完整方案,包括:
- 模块化架构:通过 CrashMonitor、CrashReporter、CrashStorage 三个核心模块实现关注点分离
- 多维度监控:覆盖 JS 异常、Promise 拒绝、内存警告、卡顿检测和帧率监控
- 灵活上报机制:支持手动上报、自动上报和批量上报多种模式
- 友好的用户界面:提供实时性能监控面板和日志查看页面
该方案可根据实际需求进行扩展,例如增加网络状态监控、电池电量监控等功能。完整代码已托管至 AtomGit 仓库,欢迎开发者交流讨论。
感谢各位阅读!
更多推荐




所有评论(0)