golangでparseのinstall数を集計するスクリプト書いた
書いた.
Parse.com使ってて(オンプレ移行は成功しそう),Parseに突っ込んでるログからインストール数の集計をできるようなコマンドを書いてみた.リポジトリに上げたいところなんだけどまだ,キーがハードコードされてるので治ったら.
要件
package main
package main import ( "fmt" "time" "bitbucket.org/xxx/xxxx/parseclient" // 見せられないよ ) var ( defaultApplicationID = "applicationID" defaultRestAPIKey = "restAPIKey" ) func printMonthlyCount(date string, count int) { fmt.Println(date, ": ", count) } func main() { client := parseclient.NewClient(defaultApplicationID, defaultRestAPIKey) androidCount, iosCount, dmAndroid, dmIos, err := client.FetchCount() if err != nil { panic(err) } fmt.Println(time.Now(), "のインストール数") fmt.Println("Android:", androidCount) fmt.Println("iOS:", iosCount) fmt.Println("月ごとの集計結果") fmt.Println("Android") dmAndroid.Each(printMonthlyCount) fmt.Println("iOS") dmIos.Each(printMonthlyCount) fmt.Println("合計:", androidCount+iosCount) }
取ってきて出力.dmAndroid.Each
とdmIos.Each
については後述
package dmap
空のときにデフォルト値が設定できるようなmapを定義
さっきのEach
はここ
http://ashitani.jp/golangtips/tips_map.html#map_Default
package dmap // Dmap Dictionaly map type Dmap struct { m map[string]int } // Get 値をGet func (d Dmap) Get(key string) int { v, ok := d.m[key] if ok { return v } return 0 } // Set 値をset func (d Dmap) Set(key string, value int) { d.m[key] = value } // Each ループ回せる func (d Dmap) Each(f func(string, int)) { for key, value := range d.m { f(key, value) } } // New func func New() *Dmap { return &Dmap{map[string]int{}} }
parseからの取得
package parseclient import ( "net/url" "strconv" "time" "bitbucket.org/xxx/xxxx/dmap" "github.com/facebookgo/parse" ) type device struct { CreatedAt time.Time `json:"createdAt"` Os string `json:"os"` } type result struct { Results []device `json:"results"` } // Client インストール数問い合わせのクライアント type Client struct { parseClient parse.Client } // NewClient Client生成 func NewClient(applicationID string, restAPIKey string) *Client { return &Client{ parseClient: parse.Client{ Credentials: parse.RestAPIKey{ ApplicationID: applicationID, RestAPIKey: restAPIKey, }, }, } } // FetchCount AndroidとiOSそれぞれカウントする func (c Client) FetchCount() (int, int, *dmap.Dmap, *dmap.Dmap, error) { jst, err := time.LoadLocation("Asia/Tokyo") if err != nil { return 0, 0, nil, nil, err } count := 0 androidCount := 0 iosCount := 0 dmAndroid := dmap.New() dmIos := dmap.New() for { var res result v := make(url.Values) v.Set("skip", strconv.Itoa(count)) v.Set("limit", "100") _, err := c.parseClient.Get(&url.URL{Path: "/1/classes/install_log", RawQuery: v.Encode()}, &res) if err != nil { return 0, 0, nil, nil, err } for _, element := range res.Results { jstTime := element.CreatedAt.In(jst) key := jstTime.Format("2006-01") if element.Os == "Android" { androidCount++ dmAndroid.Set(key, dmAndroid.Get(key)+1) } if element.Os == "iPhone OS" { iosCount++ dmIos.Set(key, dmIos.Get(key)+1) } } size := len(res.Results) count += size if size != 100 { break } time.Sleep(1000) // マナー } return androidCount, iosCount, dmAndroid, dmIos, nil }
実装は至ってシンプルで,APIをskipを使ってページ制御しながら,全件みつつOS種類に応じてカウントする. 月ごとの集計がだるかったので,dmapのkeyとして月を利用することでなんとかしました.ただ問題があって月ごとの並び順がバラバラになりがちなのでなんとかしたい.