0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

プロファイラ HTTP Server-Timing のGoパッケージ go-server-timing

Last updated at Posted at 2021-02-08

サーバサイドの処理のプロファイリングをChromeのDevtoolで可視化するライブラリです。
go-server-timing

そもそも論として

HTTPプロトコルヘッダーには、Server-Timing というものがあります。ここにサーバ側で計測した値をセットして、HTTPレスポンスに一緒に仕込んでブラウザに返せば、Chrome Devtoolがいい感じに可視化してくれるわけです。

こんな感じに。

Screen Shot 2021-02-08 at 14.21.46.png

コードサンプル

実行したソースコードです。(README.mdからママ)

package main

import (
	"fmt"
	"math/rand"
	"net/http"
	"sync"
	"time"

	servertiming "github.com/mitchellh/go-server-timing"
)

func main() {
	// Our handler. In a real application this might be your root router,
	// or some subset of your router. Wrapping this ensures that all routes
	// handled by this handler have access to the server timing header struct.
	var h http.Handler = http.HandlerFunc(handler)

	// Wrap our handler with the server timing middleware
	h = servertiming.Middleware(h, nil)

	// Start!
	http.ListenAndServe(":8080", h)
}

func handler(w http.ResponseWriter, r *http.Request) {
	// Get our timing header builder from the context
	timing := servertiming.FromContext(r.Context())

	// Imagine your handler performs some tasks in a goroutine, such as
	// accessing some remote service. timing is concurrency safe so we can
	// record how long that takes. Let's simulate making 5 concurrent requests
	// to various servicse.
	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg.Add(1)
		name := fmt.Sprintf("service-%d", i)
		go func(name string) {
			// This creats a new metric and starts the timer. The Stop is
			// deferred so when the function exits it'll record the duration.
			defer timing.NewMetric(name).Start().Stop()
			time.Sleep(random(25, 75))
			wg.Done()
		}(name)
	}
	// Imagine this is just some blocking code in your main handler such
	// as a SQL query. Let's record that.
	m := timing.NewMetric("sql").WithDesc("SQL query").Start()
	time.Sleep(random(20, 50))
	m.Stop()

	// Wait for the goroutine to end
	wg.Wait()

	// You could continue recording more metrics, but let's just return now
	w.WriteHeader(200)
	w.Write([]byte("Done. Check your browser inspector timing details."))
}

func random(min, max int) time.Duration {
	return (time.Duration(rand.Intn(max-min) + min)) * time.Millisecond
}

コードの説明

41行目の

defer timing.NewMetric(name).Start().Stop()

でプロファイラを仕込んでいます。

Goのdeferで、関数をチェインした場合、最後の.Stop()のみdeferされ、.Start()は即時実行されることに注意してください。

また、deferのスコープは関数になります。38行目のgo func

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?