npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@evertro/monitor-transport

v1.1.1

Published

Evertro Monitor 数据上报传输层

Downloads

698

Readme

@evertro/monitor-transport

Evertro Monitor 数据上报传输层 — 队列管理、批处理、重试、离线缓存

概述

本包负责将引擎产出的 MonitorEvent 通过网络发送到后端,是 SDK 的出口层。核心能力:

  1. 上报队列 — 按优先级分级处理(P0 即时、P1 批量、P2 定时)
  2. Payload 格式转换 — 将内部事件结构转换为旧 APM SDK 的扁平格式
  3. 批处理器 — 将事件切分为固定大小的批次上报
  4. 重试策略 — 指数退避重试,失败后自动存入离线缓存
  5. 离线缓存 — 上报失败时持久化到 localStorage/wx.setStorageSync
  6. 传输适配器 — 提供 WeappTransport(wx.request)和 H5Transport(fetch/XHR)两种实现

安装

pnpm add @evertro/monitor-transport

模块说明

reportQueue.ts — 上报队列(核心)

管理事件的入队、分级处理和上报调度。

import { ReportQueue } from '@evertro/monitor-transport';

const queue = new ReportQueue(
  transport,         // 传输适配器(WeappTransport 或 H5Transport)
  config,            // MonitorConfig
  getContext,        // () => MonitorContext
  getSessionId,      // () => string
  offlineStorage     // 可选,离线缓存实例
);

queue.start();          // 启动定时上报(按 reportInterval)
queue.enqueue(event);   // 添加事件(P0 立即发,P1/P2 入队)
queue.flush();          // 手动触发 flush(如 app.onHide 时)
queue.stop();           // 停止定时上报
queue.length;           // 当前队列长度

事件分级处理策略

| 优先级 | 处理方式 | 典型事件 | |--------|---------|---------| | P0 IMMEDIATE | 立即单条上报(不入队) | 白屏、崩溃 | | P1 BATCH | 入队,满 batchSize 条后自动 flush | JS 错误、Promise 拒绝 | | P2 SCHEDULED | 入队,等定时器触发 flush | 性能数据、操作链路 |

createPayload() — 载荷构建

MonitorEvent[] 转换为旧 APM SDK 的扁平结构:

MonitorEvent[] (内部格式)
       │
       ├── context.device → 打平到外层 (screenHeight, os, networkType...)
       ├── context.user   → 打平到外层 (userId, visitorId...)
       └── events → toReportEvent() 转换为 ReportEvent[] 格式
                     (eventId + eventName + eventCode + eventTime + attr)

并发安全

使用 flushing 锁防止并发 flush 导致事件重复上报或丢失:

flush() 被调用
  └─ if (flushing) return;  // 其他 flush 正在执行,跳过
  └─ flushing = true;
  └─ try { ... } finally { flushing = false; }

batchProcessor.ts — 批处理器

将事件数组按固定大小切分为多个批次。

import { BatchProcessor } from '@evertro/monitor-transport';

const processor = new BatchProcessor(10); // 每批最多 10 条
const batches = processor.process(events);
// events = [e1, e2, ..., e15]
// batches = [[e1..e10], [e11..e15]]

retryStrategy.ts — 重试策略

指数退避重试机制。

import { RetryStrategy } from '@evertro/monitor-transport';

const retry = new RetryStrategy(3); // 最多重试 3 次
const success = await retry.execute(() => transport.send(payload));
// 第 1 次失败 → 等 1s → 第 2 次失败 → 等 2s → 第 3 次失败 → 返回 false

重试间隔公式:delay = 1000 * 2^(attempt - 1) ms

| 次数 | 延迟 | |------|------| | 第 1 次重试 | 1s | | 第 2 次重试 | 2s | | 第 3 次重试 | 4s |


offlineStorage.ts — 离线缓存

上报失败的事件持久化到本地存储,下次初始化时自动重传。

import { OfflineStorage } from '@evertro/monitor-transport';

const storage = new OfflineStorage({
  maxCacheSize: 100,      // 最多缓存 100 条
  maxBytes: 512000,       // 最多 500KB
  storageKey: '_evertro_offline_events',
});

storage.save(events);               // 持久化事件
const cached = storage.load();      // 读取缓存的事件
storage.clear();                    // 清空缓存

存储引擎自动适配:

  • 小程序环境 → wx.setStorageSync / wx.getStorageSync
  • H5/PC 环境 → localStorage

interface.ts — 传输接口

所有传输适配器必须实现的接口:

interface TransportInterface {
  send(payload: ReportPayload): Promise<boolean>;
}

weappTransport.ts — 微信小程序传输

基于 wx.request 的传输实现。

import { WeappTransport } from '@evertro/monitor-transport';

const transport = new WeappTransport(dsn);
// 内部使用 wx.request POST 发送数据
// 请求标记 _evertro_skip = true 防止被 NetworkPlugin 自监控

防自我监控: 发送的请求会在 requestTask 上设置 _evertro_skip 标记,NetworkPlugin 会跳过带有此标记的请求。


h5Transport.ts — H5/PC 传输

基于 fetch(优先)或 XMLHttpRequest(降级)的传输实现。

import { H5Transport } from '@evertro/monitor-transport';

const transport = new H5Transport(dsn);
// 优先使用 fetch API
// 不支持 fetch 时降级为 XMLHttpRequest
// XHR 请求设置 _evertro_skip 防止自监控

配置参数

| 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | reportBatchSize | number | 10 | 批量上报条数阈值 | | reportInterval | number | 10000 | 定时上报间隔(ms) | | maxRetries | number | 3 | 上报重试次数 | | maxCacheSize | number | 100 | 离线缓存上限条数 | | offlineMaxBytes | number | 512000 | 离线缓存字节上限(500KB) |

依赖关系

@evertro/monitor-types  →  @evertro/monitor-core  →  @evertro/monitor-transport

导出一览

export { ReportQueue } from './reportQueue';
export { BatchProcessor } from './batchProcessor';
export { RetryStrategy } from './retryStrategy';
export { OfflineStorage } from './offlineStorage';
export { WeappTransport } from './weappTransport';
export { H5Transport } from './h5Transport';
export type { TransportInterface } from './interface';