logo
  • 指南
  • 配置
  • 插件
  • API
  • 示例
  • 社区
  • Modern.js 2.x 文档
  • 简体中文
    • 简体中文
    • English
    • 开始
      介绍
      快速上手
      版本升级
      名词解释
      技术栈
      核心概念
      页面入口
      构建工具
      Web 服务器
      基础功能
      路由
      路由基础
      配置式路由
      数据管理
      数据获取
      数据写入
      数据缓存
      渲染
      服务端渲染(SSR)
      服务端流式渲染(Streaming SSR)
      渲染缓存
      静态站点生成(SSG)
      渲染预处理 (Render Preprocessing)
      样式开发
      引入 CSS
      使用 CSS Modules
      使用 CSS-in-JS
      使用 Tailwind CSS
      HTML 模板
      引用静态资源
      引用 JSON 文件
      引用 SVG 资源
      引用 Wasm 资源
      调试
      数据模拟(Mock)
      网络代理
      使用 Rsdoctor
      使用 Storybook
      测试
      Playwright
      Vitest
      Jest
      Cypress
      路径别名
      环境变量
      构建产物目录
      部署应用
      进阶功能
      使用 Rspack
      使用 BFF
      基础用法
      运行时框架
      扩展 BFF Server
      扩展一体化调用 SDK
      文件上传
      跨项目调用
      优化页面性能
      代码分割
      静态资源内联
      产物体积优化
      React Compiler
      提升构建性能
      浏览器兼容性
      配置底层工具
      源码构建模式
      服务端监控
      Monitors
      日志事件
      指标事件
      国际化
      基础概念
      快速开始
      配置说明
      语言检测
      资源加载
      路由集成
      API 参考
      高级用法
      最佳实践
      自定义 Web Server
      专题详解
      模块联邦
      简介
      开始使用
      应用级别模块
      服务端渲染
      部署
      集成国际化能力
      常见问题
      依赖安装问题
      命令行问题
      构建相关问题
      热更新问题
      已下线功能
      📝 编辑此页面
      上一页源码构建模式下一页日志事件

      #Monitors

      Modern.js 是一个全栈框架,它可以同时支持客户端和服务端的开发。当 Modern.js 在服务端渲染页面时,框架会在运行时插入更多日志与指标,帮助开发者在线上运维时定位问题。

      但服务端代码运行在 Node.js 环境中,开发者无法直接通过浏览器控制台来排查问题,而不同的项目可能使用不同的日志库,或是将数据上报到不同的平台。框架无法覆盖所有的场景,因此需要有统一的方式,允许开发者自行管理所有的内置日志与指标。

      Monitors 是 Modern.js 提供的帮助开发者监控应用程序的运行情况的模块。它包含注册 Monitor 和分发监控事件两部分能力。当开发者中调用 Monitors 的某个 API 时,框架会对应的监控事件分发到所有注册的 Monitor 中。

      Note

      在 Modern.js 中内置了默认的 Monitor,开发者也可以注册自定义的 Monitor。

      #Monitors 定义

      Monitors 模块的类型定义如下,其中 push 方法用于注册 Monitor,其他方法用于分发监控事件。

      export type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'trace';
      export interface LogEvent {
        type: 'log';
        payload: {
          level: LogLevel;
          message: string;
          args?: any[];
        };
      }
      
      export interface TimingEvent {
        type: 'timing';
        payload: {
          name: string;
          dur: number;
          desc?: string;
          args?: any[];
        };
      }
      
      export interface CounterEvent {
        type: 'counter';
        payload: {
          name: string;
          args?: any[];
        };
      }
      
      export type MonitorEvent = LogEvent | TimingEvent | CounterEvent;
      
      export type CoreMonitor = (event: MonitorEvent) => void;
      
      export interface Monitors {
        // 注册 Monitor
        push(monitor: CoreMonitor): void;
      
        // 日志事件
        error(message: string, ...args: any[]): void;
        warn(message: string, ...args: any[]): void;
        debug(message: string, ...args: any[]): void;
        info(message: string, ...args: any[]): void;
        trace(message: string, ...args: any[]): void;
      
        // 指标事件
        timing(name: string, dur: number, ...args: any[]): void;
        counter(name: string, ...args: any[]): void;
      }

      #内置 Monitor

      Modern.js 内置了默认的 Monitor,不同的事件会触发内置 Monitor 不同的行为。详细内容查看:

      • 日志事件
      • 指标事件

      #注册 Monitors

      开发者可以通过 Monitors 的 push API 注册自己的 Monitor,但只能在服务端中间件或服务端插件中注册,在 Data Loader、组件、init 函数中无法注册。

      Note

      目前暂未开放服务端插件,后续会补充相关文档。

      server/index.ts
      import type { CoreMonitors } from '@modern-js/types';
      const injectMonitorMiddleware = c => {
        const monitors = c.get('monitors');
        const myMonitor = (event: MonitorEvent) => {
          if (event.type === 'log') {
            // some code
          } else {
            // some other code
          }
        };
        monitors.push(myMonitor);
        return next();
      };
      
      export const middlewares = [injectMonitorMiddleware];

      #调用 Monitors

      Modern.js 允许开发者在 Data Loader、组件中调用 Monitors。

      Tip

      只有在 Node.js 环境才可以调用 Monitors,在浏览器环境调用无任何效果。

      在 Data Loader 中,开发者可以这样使用:

      routes/page.data.ts
      import { LoaderFunctionArgs } from '@modern-js/runtime/router';
      import { getMonitors } from '@modern-js/runtime';
      const loader = async ({ context }: LoaderFunctionArgs) => {
          const monitors = getMonitors();
          const start = Date.now();
          try {
              await fetch(...);
              monitors.timing('loader_fetch_timing', Date.now() - start);
          } catch(e) {
              monitors.error(e);
          }
      }

      在组件中调用 Monitors,需要判断当前运行环境是否为 Node.js:

      routes/page.tsx
      import { use } from 'react';
      import { RuntimeContext, getMonitors } from '@modern-js/runtime';
      const Page = () => {
        const context = use(RuntimeContext);
        if (process.env.MODERN_TARGET === 'node') {
          const monitors = getMonitors();
          monitors.info();
        }
        return <div>Hello World</div>;
      };
      export default Page;

      在中间件中,我们也可以调用 Monitors,但方式与在运行时代码中不同,需要通过 context 来获取:

      server/modern.server.ts
      import {
        defineServerConfig,
        type MiddlewareHandler,
      } from '@modern-js/server-runtime';
      
      export const handler: MiddlewareHandler = async (c, next) => {
        const monitors = c.get('monitors');
        const start = Date.now();
      
        await next();
      
        const end = Date.now();
        // 上报耗时
        monitors.timing('request_timing', end - start);
      };
      
      export default defineServerConfig({
        middlewares: [
          {
            name: 'request-timing',
            handler,
          },
        ],
      });