成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

前端日志管理模塊的設計與實現

開發 前端
給團隊封裝一個簡單統一的日志管理工具/模塊,來替換掉項目中野蠻生長的 console.log()吧!

一、問題背景

在項目中,我們會頻繁用到 ??console.log()?? 來輸出一些關鍵信息到控制臺中,有助于開發調試,以及問題的排查,待項目上線后,這些調試日志又得及時清除。

同時在前端質量要求下,我們會做“前端埋點”,用于遠程上報一些關鍵行為信息,用于在出問題時還原用戶的操作路徑,復現 BUG,從而解決問題,而各種各樣的上報若是能在業務開發中抹平差異,也有助于研發提效。

因此,有必要在團隊中封裝日志工具(Logger),用于統一管理日志輸出和格式化上報,降低開發者對多平臺上報差異的心智負擔。

二、需求概述

預期日志管理工具(Logger)需要有如下能力:

  1. 支持區分??info???、??warn???、??error?? 三種本地調試類型日志
  2. 支持遠程上報自定義日志??report()??
  3. 支持設置 namespace,用于區分代碼執行的 scope
  4. 支持鏈式操作
  5. 區分生產環境和開發環境,生產環境禁止輸出日志到控制臺
  6. 支持功能可擴展

三、方案設計

在閱讀完 Axios 的源碼后,個人認為 Axios 里對于設計模式的應用是非常靈活,同理,一個好的日志工具也應當遵守著一定的軟件設計模式原則。

作為項目中用到的日志工具,單例模式應當是更適合的選擇!

Logger 的打印輸出能力,本質上還是借助了 ??window.console?? 對象中的方法:

圖片Console 對象

在面向對象編程中,我們可以認為 ??console?? 是一個已經初始化的實例,同時也是一個單例,因為它是全局唯一。

而單例模式的最大好處就是全局唯一,對于做日志統一管理有著天然的友好支持基礎。

四、實現細節 ??

接下來通過具體的代碼,來逐一實現并完善我們的 Logger 日志工具類。

1、ES Module 下的單例模式

在 ESM 規范下,我們可以直接通過直接導出實例方式(??export default new ClassName()??),來實現單例模式。

Logger 的基礎結構就有了:

/**
* 日志打印工具,統一管理日志輸出&上報
*/
class Logger {
/** 命名空間(scope),用于區分所在執行文件 */
private namespace: string

constructor(namespace = 'unknown') {
this.namespace = namespace
}
}
export default new Logger()

2、可擴展的單例模式

參考 Axios 的設計[1],因此我們還提供 ??create()?? 方法,為創建新實例留一個入口方法。

/**
* 創建新的 Logger 實例
*
* @param namespace 命名空間
* @returns Logger
*/
public create(namespace = 'unknown') {
return new Logger(namespace);
}

當需要重新定義一個 logger 實例時,就可以參考如下方式:

import logger from '@/utils/logger'
const newLogger = logger.create('custom')
logger.info(newLogger === logger) // [unknown] false

3、定義“打印”類日志方法

需要區分 ??info???、??warn???、??error?? 三種類型的日志,實現如下:

定義日志枚舉類型:

const enum LogLevel {
/** 普通日志 */
Log,
/** 警告日志 */
Warning,
/** 錯誤日志 */
Error,
}

const Styles = ['color: green;', 'color: orange;', 'color: red;']
const Methods = ['info', 'warn', 'error'] as const
private _log(level: LogLevel, args: unknown[]) {
if (!__DEV__) return
console[Methods[level]](`%c${this.namespace}`, Styles[level], ...args)
}
/**
* 打印輸出信息 ??
*
* @param args 任意參數
*/
public info(...args: unknown[]) {
this._log(LogLevel.Log, args)
return this
}
/**
* 打印輸出警告信息 ?
*
* @param args 任意參數
*/
public warn(...args: unknown[]) {
this._log(LogLevel.Warning, args)
return this
}
/**
* 打印輸出錯誤信息 ?
*
* @param args 任意參數
*/
public error(...args: unknown[]) {
this._log(LogLevel.Error, args)
return this
}

在 ??_log()??? 方法中,通過 ??__DEV__?? 環境變量區分“生產”和“開發”:

if (!__DEV__) return

這種變量可以理解為“開關”:

生產環境則控制臺不輸出信息,在實際應用中,可以擴展“是否輸出信息”的變量,來針對性擴展,例如線上需要通過特定參數展示調試日志,用于線上定位問題,那么就可以綜合多個條件來決定是否輸出控制臺,畢竟編程最核心的問題是解決需求。

在開發模式下,針對不同的信息類型,會標注不同的顏色:

圖片

圖片Chrome 瀏覽器下的效果

與此同時,在每個“輸出”方法中都返回了 ??this??(當前實例),因而便可以為鏈式調用方法提供了使用基礎。

4、支持修改 namespace

namespace 最重要的作用是:區分在不同組件或文件下的日志,便于問題定位排查。

由于 ??Logger??? 將所有的輸出集中到了統一文件,在 ??console.log()??? 中文件定位永遠是 ??Logger?? 類定義實現所在文件,因此需要 namespace 來區分。

新增 ??setNamespace()?? 方法:

/**
* 設置命名空間(日志前綴)
* @param namespace
*/
public setNamespace(namespace = '') {
this.namespace = `[${namespace}]`
return this
}

在 TypeScript 環境下,會提供代碼提示,例如某個文件下輸出錯誤信息的方式:

圖片

而 ??setNamespace()?? 方法,并不是每次都需要調用的,只需在文件中調用一次即可。

5、埋點遠程上報

在一些關鍵時機,例如進入頁面、點擊“付費按鈕”等一些關鍵操作上,一般會加上一些上報到遠程,用于記錄用戶操作路徑,以此便于在出現問題后,復現 BUG 并“對癥下藥”。

而埋點上報一般有三類:代碼埋點、可視化埋點、無痕埋點。

我們這里通過給 Logger 增加遠程上報的方式就是代碼埋點。

一般情況下,埋點上報屬于“前端監控”方面,前端監控是一個獨立的管理系統,它的職能是負責前端項目的監控、異常報警等,因此通常會有用于項目集成的前端 SDK

有了 Logger 實例,我們可以在 Logger 中直接統一集成“前端監控 SDK”的主動上報方法即可!

在 Logger 類中新增三個方法:

  • ??reportLog()??:上報日志。
  • ??reportEvent()??:上報事件。
  • ??reportException()??:上報異常。
/**
* 遠程上報
* TODO: 根據基建環境自定義擴展
*/
public reportLog() {
this.info() // 用于在本地輸出
}
public reportEvent() {
this.info()
}
public reportException() {
this.error()
}

至于為什么添加著兩個方法,實際是根據“前端監控 SDK”提供的 API 來決定

例如常見的 “Sentry - 應用監控錯誤溯源[2]” 平臺,針對主動上報,提供了三種方法,通常為了保持一致性,降低心智負擔,因此新增對應的三個上報方法。

具體的上報參數和邏輯,則需要大家根據自己的業務區擴展。

五、Logger 的可擴展性 ??

從上面 Logger 類的實現,可以發現一個明顯的問題,如果業務需要擴展功能,則需要修改 Logger 類內部的方法,Logger 類中的方法和邏輯,我們可以理解為是所有業務都通用的,業務定制化的功能應該通過額外擴展方式來完善。

那有沒有什么辦法,可以實現不修改方法,而擴展 Logger 的功能吶?

1、擴展方案

有幾個方案:

  1. 繼承 Logger 類擴展。
  2. 增加回調函數作為參數。

個人推薦第二個方案,但如果每一次調用,都按照如下方式:

logger.info('message', () => {})

但這種設計比較粗糙

2、攔截器

參考 Axios 的攔截器設計,也就是 AOP(面向切面編程模式)的設計思想,來擴展 ??_log()?? 方法。

新增類型申明:

/**
* 日志的配置類型
*/
type LoggerConfigType = {
/** 命名空間 */
namespace?: string
}
/**
* 攔截器函數類型
*/
type InterceptorFuncType = (config: LoggerConfigType) => void

將 Logger 的配置集中的 ??config??? 私有變量中,并新增 ??addBeforeFunc()??? 和 ??addAfterFunc()?? 兩個方法,用于新增自定義“攔截器”函數

圖片

其中一個細節是,日志打印之后的攔截器,按照FCLS(First Come Last Serve,先到后服務)的策略,和 Axios 的響應攔截器執行順序對齊,與此同時,攔截器函數中會注入當前 Logger 的 ??config?? 配置。

通過簡單的“攔截器”,即可實現功能的擴展,這種方式的功能擴展不會影響到主體功能,后期的維護升級是無侵入性的,還算比較優雅的,是吧!

3、其他方案

這里還可以考慮更多設計,例如參考發布訂閱設計模式來改造,通過生命周期的關鍵點,被動觸發,主動通知并執行所有訂閱了對應消息的事件,可以參閱《聊一聊發布訂閱設計模式[3]

也可以用插件模式方式來實現擴展,類似發布訂閱模式,給 ??_log()?? 函數添加執行的鉤子函數??(回調函數),例如這種設計下,把“埋點上報”等功能拆分成插件,再實現一個簡單的事件隊列模型,集成一下子!

六、總結

至此,一個基本的日志工具就實現完成了,但并未完完全全遵守設計原則,這里在生產實踐中還需要封裝、抽離相應“職責”,增加可維護性。

在團隊中以此作為基礎結構,然后針對團隊、項目、業務的特點做適當的擴展,構建符合當前團隊特性的通用日志工具模塊,應該也不是什么難事!

責任編輯:姜華 來源: DYBOY
相關推薦

2023-12-07 07:02:00

大倉權限設計

2010-02-26 13:14:39

Java日志系統

2013-08-20 15:31:18

前端模塊化

2012-08-20 10:24:15

ASP.NET

2025-04-27 01:05:00

AI智能日志

2016-09-29 09:57:08

JavascriptWeb前端模板

2017-07-26 14:50:37

前端模板

2022-09-13 15:33:48

KubeEdge邊緣計算容器

2015-08-20 10:23:23

前端代碼日志收集

2014-04-27 10:16:31

QCon北京2014Andrew Bett

2009-08-13 10:19:43

Linux系統Nagios網絡管理模塊

2019-05-16 09:00:06

云原生監控日志管理

2012-09-06 09:31:14

PHPmysqlpdo

2011-03-21 11:14:23

LinuxNagios

2015-11-03 09:28:52

Hybrid技術設計實現

2020-10-23 08:31:15

Nodejs-Ipc設計實現

2022-09-12 07:17:20

redis命令redissynce

2023-05-26 08:24:17

短信渠道模型

2015-06-30 11:05:11

flexibleWebAPP設計

2022-09-14 09:37:22

數據系統
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美一级α片 | 亚洲精品自在在线观看 | 成人三级网址 | 国产女人叫床高潮大片免费 | 日韩理论电影在线观看 | 91视频.com | 国产高清视频 | 欧美精品第一区 | 成人伊人网 | 久久综合九色综合欧美狠狠 | 日韩视频 中文字幕 | 国产一区二区欧美 | 福利社午夜影院 | 久久精品国产免费一区二区三区 | 在线一区视频 | av黄色国产 | 狠狠爱免费视频 | 久久精品国产一区二区电影 | 欧美a级成人淫片免费看 | 97人人澡人人爽91综合色 | 先锋影音资源网站 | 国产粉嫩尤物极品99综合精品 | 国产精品国产a | 青春草91 | 精品一区二区在线观看 | 成人精品一区二区三区中文字幕 | 亚洲一区二区精品视频 | 国产一区二区精品在线 | 亚洲视频免费在线观看 | 中文字幕亚洲视频 | 精品国产18久久久久久二百 | 欧美一级淫片免费视频黄 | 精品一区二区久久久久久久网站 | 中文字幕av免费 | 操操日 | 久久久亚洲一区 | 久久久久久国产精品 | 日韩综合在线视频 | 日韩电影中文字幕 | 久久久视 | 欧美精品一区二区三区在线播放 |