mirror of https://github.com/statping/statping
parent
b4ff76c70d
commit
b58326a453
|
@ -18,7 +18,7 @@ services:
|
|||
|
||||
env:
|
||||
global:
|
||||
- VERSION=0.28.91
|
||||
- VERSION=0.29
|
||||
- DB_HOST=localhost
|
||||
- DB_USER=travis
|
||||
- DB_PASS=
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM alpine:latest
|
||||
|
||||
ENV VERSION=v0.28.91
|
||||
ENV VERSION=v0.29
|
||||
|
||||
RUN apk --no-cache add libstdc++ ca-certificates
|
||||
RUN wget -q https://github.com/hunterlong/statup/releases/download/$VERSION/statup-linux-alpine.tar.gz && \
|
||||
|
|
|
@ -131,9 +131,9 @@ func (s *Service) GraphData() string {
|
|||
// group by interval sql query for postgres, mysql and sqlite
|
||||
sql := fmt.Sprintf("SELECT date_trunc('%v', created_at), AVG(latency)*1000 AS value FROM hits WHERE service=%v AND created_at > '%v' GROUP BY 1 ORDER BY date_trunc ASC;", increment, s.Id, since.Format(time.RFC3339))
|
||||
if dbServer == "mysql" {
|
||||
sql = fmt.Sprintf("SELECT CONCAT(date_format(created_at, '%%Y-%%m-%%dT%%TZ')) AS created_at, AVG(latency)*1000 AS value FROM hits WHERE service=%v AND DATE_FORMAT(created_at, '%%Y-%%m-%%dT%%TZ') BETWEEN DATE_FORMAT(NOW() - INTERVAL 12 HOUR, '%%Y-%%m-%%dT%%TZ') AND DATE_FORMAT(NOW(), '%%Y-%%m-%%dT%%TZ') GROUP BY created_at", s.Id)
|
||||
sql = fmt.Sprintf("SELECT CONCAT(date_format(created_at, '%%Y-%%m-%%dT%%TZ')) AS created_at, AVG(latency)*1000 AS value FROM hits WHERE service=%v AND DATE_FORMAT(created_at, '%%Y-%%m-%%dT%%TZ') BETWEEN DATE_FORMAT(NOW() - INTERVAL 12 HOUR, '%%Y-%%m-%%dT%%TZ') AND DATE_FORMAT(NOW(), '%%Y-%%m-%%dT%%TZ') GROUP BY created_at ORDER BY created_at ASC;", s.Id)
|
||||
} else if dbServer == "sqlite" {
|
||||
sql = fmt.Sprintf("SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%SZ', created_at), AVG(latency)*1000 as value FROM hits WHERE service=%v AND created_at >= '%v' GROUP BY strftime('%%M', created_at)", s.Id, since.Format(time.RFC3339))
|
||||
sql = fmt.Sprintf("SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%SZ', created_at), AVG(latency)*1000 as value FROM hits WHERE service=%v AND created_at >= '%v' GROUP BY strftime('%%M', created_at) ORDER BY created_at ASC;", s.Id, since.Format(time.RFC3339))
|
||||
}
|
||||
dated, err := DbSession.Query(db.Raw(sql))
|
||||
if err != nil {
|
||||
|
|
|
@ -98,4 +98,19 @@ func ExecuteResponse(w http.ResponseWriter, r *http.Request, file string, data i
|
|||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func ExecuteJSResponse(w http.ResponseWriter, r *http.Request, file string, data interface{}) {
|
||||
render, err := core.JsBox.String(file)
|
||||
if err != nil {
|
||||
utils.Log(4, err)
|
||||
}
|
||||
t := template.New("charts")
|
||||
t.Funcs(template.FuncMap{
|
||||
"safe": func(html string) template.HTML {
|
||||
return template.HTML(html)
|
||||
},
|
||||
})
|
||||
t.Parse(render)
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
type DbConfig types.DbConfig
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/hunterlong/statup/core"
|
||||
"github.com/tdewolff/minify"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
|
@ -11,6 +12,8 @@ func Router() *mux.Router {
|
|||
r := mux.NewRouter()
|
||||
r.Handle("/", http.HandlerFunc(IndexHandler))
|
||||
LocalizedAssets(r)
|
||||
m := minify.New()
|
||||
r.Handle("/charts.js", m.Middleware(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")
|
||||
|
|
|
@ -9,6 +9,13 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
func RenderServiceChartsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
services := core.CoreApp.Services
|
||||
//w.Header().Set("Content-Type", "text/javascript")
|
||||
//w.Header().Set("Cache-Control", "no-cache, private, max-age=0")
|
||||
ExecuteJSResponse(w, r, "charts.js", services)
|
||||
}
|
||||
|
||||
func ServicesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !IsAuthenticated(r) {
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
{{ range . }}{{ if .AvgTime }}var ctx = document.getElementById("service_{{.Id}}").getContext('2d');
|
||||
|
||||
var chartdata = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
label: 'Response Time (Milliseconds)',
|
||||
data: {{safe .GraphData}},
|
||||
backgroundColor: [
|
||||
'rgba(47, 206, 30, 0.92)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgb(47, 171, 34)'
|
||||
],
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
scaleShowValues: true,
|
||||
layout: {
|
||||
padding: {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: -10
|
||||
}
|
||||
},
|
||||
hover: {
|
||||
animationDuration: 0,
|
||||
},
|
||||
responsiveAnimationDuration: 0,
|
||||
animation: {
|
||||
duration: 3500,
|
||||
onComplete: function() {
|
||||
var chartInstance = this.chart,
|
||||
ctx = chartInstance.ctx;
|
||||
|
||||
var controller = this.chart.controller;
|
||||
var xAxis = controller.scales['x-axis-0'];
|
||||
var yAxis = controller.scales['y-axis-0'];
|
||||
|
||||
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'bottom';
|
||||
|
||||
var numTicks = xAxis.ticks.length;
|
||||
var yOffsetStart = xAxis.width / numTicks;
|
||||
var halfBarWidth = (xAxis.width / (numTicks * 2));
|
||||
|
||||
xAxis.ticks.forEach(function(value, index) {
|
||||
var xOffset = 20;
|
||||
var yOffset = (yOffsetStart * index) + halfBarWidth;
|
||||
ctx.fillStyle = '#e2e2e2';
|
||||
ctx.fillText(value, yOffset, xOffset);
|
||||
});
|
||||
|
||||
this.data.datasets.forEach(function(dataset, i) {
|
||||
var meta = chartInstance.controller.getDatasetMeta(i);
|
||||
var hxH = 0;
|
||||
var hyH = 0;
|
||||
var hxL = 0;
|
||||
var hyL = 0;
|
||||
var highestNum = 0;
|
||||
var lowestnum = 999999999999;
|
||||
meta.data.forEach(function(bar, index) {
|
||||
var data = dataset.data[index];
|
||||
|
||||
if (data.y {{safe "<"}} lowestnum) {
|
||||
lowestnum = data.y;
|
||||
hxL = bar._model.x;
|
||||
hyL = bar._model.y;
|
||||
}
|
||||
|
||||
if (data.y > highestNum) {
|
||||
highestNum = data.y;
|
||||
hxH = bar._model.x;
|
||||
hyH = bar._model.y;
|
||||
}
|
||||
});
|
||||
|
||||
if (hxH {{safe ">"}}= 820) {
|
||||
hxH = 820;
|
||||
} else if (hxH {{safe "<"}}= 50) {
|
||||
hxH = 50;
|
||||
}
|
||||
|
||||
if (hxL {{safe ">"}}= 820) {
|
||||
hxL = 820;
|
||||
} else if (hxL {{safe "<"}}= 70) {
|
||||
hxL = 70;
|
||||
}
|
||||
|
||||
ctx.fillStyle = '#ffa7a2';
|
||||
ctx.fillText(highestNum+"ms", hxH - 40, hyH + 15);
|
||||
ctx.fillStyle = '#45d642';
|
||||
ctx.fillText(lowestnum+"ms", hxL, hyL + 10);
|
||||
|
||||
console.log("done service_id_{{.Id}}")
|
||||
|
||||
});
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltips: {
|
||||
"enabled": false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
display: false,
|
||||
ticks: {
|
||||
fontSize: 20,
|
||||
display: false,
|
||||
beginAtZero: false
|
||||
},
|
||||
gridLines: {
|
||||
display:false
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
distribution: 'series',
|
||||
autoSkip: false,
|
||||
gridLines: {
|
||||
display:false
|
||||
},
|
||||
ticks: {
|
||||
stepSize: 1,
|
||||
min: 0,
|
||||
fontColor: "white",
|
||||
fontSize: 20,
|
||||
display: false,
|
||||
}
|
||||
}]
|
||||
},
|
||||
elements: {
|
||||
point: {
|
||||
radius: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
{{ end }}
|
||||
{{ end }}
|
|
@ -104,159 +104,8 @@
|
|||
<script src="/js/bootstrap.min.js"></script>
|
||||
<script src="/js/Chart.bundle.min.js"></script>
|
||||
{{end}}
|
||||
|
||||
<script>
|
||||
{{ range .Services }}
|
||||
{{ if .AvgTime }}
|
||||
var ctx = document.getElementById("service_{{.Id}}").getContext('2d');
|
||||
|
||||
var chartdata = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
label: 'Response Time (Milliseconds)',
|
||||
data: {{js .GraphData}},
|
||||
backgroundColor: [
|
||||
'rgba(47, 206, 30, 0.92)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgb(47, 171, 34)'
|
||||
],
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
scaleShowValues: true,
|
||||
layout: {
|
||||
padding: {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: -10
|
||||
}
|
||||
},
|
||||
hover: {
|
||||
animationDuration: 0,
|
||||
},
|
||||
responsiveAnimationDuration: 0,
|
||||
animation: {
|
||||
duration: 3500,
|
||||
onComplete: function() {
|
||||
var chartInstance = this.chart,
|
||||
ctx = chartInstance.ctx;
|
||||
|
||||
var controller = this.chart.controller;
|
||||
var xAxis = controller.scales['x-axis-0'];
|
||||
var yAxis = controller.scales['y-axis-0'];
|
||||
|
||||
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'bottom';
|
||||
|
||||
var numTicks = xAxis.ticks.length;
|
||||
var yOffsetStart = xAxis.width / numTicks;
|
||||
var halfBarWidth = (xAxis.width / (numTicks * 2));
|
||||
|
||||
xAxis.ticks.forEach(function(value, index) {
|
||||
var xOffset = 20;
|
||||
var yOffset = (yOffsetStart * index) + halfBarWidth;
|
||||
ctx.fillStyle = '#e2e2e2';
|
||||
ctx.fillText(value, yOffset, xOffset);
|
||||
});
|
||||
|
||||
this.data.datasets.forEach(function(dataset, i) {
|
||||
var meta = chartInstance.controller.getDatasetMeta(i);
|
||||
var hxH = 0;
|
||||
var hyH = 0;
|
||||
var hxL = 0;
|
||||
var hyL = 0;
|
||||
var highestNum = 0;
|
||||
var lowestnum = 999999999999;
|
||||
meta.data.forEach(function(bar, index) {
|
||||
var data = dataset.data[index];
|
||||
|
||||
if (data.y < lowestnum) {
|
||||
lowestnum = data.y;
|
||||
hxL = bar._model.x;
|
||||
hyL = bar._model.y;
|
||||
}
|
||||
|
||||
if (data.y > highestNum) {
|
||||
highestNum = data.y;
|
||||
hxH = bar._model.x;
|
||||
hyH = bar._model.y;
|
||||
}
|
||||
});
|
||||
|
||||
if (hxH >= 820) {
|
||||
hxH = 820;
|
||||
} else if (hxH <= 50) {
|
||||
hxH = 50;
|
||||
}
|
||||
|
||||
if (hxL >= 820) {
|
||||
hxL = 820;
|
||||
} else if (hxL <= 70) {
|
||||
hxL = 70;
|
||||
}
|
||||
|
||||
ctx.fillStyle = '#ffa7a2';
|
||||
ctx.fillText(highestNum+"ms", hxH - 40, hyH + 15);
|
||||
ctx.fillStyle = '#45d642';
|
||||
ctx.fillText(lowestnum+"ms", hxL, hyL + 10);
|
||||
|
||||
console.log("done service_id_{{.Id}}")
|
||||
|
||||
});
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltips: {
|
||||
"enabled": false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
display: false,
|
||||
ticks: {
|
||||
fontSize: 20,
|
||||
display: false,
|
||||
beginAtZero: false
|
||||
},
|
||||
gridLines: {
|
||||
display:false
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
distribution: 'series',
|
||||
autoSkip: false,
|
||||
gridLines: {
|
||||
display:false
|
||||
},
|
||||
ticks: {
|
||||
stepSize: 1,
|
||||
min: 0,
|
||||
fontColor: "white",
|
||||
fontSize: 20,
|
||||
display: false,
|
||||
}
|
||||
}]
|
||||
},
|
||||
elements: {
|
||||
point: {
|
||||
radius: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</script>
|
||||
|
||||
<script src="/js/main.js"></script>
|
||||
<script src="/charts.js"></script>
|
||||
|
||||
{{ if .Core.Style }}
|
||||
<style>
|
||||
|
|
Loading…
Reference in New Issue