前端代码规范 - 日志打印规范

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 前端代码规范 - 日志打印规范

在前端开发中,随着项目迭代升级,日志打印逐渐风格不一,合理的日志输出是监控应用状态、调试代码和跟踪用户行为的重要手段。一个好的日志系统能够帮助开发者快速定位问题,提高开发效率。本文将介绍如何在前端项目中制定日志输出规范。

  1. 日志等级
    首先,我们需要定义不同的日志等级,以便根据消息的重要性进行分类。通常,日志等级从低到高可以分为以下几类:

DEBUG: 详细的开发时信息,用于调试应用。
INFO: 重要事件的简要信息,如系统启动、配置等。
WARN: 系统能正常运行,但有潜在错误的情况。
ERROR: 由于严重的问题,某些功能无法正常运行。
FATAL: 非常严重的问题,可能导致系统崩溃。

  1. 日志内容
    日志内容应该包含足够的信息,以便于开发者理解发生了什么。一个完整的日志消息通常包括:

时间戳:精确到毫秒的事件发生时间。
日志等级:当前日志消息的等级。
消息内容:描述事件的详细信息。
错误堆栈:如果是错误,提供错误堆栈信息。

  1. 日志格式
    日志的格式应该统一,以便于阅读和解析。一个常见的日志格式如下:

[时间戳] [日志等级] [消息内容] [错误堆栈]
例如:

[2024-04-01T12:00:00.000Z] [ERROR] Failed to load user data. {stack}

  1. 日志输出
    在前端项目中,我们通常使用console对象进行日志输出。不同的日志等级可以使用不同的console方法:

console.debug用于DEBUG级别。
console.info用于INFO级别。
console.warn用于WARN级别。
console.error用于ERROR和FATAL级别。

  1. 日志封装
    为了更好地控制日志输出,我们可以封装一个日志工具,来统一管理日志输出。以下是一个简单的日志工具实现:
class Logger {
   
  static log(level, message, error) {
   
    const timestamp = new Date().toISOString();
    const stack = error ? error.stack : '';
    const formattedMessage = `[${
     timestamp}] [${
     level}] ${
     message} ${
     stack}`;

    switch (level) {
   
      case 'DEBUG':
        console.debug(formattedMessage);
        break;
      case 'INFO':
        console.info(formattedMessage);
        break;
      case 'WARN':
        console.warn(formattedMessage);
        break;
      case 'ERROR':
      case 'FATAL':
        console.error(formattedMessage);
        break;
      default:
        console.log(formattedMessage);
    }
  }

  static debug(message) {
   
    this.log('DEBUG', message);
  }

  static info(message) {
   
    this.log('INFO', message);
  }

  static warn(message) {
   
    this.log('WARN', message);
  }

  static error(message, error) {
   
    this.log('ERROR', message, error);
  }

  static fatal(message, error) {
   
    this.log('FATAL', message, error);
  }
}

// 使用示例

Logger.info('Application is starting...');
Logger.error('Failed to load user data', new Error('Network Error'));
  1. 日志收集
    在生产环境中,我们可能需要将日志发送到后端服务器进行收集和分析。这可以通过AJAX请求或专门的日志服务来实现。例如,我们可以修改Logger工具,添加一个方法来发送日志:
class Logger {
   
  // ...其他方法

 // 根据环境变量判断是否发送日志到后端
if (process.env.NODE_ENV === 'production') {
   
  this.sendLog(formattedMessage);
}

  static sendLog(message) {
   
    // 假设我们有一个日志收集的API
    const logEndpoint = '/api/logs';
 fetch(logEndpoint, {
   
  method: 'POST', 
  headers: {
   
   'Content-Type': 'application/json', 
  }, body: JSON.stringify({
    message }), }).catch((error) => {
   
  console.error('Failed to send log', error); 
 });
}
  1. 日志等级控制
    在开发环境中,我们可能希望看到尽可能多的日志输出,以便更好地调试应用。但在生产环境中,为了避免性能损耗和过多的日志信息,我们可能只希望输出WARN和以上等级的日志。我们可以在Logger中添加一个等级控制:
class Logger {
   
  static level = 'DEBUG'; // 默认为DEBUG级别

  static setLevel(newLevel) {
   
    this.level = newLevel;
  }

  static shouldLog(level) {
   
    const levels = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL'];
    return levels.indexOf(level) >= levels.indexOf(this.level);
  }

  static log(level, message, error) {
   
    if (!this.shouldLog(level)) {
   
      return;
    }
    // ...日志输出逻辑
  }

  // ...其他方法
}

// 生产环境中设置日志等级
if (process.env.NODE_ENV === 'production') {
   
  Logger.setLevel('WARN');
}

// 使用示例
Logger.debug('This will not be logged in production');
Logger.warn('This will be logged in production');
  1. 日志格式化
    为了进一步提高日志的可读性,我们可以添加格式化功能,比如为不同等级的日志添加颜色,或者为错误堆栈提供更好的格式化。
class Logger {
   
  // ...其他方法

  static formatStack(stack) {
   
    if (!stack) return '';
    // 格式化错误堆栈的逻辑
    return stack.split('\n').map(line => `    at ${
     line}`).join('\n');
  }

  static log(level, message, error) {
   
    // ...日志输出逻辑

    // 格式化错误堆栈
    if (error) {
   
      formattedMessage += `\n${
     this.formatStack(error.stack)}`;
    }

    // ...输出逻辑
  }

  // ...其他方法
}
  1. 函数式美化日志打印的实现

    export const usePrettyLog = () => {
         
    const isProduction = import.meta.env.MODE === 'production';
    const isEmpty = (value: any) => {
         
     return value == null || value === undefined || value === '';
    };
    const prettyPrint = (title: string, text: string, color: string) => {
         
     if (isProduction) return;
     console.log(
       `%c ${
           title} %c ${
           text} %c`,
       `background:${
           color};border:1px solid ${
           color}; padding: 1px; border-radius: 2px 0 0 2px; color: #fff;`,
       `border:1px solid ${
           color}; padding: 1px; border-radius: 0 2px 2px 0; color: ${
           color};`,
       'background:transparent'
     );
    };
    const info = (textOrTitle: string, content = '') => {
         
     const title = isEmpty(content) ? 'Info' : textOrTitle;
     const text = isEmpty(content) ? textOrTitle : content;
     prettyPrint(title, text, '#909399');
    };
    const error = (textOrTitle: string, content = '') => {
         
     const title = isEmpty(content) ? 'Error' : textOrTitle;
     const text = isEmpty(content) ? textOrTitle : content;
     prettyPrint(title, text, '#F56C6C');
    };
    const warning = (textOrTitle: string, content = '') => {
         
     const title = isEmpty(content) ? 'Warning' : textOrTitle;
     const text = isEmpty(content) ? textOrTitle : content;
     prettyPrint(title, text, '#E6A23C');
    };
    const success = (textOrTitle: string, content = '') => {
         
     const title = isEmpty(content) ? 'Success ' : textOrTitle;
     const text = isEmpty(content) ? textOrTitle : content;
     prettyPrint(title, text, '#67C23A');
    };
    // const data = [
    //   { id: 1, name: 'Alice', age: 25 },
    //   { id: 2, name: 'Bob', age: 30 },
    //   { id: 3, name: 'Charlie', age: 35 }
    // ];
    const table = (data: Array<any>) => {
         
     console.log(
       '%c id%c name%c age',
       'color: white; background-color: black; padding: 2px 10px;',
       'color: white; background-color: black; padding: 2px 10px;',
       'color: white; background-color: black; padding: 2px 10px;'
     );
     data.forEach((row: any) => {
         
       console.log(
         `%c ${
           row.id} %c ${
           row.name} %c ${
           row.age} `,
         'color: black; background-color: lightgray; padding: 2px 10px;',
         'color: black; background-color: lightgray; padding: 2px 10px;',
         'color: black; background-color: lightgray; padding: 2px 10px;'
       );
     });
    };
    const picture = (url: string, scale = 1) => {
         
     if (isProduction) return;
     const img = new Image();
     img.crossOrigin = 'anonymous';
     img.onload = () => {
         
       const c = document.createElement('canvas');
       const ctx = c.getContext('2d');
       if (ctx) {
         
         c.width = img.width;
         c.height = img.height;
         ctx.fillStyle = 'red';
         ctx.fillRect(0, 0, c.width, c.height);
         ctx.drawImage(img, 0, 0);
         const dataUri = c.toDataURL('image/png');
         console.log(
           `%c sup?`,
           `font-size: 1px;
           padding: ${
           Math.floor((img.height * scale) / 2)}px ${
           Math.floor((img.width * scale) / 2)}px;
           background-image: url(${
           dataUri});
           background-repeat: no-repeat;
           background-size: ${
           img.width * scale}px ${
           img.height * scale}px;
           color: transparent;
           `
         );
       }
     };
     img.src = url;
    };
    
    return {
         
     info,
     error,
     warning,
     success,
     picture,
     table
    };
    };
    

    最后
    通过以上步骤,我们可以建立一个前端项目的日志输出规范。一个好的日志系统应该是灵活的,能够根据不同的环境和需求进行适当的调整。日志是帮助我们更好地理解和维护应用的工具,合理的使用和管理日志对于任何规模的前端项目都是非常重要的。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3月前
|
存储 监控 数据库
Django 后端架构开发:高效日志规范与实践
Django 后端架构开发:高效日志规范与实践
59 1
|
19天前
|
前端开发 JavaScript 测试技术
前端研发链路之代码规范
大家好,我是徐徐。本文将探讨前端研发链路中的代码规范,包括业界流行规范、CSS命名规范和相关工具。通过保持代码整洁和一致性,不仅能提高团队协作效率,还能减少错误,提升开发质量。文中详细对比了几种常见的代码规范和工具,如 Airbnb Style Guide、BEM、Eslint 和 Prettier,并展望了未来代码规范的发展趋势。希望对大家有所帮助。
55 1
前端研发链路之代码规范
|
19天前
|
前端开发 测试技术
如何从零到一建立前端规范
【10月更文挑战第6天】
42 2
|
26天前
|
前端开发 开发工具 git
如何清理 docker 磁盘空间+修改 Gitea 服务器的 Webhook 设置+前端一些好学好用的代码规范-git hook+husky + commitlint
如何清理 docker 磁盘空间+修改 Gitea 服务器的 Webhook 设置+前端一些好学好用的代码规范-git hook+husky + commitlint
26 5
|
13天前
|
前端开发 JavaScript 开发工具
前端代码规范和质量是确保项目可维护性、可读性和可扩展性的关键(三)
前端代码规范和质量是确保项目可维护性、可读性和可扩展性的关键(三)
22 0
|
13天前
|
Web App开发 前端开发 JavaScript
前端代码规范和质量是确保项目可维护性、可读性和可扩展性的关键(二)
前端代码规范和质量是确保项目可维护性、可读性和可扩展性的关键(二)
29 0
|
13天前
|
Web App开发 移动开发 前端开发
前端代码规范和质量是确保项目可维护性、可读性和可扩展性的关键(一)
前端代码规范和质量是确保项目可维护性、可读性和可扩展性的关键(一)
32 0
|
26天前
|
前端开发 开发工具 git
搭建Registry&Harbor私有仓库、Dockerfile(八)+前端一些好学好用的代码规范-git hook+husky + commitlint
搭建Registry&Harbor私有仓库、Dockerfile(八)+前端一些好学好用的代码规范-git hook+husky + commitlint
18 0
|
3月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
|
3月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以在控制台输出日志的问题如何解决
Java应用结构规范问题之配置Logback以在控制台输出日志的问题如何解决