鸿蒙NEXT开发日志工具类(ArkTs)

复制代码
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'; // 日志Tag
  private 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 input
    if (Array.isArray(message)) {
      message.forEach((msg: string | object) => {
        logMessage += typeof msg === 'object' ? LogUtil.getObjectToJson(msg) : String(msg);
      });
    }
    // Handle object input
    else if (typeof message === 'object') {
      logMessage = LogUtil.getObjectToJson(message);
    }
    // Handle string input
    else {
      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 level
      switch (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 enabled
      switch (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;
      }
    }
  }
}

代码如下:
TypeScript 复制代码
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'; // 日志Tag
  private 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 input
    if (Array.isArray(message)) {
      message.forEach((msg: string | object) => {
        logMessage += typeof msg === 'object' ? LogUtil.getObjectToJson(msg) : String(msg);
      });
    }
    // Handle object input
    else if (typeof message === 'object') {
      logMessage = LogUtil.getObjectToJson(message);
    }
    // Handle string input
    else {
      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 level
      switch (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 enabled
      switch (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;
      }
    }
  }
}
相关推荐
Kapaseker4 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴4 小时前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭14 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab15 小时前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
BoomHe20 小时前
Now in Android 架构模式全面分析
android·android jetpack
Hcourage1 天前
鸿蒙工程获取C/C++代码覆盖
harmonyos
ssshooter1 天前
Tauri 踩坑 appLink 修改后闪退
前端·ios·rust
二流小码农1 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos
鹏程十八少1 天前
4.Android 30分钟手写一个简单版shadow, 从零理解shadow插件化零反射插件化原理
android·前端·面试
Kapaseker1 天前
一杯美式搞定 Kotlin 空安全
android·kotlin