dashboard updates

pull/135/head v0.80.42
hunterlong 2019-02-01 11:57:59 -08:00
parent fd7925aa7e
commit 60262f75f9
10 changed files with 225 additions and 65 deletions

View File

@ -149,6 +149,13 @@ func (s *Service) TotalFailures() (uint64, error) {
return count, err.Error
}
// FailuresDaysAgo returns the amount of failures since days ago
func (s *Service) FailuresDaysAgo(days int) uint64 {
ago := time.Now().Add((-24 * time.Duration(days)) * time.Hour)
count, _ := s.TotalFailuresSince(ago)
return count
}
// TotalFailuresSince returns the total amount of failures for a service since a specific time/date
func (s *Service) TotalFailuresSince(ago time.Time) (uint64, error) {
var count uint64

View File

@ -129,18 +129,6 @@ func (s *Service) OnlineDaysPercent(days int) float32 {
return s.OnlineSince(ago)
}
// Online24 returns the service's uptime percent within last 24 hours
func (s *Service) Online24() float32 {
ago := time.Now().Add(-24 * time.Hour)
return s.OnlineSince(ago)
}
// Online7Days returns the service's uptime percent within last 7 days
func (s *Service) Online7Days() float32 {
ago := time.Now().Add((-24 * 7) * time.Hour)
return s.OnlineSince(ago)
}
// OnlineSince accepts a time since parameter to return the percent of a service's uptime.
func (s *Service) OnlineSince(ago time.Time) float32 {
failed, _ := s.TotalFailuresSince(ago)
@ -375,11 +363,6 @@ func (s *Service) Delete() error {
return err.Error
}
// UpdateSingle will update a single column for a service
func (s *Service) UpdateSingle(attr ...interface{}) error {
return servicesDB().Model(s).Update(attr).Error
}
// Update will update a service in the database, the service's checking routine can be restarted by passing true
func (s *Service) Update(restart bool) error {
err := servicesDB().Update(&s)
@ -428,7 +411,7 @@ func (s *Service) Messages() []*Message {
return messages
}
// ActiveMessages returns all Messages for a Service
// ActiveMessages returns all service messages that are available based on the current time
func (s *Service) ActiveMessages() []*Message {
var messages []*Message
msgs := SelectServiceMessages(s.Id)
@ -440,12 +423,7 @@ func (s *Service) ActiveMessages() []*Message {
return messages
}
// ServicesCount returns the amount of services inside the []*core.Services slice
func (c *Core) ServicesCount() int {
return len(c.Services)
}
// CountOnline
// CountOnline returns the amount of services online
func (c *Core) CountOnline() int {
amount := 0
for _, s := range CoreApp.Services {

31
core/sparklines.go Normal file
View File

@ -0,0 +1,31 @@
package core
import (
"github.com/hunterlong/statping/utils"
"strings"
"time"
)
// SparklineDayFailures returns a string array of daily service failures
func (s *Service) SparklineDayFailures(days int) string {
var arr []string
ago := time.Now().Add((time.Duration(days) * -24) * time.Hour)
for day := 1; day <= days; day++ {
ago = ago.Add(24 * time.Hour)
failures, _ := s.TotalFailuresOnDate(ago)
arr = append(arr, utils.ToString(failures))
}
return "[" + strings.Join(arr, ",") + "]"
}
// SparklineHourResponse returns a string array for the average response or ping time for a service
func (s *Service) SparklineHourResponse(hours int, method string) string {
var arr []string
end := time.Now().UTC()
start := end.Add(time.Duration(-hours) * time.Hour)
obj := GraphDataRaw(s, start, end, "hour", method)
for _, v := range obj.Array {
arr = append(arr, utils.ToString(v.Value))
}
return "[" + strings.Join(arr, ",") + "]"
}

View File

@ -55,7 +55,7 @@ func Router() *mux.Router {
r.Handle("/charts.js", http.HandlerFunc(renderServiceChartsHandler))
r.Handle("/setup", http.HandlerFunc(setupHandler)).Methods("GET")
r.Handle("/setup", http.HandlerFunc(processSetupHandler)).Methods("POST")
r.Handle("/dashboard", http.HandlerFunc(dashboardHandler)).Methods("GET")
r.Handle("/dashboard", cached("60s", "text/html", http.HandlerFunc(dashboardHandler))).Methods("GET")
r.Handle("/dashboard", http.HandlerFunc(loginHandler)).Methods("POST")
r.Handle("/logout", http.HandlerFunc(logoutHandler))
r.Handle("/plugins/download/{name}", http.HandlerFunc(pluginsDownloadHandler))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<div class="col-12 mt-3">
<div class="row stats_area mb-5">
<div class="col-4">
<span class="lg_number">{{ CoreApp.ServicesCount }}</span>
<span class="lg_number">{{ len Services }}</span>
Total Services
</div>
<div class="col-4">
@ -17,6 +17,29 @@
Online Services
</div>
</div>
{{ range Services }}
<div class="col-12 card mb-3" style="min-height: 260px">
<div class="card-body">
<h5 class="card-title"><a href="/service/{{.Id}}">{{.Name}}</a> {{if .Online}}<span class="badge float-right badge-success">ONLINE</span>{{else}}<span class="badge float-right badge-danger">OFFLINE</span>{{end}}</h5>
<div class="row">
<div class="col-md-3 col-sm-6">
<div id="spark_service_{{.Id}}_1"></div>
</div>
<div class="col-md-3 col-sm-6">
<div id="spark_service_{{.Id}}_2"></div>
</div>
<div class="col-md-3 col-sm-6">
<div id="spark_service_{{.Id}}_3"></div>
</div>
<div class="col-md-3 col-sm-6">
<div id="spark_service_{{.Id}}_4"></div>
</div>
</div>
</div>
</div>
{{end}}
<div class="row mt-4">
<div class="col-12">
{{if eq (len CoreApp.Services) 0}}
@ -26,41 +49,160 @@
<a class="lead">You don't have any websites or applications being monitored by your Statping server. <p><a href="/services" class="btn btn-secondary mt-3">Add Service</a></p></p>
</div>
</div>
{{else}}
<div class="list-group mb-5 mt-3">
{{ range Services }}
<a href="#" class="list-group-item list-group-item-action flex-column align-items-start">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{.Name}}</h5>
<small>{{if .Online}} <span class="badge badge-success">ONLINE</span> {{else}} <span class="badge badge-danger">OFFLINE</span> {{end}}</small>
</div>
<p class="mb-1">{{.SmallText}}</p>
</a>
{{ end }}
{{end}}
</div>
{{ range Services }}
{{$failures := .LimitedFailures 16}}
{{ if $failures }}
<h4 class="text-truncate">{{.Name}} Failures</h4>
<div class="list-group mt-3 mb-4">
{{ range $failures }}
<a href="#" class="list-group-item list-group-item-action flex-column align-items-start">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{.ParseError}}</h5>
<small>{{.Ago}}</small>
</div>
<p class="mb-1">{{.Issue}}</p>
</a>
{{ end }}
</div>
{{ end }}
{{ end }}
{{end}}
</div>
</div>
</div>
</div>
{{end}}
{{define "extra_scripts"}}
<script>
function AddTotal(arr) {
var total = 0;
arr.forEach(function(d) {
total += d
});
return total.toString();
}
function Average(arr) {
var total = AddTotal(arr);
if (arr.length === 0) {
return total+"ms"
}
return (total / arr.length).toFixed(0)+"ms";
}
const sparkOption = {
chart: {
type: 'area',
height: 180,
sparkline: {
enabled: true
},
},
stroke: {
curve: 'straight'
},
fill: {
opacity: 0.3,
},
yaxis: {
min: 0
},
colors: ['#DCE6EC'],
tooltip: {
enabled: false
}
}
{{ range Services }}
var sparklineData_{{js .Id}}_1 = {{js (.SparklineDayFailures 7)}};
var sparklineData_{{js .Id}}_2 = {{js (.SparklineDayFailures 30)}};
var sparklineData_{{js .Id}}_3 = {{js (.SparklineHourResponse 30 "latency")}};
var sparklineData_{{js .Id}}_4 = {{js (.SparklineHourResponse 30 "ping_time")}};
var options_{{js .Id}}_1 = {
...sparkOption,
title: {
text: AddTotal(sparklineData_{{js .Id}}_1),
offsetX: 0,
style: {
fontSize: '28px',
cssClass: 'apexcharts-yaxis-title'
}
},
subtitle: {
text: 'Failures Last 7 Days',
offsetX: 0,
style: {
fontSize: '14px',
cssClass: 'apexcharts-yaxis-title'
}
},
series: [{
data: sparklineData_{{js .Id}}_1
}],
};
var options_{{js .Id}}_2 = {
...sparkOption,
title: {
text: AddTotal(sparklineData_{{js .Id}}_2),
offsetX: 0,
style: {
fontSize: '28px',
cssClass: 'apexcharts-yaxis-title'
}
},
subtitle: {
text: 'Failures Last Month',
offsetX: 0,
style: {
fontSize: '14px',
cssClass: 'apexcharts-yaxis-title'
}
},
series: [{
data: sparklineData_{{js .Id}}_2
}],
};
var options_{{js .Id}}_3 = {
...sparkOption,
title: {
text: Average(sparklineData_{{js .Id}}_3),
offsetX: 0,
style: {
fontSize: '28px',
cssClass: 'apexcharts-yaxis-title'
}
},
subtitle: {
text: 'Average Response',
offsetX: 0,
style: {
fontSize: '14px',
cssClass: 'apexcharts-yaxis-title'
}
},
series: [{
data: sparklineData_{{js .Id}}_3
}],
};
var options_{{js .Id}}_4 = {
...sparkOption,
title: {
text: Average(sparklineData_{{js .Id}}_4),
offsetX: 0,
style: {
fontSize: '28px',
cssClass: 'apexcharts-yaxis-title'
}
},
subtitle: {
text: 'Ping Time',
offsetX: 0,
style: {
fontSize: '14px',
cssClass: 'apexcharts-yaxis-title'
}
},
series: [{
data: sparklineData_{{js .Id}}_4
}],
};
{{end}}
{{ range Services }}
var spark_{{js .Id}}_1 = new ApexCharts(document.querySelector("#spark_service_{{.Id}}_1"), options_{{js .Id}}_1);
var spark_{{js .Id}}_2 = new ApexCharts(document.querySelector("#spark_service_{{.Id}}_2"), options_{{js .Id}}_2);
var spark_{{js .Id}}_3 = new ApexCharts(document.querySelector("#spark_service_{{.Id}}_3"), options_{{js .Id}}_3);
var spark_{{js .Id}}_4 = new ApexCharts(document.querySelector("#spark_service_{{.Id}}_4"), options_{{js .Id}}_4);
spark_{{js .Id}}_1.render();
spark_{{js .Id}}_2.render();
spark_{{js .Id}}_3.render();
spark_{{js .Id}}_4.render();
{{end}}
</script>
{{end}}

View File

@ -58,6 +58,7 @@
<div class="service-chart-container">
<div id="service"></div>
<div id="service-bar"></div>
</div>
<div class="service-chart-heatmap">
@ -262,6 +263,7 @@ let options = {
],
xaxis: {
type: "datetime",
tickAmount: 8,
},
yaxis: {
labels: {

View File

@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2019-01-31 20:41:27.660641 -0800 PST m=+0.622147537
// 2019-02-01 11:55:53.781812 -0800 PST m=+0.615412774
//
// This contains the most recently Markdown source for the Statping Wiki.
package source

View File

@ -1 +1 @@
0.80.41
0.80.42