mirror of https://github.com/statping/statping
commit
f695195b9e
|
@ -106,7 +106,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ env.VERSION }}
|
VERSION: ${{ env.VERSION }}
|
||||||
run: |
|
run: |
|
||||||
make build
|
make build certs
|
||||||
chmod +x statping
|
chmod +x statping
|
||||||
mv statping $(go env GOPATH)/bin/
|
mv statping $(go env GOPATH)/bin/
|
||||||
|
|
||||||
|
|
25
cmd/main.go
25
cmd/main.go
|
@ -23,9 +23,11 @@ var (
|
||||||
COMMIT string
|
COMMIT string
|
||||||
log = utils.Log.WithField("type", "cmd")
|
log = utils.Log.WithField("type", "cmd")
|
||||||
confgs *configs.DbConfig
|
confgs *configs.DbConfig
|
||||||
|
process chan struct{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
process = make(chan struct{})
|
||||||
core.New(VERSION)
|
core.New(VERSION)
|
||||||
rootCmd.AddCommand(versionCmd)
|
rootCmd.AddCommand(versionCmd)
|
||||||
rootCmd.AddCommand(assetsCmd)
|
rootCmd.AddCommand(assetsCmd)
|
||||||
|
@ -42,8 +44,8 @@ func init() {
|
||||||
// exit will return an error and return an exit code 1 due to this error
|
// exit will return an error and return an exit code 1 due to this error
|
||||||
func exit(err error) {
|
func exit(err error) {
|
||||||
utils.SentryErr(err)
|
utils.SentryErr(err)
|
||||||
Close()
|
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
|
close(process)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close will gracefully stop the database connection, and log file
|
// Close will gracefully stop the database connection, and log file
|
||||||
|
@ -55,14 +57,15 @@ func Close() {
|
||||||
|
|
||||||
// main will run the Statping application
|
// main will run the Statping application
|
||||||
func main() {
|
func main() {
|
||||||
Execute()
|
go Execute()
|
||||||
|
<-process
|
||||||
|
Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// main will run the Statping application
|
// main will run the Statping application
|
||||||
func start() {
|
func start() {
|
||||||
var err error
|
|
||||||
go sigterm()
|
go sigterm()
|
||||||
|
var err error
|
||||||
if err := source.Assets(); err != nil {
|
if err := source.Assets(); err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
@ -75,14 +78,10 @@ func start() {
|
||||||
|
|
||||||
log.Info(fmt.Sprintf("Starting Statping v%s", VERSION))
|
log.Info(fmt.Sprintf("Starting Statping v%s", VERSION))
|
||||||
|
|
||||||
//if err := updateDisplay(); err != nil {
|
|
||||||
// log.Warnln(err)
|
|
||||||
//}
|
|
||||||
|
|
||||||
confgs, err = configs.LoadConfigs(configFile)
|
confgs, err = configs.LoadConfigs(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Infoln("Starting in Setup Mode")
|
log.Infoln("Starting in Setup Mode")
|
||||||
if err := SetupMode(); err != nil {
|
if err = handlers.RunHTTPServer(); err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,16 +138,12 @@ func start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupMode() error {
|
|
||||||
return handlers.RunHTTPServer(ipAddress, port)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sigterm will attempt to close the database connections gracefully
|
// sigterm will attempt to close the database connections gracefully
|
||||||
func sigterm() {
|
func sigterm() {
|
||||||
sigs := make(chan os.Signal, 1)
|
sigs := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||||
<-sigs
|
<-sigs
|
||||||
Close()
|
close(process)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +155,7 @@ func mainProcess() error {
|
||||||
|
|
||||||
services.LoadServicesYaml()
|
services.LoadServicesYaml()
|
||||||
|
|
||||||
if err := handlers.RunHTTPServer(ipAddress, port); err != nil {
|
if err := handlers.RunHTTPServer(); err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
return errors.Wrap(err, "http server")
|
return errors.Wrap(err, "http server")
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
"@babel/plugin-syntax-dynamic-import": "~7.2",
|
"@babel/plugin-syntax-dynamic-import": "~7.2",
|
||||||
"@babel/plugin-syntax-import-meta": "~7.2",
|
"@babel/plugin-syntax-import-meta": "~7.2",
|
||||||
"@babel/polyfill": "~7.2",
|
"@babel/polyfill": "~7.2",
|
||||||
"@babel/preset-env": "^7.9.0",
|
"@babel/preset-env": "^7.9.5",
|
||||||
"@kazupon/vue-i18n-loader": "^0.5.0",
|
"@kazupon/vue-i18n-loader": "^0.5.0",
|
||||||
"@vue/babel-preset-app": "^4.1.2",
|
"@vue/babel-preset-app": "^4.1.2",
|
||||||
"@vue/cli-plugin-babel": "^4.1.0",
|
"@vue/cli-plugin-babel": "^4.1.0",
|
||||||
|
|
|
@ -3,11 +3,44 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>{{CoreApp.Name}}</title>
|
<title>{{CoreApp.Name}} - Service Monitoring</title>
|
||||||
|
<meta name="title" content="{{CoreApp.Name}} - Service Monitoring">
|
||||||
|
<meta name="description" content="{{CoreApp.Description}} {{CoreApp.Name}}">
|
||||||
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no">
|
||||||
<meta name="description" content="{{CoreApp.Description}}">
|
<meta name="description" content="{{CoreApp.Description}}">
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
|
<link rel="apple-touch-icon" sizes="57x57" href="https://assets.statping.com/favicon/apple-icon-57x57.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="https://assets.statping.com/favicon/apple-icon-60x60.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="72x72" href="https://assets.statping.com/favicon/apple-icon-72x72.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="76x76" href="https://assets.statping.com/favicon/apple-icon-76x76.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="114x114" href="https://assets.statping.com/favicon/apple-icon-114x114.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="120x120" href="https://assets.statping.com/favicon/apple-icon-120x120.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="144x144" href="https://assets.statping.com/favicon/apple-icon-144x144.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="152x152" href="https://assets.statping.com/favicon/apple-icon-152x152.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="https://assets.statping.com/favicon/apple-icon-180x180.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="192x192" href="https://assets.statping.com/favicon/android-icon-192x192.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="https://assets.statping.com/favicon/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="96x96" href="https://assets.statping.com/favicon/favicon-96x96.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="https://assets.statping.com/favicon/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="https://assets.statping.com/favicon/manifest.json">
|
||||||
|
<meta name="msapplication-TileColor" content="#ffffff">
|
||||||
|
<meta name="msapplication-TileImage" content="https://assets.statping.com/favicon/ms-icon-144x144.png">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
<link rel="icon" type="image/x-icon" href="https://assets.statping.com/favicon/favicon.ico" />
|
||||||
|
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:url" content="{{CoreApp.Domain}}">
|
||||||
|
<meta property="og:title" content="{{CoreApp.Name}} Service Monitoring">
|
||||||
|
<meta property="og:description" content="{{CoreApp.Description}} {{CoreApp.Name}}">
|
||||||
|
<meta property="og:image" content="https://assets.statping.com/statping_social.png">
|
||||||
|
|
||||||
|
<meta property="twitter:card" content="summary_large_image">
|
||||||
|
<meta property="twitter:url" content="{{CoreApp.Domain}}">
|
||||||
|
<meta property="twitter:title" content="{{CoreApp.Name}} Service Monitoring">
|
||||||
|
<meta property="twitter:description" content="{{CoreApp.Description}} {{CoreApp.Name}}">
|
||||||
|
<meta property="twitter:image" content="https://assets.statping.com/statping_social.png">
|
||||||
|
|
||||||
<base href="{{BasePath}}">
|
<base href="{{BasePath}}">
|
||||||
{{if USE_CDN}}
|
{{if USE_CDN}}
|
||||||
<link rel="stylesheet" href="https://assets.statping.com/vendor.css">
|
<link rel="stylesheet" href="https://assets.statping.com/vendor.css">
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -85,6 +85,9 @@ export default {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
service() {
|
service() {
|
||||||
return this.track_service
|
return this.track_service
|
||||||
|
@ -230,7 +233,7 @@ export default {
|
||||||
if (!this.timer_func) {
|
if (!this.timer_func) {
|
||||||
this.timer_func = setInterval(async () => {
|
this.timer_func = setInterval(async () => {
|
||||||
this.track_service = await Api.service(this.service.id)
|
this.track_service = await Api.service(this.service.id)
|
||||||
}, this.track_service.check_interval * 1000)
|
}, this.track_service.check_interval * 100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4220
frontend/yarn.lock
4220
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
|
@ -21,6 +21,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -28,15 +29,22 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
source.Assets()
|
|
||||||
utils.InitLogs()
|
utils.InitLogs()
|
||||||
|
source.Assets()
|
||||||
dir = utils.Directory
|
dir = utils.Directory
|
||||||
core.New("test")
|
core.New("test")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFailedHTTPServer(t *testing.T) {
|
func TestFailedHTTPServer(t *testing.T) {
|
||||||
err := RunHTTPServer("missinghost", 0)
|
var err error
|
||||||
assert.Error(t, err)
|
go func(err error) {
|
||||||
|
err = RunHTTPServer()
|
||||||
|
}(err)
|
||||||
|
go func() {
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
StopHTTPServer(nil)
|
||||||
|
}()
|
||||||
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetupRoutes(t *testing.T) {
|
func TestSetupRoutes(t *testing.T) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
|
@ -26,12 +25,23 @@ var (
|
||||||
usingSSL bool
|
usingSSL bool
|
||||||
mainTmpl = `{{define "main" }} {{ template "base" . }} {{ end }}`
|
mainTmpl = `{{define "main" }} {{ template "base" . }} {{ end }}`
|
||||||
templates = []string{"base.gohtml"}
|
templates = []string{"base.gohtml"}
|
||||||
|
httpError chan error
|
||||||
)
|
)
|
||||||
|
|
||||||
// RunHTTPServer will start a HTTP server on a specific IP and port
|
func StopHTTPServer(err error) {
|
||||||
func RunHTTPServer(ip string, port int) error {
|
log.Infoln("Stopping HTTP Server")
|
||||||
host := fmt.Sprintf("%v:%v", ip, port)
|
httpError <- err
|
||||||
|
close(httpError)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunHTTPServer will start a HTTP server on a specific IP and port
|
||||||
|
func RunHTTPServer() error {
|
||||||
|
if utils.Params.GetBool("DISABLE_HTTP") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ip := utils.Params.GetString("HOST")
|
||||||
|
host := fmt.Sprintf("%v:%v", ip, utils.Params.GetInt64("PORT"))
|
||||||
key := utils.FileExists(utils.Directory + "/server.key")
|
key := utils.FileExists(utils.Directory + "/server.key")
|
||||||
cert := utils.FileExists(utils.Directory + "/server.crt")
|
cert := utils.FileExists(utils.Directory + "/server.crt")
|
||||||
|
|
||||||
|
@ -47,37 +57,18 @@ func RunHTTPServer(ip string, port int) error {
|
||||||
resetCookies()
|
resetCookies()
|
||||||
|
|
||||||
if usingSSL {
|
if usingSSL {
|
||||||
cfg := &tls.Config{
|
go startSSLServer(ip)
|
||||||
MinVersion: tls.VersionTLS12,
|
|
||||||
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
|
|
||||||
PreferServerCipherSuites: true,
|
|
||||||
CipherSuites: []uint16{
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
srv := &http.Server{
|
|
||||||
Addr: fmt.Sprintf("%v:%v", ip, 443),
|
|
||||||
Handler: router,
|
|
||||||
TLSConfig: cfg,
|
|
||||||
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),
|
|
||||||
WriteTimeout: timeout,
|
|
||||||
ReadTimeout: timeout,
|
|
||||||
IdleTimeout: timeout,
|
|
||||||
}
|
|
||||||
return srv.ListenAndServeTLS(utils.Directory+"/server.crt", utils.Directory+"/server.key")
|
|
||||||
} else {
|
} else {
|
||||||
httpServer = &http.Server{
|
go startServer(host)
|
||||||
Addr: host,
|
}
|
||||||
WriteTimeout: timeout,
|
|
||||||
ReadTimeout: timeout,
|
for {
|
||||||
IdleTimeout: timeout,
|
select {
|
||||||
Handler: router,
|
case err := <-httpError:
|
||||||
|
return err
|
||||||
|
default:
|
||||||
|
|
||||||
}
|
}
|
||||||
httpServer.SetKeepAlivesEnabled(false)
|
|
||||||
return httpServer.ListenAndServe()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ func Router() *mux.Router {
|
||||||
r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
|
r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
|
||||||
r.HandleFunc("/debug/pprof/trace", pprof.Trace)
|
r.HandleFunc("/debug/pprof/trace", pprof.Trace)
|
||||||
http.ListenAndServe(":9090", r)
|
http.ListenAndServe(":9090", r)
|
||||||
|
// pprof -http=:9000 http://localhost:9090/debug/pprof/heap?debug=1
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"github.com/statping/statping/utils"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func startServer(host string) {
|
||||||
|
httpError = make(chan error)
|
||||||
|
httpServer = &http.Server{
|
||||||
|
Addr: host,
|
||||||
|
WriteTimeout: timeout,
|
||||||
|
ReadTimeout: timeout,
|
||||||
|
IdleTimeout: timeout,
|
||||||
|
Handler: router,
|
||||||
|
}
|
||||||
|
httpServer.SetKeepAlivesEnabled(false)
|
||||||
|
if err := httpServer.ListenAndServe(); err != nil {
|
||||||
|
httpError <- err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func startSSLServer(ip string) {
|
||||||
|
httpError = make(chan error)
|
||||||
|
cfg := &tls.Config{
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
|
||||||
|
PreferServerCipherSuites: true,
|
||||||
|
CipherSuites: []uint16{
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
srv := &http.Server{
|
||||||
|
Addr: fmt.Sprintf("%v:%v", ip, 443),
|
||||||
|
Handler: router,
|
||||||
|
TLSConfig: cfg,
|
||||||
|
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),
|
||||||
|
WriteTimeout: timeout,
|
||||||
|
ReadTimeout: timeout,
|
||||||
|
IdleTimeout: timeout,
|
||||||
|
}
|
||||||
|
if err := srv.ListenAndServeTLS(utils.Directory+"/server.crt", utils.Directory+"/server.key"); err != nil {
|
||||||
|
httpError <- err
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,8 +14,6 @@ import (
|
||||||
|
|
||||||
var _ notifier.Notifier = (*mobilePush)(nil)
|
var _ notifier.Notifier = (*mobilePush)(nil)
|
||||||
|
|
||||||
const mobileIdentifier = "com.statping"
|
|
||||||
|
|
||||||
type mobilePush struct {
|
type mobilePush struct {
|
||||||
*notifications.Notification
|
*notifications.Notification
|
||||||
}
|
}
|
||||||
|
@ -78,7 +76,6 @@ func (m *mobilePush) OnFailure(s *services.Service, f *failures.Failure) error {
|
||||||
msg := &pushArray{
|
msg := &pushArray{
|
||||||
Message: fmt.Sprintf("Your service '%v' is currently failing! Reason: %v", s.Name, f.Issue),
|
Message: fmt.Sprintf("Your service '%v' is currently failing! Reason: %v", s.Name, f.Issue),
|
||||||
Title: "Service Offline",
|
Title: "Service Offline",
|
||||||
Topic: mobileIdentifier,
|
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
return m.Send(msg)
|
return m.Send(msg)
|
||||||
|
@ -90,8 +87,8 @@ func (m *mobilePush) OnSuccess(s *services.Service) error {
|
||||||
msg := &pushArray{
|
msg := &pushArray{
|
||||||
Message: "Service is Online!",
|
Message: "Service is Online!",
|
||||||
Title: "Service Online",
|
Title: "Service Online",
|
||||||
Topic: mobileIdentifier,
|
|
||||||
Data: data,
|
Data: data,
|
||||||
|
Platform: 2,
|
||||||
}
|
}
|
||||||
return m.Send(msg)
|
return m.Send(msg)
|
||||||
}
|
}
|
||||||
|
@ -101,9 +98,8 @@ func (m *mobilePush) OnTest() (string, error) {
|
||||||
msg := &pushArray{
|
msg := &pushArray{
|
||||||
Message: "Testing the Mobile Notifier",
|
Message: "Testing the Mobile Notifier",
|
||||||
Title: "Testing Notifications",
|
Title: "Testing Notifications",
|
||||||
Topic: mobileIdentifier,
|
|
||||||
Tokens: []string{m.Var1},
|
Tokens: []string{m.Var1},
|
||||||
Platform: utils.ToInt(m.Var2),
|
Platform: 2,
|
||||||
}
|
}
|
||||||
body, err := pushRequest(msg)
|
body, err := pushRequest(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -134,9 +130,6 @@ func (m *mobilePush) Send(pushMessage *pushArray) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func pushRequest(msg *pushArray) ([]byte, error) {
|
func pushRequest(msg *pushArray) ([]byte, error) {
|
||||||
if msg.Platform == 1 {
|
|
||||||
msg.Title = ""
|
|
||||||
}
|
|
||||||
body, err := json.Marshal(&PushNotification{[]*pushArray{msg}})
|
body, err := json.Marshal(&PushNotification{[]*pushArray{msg}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -7,14 +7,12 @@ import (
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
MOBILE_ID string
|
mobileToken string
|
||||||
MOBILE_NUMBER string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMobileNotifier(t *testing.T) {
|
func TestMobileNotifier(t *testing.T) {
|
||||||
|
@ -22,25 +20,22 @@ func TestMobileNotifier(t *testing.T) {
|
||||||
err := utils.InitLogs()
|
err := utils.InitLogs()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
MOBILE_ID = utils.Params.GetString("MOBILE_ID")
|
mobileToken = utils.Params.GetString("MOBILE_TOKEN")
|
||||||
MOBILE_NUMBER = utils.Params.GetString("MOBILE_NUMBER")
|
Mobile.Var1 = mobileToken
|
||||||
Mobile.Var1 = MOBILE_ID
|
|
||||||
|
|
||||||
db, err := database.OpenTester()
|
db, err := database.OpenTester()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
|
||||||
Mobile.Var1 = MOBILE_ID
|
Mobile.Var1 = mobileToken
|
||||||
Mobile.Var2 = os.Getenv("MOBILE_NUMBER")
|
if mobileToken == "" {
|
||||||
if MOBILE_ID == "" {
|
|
||||||
t.Log("Mobile notifier testing skipped, missing MOBILE_ID environment variable")
|
t.Log("Mobile notifier testing skipped, missing MOBILE_ID environment variable")
|
||||||
t.SkipNow()
|
t.SkipNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Load Mobile", func(t *testing.T) {
|
t.Run("Load Mobile", func(t *testing.T) {
|
||||||
Mobile.Var1 = MOBILE_ID
|
Mobile.Var1 = mobileToken
|
||||||
Mobile.Var2 = MOBILE_NUMBER
|
|
||||||
Mobile.Delay = time.Duration(100 * time.Millisecond)
|
Mobile.Delay = time.Duration(100 * time.Millisecond)
|
||||||
Mobile.Limits = 10
|
Mobile.Limits = 10
|
||||||
Mobile.Enabled = null.NewNullBool(true)
|
Mobile.Enabled = null.NewNullBool(true)
|
||||||
|
@ -48,8 +43,7 @@ func TestMobileNotifier(t *testing.T) {
|
||||||
Add(Mobile)
|
Add(Mobile)
|
||||||
|
|
||||||
assert.Equal(t, "Hunter Long", Mobile.Author)
|
assert.Equal(t, "Hunter Long", Mobile.Author)
|
||||||
assert.Equal(t, MOBILE_ID, Mobile.Var1)
|
assert.Equal(t, mobileToken, Mobile.Var1)
|
||||||
assert.Equal(t, MOBILE_NUMBER, Mobile.Var2)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Mobile Notifier Tester", func(t *testing.T) {
|
t.Run("Mobile Notifier Tester", func(t *testing.T) {
|
||||||
|
@ -67,7 +61,6 @@ func TestMobileNotifier(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Mobile Test", func(t *testing.T) {
|
t.Run("Mobile Test", func(t *testing.T) {
|
||||||
t.SkipNow()
|
|
||||||
_, err := Mobile.OnTest()
|
_, err := Mobile.OnTest()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package notifiers
|
package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -70,7 +71,7 @@ func (t *twilio) sendMessage(message string) (string, error) {
|
||||||
v.Set("Body", message)
|
v.Set("Body", message)
|
||||||
rb := strings.NewReader(v.Encode())
|
rb := strings.NewReader(v.Encode())
|
||||||
|
|
||||||
authHeader := utils.Base64(fmt.Sprintf("%s:%s", t.ApiKey, t.ApiSecret))
|
authHeader := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", t.ApiKey, t.ApiSecret)))
|
||||||
|
|
||||||
contents, _, err := utils.HttpRequest(twilioUrl, "POST", "application/x-www-form-urlencoded", []string{"Authorization=Basic " + authHeader}, rb, 10*time.Second, true, nil)
|
contents, _, err := utils.HttpRequest(twilioUrl, "POST", "application/x-www-form-urlencoded", []string{"Authorization=Basic " + authHeader}, rb, 10*time.Second, true, nil)
|
||||||
success, _ := twilioSuccess(contents)
|
success, _ := twilioSuccess(contents)
|
||||||
|
|
|
@ -18,6 +18,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWebhookNotifier(t *testing.T) {
|
func TestWebhookNotifier(t *testing.T) {
|
||||||
|
t.SkipNow()
|
||||||
err := utils.InitLogs()
|
err := utils.InitLogs()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db, err := database.OpenTester()
|
db, err := database.OpenTester()
|
||||||
|
|
|
@ -22,6 +22,9 @@ var (
|
||||||
|
|
||||||
// Assets will load the Rice boxes containing the CSS, SCSS, JS, and HTML files.
|
// Assets will load the Rice boxes containing the CSS, SCSS, JS, and HTML files.
|
||||||
func Assets() error {
|
func Assets() error {
|
||||||
|
if utils.Params.GetBool("DISABLE_HTTP") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
var err error
|
var err error
|
||||||
TmplBox, err = rice.FindBox("dist")
|
TmplBox, err = rice.FindBox("dist")
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -38,6 +38,7 @@ func TestInit(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db, err := database.OpenTester()
|
db, err := database.OpenTester()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
SetDB(db)
|
||||||
db.AutoMigrate(&Checkin{}, &CheckinHit{}, &failures.Failure{})
|
db.AutoMigrate(&Checkin{}, &CheckinHit{}, &failures.Failure{})
|
||||||
db.Create(&testCheckin)
|
db.Create(&testCheckin)
|
||||||
for _, v := range testCheckinHits {
|
for _, v := range testCheckinHits {
|
||||||
|
@ -46,7 +47,6 @@ func TestInit(t *testing.T) {
|
||||||
assert.True(t, db.HasTable(&Checkin{}))
|
assert.True(t, db.HasTable(&Checkin{}))
|
||||||
assert.True(t, db.HasTable(&CheckinHit{}))
|
assert.True(t, db.HasTable(&CheckinHit{}))
|
||||||
assert.True(t, db.HasTable(&failures.Failure{}))
|
assert.True(t, db.HasTable(&failures.Failure{}))
|
||||||
SetDB(db)
|
|
||||||
|
|
||||||
t.Run("Test Checkin", func(t *testing.T) {
|
t.Run("Test Checkin", func(t *testing.T) {
|
||||||
item, err := Find(1)
|
item, err := Find(1)
|
||||||
|
@ -88,7 +88,6 @@ func TestInit(t *testing.T) {
|
||||||
err = i.Update()
|
err = i.Update()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, "Updated", i.Name)
|
assert.Equal(t, "Updated", i.Name)
|
||||||
i.Close()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Test Expected Time", func(t *testing.T) {
|
t.Run("Test Expected Time", func(t *testing.T) {
|
||||||
|
@ -115,6 +114,7 @@ func TestInit(t *testing.T) {
|
||||||
|
|
||||||
t.Run("Test Checkin", func(t *testing.T) {
|
t.Run("Test Checkin", func(t *testing.T) {
|
||||||
assert.Nil(t, db.Close())
|
assert.Nil(t, db.Close())
|
||||||
|
assert.Nil(t, dbHits.Close())
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ func (c *Checkin) Create() error {
|
||||||
q := db.Create(c)
|
q := db.Create(c)
|
||||||
|
|
||||||
c.Start()
|
c.Start()
|
||||||
go c.CheckinRoutine()
|
go c.checkinRoutine()
|
||||||
return q.Error()
|
return q.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,12 +30,14 @@ func (c *Checkin) Grace() time.Duration {
|
||||||
|
|
||||||
// Start will create a channel for the checkin checking go routine
|
// Start will create a channel for the checkin checking go routine
|
||||||
func (c *Checkin) Start() {
|
func (c *Checkin) Start() {
|
||||||
|
log.Infoln(fmt.Sprintf("Starting checkin routine: %s", c.Name))
|
||||||
c.Running = make(chan bool)
|
c.Running = make(chan bool)
|
||||||
|
go c.checkinRoutine()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close will stop the checkin routine
|
// Close will stop the checkin routine
|
||||||
func (c *Checkin) Close() {
|
func (c *Checkin) Close() {
|
||||||
if c.IsRunning() {
|
if c.Running != nil {
|
||||||
close(c.Running)
|
close(c.Running)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@ func (c *Checkin) RecheckCheckinFailure(guard chan struct{}) {
|
||||||
<-guard
|
<-guard
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine for checking if the last Checkin was within its interval
|
// checkinRoutine for checking if the last Checkin was within its interval
|
||||||
func (c *Checkin) CheckinRoutine() {
|
func (c *Checkin) checkinRoutine() {
|
||||||
lastHit := c.LastHit()
|
lastHit := c.LastHit()
|
||||||
if lastHit == nil {
|
if lastHit == nil {
|
||||||
return
|
return
|
||||||
|
@ -34,7 +34,7 @@ CheckinLoop:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-c.Running:
|
case <-c.Running:
|
||||||
log.Infoln(fmt.Sprintf("Stopping checkin routine: %v", c.Name))
|
log.Infoln(fmt.Sprintf("Stopping checkin routine: %s", c.Name))
|
||||||
c.Failing = false
|
c.Failing = false
|
||||||
break CheckinLoop
|
break CheckinLoop
|
||||||
case <-time.After(reCheck):
|
case <-time.After(reCheck):
|
||||||
|
@ -55,6 +55,5 @@ CheckinLoop:
|
||||||
}
|
}
|
||||||
reCheck = c.Period()
|
reCheck = c.Period()
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package checkins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/utils"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,10 +29,3 @@ type CheckinHit struct {
|
||||||
From string `gorm:"column:from_location" json:"from"`
|
From string `gorm:"column:from_location" json:"from"`
|
||||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Checkin) BeforeCreate() (err error) {
|
|
||||||
if c.ApiKey == "" {
|
|
||||||
c.ApiKey = utils.RandomString(7)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,8 +23,6 @@ import (
|
||||||
// Connect will attempt to connect to the sqlite, postgres, or mysql database
|
// Connect will attempt to connect to the sqlite, postgres, or mysql database
|
||||||
func Connect(configs *DbConfig, retry bool) error {
|
func Connect(configs *DbConfig, retry bool) error {
|
||||||
conn := configs.ConnectionString()
|
conn := configs.ConnectionString()
|
||||||
p := utils.Params
|
|
||||||
var err error
|
|
||||||
|
|
||||||
log.WithFields(utils.ToFields(configs, conn)).Debugln("attempting to connect to database")
|
log.WithFields(utils.ToFields(configs, conn)).Debugln("attempting to connect to database")
|
||||||
|
|
||||||
|
@ -40,20 +38,16 @@ func Connect(configs *DbConfig, retry bool) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apiSecret := p.GetString("API_SECRET")
|
configs.ApiSecret = utils.Params.GetString("API_SECRET")
|
||||||
configs.ApiSecret = apiSecret
|
|
||||||
|
|
||||||
log.WithFields(utils.ToFields(dbSession)).Debugln("connected to database")
|
log.WithFields(utils.ToFields(dbSession)).Debugln("connected to database")
|
||||||
|
|
||||||
maxOpenConn := p.GetInt("MAX_OPEN_CONN")
|
db := dbSession.DB()
|
||||||
maxIdleConn := p.GetInt("MAX_IDLE_CONN")
|
db.SetMaxOpenConns(utils.Params.GetInt("MAX_OPEN_CONN"))
|
||||||
maxLifeConn := p.GetDuration("MAX_LIFE_CONN")
|
db.SetMaxIdleConns(utils.Params.GetInt("MAX_IDLE_CONN"))
|
||||||
|
db.SetConnMaxLifetime(utils.Params.GetDuration("MAX_LIFE_CONN"))
|
||||||
|
|
||||||
dbSession.DB().SetMaxOpenConns(maxOpenConn)
|
if db.Ping() == nil {
|
||||||
dbSession.DB().SetMaxIdleConns(maxIdleConn)
|
|
||||||
dbSession.DB().SetConnMaxLifetime(maxLifeConn)
|
|
||||||
|
|
||||||
if dbSession.DB().Ping() == nil {
|
|
||||||
if utils.VerboseMode >= 4 {
|
if utils.VerboseMode >= 4 {
|
||||||
dbSession.LogMode(true).Debug().SetLogger(gorm.Logger{log})
|
dbSession.LogMode(true).Debug().SetLogger(gorm.Logger{log})
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,11 +66,6 @@ func (d *DbConfig) Update() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will initially create the config.yml file
|
|
||||||
func (d *DbConfig) Delete() error {
|
|
||||||
return os.Remove(d.filename)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DropDatabase will DROP each table Statping created
|
// DropDatabase will DROP each table Statping created
|
||||||
func (d *DbConfig) DropDatabase() error {
|
func (d *DbConfig) DropDatabase() error {
|
||||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||||
|
|
|
@ -70,7 +70,6 @@ func (d *DbConfig) BackupAssets() error {
|
||||||
//This function will NOT remove previous records, tables or columns from the database.
|
//This function will NOT remove previous records, tables or columns from the database.
|
||||||
//If this function has an issue, it will ROLLBACK to the previous state.
|
//If this function has an issue, it will ROLLBACK to the previous state.
|
||||||
func (d *DbConfig) MigrateDatabase() error {
|
func (d *DbConfig) MigrateDatabase() error {
|
||||||
|
|
||||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||||
|
|
||||||
log.Infoln("Migrating Database Tables...")
|
log.Infoln("Migrating Database Tables...")
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
package configs
|
|
||||||
|
|
||||||
//func preparePostgresDB(t *testing.T) (database.Database, error) {
|
|
||||||
// dbName := fmt.Sprintf("db_%d", time.Now().UnixNano())
|
|
||||||
// db, err := database.Openw("sqlite3", dbName)
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatalf("open connection: %s", err)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return db, db.Error()
|
|
||||||
//}
|
|
|
@ -22,14 +22,18 @@ func Samples() error {
|
||||||
Issue: "Server failure",
|
Issue: "Server failure",
|
||||||
CreatedAt: utils.Now().Add(-time.Duration(3*i) * 86400),
|
CreatedAt: utils.Now().Add(-time.Duration(3*i) * 86400),
|
||||||
}
|
}
|
||||||
f1.Create()
|
if err := f1.Create(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
f2 := &Failure{
|
f2 := &Failure{
|
||||||
Service: i,
|
Service: i,
|
||||||
Issue: "Server failure",
|
Issue: "Server failure",
|
||||||
CreatedAt: utils.Now().Add(-time.Duration(5*i) * 12400),
|
CreatedAt: utils.Now().Add(-time.Duration(5*i) * 12400),
|
||||||
}
|
}
|
||||||
f2.Create()
|
if err := f2.Create(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
log.Infoln(fmt.Sprintf("Adding %v Failure records to service", 400))
|
log.Infoln(fmt.Sprintf("Adding %v Failure records to service", 400))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package messages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/statping/statping/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BeforeCreate for Message will set CreatedAt to UTC
|
||||||
|
func (m *Message) BeforeCreate() (err error) {
|
||||||
|
if m.CreatedAt.IsZero() {
|
||||||
|
m.CreatedAt = utils.Now()
|
||||||
|
m.UpdatedAt = utils.Now()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -20,12 +20,3 @@ type Message struct {
|
||||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at" json:"created_at"`
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at" json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BeforeCreate for Message will set CreatedAt to UTC
|
|
||||||
func (m *Message) BeforeCreate() (err error) {
|
|
||||||
if m.CreatedAt.IsZero() {
|
|
||||||
m.CreatedAt = time.Now().UTC()
|
|
||||||
m.UpdatedAt = time.Now().UTC()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package notifications
|
||||||
|
|
||||||
|
import "github.com/statping/statping/utils"
|
||||||
|
|
||||||
|
// AfterFind for Notification will set the timezone
|
||||||
|
func (n *Notification) AfterFind() (err error) {
|
||||||
|
n.CreatedAt = utils.Now()
|
||||||
|
n.UpdatedAt = utils.Now()
|
||||||
|
return
|
||||||
|
}
|
|
@ -13,25 +13,6 @@ func (n *Notification) Name() string {
|
||||||
return newName
|
return newName
|
||||||
}
|
}
|
||||||
|
|
||||||
// AfterFind for Notification will set the timezone
|
|
||||||
func (n *Notification) AfterFind() (err error) {
|
|
||||||
n.CreatedAt = utils.Now()
|
|
||||||
n.UpdatedAt = utils.Now()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddQueue will add any type of interface (json, string, struct, etc) into the Notifiers queue
|
|
||||||
//func (n *Notification) AddQueue(uid string, msg interface{}) {
|
|
||||||
// data := &QueueData{uid, msg}
|
|
||||||
// n.Queue = append(n.Queue, data)
|
|
||||||
// log.WithFields(utils.ToFields(data, n)).Debug(fmt.Sprintf("Notifier '%v' added new item (%v) to the queue. (%v queued)", n.Method, uid, len(n.Queue)))
|
|
||||||
//}
|
|
||||||
|
|
||||||
// CanTest returns true if the notifier implements the OnTest interface
|
|
||||||
//func (n *Notification) CanTest() bool {
|
|
||||||
// return n.testable
|
|
||||||
//}
|
|
||||||
|
|
||||||
// LastSent returns a time.Duration of the last sent notification for the notifier
|
// LastSent returns a time.Duration of the last sent notification for the notifier
|
||||||
func (n *Notification) LastSent() time.Duration {
|
func (n *Notification) LastSent() time.Duration {
|
||||||
since := time.Since(n.lastSent)
|
since := time.Since(n.lastSent)
|
||||||
|
@ -43,11 +24,6 @@ func (n *Notification) CanSend() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
//fmt.Println("Last sent: ", n.lastSent.String())
|
|
||||||
//fmt.Println("Last count: ", n.lastSentCount)
|
|
||||||
//fmt.Println("Limits: ", n.Limits)
|
|
||||||
//fmt.Println("Last sent before now: ", n.lastSent.Add(60*time.Second).Before(utils.Now()))
|
|
||||||
|
|
||||||
// the last sent notification was past 1 minute (limit per minute)
|
// the last sent notification was past 1 minute (limit per minute)
|
||||||
if n.lastSent.Add(60 * time.Minute).Before(utils.Now()) {
|
if n.lastSent.Add(60 * time.Minute).Before(utils.Now()) {
|
||||||
if n.lastSentCount != 0 {
|
if n.lastSentCount != 0 {
|
||||||
|
@ -86,7 +62,7 @@ func (n *Notification) GetValue(dbField string) string {
|
||||||
case "api_secret":
|
case "api_secret":
|
||||||
return n.ApiSecret
|
return n.ApiSecret
|
||||||
case "limits":
|
case "limits":
|
||||||
return utils.ToString(int(n.Limits))
|
return utils.ToString(n.Limits)
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -116,34 +92,3 @@ func (n *Notification) IsRunning() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init accepts the Notifier interface to initialize the notifier
|
|
||||||
//func Init(n Notifier) (*Notification, error) {
|
|
||||||
// if Exists(n.Select().Method) {
|
|
||||||
// AllCommunications = append(AllCommunications, n)
|
|
||||||
// } else {
|
|
||||||
// _, err := insertDatabase(n)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorln(err)
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// AllCommunications = append(AllCommunications, n)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// notify, err := SelectNotification(n)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, errors.Wrap(err, "error selecting notification")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// notify.CreatedAt = time.Now().UTC()
|
|
||||||
// notify.UpdatedAt = time.Now().UTC()
|
|
||||||
// if notify.Delay.Seconds() == 0 {
|
|
||||||
// notify.Delay = 1 * time.Second
|
|
||||||
// }
|
|
||||||
// notify.testable = utils.IsType(n, new(Tester))
|
|
||||||
// notify.Form = n.Select().Form
|
|
||||||
//
|
|
||||||
// AllCommunications = append(AllCommunications, n)
|
|
||||||
//
|
|
||||||
// return nil, err
|
|
||||||
//}
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
func CheckinProcess(s *Service) {
|
func CheckinProcess(s *Service) {
|
||||||
for _, c := range s.Checkins() {
|
for _, c := range s.Checkins() {
|
||||||
c.Start()
|
c.Start()
|
||||||
go c.CheckinRoutine()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,17 @@ import (
|
||||||
var (
|
var (
|
||||||
db database.Database
|
db database.Database
|
||||||
log = utils.Log.WithField("type", "service")
|
log = utils.Log.WithField("type", "service")
|
||||||
|
allServices map[int64]*Service
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
allServices = make(map[int64]*Service)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Services() map[int64]*Service {
|
||||||
|
return allServices
|
||||||
|
}
|
||||||
|
|
||||||
func SetDB(database database.Database) {
|
func SetDB(database database.Database) {
|
||||||
db = database.Model(&Service{})
|
db = database.Model(&Service{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,7 @@ func (s *Service) AllFailures() failures.Failurer {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) FailuresSince(t time.Time) failures.Failurer {
|
func (s *Service) FailuresSince(t time.Time) failures.Failurer {
|
||||||
fails := failures.Since(t, s)
|
return failures.Since(t, s)
|
||||||
return fails
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) DowntimeAgo() string {
|
func (s *Service) DowntimeAgo() string {
|
||||||
|
|
|
@ -252,26 +252,18 @@ func SelectAllServices(start bool) (map[int64]*Service, error) {
|
||||||
if len(allServices) > 0 {
|
if len(allServices) > 0 {
|
||||||
return allServices, nil
|
return allServices, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range all() {
|
for _, s := range all() {
|
||||||
|
|
||||||
if start {
|
if start {
|
||||||
CheckinProcess(s)
|
CheckinProcess(s)
|
||||||
}
|
}
|
||||||
|
s.Failures = s.AllFailures().LastAmount(limitedFailures)
|
||||||
fails := s.AllFailures().LastAmount(limitedFailures)
|
|
||||||
s.Failures = fails
|
|
||||||
|
|
||||||
for _, c := range s.Checkins() {
|
for _, c := range s.Checkins() {
|
||||||
s.AllCheckins = append(s.AllCheckins, c)
|
s.AllCheckins = append(s.AllCheckins, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect initial service stats
|
// collect initial service stats
|
||||||
s.UpdateStats()
|
s.UpdateStats()
|
||||||
|
|
||||||
allServices[s.Id] = s
|
allServices[s.Id] = s
|
||||||
}
|
}
|
||||||
|
|
||||||
return allServices, nil
|
return allServices, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,15 +273,16 @@ func (s *Service) UpdateStats() *Service {
|
||||||
s.AvgResponse = s.AvgTime()
|
s.AvgResponse = s.AvgTime()
|
||||||
s.FailuresLast24Hours = s.FailuresSince(utils.Now().Add(-time.Hour * 24)).Count()
|
s.FailuresLast24Hours = s.FailuresSince(utils.Now().Add(-time.Hour * 24)).Count()
|
||||||
|
|
||||||
|
allFails := s.AllFailures()
|
||||||
if s.LastOffline.IsZero() {
|
if s.LastOffline.IsZero() {
|
||||||
lastFail := s.AllFailures().Last()
|
lastFail := allFails.Last()
|
||||||
if lastFail != nil {
|
if lastFail != nil {
|
||||||
s.LastOffline = lastFail.CreatedAt
|
s.LastOffline = lastFail.CreatedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Stats = &Stats{
|
s.Stats = &Stats{
|
||||||
Failures: s.AllFailures().Count(),
|
Failures: allFails.Count(),
|
||||||
Hits: s.AllHits().Count(),
|
Hits: s.AllHits().Count(),
|
||||||
FirstHit: s.FirstHit().CreatedAt,
|
FirstHit: s.FirstHit().CreatedAt,
|
||||||
}
|
}
|
||||||
|
@ -309,11 +302,8 @@ func (s *Service) OnlineDaysPercent(days int) float32 {
|
||||||
|
|
||||||
// OnlineSince accepts a time since parameter to return the percent of a service's uptime.
|
// OnlineSince accepts a time since parameter to return the percent of a service's uptime.
|
||||||
func (s *Service) OnlineSince(ago time.Time) float32 {
|
func (s *Service) OnlineSince(ago time.Time) float32 {
|
||||||
failed := s.FailuresSince(ago)
|
failsList := s.FailuresSince(ago).Count()
|
||||||
failsList := failed.Count()
|
hitsList := s.HitsSince(ago).Count()
|
||||||
|
|
||||||
total := s.HitsSince(ago)
|
|
||||||
hitsList := total.Count()
|
|
||||||
|
|
||||||
if failsList == 0 {
|
if failsList == 0 {
|
||||||
s.Online24Hours = 100.00
|
s.Online24Hours = 100.00
|
||||||
|
@ -348,3 +338,11 @@ func (s *Service) Downtime() time.Duration {
|
||||||
|
|
||||||
return fail.CreatedAt.Sub(hit.CreatedAt)
|
return fail.CreatedAt.Sub(hit.CreatedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServiceOrder will reorder the services based on 'order_id' (Order)
|
||||||
|
type ServiceOrder []Service
|
||||||
|
|
||||||
|
// Sort interface for resroting the Services in order
|
||||||
|
func (c ServiceOrder) Len() int { return len(c) }
|
||||||
|
func (c ServiceOrder) Swap(i, j int) { c[int64(i)], c[int64(j)] = c[int64(j)], c[int64(i)] }
|
||||||
|
func (c ServiceOrder) Less(i, j int) bool { return c[i].Order < c[j].Order }
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
func CheckServices() {
|
func CheckServices() {
|
||||||
log.Infoln(fmt.Sprintf("Starting monitoring process for %v Services", len(allServices)))
|
log.Infoln(fmt.Sprintf("Starting monitoring process for %v Services", len(allServices)))
|
||||||
for _, s := range allServices {
|
for _, s := range allServices {
|
||||||
//go CheckinRoutine()
|
|
||||||
time.Sleep(250 * time.Millisecond)
|
time.Sleep(250 * time.Millisecond)
|
||||||
go ServiceCheckQueue(s, true)
|
go ServiceCheckQueue(s, true)
|
||||||
}
|
}
|
||||||
|
@ -43,14 +42,14 @@ CheckLoop:
|
||||||
s.CheckService(record)
|
s.CheckService(record)
|
||||||
s.UpdateStats()
|
s.UpdateStats()
|
||||||
s.Checkpoint = s.Checkpoint.Add(s.Duration())
|
s.Checkpoint = s.Checkpoint.Add(s.Duration())
|
||||||
sleep := s.Checkpoint.Sub(time.Now())
|
|
||||||
if !s.Online {
|
if !s.Online {
|
||||||
s.SleepDuration = s.Duration()
|
s.SleepDuration = s.Duration()
|
||||||
} else {
|
} else {
|
||||||
s.SleepDuration = sleep
|
s.SleepDuration = s.Checkpoint.Sub(time.Now())
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,9 +78,7 @@ func dnsCheck(s *Service) (int64, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
t2 := utils.Now()
|
return utils.Now().Sub(t1).Microseconds(), err
|
||||||
subTime := t2.Sub(t1).Microseconds()
|
|
||||||
return subTime, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isIPv6(address string) bool {
|
func isIPv6(address string) bool {
|
||||||
|
@ -92,8 +89,7 @@ func isIPv6(address string) bool {
|
||||||
func CheckIcmp(s *Service, record bool) (*Service, error) {
|
func CheckIcmp(s *Service, record bool) (*Service, error) {
|
||||||
defer s.updateLastCheck()
|
defer s.updateLastCheck()
|
||||||
|
|
||||||
err := utils.Ping(s.Domain, s.Timeout)
|
if err := utils.Ping(s.Domain, s.Timeout); err != nil {
|
||||||
if err != nil {
|
|
||||||
if record {
|
if record {
|
||||||
recordFailure(s, fmt.Sprintf("Could not send ICMP to service %v, %v", s.Domain, err))
|
recordFailure(s, fmt.Sprintf("Could not send ICMP to service %v, %v", s.Domain, err))
|
||||||
}
|
}
|
||||||
|
@ -140,8 +136,7 @@ func CheckGrpc(s *Service, record bool) (*Service, error) {
|
||||||
}
|
}
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
t2 := utils.Now()
|
s.Latency = utils.Now().Sub(t1).Microseconds()
|
||||||
s.Latency = t2.Sub(t1).Microseconds()
|
|
||||||
s.LastResponse = ""
|
s.LastResponse = ""
|
||||||
s.Online = true
|
s.Online = true
|
||||||
if record {
|
if record {
|
||||||
|
@ -202,8 +197,7 @@ func CheckTcp(s *Service, record bool) (*Service, error) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
t2 := utils.Now()
|
s.Latency = utils.Now().Sub(t1).Microseconds()
|
||||||
s.Latency = t2.Sub(t1).Microseconds()
|
|
||||||
s.LastResponse = ""
|
s.LastResponse = ""
|
||||||
s.Online = true
|
s.Online = true
|
||||||
if record {
|
if record {
|
||||||
|
@ -279,8 +273,7 @@ func CheckHttp(s *Service, record bool) (*Service, error) {
|
||||||
}
|
}
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
t2 := utils.Now()
|
s.Latency = utils.Now().Sub(t1).Microseconds()
|
||||||
s.Latency = t2.Sub(t1).Microseconds()
|
|
||||||
s.LastResponse = string(content)
|
s.LastResponse = string(content)
|
||||||
s.LastStatusCode = res.StatusCode
|
s.LastStatusCode = res.StatusCode
|
||||||
|
|
||||||
|
|
|
@ -165,9 +165,16 @@ func TestStartExampleEndpoints(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServices(t *testing.T) {
|
func TestServices(t *testing.T) {
|
||||||
|
err := utils.InitLogs()
|
||||||
|
require.Nil(t, err)
|
||||||
db, err := database.OpenTester()
|
db, err := database.OpenTester()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(&Service{}, &hits.Hit{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &failures.Failure{})
|
db.AutoMigrate(&Service{}, &hits.Hit{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &failures.Failure{})
|
||||||
|
checkins.SetDB(db)
|
||||||
|
failures.SetDB(db)
|
||||||
|
hits.SetDB(db)
|
||||||
|
SetDB(db)
|
||||||
|
|
||||||
db.Create(&example)
|
db.Create(&example)
|
||||||
db.Create(&hit1)
|
db.Create(&hit1)
|
||||||
db.Create(&hit2)
|
db.Create(&hit2)
|
||||||
|
@ -175,10 +182,6 @@ func TestServices(t *testing.T) {
|
||||||
db.Create(&exmapleCheckin)
|
db.Create(&exmapleCheckin)
|
||||||
db.Create(&fail1)
|
db.Create(&fail1)
|
||||||
db.Create(&fail2)
|
db.Create(&fail2)
|
||||||
checkins.SetDB(db)
|
|
||||||
failures.SetDB(db)
|
|
||||||
hits.SetDB(db)
|
|
||||||
SetDB(db)
|
|
||||||
|
|
||||||
tlsCert := utils.Params.GetString("STATPING_DIR") + "/cert.pem"
|
tlsCert := utils.Params.GetString("STATPING_DIR") + "/cert.pem"
|
||||||
tlsCertKey := utils.Params.GetString("STATPING_DIR") + "/key.pem"
|
tlsCertKey := utils.Params.GetString("STATPING_DIR") + "/key.pem"
|
||||||
|
|
|
@ -4,22 +4,9 @@ import (
|
||||||
"github.com/statping/statping/types/checkins"
|
"github.com/statping/statping/types/checkins"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
"github.com/statping/statping/utils"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
allServices map[int64]*Service
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
allServices = make(map[int64]*Service)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Services() map[int64]*Service {
|
|
||||||
return allServices
|
|
||||||
}
|
|
||||||
|
|
||||||
// Service is the main struct for Services
|
// Service is the main struct for Services
|
||||||
type Service struct {
|
type Service struct {
|
||||||
Id int64 `gorm:"primary_key;column:id" json:"id" yaml:"id"`
|
Id int64 `gorm:"primary_key;column:id" json:"id" yaml:"id"`
|
||||||
|
@ -41,7 +28,7 @@ type Service struct {
|
||||||
TLSCertKey null.NullString `gorm:"column:tls_cert_key" json:"tls_cert_key" scope:"user,admin" yaml:"tls_cert_key"`
|
TLSCertKey null.NullString `gorm:"column:tls_cert_key" json:"tls_cert_key" scope:"user,admin" yaml:"tls_cert_key"`
|
||||||
TLSCertRoot null.NullString `gorm:"column:tls_cert_root" json:"tls_cert_root" scope:"user,admin" yaml:"tls_cert_root"`
|
TLSCertRoot null.NullString `gorm:"column:tls_cert_root" json:"tls_cert_root" scope:"user,admin" yaml:"tls_cert_root"`
|
||||||
Headers null.NullString `gorm:"column:headers" json:"headers" scope:"user,admin" yaml:"headers"`
|
Headers null.NullString `gorm:"column:headers" json:"headers" scope:"user,admin" yaml:"headers"`
|
||||||
Permalink null.NullString `gorm:"column:permalink;unique;" json:"permalink" yaml:"permalink"`
|
Permalink null.NullString `gorm:"column:permalink" json:"permalink" yaml:"permalink"`
|
||||||
Redirect null.NullBool `gorm:"default:false;column:redirect" json:"redirect" scope:"user,admin" yaml:"redirect"`
|
Redirect null.NullBool `gorm:"default:false;column:redirect" json:"redirect" scope:"user,admin" yaml:"redirect"`
|
||||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at" yaml:"-"`
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at" yaml:"-"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at" yaml:"-"`
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at" yaml:"-"`
|
||||||
|
@ -82,20 +69,3 @@ type Stats struct {
|
||||||
Hits int `gorm:"-" json:"hits"`
|
Hits int `gorm:"-" json:"hits"`
|
||||||
FirstHit time.Time `gorm:"-" json:"first_hit"`
|
FirstHit time.Time `gorm:"-" json:"first_hit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BeforeCreate for Service will set CreatedAt to UTC
|
|
||||||
func (s *Service) BeforeCreate() (err error) {
|
|
||||||
if s.CreatedAt.IsZero() {
|
|
||||||
s.CreatedAt = utils.Now()
|
|
||||||
s.UpdatedAt = utils.Now()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceOrder will reorder the services based on 'order_id' (Order)
|
|
||||||
type ServiceOrder []Service
|
|
||||||
|
|
||||||
// Sort interface for resroting the Services in order
|
|
||||||
func (c ServiceOrder) Len() int { return len(c) }
|
|
||||||
func (c ServiceOrder) Swap(i, j int) { c[int64(i)], c[int64(j)] = c[int64(j)], c[int64(i)] }
|
|
||||||
func (c ServiceOrder) Less(i, j int) bool { return c[i].Order < c[j].Order }
|
|
||||||
|
|
|
@ -12,6 +12,10 @@ type yamlFile struct {
|
||||||
|
|
||||||
// LoadServicesYaml will attempt to load the 'services.yml' file for Service Auto Creation on startup.
|
// LoadServicesYaml will attempt to load the 'services.yml' file for Service Auto Creation on startup.
|
||||||
func LoadServicesYaml() (*yamlFile, error) {
|
func LoadServicesYaml() (*yamlFile, error) {
|
||||||
|
if !utils.FileExists(utils.Directory + "/services.yml") {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
f, err := utils.OpenFile(utils.Directory + "/services.yml")
|
f, err := utils.OpenFile(utils.Directory + "/services.yml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -2,7 +2,7 @@ package users
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"github.com/statping/statping/utils"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,16 +14,10 @@ func AuthUser(username, password string) (*User, bool) {
|
||||||
log.Warnln(fmt.Errorf("user %v not found", username))
|
log.Warnln(fmt.Errorf("user %v not found", username))
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
if checkHash(password, user.Password) {
|
if utils.CheckHash(password, user.Password) {
|
||||||
user.UpdatedAt = time.Now().UTC()
|
user.UpdatedAt = time.Now().UTC()
|
||||||
user.Update()
|
user.Update()
|
||||||
return user, true
|
return user, true
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkHash returns true if the password matches with a hashed bcrypt password
|
|
||||||
func checkHash(password, hash string) bool {
|
|
||||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -52,10 +52,3 @@ func (u *User) Delete() error {
|
||||||
}
|
}
|
||||||
return q.Error()
|
return q.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) BeforeCreate() error {
|
|
||||||
u.Password = utils.HashPassword(u.Password)
|
|
||||||
u.ApiKey = utils.NewSHA256Hash()
|
|
||||||
u.ApiSecret = utils.NewSHA256Hash()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package users
|
||||||
|
|
||||||
|
import "github.com/statping/statping/utils"
|
||||||
|
|
||||||
|
func (u *User) BeforeCreate() error {
|
||||||
|
u.Password = utils.HashPassword(u.Password)
|
||||||
|
u.ApiKey = utils.NewSHA256Hash()
|
||||||
|
u.ApiSecret = utils.NewSHA256Hash()
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
@ -15,6 +14,12 @@ func HashPassword(password string) string {
|
||||||
return string(bytes)
|
return string(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckHash returns true if the password matches with a hashed bcrypt password
|
||||||
|
func CheckHash(password, hash string) bool {
|
||||||
|
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewSHA1Hash returns a random SHA1 hash based on a specific length
|
// NewSHA1Hash returns a random SHA1 hash based on a specific length
|
||||||
func NewSHA256Hash() string {
|
func NewSHA256Hash() string {
|
||||||
d := make([]byte, 10)
|
d := make([]byte, 10)
|
||||||
|
@ -23,10 +28,6 @@ func NewSHA256Hash() string {
|
||||||
return fmt.Sprintf("%x", sha256.Sum256(d))
|
return fmt.Sprintf("%x", sha256.Sum256(d))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Base64(s string) string {
|
|
||||||
return base64.StdEncoding.EncodeToString([]byte(s))
|
|
||||||
}
|
|
||||||
|
|
||||||
var characterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
var characterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||||
|
|
||||||
// RandomString generates a random string of n length
|
// RandomString generates a random string of n length
|
||||||
|
|
|
@ -9,47 +9,24 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Params *viper.Viper
|
Params *viper.Viper
|
||||||
configLog = Log.WithField("type", "configs")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func initCLI() {
|
func initEnvs() {
|
||||||
Params = viper.New()
|
Params = viper.New()
|
||||||
Params.AutomaticEnv()
|
Params.AutomaticEnv()
|
||||||
setDefaults()
|
|
||||||
Directory = Params.GetString("STATPING_DIR")
|
|
||||||
//Params.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
|
||||||
Params.SetConfigName("config")
|
|
||||||
Params.SetConfigType("yml")
|
|
||||||
Params.AddConfigPath(Directory)
|
|
||||||
|
|
||||||
Params.ReadInConfig()
|
|
||||||
|
|
||||||
Params.AddConfigPath(Directory)
|
|
||||||
Params.SetConfigFile(".env")
|
|
||||||
Params.ReadInConfig()
|
|
||||||
|
|
||||||
Params.Set("VERSION", version)
|
|
||||||
|
|
||||||
// check if logs are disabled
|
|
||||||
if !Params.GetBool("DISABLE_LOGS") {
|
|
||||||
Log.Out = ioutil.Discard
|
|
||||||
|
|
||||||
Log.Debugln("current working directory: ", Directory)
|
|
||||||
Log.AddHook(new(hook))
|
|
||||||
Log.SetNoLock()
|
|
||||||
checkVerboseMode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setDefaults() {
|
|
||||||
var err error
|
var err error
|
||||||
defaultDir, err := os.Getwd()
|
defaultDir, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
configLog.Errorln(err)
|
Log.Errorln(err)
|
||||||
defaultDir = "."
|
defaultDir = "."
|
||||||
}
|
}
|
||||||
|
Params.Set("VERSION", version)
|
||||||
|
Params.SetDefault("PORT", 8080)
|
||||||
|
Params.SetDefault("HOST", "0.0.0.0")
|
||||||
|
Params.SetDefault("DISABLE_HTTP", false)
|
||||||
Params.SetDefault("STATPING_DIR", defaultDir)
|
Params.SetDefault("STATPING_DIR", defaultDir)
|
||||||
Params.SetDefault("GO_ENV", "")
|
Params.SetDefault("GO_ENV", "production")
|
||||||
Params.SetDefault("DB_CONN", "")
|
Params.SetDefault("DB_CONN", "")
|
||||||
Params.SetDefault("DISABLE_LOGS", false)
|
Params.SetDefault("DISABLE_LOGS", false)
|
||||||
Params.SetDefault("USE_ASSETS", false)
|
Params.SetDefault("USE_ASSETS", false)
|
||||||
|
@ -72,6 +49,7 @@ func setDefaults() {
|
||||||
Params.SetDefault("LOGS_MAX_COUNT", 5)
|
Params.SetDefault("LOGS_MAX_COUNT", 5)
|
||||||
Params.SetDefault("LOGS_MAX_AGE", 28)
|
Params.SetDefault("LOGS_MAX_AGE", 28)
|
||||||
Params.SetDefault("LOGS_MAX_SIZE", 16)
|
Params.SetDefault("LOGS_MAX_SIZE", 16)
|
||||||
|
Params.SetDefault("DISABLE_COLORS", false)
|
||||||
|
|
||||||
dbConn := Params.GetString("DB_CONN")
|
dbConn := Params.GetString("DB_CONN")
|
||||||
dbInt := Params.GetInt("DB_PORT")
|
dbInt := Params.GetInt("DB_PORT")
|
||||||
|
@ -83,4 +61,25 @@ func setDefaults() {
|
||||||
Params.SetDefault("DB_PORT", 3306)
|
Params.SetDefault("DB_PORT", 3306)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Directory = Params.GetString("STATPING_DIR")
|
||||||
|
//Params.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||||
|
Params.SetConfigName("config")
|
||||||
|
Params.SetConfigType("yml")
|
||||||
|
Params.AddConfigPath(Directory)
|
||||||
|
Params.ReadInConfig()
|
||||||
|
|
||||||
|
Params.AddConfigPath(Directory)
|
||||||
|
Params.SetConfigFile(".env")
|
||||||
|
Params.ReadInConfig()
|
||||||
|
|
||||||
|
// check if logs are disabled
|
||||||
|
if Params.GetBool("DISABLE_LOGS") {
|
||||||
|
Log.Out = ioutil.Discard
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Log.Debugln("current working directory: ", Directory)
|
||||||
|
Log.AddHook(new(hook))
|
||||||
|
Log.SetNoLock()
|
||||||
|
checkVerboseMode()
|
||||||
}
|
}
|
|
@ -139,14 +139,14 @@ func replaceVal(d interface{}) interface{} {
|
||||||
// createLog will create the '/logs' directory based on a directory
|
// createLog will create the '/logs' directory based on a directory
|
||||||
func createLog(dir string) error {
|
func createLog(dir string) error {
|
||||||
if !FolderExists(dir + "/logs") {
|
if !FolderExists(dir + "/logs") {
|
||||||
CreateDirectory(dir + "/logs")
|
return CreateDirectory(dir + "/logs")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitLogs will create the '/logs' directory and creates a file '/logs/statup.log' for application logging
|
// InitLogs will create the '/logs' directory and creates a file '/logs/statup.log' for application logging
|
||||||
func InitLogs() error {
|
func InitLogs() error {
|
||||||
initCLI()
|
initEnvs()
|
||||||
if Params.GetBool("DISABLE_LOGS") {
|
if Params.GetBool("DISABLE_LOGS") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -164,8 +164,8 @@ func InitLogs() error {
|
||||||
Log.SetOutput(mw)
|
Log.SetOutput(mw)
|
||||||
|
|
||||||
Log.SetFormatter(&Logger.TextFormatter{
|
Log.SetFormatter(&Logger.TextFormatter{
|
||||||
ForceColors: true,
|
ForceColors: !Params.GetBool("DISABLE_COLORS"),
|
||||||
DisableColors: false,
|
DisableColors: Params.GetBool("DISABLE_COLORS"),
|
||||||
})
|
})
|
||||||
checkVerboseMode()
|
checkVerboseMode()
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -5,14 +5,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Timezoner returns the time.Time with the user set timezone
|
|
||||||
func Timezoner(t time.Time, zone float32) time.Time {
|
|
||||||
zoneInt := float32(3600) * zone
|
|
||||||
loc := time.FixedZone("", int(zoneInt))
|
|
||||||
timez := t.In(loc)
|
|
||||||
return timez
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now returns the UTC timestamp
|
// Now returns the UTC timestamp
|
||||||
func Now() time.Time {
|
func Now() time.Time {
|
||||||
return time.Now().UTC()
|
return time.Now().UTC()
|
||||||
|
|
|
@ -254,11 +254,12 @@ func HttpRequest(url, method string, content interface{}, headers []string, body
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
contents, err := ioutil.ReadAll(resp.Body)
|
contents, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
// record HTTP metrics
|
// record HTTP metrics
|
||||||
t2 := Now().Sub(t1).Milliseconds()
|
|
||||||
httpMetric.Requests++
|
httpMetric.Requests++
|
||||||
httpMetric.Milliseconds += t2 / httpMetric.Requests
|
httpMetric.Milliseconds += Now().Sub(t1).Milliseconds() / httpMetric.Requests
|
||||||
httpMetric.Bytes += int64(len(contents))
|
httpMetric.Bytes += int64(len(contents))
|
||||||
|
|
||||||
return contents, resp, err
|
return contents, resp, err
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateLog(t *testing.T) {
|
func TestCreateLog(t *testing.T) {
|
||||||
|
Directory = os.Getenv("STATPING_DIR")
|
||||||
err := createLog(Directory)
|
err := createLog(Directory)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
@ -20,7 +21,7 @@ func TestReplaceValue(t *testing.T) {
|
||||||
assert.Equal(t, true, replaceVal(true))
|
assert.Equal(t, true, replaceVal(true))
|
||||||
assert.Equal(t, 42, replaceVal(42))
|
assert.Equal(t, 42, replaceVal(42))
|
||||||
assert.Equal(t, "hello world", replaceVal("hello world"))
|
assert.Equal(t, "hello world", replaceVal("hello world"))
|
||||||
assert.Equal(t, "5s", replaceVal(time.Duration(5*time.Second)))
|
assert.Equal(t, "5s", replaceVal(5*time.Second))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInitLogs(t *testing.T) {
|
func TestInitLogs(t *testing.T) {
|
||||||
|
@ -122,15 +123,6 @@ func ExampleStringInt() {
|
||||||
// Output: 42
|
// Output: 42
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTimezone(t *testing.T) {
|
|
||||||
zone := float32(-4.0)
|
|
||||||
loc, _ := time.LoadLocation("America/Los_Angeles")
|
|
||||||
timestamp := time.Date(2018, 1, 1, 10, 0, 0, 0, loc)
|
|
||||||
timezone := Timezoner(timestamp, zone)
|
|
||||||
assert.Equal(t, "2018-01-01 10:00:00 -0800 PST", timestamp.String())
|
|
||||||
assert.Equal(t, "2018-01-01 18:00:00 +0000 UTC", timezone.UTC().String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestamp_Ago(t *testing.T) {
|
func TestTimestamp_Ago(t *testing.T) {
|
||||||
now := Timestamp(time.Now())
|
now := Timestamp(time.Now())
|
||||||
assert.Equal(t, "Just now", now.Ago())
|
assert.Equal(t, "Just now", now.Ago())
|
||||||
|
@ -185,8 +177,8 @@ func TestHttpRequest(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigLoad(t *testing.T) {
|
func TestConfigLoad(t *testing.T) {
|
||||||
initCLI()
|
InitLogs()
|
||||||
setDefaults()
|
initEnvs()
|
||||||
|
|
||||||
s := Params.GetString
|
s := Params.GetString
|
||||||
b := Params.GetBool
|
b := Params.GetBool
|
||||||
|
|
Loading…
Reference in New Issue