领导被我的花式console.log吸引了!直接写入公司公共库!

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【8月更文挑战第23天】领导被我的花式console.log吸引了!直接写入公司公共库!

背景简介

这几天代码评审,无意中看到了我本地代码的控制台,被我花里胡哨的打印内容吸引了!
image.png
老板看见后,说我这东西有意思,花里胡哨的,他喜欢!但是随即又问我,这么花里胡哨的东西,上生产会影响性能吧?我自信的说:不会,代码内有判断的,只有开发环境会打印!

老板很满意,于是让我给其他前端同事分享一下,讲解下实现思路!最终,这个方法还被写入公司的公用utils库里,供大家使用!

console简介

console 是一个用于调试和记录信息的内置对象, 提供了多种方法,可以帮助开发者输出各种信息,进行调试和分析。
console.log()
用于输出一般信息,大家应该在熟悉不过了。
image.png
console.info():
输出信息,与 console.log 类似,但在某些浏览器中可能有不同的样式。
image.png
console.warn():
输出警告信息,通常会以黄色背景或带有警告图标的样式显示。
image.png
console.error():
输出错误信息,通常会以红色背景或带有错误图标的样式显示。
image.png
console.table():
以表格形式输出数据,适用于数组和对象。
例如:

const users = [
    {
   
    name: '石小石', age: 18 },
    {
   
    name: '刘亦菲', age: 18 }
];
console.table(users);

image.png

通过上述介绍,我们可以看出,原生的文本信息、警告信息、错误信息、数组信息打印出来的效果都很普通,辨识度不高!现在我们通过console.log来实现一些花里花哨的样式!

技术方案

console.log()

console.log() 可以接受任何类型的参数,包括字符串、数字、布尔值、对象、数组、函数等。最厉害的是,它支持占位符!
常用的占位符:

  • %s - 字符串
  • %d or %i - 整数
  • %f - 浮点数
  • %o - 对象
  • %c - CSS 样式

    格式化字符串

    console.log() 支持类似于 C 语言 printf 函数的格式化字符串。我们可以使用占位符来插入变量值。
    const name = 'Alice';
    const age = 30;
    console.log('Name: %s, Age: %d', name, age); // Name: Alice, Age: 30
    

    添加样式

    可以使用 %c 占位符添加 CSS 样式,使输出内容更加美观。
    console.log('%c This is a styled message', 'color: red; font-size: 20px;');
    
    image.png

自定义样式的实现,其实主要是靠%c 占位符添加 CSS 样式实现的!

实现美化的信息打印

基础信息打印

我们创建一个prettyLog方法,用于逻辑编写

// 美化打印实现方法
const prettyLog = () => {
   
   
  const isEmpty = (value: any) => {
   
   
    return value == null || value === undefined || value === '';
  };
  const prettyPrint = (title: string, text: string, color: string) => {
   
   
    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');
  };
  return {
   
   
    info
  };
};

上述代码定义了一个 prettyLog 函数,用于美化打印信息到控制台。通过自定义样式,输出信息以更易读和美观的格式呈现。
我们使用一下看看效果

// 创建打印对象
const log = prettyLog();

// 不带标题
log.info('这是基础信息!');

//带标题
log.info('注意看', '这是个男人叫小帅!');
                 ![image.png](https://cdn.nlark.com/yuque/0/2024/png/21865277/1716362942108-e08a00ce-b42d-406a-960d-bb4651d00da1.png#averageHue=%232d251e&clientId=u3566903c-e51a-4&from=paste&height=116&id=uc8863ae0&originHeight=116&originWidth=473&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9194&status=done&style=none&taskId=u509ad53e-fc89-4629-b073-ff4b98d7c4a&title=&width=473)

info 方法用于输出信息级别的日志。它接受两个参数:textOrTitle 和 content。如果只提供一个参数,则视为内容并设置默认标题为 Info;如果提供两个参数,则第一个参数为标题,第二个参数为内容。最后调用 prettyPrint 方法进行输出。

错误信息打印

const prettyLog = () => {
   
   
    const isEmpty = (value: any) => {
   
   
        return value == null || value === undefined || value === '';
    };
    const prettyPrint = (title: string, text: string, color: string) => {
   
   
         // ...
    };
    const info = (textOrTitle: string, content = '') => {
   
   
        // ...
    };
    const error = (textOrTitle: string, content = '') => {
   
   
        const title = isEmpty(content) ? 'Error' : textOrTitle;
        const text = isEmpty(content) ? textOrTitle : content;
        prettyPrint(title, text, '#F56C6C');
    };
    // retu;
    return {
   
   
        info,
        error,
    };
};
// 创建打印对象
const log = prettyLog();

log.error('奥德彪', '出来的时候穷 生活总是让我穷 所以现在还是穷。');

log.error('前方的路看似很危险,实际一点也不安全。');
      ![image.png](https://cdn.nlark.com/yuque/0/2024/png/21865277/1716363738564-78a097f5-9ef6-4b62-ac7d-6553b35d5d9f.png#averageHue=%233d2b25&clientId=u3566903c-e51a-4&from=paste&height=96&id=u87b21477&originHeight=96&originWidth=516&originalType=binary&ratio=1&rotation=0&showTitle=false&size=14304&status=done&style=none&taskId=uc548630c-5009-456f-86a7-29a94223f59&title=&width=516)

成功信息与警告信息打印

// 美化打印实现方法
const prettyLog = () => {
   
   
    const isEmpty = (value: any) => {
   
   
        return value == null || value === undefined || value === '';
    };
    const prettyPrint = (title: string, text: string, color: string) => {
   
   
        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');
    };
    // retu;
    return {
   
   
        info,
        error,
        warning,
        success
    };
};
// 创建打印对象
const log = prettyLog();

log.warning('奥德彪', '我并非无路可走 我还有死路一条! ');

log.success('奥德彪', '钱没了可以再赚,良心没了便可以赚的更多。 ');

image.png

实现图片打印

// 美化打印实现方法
const prettyLog = () => {
   
   
  // ....
  const picture = (url: string, scale = 1) => {
   
   
    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
  };
}

// 创建打印对象
const log = prettyLog();

log.picture('https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2024%2F0514%2Fd0ea93ebj00sdgx56001xd200u000gtg00hz00a2.jpg&thumbnail=660x2147483647&quality=80&type=jpg');

image.png
上述代码参考了其他文章:Just a moment...

url可以传支持 base64,如果是url链接,图片链接则必须开启了跨域访问才能打印

实现美化的数组打印

打印对象或者数组,其实用原生的console.table比较好

const data = [
  {
   
    id: 1, name: 'Alice', age: 25 },
  {
   
    id: 2, name: 'Bob', age: 30 },
  {
   
    id: 3, name: 'Charlie', age: 35 }
];

console.table(data);

image.png
当然,我们也可以伪实现

const table = () => {
    const data = [
        { id: 1, name: 'Alice', age: 25 },
        { id: 2, name: 'Bob', age: 30 },
        { id: 3, name: 'Charlie', age: 35 }
    ];
    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;'
        );
    });
};

image.png
但是,我们无法控制表格的宽度,因此,这个方法不太好用,不如原生。

仅在开发环境使用

// 美化打印实现方法
const prettyLog = () => {
   
   
  //判断是否生产环境
  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;
    // ...
  };
  // ...
  const picture = (url: string, scale = 1) => {
   
   
    if (isProduction) return;
    // ...
    };

    // retu;
    return {
   
   
        info,
        error,
        warning,
        success,
        picture,
        table
    };
};

我们可以通过import.meta.env.MODE 判断当前环境是否为生产环境,在生产环境,我们可以禁用信息打印!

完整代码

// 美化打印实现方法
const prettyLog = () => {
   
   
    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 table = () => {
   
   
        const data = [
            {
   
    id: 1, name: 'Alice', age: 25 },
            {
   
    id: 2, name: 'Bob', age: 30 },
            {
   
    id: 3, name: 'Charlie', age: 35 }
        ];
        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;
    };

    // retu;
    return {
   
   
        info,
        error,
        warning,
        success,
        picture,
        table
    };
};
// 创建打印对象
const log = prettyLog();
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
2月前
|
存储 运维 监控
超级好用的C++实用库之日志类
超级好用的C++实用库之日志类
41 0
|
3月前
|
JSON 中间件 Go
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
本文详细介绍了如何在Go项目中集成并配置Zap日志库。首先通过`go get -u go.uber.org/zap`命令安装Zap,接着展示了`Logger`与`Sugared Logger`两种日志记录器的基本用法。随后深入探讨了Zap的高级配置,包括如何将日志输出至文件、调整时间格式、记录调用者信息以及日志分割等。最后,文章演示了如何在gin框架中集成Zap,通过自定义中间件实现了日志记录和异常恢复功能。通过这些步骤,读者可以掌握Zap在实际项目中的应用与定制方法
135 1
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
|
3月前
|
Linux API
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
|
3月前
|
存储 JSON 前端开发
一文搞懂 Go 1.21 的日志标准库 - slog
一文搞懂 Go 1.21 的日志标准库 - slog
116 2
|
3月前
|
JSON Go API
一文搞懂 Golang 高性能日志库 - Zap
一文搞懂 Golang 高性能日志库 - Zap
232 2
|
3月前
|
存储 安全 Python
[python]使用标准库logging实现多进程安全的日志模块
[python]使用标准库logging实现多进程安全的日志模块
|
4月前
|
测试技术 UED 存储
SLS Prometheus存储问题之在使用内置降采样时,SLS自动选择适配的指标库该如何解决
SLS Prometheus存储问题之在使用内置降采样时,SLS自动选择适配的指标库该如何解决
|
3月前
|
存储 JSON Go
一文搞懂 Golang 高性能日志库 Zerolog
一文搞懂 Golang 高性能日志库 Zerolog
352 0
|
5月前
spdlog 日志库部分源码说明——让你可以自定义的指定自动切换日志时间
spdlog 日志库部分源码说明——让你可以自定义的指定自动切换日志时间
140 7
|
5月前
|
C++
spdlog 日志库部分源码说明——日志格式设定,DIY你自己喜欢的调试信息,你能调试的远比你想象的还要丰富
spdlog 日志库部分源码说明——日志格式设定,DIY你自己喜欢的调试信息,你能调试的远比你想象的还要丰富
299 6