diff --git a/core/checkin.go b/core/checkin.go
index 92905ffd..0ba060a8 100644
--- a/core/checkin.go
+++ b/core/checkin.go
@@ -20,7 +20,6 @@ import (
"github.com/ararog/timeago"
"github.com/hunterlong/statping/types"
"github.com/hunterlong/statping/utils"
- "sort"
"time"
)
@@ -94,8 +93,8 @@ func (c *Checkin) CreateFailure() (int64, error) {
PingTime: c.Expected().Seconds(),
}}
row := Database(&Failure{}).Create(&fail)
- sort.Sort(types.FailSort(c.Failures))
- c.Failures = append(c.Failures, fail)
+ //sort.Sort(types.FailSort(c.Failures))
+ //c.Failures = append(c.Failures, fail)
if len(c.Failures) > limitedFailures {
c.Failures = c.Failures[1:]
}
@@ -167,23 +166,27 @@ func (c *Checkin) AllHits() []*types.CheckinHit {
return checkins
}
-// Hits returns all of the CheckinHits for a given Checkin
-func (c *Checkin) LimitedFailures(amount int) []types.FailureInterface {
- var failures []*Failure
- var failInterfaces []types.FailureInterface
- col := Database(&types.Failure{}).Where("checkin = ?", c.Id).Where("method = 'checkin'").Limit(amount).Order("id desc")
- col.Find(&failures)
- for _, f := range failures {
- failInterfaces = append(failInterfaces, f)
- }
- return failInterfaces
-}
-
// Hits returns all of the CheckinHits for a given Checkin
func (c *Checkin) AllFailures() []*types.Failure {
var failures []*types.Failure
- col := Database(&types.Failure{}).Where("checkin = ?", c.Id).Where("method = 'checkin'").Order("id desc")
- col.Find(&failures)
+ Database(&types.Failure{}).
+ Where("checkin = ?", c.Id).
+ Where("method = 'checkin'").
+ Order("id desc").
+ Find(&failures)
+
+ return failures
+}
+
+func (c *Checkin) GetFailures(count int) []*types.Failure {
+ var failures []*types.Failure
+ Database(&types.Failure{}).
+ Where("checkin = ?", c.Id).
+ Where("method = 'checkin'").
+ Limit(count).
+ Order("id desc").
+ Find(&failures)
+
return failures
}
diff --git a/core/failures.go b/core/failures.go
index a61e8d2b..1ebc4dd9 100644
--- a/core/failures.go
+++ b/core/failures.go
@@ -18,9 +18,7 @@ package core
import (
"fmt"
"github.com/ararog/timeago"
- "github.com/hunterlong/statping/database"
"github.com/hunterlong/statping/types"
- "net/http"
"sort"
"strings"
"time"
@@ -62,10 +60,6 @@ func (s *Service) AllFailures() []types.Failure {
return fails
}
-func (s *Service) FailuresDb(r *http.Request) database.Database {
- return Database(&types.Failure{}).Where("service = ?", s.Id).QuerySearch(r).Order("id desc")
-}
-
// DeleteFailures will delete all failures for a service
func (s *Service) DeleteFailures() {
err := DbSession.Exec(`DELETE FROM failures WHERE service = ?`, s.Id)
@@ -75,13 +69,6 @@ func (s *Service) DeleteFailures() {
s.Failures = nil
}
-// LimitedFailures will return the last amount of failures from a service
-func (s *Service) LimitedFailures(amount int) []*Failure {
- var failArr []*Failure
- Database(&types.Failure{}).Where("service = ?", s.Id).Not("method = 'checkin'").Order("id desc").Limit(amount).Find(&failArr)
- return failArr
-}
-
// LimitedFailures will return the last amount of failures from a service
func (s *Service) LimitedCheckinFailures(amount int) []*Failure {
var failArr []*Failure
diff --git a/core/hits.go b/core/hits.go
index c9d9f260..573c1496 100644
--- a/core/hits.go
+++ b/core/hits.go
@@ -47,13 +47,13 @@ func (s *Service) CountHits() (int64, error) {
// Hits returns all successful hits for a service
func (s *Service) HitsQuery(r *http.Request) ([]*types.Hit, error) {
var hits []*types.Hit
- col := Database(&types.Hit{}).Where("service = ?", s.Id).QuerySearch(r).Order("id desc")
+ col := Database(&types.Hit{}).Where("service = ?", s.Id).Requests(r)
err := col.Find(&hits)
return hits, err.Error()
}
func (s *Service) HitsDb(r *http.Request) database.Database {
- return Database(&types.Hit{}).Where("service = ?", s.Id).QuerySearch(r).Order("id desc")
+ return Database(&types.Hit{}).Where("service = ?", s.Id).Requests(r).Order("id desc")
}
// Hits returns all successful hits for a service
diff --git a/core/services.go b/core/services.go
index a5427099..8e443aee 100644
--- a/core/services.go
+++ b/core/services.go
@@ -16,9 +16,7 @@
package core
import (
- "encoding/json"
"fmt"
- "github.com/ararog/timeago"
"github.com/hunterlong/statping/core/notifier"
"github.com/hunterlong/statping/database"
"github.com/hunterlong/statping/types"
@@ -58,6 +56,13 @@ func SelectService(id int64) *Service {
return nil
}
+func (s *Service) GetFailures(count int) []*Failure {
+ var fails []*Failure
+ db := Database(&types.Failure{}).Where("service = ?", s.Id)
+ db.Limit(count).Find(&fails)
+ return fails
+}
+
func (s *Service) UpdateStats() *Service {
s.Online24Hours = s.OnlineDaysPercent(1)
s.Online7Days = s.OnlineDaysPercent(7)
@@ -108,7 +113,8 @@ func (s *Service) AllCheckins() []*Checkin {
return checkin
}
-// SelectAllServices returns a slice of *core.Service to be store on []*core.Services, should only be called once on startup.
+// SelectAllServices returns a slice of *core.Service to be store on []*core.Services
+// should only be called once on startup.
func (c *Core) SelectAllServices(start bool) ([]*Service, error) {
var services []*Service
db := Database(&Service{}).Find(&services).Order("order_id desc")
@@ -122,13 +128,13 @@ func (c *Core) SelectAllServices(start bool) ([]*Service, error) {
service.Start()
service.CheckinProcess()
}
- fails := service.LimitedFailures(limitedFailures)
+ fails := service.GetFailures(limitedFailures)
for _, f := range fails {
service.Failures = append(service.Failures, f)
}
checkins := service.AllCheckins()
for _, c := range checkins {
- c.Failures = c.LimitedFailures(limitedFailures)
+ c.Failures = c.GetFailures(limitedFailures)
c.Hits = c.LimitedHits(limitedHits)
service.Checkins = append(service.Checkins, c)
}
@@ -185,8 +191,8 @@ func (s *Service) OnlineSince(ago time.Time) float32 {
}
// lastFailure returns the last Failure a service had
-func (s *Service) lastFailure() *Failure {
- limited := s.LimitedFailures(1)
+func (s *Service) lastFailure() types.FailureInterface {
+ limited := s.GetFailures(1)
if len(limited) == 0 {
return nil
}
@@ -194,29 +200,6 @@ func (s *Service) lastFailure() *Failure {
return last
}
-// SmallText returns a short description about a services status
-// service.SmallText()
-// // Online since Monday 3:04:05PM, Jan _2 2006
-func (s *Service) SmallText() string {
- last := s.LimitedFailures(1)
- //hits, _ := s.LimitedHits(1)
- zone := CoreApp.Timezone
- if s.Online {
- if len(last) == 0 {
- return fmt.Sprintf("Online since %v", utils.Timezoner(s.CreatedAt, zone).Format("Monday 3:04:05PM, Jan _2 2006"))
- } else {
- return fmt.Sprintf("Online, last Failure was %v", utils.Timezoner(last[0].CreatedAt, zone).Format("Monday 3:04:05PM, Jan _2 2006"))
- }
- }
- if len(last) > 0 {
- lastFailure := s.lastFailure()
- got, _ := timeago.TimeAgoWithTime(time.Now().UTC().Add(s.Downtime()), time.Now().UTC())
- return fmt.Sprintf("Reported offline %v, %v", got, lastFailure.ParseError())
- } else {
- return fmt.Sprintf("%v is currently offline", s.Name)
- }
-}
-
// DowntimeText will return the amount of downtime for a service based on the duration
// service.DowntimeText()
// // Service has been offline for 15 minutes
@@ -261,99 +244,24 @@ func (s *Service) Downtime() time.Duration {
return time.Duration(0)
}
if len(hits) == 0 {
- return time.Now().UTC().Sub(fail.CreatedAt.UTC())
+ return time.Now().UTC().Sub(fail.Select().CreatedAt.UTC())
}
- since := fail.CreatedAt.UTC().Sub(hits[0].CreatedAt.UTC())
+ since := fail.Select().CreatedAt.UTC().Sub(hits[0].CreatedAt.UTC())
return since
}
-// DateScanObj struct is for creating the charts.js graph JSON array
-type DateScanObj struct {
- Array []*database.DateScan `json:"data"`
-}
-
-// GraphDataRaw will return all the hits between 2 times for a Service
-func GraphHitsDataRaw(service types.ServiceInterface, query *types.GroupQuery, column string) []*database.TimeValue {
- srv := service.(*Service)
-
- dbQuery, err := Database(&types.Hit{}).
- Where("service = ?", srv.Id).
- GroupQuery(query).ToTimeValue()
+// GraphData will return all hits or failures
+func GraphData(q *database.GroupQuery, dbType interface{}, by database.By) []*database.TimeValue {
+ dbQuery, err := q.Database().GroupQuery(q, by).ToTimeValue(dbType)
if err != nil {
log.Error(err)
return nil
}
- return dbQuery.FillMissing()
-}
-
-// GraphDataRaw will return all the hits between 2 times for a Service
-func GraphFailuresDataRaw(service types.ServiceInterface, query *types.GroupQuery) []*database.TimeValue {
- srv := service.(*Service)
-
- dbQuery, err := Database(&types.Failure{}).
- Where("service = ?", srv.Id).
- GroupQuery(query).ToTimeValue()
-
- if err != nil {
- log.Error(err)
- return nil
+ if q.FillEmpty {
+ return dbQuery.FillMissing(q.Start, q.End)
}
- return dbQuery.FillMissing()
-}
-
-// ToString will convert the DateScanObj into a JSON string for the charts to render
-func (d *DateScanObj) ToString() string {
- data, err := json.Marshal(d.Array)
- if err != nil {
- log.Warnln(err)
- return "{}"
- }
- return string(data)
-}
-
-// AvgUptime24 returns a service's average online status for last 24 hours
-func (s *Service) AvgUptime24() string {
- ago := time.Now().UTC().Add(-24 * time.Hour)
- return s.AvgUptime(ago)
-}
-
-// AvgUptime returns average online status for last 24 hours
-func (s *Service) AvgUptime(ago time.Time) string {
- failed, _ := s.TotalFailuresSince(ago)
- if failed == 0 {
- return "100"
- }
- total, _ := s.TotalHitsSince(ago)
- if total == 0 {
- return "0.00"
- }
- percent := float64(failed) / float64(total) * 100
- percent = 100 - percent
- if percent < 0 {
- percent = 0
- }
- amount := fmt.Sprintf("%0.2f", percent)
- if amount == "100.00" {
- amount = "100"
- }
- return amount
-}
-
-// TotalUptime returns the total uptime percent of a service
-func (s *Service) TotalUptime() string {
- hits, _ := s.TotalHits()
- failures, _ := s.TotalFailures()
- percent := float64(failures) / float64(hits) * 100
- percent = 100 - percent
- if percent < 0 {
- percent = 0
- }
- amount := fmt.Sprintf("%0.2f", percent)
- if amount == "100.00" {
- amount = "100"
- }
- return amount
+ return dbQuery.ToValues()
}
// index returns a services index int for updating the []*core.Services slice
diff --git a/core/services_test.go b/core/services_test.go
index 728c2f7d..1e90abc3 100644
--- a/core/services_test.go
+++ b/core/services_test.go
@@ -127,12 +127,6 @@ func TestServiceOnline24Hours(t *testing.T) {
assert.True(t, service3.OnlineSince(since) > float32(49))
}
-func TestServiceSmallText(t *testing.T) {
- service := SelectService(5)
- text := service.SmallText()
- assert.Contains(t, text, "Online since")
-}
-
func TestServiceAvgUptime(t *testing.T) {
since := utils.Now().Add(-24 * time.Hour).Add(-10 * time.Minute)
service := SelectService(1)
diff --git a/database/database.go b/database/database.go
index 9494a2a4..789d62b6 100644
--- a/database/database.go
+++ b/database/database.go
@@ -2,14 +2,12 @@ package database
import (
"database/sql"
- "fmt"
"github.com/hunterlong/statping/types"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"net/http"
- "strconv"
"strings"
"time"
)
@@ -21,6 +19,10 @@ const (
TIME_DAY = "2006-01-02"
)
+var (
+ database Database
+)
+
// Database is an interface which DB implements
type Database interface {
Close() error
@@ -99,11 +101,9 @@ type Database interface {
// extra
Error() error
RowsAffected() int64
- QuerySearch(*http.Request) Database
Since(time.Time) Database
Between(time.Time, time.Time) Database
- Hits() ([]*types.Hit, error)
ToChart() ([]*DateScan, error)
SelectByTime(string) string
@@ -112,7 +112,14 @@ type Database interface {
FormatTime(t time.Time) string
ParseTime(t string) (time.Time, error)
- GroupQuery(query *types.GroupQuery) GroupByer
+ Requests(*http.Request) Database
+
+ GroupQuery(query *GroupQuery, by By) GroupByer
+}
+
+func (it *Db) Requests(r *http.Request) Database {
+ g := ParseQueries(r, it)
+ return g.db
}
func (it *Db) MultipleSelects(args ...string) Database {
@@ -120,10 +127,6 @@ func (it *Db) MultipleSelects(args ...string) Database {
return it.Select(joined)
}
-func CountAmount() string {
- return fmt.Sprintf("COUNT(id) as amount")
-}
-
type Db struct {
Database *gorm.DB
Type string
@@ -132,7 +135,11 @@ type Db struct {
// Openw is a drop-in replacement for Open()
func Openw(dialect string, args ...interface{}) (db Database, err error) {
gormdb, err := gorm.Open(dialect, args...)
- return Wrap(gormdb), err
+ if err != nil {
+ return nil, err
+ }
+ database = Wrap(gormdb)
+ return database, err
}
// Wrap wraps gorm.DB in an interface
@@ -460,8 +467,8 @@ type DateScan struct {
}
type TimeValue struct {
- Timeframe time.Time `json:"timeframe"`
- Amount int64 `json:"amount"`
+ Timeframe string `json:"timeframe"`
+ Amount float64 `json:"amount"`
}
func (it *Db) ToChart() ([]*DateScan, error) {
@@ -487,55 +494,3 @@ func (it *Db) ToChart() ([]*DateScan, error) {
}
return data, err
}
-
-func (it *Db) QuerySearch(r *http.Request) Database {
- if r == nil {
- return it
- }
- db := it.Database
- start := defaultField(r, "start")
- end := defaultField(r, "end")
- limit := defaultField(r, "limit")
- offset := defaultField(r, "offset")
- params := &Params{
- Start: start,
- End: end,
- Limit: limit,
- Offset: offset,
- }
- if params.Start != nil && params.End != nil {
- db = db.Where("created_at BETWEEN ? AND ?", time.Unix(*params.Start, 0).Format(TIME), time.Unix(*params.End, 0).UTC().Format(TIME))
- } else if params.Start != nil && params.End == nil {
- db = db.Where("created_at > ?", time.Unix(*params.Start, 0).UTC().Format(TIME))
- }
- if params.Limit != nil {
- db = db.Limit(*params.Limit)
- } else {
- db = db.Limit(10000)
- }
- if params.Offset != nil {
- db = db.Offset(*params.Offset)
- } else {
- db = db.Offset(0)
- }
- return Wrap(db)
-}
-
-type Params struct {
- Start *int64
- End *int64
- Limit *int64
- Offset *int64
-}
-
-func defaultField(r *http.Request, key string) *int64 {
- r.ParseForm()
- val := r.Form.Get(key)
- if val == "" {
- return nil
- }
-
- gg, _ := strconv.Atoi(val)
- num := int64(gg)
- return &num
-}
diff --git a/database/group.go b/database/group.go
index 543b26cd..a6df21c3 100644
--- a/database/group.go
+++ b/database/group.go
@@ -3,42 +3,60 @@ 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 *types.GroupQuery
+ query *GroupQuery
}
type GroupByer interface {
- ToTimeValue() (*TimeVar, error)
+ ToTimeValue(interface{}) (*TimeVar, error)
}
-type GroupMethod interface {
+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 = func() GroupMethod {
- return fmt.Sprintf("COUNT(id) as amount")
+ ByCount = By("COUNT(id) as amount")
+ BySum = func(column string) By {
+ return By(fmt.Sprintf("SUM(%s) as amount", column))
}
- BySum = func(column string) GroupMethod {
- return fmt.Sprintf("SUM(%s) as amount", column)
- }
- ByAverage = func(column string) GroupMethod {
- return fmt.Sprintf("SUM(%s) as amount", column)
+ ByAverage = func(column string) By {
+ return By(fmt.Sprintf("AVG(%s) as amount", column))
}
)
-func execute(db Database, query *types.GroupQuery) Database {
- return db.MultipleSelects(
- db.SelectByTime(query.Group),
- CountAmount(),
- ).Between(query.Start, query.End).Group("timeframe").Debug()
-}
+func (db *Db) GroupQuery(q *GroupQuery, by By) GroupByer {
+ dbQuery := db.MultipleSelects(
+ db.SelectByTime(q.Group),
+ by.String(),
+ ).Group("timeframe")
-func (db *Db) GroupQuery(query *types.GroupQuery) GroupByer {
- return &GroupBy{execute(db, query), query}
+ return &GroupBy{dbQuery, q}
}
type TimeVar struct {
@@ -46,64 +64,72 @@ type TimeVar struct {
data []*TimeValue
}
-func (g *GroupBy) ToTimeValue() (*TimeVar, error) {
+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 string
- var amount int64
- if err := rows.Scan(&timeframe, &amount); err != nil {
- return nil, err
- }
- createdTime, _ := g.db.ParseTime(timeframe)
+ var timeframe time.Time
+ amount := float64(0)
+ rows.Scan(&timeframe, &amount)
+ newTs := types.FixedTime(timeframe, g.duration())
data = append(data, &TimeValue{
- Timeframe: createdTime,
+ Timeframe: newTs,
Amount: amount,
})
-
}
return &TimeVar{g, data}, nil
}
-func (t *TimeVar) Values() []*TimeValue {
+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 {
- validSet = append(validSet, &TimeValue{
- Timeframe: v.Timeframe,
- Amount: v.Amount,
- })
+ timeMap[v.Timeframe] = v.Amount
}
- return validSet
-}
+ currentStr := types.FixedTime(current, t.g.duration())
-func (t *TimeVar) FillMissing() []*TimeValue {
- timeMap := make(map[time.Time]*TimeValue)
- var validSet []*TimeValue
- if len(t.data) == 0 {
- return nil
- }
- current := t.data[0].Timeframe
- for _, v := range t.data {
- timeMap[v.Timeframe] = v
- }
- maxTime := t.g.query.End
for {
- amount := int64(0)
- if timeMap[current] != nil {
- amount = timeMap[current].Amount
+ var amount float64
+ if timeMap[currentStr] != 0 {
+ amount = timeMap[currentStr]
}
validSet = append(validSet, &TimeValue{
- Timeframe: current,
+ Timeframe: currentStr,
Amount: amount,
})
- if current.After(maxTime) {
+ if current.After(end) {
break
}
- current = current.Add(t.g.duration())
+ current = current.Add(dur)
+ currentStr = types.FixedTime(current, t.g.duration())
}
return validSet
@@ -112,18 +138,78 @@ func (t *TimeVar) FillMissing() []*TimeValue {
func (g *GroupBy) duration() time.Duration {
switch g.query.Group {
case "second":
- return time.Second
+ return types.Second
case "minute":
- return time.Minute
+ return types.Minute
case "hour":
- return time.Hour
+ return types.Hour
case "day":
- return time.Hour * 24
+ return types.Day
case "month":
- return time.Hour * 730
+ return types.Month
case "year":
- return time.Hour * 8760
+ return types.Year
default:
- return time.Hour
+ 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
+}
diff --git a/database/service.go b/database/service.go
index 93207f33..a6917791 100644
--- a/database/service.go
+++ b/database/service.go
@@ -2,7 +2,7 @@ package database
import "github.com/hunterlong/statping/types"
-type Service struct {
+type ServiceObj struct {
db Database
service *types.Service
}
@@ -12,16 +12,16 @@ type Servicer interface {
Hits() Database
}
-func (it *Db) GetService(id int64) (Servicer, error) {
+func Service(id int64) (Servicer, error) {
var service types.Service
- query := it.Model(&types.Service{}).Where("id = ?", id).Find(&service)
- return &Service{it, &service}, query.Error()
+ query := database.Model(&types.Service{}).Where("id = ?", id).Find(&service)
+ return &ServiceObj{query, &service}, query.Error()
}
-func (s *Service) Failures() Database {
- return s.db.Model(&types.Failure{}).Where("service = ?", s.service.Id)
+func (s *ServiceObj) Failures() Database {
+ return database.Model(&types.Failure{}).Where("service = ?", s.service.Id)
}
-func (s *Service) Hits() Database {
- return s.db.Model(&types.Hit{}).Where("service = ?", s.service.Id)
+func (s *ServiceObj) Hits() Database {
+ return database.Model(&types.Hit{}).Where("service = ?", s.service.Id)
}
diff --git a/frontend/src/API.js b/frontend/src/API.js
index 6ace37f5..c99e0a68 100644
--- a/frontend/src/API.js
+++ b/frontend/src/API.js
@@ -37,11 +37,11 @@ class Api {
}
async service_hits(id, start, end, group) {
- return axios.get('/api/services/' + id + '/hits_data?start=' + start + '&end=' + end + '&group=' + group).then(response => (response.data))
+ return axios.get('/api/services/' + id + '/hits_data?start=' + start + '&end=' + end + '&group=' + group + '&fill=true').then(response => (response.data))
}
async service_failures_data(id, start, end, group) {
- return axios.get('/api/services/' + id + '/failure_data?start=' + start + '&end=' + end + '&group=' + group).then(response => (response.data))
+ return axios.get('/api/services/' + id + '/failure_data?start=' + start + '&end=' + end + '&group=' + group + '&fill=true').then(response => (response.data))
}
async service_heatmap(id, start, end, group) {
diff --git a/frontend/src/components/Service/ServiceChart.vue b/frontend/src/components/Service/ServiceChart.vue
index 83128ef1..44af6d1e 100644
--- a/frontend/src/components/Service/ServiceChart.vue
+++ b/frontend/src/components/Service/ServiceChart.vue
@@ -132,15 +132,15 @@
},
methods: {
async chartHits(group) {
- const start = this.nowSubtract((3600 * 24) * 7)
+ const start = this.nowSubtract((3600 * 24) * 30)
this.data = await Api.service_hits(this.service.id, this.toUnix(start), this.toUnix(new Date()), group)
- if (this.data.length === 0 && group !== "minute") {
- await this.chartHits("minute")
+ if (this.data.length === 0 && group !== "hour") {
+ await this.chartHits("hour")
}
this.series = [{
name: this.service.name,
- ...this.data
+ ...this.convertToChartData(this.data)
}]
this.ready = true
}
diff --git a/frontend/src/components/Service/ServiceInfo.vue b/frontend/src/components/Service/ServiceInfo.vue
index a0321ae0..21221291 100644
--- a/frontend/src/components/Service/ServiceInfo.vue
+++ b/frontend/src/components/Service/ServiceInfo.vue
@@ -16,7 +16,7 @@
- Failed {{ago(parseTime(failure.created_at))}}
+ Failed {{failure.created_at}}
{{failure.issue}}
@@ -49,9 +49,9 @@
}
},
async mounted() {
- this.set1 = await this.getHits(24, "minute")
+ this.set1 = await this.getHits(24, "hour")
this.set1_name = this.calc(this.set1)
- this.set2 = await this.getHits(24 * 7, "hour")
+ this.set2 = await this.getHits(24 * 7, "day")
this.set2_name = this.calc(this.set2)
this.loaded = true
},
@@ -62,15 +62,16 @@
this.failures = await Api.service_failures(this.service.id, this.toUnix(start), this.toUnix(this.now()), 5)
return [{name: "None", data: []}]
}
- const data = await Api.service_hits(this.service.id, this.toUnix(start), this.toUnix(this.now()), group)
+ const fetched = await Api.service_hits(this.service.id, this.toUnix(start), this.toUnix(this.now()), group)
if (!data) {
return [{name: "None", data: []}]
}
- return [{name: "Latency", data: data.data}]
+ const data = this.convertToChartData(fetched, 1000, true)
+ return [{name: "Latency", data}]
},
calc(s) {
let data = s[0].data
- if (data.length > 1) {
+ if (data) {
let total = 0
data.forEach((f) => {
total += f.y
diff --git a/frontend/src/forms/Service.vue b/frontend/src/forms/Service.vue
index 2b77b70e..fae1acf3 100644
--- a/frontend/src/forms/Service.vue
+++ b/frontend/src/forms/Service.vue
@@ -149,7 +149,7 @@