mirror of https://github.com/statping/statping
testing - notifer update
parent
ba85a96ab8
commit
ca39fc73a4
|
@ -311,7 +311,7 @@ func RunSelectAllNotifiers(t *testing.T) {
|
|||
notifier.SetDB(core.DbSession)
|
||||
core.CoreApp.Notifications = notifier.Load()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 5, len(core.CoreApp.Notifications))
|
||||
assert.Equal(t, 6, len(core.CoreApp.Notifications))
|
||||
}
|
||||
|
||||
func RunUserSelectAll(t *testing.T) {
|
||||
|
|
|
@ -27,6 +27,10 @@ type Checkin struct {
|
|||
*types.Checkin
|
||||
}
|
||||
|
||||
type CheckinHit struct {
|
||||
*types.CheckinHit
|
||||
}
|
||||
|
||||
func (c *Checkin) String() string {
|
||||
return c.ApiKey
|
||||
}
|
||||
|
@ -35,6 +39,16 @@ func ReturnCheckin(s *types.Checkin) *Checkin {
|
|||
return &Checkin{Checkin: s}
|
||||
}
|
||||
|
||||
func ReturnCheckinHit(h *types.CheckinHit) *CheckinHit {
|
||||
return &CheckinHit{CheckinHit: h}
|
||||
}
|
||||
|
||||
func SelectCheckin(api string) *Checkin {
|
||||
var checkin Checkin
|
||||
checkinDB().Where("api_key = ?", api).First(&checkin)
|
||||
return &checkin
|
||||
}
|
||||
|
||||
func FindCheckin(api string) *types.Checkin {
|
||||
for _, ser := range CoreApp.Services {
|
||||
service := ser.Select()
|
||||
|
@ -47,6 +61,12 @@ func FindCheckin(api string) *types.Checkin {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *Checkin) Hits() []CheckinHit {
|
||||
var checkins []CheckinHit
|
||||
checkinDB().Where("checkin = ?", u.Id).Order("id DESC").Find(&checkins)
|
||||
return checkins
|
||||
}
|
||||
|
||||
func (u *Checkin) Create() (int64, error) {
|
||||
u.CreatedAt = time.Now()
|
||||
row := checkinDB().Create(u)
|
||||
|
@ -57,6 +77,16 @@ func (u *Checkin) Create() (int64, error) {
|
|||
return u.Id, row.Error
|
||||
}
|
||||
|
||||
func (u *CheckinHit) Create() (int64, error) {
|
||||
u.CreatedAt = time.Now()
|
||||
row := checkinHitsDB().Create(u)
|
||||
if row.Error == nil {
|
||||
utils.Log(2, row.Error)
|
||||
return 0, row.Error
|
||||
}
|
||||
return u.Id, row.Error
|
||||
}
|
||||
|
||||
func SelectCheckinApi(api string) *Checkin {
|
||||
var checkin *Checkin
|
||||
checkinDB().Where("api = ?", api).Find(&checkin)
|
||||
|
@ -95,3 +125,8 @@ func (f *Checkin) Ago() string {
|
|||
got, _ := timeago.TimeAgoWithTime(time.Now(), time.Now())
|
||||
return got
|
||||
}
|
||||
|
||||
func (f *CheckinHit) Ago() string {
|
||||
got, _ := timeago.TimeAgoWithTime(time.Now(), time.Now())
|
||||
return got
|
||||
}
|
||||
|
|
|
@ -61,11 +61,16 @@ func usersDB() *gorm.DB {
|
|||
return DbSession.Model(&types.User{})
|
||||
}
|
||||
|
||||
// hitsDB returns the 'hits' database column
|
||||
// checkinDB returns the Checkin records for a service
|
||||
func checkinDB() *gorm.DB {
|
||||
return DbSession.Model(&types.Checkin{})
|
||||
}
|
||||
|
||||
// checkinHitsDB returns the 'hits' from the Checkin record
|
||||
func checkinHitsDB() *gorm.DB {
|
||||
return DbSession.Model(&types.CheckinHit{})
|
||||
}
|
||||
|
||||
// HitsBetween returns the gorm database query for a collection of service hits between a time range
|
||||
func (s *Service) HitsBetween(t1, t2 time.Time, group string, column string) *gorm.DB {
|
||||
selector := Dbtimestamp(group, column)
|
||||
|
|
|
@ -232,7 +232,7 @@ func TestRunAllQueueAndStop(t *testing.T) {
|
|||
assert.Equal(t, 16, len(example.Queue))
|
||||
go Queue(example)
|
||||
assert.Equal(t, 16, len(example.Queue))
|
||||
time.Sleep(10 * time.Second)
|
||||
time.Sleep(12 * time.Second)
|
||||
assert.Equal(t, 6, len(example.Queue))
|
||||
example.close()
|
||||
assert.False(t, example.IsRunning())
|
||||
|
|
|
@ -49,8 +49,8 @@ func SelectService(id int64) *Service {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Checkins() []*types.Checkin {
|
||||
var hits []*types.Checkin
|
||||
func (s *Service) Checkins() []*Checkin {
|
||||
var hits []*Checkin
|
||||
servicesDB().Where("service = ?", s.Id).Find(&hits)
|
||||
return hits
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ func TestServiceTotalHits(t *testing.T) {
|
|||
service := SelectService(5)
|
||||
hits, err := service.TotalHits()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, uint64(0x5ac), hits)
|
||||
assert.NotZero(t, hits)
|
||||
}
|
||||
|
||||
func TestServiceSum(t *testing.T) {
|
||||
|
|
|
@ -90,7 +90,6 @@ func TestApiIndexHandler(t *testing.T) {
|
|||
rr, err := httpRequestAPI(t, "GET", "/api", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
t.Log(body)
|
||||
var obj types.Core
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
|
@ -102,7 +101,6 @@ func TestApiAllServicesHandlerHandler(t *testing.T) {
|
|||
rr, err := httpRequestAPI(t, "GET", "/api/services", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
t.Log(body)
|
||||
var obj []types.Service
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
|
@ -126,7 +124,6 @@ func TestApiCreateServiceHandler(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
t.Log(body)
|
||||
var obj types.Service
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
|
@ -162,7 +159,6 @@ func TestApiDeleteServiceHandler(t *testing.T) {
|
|||
rr, err := httpRequestAPI(t, "DELETE", "/api/services/1", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
t.Log(body)
|
||||
var obj ApiResponse
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
|
@ -171,11 +167,9 @@ func TestApiDeleteServiceHandler(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestApiAllUsersHandler(t *testing.T) {
|
||||
|
||||
rr, err := httpRequestAPI(t, "GET", "/api/users", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
t.Log(body)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
var obj []types.User
|
||||
formatJSON(body, &obj)
|
||||
|
|
|
@ -162,7 +162,7 @@ func executeResponse(w http.ResponseWriter, r *http.Request, file string, data i
|
|||
return
|
||||
}
|
||||
|
||||
templates := []string{"base.html", "head.html", "nav.html", "footer.html", "scripts.html", "form_service.html", "form_notifier.html", "form_user.html"}
|
||||
templates := []string{"base.html", "head.html", "nav.html", "footer.html", "scripts.html", "form_service.html", "form_notifier.html", "form_user.html", "form_checkin.html"}
|
||||
|
||||
javascripts := []string{"charts.js", "chart_index.js"}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ func Router() *mux.Router {
|
|||
r.Handle("/service/{id}/delete", http.HandlerFunc(servicesDeleteHandler))
|
||||
r.Handle("/service/{id}/delete_failures", http.HandlerFunc(servicesDeleteFailuresHandler)).Methods("GET")
|
||||
r.Handle("/service/{id}/checkin", http.HandlerFunc(checkinCreateUpdateHandler)).Methods("POST")
|
||||
r.Handle("/checkin/{id}", http.HandlerFunc(checkinUpdateHandler))
|
||||
r.Handle("/users", http.HandlerFunc(usersHandler)).Methods("GET")
|
||||
r.Handle("/users", http.HandlerFunc(createUserHandler)).Methods("POST")
|
||||
r.Handle("/user/{id}", http.HandlerFunc(usersEditHandler)).Methods("GET")
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/hunterlong/statup/types"
|
||||
"github.com/hunterlong/statup/utils"
|
||||
"github.com/jinzhu/now"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
@ -257,14 +258,30 @@ func checkinCreateUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
vars := mux.Vars(r)
|
||||
service := core.SelectService(utils.StringInt(vars["id"]))
|
||||
|
||||
interval := utils.StringInt(r.PostForm.Get("interval"))
|
||||
serv := core.SelectService(utils.StringInt(vars["id"]))
|
||||
service := serv
|
||||
checkin := &types.Checkin{
|
||||
Service: service.Id,
|
||||
Interval: interval,
|
||||
ApiKey: utils.NewSHA1Hash(18),
|
||||
}
|
||||
grace := utils.StringInt(r.PostForm.Get("grace"))
|
||||
checkin := core.ReturnCheckin(&types.Checkin{
|
||||
Service: service.Id,
|
||||
Interval: interval,
|
||||
GracePeriod: grace,
|
||||
ApiKey: utils.NewSHA1Hash(18),
|
||||
})
|
||||
checkin.Create()
|
||||
executeResponse(w, r, "service.html", service, "/services")
|
||||
executeResponse(w, r, "service.html", service, fmt.Sprintf("/service/%v", service.Id))
|
||||
}
|
||||
|
||||
func checkinUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
checkin := core.SelectCheckin(vars["id"])
|
||||
ip, _, _ := net.SplitHostPort(r.RemoteAddr)
|
||||
checkinHit := core.ReturnCheckinHit(&types.CheckinHit{
|
||||
Checkin: checkin.Id,
|
||||
From: ip,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
})
|
||||
checkinHit.Create()
|
||||
w.Write([]byte("ok"))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ var webhook = &Webhook{¬ifier.Notification{
|
|||
Type: "textarea",
|
||||
Title: "HTTP Body",
|
||||
Placeholder: `{"service_id": "%s.Id", "service_name": "%s.Name"}`,
|
||||
SmallText: "Optional HTTP body for a POST request. You can insert variables into your body request.<br>%service.Id, %service.Name<br>%failure.Issue",
|
||||
SmallText: "Optional HTTP body for a POST request. You can insert variables into your body request.<br>%service.Id, %service.Name, %service.Online<br>%failure.Issue",
|
||||
DbField: "Var2",
|
||||
}, {
|
||||
Type: "text",
|
||||
|
@ -87,8 +87,10 @@ func init() {
|
|||
|
||||
// Send will send a HTTP Post to the Webhook API. It accepts type: string
|
||||
func (w *Webhook) Send(msg interface{}) error {
|
||||
message := msg.(string)
|
||||
_, err := w.run(message)
|
||||
resp, err := w.run(msg.(string))
|
||||
if err == nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -100,6 +102,7 @@ func replaceBodyText(body string, s *types.Service, f *types.Failure) string {
|
|||
if s != nil {
|
||||
body = strings.Replace(body, "%service.Name", s.Name, -1)
|
||||
body = strings.Replace(body, "%service.Id", utils.ToString(s.Id), -1)
|
||||
body = strings.Replace(body, "%service.Online", utils.ToString(s.Online), -1)
|
||||
}
|
||||
if f != nil {
|
||||
body = strings.Replace(body, "%failure.Issue", f.Issue, -1)
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
var (
|
||||
WEBHOOK_URL = "https://jsonplaceholder.typicode.com/posts"
|
||||
webhookMessage = `{ "title": "%service.Id", "body": "%service.Name", "userId": 19999 }`
|
||||
webhookMessage = `{ "title": "%service.Id", "body": "%service.Name", "online": %service.Online, "userId": 19999 }`
|
||||
fullMsg string
|
||||
)
|
||||
|
||||
|
@ -56,7 +56,7 @@ func TestWebhookNotifier(t *testing.T) {
|
|||
|
||||
t.Run("Webhook Replace Body Text", func(t *testing.T) {
|
||||
fullMsg = replaceBodyText(webhookMessage, TestService, TestFailure)
|
||||
assert.Equal(t, 78, len(fullMsg))
|
||||
assert.Equal(t, "{ \"title\": \"1\", \"body\": \"Interpol - All The Rage Back Home\", \"online\": false, \"userId\": 19999 }", fullMsg)
|
||||
})
|
||||
|
||||
t.Run("Webhook Within Limits", func(t *testing.T) {
|
||||
|
@ -96,7 +96,7 @@ func TestWebhookNotifier(t *testing.T) {
|
|||
|
||||
t.Run("Webhook Queue", func(t *testing.T) {
|
||||
go notifier.Queue(webhook)
|
||||
time.Sleep(5 * time.Second)
|
||||
time.Sleep(8 * time.Second)
|
||||
assert.Equal(t, WEBHOOK_URL, webhook.Host)
|
||||
assert.Equal(t, 1, len(webhook.Queue))
|
||||
})
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
{{define "form_checkin"}}
|
||||
<form action="/service/{{.Id}}/checkin" method="POST">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 col-sm-12">
|
||||
<label for="checkin_interval" class="col-sm-4 col-form-label">Check Interval (in seconds)</label>
|
||||
<input type="number" name="interval" class="form-control" id="checkin_interval" value="30" placeholder="60">
|
||||
</div>
|
||||
<div class="col-md-12 col-sm-12">
|
||||
<label for="grace_period" class="col-sm-4 col-form-label">Grace Period </label>
|
||||
<input type="number" name="grace" class="form-control" id="grace_period" value="30" placeholder="60">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button type="submit" class="btn btn-success d-block">Save Checkin</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{{end}}
|
|
@ -96,30 +96,20 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-12 mt-4{{if eq $s.Type "tcp"}} d-none{{end}}">
|
||||
<h3>Service Checkins</h3>
|
||||
{{ range $s.Checkins }}
|
||||
<h5>Check #{{.Id}} <span class="badge online_badge float-right">Checked in {{.Ago}}</span></h5>
|
||||
<input type="text" class="form-control" value="https://domainhere.com/api/checkin/{{.Api}}">
|
||||
<h5>Check #{{.Id}} <span class="badge online_badge float-right">Checked in</span></h5>
|
||||
<input type="text" class="form-control" value="{{CoreApp.Domain}}/checkin/{{.ApiKey}}">
|
||||
<ul class="list-group">
|
||||
{{ range .Hits }}
|
||||
<li class="list-group-item">Received Checkin at {{.CreatedAt}}</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{ end }}
|
||||
|
||||
<form action="/service/{{$s.Id}}/checkin" method="POST">
|
||||
<div class="form-group row">
|
||||
<label for="service_name" class="col-sm-4 col-form-label">Check Interval (in seconds)</label>
|
||||
<div class="col-md-6 col-sm-12">
|
||||
<input type="number" name="name" class="form-control" id="checkin_interval" value="30" placeholder="Name">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="submit" class="btn btn-success d-none d-md-block float-right">Save Checkin</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button type="submit" class="btn btn-success d-block d-md-none btn-block">Save Checkin</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{{template "form_checkin" $s}}
|
||||
|
||||
</div>
|
||||
|
||||
{{end}}
|
||||
|
|
|
@ -20,15 +20,14 @@ import (
|
|||
)
|
||||
|
||||
type Checkin struct {
|
||||
Id int64 `gorm:"primary_key;column:id"`
|
||||
Service int64 `gorm:"index;column:service"`
|
||||
Interval int64 `gorm:"column:check_interval"`
|
||||
GracePeriod int64 `gorm:"column:grace_period"`
|
||||
ApiKey string `gorm:"column:api_key"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||
Hits []CheckinHit `json:"hits"`
|
||||
CheckinInterface `json:"-"`
|
||||
Id int64 `gorm:"primary_key;column:id"`
|
||||
Service int64 `gorm:"index;column:service"`
|
||||
Interval int64 `gorm:"column:check_interval"`
|
||||
GracePeriod int64 `gorm:"column:grace_period"`
|
||||
ApiKey string `gorm:"column:api_key"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||
Hits []CheckinHit `json:"hits"`
|
||||
}
|
||||
|
||||
type CheckinHit struct {
|
||||
|
@ -37,12 +36,3 @@ type CheckinHit struct {
|
|||
From string `gorm:"column:from_location"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
}
|
||||
|
||||
type CheckinInterface interface {
|
||||
// Database functions
|
||||
Create() (int64, error)
|
||||
//Update() error
|
||||
//Delete() error
|
||||
Ago() string
|
||||
Receivehit()
|
||||
}
|
||||
|
|
|
@ -56,7 +56,6 @@ type ServiceInterface interface {
|
|||
Create(bool) (int64, error)
|
||||
Update(bool) error
|
||||
Delete() error
|
||||
Checkins() []*Checkin
|
||||
}
|
||||
|
||||
// Start will create a channel for the service checking go routine
|
||||
|
|
|
@ -56,8 +56,14 @@ func ToString(s interface{}) string {
|
|||
return fmt.Sprintf("%v", v)
|
||||
case []byte:
|
||||
return string(v)
|
||||
case bool:
|
||||
if v {
|
||||
return "true"
|
||||
}
|
||||
return "false"
|
||||
default:
|
||||
return fmt.Sprintf("%v", v)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func Timezoner(t time.Time, zone float32) time.Time {
|
||||
|
|
Loading…
Reference in New Issue