http timeout in DB - tcp checker - ui updates

pull/33/head
Hunter Long 2018-07-18 16:01:24 -07:00
parent edc2d9b7d0
commit ab7e2040e7
14 changed files with 96 additions and 27 deletions

View File

@ -59,7 +59,7 @@ func ServiceTCPCheck(s *types.Service) *types.Service {
if s.Port != 0 { if s.Port != 0 {
domain = fmt.Sprintf("%v:%v", s.Domain, s.Port) domain = fmt.Sprintf("%v:%v", s.Domain, s.Port)
} }
conn, err := net.Dial("tcp", domain) conn, err := net.DialTimeout("tcp", domain, time.Duration(s.Timeout)*time.Second)
if err != nil { if err != nil {
RecordFailure(s, fmt.Sprintf("TCP Dial Error %v", err)) RecordFailure(s, fmt.Sprintf("TCP Dial Error %v", err))
return s return s
@ -93,8 +93,9 @@ func ServiceHTTPCheck(s *types.Service) *types.Service {
} }
s.DnsLookup = dnsLookup s.DnsLookup = dnsLookup
t1 := time.Now() t1 := time.Now()
timeout := time.Duration(s.Timeout)
client := http.Client{ client := http.Client{
Timeout: 30 * time.Second, Timeout: timeout * time.Second,
} }
var response *http.Response var response *http.Response
@ -154,6 +155,7 @@ func RecordSuccess(s *types.Service) {
data := HitData{ data := HitData{
Latency: s.Latency, Latency: s.Latency,
} }
utils.Log(1, fmt.Sprintf("Service %v Successful: %0.2f ms", s.Name, data.Latency*1000))
CreateServiceHit(s, data) CreateServiceHit(s, data)
OnSuccess(s) OnSuccess(s)
} }

View File

@ -25,27 +25,27 @@ func LoadSampleData() error {
Domain: "https://google.com", Domain: "https://google.com",
ExpectedStatus: 200, ExpectedStatus: 200,
Interval: 10, Interval: 10,
Port: 0,
Type: "http", Type: "http",
Method: "GET", Method: "GET",
Timeout: 10,
} }
s2 := &types.Service{ s2 := &types.Service{
Name: "Statup Github", Name: "Statup Github",
Domain: "https://github.com/hunterlong/statup", Domain: "https://github.com/hunterlong/statup",
ExpectedStatus: 200, ExpectedStatus: 200,
Interval: 30, Interval: 30,
Port: 0,
Type: "http", Type: "http",
Method: "GET", Method: "GET",
Timeout: 20,
} }
s3 := &types.Service{ s3 := &types.Service{
Name: "JSON Users Test", Name: "JSON Users Test",
Domain: "https://jsonplaceholder.typicode.com/users", Domain: "https://jsonplaceholder.typicode.com/users",
ExpectedStatus: 200, ExpectedStatus: 200,
Interval: 60, Interval: 60,
Port: 443,
Type: "http", Type: "http",
Method: "GET", Method: "GET",
Timeout: 30,
} }
s4 := &types.Service{ s4 := &types.Service{
Name: "JSON API Tester", Name: "JSON API Tester",
@ -56,6 +56,15 @@ func LoadSampleData() error {
Type: "http", Type: "http",
Method: "POST", Method: "POST",
PostData: `{ "title": "statup", "body": "bar", "userId": 19999 }`, PostData: `{ "title": "statup", "body": "bar", "userId": 19999 }`,
Timeout: 30,
}
s5 := &types.Service{
Name: "Postgres TCP Check",
Domain: "0.0.0.0",
Interval: 20,
Type: "tcp",
Port: 5432,
Timeout: 120,
} }
id, err := CreateService(s1) id, err := CreateService(s1)
if err != nil { if err != nil {
@ -73,6 +82,10 @@ func LoadSampleData() error {
if err != nil { if err != nil {
utils.Log(3, fmt.Sprintf("Error creating Service %v: %v", id, err)) utils.Log(3, fmt.Sprintf("Error creating Service %v: %v", id, err))
} }
id, err = CreateService(s5)
if err != nil {
utils.Log(3, fmt.Sprintf("Error creating TCP Service %v: %v", id, err))
}
//checkin := &Checkin{ //checkin := &Checkin{
// Service: s2.Id, // Service: s2.Id,

View File

@ -38,6 +38,7 @@ func CreateServiceHandler(w http.ResponseWriter, r *http.Request) {
status, _ := strconv.Atoi(r.PostForm.Get("expected_status")) status, _ := strconv.Atoi(r.PostForm.Get("expected_status"))
interval, _ := strconv.Atoi(r.PostForm.Get("interval")) interval, _ := strconv.Atoi(r.PostForm.Get("interval"))
port, _ := strconv.Atoi(r.PostForm.Get("port")) port, _ := strconv.Atoi(r.PostForm.Get("port"))
timeout, _ := strconv.Atoi(r.PostForm.Get("timeout"))
checkType := r.PostForm.Get("check_type") checkType := r.PostForm.Get("check_type")
postData := r.PostForm.Get("post_data") postData := r.PostForm.Get("post_data")
@ -51,6 +52,7 @@ func CreateServiceHandler(w http.ResponseWriter, r *http.Request) {
Type: checkType, Type: checkType,
Port: port, Port: port,
PostData: postData, PostData: postData,
Timeout: timeout,
} }
_, err := core.CreateService(service) _, err := core.CreateService(service)
if err != nil { if err != nil {
@ -78,9 +80,6 @@ func ServicesDeleteHandler(w http.ResponseWriter, r *http.Request) {
func ServicesViewHandler(w http.ResponseWriter, r *http.Request) { func ServicesViewHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
serv := core.SelectService(utils.StringInt(vars["id"])) serv := core.SelectService(utils.StringInt(vars["id"]))
fmt.Println(serv.ToService())
ExecuteResponse(w, r, "service.html", serv) ExecuteResponse(w, r, "service.html", serv)
} }
@ -116,6 +115,7 @@ func ServicesUpdateHandler(w http.ResponseWriter, r *http.Request) {
status, _ := strconv.Atoi(r.PostForm.Get("expected_status")) status, _ := strconv.Atoi(r.PostForm.Get("expected_status"))
interval, _ := strconv.Atoi(r.PostForm.Get("interval")) interval, _ := strconv.Atoi(r.PostForm.Get("interval"))
port, _ := strconv.Atoi(r.PostForm.Get("port")) port, _ := strconv.Atoi(r.PostForm.Get("port"))
timeout, _ := strconv.Atoi(r.PostForm.Get("timeout"))
checkType := r.PostForm.Get("check_type") checkType := r.PostForm.Get("check_type")
postData := r.PostForm.Get("post_data") postData := r.PostForm.Get("post_data")
serviceUpdate := &types.Service{ serviceUpdate := &types.Service{
@ -129,6 +129,7 @@ func ServicesUpdateHandler(w http.ResponseWriter, r *http.Request) {
Type: checkType, Type: checkType,
Port: port, Port: port,
PostData: postData, PostData: postData,
Timeout: timeout,
} }
service = core.UpdateService(serviceUpdate) service = core.UpdateService(serviceUpdate)
ExecuteResponse(w, r, "service.html", service) ExecuteResponse(w, r, "service.html", service)

View File

@ -249,7 +249,7 @@ func RunSelectAllMysqlServices(t *testing.T) {
var err error var err error
services, err := core.SelectAllServices() services, err := core.SelectAllServices()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 4, len(services)) assert.Equal(t, 5, len(services))
} }
func RunSelectAllMysqlCommunications(t *testing.T) { func RunSelectAllMysqlCommunications(t *testing.T) {
@ -320,7 +320,7 @@ func RunSelectAllServices(t *testing.T) {
var err error var err error
services, err := core.SelectAllServices() services, err := core.SelectAllServices()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 4, len(services)) assert.Equal(t, 5, len(services))
} }
func RunOneService_Check(t *testing.T) { func RunOneService_Check(t *testing.T) {
@ -339,10 +339,11 @@ func RunService_Create(t *testing.T) {
Port: 0, Port: 0,
Type: "http", Type: "http",
Method: "GET", Method: "GET",
Timeout: 30,
} }
id, err := core.CreateService(service) id, err := core.CreateService(service)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, int64(5), id) assert.Equal(t, int64(6), id)
t.Log(service) t.Log(service)
} }
@ -379,10 +380,11 @@ func RunBadService_Create(t *testing.T) {
Port: 0, Port: 0,
Type: "http", Type: "http",
Method: "GET", Method: "GET",
Timeout: 30,
} }
id, err := core.CreateService(service) id, err := core.CreateService(service)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, int64(6), id) assert.Equal(t, int64(7), id)
} }
func RunBadService_Check(t *testing.T) { func RunBadService_Check(t *testing.T) {
@ -405,7 +407,12 @@ func RunCreateService_Hits(t *testing.T) {
assert.NotNil(t, services) assert.NotNil(t, services)
for i := 0; i <= 10; i++ { for i := 0; i <= 10; i++ {
for _, s := range services { for _, s := range services {
service := core.ServiceCheck(s.ToService()) var service *types.Service
if s.ToService().Type == "http" {
service = core.ServiceHTTPCheck(s.ToService())
} else {
service = core.ServiceTCPCheck(s.ToService())
}
assert.NotNil(t, service) assert.NotNil(t, service)
} }
} }
@ -459,7 +466,7 @@ func RunPrometheusHandler(t *testing.T) {
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
route.ServeHTTP(rr, req) route.ServeHTTP(rr, req)
t.Log(rr.Body.String()) t.Log(rr.Body.String())
assert.True(t, strings.Contains(rr.Body.String(), "statup_total_services 5")) assert.True(t, strings.Contains(rr.Body.String(), "statup_total_services 6"))
} }
func RunFailingPrometheusHandler(t *testing.T) { func RunFailingPrometheusHandler(t *testing.T) {

View File

@ -10,6 +10,26 @@ $('form').submit(function() {
$(this).find("button[type='submit']").prop('disabled',true); $(this).find("button[type='submit']").prop('disabled',true);
}); });
$('select#service_type').on('change', function() {
var selected = $('#service_type option:selected').val();
if (selected == "tcp") {
$("#service_port").parent().parent().removeClass("d-none");
$("#service_check_type").parent().parent().addClass("d-none");
$("#post_data").parent().parent().addClass("d-none");
$("#service_response").parent().parent().addClass("d-none");
$("#service_response_code").parent().parent().addClass("d-none");
} else {
$("#post_data").parent().parent().removeClass("d-none");
$("#service_response").parent().parent().removeClass("d-none");
$("#service_response_code").parent().parent().removeClass("d-none");
$("#service_check_type").parent().parent().removeClass("d-none");
$("#service_port").parent().parent().addClass("d-none");
}
});
$(".confirm-btn").on('click', function() { $(".confirm-btn").on('click', function() {
var r = confirm("Are you sure you want to delete?"); var r = confirm("Are you sure you want to delete?");

View File

@ -34,8 +34,9 @@ CREATE TABLE services (
expected_status INT(6), expected_status INT(6),
check_interval int(11), check_interval int(11),
post_data text, post_data text,
order_id integer, order_id integer default 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
timeout INT(6) DEFAULT 30,
INDEX (id) INDEX (id)
); );
CREATE TABLE hits ( CREATE TABLE hits (

View File

@ -1,3 +1,6 @@
=========================================== 1531891670
ALTER TABLE services ALTER COLUMN order_id SET DEFAULT 0;
ALTER TABLE services ADD COLUMN timeout integer DEFAULT 30;
=========================================== 1530841150 =========================================== 1530841150
ALTER TABLE core ADD COLUMN use_cdn BOOL NOT NULL DEFAULT '0'; ALTER TABLE core ADD COLUMN use_cdn BOOL NOT NULL DEFAULT '0';
=========================================== 1 =========================================== 1

View File

@ -34,7 +34,8 @@ CREATE TABLE services (
expected_status integer, expected_status integer,
check_interval integer, check_interval integer,
post_data text, post_data text,
order_id integer, order_id integer default 0,
timeout integer default 30,
created_at TIMESTAMP created_at TIMESTAMP
); );

View File

@ -1,3 +1,6 @@
=========================================== 1531891670
ALTER TABLE services ALTER COLUMN order_id SET DEFAULT 0;
ALTER TABLE services ADD COLUMN timeout integer DEFAULT 30;
=========================================== 1530841150 =========================================== 1530841150
ALTER TABLE core ADD COLUMN use_cdn bool DEFAULT FALSE; ALTER TABLE core ADD COLUMN use_cdn bool DEFAULT FALSE;
=========================================== 1 =========================================== 1

View File

@ -35,7 +35,8 @@ CREATE TABLE services (
expected_status integer, expected_status integer,
check_interval integer, check_interval integer,
post_data text, post_data text,
order_id integer, order_id integer default 0,
timeout integer default 30,
created_at DATETIME created_at DATETIME
); );

View File

@ -1,3 +1,6 @@
=========================================== 1531891670
ALTER TABLE services ALTER COLUMN order_id SET DEFAULT 0;
ALTER TABLE services ADD COLUMN timeout integer DEFAULT 30;
=========================================== 1530841150 =========================================== 1530841150
ALTER TABLE core ADD COLUMN use_cdn bool DEFAULT FALSE; ALTER TABLE core ADD COLUMN use_cdn bool DEFAULT FALSE;
=========================================== 1 =========================================== 1

View File

@ -104,7 +104,7 @@
<input type="text" name="domain" class="form-control" id="service_url" value="{{$s.Domain}}" placeholder="https://google.com" required> <input type="text" name="domain" class="form-control" id="service_url" value="{{$s.Domain}}" placeholder="https://google.com" required>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row{{if eq $s.Type "tcp"}} d-none{{end}}">
<label for="service_check_type" class="col-sm-4 col-form-label">Service Check Type</label> <label for="service_check_type" class="col-sm-4 col-form-label">Service Check Type</label>
<div class="col-sm-8"> <div class="col-sm-8">
<select name="method" class="form-control" id="service_check_type" value="{{$s.Method}}"> <select name="method" class="form-control" id="service_check_type" value="{{$s.Method}}">
@ -113,25 +113,25 @@
</select> </select>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row{{if eq $s.Type "tcp"}} d-none{{end}}">
<label for="post_data" class="col-sm-4 col-form-label">Post Data (JSON)</label> <label for="post_data" class="col-sm-4 col-form-label">Optional Post Data (JSON)</label>
<div class="col-sm-8"> <div class="col-sm-8">
<textarea name="post_data" class="form-control" id="post_data" rows="3">{{$s.PostData}}</textarea> <textarea name="post_data" class="form-control" id="post_data" rows="3">{{$s.PostData}}</textarea>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row{{if eq $s.Type "tcp"}} d-none{{end}}">
<label for="service_response" class="col-sm-4 col-form-label">Expected Response (Regex)</label> <label for="service_response" class="col-sm-4 col-form-label">Expected Response (Regex)</label>
<div class="col-sm-8"> <div class="col-sm-8">
<textarea name="expected" class="form-control" id="service_response" rows="3">{{$s.Expected}}</textarea> <textarea name="expected" class="form-control" id="service_response" rows="3">{{$s.Expected}}</textarea>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row{{if eq $s.Type "tcp"}} d-none{{end}}">
<label for="service_response_code" class="col-sm-4 col-form-label">Expected Status Code</label> <label for="service_response_code" class="col-sm-4 col-form-label">Expected Status Code</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="number" name="expected_status" class="form-control" value="{{$s.ExpectedStatus}}" id="service_response_code"> <input type="number" name="expected_status" class="form-control" value="{{$s.ExpectedStatus}}" id="service_response_code">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row{{if eq $s.Type "http"}} d-none{{end}}">
<label for="service_port" class="col-sm-4 col-form-label">TCP Port</label> <label for="service_port" class="col-sm-4 col-form-label">TCP Port</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="number" name="port" class="form-control" value="{{$s.Port}}" id="service_port" placeholder="8080"> <input type="number" name="port" class="form-control" value="{{$s.Port}}" id="service_port" placeholder="8080">
@ -143,6 +143,12 @@
<input type="number" name="interval" class="form-control" value="{{$s.Interval}}" id="service_interval" required> <input type="number" name="interval" class="form-control" value="{{$s.Interval}}" id="service_interval" required>
</div> </div>
</div> </div>
<div class="form-group row">
<label for="service_timeout" class="col-sm-4 col-form-label">Timeout in Seconds</label>
<div class="col-sm-8">
<input type="number" name="timeout" class="form-control" value="{{$s.Timeout}}" id="service_timeout" placeholder="30">
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<div class="col-6"> <div class="col-6">
<button type="submit" class="btn btn-success btn-block">Update Service</button> <button type="submit" class="btn btn-success btn-block">Update Service</button>
@ -155,7 +161,7 @@
</div> </div>
<div class="col-12 mt-4"> <div class="col-12 mt-4{{if eq $s.Type "tcp"}} d-none{{end}}">
<h3>Last Response</h3> <h3>Last Response</h3>
<textarea rows="8" class="form-control" readonly>{{ $s.LastResponse }}</textarea> <textarea rows="8" class="form-control" readonly>{{ $s.LastResponse }}</textarea>
<div class="form-group row mt-2"> <div class="form-group row mt-2">
@ -168,7 +174,7 @@
</div> </div>
<div class="col-12 mt-4"> <div class="col-12 mt-4{{if eq $s.Type "tcp"}} d-none{{end}}">
<h3>Service Checkins</h3> <h3>Service Checkins</h3>
{{ range $s.Checkins }} {{ range $s.Checkins }}
<h5>Check #{{.Id}} <span class="badge online_badge float-right">Checked in {{.Ago}}</span></h5> <h5>Check #{{.Id}} <span class="badge online_badge float-right">Checked in {{.Ago}}</span></h5>

View File

@ -97,10 +97,10 @@
<div class="form-group row"> <div class="form-group row">
<label for="service_response_code" class="col-sm-4 col-form-label">Expected Status Code</label> <label for="service_response_code" class="col-sm-4 col-form-label">Expected Status Code</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="number" name="expected_status" class="form-control" id="service_response_code" value="200"> <input type="number" name="expected_status" class="form-control" id="service_response_code" placeholder="200">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row d-none">
<label for="service_port" class="col-sm-4 col-form-label">TCP Port</label> <label for="service_port" class="col-sm-4 col-form-label">TCP Port</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="number" name="port" class="form-control" id="service_port" placeholder="8080"> <input type="number" name="port" class="form-control" id="service_port" placeholder="8080">
@ -112,6 +112,12 @@
<input type="number" name="interval" class="form-control" id="service_interval" value="60" required> <input type="number" name="interval" class="form-control" id="service_interval" value="60" required>
</div> </div>
</div> </div>
<div class="form-group row">
<label for="service_timeout" class="col-sm-4 col-form-label">Timeout in Seconds</label>
<div class="col-sm-8">
<input type="number" name="timeout" class="form-control" id="service_timeout" placeholder="30">
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<div class="col-sm-12"> <div class="col-sm-12">
<button type="submit" class="btn btn-success btn-block">Create Service</button> <button type="submit" class="btn btn-success btn-block">Create Service</button>

View File

@ -79,6 +79,8 @@ type Service struct {
PostData string `db:"post_data" json:"post_data"` PostData string `db:"post_data" json:"post_data"`
Port int `db:"port" json:"port"` Port int `db:"port" json:"port"`
CreatedAt time.Time `db:"created_at" json:"created_at"` CreatedAt time.Time `db:"created_at" json:"created_at"`
Timeout int `db:"timeout" json:"timeout"`
Order int `db:"order_id" json:"order_id"`
Online bool `json:"online"` Online bool `json:"online"`
Latency float64 `json:"latency"` Latency float64 `json:"latency"`
Online24Hours float32 `json:"24_hours_online"` Online24Hours float32 `json:"24_hours_online"`