崩溃报告

社区组报告草案,

此版本:
https://wicg.github.io/crash-reporting/
版本历史:
https://github.com/WICG/crash-reporting/commits/gh-pages
编辑:
(Google Inc.)
参与:
提交问题开放问题
测试套件:
https://wpt.fyi/results/reporting/

摘要

本文档定义了一种机制,用于通过 Reporting API 向站点所有者报告浏览器崩溃。

本文档状态

本规范由 Web Platform Incubator Community Group 发布。 它不是 W3C 标准,也不在 W3C 标准轨道上。 请注意,根据 W3C 社区贡献者许可协议 (CLA), 存在有限的退出选择权,并适用其他条件。 了解更多关于 W3C 社区组和商务组的信息。

1. 引言

[引言写在这里]

1.1. 示例

Unstable, Inc. 希望更好地了解其网站在实际环境中崩溃的频率。 它可以通过发送以下标头来定义默认报告端点,从而将崩溃报告定向到该处:
Reporting-Endpoints: default="https://example.com/reports"

2. 概念

2.1. 崩溃

2.2. 内存不足

2.3. 无响应

3. 崩溃报告

崩溃报告表示 用户无法继续使用该页面,因为浏览器(或页面所必需的其中一个进程) 已崩溃。出于安全原因,除了唯一标识符(可由浏览器供应商解释)以及 可选的崩溃原因(例如 "oom")之外,不会传达崩溃的任何细节。

崩溃报告是一种报告

崩溃报告具有报告 类型 "crash"。

dictionary CrashReportBody : ReportBody {
  DOMString reason;
  DOMString stack;
  boolean is_top_level;
  DocumentVisibilityState visibility_state;
  object crash_report_api;
};

崩溃报告body,在 JavaScript 中由 CrashReportBody 表示,包含以下字段:

原因 说明
oom 页面内存耗尽。
unresponsive 页面因无响应而被终止。

注: 崩溃报告对 JavaScript 不可观察,因为 按定义,接收它们的页面已经无法这样做。CrashReportBody 的 IDL 描述存在于本规范中, 是为了提供一个可 JSON 序列化的接口,其序列化结果可以嵌入带外报告中。

3.1. 崩溃 报告递送优先级

如果指定了 crash-reporting 端点,则崩溃报告会递送到该端点。

否则,如果指定了 default 端点,则崩溃报告会递送到该端点。

如果两种端点都未指定,则不会递送崩溃报告

Reporting-Endpoints: crash-reporting="https://example.com/reports"

4. CrashReportContext 接口

partial interface Window {
  readonly attribute CrashReportContext crashReport;
};

每个 Window 对象都有一个关联的 crashReport,它是一个 CrashReportContext 实例,与 Window 一起创建。

crashReport getter 步骤为:
  1. 如果 this相关全局对象关联 Document不是完全活动的,则返回 null。

  2. 返回 this相关全局对象crashReport 对象。

[Exposed=Window]
interface CrashReportContext {
    Promise<undefined> initialize(unsigned long long length);
    undefined set(DOMString key, DOMString value);
    undefined delete(DOMString key);
};

每个 CrashReportContext 对象都有一个关联的 内部映射, 它是一个映射,其都是 DOMString

用户 代理有关联的 崩溃报告缓冲区,它是一个 映射, 其唯一 内部值,其实现定义的值。

注: 内部映射是 最终会出现在崩溃报告中的数据的映射表示,它的存在是为了通过 映射 语义以符合人体工程学的方式与这些数据交互。但本规范的实现,尤其是支持站点隔离的实现, 最终很可能会把其全部内容序列化到一个后备共享内存缓冲区中,该缓冲区由用户代理崩溃报告 缓冲区映射跟踪。该 映射的 预计是跨越 Web 进程以及在 Web 进程崩溃时负责发送崩溃报告的任何 OS 进程的那些内存缓冲区; 此时其内部映射已不再可供读取。

每个 CrashReportContext 对象都有一个关联的 后备缓冲区 ID,它是 null 或 唯一 内部值;其初始值为 null。

每个 CrashReportContext 对象都有一个关联的 is buffer initialized 布尔值,其初始值为 false。

注: 当与 this后备缓冲区 ID关联的后备内存缓冲区初始化完成时, 此成员会被异步设置为 true。

每个 CrashReportContext 对象都有一个关联的 unsigned long long buffer length,其初始值为 0。

注: 它会在 initialize() 中被赋值一次,并跟踪任何对 set() 的调用可写入支撑 内部映射的内存中的最大字节数。

内部映射用于保存所有将通过 CrashReportBody 提供给开发者的键/值。 在采用站点隔离的浏览器中,写入此数据的物理 进程不同于读取它并发送崩溃报告的进程。因此, 预期实现会将此映射维护为跨越这两个进程的共享内存 缓冲区。这正是 Chromium 对此 API 的实现方式。

initialize(length) 方法步骤 为:
  1. 如果 this相关全局对象关联 Document不是完全活动的,则抛出一个新的 "InvalidStateError" DOMException

    注: 这会通过一个被拒绝的 Promise 暴露给用户。

  2. 如果 this后备缓冲区 ID非 null,则 抛出一个新的 "InvalidStateError" DOMException

  3. 如果 length > 5 * 1024 * 1024,则抛出一个新的 "NotAllowedError" DOMException

    注: 崩溃报告内存缓冲区的限制为 5 兆字节。

  4. thisbuffer length 设置为 length

  5. this后备缓冲区 ID设置为创建新的唯一内部值的结果。

  6. cachedThisthis

  7. promise一个新的 promise

  8. 并行运行以下步骤:

    1. backing buffer IDcachedThis后备缓冲区 ID

    2. 运行实现定义的步骤,以创建并 初始化一个 length 字节的后备内存存储。

    3. 如果已创建这样的缓冲区,则:

      1. 用户代理崩溃报告 缓冲区[backing buffer ID] 设置为该 缓冲区。

      2. cachedThisis buffer initialized 设置为 true。

    4. 在给定 cachedThis相关全局对象DOM 操作任务源上,排队一个全局任务,以使用 undefined 解决 promise

  9. 返回 promise

set(key, value) 方法步骤 为:
  1. 如果 this相关全局对象关联 Document不是完全活动的,则抛出一个新的 "InvalidStateError" DOMException

  2. 如果 thisis buffer initialized 为 false, 则抛出一个新的 "InvalidStateError" DOMException

    注: 在调用 initialize() 之前,以及调用之后但在其返回的 Promise 解决之前,这都会是 false。它确保 set() 只有在由 后备缓冲区 ID标识的后备缓冲区完全 初始化后才会工作。

  3. 设置 this内部映射[key] 为 value

  4. serialization 为给定 this内部映射时,将 JavaScript 值序列化为 JSON 字节的结果。

  5. 如果 serialization大小 > thisbuffer length,则:

    1. 移除 this内部映射[key]。

    2. 抛出一个新的 "NotAllowedError" DOMException

  6. backing buffer IDthis后备缓冲区 ID

  7. serialization 写入用户代理崩溃报告缓冲区[backing buffer ID]。

delete(key) 方法步骤为:
  1. 如果 this相关全局对象关联 Document不是完全活动的,则抛出一个新的 "InvalidStateError" DOMException

  2. 如果 thisis buffer initialized 为 false, 则抛出一个新的 "InvalidStateError" DOMException

  3. 移除 this内部映射[key]。

  4. serialization 为给定 this内部映射时,将 JavaScript 值序列化为 JSON 字节的结果。

  5. backing buffer IDthis后备缓冲区 ID

  6. serialization 写入用户代理崩溃报告缓冲区[backing buffer ID]。

5. 文档策略集成

站点作者可以选择记录某些报告中的 JavaScript 调用栈。

本规范定义了一个名为 include-js-call-stacks-in-crash-reports配置点。它的类型为 boolean,默认 值为 false。当在启用了崩溃 报告的 Document 中配置为 true 时,这会导致崩溃发生时 JavaScript 调用栈的字符串表示被包含在崩溃报告中。

Document-Policy: include-js-call-stacks-in-crash-reports

6. 实现注意事项

6.1. 递送

[REPORTING] 定义了 本规范所依赖的框架, 它最多提供一种尽力而为的递送机制。在报告崩溃时尤其如此。 可能总会存在某些根本无法报告的崩溃 条件(例如,如果崩溃发生在用户代理的崩溃监控代码中,或者承载用户代理的计算机 突然不复存在)。不过,现代浏览器可以观察到许多崩溃, 并推断出其直接原因。

实现崩溃报告的用户代理 SHOULD 尝试以一种方式监视文档的 崩溃,使其即使在负责该文档的进程崩溃或被操作系统终止时仍能继续工作。

实现这种监视器有多种方式,它们在可靠性以及对特定崩溃原因的 鲁棒性方面各不相同,本规范并不试图规定任何特定的方法。

7. 报告示例

POST /reports HTTP/1.1
Host: example.com
...
Content-Type: application/reports+json

[{
  "type": "crash",
  "age": 42,
  "url": "https://example.com/",
  "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
  "body": {
    "reason": "oom"
  }
}]

8. 安全性注意事项

有关带外报告一般安全性注意事项的讨论,参见 Reporting API § 8 安全性 注意事项

本节其余部分讨论专门针对崩溃 报告的安全性注意事项。

9. 隐私注意事项

有关带外报告一般隐私注意事项的讨论,参见 Reporting API § 9 隐私 注意事项

本节其余部分讨论专门针对崩溃 报告的隐私注意事项。

9.1. 跨进程污染

索引

本规范定义的术语

由引用定义的术语

参考文献

规范性参考文献

[DOCUMENT-POLICY]
文档策略。社区组报告草案。 URL:https://wicg.github.io/document-policy/
[DOM]
Anne van Kesteren。DOM 标准。现行标准。 URL:https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML 标准。 现行标准。URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola。Infra 标准。现行标准。URL:https://infra.spec.whatwg.org/
[REPORTING]
Douglas Creager; Ian Clelland; Mike West。Reporting API。URL:https://w3c.github.io/reporting/
[WEBIDL]
Edgar Chen; Timothy Gu。Web IDL 标准。现行 标准。URL:https://webidl.spec.whatwg.org/

IDL 索引

dictionary CrashReportBody : ReportBody {
  DOMString reason;
  DOMString stack;
  boolean is_top_level;
  DocumentVisibilityState visibility_state;
  object crash_report_api;
};

partial interface Window {
  readonly attribute CrashReportContext crashReport;
};

[Exposed=Window]
interface CrashReportContext {
    Promise<undefined> initialize(unsigned long long length);
    undefined set(DOMString key, DOMString value);
    undefined delete(DOMString key);
};