mirror of https://github.com/statping/statping
parent
fc1fe03f89
commit
9a6c91a997
|
@ -49,26 +49,41 @@ func SelectCheckin(api string) *Checkin {
|
||||||
return &checkin
|
return &checkin
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindCheckin(api string) *types.Checkin {
|
func (u Checkin) Period() time.Duration {
|
||||||
for _, ser := range CoreApp.Services {
|
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", u.Interval))
|
||||||
service := ser.Select()
|
return duration
|
||||||
for _, c := range service.Checkins {
|
}
|
||||||
if c.ApiKey == api {
|
|
||||||
return c
|
func (u Checkin) Grace() time.Duration {
|
||||||
}
|
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", u.GracePeriod))
|
||||||
}
|
return duration
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
func (u Checkin) Expected() time.Duration {
|
||||||
|
last := u.Last().CreatedAt
|
||||||
|
now := time.Now()
|
||||||
|
lastDir := now.Sub(last)
|
||||||
|
sub := time.Duration(u.Period() - lastDir)
|
||||||
|
return sub
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u Checkin) Last() CheckinHit {
|
||||||
|
var hit CheckinHit
|
||||||
|
checkinHitsDB().Where("checkin = ?", u.Id).Last(&hit)
|
||||||
|
return hit
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Checkin) Hits() []CheckinHit {
|
func (u *Checkin) Hits() []CheckinHit {
|
||||||
var checkins []CheckinHit
|
var checkins []CheckinHit
|
||||||
checkinDB().Where("checkin = ?", u.Id).Order("id DESC").Find(&checkins)
|
checkinHitsDB().Where("checkin = ?", u.Id).Order("id DESC").Find(&checkins)
|
||||||
return checkins
|
return checkins
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Checkin) Create() (int64, error) {
|
func (u *Checkin) Create() (int64, error) {
|
||||||
u.CreatedAt = time.Now()
|
if u.CreatedAt.IsZero() {
|
||||||
|
u.CreatedAt = time.Now()
|
||||||
|
}
|
||||||
|
u.ApiKey = utils.NewSHA1Hash(7)
|
||||||
row := checkinDB().Create(u)
|
row := checkinDB().Create(u)
|
||||||
if row.Error == nil {
|
if row.Error == nil {
|
||||||
utils.Log(2, row.Error)
|
utils.Log(2, row.Error)
|
||||||
|
@ -78,7 +93,9 @@ func (u *Checkin) Create() (int64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *CheckinHit) Create() (int64, error) {
|
func (u *CheckinHit) Create() (int64, error) {
|
||||||
u.CreatedAt = time.Now()
|
if u.CreatedAt.IsZero() {
|
||||||
|
u.CreatedAt = time.Now()
|
||||||
|
}
|
||||||
row := checkinHitsDB().Create(u)
|
row := checkinHitsDB().Create(u)
|
||||||
if row.Error == nil {
|
if row.Error == nil {
|
||||||
utils.Log(2, row.Error)
|
utils.Log(2, row.Error)
|
||||||
|
|
|
@ -108,6 +108,16 @@ func (u *User) AfterFind() (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Checkin) AfterFind() (err error) {
|
||||||
|
s.CreatedAt = utils.Timezoner(s.CreatedAt, CoreApp.Timezone)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CheckinHit) AfterFind() (err error) {
|
||||||
|
s.CreatedAt = utils.Timezoner(s.CreatedAt, CoreApp.Timezone)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (u *Hit) BeforeCreate() (err error) {
|
func (u *Hit) BeforeCreate() (err error) {
|
||||||
if u.CreatedAt.IsZero() {
|
if u.CreatedAt.IsZero() {
|
||||||
u.CreatedAt = time.Now().UTC()
|
u.CreatedAt = time.Now().UTC()
|
||||||
|
@ -130,6 +140,16 @@ func (u *Service) BeforeCreate() (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *Checkin) BeforeCreate() (err error) {
|
||||||
|
u.CreatedAt = time.Now().UTC()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *CheckinHit) BeforeCreate() (err error) {
|
||||||
|
u.CreatedAt = time.Now().UTC()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// InsertCore create the single row for the Core settings in Statup
|
// InsertCore create the single row for the Core settings in Statup
|
||||||
func (db *DbConfig) InsertCore() (*Core, error) {
|
func (db *DbConfig) InsertCore() (*Core, error) {
|
||||||
CoreApp = &Core{Core: &types.Core{
|
CoreApp = &Core{Core: &types.Core{
|
||||||
|
|
|
@ -84,6 +84,31 @@ func InsertSampleData() error {
|
||||||
s4.Create(false)
|
s4.Create(false)
|
||||||
s5.Create(false)
|
s5.Create(false)
|
||||||
|
|
||||||
|
checkin1 := ReturnCheckin(&types.Checkin{
|
||||||
|
Service: s1.Id,
|
||||||
|
Interval: 300,
|
||||||
|
GracePeriod: 300,
|
||||||
|
})
|
||||||
|
checkin1.Create()
|
||||||
|
|
||||||
|
checkin2 := ReturnCheckin(&types.Checkin{
|
||||||
|
Service: s2.Id,
|
||||||
|
Interval: 900,
|
||||||
|
GracePeriod: 300,
|
||||||
|
})
|
||||||
|
checkin2.Create()
|
||||||
|
|
||||||
|
checkTime := time.Now().Add(-24 * time.Hour)
|
||||||
|
for i := 0; i <= 60; i++ {
|
||||||
|
checkHit := ReturnCheckinHit(&types.CheckinHit{
|
||||||
|
Checkin: checkin1.Id,
|
||||||
|
From: "192.168.0.1",
|
||||||
|
CreatedAt: checkTime.UTC(),
|
||||||
|
})
|
||||||
|
checkHit.Create()
|
||||||
|
checkTime = checkTime.Add(10 * time.Minute)
|
||||||
|
}
|
||||||
|
|
||||||
utils.Log(1, "Sample data has finished importing")
|
utils.Log(1, "Sample data has finished importing")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -114,39 +139,6 @@ func InsertSampleHits() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sampleGraphData(i float64, upward *bool) float64 {
|
|
||||||
alpha := 0.0003
|
|
||||||
if *upward {
|
|
||||||
i += 0.3
|
|
||||||
if i >= 6500 {
|
|
||||||
i += 0.1
|
|
||||||
*upward = false
|
|
||||||
} else if i >= 4500 {
|
|
||||||
i += 3
|
|
||||||
} else if i >= 2300 {
|
|
||||||
i += 1
|
|
||||||
} else if i >= 1150 {
|
|
||||||
i += 2
|
|
||||||
} else if i >= 500 {
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
i -= 0.3
|
|
||||||
if i <= 6500 {
|
|
||||||
i -= 0.1
|
|
||||||
} else if i <= 4500 {
|
|
||||||
i -= 3
|
|
||||||
} else if i <= 2300 {
|
|
||||||
i -= 1
|
|
||||||
} else if i <= 1150 {
|
|
||||||
i -= 2
|
|
||||||
} else if i <= 500 {
|
|
||||||
i -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i * alpha
|
|
||||||
}
|
|
||||||
|
|
||||||
func insertSampleCore() error {
|
func insertSampleCore() error {
|
||||||
core := &types.Core{
|
core := &types.Core{
|
||||||
Name: "Statup Sample Data",
|
Name: "Statup Sample Data",
|
||||||
|
|
|
@ -49,9 +49,9 @@ func SelectService(id int64) *Service {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Checkins() []*Checkin {
|
func (s *Service) Checkin() Checkin {
|
||||||
var hits []*Checkin
|
var hits Checkin
|
||||||
servicesDB().Where("service = ?", s.Id).Find(&hits)
|
servicesDB().Where("service = ?", s.Id).First(&hits)
|
||||||
return hits
|
return hits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ func (c *Core) SelectAllServices() ([]*Service, error) {
|
||||||
CoreApp.Services = nil
|
CoreApp.Services = nil
|
||||||
for _, service := range services {
|
for _, service := range services {
|
||||||
service.Start()
|
service.Start()
|
||||||
service.Checkins()
|
service.Checkin()
|
||||||
service.AllFailures()
|
service.AllFailures()
|
||||||
CoreApp.Services = append(CoreApp.Services, service)
|
CoreApp.Services = append(CoreApp.Services, service)
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ func apiCheckinHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
checkin := core.FindCheckin(vars["api"])
|
checkin := core.SelectCheckin(vars["api"])
|
||||||
//checkin.Receivehit()
|
//checkin.Receivehit()
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(checkin)
|
json.NewEncoder(w).Encode(checkin)
|
||||||
|
|
|
@ -137,6 +137,25 @@ var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap
|
||||||
"ToString": func(v interface{}) string {
|
"ToString": func(v interface{}) string {
|
||||||
return utils.ToString(v)
|
return utils.ToString(v)
|
||||||
},
|
},
|
||||||
|
"Ago": func(t time.Time) string {
|
||||||
|
return utils.Timestamp(t).Ago()
|
||||||
|
},
|
||||||
|
"Duration": func(t time.Duration) string {
|
||||||
|
var out string
|
||||||
|
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", t.Seconds()))
|
||||||
|
if duration.Minutes() < 1 {
|
||||||
|
out = fmt.Sprintf("%0.0f second", duration.Seconds())
|
||||||
|
if duration.Seconds() >= 2 {
|
||||||
|
out += "s"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out = fmt.Sprintf("%0.0f minute", duration.Minutes())
|
||||||
|
if duration.Minutes() >= 2 {
|
||||||
|
out += "s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
},
|
||||||
"ToUnix": func(t time.Time) int64 {
|
"ToUnix": func(t time.Time) int64 {
|
||||||
return t.UTC().Unix()
|
return t.UTC().Unix()
|
||||||
},
|
},
|
||||||
|
|
|
@ -53,6 +53,31 @@ func Router() *mux.Router {
|
||||||
r.Handle("/dashboard", http.HandlerFunc(dashboardHandler)).Methods("GET")
|
r.Handle("/dashboard", http.HandlerFunc(dashboardHandler)).Methods("GET")
|
||||||
r.Handle("/dashboard", http.HandlerFunc(loginHandler)).Methods("POST")
|
r.Handle("/dashboard", http.HandlerFunc(loginHandler)).Methods("POST")
|
||||||
r.Handle("/logout", http.HandlerFunc(logoutHandler))
|
r.Handle("/logout", http.HandlerFunc(logoutHandler))
|
||||||
|
r.Handle("/checkin/{id}", http.HandlerFunc(checkinUpdateHandler))
|
||||||
|
r.Handle("/plugins/download/{name}", http.HandlerFunc(pluginsDownloadHandler))
|
||||||
|
r.Handle("/plugins/{name}/save", http.HandlerFunc(pluginSavedHandler)).Methods("POST")
|
||||||
|
r.Handle("/help", http.HandlerFunc(helpHandler))
|
||||||
|
r.Handle("/logs", http.HandlerFunc(logsHandler))
|
||||||
|
r.Handle("/logs/line", http.HandlerFunc(logsLineHandler))
|
||||||
|
|
||||||
|
// USER Routes
|
||||||
|
r.Handle("/users", http.HandlerFunc(usersHandler)).Methods("GET")
|
||||||
|
r.Handle("/users", http.HandlerFunc(createUserHandler)).Methods("POST")
|
||||||
|
r.Handle("/user/{id}", http.HandlerFunc(usersEditHandler)).Methods("GET")
|
||||||
|
r.Handle("/user/{id}", http.HandlerFunc(updateUserHandler)).Methods("POST")
|
||||||
|
r.Handle("/user/{id}/delete", http.HandlerFunc(usersDeleteHandler)).Methods("GET")
|
||||||
|
|
||||||
|
// SETTINGS Routes
|
||||||
|
r.Handle("/settings", http.HandlerFunc(settingsHandler)).Methods("GET")
|
||||||
|
r.Handle("/settings", http.HandlerFunc(saveSettingsHandler)).Methods("POST")
|
||||||
|
r.Handle("/settings/css", http.HandlerFunc(saveSASSHandler)).Methods("POST")
|
||||||
|
r.Handle("/settings/build", http.HandlerFunc(saveAssetsHandler)).Methods("GET")
|
||||||
|
r.Handle("/settings/delete_assets", http.HandlerFunc(deleteAssetsHandler)).Methods("GET")
|
||||||
|
r.Handle("/settings/notifier/{method}", http.HandlerFunc(saveNotificationHandler)).Methods("POST")
|
||||||
|
r.Handle("/settings/notifier/{method}/test", http.HandlerFunc(testNotificationHandler)).Methods("POST")
|
||||||
|
r.Handle("/settings/export", http.HandlerFunc(exportHandler)).Methods("GET")
|
||||||
|
|
||||||
|
// SERVICE Routes
|
||||||
r.Handle("/services", http.HandlerFunc(servicesHandler)).Methods("GET")
|
r.Handle("/services", http.HandlerFunc(servicesHandler)).Methods("GET")
|
||||||
r.Handle("/services", http.HandlerFunc(createServiceHandler)).Methods("POST")
|
r.Handle("/services", http.HandlerFunc(createServiceHandler)).Methods("POST")
|
||||||
r.Handle("/services/reorder", http.HandlerFunc(reorderServiceHandler)).Methods("POST")
|
r.Handle("/services/reorder", http.HandlerFunc(reorderServiceHandler)).Methods("POST")
|
||||||
|
@ -62,27 +87,8 @@ func Router() *mux.Router {
|
||||||
r.Handle("/service/{id}/delete", http.HandlerFunc(servicesDeleteHandler))
|
r.Handle("/service/{id}/delete", http.HandlerFunc(servicesDeleteHandler))
|
||||||
r.Handle("/service/{id}/delete_failures", http.HandlerFunc(servicesDeleteFailuresHandler)).Methods("GET")
|
r.Handle("/service/{id}/delete_failures", http.HandlerFunc(servicesDeleteFailuresHandler)).Methods("GET")
|
||||||
r.Handle("/service/{id}/checkin", http.HandlerFunc(checkinCreateUpdateHandler)).Methods("POST")
|
r.Handle("/service/{id}/checkin", http.HandlerFunc(checkinCreateUpdateHandler)).Methods("POST")
|
||||||
r.Handle("/checkin/{id}", http.HandlerFunc(checkinUpdateHandler))
|
|
||||||
r.Handle("/users", http.HandlerFunc(usersHandler)).Methods("GET")
|
|
||||||
r.Handle("/users", http.HandlerFunc(createUserHandler)).Methods("POST")
|
|
||||||
r.Handle("/user/{id}", http.HandlerFunc(usersEditHandler)).Methods("GET")
|
|
||||||
r.Handle("/user/{id}", http.HandlerFunc(updateUserHandler)).Methods("POST")
|
|
||||||
r.Handle("/user/{id}/delete", http.HandlerFunc(usersDeleteHandler)).Methods("GET")
|
|
||||||
r.Handle("/settings", http.HandlerFunc(settingsHandler)).Methods("GET")
|
|
||||||
r.Handle("/settings", http.HandlerFunc(saveSettingsHandler)).Methods("POST")
|
|
||||||
r.Handle("/settings/css", http.HandlerFunc(saveSASSHandler)).Methods("POST")
|
|
||||||
r.Handle("/settings/build", http.HandlerFunc(saveAssetsHandler)).Methods("GET")
|
|
||||||
r.Handle("/settings/delete_assets", http.HandlerFunc(deleteAssetsHandler)).Methods("GET")
|
|
||||||
r.Handle("/settings/notifier/{method}", http.HandlerFunc(saveNotificationHandler)).Methods("POST")
|
|
||||||
r.Handle("/settings/notifier/{method}/test", http.HandlerFunc(testNotificationHandler)).Methods("POST")
|
|
||||||
r.Handle("/settings/export", http.HandlerFunc(exportHandler)).Methods("GET")
|
|
||||||
r.Handle("/plugins/download/{name}", http.HandlerFunc(pluginsDownloadHandler))
|
|
||||||
r.Handle("/plugins/{name}/save", http.HandlerFunc(pluginSavedHandler)).Methods("POST")
|
|
||||||
r.Handle("/help", http.HandlerFunc(helpHandler))
|
|
||||||
r.Handle("/logs", http.HandlerFunc(logsHandler))
|
|
||||||
r.Handle("/logs/line", http.HandlerFunc(logsLineHandler))
|
|
||||||
|
|
||||||
// SERVICE API Routes
|
// API SERVICE Routes
|
||||||
r.Handle("/api/services", http.HandlerFunc(apiAllServicesHandler)).Methods("GET")
|
r.Handle("/api/services", http.HandlerFunc(apiAllServicesHandler)).Methods("GET")
|
||||||
r.Handle("/api/services", http.HandlerFunc(apiCreateServiceHandler)).Methods("POST")
|
r.Handle("/api/services", http.HandlerFunc(apiCreateServiceHandler)).Methods("POST")
|
||||||
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceHandler)).Methods("GET")
|
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceHandler)).Methods("GET")
|
||||||
|
@ -91,7 +97,7 @@ func Router() *mux.Router {
|
||||||
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceUpdateHandler)).Methods("POST")
|
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceUpdateHandler)).Methods("POST")
|
||||||
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceDeleteHandler)).Methods("DELETE")
|
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceDeleteHandler)).Methods("DELETE")
|
||||||
|
|
||||||
// USER API Routes
|
// API USER Routes
|
||||||
r.Handle("/api/users", http.HandlerFunc(apiAllUsersHandler)).Methods("GET")
|
r.Handle("/api/users", http.HandlerFunc(apiAllUsersHandler)).Methods("GET")
|
||||||
r.Handle("/api/users", http.HandlerFunc(apiCreateUsersHandler)).Methods("POST")
|
r.Handle("/api/users", http.HandlerFunc(apiCreateUsersHandler)).Methods("POST")
|
||||||
r.Handle("/api/users/{id}", http.HandlerFunc(apiUserHandler)).Methods("GET")
|
r.Handle("/api/users/{id}", http.HandlerFunc(apiUserHandler)).Methods("GET")
|
||||||
|
@ -103,8 +109,8 @@ func Router() *mux.Router {
|
||||||
r.Handle("/api/renew", http.HandlerFunc(apiRenewHandler))
|
r.Handle("/api/renew", http.HandlerFunc(apiRenewHandler))
|
||||||
r.Handle("/api/checkin/{api}", http.HandlerFunc(apiCheckinHandler))
|
r.Handle("/api/checkin/{api}", http.HandlerFunc(apiCheckinHandler))
|
||||||
r.Handle("/metrics", http.HandlerFunc(prometheusHandler))
|
r.Handle("/metrics", http.HandlerFunc(prometheusHandler))
|
||||||
r.NotFoundHandler = http.HandlerFunc(error404Handler)
|
|
||||||
r.Handle("/tray", http.HandlerFunc(trayHandler))
|
r.Handle("/tray", http.HandlerFunc(trayHandler))
|
||||||
|
r.NotFoundHandler = http.HandlerFunc(error404Handler)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -268,7 +268,6 @@ func checkinCreateUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
Service: service.Id,
|
Service: service.Id,
|
||||||
Interval: interval,
|
Interval: interval,
|
||||||
GracePeriod: grace,
|
GracePeriod: grace,
|
||||||
ApiKey: utils.NewSHA1Hash(18),
|
|
||||||
})
|
})
|
||||||
checkin.Create()
|
checkin.Create()
|
||||||
executeResponse(w, r, "service.html", service, fmt.Sprintf("/service/%v", service.Id))
|
executeResponse(w, r, "service.html", service, fmt.Sprintf("/service/%v", service.Id))
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
<input type="number" name="expected_status" class="form-control" value="{{if ne .ExpectedStatus 0}}{{.ExpectedStatus}}{{end}}" placeholder="200" id="service_response_code">
|
<input type="number" name="expected_status" class="form-control" value="{{if ne .ExpectedStatus 0}}{{.ExpectedStatus}}{{end}}" placeholder="200" id="service_response_code">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row{{if eq .Type "http"}} d-none{{end}}">
|
<div class="form-group row{{if eq .Type ""}} d-none{{else if eq .Type "http"}} d-none{{end}}">
|
||||||
<label for="service_port" class="col-sm-4 col-form-label">TCP Port</label>
|
<label for="service_port" class="col-sm-4 col-form-label">TCP Port</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<input type="number" name="port" class="form-control" value="{{if ne .Port 0}}{{.Port}}{{end}}" id="service_port" placeholder="8080">
|
<input type="number" name="port" class="form-control" value="{{if ne .Port 0}}{{.Port}}{{end}}" id="service_port" placeholder="8080">
|
||||||
|
|
|
@ -96,18 +96,27 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12 mt-4{{if eq $s.Type "tcp"}} d-none{{end}}">
|
<div class="col-12 mt-4">
|
||||||
<h3>Service Checkins</h3>
|
<h3>Service Checkin</h3>
|
||||||
{{ range $s.Checkins }}
|
<table class="table">
|
||||||
<h5>Check #{{.Id}} <span class="badge online_badge float-right">Checked in</span></h5>
|
<thead>
|
||||||
<input type="text" class="form-control" value="{{CoreApp.Domain}}/checkin/{{.ApiKey}}">
|
<tr>
|
||||||
<ul class="list-group">
|
<th scope="col">Checkin</th>
|
||||||
{{ range .Hits }}
|
<th scope="col">Report Period<br>Grace Period</th>
|
||||||
<li class="list-group-item">Received Checkin at {{.CreatedAt}}</li>
|
<th scope="col">Last Seen</th>
|
||||||
{{end}}
|
<th scope="col">Expected</th>
|
||||||
</ul>
|
</tr>
|
||||||
{{ end }}
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{$ch := $s.Checkin}}
|
||||||
|
<tr>
|
||||||
|
<td>{{CoreApp.Domain}}/checkin/{{$ch.ApiKey}}</td>
|
||||||
|
<td>every {{Duration $ch.Period}}<br>{{Duration $ch.Grace}} grace period</td>
|
||||||
|
<td>{{Ago $ch.Last.CreatedAt}}</td>
|
||||||
|
<td>{{ if lt $ch.Expected 0}}{{Duration $ch.Expected}} ago{{else}}in {{Duration $ch.Expected}}{{end}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
{{template "form_checkin" $s}}
|
{{template "form_checkin" $s}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -20,14 +20,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Checkin struct {
|
type Checkin struct {
|
||||||
Id int64 `gorm:"primary_key;column:id"`
|
Id int64 `gorm:"primary_key;column:id"`
|
||||||
Service int64 `gorm:"index;column:service"`
|
Service int64 `gorm:"index;column:service"`
|
||||||
Interval int64 `gorm:"column:check_interval"`
|
Interval int64 `gorm:"column:check_interval"`
|
||||||
GracePeriod int64 `gorm:"column:grace_period"`
|
GracePeriod int64 `gorm:"column:grace_period"`
|
||||||
ApiKey string `gorm:"column:api_key"`
|
ApiKey string `gorm:"column:api_key"`
|
||||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||||
Hits []CheckinHit `json:"hits"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckinHit struct {
|
type CheckinHit struct {
|
||||||
|
|
|
@ -46,7 +46,7 @@ type Service struct {
|
||||||
LastStatusCode int `gorm:"-" json:"status_code"`
|
LastStatusCode int `gorm:"-" json:"status_code"`
|
||||||
LastOnline time.Time `gorm:"-" json:"last_online"`
|
LastOnline time.Time `gorm:"-" json:"last_online"`
|
||||||
Failures []interface{} `gorm:"-" json:"failures,omitempty"`
|
Failures []interface{} `gorm:"-" json:"failures,omitempty"`
|
||||||
Checkins []*Checkin `gorm:"-" json:"checkins,omitempty"`
|
//Checkins []*Checkin `gorm:"-" json:"checkins,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServiceInterface interface {
|
type ServiceInterface interface {
|
||||||
|
|
Loading…
Reference in New Issue