Network Error Loggingでブラウザのネットワークエラーを検知する

20180528 追記
Chrome devに来たので試した
asnokaze.hatenablog.com


20180301 追記
結構代わりました
NELヘッダは、json形式で表現するようになりました。また、report APIに準拠する形になりました

NEL: {"report-to": "network-errors", "max-age": 2592000}
report-to: { "url": "https://asnokaze.com/report", "group": "network-errors", "max-age": 10886400 }

Webアプリケーションの特性を測定することは非常に大切だが、DNSによる名前解決・接続のタイムアウト・接続のリセットといったユーザ側による読み込み失敗などを知るすべはありません。


Network Error Loggingでは、ユーザエージェントにネットワークエラーをレポートする仕組みを定義することでそのような問題を解決する。

Network Error Logging

現在W3Cでは仕様策定がすすんでおり、現在 Draft 05(http://www.w3.org/TR/2015/WD-network-error-logging-20150305/)となっている。

NELヘッダ

以下の様に、HTTPレスポンスのNELヘッダによってユーザエージェントに通知されます。

HTTP/1.1 200 OK
...
NEL: report-uri="/report"; max-age=2592000
  • report-uri: レポートを提出するURL(絶対パスでも可、複数指定も可)
  • max-age: このポリシーを適応する時間(秒)


このNELヘッダはTLS(証明書エラーなど無い)を使用された信頼できるオリジンである必要がある。

レポート形式
{
  "nel-report": [
   {
      "uri": "https://widget.com/thing.js",
      "referrer": "https://www.example.com/",
      "server-ip": "234.233.232.231",
      "protocol": "",
      "status-code": 0,
      "elapsed-time": 143,
      "age": 0,
      "type": "http.dns.name_not_resolved"
    }
  ]
}

ぱっと見でだいたいわかるが

  • uri: ネットワークエラーがおきたURI
  • referrer: そのリソースに対するreferrer属性
  • server-ip: IPv4またはIPv6の文字列表現
  • protocol: プロトコル、ALPNのprotocol ID
  • status-code: 取得可能であればHTTPのステータスコード
  • elapsed-time: リソースをフェッチしてから中止されるまでの時間(msec)
  • age: リクエストを中断してからレポートを送り終わるまでの時間(msec)
  • type:ネットワークエラーの種類
ネットワークエラーの種類

ネットワークエラーの種類は多く定義されている。
おおむね以下のエラーが定義されているが、それぞれより細かくエラーが定義されているので(証明書エラー等)、詳しく知りたい場合は仕様を確認ください。

  • DNS名前解決失敗
  • TCPコネクション確立失敗
  • TLSセッション確立失敗
  • TLSプロトコルに起因する、リソースフェッチ失敗
  • HTTPプロトコルに起因する、リソースフェッチ失敗
  • ソケットタイムアウトに起因する、リソースフェッチ失敗
  • リダイレクトループに起因する、リソースフェッチ失敗
  • 中止や不明なエラー
プライバシー

DraftはGithub上で管理されており、プライバシーに関するコミットが加わっている。
https://w3c.github.io/network-error-logging/#privacy-considerations