mirror of https://github.com/statping/statping
checkin - notifier docs
parent
bb3ab30a61
commit
f5e15258c8
|
@ -9,7 +9,7 @@
|
|||
# Statup - Status Page & Monitoring Server
|
||||
An easy to use Status Page for your websites and applications. Statup will automatically fetch the application and render a beautiful status page with tons of features for you to build an even better status page. This Status Page generator allows you to use MySQL, Postgres, or SQLite on multiple operating systems.
|
||||
|
||||
[](https://gitter.im/statup-app/general)
|
||||
[](https://godoc.org/github.com/hunterlong/statup) [](https://gitter.im/statup-app/general)
|
||||
|
||||
## A Future-Proof Status Page
|
||||
Statup strives to remain future-proof and remain intact if a failure is created. Your Statup service should not be running on the same instance you're trying to monitor. If your server crashes your Status Page should still remaining online to notify your users of downtime.
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"github.com/ararog/timeago"
|
||||
"github.com/hunterlong/statup/types"
|
||||
"github.com/hunterlong/statup/utils"
|
||||
"github.com/jinzhu/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -80,17 +79,18 @@ func (u *Checkin) Hits() []CheckinHit {
|
|||
return checkins
|
||||
}
|
||||
|
||||
func (u *Checkin) Update() (int64, error) {
|
||||
fmt.Println("updating: ", u.Id, u.ApiKey)
|
||||
exists := checkinDB().Find(&u).RecordNotFound()
|
||||
var row *gorm.DB
|
||||
if !exists {
|
||||
row = checkinDB().Update(&u)
|
||||
} else {
|
||||
func (u *Checkin) Create() (int64, error) {
|
||||
u.ApiKey = utils.RandomString(7)
|
||||
row = checkinDB().Create(&u)
|
||||
row := checkinDB().Create(&u)
|
||||
if row.Error != nil {
|
||||
utils.Log(2, row.Error)
|
||||
return 0, row.Error
|
||||
}
|
||||
fmt.Println("found: ", exists, u.Id, u.Service, u.Interval, u.GracePeriod, u.ApiKey)
|
||||
return u.Id, row.Error
|
||||
}
|
||||
|
||||
func (u *Checkin) Update() (int64, error) {
|
||||
row := checkinDB().Update(&u)
|
||||
if row.Error != nil {
|
||||
utils.Log(2, row.Error)
|
||||
return 0, row.Error
|
||||
|
|
|
@ -33,7 +33,7 @@ var example = &ExampleNotifier{&Notification{
|
|||
Description: "Example Notifier",
|
||||
Author: "Hunter Long",
|
||||
AuthorUrl: "https://github.com/hunterlong",
|
||||
Delay: time.Duration(200 * time.Millisecond),
|
||||
Delay: time.Duration(3 * time.Second),
|
||||
Limits: 7,
|
||||
Form: []NotificationForm{{
|
||||
Type: "text",
|
||||
|
@ -182,7 +182,7 @@ func (n *ExampleNotifier) OnUpdatedNotifier(s *Notification) {
|
|||
}
|
||||
|
||||
// Create a new notifier that includes a form for the end user to insert their own values
|
||||
func Example() {
|
||||
func ExampleNotification() {
|
||||
// Create a new variable for your Notifier
|
||||
example = &ExampleNotifier{&Notification{
|
||||
Method: "Example",
|
||||
|
@ -198,29 +198,91 @@ func Example() {
|
|||
Placeholder: "Insert your Host here.",
|
||||
DbField: "host",
|
||||
SmallText: "you can also use SmallText to insert some helpful hints under this input",
|
||||
}, {
|
||||
Type: "text",
|
||||
Title: "API Key",
|
||||
Placeholder: "Include some type of API key here",
|
||||
DbField: "api_key",
|
||||
}},
|
||||
}}
|
||||
|
||||
// AddNotifier accepts a notifier to load into the Statup Notification system
|
||||
AddNotifier(example)
|
||||
// AddNotifier accepts a Notifier to load into the Statup Notification system
|
||||
err := AddNotifier(example)
|
||||
fmt.Println(err)
|
||||
// Output: <nil>
|
||||
}
|
||||
|
||||
// Add any type of interface to the AddQueue function when a service is successful
|
||||
func Example_onSuccess() {
|
||||
// Add a Notifier to the AddQueue function to insert it into the system
|
||||
func ExampleAddNotifier() {
|
||||
err := AddNotifier(example)
|
||||
fmt.Println(err)
|
||||
// Output: <nil>
|
||||
}
|
||||
|
||||
// OnSuccess will be triggered everytime a service is online
|
||||
func ExampleNotification_OnSuccess() {
|
||||
msg := fmt.Sprintf("this is a successful message as a string passing into AddQueue function")
|
||||
example.AddQueue(msg)
|
||||
fmt.Println(len(example.Queue))
|
||||
// Output: 1
|
||||
}
|
||||
|
||||
// Add any type of interface to the AddQueue function when a service is successful
|
||||
func Example_onFailure() {
|
||||
// Add any type of interface to the AddQueue function to be ran in the queue
|
||||
func ExampleNotification_AddQueue() {
|
||||
msg := fmt.Sprintf("this is a failing message as a string passing into AddQueue function")
|
||||
example.AddQueue(msg)
|
||||
queue := example.Queue
|
||||
fmt.Printf("Example has %v items in the queue", len(queue))
|
||||
// Output: Example has 2 items in the queue
|
||||
}
|
||||
|
||||
// The Send method will run the main functionality of your notifier
|
||||
func Example_send() {
|
||||
// example.Send(msg interface{})
|
||||
for i := 0; i <= 10; i++ {
|
||||
fmt.Printf("do something awesome rather than a loop %v\n", i)
|
||||
func ExampleNotification_Send() {
|
||||
msg := "this can be any type of interface"
|
||||
example.Send(msg)
|
||||
queue := example.Queue
|
||||
fmt.Printf("Example has %v items in the queue", len(queue))
|
||||
// Output:
|
||||
// i received this string: this can be any type of interface
|
||||
// Example has 2 items in the queue
|
||||
}
|
||||
|
||||
// LastSent will return the time.Duration of the last sent message
|
||||
func ExampleNotification_LastSent() {
|
||||
last := example.LastSent()
|
||||
fmt.Printf("Last message was sent %v seconds ago", last.Seconds())
|
||||
// Output: Last message was sent 0 seconds ago
|
||||
}
|
||||
|
||||
// Logs will return a slice of previously sent items from your notifier
|
||||
func ExampleNotification_Logs() {
|
||||
logs := example.Logs()
|
||||
fmt.Printf("Example has %v items in the log", len(logs))
|
||||
// Output: Example has 0 items in the log
|
||||
}
|
||||
|
||||
// SentLastMinute will return he amount of notifications sent in last 1 minute
|
||||
func ExampleNotification_SentLastMinute() {
|
||||
lastMinute := example.SentLastMinute()
|
||||
fmt.Printf("%v notifications sent in the last minute", lastMinute)
|
||||
// Output: 0 notifications sent in the last minute
|
||||
}
|
||||
|
||||
// SentLastHour will return he amount of notifications sent in last 1 hour
|
||||
func ExampleNotification_SentLastHour() {
|
||||
lastHour := example.SentLastHour()
|
||||
fmt.Printf("%v notifications sent in the last hour", lastHour)
|
||||
// Output: 0 notifications sent in the last hour
|
||||
}
|
||||
|
||||
// SentLastHour will return he amount of notifications sent in last 1 hour
|
||||
func ExampleNotification_WithinLimits() {
|
||||
ok, err := example.WithinLimits()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if ok {
|
||||
fmt.Printf("Example notifier is still within its sending limits")
|
||||
}
|
||||
// Output: Example notifier is still within its sending limits
|
||||
}
|
||||
|
|
|
@ -94,18 +94,14 @@ func SetDB(d *gorm.DB) {
|
|||
db = d
|
||||
}
|
||||
|
||||
func asNotifier(n interface{}) Notifier {
|
||||
return n.(Notifier)
|
||||
}
|
||||
|
||||
func asNotification(n interface{}) *Notification {
|
||||
return n.(Notifier).Select()
|
||||
func asNotification(n Notifier) *Notification {
|
||||
return n.Select()
|
||||
}
|
||||
|
||||
// AddNotifier accept a Notifier interface to be added into the array
|
||||
func AddNotifier(n interface{}) error {
|
||||
func AddNotifier(n Notifier) error {
|
||||
if isType(n, new(Notifier)) {
|
||||
err := checkNotifierForm(asNotifier(n))
|
||||
err := checkNotifierForm(n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -231,10 +231,9 @@ func TestRunAllQueueAndStop(t *testing.T) {
|
|||
assert.True(t, example.IsRunning())
|
||||
assert.Equal(t, 16, len(example.Queue))
|
||||
go Queue(example)
|
||||
assert.Equal(t, 16, len(example.Queue))
|
||||
time.Sleep(12 * time.Second)
|
||||
assert.Equal(t, 6, len(example.Queue))
|
||||
time.Sleep(13 * time.Second)
|
||||
assert.True(t, len(example.Queue) >= 10)
|
||||
example.close()
|
||||
assert.False(t, example.IsRunning())
|
||||
assert.Equal(t, 6, len(example.Queue))
|
||||
assert.True(t, len(example.Queue) >= 10)
|
||||
}
|
||||
|
|
|
@ -49,10 +49,10 @@ func SelectService(id int64) *Service {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Checkin() *Checkin {
|
||||
var checkin types.Checkin
|
||||
checkinDB().Find(&checkin, "service = ?", s.Id)
|
||||
return &Checkin{&checkin}
|
||||
func (s *Service) Checkins() []*Checkin {
|
||||
var checkin []*Checkin
|
||||
checkinDB().Where("service = ?", s.Id).Find(&checkin)
|
||||
return checkin
|
||||
}
|
||||
|
||||
// SelectAllServices returns a slice of *core.Service to be store on []*core.Services, should only be called once on startup.
|
||||
|
@ -66,7 +66,7 @@ func (c *Core) SelectAllServices() ([]*Service, error) {
|
|||
CoreApp.Services = nil
|
||||
for _, service := range services {
|
||||
service.Start()
|
||||
service.Checkin()
|
||||
service.Checkins()
|
||||
service.AllFailures()
|
||||
CoreApp.Services = append(CoreApp.Services, service)
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ package core
|
|||
|
||||
import (
|
||||
"github.com/hunterlong/statup/types"
|
||||
"github.com/hunterlong/statup/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -224,7 +225,7 @@ func TestCreateFailingHTTPService(t *testing.T) {
|
|||
func TestServiceFailedCheck(t *testing.T) {
|
||||
service := SelectService(17)
|
||||
assert.Equal(t, "Bad URL", service.Name)
|
||||
service.Check(true)
|
||||
service.Check(false)
|
||||
assert.Equal(t, "Bad URL", service.Name)
|
||||
assert.False(t, service.Online)
|
||||
}
|
||||
|
@ -249,7 +250,7 @@ func TestCreateFailingTCPService(t *testing.T) {
|
|||
|
||||
func TestServiceFailedTCPCheck(t *testing.T) {
|
||||
service := SelectService(newServiceId)
|
||||
service.Check(true)
|
||||
service.Check(false)
|
||||
assert.Equal(t, "Bad TCP", service.Name)
|
||||
assert.False(t, service.Online)
|
||||
}
|
||||
|
@ -342,3 +343,57 @@ func TestDNScheckService(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
assert.NotZero(t, amount)
|
||||
}
|
||||
|
||||
func TestCreateCheckin(t *testing.T) {
|
||||
checkin := ReturnCheckin(&types.Checkin{
|
||||
Service: 1,
|
||||
Interval: 10,
|
||||
GracePeriod: 5,
|
||||
ApiKey: utils.RandomString(7),
|
||||
})
|
||||
id, err := checkin.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, id)
|
||||
}
|
||||
|
||||
func TestSelectCheckin(t *testing.T) {
|
||||
service := SelectService(1)
|
||||
checkins := service.Checkins()
|
||||
assert.NotNil(t, checkins)
|
||||
assert.Equal(t, 1, len(checkins))
|
||||
first := checkins[0]
|
||||
assert.Equal(t, int64(10), first.Interval)
|
||||
assert.Equal(t, 7, len(first.ApiKey))
|
||||
assert.Equal(t, int64(5), first.GracePeriod)
|
||||
}
|
||||
|
||||
func TestCreateCheckinHits(t *testing.T) {
|
||||
service := SelectService(1)
|
||||
checkins := service.Checkins()
|
||||
first := checkins[0]
|
||||
created := time.Now().Add(-2 * time.Hour)
|
||||
for i := 0; i <= 20; i++ {
|
||||
hit := ReturnCheckinHit(&types.CheckinHit{
|
||||
Checkin: first.Id,
|
||||
From: "192.168.1.1",
|
||||
CreatedAt: created,
|
||||
})
|
||||
hit.Create()
|
||||
created = created.Add(10 * time.Second)
|
||||
}
|
||||
hits := first.Hits()
|
||||
assert.Equal(t, 21, len(hits))
|
||||
}
|
||||
|
||||
func TestSelectCheckinMethods(t *testing.T) {
|
||||
time.Sleep(5 * time.Second)
|
||||
service := SelectService(1)
|
||||
checkins := service.Checkins()
|
||||
assert.NotNil(t, checkins)
|
||||
first := checkins[0]
|
||||
lastHit := first.Last()
|
||||
assert.Equal(t, float64(10), first.Period().Seconds())
|
||||
assert.Equal(t, float64(5), first.Grace().Seconds())
|
||||
assert.Equal(t, time.Now().Day(), lastHit.CreatedAt.Day())
|
||||
assert.Equal(t, "Just now", lastHit.Ago())
|
||||
}
|
||||
|
|
|
@ -261,7 +261,9 @@ func checkinCreateUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
vars := mux.Vars(r)
|
||||
service := core.SelectService(utils.StringInt(vars["id"]))
|
||||
checkin := service.Checkin()
|
||||
api := r.PostForm.Get("api")
|
||||
checkin := core.SelectCheckin(api)
|
||||
|
||||
interval := utils.StringInt(r.PostForm.Get("interval"))
|
||||
grace := utils.StringInt(r.PostForm.Get("grace"))
|
||||
checkin.Interval = interval
|
||||
|
|
|
@ -105,16 +105,18 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{$ch := $s.Checkin}}
|
||||
{{range $s.Checkins}}
|
||||
{{ $ch := . }}
|
||||
<tr class="{{ if lt $ch.Expected 0}}bg-danger text-white{{else}}bg-light{{end}}">
|
||||
<td>{{CoreApp.Domain}}/checkin/{{$ch.ApiKey}}</td>
|
||||
<td>every {{Duration $ch.Period}}<br>after {{Duration $ch.Grace}}</td>
|
||||
<td>{{Ago $ch.Last.CreatedAt}}</td>
|
||||
<td>{{ if lt $ch.Expected 0}}{{Duration $ch.Expected}} ago{{else}}in {{Duration $ch.Expected}}{{end}}</td>
|
||||
</tr>
|
||||
{{template "form_checkin" $ch}}
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{template "form_checkin" $ch}}
|
||||
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in New Issue