• 基于 WebWorker 和 indexedDB 的高性能、高容量、高扩展的web端日志系统


    idb-logger

    stars forks version downloads jsdelivr issue

    author license Size TopLang Dependent test

    🚀 基于 WebWorker 和 indexedDB 的高性能、高容量、高扩展的web端日志系统

    在线使用 | English | 更新日志 | 问题反馈 | Gitee

    0. 介绍

    idb-logger 致力于帮助web开发者便捷高效的接入高性能的日志系统,依托于webworker和indexedDB技术,web应用可以已几乎不影响用户体验的方式在浏览器中存入大容量的日志,并且在合适的时机上报到服务端,或者由用户自行下载。

    0.1 特性

    1. 支持 WebWorker + indexedDB 存储日志
    2. 可选三种日志存储模式,且当不支持时会自动向下选择支持的模式
    3. 支持不存储模式,只使用idb-logger作为日志生成工具
    4. 支持定义最大存储日志数量,会自动删除最早的记录
    5. 支持下载日志
    6. 支持查询日志,支持多种查询模式
    7. 支持自定义基础数据
    8. 支持基于onReport回调自定义上报

    1. 快速使用

    1.0 install

    1.0.1 npm install

    npm i idb-logger
    
    • 1
    import Logger from 'idb-logger';
    
    • 1

    1.0.2 cdn

    <script src="https://cdn.jsdelivr.net/npm/idb-logger/idb-logger.min.js">script>
    <script>
      window.IDBLogger;
    script>
    
    • 1
    • 2
    • 3
    • 4

    1.1 快速使用

    const logger = new Logger();
    
    logger.log('一条普通日志');
    logger.error('一条错误日志', '附加信息', {type: '附加信息'});
    
    logger.download(); // 下载日志
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1.2. api 介绍

    ts声明:

    declare class Logger {
        static version: string;
        private _store;
        id: string;
        storeType: TLogStoreType;
        constructor({ id, useConsole, storeType, maxRecords, baseInfo, onReport, onDiscard, }?: ILoggerOption);
        injectBaseInfo(baseInfo?: IBaseInfoOption & IJson): Promise<void>;
        log(...args: any[]): Promise<IAddReturn>;
        error(...args: any[]): Promise<IAddReturn>;
        warn(...args: any[]): Promise<IAddReturn>;
        info(...args: any[]): Promise<IAddReturn>;
        private _logCommon;
        close(): Promise<boolean>;
        destory(): Promise<boolean>;
        clear(): Promise<boolean>;
        count(): Promise<number>;
        delete(logid: string): Promise<boolean>;
        refreshTraceId(): Promise<void>;
        refreshDurationStart(): Promise<void>;
        download({ name, filter }?: {
            name?: string;
            filter?: TFilterOption;
        }): Promise<number>;
        get(logid: string): Promise<ILogDBData | null>;
        getAll(): Promise<ILogDBData[]>;
        filter(filter?: TFilterOption): Promise<ILogDBData[]>;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    完整的 logdata

    interface ILogDBData {
        uid: string; // 用户id 会存储在storage中
        clientid: string; // 客户端id 会存储在storage中
        traceid: string; // 本次访问id,可以通过 refreshTraceId 刷新
        network: string; // 网络状况
        url: string; // 当前url
        ua: string; // 浏览器ua
    
        msg: string; // 消息类型,如果log第一个参数是字符串,则取该值
        payload?: any; // log的其他参数
        type: TLogType; // log info warn error
        duration: number; // 页面进入到当前日志的时间,可以通过 refreshDurationStart 刷新计时七点
        time: string; // 时间字符串
        timestamp: number; // 时间戳
        logid: string; // 日志唯一id
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    1.2.1 构造函数

    new Logger({
      id, // 指定数据库名称 默认值:default
      useConsole, // 是否打印到控制台 默认 true
      storeType, // 存储模式,默认 idb,支持 idb storage temp none
      maxRecords, // 最大存储记录数 默认10000
      baseInfo, // 注入自定义的基础信息
      onReport, // 当生成日志时触发,可用于自定义上报数据
      onDiscard // 当达到 maxRecords 时触发,丢弃掉的数据
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1. storeType

    idb 表示使用indexedDB存储日志,storage 表示使用 localStorage进行存储日志,temp 表示使用js变量存储数据(非持久化),none表示不存储数据(仅将idb-logger作为日志生成工具)

    默认值为idb,当某个存储类型浏览器不支持时,会自动向后选用下一个模式

    1. maxRecords

    为了降低客户端性能消耗,可以指定一个最大存储数量,当超过这个数量时,logger会自动删除最早的记录并且 触发 onDiscard 回调

    1. baseInfo

    接受一个json,用于注入日志的基础信息,当与默认baseInfo命名一致时会覆盖默认的baseInfo

    默认的baseInfo clientid, uid, traceid, network, url, ua

    1.2.2 打日志

    logger对象上有四个方法:log,error, warn,info

    使用方法类似支持传入任意数量、任意类型的数据

    参数规则

    1. 当第一个参数是 字符串或者数字时,该参数作为log的msg字段,后面的所有参数合并成一个数组作为payload属性
    2. 当第一个参数json时且仅有一个参数,会将该json中的所有属性覆盖到log的属性上
    3. 当第一个参数不是数字或字符串,会将默认值__def__作为msg,所有参数合并成一个数组作为payload属性
    await logger.log('start'); // 返回Promise<{discard, add}> add 是添加的日志数据。该调用方式符合规则1
    await logger.info({
        msg: 'start', // 写入message
        time: 'xxxx', // 覆盖log的属性
        your_custom: 'xxxx', // 自定义属性
    }); // 该调用方式符合规则2
    await logger.warn({}, [], '', 1); // 该调用方式符合规则3
    await logger.error('error', {}, [], '', 1); // 该调用方式符合规则1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    1.2.3 查询

    await logger.filter(filter); // 返回Promise
    
    • 1

    filter 支持三种模式

    1. 过滤器

    支持传入一个函数 (data: ILogDBData) => boolean,回调函数是日志数据,返回 true 或者 false 表示是否该条数据命中

    注意: 在indexedDB模式中,由于会将函数传到 worker中执行,要求函数中不能调用其他方法或者worker中不支持的特性

    await logger.filter(item=>{
        return item.msg.includes('xxx') && item.type === 'log';
    })
    
    • 1
    • 2
    • 3
    1. AND (传入json)

    传入一个json,每个属性之间会使用 and 串起来, 支持正则表达式

    await logger.filter({
        msg: /xxx/i,
        type: 'log',
    })
    
    • 1
    • 2
    • 3
    • 4
    1. OR (传入json数组)

    传入一个json数组,数组中每个元素之间或使用 or 逻辑串起来,元素内属性之间使用 and 逻辑,与 2 中一致

    await logger.filter([{
        msg: /xxx/i,
    }, {
        type: 'log',
    }])
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上面语句表示日志中 msg含有xxx 或者 type等于log

    1.2.4 下载

    下载indexedDB中存储的日志

    await logger.download({
      name, // 下载文件的名字
      filter, // 同 1.2.3 中的 filter
    });
    
    • 1
    • 2
    • 3
    • 4

    1.2.5 其他api

    1.2.5.1 getAll

    获取全部日志

    await logger.getAll();
    
    • 1
    1.2.5.1 get

    根据日志id获取某条日志

    await logger.getAll(logid);
    
    • 1
    1.2.5.1 count

    获取日志数量

    await logger.count();
    
    • 1
    1.2.5.1 delete

    根据日志id删除某条日志

    await logger.delete(logid);
    
    • 1
    1.2.5.1 injectBaseInfo

    注入日志基础信息

    await logger.injectBaseInfo({
        network: 'wifi',
        phone: 'xxxx',
    });
    
    • 1
    • 2
    • 3
    • 4
    1.2.5.1 refreshTraceId

    刷新traceid,一般用于重连等,认为是第二次访问的场景

    同时也会 refreshDurationStart

    await logger.refreshTraceId();
    
    • 1
    1.2.5.1 refreshDurationStart

    刷新计时起点,一般用于需要重新统计时间的场景

    await logger.refreshTraceId();
    
    • 1
    1.2.5.1 close

    关闭数据库

    await logger.close();
    
    • 1
    1.2.5.1 clear

    关闭并且清空数据库

    await logger.clear();
    
    • 1
    1.2.5.1 destory

    关闭、清空并且删除数据库

    await logger.destory();
    
    • 1
  • 相关阅读:
    1152:最大数max(x,y,z)
    14:00面试,14:06就出来了,问的问题有点变态。。。
    A02-HTML5入门
    springcloud-GateWay设计
    Idea代码上传至Git完整教程(阿里云)
    简单讲讲在一台机器上用docker部署hadoop HDFS
    Elasticsearch学习-文档更新,可能存在的坑
    论文阅读: 面向Planning的端到端智驾Planning-oriented Autonomous Driving
    惠普战99移动工作站: 第十三代英特尔酷睿处理器和惠普一站式AI应用开发方案的完美融合
    【sciter】sciter 拖拽过程总结
  • 原文地址:https://blog.csdn.net/yanxiaomu/article/details/126296408