mirror of https://github.com/statping/statping
				
				
				
			
							parent
							
								
									87f493bf4e
								
							
						
					
					
						commit
						91daa01825
					
				|  | @ -18,7 +18,7 @@ services: | |||
| 
 | ||||
| env: | ||||
|   global: | ||||
|      - VERSION=0.28.8 | ||||
|      - VERSION=0.28.9 | ||||
|      - DB_HOST=localhost | ||||
|      - DB_USER=travis | ||||
|      - DB_PASS= | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| FROM alpine:latest | ||||
| 
 | ||||
| ENV VERSION=v0.28.8 | ||||
| ENV VERSION=v0.28.9 | ||||
| 
 | ||||
| RUN apk --no-cache add libstdc++ ca-certificates | ||||
| RUN wget -q https://github.com/hunterlong/statup/releases/download/$VERSION/statup-linux-alpine.tar.gz && \ | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| </p> | ||||
| <p align="center"> | ||||
|     <b>Statup - Web and App Status Monitoring for Any Type of Project</b><br> | ||||
| <a href="https://github.com/hunterlong/statup/wiki">View Wiki</a> | <a href="https://demo.statup.io">Demo</a> <br> <a href="https://github.com/hunterlong/statup/wiki/Docker">Docker</a> | <a href="https://github.com/hunterlong/statup/wiki/AWS-EC2">EC2</a> | <a href="https://github.com/hunterlong/statup/wiki/Heroku">Heroku</a> | <a href="https://github.com/hunterlong/statup/wiki/Mac">Mac</a> | <a href="https://github.com/hunterlong/statup/wiki/Linux">Linux</a> | <a href="https://github.com/hunterlong/statup/wiki/Windows">Windows</a><br> | ||||
| <a href="https://github.com/hunterlong/statup/wiki">View Wiki</a> | <a href="https://demo.statup.io">Demo</a> <br> <a href="https://github.com/hunterlong/statup/wiki/Docker">Docker</a> | <a href="https://github.com/hunterlong/statup/wiki/AWS-EC2">EC2</a> | <a href="https://github.com/hunterlong/statup/wiki/Heroku">Heroku</a> | <a href="https://github.com/hunterlong/statup/wiki/Mac">Mac</a> | <a href="https://github.com/hunterlong/statup/wiki/Linux">Linux</a> | <a href="https://github.com/hunterlong/statup/wiki/Windows">Windows</a> | <a href="https://github.com/hunterlong/statup/wiki/Statup-Plugins">Plugins</a> | ||||
| </p> | ||||
| 
 | ||||
| # Statup - Status Page & Monitoring Server | ||||
|  |  | |||
							
								
								
									
										27
									
								
								core/core.go
								
								
								
								
							
							
						
						
									
										27
									
								
								core/core.go
								
								
								
								
							|  | @ -10,19 +10,19 @@ type PluginJSON types.PluginJSON | |||
| type PluginRepos types.PluginRepos | ||||
| 
 | ||||
| type Core struct { | ||||
| 	Name        string     `db:"name" json:"name"` | ||||
| 	Description string     `db:"description" json:"name"` | ||||
| 	Config      string     `db:"config" json:"-"` | ||||
| 	ApiKey      string     `db:"api_key" json:"-"` | ||||
| 	ApiSecret   string     `db:"api_secret" json:"-"` | ||||
| 	Style       string     `db:"style" json:"-"` | ||||
| 	Footer      string     `db:"footer" json:"-"` | ||||
| 	Domain      string     `db:"domain" json:"domain,omitempty"` | ||||
| 	Version     string     `db:"version" json:"version,omitempty"` | ||||
| 	Services    []*Service `json:"services,omitempty"` | ||||
| 	Plugins     []plugin.Info | ||||
| 	Repos       []PluginJSON | ||||
| 	//PluginFields   []PluginSelect
 | ||||
| 	Name           string     `db:"name" json:"name"` | ||||
| 	Description    string     `db:"description" json:"name"` | ||||
| 	Config         string     `db:"config" json:"-"` | ||||
| 	ApiKey         string     `db:"api_key" json:"-"` | ||||
| 	ApiSecret      string     `db:"api_secret" json:"-"` | ||||
| 	Style          string     `db:"style" json:"-"` | ||||
| 	Footer         string     `db:"footer" json:"-"` | ||||
| 	Domain         string     `db:"domain" json:"domain,omitempty"` | ||||
| 	Version        string     `db:"version" json:"version,omitempty"` | ||||
| 	Services       []*Service `json:"services,omitempty"` | ||||
| 	Plugins        []plugin.Info | ||||
| 	Repos          []PluginJSON | ||||
| 	AllPlugins     []plugin.PluginActions | ||||
| 	Communications []*types.Communication | ||||
| 	OfflineAssets  bool | ||||
| } | ||||
|  | @ -37,7 +37,6 @@ var ( | |||
| 	TmplBox     *rice.Box | ||||
| 	EmailBox    *rice.Box | ||||
| 	SetupMode   bool | ||||
| 	AllPlugins  []plugin.PluginActions | ||||
| 	UsingAssets bool | ||||
| ) | ||||
| 
 | ||||
|  |  | |||
|  | @ -39,11 +39,13 @@ func DbConnection(dbType string) error { | |||
| 		if Configs.Port == "" { | ||||
| 			Configs.Port = "3306" | ||||
| 		} | ||||
| 
 | ||||
| 		mysqlSettings = mysql.ConnectionURL{ | ||||
| 			Database: Configs.Database, | ||||
| 			Host:     Configs.Host, | ||||
| 			User:     Configs.User, | ||||
| 			Password: Configs.Password, | ||||
| 			Options:  map[string]string{"parseTime": "true", "charset": "utf8"}, | ||||
| 		} | ||||
| 		DbSession, err = mysql.Open(mysqlSettings) | ||||
| 		if err != nil { | ||||
|  | @ -67,7 +69,6 @@ func DbConnection(dbType string) error { | |||
| 	} | ||||
| 	//dbSession.SetLogging(true)
 | ||||
| 	dbServer = dbType | ||||
| 	OnLoad(DbSession) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,19 +10,19 @@ import ( | |||
| ) | ||||
| 
 | ||||
| func OnLoad(db sqlbuilder.Database) { | ||||
| 	for _, p := range AllPlugins { | ||||
| 	for _, p := range CoreApp.AllPlugins { | ||||
| 		p.OnLoad(db) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func OnSuccess(s *Service) { | ||||
| 	for _, p := range AllPlugins { | ||||
| 	for _, p := range CoreApp.AllPlugins { | ||||
| 		p.OnSuccess(structs.Map(s)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func OnFailure(s *Service, f FailureData) { | ||||
| 	for _, p := range AllPlugins { | ||||
| 	for _, p := range CoreApp.AllPlugins { | ||||
| 		p.OnFailure(structs.Map(s)) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -61,37 +61,37 @@ func onFailureEmail(s *Service, f FailureData) { | |||
| } | ||||
| 
 | ||||
| func OnSettingsSaved(c *Core) { | ||||
| 	for _, p := range AllPlugins { | ||||
| 	for _, p := range CoreApp.AllPlugins { | ||||
| 		p.OnSettingsSaved(structs.Map(c)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func OnNewUser(u *User) { | ||||
| 	for _, p := range AllPlugins { | ||||
| 	for _, p := range CoreApp.AllPlugins { | ||||
| 		p.OnNewUser(structs.Map(u)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func OnNewService(s *Service) { | ||||
| 	for _, p := range AllPlugins { | ||||
| 	for _, p := range CoreApp.AllPlugins { | ||||
| 		p.OnNewService(structs.Map(s)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func OnDeletedService(s *Service) { | ||||
| 	for _, p := range AllPlugins { | ||||
| 	for _, p := range CoreApp.AllPlugins { | ||||
| 		p.OnDeletedService(structs.Map(s)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func OnUpdateService(s *Service) { | ||||
| 	for _, p := range AllPlugins { | ||||
| 	for _, p := range CoreApp.AllPlugins { | ||||
| 		p.OnUpdatedService(structs.Map(s)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func SelectPlugin(name string) plugin.PluginActions { | ||||
| 	for _, p := range AllPlugins { | ||||
| 	for _, p := range CoreApp.AllPlugins { | ||||
| 		if p.GetInfo().Name == name { | ||||
| 			return p | ||||
| 		} | ||||
|  |  | |||
|  | @ -17,6 +17,9 @@ func (s *Service) CreateFailure(data FailureData) (int64, error) { | |||
| 	s.Failures = append(s.Failures, fail) | ||||
| 	col := DbSession.Collection("failures") | ||||
| 	uuid, err := col.Insert(fail) | ||||
| 	if err != nil { | ||||
| 		utils.Log(3, err) | ||||
| 	} | ||||
| 	if uuid == nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|  | @ -26,7 +29,10 @@ func (s *Service) CreateFailure(data FailureData) (int64, error) { | |||
| func (s *Service) SelectAllFailures() []*Failure { | ||||
| 	var fails []*Failure | ||||
| 	col := DbSession.Collection("failures").Find("service", s.Id).OrderBy("-id") | ||||
| 	col.All(&fails) | ||||
| 	err := col.All(&fails) | ||||
| 	if err != nil { | ||||
| 		utils.Log(3, fmt.Sprintf("Issue getting failures for service %v, %v", s.Name, err)) | ||||
| 	} | ||||
| 	return fails | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -125,28 +125,33 @@ func (s *Service) SmallText() string { | |||
| } | ||||
| 
 | ||||
| func (s *Service) GraphData() string { | ||||
| 	var d []DateScan | ||||
| 	var d []*DateScan | ||||
| 	increment := "minute" | ||||
| 	since := time.Now().Add(time.Hour*-12 + time.Minute*0 + time.Second*0) | ||||
| 
 | ||||
| 	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(created_at), ' ', %v(created_at)) AS created_at, AVG(latency)*1000 AS value FROM hits WHERE service=%v AND DATE_FORMAT(created_at, 'Y-m-d H:i:s') BETWEEN DATE_FORMAT(NOW() - INTERVAL 12 HOUR, 'Y-m-d H:i:s') AND DATE_FORMAT(NOW(), 'Y-m-d H:i:s') GROUP BY created_at", increment, 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", s.Id) | ||||
| 	} else if dbServer == "sqlite" { | ||||
| 		sql = fmt.Sprintf("SELECT 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)) | ||||
| 		fmt.Println(sql) | ||||
| 		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)) | ||||
| 	} | ||||
| 
 | ||||
| 	dated, err := DbSession.Query(db.Raw(sql)) | ||||
| 	if err != nil { | ||||
| 		utils.Log(2, err) | ||||
| 		return "" | ||||
| 	} | ||||
| 	for dated.Next() { | ||||
| 		var gd DateScan | ||||
| 		gd := new(DateScan) | ||||
| 		var tt string | ||||
| 		var ff float64 | ||||
| 		dated.Scan(&gd.CreatedAt, &ff) | ||||
| 		err := dated.Scan(&tt, &ff) | ||||
| 		if err != nil { | ||||
| 			utils.Log(2, fmt.Sprintf("Issue loading chart data for service %v, %v", s.Name, err)) | ||||
| 		} | ||||
| 		gd.CreatedAt, err = time.Parse(time.RFC3339, tt) | ||||
| 		if err != nil { | ||||
| 			utils.Log(2, fmt.Sprintf("Issue parsing time %v", err)) | ||||
| 		} | ||||
| 		gd.Value = int64(ff) | ||||
| 		d = append(d, gd) | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										23
									
								
								main.go
								
								
								
								
							
							
						
						
									
										23
									
								
								main.go
								
								
								
								
							|  | @ -82,11 +82,12 @@ func ForEachPlugin() { | |||
| } | ||||
| 
 | ||||
| func LoadPlugins() { | ||||
| 	utils.Log(1, fmt.Sprintf("Loading any available Plugins from /plugins directory")) | ||||
| 	if _, err := os.Stat("./plugins"); os.IsNotExist(err) { | ||||
| 		os.Mkdir("./plugins", os.ModePerm) | ||||
| 	} | ||||
| 
 | ||||
| 	ForEachPlugin() | ||||
| 	//ForEachPlugin()
 | ||||
| 
 | ||||
| 	files, err := ioutil.ReadDir("./plugins") | ||||
| 	if err != nil { | ||||
|  | @ -94,33 +95,39 @@ func LoadPlugins() { | |||
| 		return | ||||
| 	} | ||||
| 	for _, f := range files { | ||||
| 		utils.Log(1, fmt.Sprintf("Attempting to load plugin '%v'", f.Name())) | ||||
| 		ext := strings.Split(f.Name(), ".") | ||||
| 		if len(ext) != 2 { | ||||
| 			utils.Log(3, fmt.Sprintf("Plugin '%v' must end in .so extension", f.Name())) | ||||
| 			continue | ||||
| 		} | ||||
| 		if ext[1] != "so" { | ||||
| 			utils.Log(3, fmt.Sprintf("Plugin '%v' must end in .so extension", f.Name())) | ||||
| 			continue | ||||
| 		} | ||||
| 		plug, err := plg.Open("plugins/" + f.Name()) | ||||
| 		if err != nil { | ||||
| 			utils.Log(2, fmt.Sprintf("Plugin '%v' could not load correctly.\n", f.Name())) | ||||
| 			utils.Log(3, fmt.Sprintf("Plugin '%v' could not load correctly. %v", f.Name(), err)) | ||||
| 			continue | ||||
| 		} | ||||
| 		symPlugin, err := plug.Lookup("Plugin") | ||||
| 		if err != nil { | ||||
| 			utils.Log(3, fmt.Sprintf("Plugin '%v' could not load correctly. %v", f.Name(), err)) | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		var plugActions plugin.PluginActions | ||||
| 		plugActions, ok := symPlugin.(plugin.PluginActions) | ||||
| 		if !ok { | ||||
| 			utils.Log(2, fmt.Sprintf("Plugin '%v' could not load correctly, error: %v\n", f.Name(), "unexpected type from module symbol")) | ||||
| 			utils.Log(3, fmt.Sprintf("Plugin '%v' could not load correctly, error: %v", f.Name(), err)) | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		//allPlugins = append(allPlugins, plugActions)
 | ||||
| 		plugActions.OnLoad(core.DbSession) | ||||
| 
 | ||||
| 		core.CoreApp.Plugins = append(core.CoreApp.Plugins, plugActions.GetInfo()) | ||||
| 		core.CoreApp.AllPlugins = append(core.CoreApp.AllPlugins, plugActions) | ||||
| 	} | ||||
| 
 | ||||
| 	core.OnLoad(core.DbSession) | ||||
| 
 | ||||
| 	//utils.Log(1, fmt.Sprintf("Loaded %v Plugins\n", len(allPlugins)))
 | ||||
| 	ForEachPlugin() | ||||
| 	utils.Log(1, fmt.Sprintf("Loaded %v Plugins\n", len(core.CoreApp.Plugins))) | ||||
| } | ||||
|  |  | |||
							
								
								
									
										76
									
								
								main_test.go
								
								
								
								
							
							
						
						
									
										76
									
								
								main_test.go
								
								
								
								
							|  | @ -13,6 +13,7 @@ import ( | |||
| 	"os" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
|  | @ -24,19 +25,13 @@ func RunInit(t *testing.T) { | |||
| 	RenderBoxes() | ||||
| 	os.Remove("./statup.db") | ||||
| 	os.Remove("./config.yml") | ||||
| 	os.Remove("./index.html") | ||||
| 	route = handlers.Router() | ||||
| 	LoadDotEnvs() | ||||
| } | ||||
| 
 | ||||
| var forceSequential chan bool = make(chan bool, 1) | ||||
| 
 | ||||
| type databaseTest struct { | ||||
| 	in  string | ||||
| 	out string | ||||
| } | ||||
| 
 | ||||
| var dbTests []databaseTest | ||||
| 
 | ||||
| func TestRunAll(t *testing.T) { | ||||
| 
 | ||||
| 	databases := []string{"mysql", "sqlite", "postgres"} | ||||
|  | @ -63,9 +58,12 @@ func TestRunAll(t *testing.T) { | |||
| 		t.Run(dbt+" Select Comms", func(t *testing.T) { | ||||
| 			RunSelectAllMysqlCommunications(t) | ||||
| 		}) | ||||
| 		t.Run(dbt+" Create User", func(t *testing.T) { | ||||
| 		t.Run(dbt+" Create Users", func(t *testing.T) { | ||||
| 			RunUser_Create(t) | ||||
| 		}) | ||||
| 		t.Run(dbt+" Select Users", func(t *testing.T) { | ||||
| 			RunUser_SelectAll(t) | ||||
| 		}) | ||||
| 		t.Run(dbt+" Select Services", func(t *testing.T) { | ||||
| 			RunSelectAllServices(t) | ||||
| 		}) | ||||
|  | @ -87,7 +85,7 @@ func TestRunAll(t *testing.T) { | |||
| 		t.Run(dbt+" Chart Data", func(t *testing.T) { | ||||
| 			RunService_GraphData(t) | ||||
| 		}) | ||||
| 		t.Run(dbt+" Create Service", func(t *testing.T) { | ||||
| 		t.Run(dbt+" Create Failing Service", func(t *testing.T) { | ||||
| 			RunBadService_Create(t) | ||||
| 		}) | ||||
| 		t.Run(dbt+" Check Service", func(t *testing.T) { | ||||
|  | @ -96,9 +94,18 @@ func TestRunAll(t *testing.T) { | |||
| 		t.Run(dbt+" Select Hits", func(t *testing.T) { | ||||
| 			RunService_Hits(t) | ||||
| 		}) | ||||
| 		t.Run(dbt+" Select Failures", func(t *testing.T) { | ||||
| 			RunService_Failures(t) | ||||
| 		}) | ||||
| 		t.Run(dbt+" Select Limited Hits", func(t *testing.T) { | ||||
| 			RunService_LimitedHits(t) | ||||
| 		}) | ||||
| 		t.Run(dbt+" Delete Service", func(t *testing.T) { | ||||
| 			RunDeleteService(t) | ||||
| 		}) | ||||
| 		t.Run(dbt+" Delete User", func(t *testing.T) { | ||||
| 			RunUser_Delete(t) | ||||
| 		}) | ||||
| 		t.Run(dbt+" HTTP /", func(t *testing.T) { | ||||
| 			RunIndexHandler(t) | ||||
| 		}) | ||||
|  | @ -211,6 +218,8 @@ func RunSelectCoreMYQL(t *testing.T, db string) { | |||
| 	core.CoreApp, err = core.SelectCore() | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.Equal(t, "Testing "+db, core.CoreApp.Name) | ||||
| 	assert.NotEmpty(t, core.CoreApp.ApiKey) | ||||
| 	assert.NotEmpty(t, core.CoreApp.ApiSecret) | ||||
| 	assert.Equal(t, VERSION, core.CoreApp.Version) | ||||
| } | ||||
| 
 | ||||
|  | @ -228,6 +237,12 @@ func RunSelectAllMysqlCommunications(t *testing.T) { | |||
| 	assert.Equal(t, 2, len(comms)) | ||||
| } | ||||
| 
 | ||||
| func RunUser_SelectAll(t *testing.T) { | ||||
| 	users, err := core.SelectAllUsers() | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.Equal(t, 2, len(users)) | ||||
| } | ||||
| 
 | ||||
| func RunUser_Create(t *testing.T) { | ||||
| 	user := &core.User{ | ||||
| 		Username: "admin", | ||||
|  | @ -236,7 +251,24 @@ func RunUser_Create(t *testing.T) { | |||
| 	} | ||||
| 	id, err := user.Create() | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.NotZero(t, id) | ||||
| 	assert.Equal(t, int64(1), id) | ||||
| 	user2 := &core.User{ | ||||
| 		Username: "superadmin", | ||||
| 		Password: "admin", | ||||
| 		Email:    "info@adminer.com", | ||||
| 		Admin:    true, | ||||
| 	} | ||||
| 	id, err = user2.Create() | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.Equal(t, int64(2), id) | ||||
| } | ||||
| 
 | ||||
| func RunUser_Delete(t *testing.T) { | ||||
| 	user, err := core.SelectUser(2) | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.NotNil(t, user) | ||||
| 	err = user.Delete() | ||||
| 	assert.Nil(t, err) | ||||
| } | ||||
| 
 | ||||
| func RunSelectAllServices(t *testing.T) { | ||||
|  | @ -266,6 +298,7 @@ func RunService_Create(t *testing.T) { | |||
| 	id, err := service.Create() | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.Equal(t, int64(5), id) | ||||
| 	t.Log(service) | ||||
| } | ||||
| 
 | ||||
| func RunService_AvgTime(t *testing.T) { | ||||
|  | @ -286,6 +319,9 @@ func RunService_GraphData(t *testing.T) { | |||
| 	service := core.SelectService(1) | ||||
| 	assert.NotNil(t, service) | ||||
| 	data := service.GraphData() | ||||
| 	t.Log(data) | ||||
| 	assert.NotEqual(t, "null", data) | ||||
| 	assert.False(t, strings.Contains(data, "0001-01-01T00:00:00Z")) | ||||
| 	assert.NotEmpty(t, data) | ||||
| } | ||||
| 
 | ||||
|  | @ -310,15 +346,24 @@ func RunBadService_Check(t *testing.T) { | |||
| 	assert.Equal(t, "JSON API Tester", service.Name) | ||||
| } | ||||
| 
 | ||||
| func RunDeleteService(t *testing.T) { | ||||
| 	service := core.SelectService(4) | ||||
| 	assert.NotNil(t, service) | ||||
| 	assert.Equal(t, "JSON API Tester", service.Name) | ||||
| 	err := service.Delete() | ||||
| 	assert.Nil(t, err) | ||||
| } | ||||
| 
 | ||||
| func RunCreateService_Hits(t *testing.T) { | ||||
| 	services, err := core.SelectAllServices() | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.NotNil(t, services) | ||||
| 	for i := 0; i <= 2; i++ { | ||||
| 	for i := 0; i <= 10; i++ { | ||||
| 		for _, s := range services { | ||||
| 			service := s.Check() | ||||
| 			assert.NotNil(t, service) | ||||
| 		} | ||||
| 		time.Sleep(1 * time.Second) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -330,6 +375,13 @@ func RunService_Hits(t *testing.T) { | |||
| 	assert.NotZero(t, len(hits)) | ||||
| } | ||||
| 
 | ||||
| func RunService_Failures(t *testing.T) { | ||||
| 	t.SkipNow() | ||||
| 	service := core.SelectService(6) | ||||
| 	assert.NotNil(t, service) | ||||
| 	assert.NotEmpty(t, service.Failures) | ||||
| } | ||||
| 
 | ||||
| func RunService_LimitedHits(t *testing.T) { | ||||
| 	service := core.SelectService(1) | ||||
| 	assert.NotNil(t, service) | ||||
|  | @ -363,7 +415,7 @@ func RunPrometheusHandler(t *testing.T) { | |||
| 	rr := httptest.NewRecorder() | ||||
| 	route.ServeHTTP(rr, req) | ||||
| 	t.Log(rr.Body.String()) | ||||
| 	assert.True(t, strings.Contains(rr.Body.String(), "statup_total_services 6")) | ||||
| 	assert.True(t, strings.Contains(rr.Body.String(), "statup_total_services 5")) | ||||
| } | ||||
| 
 | ||||
| func RunFailingPrometheusHandler(t *testing.T) { | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ CREATE TABLE users ( | |||
|     api_key VARCHAR(50), | ||||
|     api_secret VARCHAR(50), | ||||
|     administrator BOOL NOT NULL DEFAULT '0', | ||||
|     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||||
|     created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | ||||
|     INDEX (id) | ||||
| ); | ||||
| CREATE TABLE services ( | ||||
|  | @ -32,34 +32,34 @@ CREATE TABLE services ( | |||
|     check_interval int(11), | ||||
|     post_data text, | ||||
|     order_id integer, | ||||
|     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||||
|     created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | ||||
|     INDEX (id) | ||||
| ); | ||||
| CREATE TABLE hits ( | ||||
|     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|     service INTEGER NOT NULL, | ||||
|     latency float, | ||||
|     created_at TIMESTAMP, | ||||
|     created_at DATETIME, | ||||
|     INDEX (id, service), | ||||
|     FOREIGN KEY (service) REFERENCES services(id) | ||||
|     FOREIGN KEY (service) REFERENCES services(id) ON DELETE CASCADE | ||||
| ); | ||||
| CREATE TABLE failures ( | ||||
|     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|     issue text, | ||||
|     method text, | ||||
|     service INTEGER NOT NULL, | ||||
|     created_at TIMESTAMP, | ||||
|     created_at DATETIME, | ||||
|     INDEX (id, service), | ||||
|     FOREIGN KEY (service) REFERENCES services(id) | ||||
|     FOREIGN KEY (service) REFERENCES services(id) ON DELETE CASCADE | ||||
| ); | ||||
| CREATE TABLE checkins ( | ||||
|     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|     service INTEGER NOT NULL, | ||||
|     check_interval integer, | ||||
|     api text, | ||||
|     created_at TIMESTAMP, | ||||
|     created_at DATETIME, | ||||
|     INDEX (id, service), | ||||
|     FOREIGN KEY (service) REFERENCES services(id) | ||||
|     FOREIGN KEY (service) REFERENCES services(id) ON DELETE CASCADE | ||||
| ); | ||||
| CREATE TABLE communication ( | ||||
|     id SERIAL PRIMARY KEY, | ||||
|  | @ -75,5 +75,5 @@ CREATE TABLE communication ( | |||
|     enabled BOOL NOT NULL DEFAULT '0', | ||||
|     removable BOOL NOT NULL DEFAULT '0', | ||||
|     limits integer, | ||||
|     created_at TIMESTAMP | ||||
|     created_at DATETIME | ||||
| ); | ||||
|  | @ -18,7 +18,7 @@ CREATE TABLE users ( | |||
|     api_key text, | ||||
|     api_secret text, | ||||
|     administrator bool, | ||||
|     created_at TIMESTAMP | ||||
|     created_at DATETIME | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE services ( | ||||
|  | @ -33,14 +33,14 @@ CREATE TABLE services ( | |||
|     check_interval integer, | ||||
|     post_data text, | ||||
|     order_id integer, | ||||
|     created_at TIMESTAMP | ||||
|     created_at DATETIME | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE hits ( | ||||
|     id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, | ||||
|     service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE, | ||||
|     latency float, | ||||
|     created_at TIMESTAMP | ||||
|     created_at DATETIME | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE failures ( | ||||
|  | @ -48,7 +48,7 @@ CREATE TABLE failures ( | |||
|     issue text, | ||||
|     method text, | ||||
|     service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE, | ||||
|     created_at TIMESTAMP | ||||
|     created_at DATETIME | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE checkins ( | ||||
|  | @ -56,7 +56,7 @@ CREATE TABLE checkins ( | |||
|     service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE, | ||||
|     check_interval integer, | ||||
|     api text, | ||||
|     created_at TIMESTAMP | ||||
|     created_at DATETIME | ||||
| ); | ||||
| 
 | ||||
| CREATE TABLE communication ( | ||||
|  | @ -73,7 +73,7 @@ CREATE TABLE communication ( | |||
|     enabled boolean, | ||||
|     removable boolean, | ||||
|     limits integer, | ||||
|     created_at TIMESTAMP | ||||
|     created_at DATETIME | ||||
| ); | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Hunter Long
						Hunter Long