HTTP ヘッダーを使ってアプリケーションのパフォーマンスメトリクスをクライアント側に返す仕様「Server Timing」を調べながら試してみた.詳細な仕様は以下の W3C ドキュメントに載っている.ドキュメントの Introduction に載っているけど,今まではクライアント側で "レスポンスタイム" は確認できても「どの段階でなぜ時間がかかったのか」という詳細までは確認できなかったという背景がある.そして Google Chrome 65 以上など,Server Timing をサポートしてるブラウザなら DevTools で可視化できる❗️
Server Timing 仕様
仕様としては HTTP ヘッダー Server-Timing
にパフォーマンスメトリクスを設定してレスポンスを返す.フォーマットは以下の通り(W3C ドキュメントを引用).
Server-Timing = #server-timing-metric server-timing-metric = metric-name *( OWS ";" OWS server-timing-param ) metric-name = token server-timing-param = server-timing-param-name OWS "=" OWS server-timing-param-value server-timing-param-name = token server-timing-param-value = token / quoted-string
設定するレスポンスは具体的なサンプルを見るのが良いと思う.MDN に載っているサンプルを以下にまとめる.
Server-Timing: missedCache
(キャッシュミスだった)- メトリクス名のみを返せる
Server-Timing: cpu;dur=2.4
(CPU 処理時間は 2.4 ms だった)dur
を使って時間付きでメトリクスを返せる
Server-Timing: cache;desc="Cache Read";dur=23.2
(キャッシュ読み取り時間は 23.2 ms だった)desc
を使って説明付きでメトリクスを返せる
Server-Timing: db;dur=53, app;dur=47.2
(データベース処理は 53 ms / アプリケーション処理は 47.2 ms だった)- メトリクスを複数返せる
サンプル実装
Go の Gin を使ってサンプル実装をする.Server-Timing
は MDN に載っているサンプルを参考に組み合わせて,シンプルに HTTP ヘッダーを返すように実装する.なお,調べたところ HashiCorp の Mitchell が公開している middleware "HTTP Server-Timing for Go" もあるようだった(特にメンテナンスはされてなさそうだけど).
サンプル 1
以下のメトリクスを返す.
missedCache
cpu;dur=2.4
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/", func(c *gin.Context) { c.Header("Server-Timing", "missedCache, cpu;dur=2.4") c.JSON(http.StatusOK, gin.H{ "message": "hello", }) }) r.Run() }
期待通りに HTTP ヘッダーを取得できた.
$ curl -is http://localhost:8080/ | grep Server-Timing Server-Timing: missedCache, cpu;dur=2.4
サンプル 2
以下のメトリクスを返す.
cache;desc="Cache Read";dur=1.2
db;dur=3.4
app;dur=2.3
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/", func(c *gin.Context) { c.Header("Server-Timing", "cache;desc=\"Cache Read\";dur=1.2, db;dur=3.4, app;dur=2.3") c.JSON(http.StatusOK, gin.H{ "message": "hello", }) }) r.Run() }
期待通りに HTTP ヘッダーを取得できた.
$ curl -is http://localhost:8080/ | grep Server-Timing Server-Timing: cache;desc="Cache Read";dur=1.2, db;dur=3.4, app;dur=2.3
Google Chrome の DevTools でも確認できた❗️
活用事例
Server Timing の活用事例を探してみたら CDN (Content Delivery Network) でよくサポートされていた.例えば Amazon CloudFront や Akamai など.確かにキャッシュ関連は詳細に情報を取得できると良さそう.
サービスだと Ameba News で HTTP ヘッダー Server-Timing
を返してるというブログ記事があって,実際に確認できた.Fastly というメトリクス名になっていた.
$ curl --head -s https://news.ameba.jp/entry/xxx/ | grep server-timing server-timing: HIT-CLUSTER, fastly;desc="Edge time";dur=1 $ curl --head -s https://news.ameba.jp/entry/xxx/ | grep server-timing server-timing: HIT, fastly;desc="Edge time";dur=0
他にはどんな活用事例があるだろう〜