changes n upgrades

pull/10/head
Hunter Long 2018-06-10 17:20:42 -07:00
parent cb70a0134d
commit 09bc158e5e
8 changed files with 150 additions and 48 deletions

View File

@ -1,31 +1,44 @@
package main package main
import "time" import (
"github.com/ararog/timeago"
"time"
)
type Failure struct { type Failure struct {
Id int Id int
Issue string Issue string
Service int Service int
CreatedAt time.Time CreatedAt time.Time
Ago string
} }
func SelectAllFailures(id int64) []float64 { func (s *Service) SelectAllFailures() []*Failure {
var tks []float64 var tks []*Failure
rows, err := db.Query("SELECT * FROM failures WHERE service=$1 ORDER BY id ASC", id) rows, err := db.Query("SELECT * FROM failures WHERE service=$1 ORDER BY id DESC LIMIT 10", s.Id)
if err != nil { if err != nil {
panic(err) panic(err)
} }
for rows.Next() { for rows.Next() {
var tk Hit var tk Failure
err = rows.Scan(&tk.Id, &tk.Metric, &tk.Value, &tk.CreatedAt) err = rows.Scan(&tk.Id, &tk.Issue, &tk.Service, &tk.CreatedAt)
if err != nil { if err != nil {
panic(err) panic(err)
} }
tks = append(tks, tk.Value)
tk.Ago, _ = timeago.TimeAgoWithTime(time.Now(), tk.CreatedAt)
tks = append(tks, &tk)
} }
return tks return tks
} }
func CountFailures() int {
var amount int
db.QueryRow("SELECT COUNT(id) FROM failures;").Scan(&amount)
return amount
}
func (s *Service) TotalFailures() int { func (s *Service) TotalFailures() int {
var amount int var amount int
db.QueryRow("SELECT COUNT(id) FROM failures WHERE service=$1;", s.Id).Scan(&amount) 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 var amount int
t := time.Now() t := time.Now()
x := t.AddDate(0, 0, -1) 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 return amount
} }

View File

@ -21,14 +21,36 @@ HTML,BODY {
font-size: 26pt; font-size: 26pt;
font-weight: bold; font-weight: bold;
display: block; 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 { .stats_area {
text-align: center; text-align: center;
color: #a5a5a5;
} }
.offline_bg { .offline_bg {
background-color: #c5c5c578 !important; background-color: white !important;
} }
.footer { .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) { @media (max-width: 767px) {

View File

@ -43,18 +43,18 @@
<div class="row stats_area"> <div class="row stats_area">
<div class="col-4"> <div class="col-4">
<span class="lg_number">69</span> <span class="lg_number">{{ .CountServices }}</span>
24 Hour Hits Total Services
</div> </div>
<div class="col-4"> <div class="col-4">
<span class="lg_number">3921</span> <span class="lg_number">{{ .Count24Failures }}</span>
24 Hour Hits Failures last 24 Hours
</div> </div>
<div class="col-4"> <div class="col-4">
<span class="lg_number">453</span> <span class="lg_number">{{ .CountOnline }}</span>
Total Tokens Online Services
</div> </div>

View File

@ -8,22 +8,33 @@
<link rel="stylesheet" href="/css/base.css"> <link rel="stylesheet" href="/css/base.css">
<script src="/js/Chart.bundle.min.js"></script> <script src="/js/Chart.bundle.min.js"></script>
<title>Statup | Dashboard</title> <title>{{.Project}} Status</title>
</head> </head>
<body> <body>
<h1 class="text-center">{{.Project}}</h1> <h1 class="text-center mb-4">{{.Project}}</h1>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
{{ range .Services }} {{ range .Services }}
<div class="col-12 mb-4"> <div class="col-12 mb-4">
<div class="card"> <div class="card">
<div class="card-body{{if .Online}}{{else}} offline_bg{{end}}"> <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"> <div class="col-4">
<span class="lg_number">{{.Online24Hours}}%</span> <span class="lg_number">{{.Online24Hours}}%</span>
@ -39,10 +50,17 @@
<span class="lg_number">{{.TotalUptime}}%</span> <span class="lg_number">{{.TotalUptime}}%</span>
Total Uptime Total Uptime
</div> </div>
</div> </div>
<canvas id="service_{{ .Id }}" width="400" height="120"></canvas> <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> </div>
</div> </div>
@ -53,7 +71,7 @@
</div> </div>
<div class="footer text-center"> <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> </div>
<script> <script>

View File

@ -52,7 +52,8 @@
<tr> <tr>
<th scope="col">#</th> <th scope="col">#</th>
<th scope="col">Name</th> <th scope="col">Name</th>
<th scope="col">Actions</th> <th scope="col">Status</th>
<th scope="col"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -60,11 +61,12 @@
<tr> <tr>
<th scope="row">{{.Id}}</th> <th scope="row">{{.Id}}</th>
<td>{{.Name}}</td> <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"> <div class="btn-group" data-toggle="buttons">
<button class="btn btn-primary" type="submit">View</button> <a href="/services/{{.Id}}" class="btn btn-primary">View</a>
<button class="btn btn-primary" type="submit">Edit</button> <a href="/services/{{.Id}}/edit" class="btn btn-primary">Edit</a>
<button class="btn btn-primary" type="submit">Delete</button> <a href="/services/{{.Id}}/delete" class="btn btn-danger">Delete</a>
</div> </div>
</td> </td>
</tr> </tr>
@ -81,8 +83,8 @@
<form action="/services/create" method="POST"> <form action="/services/create" method="POST">
<div class="form-group row"> <div class="form-group row">
<label for="inputEmail3" class="col-sm-2 col-form-label">Name</label> <label for="inputEmail3" class="col-sm-4 col-form-label">Service Name</label>
<div class="col-sm-10"> <div class="col-sm-8">
<input type="text" name="name" class="form-control" id="inputEmail3" placeholder="Name"> <input type="text" name="name" class="form-control" id="inputEmail3" placeholder="Name">
</div> </div>
</div> </div>
@ -118,7 +120,8 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<div class="col-sm-10"> <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>
</div> </div>
</form> </form>

View File

@ -1,8 +1,8 @@
package main package main
import ( import (
"testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
func TestMakeConfig(t *testing.T) { func TestMakeConfig(t *testing.T) {

View File

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"math/rand" "math/rand"
"strconv"
"time" "time"
) )
@ -25,9 +26,10 @@ type Service struct {
Data string Data string
Online bool Online bool
Latency float64 Latency float64
Online24Hours float64 Online24Hours float32
AvgResponse string AvgResponse string
TotalUptime float64 TotalUptime string
Failures []*Failure
} }
func SelectService(id string) Service { func SelectService(id string) Service {
@ -57,6 +59,7 @@ func SelectAllServices() []*Service {
if err != nil { if err != nil {
panic(err) panic(err)
} }
tk.Failures = tk.SelectAllFailures()
tk.FormatData() tk.FormatData()
tks = append(tks, &tk) tks = append(tks, &tk)
} }
@ -79,7 +82,7 @@ func (s *Service) AvgTime() float64 {
return avg return avg
} }
func (s *Service) Online24() float64 { func (s *Service) Online24() float32 {
total := s.TotalHits() total := s.TotalHits()
failed := s.TotalFailures24Hours() failed := s.TotalFailures24Hours()
if failed == 0 { if failed == 0 {
@ -91,8 +94,13 @@ func (s *Service) Online24() float64 {
return s.Online24Hours return s.Online24Hours
} }
avg := float64(failed) / float64(total) * 100 avg := float64(failed) / float64(total) * 100
s.Online24Hours = avg avg = 100 - avg
return 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 { type GraphJson struct {
@ -116,20 +124,24 @@ func (s *Service) GraphData() string {
return s.Data return s.Data
} }
func (s *Service) AvgUptime() float64 { func (s *Service) AvgUptime() string {
failed := s.TotalFailures() failed := s.TotalFailures()
total := s.TotalHits() total := s.TotalHits()
if failed == 0 { if failed == 0 {
s.TotalUptime = 100.00 s.TotalUptime = "100.00"
return s.TotalUptime return s.TotalUptime
} }
if total == 0 { if total == 0 {
s.TotalUptime = 0 s.TotalUptime = "0"
return s.TotalUptime return s.TotalUptime
} }
percent := float64(failed) / float64(total) * 100 percent := float64(failed) / float64(total) * 100
s.TotalUptime = percent percent = 100 - percent
return percent if percent < 0 {
percent = 0
}
s.TotalUptime = fmt.Sprintf("%0.2f", percent)
return s.TotalUptime
} }
func (u *Service) Create() int { func (u *Service) Create() int {
@ -143,6 +155,16 @@ func (u *Service) Create() int {
return lastInsertId return lastInsertId
} }
func CountOnline() int {
amount := 0
for _, v := range services {
if v.Online {
amount++
}
}
return amount
}
func NewSHA1Hash(n ...int) string { func NewSHA1Hash(n ...int) string {
noRandomCharacters := 32 noRandomCharacters := 32

16
web.go
View File

@ -7,12 +7,6 @@ import (
"strconv" "strconv"
) )
type dashboard struct {
Services []*Service
Users []User
Core *Core
}
func RunHTTPServer() { func RunHTTPServer() {
fmt.Println("Fusioner HTTP Server running on http://localhost:8080") fmt.Println("Fusioner HTTP Server running on http://localhost:8080")
css := http.StripPrefix("/css/", http.FileServer(cssBox.HTTPBox())) css := http.StripPrefix("/css/", http.FileServer(cssBox.HTTPBox()))
@ -149,6 +143,14 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
indexTmpl.Execute(w, out) 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) { func DashboardHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "apizer_auth") session, _ := store.Get(r, "apizer_auth")
if auth, ok := session.Values["authenticated"].(bool); !ok || !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 { if err != nil {
panic(err) panic(err)
} }
out := dashboard{services, SelectAllUsers(), core} out := dashboard{services, core, CountOnline(), len(services), CountFailures()}
dashboardTmpl.Execute(w, out) dashboardTmpl.Execute(w, out)
} }