mirror of https://github.com/statping/statping
parent
345cc25512
commit
41e35ae444
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
|||
VERSION=0.79.8
|
||||
VERSION=0.79.81
|
||||
BINARY_NAME=statup
|
||||
GOPATH:=$(GOPATH)
|
||||
GOCMD=go
|
||||
|
|
|
@ -17,6 +17,7 @@ package core
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/hunterlong/statup/core/notifier"
|
||||
"github.com/hunterlong/statup/types"
|
||||
|
@ -158,11 +159,17 @@ func (s *Service) checkHttp(record bool) *Service {
|
|||
}
|
||||
s.PingTime = dnsLookup
|
||||
t1 := time.Now()
|
||||
timeout := time.Duration(s.Timeout)
|
||||
client := http.Client{
|
||||
Timeout: timeout * time.Second,
|
||||
timeout := time.Duration(time.Duration(s.Timeout) * time.Second)
|
||||
transport := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
TLSHandshakeTimeout: timeout,
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: timeout,
|
||||
}
|
||||
|
||||
var response *http.Response
|
||||
if s.Method == "POST" {
|
||||
response, err = client.Post(s.Domain, "application/json", bytes.NewBuffer([]byte(s.PostData.String)))
|
||||
|
|
|
@ -235,7 +235,7 @@ func (db *DbConfig) Connect(retry bool, location string) error {
|
|||
err = dbSession.DB().Ping()
|
||||
if err == nil {
|
||||
DbSession = dbSession
|
||||
utils.Log(1, fmt.Sprintf("Database %v connection '%v@%v' at %v was successful.", dbType, Configs.DbUser, Configs.DbHost, Configs.DbData))
|
||||
utils.Log(1, fmt.Sprintf("Database %v connection '%v@%v:%v' at %v was successful.", dbType, Configs.DbUser, Configs.DbHost, Configs.DbPort, Configs.DbData))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -157,24 +157,24 @@ func apiServiceUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
vars := mux.Vars(r)
|
||||
service := core.SelectService(utils.StringInt(vars["id"]))
|
||||
if service == nil {
|
||||
srv := core.SelectServicer(utils.StringInt(vars["id"]))
|
||||
if srv.Select() == nil {
|
||||
sendErrorJson(errors.New("service not found"), w, r)
|
||||
return
|
||||
}
|
||||
var updatedService *types.Service
|
||||
var updatedService *core.Service
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
decoder.Decode(&updatedService)
|
||||
updatedService.Id = service.Id
|
||||
service = core.ReturnService(updatedService)
|
||||
err := service.Update(true)
|
||||
updatedService.Id = srv.Select().Id
|
||||
|
||||
err := updatedService.Update(true)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
go service.Check(true)
|
||||
go updatedService.Check(true)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(service)
|
||||
json.NewEncoder(w).Encode(updatedService)
|
||||
}
|
||||
|
||||
func apiServiceDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -125,6 +125,10 @@ func Router() *mux.Router {
|
|||
r.Handle("/api/messages/{id}", http.HandlerFunc(apiMessageUpdateHandler)).Methods("POST")
|
||||
r.Handle("/api/messages/{id}", http.HandlerFunc(apiMessageDeleteHandler)).Methods("DELETE")
|
||||
|
||||
r.PathPrefix("/files/postman.json").Handler(http.StripPrefix("/files/", http.FileServer(source.TmplBox.HTTPBox())))
|
||||
r.PathPrefix("/files/swagger.json").Handler(http.StripPrefix("/files/", http.FileServer(source.TmplBox.HTTPBox())))
|
||||
r.PathPrefix("/files/grafana.json").Handler(http.StripPrefix("/files/", http.FileServer(source.TmplBox.HTTPBox())))
|
||||
|
||||
// API Generic Routes
|
||||
r.Handle("/metrics", http.HandlerFunc(prometheusHandler))
|
||||
r.Handle("/health", http.HandlerFunc(healthCheckHandler))
|
||||
|
|
|
@ -29,13 +29,14 @@ type mobilePush struct {
|
|||
}
|
||||
|
||||
var mobile = &mobilePush{¬ifier.Notification{
|
||||
Method: "mobile",
|
||||
Title: "Mobile Notifications",
|
||||
Description: "Receive push notifications on your Android or iPhone devices using the Statup App. You can scan the Authentication QR Code found in Settings to get the mobile app setup in seconds.",
|
||||
Author: "Hunter Long",
|
||||
AuthorUrl: "https://github.com/hunterlong",
|
||||
Delay: time.Duration(5 * time.Second),
|
||||
Icon: "fas fa-mobile-alt",
|
||||
Method: "mobile",
|
||||
Title: "Mobile Notifications",
|
||||
Description: `Receive push notifications on your Android or iPhone devices using the Statup App. You can scan the Authentication QR Code found in Settings to get the mobile app setup in seconds.
|
||||
<p align="center"><a href="https://play.google.com/store/apps/details?id=com.statup"><img src="https://img.cjx.io/google-play.svg"></a> <a href="#"><img src="https://img.cjx.io/app-store-badge.svg"></a></p>`,
|
||||
Author: "Hunter Long",
|
||||
AuthorUrl: "https://github.com/hunterlong",
|
||||
Delay: time.Duration(5 * time.Second),
|
||||
Icon: "fas fa-mobile-alt",
|
||||
Form: []notifier.NotificationForm{{
|
||||
Type: "text",
|
||||
Title: "Device Identifiers",
|
||||
|
|
|
@ -158,6 +158,7 @@ func CreateAllAssets(folder string) error {
|
|||
MakePublicFolder(folder + "/assets/css")
|
||||
MakePublicFolder(folder + "/assets/scss")
|
||||
MakePublicFolder(folder + "/assets/font")
|
||||
MakePublicFolder(folder + "/assets/files")
|
||||
utils.Log(1, "Inserting scss, css, and javascript files into assets folder")
|
||||
CopyAllToPublic(FontBox, "font")
|
||||
CopyAllToPublic(ScssBox, "scss")
|
||||
|
@ -167,6 +168,9 @@ func CreateAllAssets(folder string) error {
|
|||
CopyToPublic(TmplBox, folder+"/assets", "robots.txt")
|
||||
CopyToPublic(TmplBox, folder+"/assets", "statup.png")
|
||||
CopyToPublic(TmplBox, folder+"/assets", "favicon.ico")
|
||||
CopyToPublic(TmplBox, folder+"/assets/files", "swagger.json")
|
||||
CopyToPublic(TmplBox, folder+"/assets/files", "postman.json")
|
||||
CopyToPublic(TmplBox, folder+"/assets/files", "grafana.json")
|
||||
utils.Log(1, "Compiling CSS from SCSS style...")
|
||||
err := CompileSASS(utils.Directory)
|
||||
utils.Log(1, "Statup assets have been inserted")
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<div class="form-group row">
|
||||
<label for="service_type" class="col-sm-4 col-form-label">Service Type</label>
|
||||
<div class="col-sm-8">
|
||||
<select name="check_type" class="form-control" id="service_type" value="{{.Type}}" {{if ne .Type ""}}readonly{{end}}>
|
||||
<select name="type" class="form-control" id="service_type" value="{{.Type}}" {{if ne .Type ""}}readonly{{end}}>
|
||||
<option value="http" {{if eq .Type "http"}}selected{{end}}>HTTP Service</option>
|
||||
<option value="tcp" {{if eq .Type "tcp"}}selected{{end}}>TCP Service</option>
|
||||
<option value="udp" {{if eq .Type "udp"}}selected{{end}}>UDP Service</option>
|
||||
|
@ -70,9 +70,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="interval" class="col-sm-4 col-form-label">Check Interval (Seconds)</label>
|
||||
<label for="service_interval" class="col-sm-4 col-form-label">Check Interval (Seconds)</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" name="interval" class="form-control" value="{{if ne .Interval 0}}{{.Interval}}{{else}}60{{end}}" min="1" id="service_interval" required>
|
||||
<input type="number" name="check_interval" class="form-control" value="{{if ne .Interval 0}}{{.Interval}}{{else}}60{{end}}" min="1" id="service_interval" required>
|
||||
<small id="interval" class="form-text text-muted">10,000+ will be checked in Microseconds (1 millisecond = 1000 microseconds).</small>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,583 @@
|
|||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": 16,
|
||||
"iteration": 1542323708843,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"colorBackground": false,
|
||||
"colorValue": true,
|
||||
"colors": [
|
||||
"#890f02",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgb(72, 198, 35)"
|
||||
],
|
||||
"datasource": null,
|
||||
"format": "locale",
|
||||
"gauge": {
|
||||
"maxValue": 1,
|
||||
"minValue": 0,
|
||||
"show": false,
|
||||
"thresholdLabels": false,
|
||||
"thresholdMarkers": true
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 2,
|
||||
"w": 5,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 6,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"mappingType": 1,
|
||||
"mappingTypes": [
|
||||
{
|
||||
"name": "value to text",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"name": "range to text",
|
||||
"value": 2
|
||||
}
|
||||
],
|
||||
"maxDataPoints": 100,
|
||||
"nullPointMode": "connected",
|
||||
"nullText": null,
|
||||
"postfix": "",
|
||||
"postfixFontSize": "50%",
|
||||
"prefix": "",
|
||||
"prefixFontSize": "50%",
|
||||
"rangeMaps": [
|
||||
{
|
||||
"from": "null",
|
||||
"text": "N/A",
|
||||
"to": "null"
|
||||
}
|
||||
],
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": false
|
||||
},
|
||||
"tableColumn": "",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "statup_service_online{name=\"${service}\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": "0,1",
|
||||
"title": "",
|
||||
"transparent": true,
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "120%",
|
||||
"valueMaps": [
|
||||
{
|
||||
"op": "=",
|
||||
"text": "ONLINE",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"op": "=",
|
||||
"text": "OFFLINE",
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
"valueName": "current"
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"fill": 1,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 19,
|
||||
"x": 5,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": false,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "statup_service_latency{name=\"${service}\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "{{name}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "${service} Latency",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "ms",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"colorBackground": false,
|
||||
"colorValue": false,
|
||||
"colors": [
|
||||
"#299c46",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"#890f02"
|
||||
],
|
||||
"datasource": null,
|
||||
"decimals": 0,
|
||||
"format": "ms",
|
||||
"gauge": {
|
||||
"maxValue": 500,
|
||||
"minValue": 1,
|
||||
"show": true,
|
||||
"thresholdLabels": true,
|
||||
"thresholdMarkers": true
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 5,
|
||||
"x": 0,
|
||||
"y": 2
|
||||
},
|
||||
"id": 7,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"mappingType": 1,
|
||||
"mappingTypes": [
|
||||
{
|
||||
"name": "value to text",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"name": "range to text",
|
||||
"value": 2
|
||||
}
|
||||
],
|
||||
"maxDataPoints": 100,
|
||||
"nullPointMode": "connected",
|
||||
"nullText": null,
|
||||
"postfix": "",
|
||||
"postfixFontSize": "50%",
|
||||
"prefix": "",
|
||||
"prefixFontSize": "50%",
|
||||
"rangeMaps": [
|
||||
{
|
||||
"from": "null",
|
||||
"text": "N/A",
|
||||
"to": "null"
|
||||
}
|
||||
],
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": false
|
||||
},
|
||||
"tableColumn": "",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "statup_service_latency{name=\"${service}\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": "250,400",
|
||||
"title": "",
|
||||
"transparent": true,
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "50%",
|
||||
"valueMaps": [
|
||||
{
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"valueName": "current"
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"fill": 1,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 19,
|
||||
"x": 5,
|
||||
"y": 8
|
||||
},
|
||||
"id": 8,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": false,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "statup_service_response_length{name=\"${service}\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "{{name}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "${service} Response Size",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"colorBackground": false,
|
||||
"colorValue": false,
|
||||
"colors": [
|
||||
"#299c46",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"#d44a3a"
|
||||
],
|
||||
"datasource": null,
|
||||
"format": "locale",
|
||||
"gauge": {
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"show": false,
|
||||
"thresholdLabels": false,
|
||||
"thresholdMarkers": true
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 3,
|
||||
"w": 5,
|
||||
"x": 0,
|
||||
"y": 9
|
||||
},
|
||||
"id": 5,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"mappingType": 1,
|
||||
"mappingTypes": [
|
||||
{
|
||||
"name": "value to text",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"name": "range to text",
|
||||
"value": 2
|
||||
}
|
||||
],
|
||||
"maxDataPoints": 100,
|
||||
"nullPointMode": "connected",
|
||||
"nullText": null,
|
||||
"postfix": "",
|
||||
"postfixFontSize": "50%",
|
||||
"prefix": "",
|
||||
"prefixFontSize": "50%",
|
||||
"rangeMaps": [
|
||||
{
|
||||
"from": "null",
|
||||
"text": "N/A",
|
||||
"to": "null"
|
||||
}
|
||||
],
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": false
|
||||
},
|
||||
"tableColumn": "",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "statup_service_status_code{name=\"${service}\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Response Status Code",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "120%",
|
||||
"valueMaps": [
|
||||
{
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"valueName": "current"
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"colorBackground": false,
|
||||
"colorValue": false,
|
||||
"colors": [
|
||||
"#299c46",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"#d44a3a"
|
||||
],
|
||||
"datasource": null,
|
||||
"format": "bytes",
|
||||
"gauge": {
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"show": false,
|
||||
"thresholdLabels": false,
|
||||
"thresholdMarkers": true
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 3,
|
||||
"w": 5,
|
||||
"x": 0,
|
||||
"y": 12
|
||||
},
|
||||
"id": 4,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"mappingType": 1,
|
||||
"mappingTypes": [
|
||||
{
|
||||
"name": "value to text",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"name": "range to text",
|
||||
"value": 2
|
||||
}
|
||||
],
|
||||
"maxDataPoints": 100,
|
||||
"nullPointMode": "connected",
|
||||
"nullText": null,
|
||||
"postfix": "",
|
||||
"postfixFontSize": "50%",
|
||||
"prefix": "",
|
||||
"prefixFontSize": "50%",
|
||||
"rangeMaps": [
|
||||
{
|
||||
"from": "null",
|
||||
"text": "N/A",
|
||||
"to": "null"
|
||||
}
|
||||
],
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": false
|
||||
},
|
||||
"tableColumn": "",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "statup_service_response_length{name=\"${service}\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Response Size",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "80%",
|
||||
"valueMaps": [
|
||||
{
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"valueName": "current"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 16,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allValue": null,
|
||||
"current": {
|
||||
"text": "SQLite Statup",
|
||||
"value": "SQLite Statup"
|
||||
},
|
||||
"datasource": "prometheus",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "service",
|
||||
"multi": false,
|
||||
"name": "service",
|
||||
"options": [],
|
||||
"query": "label_values(statup_service_latency, name)",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 0,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "",
|
||||
"title": "Statup",
|
||||
"uid": "6BzRjddmz",
|
||||
"version": 25
|
||||
}
|
|
@ -7,17 +7,38 @@ Statup is an easy to use Status Page monitor for your websites and applications.
|
|||
<a href="https://github.com/hunterlong/statup"><img src="https://img.shields.io/github/release/hunterlong/statup.svg"></a>
|
||||
</p>
|
||||
|
||||
# Services
|
||||
# Core Elements
|
||||
Statup is continuing being updated and has many awesome features to help you catch issues if your servers go down.
|
||||
|
||||
## Services
|
||||
For each website and application you want to add a new Service. Each Service will require a URL endpoint to test your applications status.
|
||||
You can also add expected HTTP responses (regex allow), expected HTTP response codes, and other fields to make sure your service is online or offline.
|
||||
|
||||
# Statup Settings
|
||||
You can change multiple settings in your Statup instance.
|
||||
## Settings
|
||||
Changing variables for your Statup instance is fairly simple and quick. You can change the footer HTML/text, domain of server, and many other aspects.
|
||||
The guide below will explain each setting feature.
|
||||
|
||||
# Users
|
||||
Users can access the Statup Dashboard to add, remove, and view services.
|
||||
#### Export Assets
|
||||
The single Statup binary file includes all assets used for the web page. Go the the Theme Editor in Settings and click Enable Assets.
|
||||
This will create a 'assets' folder in the working directory, it will create all the assets used into their own folders.
|
||||
|
||||
# Plugins
|
||||
#### Custom Design
|
||||
After you've exported the assets you can edit the CSS directly or use the Theme Editor to customize the SASS design.
|
||||
Statup uses sass to generate CSS files from SASS. You can install sass with a command below.
|
||||
|
||||
- node: `npm install sass -g`
|
||||
- ruby: `gem install sass`
|
||||
|
||||
#### CDN Assets
|
||||
If you want to host the Statup assets from our CDN rather than from your local instance, enable "Use CDN" toggle switch on the Settings page.
|
||||
|
||||
## Notifications
|
||||
Statup includes a few notification methods to receive alerts when a service is online/offline. Each notifier is different, users can create your own notifier and send a Push Request to github.
|
||||
|
||||
## Users
|
||||
Administrators can add, update, and remove all elements on your Statup instance. Other users can only view the status page and
|
||||
|
||||
## Plugins
|
||||
Creating a plugin for Statup is not that difficult, if you know a little bit of Go Language you can create any type of application to be embedded into the Status framework.
|
||||
Checkout the example plugin that includes all the interfaces, information, and custom HTTP routing at <a href="https://github.com/hunterlong/statup_plugin">https://github.com/hunterlong/statup_plugin</a>.
|
||||
Anytime there is an action on your status page, all of your plugins will be notified of the change with the values that were changed or created.
|
||||
|
@ -25,260 +46,30 @@ Anytime there is an action on your status page, all of your plugins will be noti
|
|||
Using the statup/plugin Golang package you can quickly implement the event listeners. Statup uses <a href="https://github.com/upper/db">upper.io/db.v3</a> for the database connection.
|
||||
You can use the database inside of your plugin to create, update, and destroy tables/data. <b>Please only use respectable plugins!</b>
|
||||
|
||||
# Custom Stlying
|
||||
On Statup Status Page server can you create your own custom stylesheet to be rendered on the index view of your status page. Go to <a href="/settings">Settings</a> and click on Custom Styling.
|
||||
|
||||
# API Endpoints
|
||||
# API Usage
|
||||
Statup includes a RESTFUL API so you can view, update, and edit your services with easy to use routes. You can currently view, update and delete services, view, create, update users, and get detailed information about the Statup instance. To make life easy, try out a Postman or Swagger JSON file and use it on your Statup Server.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/hunterlong/statup/blob/master/dev/postman.json">Postman JSON Export</a> | <a href="https://github.com/hunterlong/statup/blob/master/dev/swagger.json">Swagger Export</a>
|
||||
<a href="/files/postman.json">Postman Export</a> | <a href="/files/swagger.json">Swagger Export</a> | <a href="https://app.swaggerhub.com/apis/statup/statup/1">Swagger Hub</a>
|
||||
</p>
|
||||
|
||||
## Authentication
|
||||
### API Authentication
|
||||
Authentication uses the Statup API Secret to accept remote requests. You can find the API Secret in the Settings page of your Statup server. To send requests to your Statup API, include a Authorization Header when you send the request. The API will accept any one of the headers below.
|
||||
|
||||
- HTTP Header: `Authorization: API SECRET HERE`
|
||||
- HTTP Header: `Authorization: Bearer API SECRET HERE`
|
||||
|
||||
## Main Route `/api`
|
||||
The main API route will show you all services and failures along with them.
|
||||
|
||||
## Services
|
||||
The services API endpoint will show you detailed information about services and will allow you to edit/delete services with POST/DELETE http methods.
|
||||
|
||||
### Viewing All Services
|
||||
- Endpoint: `/api/services`
|
||||
- Method: `GET`
|
||||
- Response: Array of [Services](https://github.com/hunterlong/statup/wiki/API#service-response)
|
||||
- Response Type: `application/json`
|
||||
- Request Type: `application/json`
|
||||
|
||||
### Viewing Service
|
||||
- Endpoint: `/api/services/{id}`
|
||||
- Method: `GET`
|
||||
- Response: [Service](https://github.com/hunterlong/statup/wiki/API#service-response)
|
||||
- Response Type: `application/json`
|
||||
- Request Type: `application/json`
|
||||
|
||||
### Updating Service
|
||||
- Endpoint: `/api/services/{id}`
|
||||
- Method: `POST`
|
||||
- Response: [Service](https://github.com/hunterlong/statup/wiki/API#service-response)
|
||||
- Response Type: `application/json`
|
||||
- Request Type: `application/json`
|
||||
|
||||
POST Data:
|
||||
``` json
|
||||
{
|
||||
"name": "Updated Service",
|
||||
"domain": "https://google.com",
|
||||
"expected": "",
|
||||
"expected_status": 200,
|
||||
"check_interval": 15,
|
||||
"type": "http",
|
||||
"method": "GET",
|
||||
"post_data": "",
|
||||
"port": 0,
|
||||
"timeout": 10,
|
||||
"order_id": 0
|
||||
}
|
||||
```
|
||||
|
||||
### Deleting Service
|
||||
- Endpoint: `/api/services/{id}`
|
||||
- Method: `DELETE`
|
||||
- Response: [Object Response](https://github.com/hunterlong/statup/wiki/API#object-response)
|
||||
- Response Type: `application/json`
|
||||
- Request Type: `application/json`
|
||||
|
||||
Response:
|
||||
``` json
|
||||
{
|
||||
"status": "success",
|
||||
"id": 4,
|
||||
"type": "service",
|
||||
"method": "delete"
|
||||
}
|
||||
```
|
||||
|
||||
## Users
|
||||
The users API endpoint will show you users that are registered inside your Statup instance.
|
||||
|
||||
### View All Users
|
||||
- Endpoint: `/api/users`
|
||||
- Method: `GET`
|
||||
- Response: Array of [Users](https://github.com/hunterlong/statup/wiki/API#user-response)
|
||||
- Response Type: `application/json`
|
||||
- Request Type: `application/json`
|
||||
|
||||
### Viewing User
|
||||
- Endpoint: `/api/users/{id}`
|
||||
- Method: `GET`
|
||||
- Response: [User](https://github.com/hunterlong/statup/wiki/API#user-response)
|
||||
- Response Type: `application/json`
|
||||
- Request Type: `application/json`
|
||||
|
||||
### Creating New User
|
||||
- Endpoint: `/api/users`
|
||||
- Method: `POST`
|
||||
- Response: [User](https://github.com/hunterlong/statup/wiki/API#user-response)
|
||||
- Response Type: `application/json`
|
||||
- Request Type: `application/json`
|
||||
|
||||
POST Data:
|
||||
``` json
|
||||
{
|
||||
"username": "newadmin",
|
||||
"email": "info@email.com",
|
||||
"password": "password123",
|
||||
"admin": true
|
||||
}
|
||||
```
|
||||
|
||||
### Updating User
|
||||
- Endpoint: `/api/users/{id}`
|
||||
- Method: `POST`
|
||||
- Response: [User](https://github.com/hunterlong/statup/wiki/API#user-response)
|
||||
- Response Type: `application/json`
|
||||
- Request Type: `application/json`
|
||||
|
||||
POST Data:
|
||||
``` json
|
||||
{
|
||||
"username": "updatedadmin",
|
||||
"email": "info@email.com",
|
||||
"password": "password123",
|
||||
"admin": true
|
||||
}
|
||||
```
|
||||
|
||||
### Deleting User
|
||||
- Endpoint: `/api/services/{id}`
|
||||
- Method: `DELETE`
|
||||
- Response: [Object Response](https://github.com/hunterlong/statup/wiki/API#object-response)
|
||||
- Response Type: `application/json`
|
||||
- Request Type: `application/json`
|
||||
|
||||
Response:
|
||||
``` json
|
||||
{
|
||||
"status": "success",
|
||||
"id": 3,
|
||||
"type": "user",
|
||||
"method": "delete"
|
||||
}
|
||||
```
|
||||
|
||||
# Service Response
|
||||
``` json
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Test Service 0",
|
||||
"domain": "https://status.coinapp.io",
|
||||
"expected": "",
|
||||
"expected_status": 200,
|
||||
"check_interval": 1,
|
||||
"type": "http",
|
||||
"method": "GET",
|
||||
"post_data": "",
|
||||
"port": 0,
|
||||
"timeout": 30,
|
||||
"order_id": 0,
|
||||
"created_at": "2018-09-12T09:07:03.045832088-07:00",
|
||||
"updated_at": "2018-09-12T09:07:03.046114305-07:00",
|
||||
"online": false,
|
||||
"latency": 0.031411064,
|
||||
"24_hours_online": 0,
|
||||
"avg_response": "",
|
||||
"status_code": 502,
|
||||
"last_online": "0001-01-01T00:00:00Z",
|
||||
"dns_lookup_time": 0.001727175,
|
||||
"failures": [
|
||||
{
|
||||
"id": 5187,
|
||||
"issue": "HTTP Status Code 502 did not match 200",
|
||||
"created_at": "2018-09-12T10:41:46.292277471-07:00"
|
||||
},
|
||||
{
|
||||
"id": 5188,
|
||||
"issue": "HTTP Status Code 502 did not match 200",
|
||||
"created_at": "2018-09-12T10:41:47.337659862-07:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
# User Response
|
||||
``` json
|
||||
{
|
||||
"id": 1,
|
||||
"username": "admin",
|
||||
"api_key": "02f324450a631980121e8fd6ea7dfe4a7c685a2f",
|
||||
"admin": true,
|
||||
"created_at": "2018-09-12T09:06:53.906398511-07:00",
|
||||
"updated_at": "2018-09-12T09:06:54.972440207-07:00"
|
||||
}
|
||||
```
|
||||
|
||||
# Object Response
|
||||
``` json
|
||||
{
|
||||
"type": "service",
|
||||
"id": 19,
|
||||
"method": "delete",
|
||||
"status": "success"
|
||||
}
|
||||
```
|
||||
|
||||
# Main API Response
|
||||
``` json
|
||||
{
|
||||
"name": "Awesome Status",
|
||||
"description": "An awesome status page by Statup",
|
||||
"footer": "This is my custom footer",
|
||||
"domain": "https://demo.statup.io",
|
||||
"version": "v0.56",
|
||||
"migration_id": 1536768413,
|
||||
"created_at": "2018-09-12T09:06:53.905374829-07:00",
|
||||
"updated_at": "2018-09-12T09:07:01.654201225-07:00",
|
||||
"database": "sqlite",
|
||||
"started_on": "2018-09-12T10:43:07.760729349-07:00",
|
||||
"services": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Google",
|
||||
"domain": "https://google.com",
|
||||
"expected": "",
|
||||
"expected_status": 200,
|
||||
"check_interval": 10,
|
||||
"type": "http",
|
||||
"method": "GET",
|
||||
"post_data": "",
|
||||
"port": 0,
|
||||
"timeout": 10,
|
||||
"order_id": 0,
|
||||
"created_at": "2018-09-12T09:06:54.97549122-07:00",
|
||||
"updated_at": "2018-09-12T09:06:54.975624103-07:00",
|
||||
"online": true,
|
||||
"latency": 0.09080986,
|
||||
"24_hours_online": 0,
|
||||
"avg_response": "",
|
||||
"status_code": 200,
|
||||
"last_online": "2018-09-12T10:44:07.931990439-07:00",
|
||||
"dns_lookup_time": 0.005543935
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
# Prometheus Exporter
|
||||
Statup includes a prometheus exporter so you can have even more monitoring power with your services. The prometheus exporter can be seen on `/metrics`, simply create another exporter in your prometheus config. Use your Statup API Secret for the Authorization Bearer header, the `/metrics` URL is dedicated for Prometheus and requires the correct API Secret has `Authorization` header.
|
||||
|
||||
# Grafana Dashboard
|
||||
Statup has a [Grafana Dashboard](https://grafana.com/dashboards/6950) that you can quickly implement if you've added your Statup service to Prometheus. Import Dashboard ID: `6950` into your Grafana dashboard and watch the metrics come in!
|
||||
Statup has a Grafana Dashboard that you can quickly implement if you've added your Statup service to Prometheus. Import Dashboard ID: `6950` into your Grafana dashboard and watch the metrics come in!
|
||||
|
||||
<p align="center"><img width="80%" src="https://img.cjx.io/statupgrafana.png"></p>
|
||||
<p align="center">
|
||||
<a href="https://grafana.com/dashboards/6950">Grafana Dashboard</a> | <a href="/files/grafana.json">Grafana JSON Export</a>
|
||||
<br>
|
||||
<img width="80%" src="https://img.cjx.io/statupgrafana.png">
|
||||
</p>
|
||||
|
||||
## Basic Prometheus Exporter
|
||||
If you have Statup and the Prometheus server in the same Docker network, you can use the yaml config below.
|
||||
|
@ -341,7 +132,7 @@ It may be useful to load your environment using a `.env` file in the root direct
|
|||
|
||||
If you have the `DB_CONN` environment variable set Statup will bypass all values in config.yml and will require you to have the other DB_* variables in place. You can pass in these environment variables without requiring a .env file.
|
||||
|
||||
## `.env` File
|
||||
### `.env` File
|
||||
```bash
|
||||
DB_CONN=postgres
|
||||
DB_HOST=0.0.0.0
|
||||
|
@ -397,7 +188,7 @@ make cypress-install
|
|||
make cypress-test
|
||||
```
|
||||
|
||||
## Testing
|
||||
# Testing
|
||||
* If you want to test your updates with the current golang testing units, you can follow the guide below to run a full test process. Each test for Statup will run in MySQL, Postgres, and SQlite to make sure all database types work correctly.
|
||||
|
||||
## Create Docker Databases
|
||||
|
|
|
@ -23,10 +23,10 @@ import (
|
|||
type User struct {
|
||||
Id int64 `gorm:"primary_key;column:id" json:"id"`
|
||||
Username string `gorm:"type:varchar(100);unique;column:username;" json:"username,omitempty"`
|
||||
Password string `gorm:"column:password" json:"password,omitempty"`
|
||||
Password string `gorm:"column:password" json:"-"`
|
||||
Email string `gorm:"type:varchar(100);unique;column:email" json:"email,omitempty"`
|
||||
ApiKey string `gorm:"column:api_key" json:"api_key,omitempty"`
|
||||
ApiSecret string `gorm:"column:api_secret" json:"-"`
|
||||
ApiSecret string `gorm:"column:api_secret" json:"api_secret,omitempty"`
|
||||
Admin NullBool `gorm:"column:administrator" json:"admin,omitempty"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||
|
|
Loading…
Reference in New Issue