import hilog from '@ohos.hilog';
import { JSON } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
import { StrUtil } from './StrUtil';/*** 日志工具類* author: 鴻蒙布道師* since: 2024/03/31*/
export class LogUtil {private static logSize: number = 2048;private static domain: number = 0x0000;private static tag: string = 'HarmonyUtilsLog'; // 日志Tagprivate static showLog: boolean = true; // 是否顯示打印日志private static isHilog: boolean = true; // true-hilog、false-console/*** 初始化日志參數(該方法建議在Ability里調用)* @param domain - 領域標識* @param tag - 日志標簽* @param showLog - 是否顯示日志* @param isHilog - 是否使用hilog*/static init(domain: number = LogUtil.domain, tag: string = LogUtil.tag, showLog: boolean = true,isHilog: boolean = true): void {LogUtil.domain = domain;LogUtil.tag = tag;LogUtil.showLog = showLog;LogUtil.isHilog = isHilog;}/*** 設置領域標識* @param domain - 領域標識*/static setDomain(domain: number = LogUtil.domain): void {LogUtil.domain = domain;}/*** 設置日志標簽* @param tag - 日志標簽*/static setTag(tag: string = LogUtil.tag): void {LogUtil.tag = tag;}/*** 設置是否顯示日志* @param showLog - 是否顯示日志*/static setShowLog(showLog: boolean = true): void {LogUtil.showLog = showLog;}/*** 設置日志打印方式* @param isHilog - true-hilog、false-console*/static setHilog(isHilog: boolean): void {LogUtil.isHilog = isHilog;}/*** 打印DEBUG級別日志* @param args - 日志內容*/static debug(...args: (string | object)[]): void {LogUtil.uniLog(args, hilog.LogLevel.DEBUG);}/*** 打印INFO級別日志* @param args - 日志內容*/static info(...args: (string | object)[]): void {LogUtil.uniLog(args, hilog.LogLevel.INFO);}/*** 打印WARN級別日志* @param args - 日志內容*/static warn(...args: (string | object)[]): void {LogUtil.uniLog(args, hilog.LogLevel.WARN);}/*** 打印ERROR級別日志* @param args - 日志內容*/static error(...args: (string | object)[]): void {LogUtil.uniLog(args, hilog.LogLevel.ERROR);}/*** 打印FATAL級別日志* @param args - 日志內容*/static fatal(...args: (string | object)[]): void {LogUtil.uniLog(args, hilog.LogLevel.FATAL);}/*** 打印JSON對象或JSON字符串* @param msg - JSON對象或字符串*/static print(msg: object | string): void {try {const content = LogUtil.formatMessage(msg);const len = Math.ceil(content.length / LogUtil.logSize);for (let i = 0; i < len; i++) {const end = Math.min((i + 1) * LogUtil.logSize, content.length);const logMsg = `\n${content.substring(i * LogUtil.logSize, end)}`;LogUtil.levelLog(logMsg, hilog.LogLevel.DEBUG);}} catch (err) {const error = err as BusinessError;console.error(`LogUtil-print-異常 ~ code: ${error.code} -·- message: ${error.message}`);}}/*** 統一日志輸出* @param message - 日志內容* @param level - 日志級別*/private static uniLog(message: (string | object)[], level: hilog.LogLevel): void {if (!LogUtil.showLog) return;const topLine = LogUtil.getLine(LogUtil.tag);LogUtil.levelLog(topLine, level);if (level === hilog.LogLevel.ERROR) {const locationLog = LogUtil.getLogLocation();LogUtil.levelLog(locationLog, level);}const content = LogUtil.formatMessage(message);const len = Math.ceil(content.length / LogUtil.logSize);for (let i = 0; i < len; i++) {const end = Math.min((i + 1) * LogUtil.logSize, content.length);const logMsg = `\n| ${content.substring(i * LogUtil.logSize, end)}`;LogUtil.levelLog(logMsg, level);}const bottomLine = LogUtil.getLine('');LogUtil.levelLog(bottomLine, level);}/*** 格式化日志內容* @param message - 日志內容,可以是字符串、對象或數組*/private static formatMessage(message: (string | object)[] | object | string): string {let logMessage = '';// Handle array inputif (Array.isArray(message)) {message.forEach((msg: string | object) => {logMessage += typeof msg === 'object' ? LogUtil.getObjectToJson(msg) : String(msg);});}// Handle object inputelse if (typeof message === 'object') {logMessage = LogUtil.getObjectToJson(message);}// Handle string inputelse {logMessage = String(message);}return logMessage;}/*** 對象轉JSON字符串* @param obj - 對象* @param line - 是否格式化換行*/private static getObjectToJson(obj: object, line: boolean = true): string {try {let jsonStr = JSON.stringify(obj, null, 2);if (line) {jsonStr = jsonStr.replace(/\n/g, '\n|\t');jsonStr = jsonStr.replace(/..$/, ' ');}return jsonStr;} catch {return '';}}/*** 獲取代碼位置*/private static getLogLocation(): string {const stackArray = new Error().stack?.split('\n').filter(item => item.trim() !== '').splice(-2) ?? [];const errorLocation = stackArray.join('\n').replace(/\s+/g, '');return `\n| ${errorLocation}`;}/*** 獲取生成的日志邊框* @param tag - 日志標簽* @param length - 邊框長度*/private static getLine(tag: string = '', length: number = 160): string {if (StrUtil.isNotEmpty(tag)) {return `┌${StrUtil.repeat('─', 10)} ${tag} ${StrUtil.repeat('─', length - tag.length - 2)}`;}return `└${StrUtil.repeat('─', 10)}${StrUtil.repeat('─', length)}`;}/*** 日志打印* @param msg - 日志內容* @param level - 日志級別*/private static levelLog(msg: string, level: hilog.LogLevel): void {if (LogUtil.isHilog) {// Explicitly call the appropriate hilog method based on the log levelswitch (level) {case hilog.LogLevel.DEBUG:hilog.debug(LogUtil.domain, LogUtil.tag, msg);break;case hilog.LogLevel.INFO:hilog.info(LogUtil.domain, LogUtil.tag, msg);break;case hilog.LogLevel.WARN:hilog.warn(LogUtil.domain, LogUtil.tag, msg);break;case hilog.LogLevel.ERROR:hilog.error(LogUtil.domain, LogUtil.tag, msg);break;case hilog.LogLevel.FATAL:hilog.fatal(LogUtil.domain, LogUtil.tag, msg);break;default:console.error(`Unsupported log level: ${level}`);break;}} else {// Fallback to console logging if hilog is not enabledswitch (level) {case hilog.LogLevel.DEBUG:console.debug(msg);break;case hilog.LogLevel.INFO:console.info(msg);break;case hilog.LogLevel.WARN:console.warn(msg);break;case hilog.LogLevel.ERROR:console.error(msg);break;case hilog.LogLevel.FATAL:console.log(msg);break;default:console.error(`Unsupported log level: ${level}`);break;}}}
}代碼如下:
import hilog from '@ohos.hilog';
import { JSON } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
import { StrUtil } from './StrUtil';/*** 日志工具類* author: 鴻蒙布道師* since: 2024/03/31*/
export class LogUtil {private static logSize: number = 2048;private static domain: number = 0x0000;private static tag: string = 'HarmonyUtilsLog'; // 日志Tagprivate static showLog: boolean = true; // 是否顯示打印日志private static isHilog: boolean = true; // true-hilog、false-console/*** 初始化日志參數(該方法建議在Ability里調用)* @param domain - 領域標識* @param tag - 日志標簽* @param showLog - 是否顯示日志* @param isHilog - 是否使用hilog*/static init(domain: number = LogUtil.domain, tag: string = LogUtil.tag, showLog: boolean = true,isHilog: boolean = true): void {LogUtil.domain = domain;LogUtil.tag = tag;LogUtil.showLog = showLog;LogUtil.isHilog = isHilog;}/*** 設置領域標識* @param domain - 領域標識*/static setDomain(domain: number = LogUtil.domain): void {LogUtil.domain = domain;}/*** 設置日志標簽* @param tag - 日志標簽*/static setTag(tag: string = LogUtil.tag): void {LogUtil.tag = tag;}/*** 設置是否顯示日志* @param showLog - 是否顯示日志*/static setShowLog(showLog: boolean = true): void {LogUtil.showLog = showLog;}/*** 設置日志打印方式* @param isHilog - true-hilog、false-console*/static setHilog(isHilog: boolean): void {LogUtil.isHilog = isHilog;}/*** 打印DEBUG級別日志* @param args - 日志內容*/static debug(...args: (string | object)[]): void {LogUtil.uniLog(args, hilog.LogLevel.DEBUG);}/*** 打印INFO級別日志* @param args - 日志內容*/static info(...args: (string | object)[]): void {LogUtil.uniLog(args, hilog.LogLevel.INFO);}/*** 打印WARN級別日志* @param args - 日志內容*/static warn(...args: (string | object)[]): void {LogUtil.uniLog(args, hilog.LogLevel.WARN);}/*** 打印ERROR級別日志* @param args - 日志內容*/static error(...args: (string | object)[]): void {LogUtil.uniLog(args, hilog.LogLevel.ERROR);}/*** 打印FATAL級別日志* @param args - 日志內容*/static fatal(...args: (string | object)[]): void {LogUtil.uniLog(args, hilog.LogLevel.FATAL);}/*** 打印JSON對象或JSON字符串* @param msg - JSON對象或字符串*/static print(msg: object | string): void {try {const content = LogUtil.formatMessage(msg);const len = Math.ceil(content.length / LogUtil.logSize);for (let i = 0; i < len; i++) {const end = Math.min((i + 1) * LogUtil.logSize, content.length);const logMsg = `\n${content.substring(i * LogUtil.logSize, end)}`;LogUtil.levelLog(logMsg, hilog.LogLevel.DEBUG);}} catch (err) {const error = err as BusinessError;console.error(`LogUtil-print-異常 ~ code: ${error.code} -·- message: ${error.message}`);}}/*** 統一日志輸出* @param message - 日志內容* @param level - 日志級別*/private static uniLog(message: (string | object)[], level: hilog.LogLevel): void {if (!LogUtil.showLog) return;const topLine = LogUtil.getLine(LogUtil.tag);LogUtil.levelLog(topLine, level);if (level === hilog.LogLevel.ERROR) {const locationLog = LogUtil.getLogLocation();LogUtil.levelLog(locationLog, level);}const content = LogUtil.formatMessage(message);const len = Math.ceil(content.length / LogUtil.logSize);for (let i = 0; i < len; i++) {const end = Math.min((i + 1) * LogUtil.logSize, content.length);const logMsg = `\n| ${content.substring(i * LogUtil.logSize, end)}`;LogUtil.levelLog(logMsg, level);}const bottomLine = LogUtil.getLine('');LogUtil.levelLog(bottomLine, level);}/*** 格式化日志內容* @param message - 日志內容,可以是字符串、對象或數組*/private static formatMessage(message: (string | object)[] | object | string): string {let logMessage = '';// Handle array inputif (Array.isArray(message)) {message.forEach((msg: string | object) => {logMessage += typeof msg === 'object' ? LogUtil.getObjectToJson(msg) : String(msg);});}// Handle object inputelse if (typeof message === 'object') {logMessage = LogUtil.getObjectToJson(message);}// Handle string inputelse {logMessage = String(message);}return logMessage;}/*** 對象轉JSON字符串* @param obj - 對象* @param line - 是否格式化換行*/private static getObjectToJson(obj: object, line: boolean = true): string {try {let jsonStr = JSON.stringify(obj, null, 2);if (line) {jsonStr = jsonStr.replace(/\n/g, '\n|\t');jsonStr = jsonStr.replace(/..$/, ' ');}return jsonStr;} catch {return '';}}/*** 獲取代碼位置*/private static getLogLocation(): string {const stackArray = new Error().stack?.split('\n').filter(item => item.trim() !== '').splice(-2) ?? [];const errorLocation = stackArray.join('\n').replace(/\s+/g, '');return `\n| ${errorLocation}`;}/*** 獲取生成的日志邊框* @param tag - 日志標簽* @param length - 邊框長度*/private static getLine(tag: string = '', length: number = 160): string {if (StrUtil.isNotEmpty(tag)) {return `┌${StrUtil.repeat('─', 10)} ${tag} ${StrUtil.repeat('─', length - tag.length - 2)}`;}return `└${StrUtil.repeat('─', 10)}${StrUtil.repeat('─', length)}`;}/*** 日志打印* @param msg - 日志內容* @param level - 日志級別*/private static levelLog(msg: string, level: hilog.LogLevel): void {if (LogUtil.isHilog) {// Explicitly call the appropriate hilog method based on the log levelswitch (level) {case hilog.LogLevel.DEBUG:hilog.debug(LogUtil.domain, LogUtil.tag, msg);break;case hilog.LogLevel.INFO:hilog.info(LogUtil.domain, LogUtil.tag, msg);break;case hilog.LogLevel.WARN:hilog.warn(LogUtil.domain, LogUtil.tag, msg);break;case hilog.LogLevel.ERROR:hilog.error(LogUtil.domain, LogUtil.tag, msg);break;case hilog.LogLevel.FATAL:hilog.fatal(LogUtil.domain, LogUtil.tag, msg);break;default:console.error(`Unsupported log level: ${level}`);break;}} else {// Fallback to console logging if hilog is not enabledswitch (level) {case hilog.LogLevel.DEBUG:console.debug(msg);break;case hilog.LogLevel.INFO:console.info(msg);break;case hilog.LogLevel.WARN:console.warn(msg);break;case hilog.LogLevel.ERROR:console.error(msg);break;case hilog.LogLevel.FATAL:console.log(msg);break;default:console.error(`Unsupported log level: ${level}`);break;}}}
}