> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flashcat.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# 源码映射与异常追踪

> 本文档详细介绍如何使用 RUM 进行源码映射管理，以及如何通过源码映射进行异常追踪和调试。

Flashduty 支持多平台的符号文件上传与源码映射，帮助开发者将混淆或压缩后的错误堆栈还原为可读的原始源代码。

* **Web（JavaScript）**：通过 [Flashduty CLI](https://github.com/flashcatcloud/flashcat-cli) 上传 `sourcemap` 文件
* **Android**：通过 Gradle 插件自动上传 ProGuard/R8 mapping 文件和 NDK 符号文件
* **iOS**：通过 Flashduty CLI 上传 dSYM 符号文件

用户可在「应用管理」-「源码管理」菜单查看已上传的符号文件，并通过上传面板生成脚本在本地执行上传操作。

## 为什么需要源码映射？

在现代应用开发中，代码通常会被压缩、混淆或编译，以优化加载速度和性能。无论是 Web 端的 JavaScript 压缩、Android 的 ProGuard/R8 混淆，还是 iOS 的编译优化，这些处理都会导致错误堆栈中的代码位置信息无法直接映射到原始源代码，增加了调试难度。

<CardGroup cols={3}>
  <Card title="映射压缩代码" icon="map">
    `SourceMap` 记录了压缩代码与原始代码之间的映射关系，允许开发者在调试时查看未压缩的源代码
  </Card>

  <Card title="精确定位错误" icon="crosshairs">
    通过 `SourceMap` 可以在异常追踪中直接定位到原始源代码中的具体位置
  </Card>

  <Card title="提升调试效率" icon="gauge-high">
    开发者无需手动解码压缩文件，节省排查问题的时间
  </Card>
</CardGroup>

## 生成 SourceMap

大多数现代构建工具（如 Webpack、Rollup 或 Vite）都支持生成 `SourceMap`。

<Tabs>
  <Tab title="Webpack">
    在 `webpack.config.js` 中启用 `SourceMap` 生成：

    ```javascript theme={null}
    module.exports = {
      mode: "production",
      devtool: "source-map", // 生成独立的 .map 文件
      output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "dist"),
      },
    };
    ```

    构建后，`dist` 目录中会生成 `bundle.js` 和对应的 `bundle.js.map` 文件。
  </Tab>

  <Tab title="Vite">
    在 `vite.config.js` 中配置：

    ```javascript theme={null}
    export default {
      build: {
        sourcemap: true, // 生成 sourcemap
      },
    };
    ```
  </Tab>

  <Tab title="Rollup">
    在 `rollup.config.js` 中配置：

    ```javascript theme={null}
    export default {
      output: {
        sourcemap: true,
      },
    };
    ```
  </Tab>
</Tabs>

## 上传 SourceMap

使用 Flashduty CLI 将 `sourcemap` 文件上传至 Flashduty 服务器。

<Steps>
  <Step title="安装 Flashduty CLI">
    确保已安装 Node.js，然后通过 npm 安装：

    ```bash theme={null}
    npm install -g @flashcloud/flashcat-cli
    ```
  </Step>

  <Step title="配置上传参数">
    <Frame>
      <img src="https://docs-cdn.flashcat.cloud/imges/png/69c1c53e5df18d5241d8e0fa17e56198.png" alt="上传源码配置" />
    </Frame>

    在「应用管理」-「源码管理」菜单中，点击「上传源码」面板，填写以下信息：

    <ParamField path="API Key" type="string" required>
      用于认证您的身份
    </ParamField>

    <ParamField path="服务名" type="string" required>
      应用的服务名（例如 `my-service`）
    </ParamField>

    <ParamField path="版本号" type="string" required>
      应用的发布版本（例如 `1.0.0`）
    </ParamField>

    <ParamField path="压缩文件前缀" type="string" required>
      压缩文件的路径前缀（例如 `/assets`）
    </ParamField>
  </Step>

  <Step title="执行上传">
    在项目根目录下运行生成的脚本：

    ```bash theme={null}
    flashcat-cli sourcemaps upload \
      --service my-service \
      --release-version 1.0.0 \
      --minified-path-prefix /assets \
      --api-key your-api-key \
      ./dist
    ```
  </Step>
</Steps>

<Warning>
  * 确保 `minified-path-prefix` 与实际部署的压缩文件路径一致
  * 上传成功后，可在「应用管理」-「源码管理」中查看已上传的 `sourcemap` 文件
</Warning>

## 上传 Android 符号文件

Android 应用使用 ProGuard/R8 进行代码混淆后，错误堆栈中的类名和方法名会被替换为无意义的短名称。通过上传 mapping 文件，Flashduty 可以将混淆后的堆栈还原为原始代码。

对于包含 NDK 原生代码的应用，还需要上传 NDK 符号文件以还原 C/C++ 层的堆栈。

<Steps>
  <Step title="添加 Gradle 插件">
    在应用的 `build.gradle` 中添加 Flashcat Gradle 插件：

    ```groovy theme={null}
    // In your app's build.gradle script
    plugins {
        id("cloud.flashcat.fc-sdk-android-gradle-plugin") version "1.0.0"
    }
    ```
  </Step>

  <Step title="配置 API Key">
    通过环境变量或项目配置文件提供 API Key：

    ```bash theme={null}
    # 设置环境变量（二选一）
    export FC_API_KEY=your-api-key
    # 或
    export FLASHCAT_API_KEY=your-api-key
    ```

    也可以在项目根目录创建 `flashcat-ci.json` 配置文件：

    ```json theme={null}
    {
      "apiKey": "your-api-key"
    }
    ```

    <Tip>
      API Key 可在控制台的「API Key 管理」页面创建和管理。
    </Tip>
  </Step>

  <Step title="运行上传任务">
    构建完成后，执行 Gradle 任务上传符号文件：

    ```bash theme={null}
    # 上传 ProGuard/R8 mapping 文件
    ./gradlew uploadMappingRelease

    # 如果项目包含 NDK 原生代码，上传 NDK 符号文件
    ./gradlew uploadNdkSymbolFilesRelease
    ```

    <Note>
      如果项目使用了多个 flavor，插件会为每个启用了混淆的 variant 提供对应的上传任务。
    </Note>
  </Step>
</Steps>

## 上传 iOS dSYM 文件

iOS 应用在编译时会生成 dSYM（Debug Symbol）文件，其中包含将内存地址映射回源代码位置所需的调试符号信息。上传 dSYM 文件后，Flashduty 可以将崩溃堆栈中的地址还原为可读的函数名、文件名和行号。

<Steps>
  <Step title="安装 Flashduty CLI">
    确保已安装 Node.js，然后通过 npm 安装：

    ```bash theme={null}
    npm install -g @flashcatcloud/flashcat-cli
    ```
  </Step>

  <Step title="获取 dSYM 文件">
    dSYM 文件可从以下位置获取：

    * **Xcode 本地构建**：在 Xcode 的 Build Products 目录中找到 `.dSYM` 文件
    * **Xcode Archive**：通过 Organizer 窗口导出 dSYMs
    * **App Store Connect**：从 App Store Connect 下载 dSYMs（需要在构建设置中启用符号上传）
  </Step>

  <Step title="执行上传">
    使用 Flashduty CLI 上传 dSYM 文件：

    ```bash theme={null}
    FLASHCAT_API_KEY=your-api-key flashcat-cli dsyms upload ./app.dSYM
    ```

    <Tip>
      您也可以在控制台的「源码管理」面板中，填写参数后自动生成上传命令。
    </Tip>
  </Step>
</Steps>

## 符号文件管理

在 Flashduty 平台上，符号文件的管理通过「应用管理」-「源码管理」菜单完成：

| 功能         | 说明                                                         |
| ---------- | ---------------------------------------------------------- |
| 查看已上传的符号文件 | 列出所有已上传的文件（SourceMap、mapping 文件、dSYM），包括路径、服务名、版本号、大小和上传时间 |
| 版本管理       | 通过 `service` 和 `release-version` 参数为不同版本的应用分别管理            |
| 权限控制       | 通过 `API Key` 确保只有授权用户可以上传或管理                               |

## 在异常追踪中查看源码

RUM 集成了 `sourcemap` 功能，支持在异常追踪模块中直接查看原始源代码，精确定位问题。

<Steps>
  <Step title="捕获前端错误">
    RUM SDK 会自动捕获前端错误（如 JavaScript 异常、Promise 拒绝、网络错误等），并将错误堆栈信息发送至服务器。

    ```javascript theme={null}
    throw new Error("Something went wrong");
    ```
  </Step>

  <Step title="关联 SourceMap">
    当错误堆栈中的文件路径和行号与已上传的 `sourcemap` 匹配时，Flashduty 会自动将压缩代码的错误位置映射到原始源代码。

    **压缩文件堆栈：**

    ```
    Error: Something went wrong
        at Object.<anonymous> (/assets/index-5e0391ac.js:1:123)
    ```

    **映射后的源代码：**

    ```
    Error: Something went wrong
        at App.render (src/components/App.js:45:10)
    ```
  </Step>

  <Step title="查看异常详情">
    在异常追踪模块中，点击具体的错误记录，可以查看：

    * **错误消息**：如 `Something went wrong`
    * **原始堆栈**：映射后的源代码文件路径、行号和列号
    * **上下文代码**：显示错误位置附近的源代码片段
  </Step>

  <Step title="调试与修复">
    根据映射后的源代码位置，直接在本地开发环境中找到对应代码，分析问题根因并修复。
  </Step>
</Steps>

## 最佳实践

<AccordionGroup>
  <Accordion title="规范化 SourceMap 上传">
    在 CI/CD 流水线中集成上传命令，确保每次发布时自动上传 `sourcemap`。

    **GitHub Actions 示例：**

    ```yaml theme={null}
    - name: Upload SourceMaps
      run: |
        flashcat-cli sourcemaps upload \
          --service my-service \
          --release-version ${{ github.sha }} \
          --minified-path-prefix /assets \
          --api-key ${{ secrets.FLASHCAT_API_KEY }} \
          ./dist
    ```
  </Accordion>

  <Accordion title="版本管理">
    使用 `--release-version` 参数与应用版本号保持一致，便于追踪特定版本的 `sourcemap`。
  </Accordion>

  <Accordion title="清理源码">
    在资源上传 CDN 之前删除 `sourcemap` 文件，避免将源码信息带入生产环境。
  </Accordion>

  <Accordion title="测试映射效果">
    上传 `sourcemap` 后，主动抛出测试错误，验证异常追踪模块是否能正确映射到源代码。
  </Accordion>
</AccordionGroup>

## 常见问题

<AccordionGroup>
  <Accordion title="为什么异常堆栈没有映射到源代码？">
    * 确认 `sourcemap` 是否成功上传，且 `minified-path-prefix` 与实际部署路径一致
    * 检查 `service` 和 `release-version` 是否与错误发生时的应用版本匹配
  </Accordion>

  <Accordion title="如何避免 SourceMap 泄露敏感信息？">
    * 确保 `sourcemap` 文件仅上传至 Flashduty 服务器，不直接暴露在公网
    * 在生产环境中，移除对 `sourcemap` 文件的直接访问（如通过 Nginx 配置）
  </Accordion>

  <Accordion title="上传 SourceMap 失败怎么办？">
    * 检查 `API Key` 是否有效
    * 确保网络连接正常，CLI 版本是最新的
  </Accordion>
</AccordionGroup>

## 下一步

<CardGroup cols={2}>
  <Card title="异常聚合" icon="layer-group" href="./error-aggregation">
    了解异常聚合机制
  </Card>

  <Card title="Issue 状态" icon="circle-check" href="./issue-status">
    管理 Issue 状态流转
  </Card>
</CardGroup>
