mirror of https://github.com/statping/statping
parent
04e3a4239c
commit
0666ce247a
|
@ -18,7 +18,7 @@ services:
|
|||
|
||||
env:
|
||||
global:
|
||||
- VERSION=0.21
|
||||
- VERSION=0.22
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM alpine:latest
|
||||
|
||||
ENV VERSION=v0.21
|
||||
ENV VERSION=v0.22
|
||||
|
||||
RUN apk --no-cache add ca-certificates
|
||||
RUN wget https://github.com/hunterlong/statup/releases/download/$VERSION/statup-alpine && \
|
||||
|
|
|
@ -10,10 +10,12 @@ import (
|
|||
|
||||
func CheckServices() {
|
||||
services, _ = SelectAllServices()
|
||||
time.Sleep(3 * time.Second)
|
||||
for _, v := range services {
|
||||
obj := v
|
||||
go obj.StartCheckins()
|
||||
go obj.CheckQueue()
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +25,7 @@ func (s *Service) CheckQueue() {
|
|||
if s.Interval < 1 {
|
||||
s.Interval = 1
|
||||
}
|
||||
fmt.Printf(" Service: %v | Online: %v | Latency: %0.0fms\n", s.Name, s.Online, (s.Latency * 100))
|
||||
fmt.Printf(" Service: %v | Online: %v | Latency: %0.0fms\n", s.Name, s.Online, (s.Latency * 1000))
|
||||
time.Sleep(time.Duration(s.Interval) * time.Second)
|
||||
}
|
||||
|
||||
|
|
|
@ -47,10 +47,17 @@ func (u *Service) DeleteFailures() {
|
|||
func (s *Service) LimitedFailures() []*Failure {
|
||||
var fails []*Failure
|
||||
col := dbSession.Collection("failures").Find("service", s.Id)
|
||||
col.OrderBy("-id").Limit(10).All(&fails)
|
||||
col.OrderBy("create_at").All(&fails)
|
||||
return fails
|
||||
}
|
||||
|
||||
func reverseFailures(input []*Failure) []*Failure {
|
||||
if len(input) == 0 {
|
||||
return input
|
||||
}
|
||||
return append(reverseFailures(input[1:]), input[0])
|
||||
}
|
||||
|
||||
func (f *Failure) Ago() string {
|
||||
got, _ := timeago.TimeAgoWithTime(time.Now(), f.CreatedAt)
|
||||
return got
|
||||
|
|
15
hits.go
15
hits.go
|
@ -36,11 +36,18 @@ func (s *Service) Hits() ([]Hit, error) {
|
|||
return hits, err
|
||||
}
|
||||
|
||||
func (s *Service) LimitedHits() ([]Hit, error) {
|
||||
var hits []Hit
|
||||
col := hitCol().Find("service", s.Id).Limit(1056).OrderBy("-id")
|
||||
func (s *Service) LimitedHits() ([]*Hit, error) {
|
||||
var hits []*Hit
|
||||
col := hitCol().Find("service", s.Id).OrderBy("-id").Limit(1024)
|
||||
err := col.All(&hits)
|
||||
return hits, err
|
||||
return reverseHits(hits), err
|
||||
}
|
||||
|
||||
func reverseHits(input []*Hit) []*Hit {
|
||||
if len(input) == 0 {
|
||||
return input
|
||||
}
|
||||
return append(reverseHits(input[1:]), input[0])
|
||||
}
|
||||
|
||||
func (s *Service) SelectHitsGroupBy(group string) ([]Hit, error) {
|
||||
|
|
|
@ -90,10 +90,30 @@ HTML,BODY {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
position: relative;
|
||||
height: 20vh;
|
||||
width: 60vh;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
|
||||
.sm-container {
|
||||
margin-top: 40px !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.list-group-item H5 {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
position: relative;
|
||||
height:17vh;
|
||||
width:80vw;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-top: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<body>
|
||||
|
||||
|
||||
<div class="container col-md-7 col-sm-12 mt-2 bg-light">
|
||||
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
|
||||
|
||||
{{template "nav"}}
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
{{ if .Core.Footer }}
|
||||
{{ safe .Core.Footer }}
|
||||
{{ end }}
|
||||
<a href="https://statup.io" target="_blank">Statup made with ❤️ {{ VERSION }}</a> | <a href="/dashboard">Dashboard</a>
|
||||
<a href="https://statup.io" target="_blank">Statup {{ VERSION }} made with ❤️</a> | <a href="/dashboard">Dashboard</a>
|
||||
</div>
|
||||
{{ end }}
|
|
@ -11,7 +11,7 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container col-md-7 col-sm-12 mt-2 bg-light">
|
||||
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
|
||||
|
||||
{{if Auth}}
|
||||
{{template "nav"}}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<body>
|
||||
|
||||
|
||||
<div class="container col-md-7 col-sm-12 mt-2">
|
||||
<div class="container col-md-7 col-sm-12 mt-2 sm-container">
|
||||
|
||||
<h1 class="text-center mb-4 mt-sm-3">{{.Core.Name}}</h1>
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
|||
<div class="col-12">
|
||||
|
||||
{{ range .Services }}
|
||||
<div class="mb-4">
|
||||
<div class="mt-4">
|
||||
<div class="card">
|
||||
<div class="card-body{{if .Online}}{{else}} offline_bg{{end}}">
|
||||
|
||||
|
@ -79,7 +79,9 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<canvas id="service_{{ .Id }}" width="400" height="120"></canvas>
|
||||
<div class="chart-container">
|
||||
<canvas id="service_{{ .Id }}"></canvas>
|
||||
</div>
|
||||
|
||||
{{ if .LimitedFailures }}
|
||||
<div class="list-group mt-5">
|
||||
|
@ -130,6 +132,7 @@ var chartdata = new Chart(ctx, {
|
|||
}]
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<body>
|
||||
|
||||
|
||||
<div class="container col-md-7 col-sm-12 mt-2 bg-light">
|
||||
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
|
||||
|
||||
<div class="col-12">
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<body>
|
||||
|
||||
|
||||
<div class="container col-md-7 col-sm-12 mt-2 bg-light">
|
||||
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
|
||||
|
||||
|
||||
{{template "nav"}}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container col-md-7 col-sm-12 mt-2 bg-light">
|
||||
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
|
||||
|
||||
{{if Auth}}
|
||||
{{template "nav"}}
|
||||
|
@ -155,9 +155,11 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button type="submit" class="btn btn-success">Update Service</button>
|
||||
<a href="/service/{{ .Id }}/delete_failures" class="btn btn-danger">Delete All Failures</a>
|
||||
<div class="col-sm-6">
|
||||
<button type="submit" class="btn btn-success btn-block">Update Service</button>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<a href="/service/{{ .Id }}/delete_failures" class="btn btn-danger btn-block">Delete All Failures</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<body>
|
||||
|
||||
|
||||
<div class="container col-md-7 col-sm-12 mt-2 bg-light">
|
||||
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
|
||||
|
||||
{{template "nav"}}
|
||||
|
||||
|
@ -103,7 +103,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-success btn-block">Create Service</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<body>
|
||||
|
||||
|
||||
<div class="container col-md-7 col-sm-12 mt-2 bg-light">
|
||||
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
|
||||
|
||||
{{ if .Error }}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<body>
|
||||
|
||||
|
||||
<div class="container col-md-7 col-sm-12 mt-2 bg-light">
|
||||
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
|
||||
|
||||
{{template "nav"}}
|
||||
|
||||
|
|
69
services.go
69
services.go
|
@ -102,21 +102,74 @@ type GraphJson struct {
|
|||
Y float64 `json:"y"`
|
||||
}
|
||||
|
||||
|
||||
type DateScan struct {
|
||||
CreatedAt time.Time `json:"x"`
|
||||
Value int64 `json:"y"`
|
||||
}
|
||||
|
||||
|
||||
func (s *Service) GraphData() string {
|
||||
var d []GraphJson
|
||||
hits, _ := s.LimitedHits()
|
||||
for _, h := range hits {
|
||||
val := h.CreatedAt
|
||||
o := GraphJson{
|
||||
X: val.String(),
|
||||
Y: h.Latency * 1000,
|
||||
var d []DateScan
|
||||
|
||||
since := time.Now().Add(time.Hour * -12 + time.Minute * 0 + time.Second * 0)
|
||||
|
||||
sql := fmt.Sprintf("SELECT date_trunc('minute', created_at), AVG(latency)*1000 AS value FROM hits WHERE service=%v AND created_at > '%v' GROUP BY 1 ORDER BY date_trunc ASC;", s.Id, since.Format(time.RFC3339))
|
||||
|
||||
fmt.Println(sql)
|
||||
|
||||
dated, err := dbSession.Query(db.Raw(sql))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
d = append(d, o)
|
||||
|
||||
for dated.Next() {
|
||||
|
||||
var gd DateScan
|
||||
|
||||
var ff float64
|
||||
|
||||
dated.Scan(&gd.CreatedAt, &ff)
|
||||
gd.Value = int64(ff)
|
||||
|
||||
d = append(d, gd)
|
||||
|
||||
}
|
||||
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
//
|
||||
//hits, _ := s.LimitedHits()
|
||||
//for _, h := range hits {
|
||||
// val := h.CreatedAt
|
||||
// o := GraphJson{
|
||||
// X: val.String(),
|
||||
// Y: h.Latency * 1000,
|
||||
// }
|
||||
// d = append(d, o)
|
||||
//}
|
||||
data, _ := json.Marshal(d)
|
||||
return string(data)
|
||||
}
|
||||
|
||||
|
||||
//func (s *Service) GraphData() string {
|
||||
// var d []GraphJson
|
||||
// hits, _ := s.LimitedHits()
|
||||
// for _, h := range hits {
|
||||
// val := h.CreatedAt
|
||||
// o := GraphJson{
|
||||
// X: val.String(),
|
||||
// Y: h.Latency * 1000,
|
||||
// }
|
||||
// d = append(d, o)
|
||||
// }
|
||||
// data, _ := json.Marshal(d)
|
||||
// return string(data)
|
||||
//}
|
||||
|
||||
func (s *Service) AvgUptime() string {
|
||||
failed, _ := s.TotalFailures()
|
||||
total, _ := s.TotalHits()
|
||||
|
|
5
web.go
5
web.go
|
@ -217,6 +217,11 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
out := index{*core, services}
|
||||
|
||||
first, _ := out.Services[0].LimitedHits()
|
||||
|
||||
fmt.Println(out.Services[0].Name, "start:", first[0].Id, "last:", first[len(first)-1].Id)
|
||||
|
||||
ExecuteResponse(w, r, "index.html", out)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue