mirror of https://github.com/statping/statping
parent
0a1b63fa76
commit
8dbf573667
3
Makefile
3
Makefile
|
@ -172,6 +172,9 @@ docker-push-latest:
|
|||
docker push hunterlong/statup:latest
|
||||
docker push hunterlong/statup:latest-v$(VERSION)
|
||||
|
||||
docker-run-mssql:
|
||||
docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=PaSsW0rD123' -p 1433:1433 -d microsoft/mssql-server-linux
|
||||
|
||||
# create Postgres, and MySQL instance using Docker (used for testing)
|
||||
databases:
|
||||
docker run --name statup_postgres -p 5432:5432 -e POSTGRES_PASSWORD=password123 -e POSTGRES_USER=root -e POSTGRES_DB=root -d postgres
|
||||
|
|
|
@ -52,7 +52,13 @@ func Clean() {
|
|||
utils.DeleteDirectory(dir + "/logs")
|
||||
}
|
||||
|
||||
func RunInit(t *testing.T) {
|
||||
func RunInit(db string, t *testing.T) {
|
||||
if db == "mssql" {
|
||||
os.Setenv("DB_DATABASE", "tempdb")
|
||||
os.Setenv("DB_PASS", "PaSsW0rD123")
|
||||
os.Setenv("DB_PORT", "1433")
|
||||
os.Setenv("DB_USER", "sa")
|
||||
}
|
||||
source.Assets()
|
||||
Clean()
|
||||
route = handlers.Router()
|
||||
|
@ -69,7 +75,7 @@ func TestRunAll(t *testing.T) {
|
|||
|
||||
for _, dbt := range databases {
|
||||
t.Run(dbt+" init", func(t *testing.T) {
|
||||
RunInit(t)
|
||||
RunInit(dbt, t)
|
||||
})
|
||||
t.Run(dbt+" Save Config", func(t *testing.T) {
|
||||
RunSaveConfig(t, dbt)
|
||||
|
@ -206,6 +212,11 @@ func TestRunAll(t *testing.T) {
|
|||
t.Run(dbt+" Cleanup", func(t *testing.T) {
|
||||
core.Configs.Close()
|
||||
core.DbSession = nil
|
||||
if dbt == "mssql" {
|
||||
os.Setenv("DB_DATABASE", "root")
|
||||
os.Setenv("DB_PASS", "password123")
|
||||
os.Setenv("DB_PORT", "1433")
|
||||
}
|
||||
//Clean()
|
||||
})
|
||||
|
||||
|
@ -220,6 +231,8 @@ func RunSaveConfig(t *testing.T, db string) {
|
|||
port := 5432
|
||||
if db == "mysql" {
|
||||
port = 3306
|
||||
} else if db == "mssql" {
|
||||
port = 1433
|
||||
}
|
||||
core.Configs = &core.DbConfig{DbConfig: &types.DbConfig{
|
||||
DbConn: db,
|
||||
|
|
|
@ -163,12 +163,7 @@ func (s *Service) SmallText() string {
|
|||
}
|
||||
|
||||
func (s *Service) DowntimeText() string {
|
||||
lastFailure := s.lastFailure()
|
||||
if lastFailure == nil {
|
||||
return ""
|
||||
}
|
||||
got, _ := timeago.TimeAgoWithTime(time.Now().UTC().Add(s.Downtime()), time.Now().UTC())
|
||||
return fmt.Sprintf("Reported offline %v, %v", got, lastFailure.ParseError())
|
||||
return fmt.Sprintf("%v has been offline for %v", s.Name, utils.DurationReadable(s.Downtime()))
|
||||
}
|
||||
|
||||
// GroupDataBy returns a SQL query as a string to group a column by a time
|
||||
|
@ -188,13 +183,13 @@ func GroupDataBy(column string, id int64, start, end time.Time, increment string
|
|||
// Downtime returns the amount of time of a offline service
|
||||
func (s *Service) Downtime() time.Duration {
|
||||
hits, _ := s.Hits()
|
||||
if len(hits) == 0 {
|
||||
return time.Duration(0)
|
||||
}
|
||||
fails := s.LimitedFailures()
|
||||
if len(fails) == 0 {
|
||||
return time.Duration(0)
|
||||
}
|
||||
if len(hits) == 0 {
|
||||
return time.Now().UTC().Sub(fails[len(fails)-1].CreatedAt.UTC())
|
||||
}
|
||||
since := fails[0].CreatedAt.UTC().Sub(hits[0].CreatedAt.UTC())
|
||||
return since
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
postgres:
|
||||
container_name: postgres
|
||||
image: postgres
|
||||
restart: always
|
||||
ports:
|
||||
- 5432:5432
|
||||
environment:
|
||||
POSTGRES_PASSWORD: password123
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_DB: root
|
||||
|
||||
mysql:
|
||||
container_name: mysql
|
||||
image: mysql:5.6
|
||||
restart: always
|
||||
ports:
|
||||
- 3306:3306
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: password123
|
||||
MYSQL_DATABASE: root
|
||||
MYSQL_USER: root
|
||||
MYSQL_PASSWORD: password123
|
||||
|
||||
mssql:
|
||||
container_name: mssql
|
||||
image: microsoft/mssql-server-linux
|
||||
restart: always
|
||||
ports:
|
||||
- 1433:1433
|
||||
environment:
|
||||
SA_PASSWORD: PaSsW0rD123
|
||||
ACCEPT_EULA: "Y"
|
|
@ -23,7 +23,6 @@ import (
|
|||
"github.com/hunterlong/statup/utils"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ApiResponse struct {
|
||||
|
@ -94,38 +93,6 @@ func apiServiceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
json.NewEncoder(w).Encode(service)
|
||||
}
|
||||
|
||||
func apiServiceDataHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !isAPIAuthorized(r) {
|
||||
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
vars := mux.Vars(r)
|
||||
fields := parseGet(r)
|
||||
|
||||
startField := utils.StringInt(fields.Get("start"))
|
||||
endField := utils.StringInt(fields.Get("end"))
|
||||
var start time.Time
|
||||
var end time.Time
|
||||
if startField == 0 {
|
||||
start = time.Now().Add(-24 * time.Hour).UTC()
|
||||
} else {
|
||||
start = time.Unix(startField, 0)
|
||||
}
|
||||
if endField == 0 {
|
||||
end = time.Now().UTC()
|
||||
} else {
|
||||
end = time.Unix(endField, 0)
|
||||
}
|
||||
service := core.SelectService(utils.StringInt(vars["id"]))
|
||||
if service == nil {
|
||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(core.GraphDataRaw(service, start, end).Array)
|
||||
}
|
||||
|
||||
func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !isAPIAuthorized(r) {
|
||||
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
|
|
|
@ -121,16 +121,6 @@ func TestApiServiceHandler(t *testing.T) {
|
|||
assert.Equal(t, "https://google.com", obj.Domain)
|
||||
}
|
||||
|
||||
func TestApiServiceDataHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "GET", "/api/services/1/data", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj []*core.DateScan
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, 60, len(obj))
|
||||
}
|
||||
|
||||
func TestApiCreateServiceHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "POST", "/api/services", strings.NewReader(NEW_HTTP_SERVICE))
|
||||
assert.Nil(t, err)
|
||||
|
|
|
@ -84,7 +84,6 @@ func Router() *mux.Router {
|
|||
r.Handle("/api/services", http.HandlerFunc(apiAllServicesHandler)).Methods("GET")
|
||||
r.Handle("/api/services", http.HandlerFunc(apiCreateServiceHandler)).Methods("POST")
|
||||
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceHandler)).Methods("GET")
|
||||
r.Handle("/api/services/{id}/data", http.HandlerFunc(apiServiceDataHandler)).Methods("GET")
|
||||
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceUpdateHandler)).Methods("POST")
|
||||
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceDeleteHandler)).Methods("DELETE")
|
||||
|
||||
|
|
|
@ -190,3 +190,14 @@ func copyAndCapture(w io.Writer, r io.Reader) ([]byte, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func DurationReadable(d time.Duration) string {
|
||||
if d.Hours() >= 1 {
|
||||
return fmt.Sprintf("%0.0f hours and %0.0f minutes", d.Hours(), d.Minutes())
|
||||
} else if d.Minutes() >= 1 {
|
||||
return fmt.Sprintf("%0.0f minutes", d.Minutes())
|
||||
} else if d.Seconds() >= 1 {
|
||||
return fmt.Sprintf("%0.0f seconds", d.Seconds())
|
||||
}
|
||||
return d.String()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue