Help us understand the problem. What is going on with this article?

Goのバッチで統計を取得するAPIを用意しておくと便利

More than 3 years have passed since last update.

golangで以下のようなKillするまでずっと動くバッチがあるとします。

package main

import (
    "fmt"
    "sync"
    "time"
)

// なんかしらの処理
func someprocess() {
    somedata := []string{"a", "b", "c", "d", "e"}

    var wg sync.WaitGroup
    for _, s := range somedata {
        wg.Add(1)
        go func(val string) {
            defer wg.Done()
            fmt.Println(val)
        }(s)
    }
}

func main() {
    // ずっと動き続ける
    for {
        someprocess()
        time.Sleep(3 * time.Second)
    }
}

このとき、この処理の稼働状況を知りたくなるのが人の常なので、以下のようにhttpサーバを立てて、
jsonで統計情報を取得できるようにしておくと便利です。
(統計情報の書き込みでロックが発生しますが、処理量にもよりますがほとんど問題にならないはず。)

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "os"
    "sync"
    "time"
)

var metrics *Metrics

type Metrics struct {
    sync.RWMutex
    PID          int
    StartedAt    time.Time
    LastWorkedAt time.Time
    LoopCount    int
    DataCount    int
}

func someprocess() {
    somedata := []string{"a", "b", "c", "d", "e"}

    var wg sync.WaitGroup
    for _, s := range somedata {
        wg.Add(1)
        go func(val string) {
            defer wg.Done()
            fmt.Println(val)

            // 詳細な処理の統計を更新
            metrics.Lock()
            defer metrics.Unlock()
            metrics.DataCount++
        }(s)
    }
}

func init() {
    metrics = &Metrics{
        PID:          os.Getpid(),
        StartedAt:    time.Now(),
        LastWorkedAt: time.Now(),
        DataCount:    0,
    }
}

func MetricsHandler(w http.ResponseWriter, r *http.Request) {
    metrics.RLock()
    defer metrics.RUnlock()
    b, err := json.Marshal(metrics)
    if err != nil {
        http.Error(w, http.StatusText(500), 500)
    }

    fmt.Fprintf(w, string(b))
}

func main() {
    go func() {
        for {
            someprocess()

            // 1ループごとの統計を更新
            metrics.Lock()
            metrics.LoopCount++
            metrics.LastWorkedAt = time.Now()
            metrics.Unlock()
            time.Sleep(3 * time.Second)
        }
    }()

    // 実行状況を表示するHTTPサーバを立てる。
    port := 9001
    http.HandleFunc("/metrics", MetricsHandler)
    fmt.Printf("Listening on %d...\n", port)
    log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
}

起動後、http://localhost:9001/metricsにアクセスすると、以下のようなjsonが返ってきます。

{
  "PID": 85568,
  "StartedAt": "2015-08-31T20:41:19.326943122+09:00",
  "LastWorkedAt": "2015-08-31T20:41:43.350825325+09:00",
  "LoopCount": 9,
  "DataCount": 45
}

これを監視するとかしておくとよいのではないでしょうか。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away