mirror of https://github.com/statping/statping
pull/429/head
parent
f64fc9e682
commit
7cf239125f
|
@ -17,6 +17,7 @@ package core
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
@ -56,14 +57,14 @@ func SelectUsername(username string) (*User, error) {
|
|||
|
||||
// Delete will remove the User record from the database
|
||||
func (u *User) Delete() error {
|
||||
return Database(&User{}).Delete(u).Error()
|
||||
return database.Delete(&u)
|
||||
}
|
||||
|
||||
// Update will update the User's record in database
|
||||
func (u *User) Update() error {
|
||||
u.ApiKey = utils.NewSHA1Hash(5)
|
||||
u.ApiSecret = utils.NewSHA1Hash(10)
|
||||
return Database(&User{}).Update(u).Error()
|
||||
return database.Update(&u)
|
||||
}
|
||||
|
||||
// Create will insert a new User into the database
|
||||
|
@ -72,15 +73,16 @@ func (u *User) Create() (int64, error) {
|
|||
u.Password = utils.HashPassword(u.Password)
|
||||
u.ApiKey = utils.NewSHA1Hash(5)
|
||||
u.ApiSecret = utils.NewSHA1Hash(10)
|
||||
db := Database(&User{}).Create(u)
|
||||
if db.Error() != nil {
|
||||
return 0, db.Error()
|
||||
|
||||
user, err := database.Create(&u)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if u.Id == 0 {
|
||||
log.Errorln(fmt.Sprintf("Failed to create User %v. %v", u.Username, db.Error()))
|
||||
return 0, db.Error()
|
||||
if user.Id == 0 {
|
||||
log.Errorln(fmt.Sprintf("Failed to create User %v. %v", u.Username, err))
|
||||
return 0, err
|
||||
}
|
||||
return u.Id, db.Error()
|
||||
return u.Id, err
|
||||
}
|
||||
|
||||
// SelectAllUsers returns all users
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package database
|
||||
|
||||
import "github.com/hunterlong/statping/types"
|
||||
|
||||
type CheckinObj struct {
|
||||
*types.Checkin
|
||||
failures
|
||||
}
|
||||
|
||||
func (o *Object) AsCheckin() HitsFailures {
|
||||
return &CheckinObj{
|
||||
Checkin: o.model.(*types.Checkin),
|
||||
}
|
||||
}
|
||||
|
||||
func Checkin(id int64) (HitsFailures, error) {
|
||||
var checkin types.Checkin
|
||||
query := database.Model(&types.Checkin{}).Where("id = ?", id).Find(&checkin)
|
||||
return &CheckinObj{Checkin: &checkin}, query.Error()
|
||||
}
|
||||
|
||||
func (c *CheckinObj) Hits() *hits {
|
||||
return &hits{
|
||||
database.Model(&types.Checkin{}).Where("checkin = ?", c.Id),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CheckinObj) Failures() *failures {
|
||||
return &failures{
|
||||
database.Model(&types.Failure{}).
|
||||
Where("method = 'checkin' AND service = ?", c.Id).Order("id desc"),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
Id int64
|
||||
model interface{}
|
||||
db Database
|
||||
}
|
||||
|
||||
type HitsFailures interface {
|
||||
Hits() *hits
|
||||
Failures() *failures
|
||||
}
|
||||
|
||||
func modelId(model interface{}) int64 {
|
||||
iface := reflect.ValueOf(model)
|
||||
field := iface.Elem().FieldByName("Id")
|
||||
return field.Int()
|
||||
}
|
||||
|
||||
func toModel(model interface{}) Database {
|
||||
return database.Model(&model)
|
||||
}
|
||||
|
||||
func Create(data interface{}) (*Object, error) {
|
||||
model := toModel(data)
|
||||
query := model.Create(data)
|
||||
if query.Error() != nil {
|
||||
return nil, query.Error()
|
||||
}
|
||||
obj := &Object{
|
||||
Id: modelId(data),
|
||||
model: data,
|
||||
db: model,
|
||||
}
|
||||
return obj, query.Error()
|
||||
}
|
||||
|
||||
func Update(data interface{}) error {
|
||||
model := toModel(data)
|
||||
return model.Update(&data).Error()
|
||||
}
|
||||
|
||||
func Delete(data interface{}) error {
|
||||
model := toModel(data)
|
||||
return model.Delete(data).Error()
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types"
|
||||
)
|
||||
|
||||
type failures struct {
|
||||
DB Database
|
||||
}
|
||||
|
||||
func (f *failures) All() []*types.Failure {
|
||||
var fails []*types.Failure
|
||||
f.DB = f.DB.Find(&fails)
|
||||
return fails
|
||||
}
|
||||
|
||||
func (f *failures) Last(amount int) *types.Failure {
|
||||
var fail types.Failure
|
||||
f.DB = f.DB.Limit(amount).Find(&fail)
|
||||
return &fail
|
||||
}
|
||||
|
||||
func (f *failures) Count() int {
|
||||
var amount int
|
||||
f.DB = f.DB.Count(&amount)
|
||||
return amount
|
||||
}
|
||||
|
||||
func (f *failures) Find(data interface{}) error {
|
||||
q := f.Find(&data)
|
||||
return q
|
||||
}
|
|
@ -1,215 +1,26 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
import "github.com/hunterlong/statping/types"
|
||||
|
||||
type GroupBy struct {
|
||||
db Database
|
||||
query *GroupQuery
|
||||
type GroupObj struct {
|
||||
*types.Group
|
||||
db Database
|
||||
}
|
||||
|
||||
type GroupByer interface {
|
||||
ToTimeValue(interface{}) (*TimeVar, error)
|
||||
type Grouper interface {
|
||||
Services() Database
|
||||
}
|
||||
|
||||
type By string
|
||||
|
||||
func (b By) String() string {
|
||||
return string(b)
|
||||
func (o *Object) AsGroup() *types.Group {
|
||||
return o.model.(*types.Group)
|
||||
}
|
||||
|
||||
type GroupQuery struct {
|
||||
db Database
|
||||
Start time.Time
|
||||
End time.Time
|
||||
Group string
|
||||
Order string
|
||||
Limit int
|
||||
Offset int
|
||||
FillEmpty bool
|
||||
func (it *Db) GetGroup(id int64) (*GroupObj, error) {
|
||||
var group types.Group
|
||||
query := it.Model(&types.Group{}).Where("id = ?", id).Find(&group)
|
||||
return &GroupObj{&group, it}, query.Error()
|
||||
}
|
||||
|
||||
func (b GroupQuery) Database() Database {
|
||||
return b.db
|
||||
}
|
||||
|
||||
var (
|
||||
ByCount = By("COUNT(id) as amount")
|
||||
BySum = func(column string) By {
|
||||
return By(fmt.Sprintf("SUM(%s) as amount", column))
|
||||
}
|
||||
ByAverage = func(column string) By {
|
||||
return By(fmt.Sprintf("AVG(%s) as amount", column))
|
||||
}
|
||||
)
|
||||
|
||||
func (db *Db) GroupQuery(q *GroupQuery, by By) GroupByer {
|
||||
dbQuery := db.MultipleSelects(
|
||||
db.SelectByTime(q.Group),
|
||||
by.String(),
|
||||
).Group("timeframe")
|
||||
|
||||
return &GroupBy{dbQuery, q}
|
||||
}
|
||||
|
||||
type TimeVar struct {
|
||||
g *GroupBy
|
||||
data []*TimeValue
|
||||
}
|
||||
|
||||
func (t *TimeVar) ToValues() []*TimeValue {
|
||||
return t.data
|
||||
}
|
||||
|
||||
func (g *GroupBy) toFloatRows() []*TimeValue {
|
||||
rows, err := g.db.Rows()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var data []*TimeValue
|
||||
for rows.Next() {
|
||||
var timeframe time.Time
|
||||
amount := float64(0)
|
||||
rows.Scan(&timeframe, &amount)
|
||||
newTs := types.FixedTime(timeframe, g.duration())
|
||||
data = append(data, &TimeValue{
|
||||
Timeframe: newTs,
|
||||
Amount: amount,
|
||||
})
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (g *GroupBy) ToTimeValue(dbType interface{}) (*TimeVar, error) {
|
||||
rows, err := g.db.Rows()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data []*TimeValue
|
||||
for rows.Next() {
|
||||
var timeframe time.Time
|
||||
amount := float64(0)
|
||||
rows.Scan(&timeframe, &amount)
|
||||
newTs := types.FixedTime(timeframe, g.duration())
|
||||
data = append(data, &TimeValue{
|
||||
Timeframe: newTs,
|
||||
Amount: amount,
|
||||
})
|
||||
}
|
||||
return &TimeVar{g, data}, nil
|
||||
}
|
||||
|
||||
func (t *TimeVar) FillMissing(current, end time.Time) []*TimeValue {
|
||||
timeMap := make(map[string]float64)
|
||||
var validSet []*TimeValue
|
||||
dur := t.g.duration()
|
||||
for _, v := range t.data {
|
||||
timeMap[v.Timeframe] = v.Amount
|
||||
}
|
||||
|
||||
currentStr := types.FixedTime(current, t.g.duration())
|
||||
|
||||
for {
|
||||
var amount float64
|
||||
if timeMap[currentStr] != 0 {
|
||||
amount = timeMap[currentStr]
|
||||
}
|
||||
validSet = append(validSet, &TimeValue{
|
||||
Timeframe: currentStr,
|
||||
Amount: amount,
|
||||
})
|
||||
if current.After(end) {
|
||||
break
|
||||
}
|
||||
current = current.Add(dur)
|
||||
currentStr = types.FixedTime(current, t.g.duration())
|
||||
}
|
||||
|
||||
return validSet
|
||||
}
|
||||
|
||||
func (g *GroupBy) duration() time.Duration {
|
||||
switch g.query.Group {
|
||||
case "second":
|
||||
return types.Second
|
||||
case "minute":
|
||||
return types.Minute
|
||||
case "hour":
|
||||
return types.Hour
|
||||
case "day":
|
||||
return types.Day
|
||||
case "month":
|
||||
return types.Month
|
||||
case "year":
|
||||
return types.Year
|
||||
default:
|
||||
return types.Hour
|
||||
}
|
||||
}
|
||||
|
||||
func ParseQueries(r *http.Request, db Database) *GroupQuery {
|
||||
fields := parseGet(r)
|
||||
grouping := fields.Get("group")
|
||||
if grouping == "" {
|
||||
grouping = "hour"
|
||||
}
|
||||
startField := utils.ToInt(fields.Get("start"))
|
||||
endField := utils.ToInt(fields.Get("end"))
|
||||
limit := utils.ToInt(fields.Get("limit"))
|
||||
offset := utils.ToInt(fields.Get("offset"))
|
||||
fill, _ := strconv.ParseBool(fields.Get("fill"))
|
||||
orderBy := fields.Get("order")
|
||||
if limit == 0 {
|
||||
limit = 10000
|
||||
}
|
||||
|
||||
query := &GroupQuery{
|
||||
Start: time.Unix(startField, 0).UTC(),
|
||||
End: time.Unix(endField, 0).UTC(),
|
||||
Group: grouping,
|
||||
Order: orderBy,
|
||||
Limit: int(limit),
|
||||
Offset: int(offset),
|
||||
FillEmpty: fill,
|
||||
}
|
||||
|
||||
if query.Limit != 0 {
|
||||
db = db.Limit(query.Limit)
|
||||
}
|
||||
if query.Offset > 0 {
|
||||
db = db.Offset(query.Offset)
|
||||
}
|
||||
if !query.Start.IsZero() && !query.End.IsZero() {
|
||||
db = db.Where("created_at BETWEEN ? AND ?", db.FormatTime(query.Start), db.FormatTime(query.End))
|
||||
} else {
|
||||
if !query.Start.IsZero() {
|
||||
db = db.Where("created_at > ?", db.FormatTime(query.Start))
|
||||
}
|
||||
if !query.End.IsZero() {
|
||||
db = db.Where("created_at < ?", db.FormatTime(query.End))
|
||||
}
|
||||
}
|
||||
if query.Order != "" {
|
||||
db = db.Order(query.Order)
|
||||
}
|
||||
query.db = db.Debug()
|
||||
|
||||
return query
|
||||
}
|
||||
|
||||
func parseForm(r *http.Request) url.Values {
|
||||
r.ParseForm()
|
||||
return r.PostForm
|
||||
}
|
||||
|
||||
func parseGet(r *http.Request) url.Values {
|
||||
r.ParseForm()
|
||||
return r.Form
|
||||
func (it *GroupObj) Services() Database {
|
||||
return it.db.Model(&types.Service{}).Where("service = ?", it.Id)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type GroupBy struct {
|
||||
db Database
|
||||
query *GroupQuery
|
||||
}
|
||||
|
||||
type GroupByer interface {
|
||||
ToTimeValue(interface{}) (*TimeVar, error)
|
||||
}
|
||||
|
||||
type By string
|
||||
|
||||
func (b By) String() string {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
type GroupQuery struct {
|
||||
db Database
|
||||
Start time.Time
|
||||
End time.Time
|
||||
Group string
|
||||
Order string
|
||||
Limit int
|
||||
Offset int
|
||||
FillEmpty bool
|
||||
}
|
||||
|
||||
func (b GroupQuery) Database() Database {
|
||||
return b.db
|
||||
}
|
||||
|
||||
var (
|
||||
ByCount = By("COUNT(id) as amount")
|
||||
BySum = func(column string) By {
|
||||
return By(fmt.Sprintf("SUM(%s) as amount", column))
|
||||
}
|
||||
ByAverage = func(column string) By {
|
||||
return By(fmt.Sprintf("AVG(%s) as amount", column))
|
||||
}
|
||||
)
|
||||
|
||||
func (db *Db) GroupQuery(q *GroupQuery, by By) GroupByer {
|
||||
dbQuery := db.MultipleSelects(
|
||||
db.SelectByTime(q.Group),
|
||||
by.String(),
|
||||
).Group("timeframe")
|
||||
|
||||
return &GroupBy{dbQuery, q}
|
||||
}
|
||||
|
||||
type TimeVar struct {
|
||||
g *GroupBy
|
||||
data []*TimeValue
|
||||
}
|
||||
|
||||
func (t *TimeVar) ToValues() []*TimeValue {
|
||||
return t.data
|
||||
}
|
||||
|
||||
func (g *GroupBy) toFloatRows() []*TimeValue {
|
||||
rows, err := g.db.Rows()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var data []*TimeValue
|
||||
for rows.Next() {
|
||||
var timeframe time.Time
|
||||
amount := float64(0)
|
||||
rows.Scan(&timeframe, &amount)
|
||||
newTs := types.FixedTime(timeframe, g.duration())
|
||||
data = append(data, &TimeValue{
|
||||
Timeframe: newTs,
|
||||
Amount: amount,
|
||||
})
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (g *GroupBy) ToTimeValue(dbType interface{}) (*TimeVar, error) {
|
||||
rows, err := g.db.Rows()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data []*TimeValue
|
||||
for rows.Next() {
|
||||
var timeframe time.Time
|
||||
amount := float64(0)
|
||||
rows.Scan(&timeframe, &amount)
|
||||
newTs := types.FixedTime(timeframe, g.duration())
|
||||
data = append(data, &TimeValue{
|
||||
Timeframe: newTs,
|
||||
Amount: amount,
|
||||
})
|
||||
}
|
||||
return &TimeVar{g, data}, nil
|
||||
}
|
||||
|
||||
func (t *TimeVar) FillMissing(current, end time.Time) []*TimeValue {
|
||||
timeMap := make(map[string]float64)
|
||||
var validSet []*TimeValue
|
||||
dur := t.g.duration()
|
||||
for _, v := range t.data {
|
||||
timeMap[v.Timeframe] = v.Amount
|
||||
}
|
||||
|
||||
currentStr := types.FixedTime(current, t.g.duration())
|
||||
|
||||
for {
|
||||
var amount float64
|
||||
if timeMap[currentStr] != 0 {
|
||||
amount = timeMap[currentStr]
|
||||
}
|
||||
validSet = append(validSet, &TimeValue{
|
||||
Timeframe: currentStr,
|
||||
Amount: amount,
|
||||
})
|
||||
if current.After(end) {
|
||||
break
|
||||
}
|
||||
current = current.Add(dur)
|
||||
currentStr = types.FixedTime(current, t.g.duration())
|
||||
}
|
||||
|
||||
return validSet
|
||||
}
|
||||
|
||||
func (g *GroupBy) duration() time.Duration {
|
||||
switch g.query.Group {
|
||||
case "second":
|
||||
return types.Second
|
||||
case "minute":
|
||||
return types.Minute
|
||||
case "hour":
|
||||
return types.Hour
|
||||
case "day":
|
||||
return types.Day
|
||||
case "month":
|
||||
return types.Month
|
||||
case "year":
|
||||
return types.Year
|
||||
default:
|
||||
return types.Hour
|
||||
}
|
||||
}
|
||||
|
||||
func ParseQueries(r *http.Request, db Database) *GroupQuery {
|
||||
fields := parseGet(r)
|
||||
grouping := fields.Get("group")
|
||||
if grouping == "" {
|
||||
grouping = "hour"
|
||||
}
|
||||
startField := utils.ToInt(fields.Get("start"))
|
||||
endField := utils.ToInt(fields.Get("end"))
|
||||
limit := utils.ToInt(fields.Get("limit"))
|
||||
offset := utils.ToInt(fields.Get("offset"))
|
||||
fill, _ := strconv.ParseBool(fields.Get("fill"))
|
||||
orderBy := fields.Get("order")
|
||||
if limit == 0 {
|
||||
limit = 10000
|
||||
}
|
||||
|
||||
query := &GroupQuery{
|
||||
Start: time.Unix(startField, 0).UTC(),
|
||||
End: time.Unix(endField, 0).UTC(),
|
||||
Group: grouping,
|
||||
Order: orderBy,
|
||||
Limit: int(limit),
|
||||
Offset: int(offset),
|
||||
FillEmpty: fill,
|
||||
}
|
||||
|
||||
if query.Limit != 0 {
|
||||
db = db.Limit(query.Limit)
|
||||
}
|
||||
if query.Offset > 0 {
|
||||
db = db.Offset(query.Offset)
|
||||
}
|
||||
if !query.Start.IsZero() && !query.End.IsZero() {
|
||||
db = db.Where("created_at BETWEEN ? AND ?", db.FormatTime(query.Start), db.FormatTime(query.End))
|
||||
} else {
|
||||
if !query.Start.IsZero() {
|
||||
db = db.Where("created_at > ?", db.FormatTime(query.Start))
|
||||
}
|
||||
if !query.End.IsZero() {
|
||||
db = db.Where("created_at < ?", db.FormatTime(query.End))
|
||||
}
|
||||
}
|
||||
if query.Order != "" {
|
||||
db = db.Order(query.Order)
|
||||
}
|
||||
query.db = db.Debug()
|
||||
|
||||
return query
|
||||
}
|
||||
|
||||
func parseForm(r *http.Request) url.Values {
|
||||
r.ParseForm()
|
||||
return r.PostForm
|
||||
}
|
||||
|
||||
func parseGet(r *http.Request) url.Values {
|
||||
r.ParseForm()
|
||||
return r.Form
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package database
|
||||
|
||||
import "github.com/hunterlong/statping/types"
|
||||
|
||||
type Group struct {
|
||||
db Database
|
||||
group *types.Group
|
||||
}
|
||||
|
||||
type Groupser interface {
|
||||
Services() Database
|
||||
}
|
||||
|
||||
func (it *Db) GetGroup(id int64) (Groupser, error) {
|
||||
var group types.Group
|
||||
query := it.Model(&types.Group{}).Where("id = ?", id).Find(&group)
|
||||
return &Group{it, &group}, query.Error()
|
||||
}
|
||||
|
||||
func (it *Group) Services() Database {
|
||||
return it.db.Model(&types.Service{}).Where("group = ?", it.group.Id)
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package database
|
||||
|
||||
import "github.com/hunterlong/statping/types"
|
||||
|
||||
type hits struct {
|
||||
DB Database
|
||||
}
|
||||
|
||||
func (h *hits) All() []*types.Hit {
|
||||
var fails []*types.Hit
|
||||
h.DB = h.DB.Find(&fails)
|
||||
return fails
|
||||
}
|
||||
|
||||
func (h *hits) Last(amount int) *types.Hit {
|
||||
var hits types.Hit
|
||||
h.DB = h.DB.Limit(amount).Find(&hits)
|
||||
return &hits
|
||||
}
|
||||
|
||||
func (h *hits) Count() int {
|
||||
var amount int
|
||||
h.DB = h.DB.Count(&amount)
|
||||
return amount
|
||||
}
|
||||
|
||||
func (h *hits) Find(data interface{}) error {
|
||||
q := h.Find(&data)
|
||||
return q
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package database
|
||||
|
||||
import "github.com/hunterlong/statping/types"
|
||||
|
||||
type IncidentObj struct {
|
||||
*types.Incident
|
||||
db Database
|
||||
}
|
||||
|
||||
func (o *IncidentObj) AsIncident() *types.Incident {
|
||||
return o.Incident
|
||||
}
|
||||
|
||||
func Incident(id int64) (*IncidentObj, error) {
|
||||
var incident types.Incident
|
||||
query := database.Model(&types.Incident{}).Where("id = ?", id).Find(&incident)
|
||||
return &IncidentObj{Incident: &incident, db: query}, query.Error()
|
||||
}
|
|
@ -3,25 +3,29 @@ package database
|
|||
import "github.com/hunterlong/statping/types"
|
||||
|
||||
type ServiceObj struct {
|
||||
db Database
|
||||
service *types.Service
|
||||
*types.Service
|
||||
failures
|
||||
}
|
||||
|
||||
type Servicer interface {
|
||||
Failures() Database
|
||||
Hits() Database
|
||||
func (o *Object) AsService() *types.Service {
|
||||
return o.model.(*types.Service)
|
||||
}
|
||||
|
||||
func Service(id int64) (Servicer, error) {
|
||||
func Service(id int64) (HitsFailures, error) {
|
||||
var service types.Service
|
||||
query := database.Model(&types.Service{}).Where("id = ?", id).Find(&service)
|
||||
return &ServiceObj{query, &service}, query.Error()
|
||||
return &ServiceObj{Service: &service}, query.Error()
|
||||
}
|
||||
|
||||
func (s *ServiceObj) Failures() Database {
|
||||
return database.Model(&types.Failure{}).Where("service = ?", s.service.Id)
|
||||
func (s *ServiceObj) Hits() *hits {
|
||||
return &hits{
|
||||
database.Model(&types.Hit{}).Where("service = ?", s.Id),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ServiceObj) Hits() Database {
|
||||
return database.Model(&types.Hit{}).Where("service = ?", s.service.Id)
|
||||
func (s *ServiceObj) Failures() *failures {
|
||||
return &failures{
|
||||
database.Model(&types.Failure{}).
|
||||
Where("method != 'checkin' AND service = ?", s.Id).Order("id desc"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package database
|
||||
|
||||
import "github.com/hunterlong/statping/types"
|
||||
|
||||
type UserObj struct {
|
||||
*types.User
|
||||
}
|
||||
|
||||
func (o *Object) AsUser() *UserObj {
|
||||
return &UserObj{
|
||||
User: o.model.(*types.User),
|
||||
}
|
||||
}
|
||||
|
||||
func User(id int64) (*UserObj, error) {
|
||||
var user types.User
|
||||
query := database.Model(&types.User{}).Where("id = ?", id).Find(&user)
|
||||
return &UserObj{User: &user}, query.Error()
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/hunterlong/statping/core"
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
@ -11,6 +12,39 @@ var (
|
|||
basePath = "/"
|
||||
)
|
||||
|
||||
type HandlerFunc func(Responder, *Request)
|
||||
|
||||
func (f HandlerFunc) ServeHTTP(w Responder, r *Request) {
|
||||
f(w, r)
|
||||
}
|
||||
|
||||
type Handler interface {
|
||||
ServeHTTP(Responder, *Request)
|
||||
}
|
||||
|
||||
type Responder struct {
|
||||
Code int // the HTTP response code from WriteHeader
|
||||
HeaderMap http.Header // the HTTP response headers
|
||||
Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
|
||||
Flushed bool
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
*http.Request
|
||||
}
|
||||
|
||||
func (r Responder) Header() http.Header {
|
||||
return r.HeaderMap
|
||||
}
|
||||
|
||||
func (r Responder) Write(p []byte) (int, error) {
|
||||
return r.Body.Write(p)
|
||||
}
|
||||
|
||||
func (r Responder) WriteHeader(statusCode int) {
|
||||
r.Code = statusCode
|
||||
}
|
||||
|
||||
func parseForm(r *http.Request) url.Values {
|
||||
r.ParseForm()
|
||||
return r.PostForm
|
||||
|
|
|
@ -130,8 +130,8 @@ func readOnly(handler func(w http.ResponseWriter, r *http.Request), redirect boo
|
|||
}
|
||||
|
||||
// cached is a middleware function that accepts a duration and content type and will cache the response of the original request
|
||||
func cached(duration, contentType string, handler func(w http.ResponseWriter, r *http.Request)) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
func cached(duration, contentType string, handler func(w Responder, r *Request)) Responder {
|
||||
return HandlerFunc(func(w Responder, r *Request) {
|
||||
content := CacheStorage.Get(r.RequestURI)
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
|
|
@ -150,7 +150,7 @@ func apiServiceRunningHandler(w http.ResponseWriter, r *http.Request) {
|
|||
sendJsonAction(service, "running", w, r)
|
||||
}
|
||||
|
||||
func apiServiceDataHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func apiServiceDataHandler(w Responder, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
service, err := database.Service(utils.ToInt(vars["id"]))
|
||||
if err != nil {
|
||||
|
@ -158,7 +158,7 @@ func apiServiceDataHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
groupQuery := database.ParseQueries(r, service.Hits())
|
||||
groupQuery := database.ParseQueries(r, service.Hits().DB)
|
||||
|
||||
obj := core.GraphData(groupQuery, &types.Hit{}, database.ByAverage("latency"))
|
||||
returnJson(obj, w, r)
|
||||
|
@ -171,7 +171,7 @@ func apiServiceFailureDataHandler(w http.ResponseWriter, r *http.Request) {
|
|||
sendErrorJson(errors.New("service data not found"), w, r)
|
||||
return
|
||||
}
|
||||
groupQuery := database.ParseQueries(r, service.Failures())
|
||||
groupQuery := database.ParseQueries(r, service.Hits().DB)
|
||||
|
||||
obj := core.GraphData(groupQuery, &types.Failure{}, database.ByCount)
|
||||
returnJson(obj, w, r)
|
||||
|
@ -184,7 +184,7 @@ func apiServicePingDataHandler(w http.ResponseWriter, r *http.Request) {
|
|||
sendErrorJson(errors.New("service data not found"), w, r)
|
||||
return
|
||||
}
|
||||
groupQuery := database.ParseQueries(r, service.Hits())
|
||||
groupQuery := database.ParseQueries(r, service.Hits().DB)
|
||||
|
||||
obj := core.GraphData(groupQuery, &types.Hit{}, database.ByAverage("ping_time"))
|
||||
returnJson(obj, w, r)
|
||||
|
@ -274,7 +274,7 @@ func joinServices(srvs []types.ServiceInterface) []*types.Service {
|
|||
return services
|
||||
}
|
||||
|
||||
func servicesDeleteFailuresHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func servicesDeleteFailuresHandler(w Responder, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
service := core.SelectService(utils.ToInt(vars["id"]))
|
||||
if service == nil {
|
||||
|
@ -293,8 +293,12 @@ func apiServiceFailuresHandler(r *http.Request) interface{} {
|
|||
return errors.New("service not found")
|
||||
}
|
||||
|
||||
service.Hits()
|
||||
|
||||
service.Failures()
|
||||
|
||||
var fails []types.Failure
|
||||
service.Failures().Requests(r).Find(&fails)
|
||||
service.Failures().DB.Requests(r).Find(&fails)
|
||||
return fails
|
||||
}
|
||||
|
||||
|
|
|
@ -30,11 +30,11 @@ type User struct {
|
|||
Admin NullBool `gorm:"column:administrator" json:"admin,omitempty"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||
UserInterface `gorm:"-" json:"-"`
|
||||
DatabaseInter `gorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
// UserInterface interfaces the Db functions
|
||||
type UserInterface interface {
|
||||
type DatabaseInter interface {
|
||||
Create() (int64, error)
|
||||
Update() error
|
||||
Delete() error
|
||||
|
|
Loading…
Reference in New Issue