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
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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("/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
|
@ -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}}
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.80.41
|
||||
0.80.42
|
||||
|
|
Loading…
Reference in New Issue