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