diff options
Diffstat (limited to 'system')
-rw-r--r-- | system/api/analytics/batch.go | 47 | ||||
-rw-r--r-- | system/api/analytics/init.go | 39 | ||||
-rw-r--r-- | system/api/server.go | 14 |
3 files changed, 79 insertions, 21 deletions
diff --git a/system/api/analytics/batch.go b/system/api/analytics/batch.go new file mode 100644 index 0000000..1fee247 --- /dev/null +++ b/system/api/analytics/batch.go @@ -0,0 +1,47 @@ +package analytics + +import ( + "encoding/json" + "strconv" + + "github.com/boltdb/bolt" +) + +// batchInsert is effectively a specialized version of SetContentMulti from the +// db package, iterating over a []apiRequest instead of []url.Values +func batchInsert(batch []apiRequest) error { + err := store.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("requests")) + if err != nil { + return err + } + + for _, apiReq := range batch { + // get the next available ID and convert to string + // also set effectedID to int of ID + id, err := b.NextSequence() + if err != nil { + return err + } + cid := strconv.FormatUint(id, 10) + + j, err := json.Marshal(apiReq) + if err != nil { + return err + } + + err = b.Put([]byte(cid), j) + if err != nil { + return err + } + } + + return nil + + }) + if err != nil { + return err + } + + return nil +} diff --git a/system/api/analytics/init.go b/system/api/analytics/init.go index c351bed..eaac246 100644 --- a/system/api/analytics/init.go +++ b/system/api/analytics/init.go @@ -15,6 +15,7 @@ import ( type apiRequest struct { URL string `json:"url"` Method string `json:"http_method"` + Origin string `json:"origin"` RemoteAddr string `json:"ip_address"` Timestamp int64 `json:"timestamp"` External bool `json:"external"` @@ -26,19 +27,24 @@ var ( ) // Record queues an apiRequest for metrics -func Record(req *http.Request) { - external := strings.Contains(req.URL.Path, "/external/") - - r := apiRequest{ - URL: req.URL.String(), - Method: req.Method, - RemoteAddr: req.RemoteAddr, - Timestamp: time.Now().Unix() * 1000, - External: external, - } +func Record(next http.HandlerFunc) http.HandlerFunc { + return func(res http.ResponseWriter, req *http.Request) { + external := strings.Contains(req.URL.Path, "/external/") + + r := apiRequest{ + URL: req.URL.String(), + Method: req.Method, + Origin: req.Header.Get("Origin"), + RemoteAddr: req.RemoteAddr, + Timestamp: time.Now().Unix() * 1000, + External: external, + } - // put r on buffered recordChan to take advantage of batch insertion in DB - recordChan <- r + // put r on buffered recordChan to take advantage of batch insertion in DB + recordChan <- r + + next.ServeHTTP(res, req) + } } @@ -64,10 +70,6 @@ func Init() { go serve() - err = store.Update(func(tx *bolt.Tx) error { - - return nil - }) if err != nil { log.Fatalln(err) } @@ -93,6 +95,11 @@ func serve() { reqs = append(reqs, <-recordChan) } + err := batchInsert(reqs) + if err != nil { + log.Println(err) + } + case <-pruneDBTimer.C: default: diff --git a/system/api/server.go b/system/api/server.go index 816bc21..bfd8469 100644 --- a/system/api/server.go +++ b/system/api/server.go @@ -1,14 +1,18 @@ package api -import "net/http" +import ( + "net/http" + + a "github.com/bosssauce/ponzu/system/api/analytics" +) // Run adds Handlers to default http listener for API func Run() { - http.HandleFunc("/api/types", CORS(typesHandler)) + http.HandleFunc("/api/types", CORS(a.Record(typesHandler))) - http.HandleFunc("/api/posts", CORS(postsHandler)) + http.HandleFunc("/api/posts", CORS(a.Record(postsHandler))) - http.HandleFunc("/api/post", CORS(postHandler)) + http.HandleFunc("/api/post", CORS(a.Record(postHandler))) - http.HandleFunc("/api/external/posts", CORS(externalPostsHandler)) + http.HandleFunc("/api/external/posts", CORS(a.Record(externalPostsHandler))) } |