summaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
authorSteve Manuel <nilslice@gmail.com>2016-11-01 21:36:25 -0700
committerSteve Manuel <nilslice@gmail.com>2016-11-01 21:36:25 -0700
commit6ee469616d56b069dd68391577f0cd9411abc46a (patch)
tree2ea2da04b0726706bd5b0aa81891b02f7fa1ac32 /system
parentac647e2f77d05cc015a369832c2d428ec1cd6567 (diff)
adding analytics tracking to API calls
Diffstat (limited to 'system')
-rw-r--r--system/api/analytics/batch.go47
-rw-r--r--system/api/analytics/init.go39
-rw-r--r--system/api/server.go14
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)))
}