mirror of https://github.com/statping/statping
parent
fd7925aa7e
commit
60262f75f9
|
@ -149,6 +149,13 @@ func (s *Service) TotalFailures() (uint64, error) {
|
||||||
return count, err.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
|
// TotalFailuresSince returns the total amount of failures for a service since a specific time/date
|
||||||
func (s *Service) TotalFailuresSince(ago time.Time) (uint64, error) {
|
func (s *Service) TotalFailuresSince(ago time.Time) (uint64, error) {
|
||||||
var count uint64
|
var count uint64
|
||||||
|
|
|
@ -129,18 +129,6 @@ func (s *Service) OnlineDaysPercent(days int) float32 {
|
||||||
return s.OnlineSince(ago)
|
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.
|
// OnlineSince accepts a time since parameter to return the percent of a service's uptime.
|
||||||
func (s *Service) OnlineSince(ago time.Time) float32 {
|
func (s *Service) OnlineSince(ago time.Time) float32 {
|
||||||
failed, _ := s.TotalFailuresSince(ago)
|
failed, _ := s.TotalFailuresSince(ago)
|
||||||
|
@ -375,11 +363,6 @@ func (s *Service) Delete() error {
|
||||||
return err.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
|
// 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 {
|
func (s *Service) Update(restart bool) error {
|
||||||
err := servicesDB().Update(&s)
|
err := servicesDB().Update(&s)
|
||||||
|
@ -428,7 +411,7 @@ func (s *Service) Messages() []*Message {
|
||||||
return messages
|
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 {
|
func (s *Service) ActiveMessages() []*Message {
|
||||||
var messages []*Message
|
var messages []*Message
|
||||||
msgs := SelectServiceMessages(s.Id)
|
msgs := SelectServiceMessages(s.Id)
|
||||||
|
@ -440,12 +423,7 @@ func (s *Service) ActiveMessages() []*Message {
|
||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServicesCount returns the amount of services inside the []*core.Services slice
|
// CountOnline returns the amount of services online
|
||||||
func (c *Core) ServicesCount() int {
|
|
||||||
return len(c.Services)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountOnline
|
|
||||||
func (c *Core) CountOnline() int {
|
func (c *Core) CountOnline() int {
|
||||||
amount := 0
|
amount := 0
|
||||||
for _, s := range CoreApp.Services {
|
for _, s := range CoreApp.Services {
|
||||||
|
|
|
@ -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, ",") + "]"
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ func Router() *mux.Router {
|
||||||
r.Handle("/charts.js", http.HandlerFunc(renderServiceChartsHandler))
|
r.Handle("/charts.js", http.HandlerFunc(renderServiceChartsHandler))
|
||||||
r.Handle("/setup", http.HandlerFunc(setupHandler)).Methods("GET")
|
r.Handle("/setup", http.HandlerFunc(setupHandler)).Methods("GET")
|
||||||
r.Handle("/setup", http.HandlerFunc(processSetupHandler)).Methods("POST")
|
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("/dashboard", http.HandlerFunc(loginHandler)).Methods("POST")
|
||||||
r.Handle("/logout", http.HandlerFunc(logoutHandler))
|
r.Handle("/logout", http.HandlerFunc(logoutHandler))
|
||||||
r.Handle("/plugins/download/{name}", http.HandlerFunc(pluginsDownloadHandler))
|
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
|
@ -5,7 +5,7 @@
|
||||||
<div class="col-12 mt-3">
|
<div class="col-12 mt-3">
|
||||||
<div class="row stats_area mb-5">
|
<div class="row stats_area mb-5">
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<span class="lg_number">{{ CoreApp.ServicesCount }}</span>
|
<span class="lg_number">{{ len Services }}</span>
|
||||||
Total Services
|
Total Services
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
|
@ -17,6 +17,29 @@
|
||||||
Online Services
|
Online Services
|
||||||
</div>
|
</div>
|
||||||
</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="row mt-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
{{if eq (len CoreApp.Services) 0}}
|
{{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>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{end}}
|
||||||
<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 }}
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{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}}
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
|
|
||||||
<div class="service-chart-container">
|
<div class="service-chart-container">
|
||||||
<div id="service"></div>
|
<div id="service"></div>
|
||||||
|
<div id="service-bar"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="service-chart-heatmap">
|
<div class="service-chart-heatmap">
|
||||||
|
@ -262,6 +263,7 @@ let options = {
|
||||||
],
|
],
|
||||||
xaxis: {
|
xaxis: {
|
||||||
type: "datetime",
|
type: "datetime",
|
||||||
|
tickAmount: 8,
|
||||||
},
|
},
|
||||||
yaxis: {
|
yaxis: {
|
||||||
labels: {
|
labels: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// This file was generated by robots at
|
// 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.
|
// This contains the most recently Markdown source for the Statping Wiki.
|
||||||
package source
|
package source
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.80.41
|
0.80.42
|
||||||
|
|
Loading…
Reference in New Issue