mirror of https://github.com/statping/statping
core updates - sql migrations
parent
b58326a453
commit
cb46bf6496
|
@ -18,7 +18,7 @@ services:
|
|||
|
||||
env:
|
||||
global:
|
||||
- VERSION=0.29
|
||||
- VERSION=0.29.1
|
||||
- DB_HOST=localhost
|
||||
- DB_USER=travis
|
||||
- DB_PASS=
|
||||
|
|
|
@ -5,7 +5,7 @@ gem install sass
|
|||
sass source/scss/base.scss source/css/base.css
|
||||
|
||||
# MIGRATION SQL FILE FOR CURRENT VERSION
|
||||
printf "UPDATE core SET version='$VERSION';\n" >> source/sql/upgrade.sql
|
||||
#printf "UPDATE core SET version='$VERSION';\n" >> source/sql/upgrade.sql
|
||||
|
||||
# COMPILE SRC INTO BIN
|
||||
rice embed-go
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM alpine:latest
|
||||
|
||||
ENV VERSION=v0.29
|
||||
ENV VERSION=v0.29.1
|
||||
|
||||
RUN apk --no-cache add libstdc++ ca-certificates
|
||||
RUN wget -q https://github.com/hunterlong/statup/releases/download/$VERSION/statup-linux-alpine.tar.gz && \
|
||||
|
|
|
@ -13,12 +13,13 @@ var (
|
|||
)
|
||||
|
||||
func LoadConfig() (*Config, error) {
|
||||
var config Config
|
||||
var config *Config
|
||||
file, err := ioutil.ReadFile("config.yml")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = yaml.Unmarshal(file, &config)
|
||||
Configs = &config
|
||||
return &config, err
|
||||
Configs = config
|
||||
CoreApp.DbConnection = config.Connection
|
||||
return config, err
|
||||
}
|
||||
|
|
18
core/core.go
18
core/core.go
|
@ -4,6 +4,7 @@ import (
|
|||
"github.com/GeertJohan/go.rice"
|
||||
"github.com/hunterlong/statup/plugin"
|
||||
"github.com/hunterlong/statup/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
type PluginJSON types.PluginJSON
|
||||
|
@ -25,6 +26,8 @@ type Core struct {
|
|||
AllPlugins []plugin.PluginActions
|
||||
Communications []*types.Communication
|
||||
OfflineAssets bool
|
||||
DbConnection string
|
||||
started time.Time
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -41,7 +44,13 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
CoreApp = NewCore()
|
||||
}
|
||||
|
||||
func NewCore() *Core {
|
||||
CoreApp = new(Core)
|
||||
CoreApp.started = time.Now()
|
||||
return CoreApp
|
||||
}
|
||||
|
||||
func InitApp() {
|
||||
|
@ -56,9 +65,10 @@ func InitApp() {
|
|||
|
||||
func (c *Core) Update() (*Core, error) {
|
||||
res := DbSession.Collection("core").Find().Limit(1)
|
||||
res.Update(c)
|
||||
err := res.Update(c)
|
||||
CoreApp = c
|
||||
return c, nil
|
||||
CoreApp.Services, err = SelectAllServices()
|
||||
return c, err
|
||||
}
|
||||
|
||||
func (c Core) UsingAssets() bool {
|
||||
|
@ -102,6 +112,10 @@ func SelectCore() (*Core, error) {
|
|||
return nil, err
|
||||
}
|
||||
CoreApp = c
|
||||
CoreApp.DbConnection = Configs.Connection
|
||||
CoreApp.Version = VERSION
|
||||
CoreApp.Services, _ = SelectAllServices()
|
||||
CoreApp.Update()
|
||||
//store = sessions.NewCookieStore([]byte(core.ApiSecret))
|
||||
return CoreApp, err
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
dbServer string
|
||||
sqliteSettings sqlite.ConnectionURL
|
||||
postgresSettings postgresql.ConnectionURL
|
||||
mysqlSettings mysql.ConnectionURL
|
||||
|
@ -68,7 +67,6 @@ func DbConnection(dbType string) error {
|
|||
}
|
||||
}
|
||||
//dbSession.SetLogging(true)
|
||||
dbServer = dbType
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -130,20 +128,87 @@ func (c *DbConfig) Save() error {
|
|||
if err == nil {
|
||||
CoreApp = newCore
|
||||
}
|
||||
|
||||
CoreApp, err = SelectCore()
|
||||
CoreApp.DbConnection = c.DbConn
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func RunDatabaseUpgrades() {
|
||||
utils.Log(1, "Running Database Upgrade from 'upgrade.sql'...")
|
||||
upgrade, _ := SqlBox.String("upgrade.sql")
|
||||
requests := strings.Split(upgrade, ";")
|
||||
for _, request := range requests {
|
||||
_, err := DbSession.Exec(db.Raw(request + ";"))
|
||||
if err != nil {
|
||||
utils.Log(2, err)
|
||||
func versionSplit(v string) (int64, int64, int64) {
|
||||
currSplit := strings.Split(v, ".")
|
||||
if len(currSplit) < 2 {
|
||||
return 9999, 9999, 9999
|
||||
}
|
||||
var major, mid, minor string
|
||||
if len(currSplit) == 3 {
|
||||
major = currSplit[0]
|
||||
mid = currSplit[1]
|
||||
minor = currSplit[2]
|
||||
return utils.StringInt(major), utils.StringInt(mid), utils.StringInt(minor)
|
||||
}
|
||||
major = currSplit[0]
|
||||
mid = currSplit[1]
|
||||
return utils.StringInt(major), utils.StringInt(mid), 0
|
||||
}
|
||||
|
||||
func versionHigher(migrate string) bool {
|
||||
cM, cMi, cMn := versionSplit(CoreApp.Version)
|
||||
mM, mMi, mMn := versionSplit(migrate)
|
||||
if mM > cM {
|
||||
return true
|
||||
}
|
||||
if mMi > cMi {
|
||||
return true
|
||||
}
|
||||
if mMn > cMn {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func RunDatabaseUpgrades() error {
|
||||
var err error
|
||||
utils.Log(1, fmt.Sprintf("Checking Database Upgrades from v%v in '%v_upgrade.sql'...", CoreApp.Version, CoreApp.DbConnection))
|
||||
upgrade, _ := SqlBox.String(CoreApp.DbConnection + "_upgrade.sql")
|
||||
// parse db version and upgrade file
|
||||
ups := strings.Split(upgrade, "=========================================== ")
|
||||
var ran int
|
||||
for _, v := range ups {
|
||||
if len(v) == 0 {
|
||||
continue
|
||||
}
|
||||
vers := strings.Split(v, "\n")
|
||||
version := vers[0]
|
||||
data := vers[1:]
|
||||
//fmt.Printf("Checking Migration from v%v to v%v - %v\n", CoreApp.Version, version, versionHigher(version))
|
||||
if !versionHigher(version) {
|
||||
//fmt.Printf("Already up-to-date with v%v\n", version)
|
||||
continue
|
||||
}
|
||||
fmt.Printf("Migration Database from v%v to v%v\n", CoreApp.Version, version)
|
||||
for _, m := range data {
|
||||
if m == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("Running Migration: %v\n", m)
|
||||
_, err := DbSession.Exec(db.Raw(m + ";"))
|
||||
if err != nil {
|
||||
utils.Log(2, err)
|
||||
continue
|
||||
}
|
||||
ran++
|
||||
CoreApp.Version = m
|
||||
}
|
||||
}
|
||||
utils.Log(1, "Database Upgraded")
|
||||
CoreApp.Update()
|
||||
CoreApp, err = SelectCore()
|
||||
if ran > 0 {
|
||||
utils.Log(1, fmt.Sprintf("Database Upgraded, %v query ran", ran))
|
||||
} else {
|
||||
utils.Log(1, fmt.Sprintf("Database is already up-to-date, latest v%v", CoreApp.Version))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func DropDatabase() {
|
||||
|
@ -161,9 +226,9 @@ func DropDatabase() {
|
|||
func CreateDatabase() {
|
||||
fmt.Println("Creating Tables...")
|
||||
sql := "postgres_up.sql"
|
||||
if dbServer == "mysql" {
|
||||
if CoreApp.DbConnection == "mysql" {
|
||||
sql = "mysql_up.sql"
|
||||
} else if dbServer == "sqlite" {
|
||||
} else if CoreApp.DbConnection == "sqlite" {
|
||||
sql = "sqlite_up.sql"
|
||||
}
|
||||
up, _ := SqlBox.String(sql)
|
||||
|
|
|
@ -124,17 +124,27 @@ func (s *Service) SmallText() string {
|
|||
return fmt.Sprintf("No Failures in the last 24 hours! %v", hits[0])
|
||||
}
|
||||
|
||||
func GroupDataBy(column string, id int64, tm time.Time, increment string) string {
|
||||
var sql string
|
||||
fmt.Println("gropu by", column, CoreApp.DbConnection)
|
||||
switch CoreApp.DbConnection {
|
||||
case "mysql":
|
||||
sql = fmt.Sprintf("SELECT CONCAT(date_format(created_at, '%%Y-%%m-%%dT%%H:%%i:00Z')) AS created_at, AVG(latency)*1000 AS value FROM %v WHERE service=%v AND DATE_FORMAT(created_at, '%%Y-%%m-%%dT%%TZ') BETWEEN DATE_FORMAT('%v', '%%Y-%%m-%%dT%%TZ') AND DATE_FORMAT(NOW(), '%%Y-%%m-%%dT%%TZ') GROUP BY 1 ORDER BY created_at ASC;", column, id, tm.Format(time.RFC3339))
|
||||
case "sqlite":
|
||||
sql = fmt.Sprintf("SELECT strftime('%%Y-%%m-%%dT%%H:%%M:00Z', created_at), AVG(latency)*1000 as value FROM %v WHERE service=%v AND created_at >= '%v' GROUP BY strftime('%%M:00', created_at) ORDER BY created_at ASC;", column, id, tm.Format(time.RFC3339))
|
||||
case "postgres":
|
||||
sql = fmt.Sprintf("SELECT date_trunc('%v', created_at), AVG(latency)*1000 AS value FROM %v WHERE service=%v AND created_at >= '%v' GROUP BY 1 ORDER BY date_trunc ASC;", increment, column, id, tm.Format(time.RFC3339))
|
||||
}
|
||||
fmt.Println(sql)
|
||||
return sql
|
||||
}
|
||||
|
||||
func (s *Service) GraphData() string {
|
||||
var d []*DateScan
|
||||
increment := "minute"
|
||||
since := time.Now().Add(time.Hour*-24 + time.Minute*0 + time.Second*0)
|
||||
// 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 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) ORDER BY created_at ASC;", s.Id, since.Format(time.RFC3339))
|
||||
}
|
||||
|
||||
sql := GroupDataBy("hits", s.Id, since, "minute")
|
||||
|
||||
dated, err := DbSession.Query(db.Raw(sql))
|
||||
if err != nil {
|
||||
utils.Log(2, err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/hunterlong/statup/core"
|
||||
"github.com/hunterlong/statup/types"
|
||||
|
@ -22,14 +23,14 @@ var (
|
|||
func RunHTTPServer() {
|
||||
utils.Log(1, "Statup HTTP Server running on http://localhost:8080")
|
||||
r := Router()
|
||||
//for _, p := range allPlugins {
|
||||
// info := p.GetInfo()
|
||||
// for _, route := range p.Routes() {
|
||||
// path := fmt.Sprintf("/plugins/%v/%v", info.Name, route.URL)
|
||||
// r.Handle(path, http.HandlerFunc(route.Handler)).Methods(route.Method)
|
||||
// fmt.Printf("Added Route %v for plugin %v\n", path, info.Name)
|
||||
// }
|
||||
//}
|
||||
for _, p := range core.CoreApp.AllPlugins {
|
||||
info := p.GetInfo()
|
||||
for _, route := range p.Routes() {
|
||||
path := fmt.Sprintf("/plugins/%v/%v", info.Name, route.URL)
|
||||
r.Handle(path, http.HandlerFunc(route.Handler)).Methods(route.Method)
|
||||
fmt.Printf("Added Route %v for plugin %v\n", path, info.Name)
|
||||
}
|
||||
}
|
||||
srv := &http.Server{
|
||||
Addr: "0.0.0.0:8080",
|
||||
WriteTimeout: time.Second * 15,
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/hunterlong/statup/core"
|
||||
"github.com/tdewolff/minify"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
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("/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")
|
||||
|
@ -49,7 +49,12 @@ func Router() *mux.Router {
|
|||
r.Handle("/api/users/{id}", http.HandlerFunc(ApiUserHandler))
|
||||
r.Handle("/metrics", http.HandlerFunc(PrometheusHandler))
|
||||
r.NotFoundHandler = http.HandlerFunc(Error404Handler)
|
||||
Store = sessions.NewCookieStore([]byte("secretinfo"))
|
||||
if core.CoreApp != nil {
|
||||
cookie := fmt.Sprintf("%v_%v", core.CoreApp.ApiSecret, time.Now().Nanosecond())
|
||||
Store = sessions.NewCookieStore([]byte(cookie))
|
||||
} else {
|
||||
Store = sessions.NewCookieStore([]byte("secretinfo"))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
|
||||
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")
|
||||
w.Header().Set("Content-Type", "text/javascript")
|
||||
w.Header().Set("Cache-Control", "max-age=60")
|
||||
ExecuteJSResponse(w, r, "charts.js", services)
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ func CreateServiceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
fmt.Println("service adding")
|
||||
r.ParseForm()
|
||||
name := r.PostForm.Get("name")
|
||||
domain := r.PostForm.Get("domain")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/hunterlong/statup/core"
|
||||
"github.com/hunterlong/statup/types"
|
||||
"github.com/hunterlong/statup/utils"
|
||||
|
@ -106,7 +107,7 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
admin := &core.User{
|
||||
Username: config.Username,
|
||||
Password: config.Password,
|
||||
Email: email,
|
||||
Email: config.Email,
|
||||
Admin: true,
|
||||
}
|
||||
admin.Create()
|
||||
|
@ -116,6 +117,7 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
core.InitApp()
|
||||
Store = sessions.NewCookieStore([]byte(core.CoreApp.ApiSecret))
|
||||
time.Sleep(2 * time.Second)
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
|
15
main_test.go
15
main_test.go
|
@ -13,7 +13,6 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -28,6 +27,7 @@ func RunInit(t *testing.T) {
|
|||
os.Remove("./index.html")
|
||||
route = handlers.Router()
|
||||
LoadDotEnvs()
|
||||
core.CoreApp = core.NewCore()
|
||||
}
|
||||
|
||||
var forceSequential chan bool = make(chan bool, 1)
|
||||
|
@ -49,6 +49,9 @@ func TestRunAll(t *testing.T) {
|
|||
t.Run(dbt+" Sample Data", func(t *testing.T) {
|
||||
RunInsertMysqlSample(t)
|
||||
})
|
||||
t.Run(dbt+" Load Configs", func(t *testing.T) {
|
||||
RunLoadConfig(t)
|
||||
})
|
||||
t.Run(dbt+" Select Core", func(t *testing.T) {
|
||||
RunSelectCoreMYQL(t, dbt)
|
||||
})
|
||||
|
@ -213,11 +216,20 @@ func RunInsertMysqlSample(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func RunLoadConfig(t *testing.T) {
|
||||
var err error
|
||||
core.Configs, err = core.LoadConfig()
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, core.Configs)
|
||||
}
|
||||
|
||||
func RunSelectCoreMYQL(t *testing.T, db string) {
|
||||
var err error
|
||||
core.CoreApp, err = core.SelectCore()
|
||||
assert.Nil(t, err)
|
||||
t.Log(core.CoreApp)
|
||||
assert.Equal(t, "Testing "+db, core.CoreApp.Name)
|
||||
assert.Equal(t, db, core.CoreApp.DbConnection)
|
||||
assert.NotEmpty(t, core.CoreApp.ApiKey)
|
||||
assert.NotEmpty(t, core.CoreApp.ApiSecret)
|
||||
assert.Equal(t, VERSION, core.CoreApp.Version)
|
||||
|
@ -363,7 +375,6 @@ func RunCreateService_Hits(t *testing.T) {
|
|||
service := s.Check()
|
||||
assert.NotNil(t, service)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"upper.io/db.v3/lib/sqlbuilder"
|
||||
)
|
||||
|
@ -26,10 +25,6 @@ func SetDatabase(database sqlbuilder.Database) {
|
|||
DB = database
|
||||
}
|
||||
|
||||
func Throw(err error) {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
type PluginInfo struct {
|
||||
Info Info
|
||||
PluginActions
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[{
|
||||
"name": "slack",
|
||||
"description": "slack bot that send a message in a channel when server is down.",
|
||||
"repo": "https://github.com/hunterlong/statup_slack",
|
||||
"name": "Example Plugin",
|
||||
"description": "An example of a plugin for Statup",
|
||||
"repo": "https://github.com/hunterlong/statup_plugin",
|
||||
"author": "Hunter Long",
|
||||
"namespace": "slack"
|
||||
"namespace": "example"
|
||||
}]
|
|
@ -1,146 +1,6 @@
|
|||
{{ 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
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
{{ range . }}{{ if .AvgTime }}var ctx_{{.Id}}=document.getElementById("service_{{.Id}}").getContext('2d');var chartdata=new Chart(ctx_{{.Id}},{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:!1,scaleShowValues:!0,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(lowestnum>data.y){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(50>=hxH){hxH=50}
|
||||
if(hxL>=820){hxL=820}else if(70>=hxL){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:!1},tooltips:{"enabled":!1},scales:{yAxes:[{display:!1,ticks:{fontSize:20,display:!1,beginAtZero:!1},gridLines:{display:!1}}],xAxes:[{type:'time',distribution:'series',autoSkip:!1,gridLines:{display:!1},ticks:{stepSize:1,min:0,fontColor:"white",fontSize:20,display:!1,}}]},elements:{point:{radius:0}}}})
|
||||
{{ end }}
|
||||
{{ end }}
|
|
@ -45,9 +45,7 @@
|
|||
<div class="mt-4" id="service_id_{{.Id}}">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
|
||||
<div class="col-12">
|
||||
|
||||
<h4 class="mt-3"><a href="/service/{{.Id}}"{{if not .Online}} class="text-danger"{{end}}>{{ .Name }}</a>
|
||||
{{if .Online}}
|
||||
<span class="badge bg-success float-right">ONLINE</span>
|
||||
|
|
Loading…
Reference in New Issue