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
}
これを監視するとかしておくとよいのではないでしょうか。