LoginSignup
3
2

More than 5 years have passed since last update.

golang Echoで使えるstats handlerを作ってみた

Last updated at Posted at 2017-12-14

golangのパフォーマンスを見れるライブラリがないか探していて、
golang-stats-api-handlerというパッケージを見つけました。

golang-stats-api-handlerを利用してみる

まずはInstallから

$ go get -u github.com/fukata/golang-stats-api-handler

以下がnet/httpを利用して書いたコードです。

main.go
package main

import (
        "github.com/fukata/golang-stats-api-handler"
        "net/http"
)

func main() {
        http.HandleFunc("/stats", stats_api.Handler)
        http.ListenAndServe(":8000", nil)
}

localhost:8000/statsにアクセスすると以下のように表示されます。

$ curl -i localhost:8000/stats
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Date: Thu, 14 Dec 2017 13:43:20 GMT
Content-Length: 520

{
  "time": 1513259000865514903,
  "go_version": "go1.8.3",
  "go_os": "darwin",
  "go_arch": "amd64",
  "cpu_num": 4,
  "goroutine_num": 4,
  "gomaxprocs": 4,
  "cgo_call_num": 1,
  "memory_alloc": 383784,
  "memory_total_alloc": 383784,
  "memory_sys": 3084288,
  "memory_lookups": 15,
  "memory_mallocs": 5071,
  "memory_frees": 140,
  "memory_stack": 327680,
  "heap_alloc": 383784,
  "heap_sys": 1769472,
  "heap_idle": 950272,
  "heap_inuse": 819200,
  "heap_released": 917504,
  "heap_objects": 4931,
  "gc_next": 4473924,
  "gc_last": 0,
  "gc_num": 0,
  "gc_per_second": 0,
  "gc_pause_per_second": 0,
  "gc_pause": []
}

メモリなどの情報を取得することができました。
apiを追加するだけなのでとても簡単に利用することができます。
これだけでも十分使いやすいライブラリなのですが、
echoなどのフレームワークに組み込むとなるとHandlerがフレームワーク独自のものなのでそのままでは使えません。

echoにstatsを確認するようのapiを実装

では、echoにstats確認用apiを追加してみます。

main.go
package main

import (
    "net/http"

    "github.com/fukata/golang-stats-api-handler"
    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.GET("/hello", hello)
    e.GET("/stats", stats_api.Handler)
    e.Start(":8000")
}

func hello() echo.HandlerFunc {
    return func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello World!")
    }
}

このまま実行すると

$ go run main.go
# command-line-arguments
./main.go:12: cannot use stats_api.Handler (type func(http.ResponseWriter, *http.Request)) as type echo.HandlerFunc in argument to e.GET

と表示されて実行することができません。
なので以下のように書き換えてみます。

main.go
package main

import (
    "log"
    "net/http"

    "github.com/fukata/golang-stats-api-handler"
    "github.com/labstack/echo"
)

func main() {
    go func() {
        http.HandlerFunc("/stats", stats_api.Handler)
        log.Fatal(http.ListenAndServe(":8080", nil))
    }()

    e := echo.New()
    e.GET("/hello", hello)
    e.Start(":8000")
}

func hello() echo.HandlerFunc {
    return func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello World!")
    }
}

これで実行すると以下のように結果を取得することができます。

$ go run main.go
$ curl -i localhost:8080/stats
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Date: Thu, 14 Dec 2017 13:43:20 GMT
Content-Length: 520

{
  "time": 1513259000865514903,
  "go_version": "go1.8.3",
  "go_os": "darwin",
  "go_arch": "amd64",
  "cpu_num": 4,
  "goroutine_num": 4,
  "gomaxprocs": 4,
  "cgo_call_num": 1,
  "memory_alloc": 383784,
  "memory_total_alloc": 383784,
  "memory_sys": 3084288,
  "memory_lookups": 15,
  "memory_mallocs": 5071,
  "memory_frees": 140,
  "memory_stack": 327680,
  "heap_alloc": 383784,
  "heap_sys": 1769472,
  "heap_idle": 950272,
  "heap_inuse": 819200,
  "heap_released": 917504,
  "heap_objects": 4931,
  "gc_next": 4473924,
  "gc_last": 0,
  "gc_num": 0,
  "gc_per_second": 0,
  "gc_pause_per_second": 0,
  "gc_pause": []
}

これでメモリなどの情報をフレームワークを利用したapiでも取得することができました。
しかし、ここでgroutine使うのもなーって感じがするのでecho用のHandlerをライブラリ化してみました。

echo用のHandlerを実装したライブラリ

githubにHandler用のパッケージを作成しました。

まずはinstall

go get -u github.com/y-ogura/stats-handler

コードに書くと下記のようになります。

main.go
package main

import (
    "net/http"

    "github.com/labstack/echo"
    "github.com/y-ogura/stats-handler"
)

func main() {
    e := echo.New()
    e.GET("/hello", hello())
    e.GET("/stats", stats_handler.EchoStatsHandler)
    e.Start(":8000")
}

func hello() echo.HandlerFunc {
    return func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello World!")
    }
}

コードの見た目も多少スッキリしました。
ポートも余計に使用しなくて済みました。
実行結果も問題なく取得することができます。

$ go run main.go
$ curl -i localhost:8000/stats
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Date: Thu, 14 Dec 2017 13:43:20 GMT
Content-Length: 520

{
  "time": 1513259000865514903,
  "go_version": "go1.8.3",
  "go_os": "darwin",
  "go_arch": "amd64",
  "cpu_num": 4,
  "goroutine_num": 4,
  "gomaxprocs": 4,
  "cgo_call_num": 1,
  "memory_alloc": 383784,
  "memory_total_alloc": 383784,
  "memory_sys": 3084288,
  "memory_lookups": 15,
  "memory_mallocs": 5071,
  "memory_frees": 140,
  "memory_stack": 327680,
  "heap_alloc": 383784,
  "heap_sys": 1769472,
  "heap_idle": 950272,
  "heap_inuse": 819200,
  "heap_released": 917504,
  "heap_objects": 4931,
  "gc_next": 4473924,
  "gc_last": 0,
  "gc_num": 0,
  "gc_per_second": 0,
  "gc_pause_per_second": 0,
  "gc_pause": []
}

さいごに

こんな感じでフレームワークを利用していてもgolang-stats-api-handlerが使えるようになりました。
ちょっとしたときに確認したいときにapiを追加しておけば簡単に確認できるのでgolang-stats-api-handlerは普段から使っています。
普段はgoaで開発を行っているのでgoa用のHandlerも作る予定でいます。
まだ、パフォーマンスチェックに関しては知識不足が多いので、もっといい方法あるよって方や良いツール知ってるよって方がいましたらコメントをお待ちしています。

3
2
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
3
2