跳转至

前端监控

📚 章节目标

本章节将全面介绍前端监控的各种技术和工具,包括Sentry、Lighthouse、Web Vitals、APM等,帮助学习者掌握前端监控的核心方法。

学习目标

  1. 理解前端监控的核心概念
  2. 掌握Sentry错误监控
  3. 掌握Lighthouse性能分析
  4. 掌握Web Vitals性能监控
  5. 掌握APM性能监控
  6. 理解监控最佳实践

🔍 前端监控概述

1. 监控类型

JavaScript
// 前端监控类型
// 1. 错误监控 - 捕获和上报错误
// 2. 性能监控 - 监控应用性能
// 3. 行为监控 - 监控用户行为
// 4. 业务监控 - 监控业务指标

// 错误监控示例
window.addEventListener('error', (event) => {
  console.error('Error:', event.error);
  // 上报错误
  reportError(event.error);
});

// 性能监控示例
const perfData = performance.getEntriesByType('navigation')[0];
console.log('Page load time:', perfData.loadEventEnd - perfData.fetchStart);

2. 监控指标

JavaScript
// 核心监控指标
// 1. 错误率 - 错误次数 / PV
// 2. 性能指标 - LCP, INP, CLS
// 3. 转化率 - 转化次数 / PV
// 4. 留存率 - 活跃用户 / 总用户
// 5. 用户满意度 - 用户评分

// 计算错误率
const errorRate = (errorCount / pageViews) * 100;
console.log(`Error rate: ${errorRate}%`);

🚨 Sentry错误监控

1. Sentry基础

1.1 基本配置

JavaScript
// 安装Sentry(v8+ 无需单独安装 @sentry/tracing)
npm install @sentry/react

// 配置Sentry
import * as Sentry from '@sentry/react';

Sentry.init({
  dsn: 'https://example@sentry.io/project-id',
  integrations: [
    Sentry.browserTracingIntegration({
      tracePropagationTargets: ['localhost', 'https://api.example.com'],
    }),
  ],
  tracesSampleRate: 1.0,
  environment: process.env.NODE_ENV,
  release: 'my-project@1.0.0',
});

// 在React中使用
import { ErrorBoundary } from '@sentry/react';

function App() {
  return (
    <ErrorBoundary fallback={<div>Something went wrong</div>}>
      <MyComponent />
    </ErrorBoundary>
  );
}

1.2 错误捕获

JavaScript
// 捕获全局错误
window.addEventListener('error', (event) => {
  Sentry.captureException(event.error);
});

// 捕获未处理的Promise拒绝
window.addEventListener('unhandledrejection', (event) => {
  Sentry.captureException(event.reason);
});

// 手动捕获错误
try {
  doSomething();
} catch (error) {
  Sentry.captureException(error);
}

// 捕获React错误
class ErrorBoundary extends React.Component {
  componentDidCatch(error, errorInfo) {
    Sentry.captureException(error, {
      contexts: {
        react: {
          componentStack: errorInfo.componentStack,
        },
      },
    });
  }
}

2. Sentry高级特性

2.1 用户信息

JavaScript
// 设置用户信息
Sentry.setUser({
  id: '123',
  username: 'john_doe',
  email: 'john@example.com',
});

// 清除用户信息
Sentry.setUser(null);

// 设置标签
Sentry.setTag('page', 'home');
Sentry.setTag('userType', 'premium');

// 设置额外数据
Sentry.setExtra('customData', {
  featureFlag: true,
  experiment: 'A',
});

2.2 自定义事件

JavaScript
// 发送自定义事件
Sentry.captureMessage('Custom message', 'info');

// 发送自定义错误
Sentry.captureException(new Error('Custom error'));

// 发送带上下文的事件
Sentry.captureException(error, {
  level: 'error',
  tags: {
    section: 'checkout',
  },
  extra: {
    cartItems: 5,
    totalAmount: 100,
  },
});

// 发送面包屑
Sentry.addBreadcrumb({
  message: 'User clicked button',
  category: 'user',
  level: 'info',
});

🚀 Lighthouse性能分析

1. Lighthouse基础

1.1 命令行使用

Bash
# 安装Lighthouse
npm install -g lighthouse

# 运行Lighthouse
lighthouse https://example.com --output html --output-path report.html

# 运行特定类别
lighthouse https://example.com --only-categories=performance

# 运行多次取平均值
for i in {1..5}; do  # Shell for循环
  lighthouse https://example.com --output json --output-path "report-$i.json"
done

1.2 Node.js API

JavaScript
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

async function runLighthouse(url) {
  const chrome = await chromeLauncher.launch({
    chromeFlags: ['--headless'],
  });

  const options = {
    logLevel: 'info',
    output: 'html',
    onlyCategories: ['performance'],
    port: chrome.port,
  };

  const runnerResult = await lighthouse(url, options);
  await chrome.kill();

  return runnerResult;
}

runLighthouse('https://example.com').then((results) => {
  console.log('Performance score:', results.lhr.categories.performance.score * 100);
});

2. Lighthouse配置

2.1 自定义配置

JavaScript
// lighthouse-config.js
module.exports = {
  extends: 'lighthouse:default',
  settings: {
    onlyCategories: ['performance', 'accessibility', 'best-practices', 'seo'],
    throttling: {
      rttMs: 40,
      throughputKbps: 10240,
      cpuSlowdownMultiplier: 1,
      requestLatencyMs: 0,
      downloadThroughputKbps: 0,
      uploadThroughputKbps: 0,
    },
    emulatedFormFactor: 'desktop',
    screenEmulation: {
      mobile: false,
      width: 1920,
      height: 1080,
      deviceScaleFactor: 1,
      disabled: false,
    },
  },
};

// 使用自定义配置
lighthouse https://example.com --config-path=lighthouse-config.js

2.2 CI集成

YAML
# .github/workflows/lighthouse.yml
name: Lighthouse CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  lighthouse:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Run Lighthouse
        uses: treosh/lighthouse-ci-action@v9
        with:
          urls: |
            https://example.com
          uploadArtifacts: true
          temporaryPublicStorage: true

📊 Web Vitals性能监控

1. Web Vitals基础

1.1 核心指标

JavaScript
import { onCLS, onINP, onLCP } from 'web-vitals';

// 监控CLS
onCLS((metric) => {
  console.log('CLS:', metric.value);
  // 发送到分析服务
  analytics.track('CLS', {
    value: metric.value,
    id: metric.id,
  });
});

// 监控INP(替代已废弃的FID,2024年3月起成为Core Web Vital)
onINP((metric) => {
  console.log('INP:', metric.value);
  analytics.track('INP', {
    value: metric.value,
    id: metric.id,
  });
});

// 监控LCP
onLCP((metric) => {
  console.log('LCP:', metric.value);
  analytics.track('LCP', {
    value: metric.value,
    id: metric.id,
  });
});

1.2 所有Web Vitals

JavaScript
import {
  onCLS,
  onFCP,
  onLCP,
  onTTFB,
  onINP,
} from 'web-vitals';

// 监控所有指标(INP 已于 2024年3月取代 FID 成为 Core Web Vital)
onCLS(sendToAnalytics);
onFCP(sendToAnalytics);
onLCP(sendToAnalytics);
onTTFB(sendToAnalytics);
onINP(sendToAnalytics);

function sendToAnalytics(metric) {
  const data = {
    name: metric.name,
    value: metric.value,
    id: metric.id,
    delta: metric.delta,
    rating: metric.rating,
  };

  // 发送到分析服务
  analytics.track('Web Vitals', data);

  // 发送到自定义端点
  fetch('/api/analytics', {
    method: 'POST',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json',
    },
  });
}

2. Web Vitals优化

2.1 LCP优化

JavaScript
// 优化LCP的策略
// 1. 预加载关键资源
<link rel="preload" href="/images/hero.jpg" as="image">
<link rel="preload" href="/fonts/main.woff2" as="font">

// 2. 优化图片
<img
  src="image.webp"
  srcset="image-small.webp 400w, image-medium.webp 800w"
  sizes="(max-width: 600px) 400px, 800px"
  loading="eager"
  decoding="async"
>

// 3. 优化关键CSS
<style>
  /* 内联关键CSS */
</style>
<link rel="preload" href="/styles/main.css" as="style">

2.2 INP优化

JavaScript
// 优化INP(Interaction to Next Paint)的策略
// 1. 减少JavaScript执行时间
// 2. 代码分割和懒加载
// 3. 使用Web Workers

// Web Worker示例
const worker = new Worker('worker.js');

worker.postMessage({ data: largeData });

worker.onmessage = (e) => {  // 箭头函数:简洁的函数语法
  console.log('Result:', e.data);
};

// worker.js
self.onmessage = (e) => {
  const result = processData(e.data);
  self.postMessage(result);
};

2.3 CLS优化

JavaScript
// 优化CLS的策略
// 1. 为图片和视频设置尺寸
<img
  src="image.jpg"
  width="800"
  height="600"
  alt="Description"
>

// 2. 为动态内容预留空间
<div style="min-height: 200px;">
  <!-- 动态内容 -->
</div>

// 3. 使用transform和opacity进行动画
.animated-element {
  transition: transform 0.3s ease, opacity 0.3s ease;
}

📈 APM性能监控

1. APM基础

1.1 基本配置

JavaScript
// 使用New Relic
import * as newrelic from 'newrelic';

newrelic.initializeAgent({
  appName: 'my-app',
  licenseKey: 'your-license-key',
  distributedTracingEnabled: true,
});

// 使用Datadog
import { datadogRum } from '@datadog/browser-rum';

datadogRum.init({
  applicationId: 'your-app-id',
  clientToken: 'your-client-token',
  site: 'datadoghq.com',
  service: 'my-app',
  env: 'production',
  sessionSampleRate: 100,
  trackInteractions: true,
});

// 使用Dynatrace
import { dtrum } from '@dynatrace/browser-agent';

dtrum.init({
  applicationId: 'your-app-id',
  beaconURL: 'https://your-beacon-url',
});

2.2 性能追踪

JavaScript
// 追踪用户操作
datadogRum.addAction('button_click', {
  buttonName: 'submit',
  page: 'checkout',
});

// 追踪错误
datadogRum.addError(new Error('Something went wrong'), {
  component: 'CheckoutForm',
  action: 'submit',
});

// 追踪资源
datadogRum.addResourceTiming({
  name: '/api/users',
  duration: 150,
  size: 1024,
});

// 追踪自定义指标
datadogRum.addTiming('custom_metric', 100);

2. APM高级特性

2.1 分布式追踪

JavaScript
// 追踪API请求
import { trace } from '@opentelemetry/api';

const tracer = trace.getTracer('my-app');  // const不可重新赋值;let块级作用域变量

async function fetchUsers() {  // async定义异步函数;await等待Promise完成
  const span = tracer.startSpan('fetchUsers', {
    attributes: {
      'http.method': 'GET',
      'http.url': '/api/users',
    },
  });

  try {  // try/catch捕获异常
    const response = await fetch('/api/users');  // await等待异步操作完成
    span.setStatus({ code: SpanStatusCode.OK });
    return response.json();
  } catch (error) {
    span.recordException(error);
    span.setStatus({ code: SpanStatusCode.ERROR });
    throw error;
  } finally {
    span.end();
  }
}

2.2 自定义指标

JavaScript
// 发送自定义指标
fetch('/api/analytics', {
  method: 'POST',
  body: JSON.stringify({
    metric: 'checkout_duration',
    value: 5000,
    tags: {
      payment_method: 'credit_card',
      user_type: 'premium',
    },
  }),
});

// 发送自定义事件
fetch('/api/analytics', {
  method: 'POST',
  body: JSON.stringify({
    event: 'purchase_completed',
    properties: {
      amount: 100,
      items: 5,
    },
  }),
});

📝 练习题

1. 基础题

题目1:配置Sentry错误监控

JavaScript
// 配置Sentry
import * as Sentry from '@sentry/react';

Sentry.init({
  // 完成配置
});

2. 进阶题

题目2:实现Web Vitals监控

JavaScript
// 实现Web Vitals监控
import { onCLS, onINP, onLCP } from 'web-vitals';

function sendToAnalytics(metric) {
  // 发送到分析服务
}

// 监控核心指标

3. 面试题

题目3:解释Core Web Vitals的含义

JavaScript
// 答案要点:
// 1. LCP (Largest Contentful Paint) - 最大内容绘制,衡量页面主要内容加载时间
// 2. INP (Interaction to Next Paint) - 交互到下一次绘制,衡量页面整体交互响应性
//    (2024年3月起取代 FID 成为 Core Web Vital)
// 3. CLS (Cumulative Layout Shift) - 累积布局偏移,衡量页面布局稳定性
// 4. 目标值:LCP < 2.5s, INP < 200ms, CLS < 0.1

🎯 本章总结

本章节全面介绍了前端监控的各种技术和工具,包括Sentry、Lighthouse、Web Vitals、APM等。关键要点:

  1. 监控类型:理解错误监控、性能监控、行为监控
  2. Sentry:掌握Sentry错误监控和高级特性
  3. Lighthouse:掌握Lighthouse性能分析和CI集成
  4. Web Vitals:掌握Web Vitals性能监控和优化
  5. APM:掌握APM性能监控和分布式追踪
  6. 最佳实践:理解监控最佳实践和指标分析

下一步将深入学习微前端架构。