mirror of https://github.com/statping/statping
changes n upgrades
parent
cb70a0134d
commit
09bc158e5e
29
failures.go
29
failures.go
|
@ -1,31 +1,44 @@
|
|||
package main
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"github.com/ararog/timeago"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Failure struct {
|
||||
Id int
|
||||
Issue string
|
||||
Service int
|
||||
CreatedAt time.Time
|
||||
Ago string
|
||||
}
|
||||
|
||||
func SelectAllFailures(id int64) []float64 {
|
||||
var tks []float64
|
||||
rows, err := db.Query("SELECT * FROM failures WHERE service=$1 ORDER BY id ASC", id)
|
||||
func (s *Service) SelectAllFailures() []*Failure {
|
||||
var tks []*Failure
|
||||
rows, err := db.Query("SELECT * FROM failures WHERE service=$1 ORDER BY id DESC LIMIT 10", s.Id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for rows.Next() {
|
||||
var tk Hit
|
||||
err = rows.Scan(&tk.Id, &tk.Metric, &tk.Value, &tk.CreatedAt)
|
||||
var tk Failure
|
||||
err = rows.Scan(&tk.Id, &tk.Issue, &tk.Service, &tk.CreatedAt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tks = append(tks, tk.Value)
|
||||
|
||||
tk.Ago, _ = timeago.TimeAgoWithTime(time.Now(), tk.CreatedAt)
|
||||
|
||||
tks = append(tks, &tk)
|
||||
}
|
||||
return tks
|
||||
}
|
||||
|
||||
func CountFailures() int {
|
||||
var amount int
|
||||
db.QueryRow("SELECT COUNT(id) FROM failures;").Scan(&amount)
|
||||
return amount
|
||||
}
|
||||
|
||||
func (s *Service) TotalFailures() int {
|
||||
var amount int
|
||||
db.QueryRow("SELECT COUNT(id) FROM failures WHERE service=$1;", s.Id).Scan(&amount)
|
||||
|
@ -36,6 +49,6 @@ func (s *Service) TotalFailures24Hours() int {
|
|||
var amount int
|
||||
t := time.Now()
|
||||
x := t.AddDate(0, 0, -1)
|
||||
db.QueryRow("SELECT COUNT(id) FROM failures WHERE service=$1 AND created_at>=$2 AND created_at<$3;", s.Id, t, x).Scan(&amount)
|
||||
db.QueryRow("SELECT COUNT(id) FROM failures WHERE service=$1 AND created_at>=$2 AND created_at<$3;", s.Id, x, t).Scan(&amount)
|
||||
return amount
|
||||
}
|
||||
|
|
|
@ -21,14 +21,36 @@ HTML,BODY {
|
|||
font-size: 26pt;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
color: #3e3e3e;
|
||||
}
|
||||
|
||||
.text_perfect {
|
||||
color: #33b418;
|
||||
text-shadow: 0px 1px 0 #0e6702;
|
||||
}
|
||||
|
||||
.text_good {
|
||||
color: #33b418;
|
||||
text-shadow: 0px 1px 0 #0e6702;
|
||||
}
|
||||
|
||||
.text_ok {
|
||||
color: #33b418;
|
||||
text-shadow: 0px 1px 0 #0e6702;
|
||||
}
|
||||
|
||||
.text_bad {
|
||||
color: #33b418;
|
||||
text-shadow: 0px 1px 0 #0e6702;
|
||||
}
|
||||
|
||||
.stats_area {
|
||||
text-align: center;
|
||||
color: #a5a5a5;
|
||||
}
|
||||
|
||||
.offline_bg {
|
||||
background-color: #c5c5c578 !important;
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
.footer {
|
||||
|
@ -41,6 +63,28 @@ HTML,BODY {
|
|||
}
|
||||
|
||||
|
||||
.online_badge {
|
||||
color: #fff;
|
||||
background-color: #35b317;
|
||||
}
|
||||
|
||||
.offline_badge {
|
||||
color: #fff;
|
||||
background-color: #c51919;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin-top: -20px;
|
||||
margin-left: -20px;
|
||||
margin-bottom: 15px;
|
||||
width: calc(100% + 40px);
|
||||
height: 3px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
|
||||
|
|
|
@ -43,18 +43,18 @@
|
|||
<div class="row stats_area">
|
||||
|
||||
<div class="col-4">
|
||||
<span class="lg_number">69</span>
|
||||
24 Hour Hits
|
||||
<span class="lg_number">{{ .CountServices }}</span>
|
||||
Total Services
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<span class="lg_number">3921</span>
|
||||
24 Hour Hits
|
||||
<span class="lg_number">{{ .Count24Failures }}</span>
|
||||
Failures last 24 Hours
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
<span class="lg_number">453</span>
|
||||
Total Tokens
|
||||
<span class="lg_number">{{ .CountOnline }}</span>
|
||||
Online Services
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -8,22 +8,33 @@
|
|||
<link rel="stylesheet" href="/css/base.css">
|
||||
<script src="/js/Chart.bundle.min.js"></script>
|
||||
|
||||
<title>Statup | Dashboard</title>
|
||||
<title>{{.Project}} Status</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1 class="text-center">{{.Project}}</h1>
|
||||
<h1 class="text-center mb-4">{{.Project}}</h1>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div class="row">
|
||||
|
||||
{{ range .Services }}
|
||||
<div class="col-12 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-body{{if .Online}}{{else}} offline_bg{{end}}">
|
||||
<h3>{{ .Name }} <span class="badge badge-secondary float-right">{{if .Online}} ONLINE {{ else }} OFFLINE {{end}}</span></h3>
|
||||
|
||||
<div class="row stats_area mt-3 mb-3">
|
||||
<div class="progress">
|
||||
<div class="progress-bar {{if .Online24Hours}} bg-success {{else}} bg-danger {{end}}" role="progressbar" style="width: {{.Online24Hours}}%" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
|
||||
<h3 class="mt-4">{{ .Name }}
|
||||
{{if .Online}}
|
||||
<span class="badge online_badge float-right">ONLINE</span>
|
||||
{{ else }}
|
||||
<span class="badge offline_badge float-right">OFFLINE</span>
|
||||
{{end}}</h3>
|
||||
|
||||
<div class="row stats_area mt-5 mb-5">
|
||||
|
||||
<div class="col-4">
|
||||
<span class="lg_number">{{.Online24Hours}}%</span>
|
||||
|
@ -39,10 +50,17 @@
|
|||
<span class="lg_number">{{.TotalUptime}}%</span>
|
||||
Total Uptime
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<canvas id="service_{{ .Id }}" width="400" height="120"></canvas>
|
||||
|
||||
{{ range .Failures }}
|
||||
<blockquote class="blockquote text-right mt-3">
|
||||
<p class="mb-0">{{.Issue}}</p>
|
||||
<footer class="blockquote-footer">Reported <cite title="Source Title">{{.Ago}}</cite></footer>
|
||||
</blockquote>
|
||||
{{ end }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -53,7 +71,7 @@
|
|||
</div>
|
||||
|
||||
<div class="footer text-center">
|
||||
<a href="https://statup.io" target="_blank">Statup.io Opensource Status Page</a>
|
||||
<a href="https://statup.io" target="_blank">Created with Statup.io</a> | <a href="/dashboard">Dashboard</a>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -52,7 +52,8 @@
|
|||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Actions</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -60,11 +61,12 @@
|
|||
<tr>
|
||||
<th scope="row">{{.Id}}</th>
|
||||
<td>{{.Name}}</td>
|
||||
<td>
|
||||
<td>{{.Online}} <span class="badge badge-danger">OFFLINE</span> </td>
|
||||
<td class="text-right">
|
||||
<div class="btn-group" data-toggle="buttons">
|
||||
<button class="btn btn-primary" type="submit">View</button>
|
||||
<button class="btn btn-primary" type="submit">Edit</button>
|
||||
<button class="btn btn-primary" type="submit">Delete</button>
|
||||
<a href="/services/{{.Id}}" class="btn btn-primary">View</a>
|
||||
<a href="/services/{{.Id}}/edit" class="btn btn-primary">Edit</a>
|
||||
<a href="/services/{{.Id}}/delete" class="btn btn-danger">Delete</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -81,8 +83,8 @@
|
|||
|
||||
<form action="/services/create" method="POST">
|
||||
<div class="form-group row">
|
||||
<label for="inputEmail3" class="col-sm-2 col-form-label">Name</label>
|
||||
<div class="col-sm-10">
|
||||
<label for="inputEmail3" class="col-sm-4 col-form-label">Service Name</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" name="name" class="form-control" id="inputEmail3" placeholder="Name">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -118,7 +120,8 @@
|
|||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button type="submit" class="btn btn-primary">Create</button>
|
||||
<a class="btn btn-primary">Test</a>
|
||||
<button type="submit" class="btn btn-success">Create Service</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMakeConfig(t *testing.T) {
|
||||
|
|
42
services.go
42
services.go
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -25,9 +26,10 @@ type Service struct {
|
|||
Data string
|
||||
Online bool
|
||||
Latency float64
|
||||
Online24Hours float64
|
||||
Online24Hours float32
|
||||
AvgResponse string
|
||||
TotalUptime float64
|
||||
TotalUptime string
|
||||
Failures []*Failure
|
||||
}
|
||||
|
||||
func SelectService(id string) Service {
|
||||
|
@ -57,6 +59,7 @@ func SelectAllServices() []*Service {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tk.Failures = tk.SelectAllFailures()
|
||||
tk.FormatData()
|
||||
tks = append(tks, &tk)
|
||||
}
|
||||
|
@ -79,7 +82,7 @@ func (s *Service) AvgTime() float64 {
|
|||
return avg
|
||||
}
|
||||
|
||||
func (s *Service) Online24() float64 {
|
||||
func (s *Service) Online24() float32 {
|
||||
total := s.TotalHits()
|
||||
failed := s.TotalFailures24Hours()
|
||||
if failed == 0 {
|
||||
|
@ -91,8 +94,13 @@ func (s *Service) Online24() float64 {
|
|||
return s.Online24Hours
|
||||
}
|
||||
avg := float64(failed) / float64(total) * 100
|
||||
s.Online24Hours = avg
|
||||
return avg
|
||||
avg = 100 - avg
|
||||
if avg < 0 {
|
||||
avg = 0
|
||||
}
|
||||
amount, _ := strconv.ParseFloat(fmt.Sprintf("%0.2f", avg), 10)
|
||||
s.Online24Hours = float32(amount)
|
||||
return s.Online24Hours
|
||||
}
|
||||
|
||||
type GraphJson struct {
|
||||
|
@ -116,20 +124,24 @@ func (s *Service) GraphData() string {
|
|||
return s.Data
|
||||
}
|
||||
|
||||
func (s *Service) AvgUptime() float64 {
|
||||
func (s *Service) AvgUptime() string {
|
||||
failed := s.TotalFailures()
|
||||
total := s.TotalHits()
|
||||
if failed == 0 {
|
||||
s.TotalUptime = 100.00
|
||||
s.TotalUptime = "100.00"
|
||||
return s.TotalUptime
|
||||
}
|
||||
if total == 0 {
|
||||
s.TotalUptime = 0
|
||||
s.TotalUptime = "0"
|
||||
return s.TotalUptime
|
||||
}
|
||||
percent := float64(failed) / float64(total) * 100
|
||||
s.TotalUptime = percent
|
||||
return percent
|
||||
percent = 100 - percent
|
||||
if percent < 0 {
|
||||
percent = 0
|
||||
}
|
||||
s.TotalUptime = fmt.Sprintf("%0.2f", percent)
|
||||
return s.TotalUptime
|
||||
}
|
||||
|
||||
func (u *Service) Create() int {
|
||||
|
@ -143,6 +155,16 @@ func (u *Service) Create() int {
|
|||
return lastInsertId
|
||||
}
|
||||
|
||||
func CountOnline() int {
|
||||
amount := 0
|
||||
for _, v := range services {
|
||||
if v.Online {
|
||||
amount++
|
||||
}
|
||||
}
|
||||
return amount
|
||||
}
|
||||
|
||||
func NewSHA1Hash(n ...int) string {
|
||||
noRandomCharacters := 32
|
||||
|
||||
|
|
16
web.go
16
web.go
|
@ -7,12 +7,6 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
type dashboard struct {
|
||||
Services []*Service
|
||||
Users []User
|
||||
Core *Core
|
||||
}
|
||||
|
||||
func RunHTTPServer() {
|
||||
fmt.Println("Fusioner HTTP Server running on http://localhost:8080")
|
||||
css := http.StripPrefix("/css/", http.FileServer(cssBox.HTTPBox()))
|
||||
|
@ -149,6 +143,14 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
indexTmpl.Execute(w, out)
|
||||
}
|
||||
|
||||
type dashboard struct {
|
||||
Services []*Service
|
||||
Core *Core
|
||||
CountOnline int
|
||||
CountServices int
|
||||
Count24Failures int
|
||||
}
|
||||
|
||||
func DashboardHandler(w http.ResponseWriter, r *http.Request) {
|
||||
session, _ := store.Get(r, "apizer_auth")
|
||||
if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
|
||||
|
@ -170,7 +172,7 @@ func DashboardHandler(w http.ResponseWriter, r *http.Request) {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
out := dashboard{services, SelectAllUsers(), core}
|
||||
out := dashboard{services, core, CountOnline(), len(services), CountFailures()}
|
||||
dashboardTmpl.Execute(w, out)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue