Org stat endpoints & queries
This commit is contained in:
		
							parent
							
								
									7d38440126
								
							
						
					
					
						commit
						3e27fd11ae
					
				@ -15,7 +15,7 @@ type Contrib struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const saveContribQuery = `
 | 
			
		||||
insert into contributions (week, author, owner, repo, commits, additions, deletions)
 | 
			
		||||
insert into contribs (week, author, owner, repo, commits, additions, deletions)
 | 
			
		||||
values (:week, :author, :owner, :repo, :commits, :additions, :deletions)
 | 
			
		||||
on duplicate key update
 | 
			
		||||
commits=values(commits), additions=values(additions), deletions=values(deletions)`
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								db/db.go
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								db/db.go
									
									
									
									
									
								
							@ -34,9 +34,13 @@ func mustSelect(dest interface{}, query string, args ...interface{}) {
 | 
			
		||||
func measure(op string, start time.Time) {
 | 
			
		||||
	duration := time.Since(start).Nanoseconds()
 | 
			
		||||
	outcome := "succeeded"
 | 
			
		||||
	if err := recover(); err != nil {
 | 
			
		||||
	err := recover()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		outcome = "failed"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Printf("Operation %s %s; time: %d (%dms)\n", op, outcome, duration, duration/1000000)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										163
									
								
								db/stat.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								db/stat.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,163 @@
 | 
			
		||||
package db
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type (
 | 
			
		||||
	StatRequest struct {
 | 
			
		||||
		Org  string
 | 
			
		||||
		Team string
 | 
			
		||||
		User string
 | 
			
		||||
		From int64
 | 
			
		||||
		To   int64
 | 
			
		||||
	}
 | 
			
		||||
	StatItem struct {
 | 
			
		||||
		Item  string `json:"item"`
 | 
			
		||||
		Value int    `json:"value"`
 | 
			
		||||
	}
 | 
			
		||||
	StatPoint struct {
 | 
			
		||||
		StatItem
 | 
			
		||||
		Timestamp uint64 `json:"ts"`
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const orgReposTopQuery = `
 | 
			
		||||
select
 | 
			
		||||
    c.repo as item,
 | 
			
		||||
    sum(c.commits) as value
 | 
			
		||||
from contribs c
 | 
			
		||||
join members m on
 | 
			
		||||
    c.author = m.user and
 | 
			
		||||
    c.owner = m.org
 | 
			
		||||
where
 | 
			
		||||
    m.id is not null and
 | 
			
		||||
    c.owner = ? and
 | 
			
		||||
    c.week >= ? and
 | 
			
		||||
    c.week <= ?
 | 
			
		||||
group by item
 | 
			
		||||
order by value desc`
 | 
			
		||||
 | 
			
		||||
const orgReposActivityQuery = `
 | 
			
		||||
select
 | 
			
		||||
    c.week as ts,
 | 
			
		||||
    c.repo as item,
 | 
			
		||||
    sum(c.commits) as value
 | 
			
		||||
from contribs c
 | 
			
		||||
join members m on
 | 
			
		||||
    c.author = m.user and
 | 
			
		||||
    c.owner = m.org
 | 
			
		||||
where
 | 
			
		||||
    m.id is not null and
 | 
			
		||||
    c.owner = ? and
 | 
			
		||||
    c.week >= ? and
 | 
			
		||||
    c.week <= ?
 | 
			
		||||
group by ts, item
 | 
			
		||||
order by ts, item`
 | 
			
		||||
 | 
			
		||||
const orgTeamsTopQuery = `
 | 
			
		||||
select
 | 
			
		||||
    t.name as item,
 | 
			
		||||
    sum(c.commits) value
 | 
			
		||||
from contribs c
 | 
			
		||||
join members m on
 | 
			
		||||
    c.author = m.user and
 | 
			
		||||
    c.owner = m.org
 | 
			
		||||
join teams t on
 | 
			
		||||
    m.team_id = t.id
 | 
			
		||||
where
 | 
			
		||||
    m.id is not null and
 | 
			
		||||
    c.owner = ? and
 | 
			
		||||
    c.week >= ? and
 | 
			
		||||
    c.week <= ?
 | 
			
		||||
group by item
 | 
			
		||||
order by value desc`
 | 
			
		||||
 | 
			
		||||
const orgTeamsActivityQuery = `
 | 
			
		||||
select
 | 
			
		||||
    c.week as ts,
 | 
			
		||||
    t.name as item,
 | 
			
		||||
    sum(c.commits) as value
 | 
			
		||||
from contribs c
 | 
			
		||||
join members m on
 | 
			
		||||
    c.author = m.user and
 | 
			
		||||
    c.owner = m.org
 | 
			
		||||
join teams t on
 | 
			
		||||
    m.team_id = t.id
 | 
			
		||||
where
 | 
			
		||||
    m.id is not null and
 | 
			
		||||
    c.owner = ? and
 | 
			
		||||
    c.week >= ? and
 | 
			
		||||
    c.week <= ?
 | 
			
		||||
group by ts, item
 | 
			
		||||
order by ts, item`
 | 
			
		||||
 | 
			
		||||
const orgUsersTopQuery = `
 | 
			
		||||
select
 | 
			
		||||
    c.author as item,
 | 
			
		||||
    sum(c.commits) value
 | 
			
		||||
from contribs c
 | 
			
		||||
join members m on
 | 
			
		||||
    c.author = m.user and
 | 
			
		||||
    c.owner = m.org
 | 
			
		||||
where
 | 
			
		||||
    m.id is not null and
 | 
			
		||||
    c.owner = ? and
 | 
			
		||||
    c.week >= ? and
 | 
			
		||||
    c.week <= ?
 | 
			
		||||
group by item
 | 
			
		||||
order by value desc`
 | 
			
		||||
 | 
			
		||||
func StatOrgReposTop(r *StatRequest) (res []StatItem) {
 | 
			
		||||
	defer measure("StatOrgReposTop", time.Now())
 | 
			
		||||
	mustSelect(&res, orgReposTopQuery, r.Org, r.From, r.To)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StatOrgReposActivity(r *StatRequest) (res []StatPoint) {
 | 
			
		||||
	defer measure("StatOrgReposActivity", time.Now())
 | 
			
		||||
	mustSelect(&res, orgReposActivityQuery, r.Org, r.From, r.To)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StatOrgTeamsTop(r *StatRequest) (res []StatItem) {
 | 
			
		||||
	defer measure("StatOrgTeamsTop", time.Now())
 | 
			
		||||
	mustSelect(&res, orgTeamsTopQuery, r.Org, r.From, r.To)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StatOrgTeamsActivity(r *StatRequest) (res []StatPoint) {
 | 
			
		||||
	defer measure("StatOrgTeamsActivity", time.Now())
 | 
			
		||||
	mustSelect(&res, orgTeamsActivityQuery, r.Org, r.From, r.To)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StatOrgUsersTop(r *StatRequest) (res []StatItem) {
 | 
			
		||||
	defer measure("StatOrgUsersTop", time.Now())
 | 
			
		||||
	mustSelect(&res, orgUsersTopQuery, r.Org, r.From, r.To)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ParseRequest(r *http.Request) *StatRequest {
 | 
			
		||||
	var err error
 | 
			
		||||
	var from, to int64
 | 
			
		||||
	if len(r.FormValue("from")) > 0 {
 | 
			
		||||
		if from, err = strconv.ParseInt(r.FormValue("from"), 10, 64); err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(r.FormValue("to")) > 0 {
 | 
			
		||||
		if to, err = strconv.ParseInt(r.FormValue("to"), 10, 64); err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return &StatRequest{
 | 
			
		||||
		Org:  r.FormValue("org"),
 | 
			
		||||
		Team: r.FormValue("team"),
 | 
			
		||||
		User: r.FormValue("user"),
 | 
			
		||||
		From: from,
 | 
			
		||||
		To:   to,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -6,6 +6,7 @@ import (
 | 
			
		||||
 | 
			
		||||
type Team struct {
 | 
			
		||||
	ID    uint64 `json:"id"`
 | 
			
		||||
	Slug  string `json:"slug"`
 | 
			
		||||
	Owner string `json:"owner"`
 | 
			
		||||
	Name  string `json:"name"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,11 @@ func init() {
 | 
			
		||||
	http.HandleFunc("/api/orgs", apiOrgsHandler)
 | 
			
		||||
	http.HandleFunc("/api/teams", apiTeamsHandler)
 | 
			
		||||
	http.HandleFunc("/api/repos", apiReposHandler)
 | 
			
		||||
	http.HandleFunc("/api/stat/repos/top", statOrgReposTop)
 | 
			
		||||
	http.HandleFunc("/api/stat/repos/activity", statOrgReposActivity)
 | 
			
		||||
	http.HandleFunc("/api/stat/teams/top", statOrgTeamsTop)
 | 
			
		||||
	http.HandleFunc("/api/stat/teams/activity", statOrgTeamsActivity)
 | 
			
		||||
	http.HandleFunc("/api/stat/users/top", statOrgUsersTop)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Start() {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										32
									
								
								server/stat.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								server/stat.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
package server
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/localhots/empact/db"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func statOrgReposTop(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	top := db.StatOrgReposTop(db.ParseRequest(r))
 | 
			
		||||
	respondWith(w, top)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func statOrgReposActivity(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	activity := db.StatOrgReposActivity(db.ParseRequest(r))
 | 
			
		||||
	respondWith(w, activity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func statOrgTeamsTop(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	top := db.StatOrgTeamsTop(db.ParseRequest(r))
 | 
			
		||||
	respondWith(w, top)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func statOrgTeamsActivity(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	activity := db.StatOrgTeamsActivity(db.ParseRequest(r))
 | 
			
		||||
	respondWith(w, activity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func statOrgUsersTop(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	top := db.StatOrgUsersTop(db.ParseRequest(r))
 | 
			
		||||
	respondWith(w, top)
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user