mirror of https://github.com/statping/statping
db changes
parent
d9e47e6d3d
commit
c92f99a455
|
@ -4,20 +4,20 @@ about: If you're having an issue or see an error
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Describe the bug**
|
### Describe the bug
|
||||||
Try to explain what issue your'e having in detail. You can copy and paste the issue from the log file in your root directory `/logs/statup.log`.
|
Try to explain what issue your'e having in detail. You can copy and paste the issue from the log file in your root directory `/logs/statup.log`.
|
||||||
|
|
||||||
**To Reproduce**
|
### To Reproduce
|
||||||
Steps to reproduce the behavior:
|
Steps to reproduce the behavior:
|
||||||
1. I'm using version: '...'
|
1. I'm using version: '...'
|
||||||
2. I went to '....'
|
2. I went to '....'
|
||||||
3. Press this button '....'
|
3. Press this button '....'
|
||||||
4. And things did '....'
|
4. And things did '....'
|
||||||
|
|
||||||
**Expected Behavior**
|
### Expected Behavior
|
||||||
A clear and concise description of what you expected to happen.
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
**Screenshots**
|
### Screenshots
|
||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
[](https://gitter.im/statup-app/general) [](https://github.com/hunterlong/statping/releases/latest) [](https://travis-ci.com/hunterlong/statup)
|
[](https://slack.statping.com/) [](https://github.com/hunterlong/statping/releases/latest) [](https://travis-ci.com/hunterlong/statping)
|
||||||
|
|
|
@ -4,19 +4,19 @@ about: Suggest a feature and let's see what others say
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**What would you like on Statping?**
|
### What would you like on Statping?
|
||||||
A clear and concise description of what you want to happen.
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
### Describe the solution you'd like
|
||||||
A clear and concise description of what you want to happen.
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
### Describe alternatives you've considered
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
### Is your feature request related to a problem? Please describe.
|
||||||
I'm always frustrated when [...]
|
I'm always frustrated when [...]
|
||||||
|
|
||||||
**Additional context**
|
### Additional context
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|
||||||
[](https://gitter.im/statup-app/general) [](https://github.com/hunterlong/statping/releases/latest) [](https://travis-ci.com/hunterlong/statup)
|
[](https://slack.statping.com/) [](https://github.com/hunterlong/statping/releases/latest) [](https://travis-ci.com/hunterlong/statping)
|
||||||
|
|
|
@ -4,20 +4,20 @@ about: If you're having an issue or see an error
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Describe the bug**
|
### Describe the bug
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
**To Reproduce**
|
### To Reproduce
|
||||||
Steps to reproduce the behavior:
|
Steps to reproduce the behavior:
|
||||||
1. Go to '...'
|
1. Go to '...'
|
||||||
2. Click on '....'
|
2. Click on '....'
|
||||||
3. Scroll down to '....'
|
3. Scroll down to '....'
|
||||||
4. See error
|
4. See error
|
||||||
|
|
||||||
**Expected behavior**
|
### Expected behavior
|
||||||
A clear and concise description of what you expected to happen.
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
**Screenshots**
|
### Screenshots
|
||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
[](https://gitter.im/statup-app/general) [](https://github.com/hunterlong/statping/releases/latest) [](https://travis-ci.com/hunterlong/statup)
|
[](https://gitter.im/statup-app/general) [](https://github.com/hunterlong/statping/releases/latest) [](https://travis-ci.com/hunterlong/statup)
|
||||||
|
|
42
Dockerfile
42
Dockerfile
|
@ -1,16 +1,43 @@
|
||||||
FROM hunterlong/statping:base as base
|
FROM node:10.17.0 AS frontend
|
||||||
|
RUN npm install yarn -g
|
||||||
|
WORKDIR /statping
|
||||||
|
COPY ./frontend/package.json .
|
||||||
|
COPY ./frontend/yarn.lock .
|
||||||
|
RUN yarn install
|
||||||
|
COPY ./frontend .
|
||||||
|
RUN yarn build && rm -rf node_modules
|
||||||
|
|
||||||
FROM alpine:latest
|
# Statping Golang BACKEND building from source
|
||||||
|
# Creates "/go/bin/statping" and "/usr/local/bin/sass" for copying
|
||||||
|
FROM golang:1.14-alpine AS backend
|
||||||
LABEL maintainer="Hunter Long (https://github.com/hunterlong)"
|
LABEL maintainer="Hunter Long (https://github.com/hunterlong)"
|
||||||
COPY --from=base /usr/local/bin/sass /usr/local/bin/sass
|
|
||||||
COPY --from=base /go/bin/statping /usr/local/bin/statping
|
|
||||||
|
|
||||||
ARG VERSION
|
ARG VERSION
|
||||||
|
RUN apk add --update --no-cache libstdc++ gcc g++ make git ca-certificates linux-headers wget curl jq
|
||||||
|
RUN curl -L -s https://assets.statping.com/sass -o /usr/local/bin/sass && \
|
||||||
|
chmod +x /usr/local/bin/sass
|
||||||
|
WORKDIR /go/src/github.com/hunterlong/statping
|
||||||
|
ADD go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
ENV GO111MODULE on
|
||||||
|
RUN go get github.com/stretchr/testify/assert && \
|
||||||
|
go get github.com/stretchr/testify/require && \
|
||||||
|
go get github.com/GeertJohan/go.rice/rice && \
|
||||||
|
go get github.com/cortesi/modd/cmd/modd && \
|
||||||
|
go get github.com/crazy-max/xgo
|
||||||
|
COPY . .
|
||||||
|
COPY --from=frontend /statping/dist ./source/
|
||||||
|
RUN make clean generate embed build
|
||||||
|
RUN chmod a+x statping && mv statping /go/bin/statping
|
||||||
|
|
||||||
RUN apk --no-cache add curl jq
|
# Statping main Docker image that contains all required libraries
|
||||||
|
FROM alpine:latest
|
||||||
|
RUN apk --no-cache add libgcc libstdc++ curl jq
|
||||||
|
|
||||||
|
COPY --from=backend /go/bin/statping /usr/local/bin/
|
||||||
|
COPY --from=backend /usr/local/bin/sass /usr/local/bin/
|
||||||
|
COPY --from=backend /usr/local/share/ca-certificates /usr/local/share/
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
VOLUME /app
|
|
||||||
|
|
||||||
ENV IS_DOCKER=true
|
ENV IS_DOCKER=true
|
||||||
ENV STATPING_DIR=/app
|
ENV STATPING_DIR=/app
|
||||||
|
@ -21,3 +48,4 @@ EXPOSE $PORT
|
||||||
HEALTHCHECK --interval=60s --timeout=10s --retries=3 CMD curl -s "http://localhost:$PORT/health" | jq -r -e ".online==true"
|
HEALTHCHECK --interval=60s --timeout=10s --retries=3 CMD curl -s "http://localhost:$PORT/health" | jq -r -e ".online==true"
|
||||||
|
|
||||||
CMD statping -port $PORT
|
CMD statping -port $PORT
|
||||||
|
|
||||||
|
|
11
Makefile
11
Makefile
|
@ -80,15 +80,20 @@ top:
|
||||||
docker-compose -f docker-compose.yml -f dev/docker-compose.full.yml top
|
docker-compose -f docker-compose.yml -f dev/docker-compose.full.yml top
|
||||||
|
|
||||||
frontend-build:
|
frontend-build:
|
||||||
cd frontend && rm -rf dist && yarn build
|
rm -rf source/dist && rm -rf frontend/dist
|
||||||
rm -rf source/dist && cp -r frontend/dist source/ && cp -r frontend/src/assets/scss source/dist/
|
cd frontend && yarn build
|
||||||
|
cp -r frontend/dist source/ && cp -r frontend/src/assets/scss source/dist/
|
||||||
cp -r source/tmpl/*.* source/dist/
|
cp -r source/tmpl/*.* source/dist/
|
||||||
|
|
||||||
# compile assets using SASS and Rice. compiles scss -> css, and run rice embed-go
|
# compile assets using SASS and Rice. compiles scss -> css, and run rice embed-go
|
||||||
compile: generate frontend-build
|
compile: generate frontend-build
|
||||||
|
rm -f source/rice-box.go
|
||||||
cd source && rice embed-go
|
cd source && rice embed-go
|
||||||
|
|
||||||
build: clean
|
embed:
|
||||||
|
cd source && rice embed-go
|
||||||
|
|
||||||
|
build:
|
||||||
$(GOBUILD) $(BUILDVERSION) -o $(BINARY_NAME) ./cmd
|
$(GOBUILD) $(BUILDVERSION) -o $(BINARY_NAME) ./cmd
|
||||||
|
|
||||||
install: build
|
install: build
|
||||||
|
|
|
@ -106,7 +106,7 @@ func catchCLI(args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = configs.ConnectConfigs(config); err != nil {
|
if err = configs.ConnectConfigs(config, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if data, err = handlers.ExportSettings(); err != nil {
|
if data, err = handlers.ExportSettings(); err != nil {
|
||||||
|
@ -206,7 +206,7 @@ func runOnce() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "config.yml file not found")
|
return errors.Wrap(err, "config.yml file not found")
|
||||||
}
|
}
|
||||||
err = configs.ConnectConfigs(config)
|
err = configs.ConnectConfigs(config, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "issue connecting to database")
|
return errors.Wrap(err, "issue connecting to database")
|
||||||
}
|
}
|
||||||
|
|
22
cmd/main.go
22
cmd/main.go
|
@ -16,20 +16,21 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/hunterlong/statping/source"
|
||||||
|
|
||||||
"github.com/hunterlong/statping/database"
|
"github.com/hunterlong/statping/database"
|
||||||
|
"github.com/hunterlong/statping/handlers"
|
||||||
"github.com/hunterlong/statping/types/configs"
|
"github.com/hunterlong/statping/types/configs"
|
||||||
"github.com/hunterlong/statping/types/core"
|
"github.com/hunterlong/statping/types/core"
|
||||||
"github.com/hunterlong/statping/types/services"
|
"github.com/hunterlong/statping/types/services"
|
||||||
"github.com/hunterlong/statping/utils"
|
"github.com/hunterlong/statping/utils"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"github.com/hunterlong/statping/handlers"
|
|
||||||
"github.com/hunterlong/statping/source"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -113,7 +114,7 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = configs.ConnectConfigs(c); err != nil {
|
if err = configs.ConnectConfigs(c, true); err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,8 +140,9 @@ func SetupMode() error {
|
||||||
// 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, syscall.SIGKILL)
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||||
<-sigs
|
<-sigs
|
||||||
|
fmt.Println("Shutting down Statping")
|
||||||
Close()
|
Close()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -498,5 +498,5 @@ func (it *Db) Between(t1 time.Time, t2 time.Time) Database {
|
||||||
|
|
||||||
type TimeValue struct {
|
type TimeValue struct {
|
||||||
Timeframe string `json:"timeframe"`
|
Timeframe string `json:"timeframe"`
|
||||||
Amount float64 `json:"amount"`
|
Amount int64 `json:"amount"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,37 +68,13 @@ func (t *TimeVar) ToValues() ([]*TimeValue, error) {
|
||||||
return t.data, nil
|
return t.data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GroupQuery) toFloatRows() []*TimeValue {
|
|
||||||
rows, err := g.db.Rows()
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var data []*TimeValue
|
|
||||||
for rows.Next() {
|
|
||||||
var timeframe time.Time
|
|
||||||
amount := float64(0)
|
|
||||||
if err := rows.Scan(&timeframe, &amount); err != nil {
|
|
||||||
log.Errorln(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("float rows: ", timeframe, amount)
|
|
||||||
|
|
||||||
newTs := types.FixedTime(timeframe, g.Group)
|
|
||||||
data = append(data, &TimeValue{
|
|
||||||
Timeframe: newTs,
|
|
||||||
Amount: amount,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// GraphData will return all hits or failures
|
// GraphData will return all hits or failures
|
||||||
func (g *GroupQuery) GraphData(by By) ([]*TimeValue, error) {
|
func (g *GroupQuery) GraphData(by By) ([]*TimeValue, error) {
|
||||||
|
|
||||||
dbQuery := g.db.MultipleSelects(
|
dbQuery := g.db.MultipleSelects(
|
||||||
g.db.SelectByTime(g.Group),
|
g.db.SelectByTime(g.Group),
|
||||||
by.String(),
|
by.String(),
|
||||||
).Group("timeframe").Debug()
|
).Group("timeframe")
|
||||||
|
|
||||||
g.db = dbQuery
|
g.db = dbQuery
|
||||||
|
|
||||||
|
@ -121,7 +97,7 @@ func (g *GroupQuery) ToTimeValue() (*TimeVar, error) {
|
||||||
var data []*TimeValue
|
var data []*TimeValue
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var timeframe string
|
var timeframe string
|
||||||
amount := float64(0)
|
amount := int64(0)
|
||||||
if err := rows.Scan(&timeframe, &amount); err != nil {
|
if err := rows.Scan(&timeframe, &amount); err != nil {
|
||||||
log.Error(err, timeframe)
|
log.Error(err, timeframe)
|
||||||
}
|
}
|
||||||
|
@ -136,7 +112,7 @@ func (g *GroupQuery) ToTimeValue() (*TimeVar, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TimeVar) FillMissing(current, end time.Time) ([]*TimeValue, error) {
|
func (t *TimeVar) FillMissing(current, end time.Time) ([]*TimeValue, error) {
|
||||||
timeMap := make(map[string]float64)
|
timeMap := make(map[string]int64)
|
||||||
var validSet []*TimeValue
|
var validSet []*TimeValue
|
||||||
dur := t.g.Group
|
dur := t.g.Group
|
||||||
for _, v := range t.data {
|
for _, v := range t.data {
|
||||||
|
@ -146,7 +122,7 @@ func (t *TimeVar) FillMissing(current, end time.Time) ([]*TimeValue, error) {
|
||||||
currentStr := types.FixedTime(current, t.g.Group)
|
currentStr := types.FixedTime(current, t.g.Group)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var amount float64
|
var amount int64
|
||||||
if timeMap[currentStr] != 0 {
|
if timeMap[currentStr] != 0 {
|
||||||
amount = timeMap[currentStr]
|
amount = timeMap[currentStr]
|
||||||
}
|
}
|
||||||
|
|
|
@ -543,6 +543,10 @@ input.inputTags-field:focus {
|
||||||
min-height: 85pt;
|
min-height: 85pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.list-group-item:HOVER {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.index_container {
|
.index_container {
|
||||||
min-height: 980pt;
|
min-height: 980pt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lower_canvas {
|
||||||
|
height: 4rem;
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
.list-group-item H5 {
|
.list-group-item H5 {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
@ -36,8 +41,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-sm {
|
.btn-sm {
|
||||||
line-height: 0.9rem;
|
line-height: 1.4rem;
|
||||||
font-size: 0.65rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.full-col-12 {
|
.full-col-12 {
|
||||||
|
|
|
@ -126,17 +126,17 @@
|
||||||
visible: function(newVal, oldVal) {
|
visible: function(newVal, oldVal) {
|
||||||
if (newVal && !this.showing) {
|
if (newVal && !this.showing) {
|
||||||
this.showing = true
|
this.showing = true
|
||||||
this.chartHits("1h")
|
this.chartHits("2h")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async chartHits(group) {
|
async chartHits(group) {
|
||||||
const start = this.nowSubtract((3600 * 24) * 30)
|
const start = this.nowSubtract((3600 * 24) * 3)
|
||||||
this.data = await Api.service_hits(this.service.id, this.toUnix(start), this.toUnix(new Date()), group)
|
this.data = await Api.service_hits(this.service.id, this.toUnix(start), this.toUnix(new Date()), group, false)
|
||||||
|
|
||||||
if (this.data.length === 0 && group !== "1h") {
|
if (this.data.length === 0 && group !== "1h") {
|
||||||
await this.chartHits("30m")
|
await this.chartHits("1h")
|
||||||
}
|
}
|
||||||
this.series = [{
|
this.series = [{
|
||||||
name: this.service.name,
|
name: this.service.name,
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
this.failures = await Api.service_failures(this.service.id, this.toUnix(start), this.toUnix(this.now()), 5)
|
this.failures = await Api.service_failures(this.service.id, this.toUnix(start), this.toUnix(this.now()), 5)
|
||||||
return [{name: "None", data: []}]
|
return [{name: "None", data: []}]
|
||||||
}
|
}
|
||||||
const fetched = await Api.service_hits(this.service.id, this.toUnix(start), this.toUnix(this.now()), group)
|
const fetched = await Api.service_hits(this.service.id, this.toUnix(start), this.toUnix(this.now()), group, false)
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return [{name: "None", data: []}]
|
return [{name: "None", data: []}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,9 +170,7 @@
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const auth = await Api.login(s.username, s.password)
|
await this.$store.dispatch('loadRequired')
|
||||||
this.auth = Api.saveToken(s.username, auth.token)
|
|
||||||
await this.$store.dispatch('loadAdmin')
|
|
||||||
|
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.$router.push('/')
|
this.$router.push('/')
|
||||||
|
|
|
@ -247,10 +247,10 @@ export default {
|
||||||
this.failures = await Api.service_failures(this.service.id, this.now() - 3600, this.now(), 15)
|
this.failures = await Api.service_failures(this.service.id, this.now() - 3600, this.now(), 15)
|
||||||
},
|
},
|
||||||
async chartHits() {
|
async chartHits() {
|
||||||
const start = this.nowSubtract((3600 * 24) * 7)
|
const start = this.nowSubtract((3600 * 24) * 3)
|
||||||
this.start_time = start
|
this.start_time = start
|
||||||
this.end_time = new Date()
|
this.end_time = new Date()
|
||||||
this.data = await Api.service_hits(this.service.id, this.toUnix(start), this.toUnix(new Date()), "1h")
|
this.data = await Api.service_hits(this.service.id, this.toUnix(start), this.toUnix(new Date()), "15m", false)
|
||||||
this.series = [{
|
this.series = [{
|
||||||
name: this.service.name,
|
name: this.service.name,
|
||||||
...this.data
|
...this.data
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -8,7 +8,6 @@ require (
|
||||||
github.com/Microsoft/go-winio v0.4.14 // indirect
|
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
|
||||||
github.com/ararog/timeago v0.0.0-20160328174124-e9969cf18b8d
|
github.com/ararog/timeago v0.0.0-20160328174124-e9969cf18b8d
|
||||||
github.com/crazy-max/xgo v0.3.2 // indirect
|
|
||||||
github.com/daaku/go.zipexe v1.0.1 // indirect
|
github.com/daaku/go.zipexe v1.0.1 // indirect
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -1,10 +1,12 @@
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg=
|
||||||
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
|
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
|
||||||
github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ=
|
github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ=
|
||||||
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
|
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
|
||||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||||
|
github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=
|
||||||
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||||
|
@ -18,8 +20,6 @@ github.com/ararog/timeago v0.0.0-20160328174124-e9969cf18b8d h1:ZX0t+GA3MWiP7LWt
|
||||||
github.com/ararog/timeago v0.0.0-20160328174124-e9969cf18b8d/go.mod h1:EcJ034SpbWy4heOSDiBZJRn3b5wKJM1b4sFfYeVAkI4=
|
github.com/ararog/timeago v0.0.0-20160328174124-e9969cf18b8d/go.mod h1:EcJ034SpbWy4heOSDiBZJRn3b5wKJM1b4sFfYeVAkI4=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/crazy-max/xgo v0.3.2 h1:A5KmtgpPVzzqJzYcEmzpM0zFgCCyUar1FSvHFXxLiWA=
|
|
||||||
github.com/crazy-max/xgo v0.3.2/go.mod h1:9sA9qZWLR9koBkgNTcktix7/MVbYrLWNnIQvYYq6/DA=
|
|
||||||
github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=
|
github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=
|
||||||
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
|
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
|
||||||
github.com/daaku/go.zipexe v1.0.1 h1:wV4zMsDOI2SZ2m7Tdz1Ps96Zrx+TzaK15VbUaGozw0M=
|
github.com/daaku/go.zipexe v1.0.1 h1:wV4zMsDOI2SZ2m7Tdz1Ps96Zrx+TzaK15VbUaGozw0M=
|
||||||
|
@ -64,6 +64,7 @@ github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPg
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
|
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
|
github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
|
||||||
github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
|
github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
|
||||||
|
@ -92,6 +93,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg=
|
||||||
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
|
@ -130,7 +132,9 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e h1:nt2877sKfojlHCTOBXbpWjBkuWKritFaGIfgQwbQUls=
|
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e h1:nt2877sKfojlHCTOBXbpWjBkuWKritFaGIfgQwbQUls=
|
||||||
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e/go.mod h1:B4+Kq1u5FlULTjFSM707Q6e/cOHFv0z/6QRoxubDIQ8=
|
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e/go.mod h1:B4+Kq1u5FlULTjFSM707Q6e/cOHFv0z/6QRoxubDIQ8=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
|
||||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
|
|
@ -62,11 +62,12 @@ func reorderServiceHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiServiceHandler(r *http.Request) interface{} {
|
func apiServiceHandler(r *http.Request) interface{} {
|
||||||
service, err := serviceByID(r)
|
srv, err := serviceByID(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return *service
|
srv = srv.UpdateStats()
|
||||||
|
return *srv
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) {
|
func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -192,15 +193,6 @@ func apiAllServicesHandler(r *http.Request) interface{} {
|
||||||
return services.AllInOrder()
|
return services.AllInOrder()
|
||||||
}
|
}
|
||||||
|
|
||||||
func joinServices(srvss map[int64]*services.Service) []*services.Service {
|
|
||||||
var srvs []*services.Service
|
|
||||||
for _, v := range srvss {
|
|
||||||
v.UpdateStats()
|
|
||||||
srvs = append(srvs, v)
|
|
||||||
}
|
|
||||||
return srvs
|
|
||||||
}
|
|
||||||
|
|
||||||
func servicesDeleteFailuresHandler(w http.ResponseWriter, r *http.Request) {
|
func servicesDeleteFailuresHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
service, err := serviceByID(r)
|
service, err := serviceByID(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -20,10 +20,8 @@ import (
|
||||||
"github.com/hunterlong/statping/types/configs"
|
"github.com/hunterlong/statping/types/configs"
|
||||||
"github.com/hunterlong/statping/types/core"
|
"github.com/hunterlong/statping/types/core"
|
||||||
"github.com/hunterlong/statping/types/null"
|
"github.com/hunterlong/statping/types/null"
|
||||||
"github.com/hunterlong/statping/types/users"
|
|
||||||
"github.com/hunterlong/statping/utils"
|
"github.com/hunterlong/statping/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,59 +31,21 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
sendErrorJson(errors.New("Statping has already been setup"), w, r)
|
sendErrorJson(errors.New("Statping has already been setup"), w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = r.ParseForm(); err != nil {
|
|
||||||
log.Errorln(err)
|
|
||||||
sendErrorJson(err, w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dbHost := r.PostForm.Get("db_host")
|
|
||||||
dbUser := r.PostForm.Get("db_user")
|
|
||||||
dbPass := r.PostForm.Get("db_password")
|
|
||||||
dbDatabase := r.PostForm.Get("db_database")
|
|
||||||
dbConn := r.PostForm.Get("db_connection")
|
|
||||||
dbPort := utils.ToInt(r.PostForm.Get("db_port"))
|
|
||||||
project := r.PostForm.Get("project")
|
|
||||||
username := r.PostForm.Get("username")
|
|
||||||
password := r.PostForm.Get("password")
|
|
||||||
description := r.PostForm.Get("description")
|
|
||||||
domain := r.PostForm.Get("domain")
|
|
||||||
email := r.PostForm.Get("email")
|
|
||||||
sample, _ := strconv.ParseBool(r.PostForm.Get("sample_data"))
|
|
||||||
|
|
||||||
confg := &configs.DbConfig{
|
confgs, err := configs.LoadConfigForm(r)
|
||||||
DbConn: dbConn,
|
if err != nil {
|
||||||
DbHost: dbHost,
|
|
||||||
DbUser: dbUser,
|
|
||||||
DbPass: dbPass,
|
|
||||||
DbData: dbDatabase,
|
|
||||||
DbPort: int(dbPort),
|
|
||||||
Project: project,
|
|
||||||
Description: description,
|
|
||||||
Domain: domain,
|
|
||||||
Username: username,
|
|
||||||
Password: password,
|
|
||||||
Email: email,
|
|
||||||
Error: nil,
|
|
||||||
Location: utils.Directory,
|
|
||||||
}
|
|
||||||
|
|
||||||
log.WithFields(utils.ToFields(core.App, confg)).Debugln("new configs posted")
|
|
||||||
|
|
||||||
if err := confg.Save(utils.Directory); err != nil {
|
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
sendErrorJson(err, w, r)
|
sendErrorJson(err, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if confg, err = configs.LoadConfigFile(utils.Directory); err != nil {
|
//sample, _ := strconv.ParseBool(r.PostForm.Get("sample_data"))
|
||||||
log.Errorln(err)
|
|
||||||
sendErrorJson(err, w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = configs.ConnectConfigs(confg); err != nil {
|
log.WithFields(utils.ToFields(core.App, confgs)).Debugln("new configs posted")
|
||||||
|
|
||||||
|
if err = configs.ConnectConfigs(confgs, true); err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
if err := confg.Delete(); err != nil {
|
if err := confgs.Delete(); err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
sendErrorJson(err, w, r)
|
sendErrorJson(err, w, r)
|
||||||
return
|
return
|
||||||
|
@ -94,7 +54,13 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = confg.MigrateDatabase(); err != nil {
|
if err := confgs.Save(utils.Directory); err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
sendErrorJson(err, w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = confgs.MigrateDatabase(); err != nil {
|
||||||
sendErrorJson(err, w, r)
|
sendErrorJson(err, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -111,6 +77,7 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
Footer: null.NewNullString(""),
|
Footer: null.NewNullString(""),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infoln("Creating new Core")
|
||||||
if err := c.Create(); err != nil {
|
if err := c.Create(); err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
sendErrorJson(err, w, r)
|
sendErrorJson(err, w, r)
|
||||||
|
@ -119,27 +86,22 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
core.App = c
|
core.App = c
|
||||||
|
|
||||||
admin := &users.User{
|
//if sample {
|
||||||
Username: confg.Username,
|
// log.Infoln("Adding sample data into new database")
|
||||||
Password: confg.Password,
|
// if err = configs.TriggerSamples(); err != nil {
|
||||||
Email: confg.Email,
|
// log.Errorln(err)
|
||||||
Admin: null.NewNullBool(true),
|
// sendErrorJson(err, w, r)
|
||||||
}
|
// return
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
if err := admin.Create(); err != nil {
|
log.Infoln("Initializing new Statping instance")
|
||||||
|
if err := core.InitApp(); err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
sendErrorJson(err, w, r)
|
sendErrorJson(err, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if sample {
|
|
||||||
if err = configs.TriggerSamples(); err != nil {
|
|
||||||
sendErrorJson(err, w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
core.InitApp()
|
|
||||||
CacheStorage.Delete("/")
|
CacheStorage.Delete("/")
|
||||||
resetCookies()
|
resetCookies()
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
|
@ -148,11 +110,7 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
Config *configs.DbConfig `json:"config"`
|
Config *configs.DbConfig `json:"config"`
|
||||||
}{
|
}{
|
||||||
"success",
|
"success",
|
||||||
confg,
|
confgs,
|
||||||
}
|
}
|
||||||
returnJson(out, w, r)
|
returnJson(out, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupResponseError(w http.ResponseWriter, r *http.Request, a interface{}) {
|
|
||||||
ExecuteResponse(w, r, "setup.gohtml", a, nil)
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package configs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hunterlong/statping/utils"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadConfigForm(r *http.Request) (*DbConfig, error) {
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dbHost := r.PostForm.Get("db_host")
|
||||||
|
dbUser := r.PostForm.Get("db_user")
|
||||||
|
dbPass := r.PostForm.Get("db_password")
|
||||||
|
dbDatabase := r.PostForm.Get("db_database")
|
||||||
|
dbConn := r.PostForm.Get("db_connection")
|
||||||
|
dbPort := utils.ToInt(r.PostForm.Get("db_port"))
|
||||||
|
project := r.PostForm.Get("project")
|
||||||
|
username := r.PostForm.Get("username")
|
||||||
|
password := r.PostForm.Get("password")
|
||||||
|
description := r.PostForm.Get("description")
|
||||||
|
domain := r.PostForm.Get("domain")
|
||||||
|
email := r.PostForm.Get("email")
|
||||||
|
|
||||||
|
if project == "" || username == "" || password == "" {
|
||||||
|
err := errors.New("Missing required elements on setup form")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
confg := &DbConfig{
|
||||||
|
DbConn: dbConn,
|
||||||
|
DbHost: dbHost,
|
||||||
|
DbUser: dbUser,
|
||||||
|
DbPass: dbPass,
|
||||||
|
DbData: dbDatabase,
|
||||||
|
DbPort: int(dbPort),
|
||||||
|
Project: project,
|
||||||
|
Description: description,
|
||||||
|
Domain: domain,
|
||||||
|
Username: username,
|
||||||
|
Password: password,
|
||||||
|
Email: email,
|
||||||
|
Error: nil,
|
||||||
|
Location: utils.Directory,
|
||||||
|
}
|
||||||
|
|
||||||
|
return confg, nil
|
||||||
|
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ func TestDbConfig_Save(t *testing.T) {
|
||||||
Location: utils.Directory,
|
Location: utils.Directory,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ConnectConfigs(config)
|
err := ConnectConfigs(config, true)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
err = config.Save(utils.Directory)
|
err = config.Save(utils.Directory)
|
||||||
|
|
|
@ -99,15 +99,18 @@ func InitialSetup(configs *DbConfig) error {
|
||||||
return errors.Wrap(err, "error creating database")
|
return errors.Wrap(err, "error creating database")
|
||||||
}
|
}
|
||||||
|
|
||||||
username := utils.Getenv("ADMIN_USER", "admin").(string)
|
if configs.Username == "" && configs.Password == "" {
|
||||||
password := utils.Getenv("ADMIN_PASSWORD", "admin").(string)
|
configs.Username = utils.Getenv("ADMIN_USER", "admin").(string)
|
||||||
|
configs.Password = utils.Getenv("ADMIN_PASSWORD", "admin").(string)
|
||||||
|
}
|
||||||
|
|
||||||
admin := &users.User{
|
admin := &users.User{
|
||||||
Username: username,
|
Username: configs.Username,
|
||||||
Password: password,
|
Password: configs.Password,
|
||||||
Email: "info@admin.com",
|
Email: "info@admin.com",
|
||||||
Admin: null.NewNullBool(true),
|
Admin: null.NewNullBool(true),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := admin.Create(); err != nil {
|
if err := admin.Create(); err != nil {
|
||||||
return errors.Wrap(err, "error creating admin")
|
return errors.Wrap(err, "error creating admin")
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
var log = utils.Log
|
var log = utils.Log
|
||||||
|
|
||||||
func ConnectConfigs(configs *DbConfig) error {
|
func ConnectConfigs(configs *DbConfig, initiate bool) error {
|
||||||
err := Connect(configs, true)
|
err := Connect(configs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error connecting to database")
|
return errors.Wrap(err, "error connecting to database")
|
||||||
|
@ -21,7 +21,7 @@ func ConnectConfigs(configs *DbConfig) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
exists := database.DB().HasTable("core")
|
exists := database.DB().HasTable("core")
|
||||||
if !exists {
|
if !exists && initiate {
|
||||||
return InitialSetup(configs)
|
return InitialSetup(configs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -3,6 +3,7 @@ package failures
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hunterlong/statping/types"
|
"github.com/hunterlong/statping/types"
|
||||||
|
"github.com/hunterlong/statping/utils"
|
||||||
"github.com/prometheus/common/log"
|
"github.com/prometheus/common/log"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -16,7 +17,7 @@ func Samples() {
|
||||||
tx := DB().Begin()
|
tx := DB().Begin()
|
||||||
sg := new(sync.WaitGroup)
|
sg := new(sync.WaitGroup)
|
||||||
|
|
||||||
createdAt := time.Now().Add(-1 * types.Month)
|
createdAt := utils.Now().Add(-3 * types.Day)
|
||||||
|
|
||||||
for i := int64(1); i <= 4; i++ {
|
for i := int64(1); i <= 4; i++ {
|
||||||
sg.Add(1)
|
sg.Add(1)
|
||||||
|
@ -25,8 +26,8 @@ func Samples() {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer sg.Done()
|
defer sg.Done()
|
||||||
for fi := 0.; fi <= float64(730); fi++ {
|
for fi := 0.; fi <= float64(400); fi++ {
|
||||||
createdAt = createdAt.Add(2 * time.Minute)
|
createdAt = createdAt.Add(35 * time.Minute)
|
||||||
failure := &Failure{
|
failure := &Failure{
|
||||||
Service: i,
|
Service: i,
|
||||||
Issue: "testing right here",
|
Issue: "testing right here",
|
||||||
|
|
|
@ -63,6 +63,15 @@ func (h Hitters) Sum() float64 {
|
||||||
return result.amount
|
return result.amount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h Hitters) Avg() int64 {
|
||||||
|
result := struct {
|
||||||
|
amount int64
|
||||||
|
}{0}
|
||||||
|
|
||||||
|
h.db.Select("AVG(latency) as amount").Scan(&result)
|
||||||
|
return result.amount
|
||||||
|
}
|
||||||
|
|
||||||
func AllHits(obj ColumnIDInterfacer) Hitters {
|
func AllHits(obj ColumnIDInterfacer) Hitters {
|
||||||
column, id := obj.HitsColumnID()
|
column, id := obj.HitsColumnID()
|
||||||
return Hitters{DB().Where(fmt.Sprintf("%s = ?", column), id)}
|
return Hitters{DB().Where(fmt.Sprintf("%s = ?", column), id)}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package hits
|
package hits
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/hunterlong/statping/database"
|
"github.com/hunterlong/statping/database"
|
||||||
"github.com/hunterlong/statping/types"
|
"github.com/hunterlong/statping/types"
|
||||||
"github.com/hunterlong/statping/utils"
|
"github.com/hunterlong/statping/utils"
|
||||||
|
@ -13,13 +12,13 @@ import (
|
||||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
var SampleHits = 9900.
|
var SampleHits = 99900.
|
||||||
|
|
||||||
func Samples() {
|
func Samples() {
|
||||||
tx := DB().Begin()
|
tx := DB().Begin()
|
||||||
sg := new(sync.WaitGroup)
|
sg := new(sync.WaitGroup)
|
||||||
|
|
||||||
for i := int64(1); i <= 4; i++ {
|
for i := int64(1); i <= 5; i++ {
|
||||||
err := createHitsAt(tx, i, sg)
|
err := createHitsAt(tx, i, sg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
|
@ -30,14 +29,14 @@ func Samples() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createHitsAt(db database.Database, serviceID int64, sg *sync.WaitGroup) error {
|
func createHitsAt(db database.Database, serviceID int64, sg *sync.WaitGroup) error {
|
||||||
createdAt := utils.Now().Add(-30 * types.Day)
|
createdAt := utils.Now().Add(-3 * types.Day)
|
||||||
p := utils.NewPerlin(2, 2, 5, utils.Now().UnixNano())
|
p := utils.NewPerlin(2, 2, 5, utils.Now().UnixNano())
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for hi := 0.; hi <= SampleHits; hi++ {
|
for hi := 0.; hi <= SampleHits; hi++ {
|
||||||
latency := p.Noise1D(hi / 500)
|
latency := p.Noise1D(hi / 500)
|
||||||
|
|
||||||
createdAt = createdAt.Add(10 * time.Minute)
|
createdAt = createdAt.Add(30 * time.Second)
|
||||||
|
|
||||||
hit := &Hit{
|
hit := &Hit{
|
||||||
Service: serviceID,
|
Service: serviceID,
|
||||||
|
@ -47,10 +46,11 @@ func createHitsAt(db database.Database, serviceID int64, sg *sync.WaitGroup) err
|
||||||
}
|
}
|
||||||
|
|
||||||
db = db.Create(&hit)
|
db = db.Create(&hit)
|
||||||
fmt.Printf("Creating hit %d hit %d: %.2f %v\n", serviceID, hit.Id, latency, createdAt.String())
|
|
||||||
i++
|
i++
|
||||||
|
if createdAt.After(utils.Now()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return db.Commit().Error()
|
return db.Commit().Error()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,32 +133,35 @@ func niceDomainName(domain string, paths string) string {
|
||||||
return domain + strings.Join(addedName, "/")
|
return domain + strings.Join(addedName, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UpdateStats() {
|
func (s *Service) UpdateStats() *Service {
|
||||||
s.Online24Hours = s.OnlineDaysPercent(1)
|
s.Online24Hours = s.OnlineDaysPercent(1)
|
||||||
s.Online7Days = s.OnlineDaysPercent(7)
|
s.Online7Days = s.OnlineDaysPercent(7)
|
||||||
s.AvgResponse = s.AvgTime()
|
s.AvgResponse = s.AvgTime()
|
||||||
s.FailuresLast24Hours = len(s.AllFailures().Since(time.Now().UTC().Add(-time.Hour * 24)))
|
s.FailuresLast24Hours = len(s.AllFailures().Since(utils.Now().Add(-time.Hour * 24)))
|
||||||
|
|
||||||
|
if s.LastOffline.IsZero() {
|
||||||
|
lastFail := s.LastFailure()
|
||||||
|
if lastFail != nil {
|
||||||
|
s.LastOffline = s.LastFailure().CreatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s.Stats = &Stats{
|
s.Stats = &Stats{
|
||||||
Failures: s.AllFailures().Count(),
|
Failures: s.AllFailures().Count(),
|
||||||
Hits: s.AllHits().Count(),
|
Hits: s.AllHits().Count(),
|
||||||
|
FirstHit: s.FirstHit().CreatedAt,
|
||||||
}
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// AvgTime will return the average amount of time for a service to response back successfully
|
// AvgTime will return the average amount of time for a service to response back successfully
|
||||||
func (s *Service) AvgTime() float64 {
|
func (s *Service) AvgTime() int64 {
|
||||||
sum := s.AllHits().Sum()
|
return s.AllHits().Avg()
|
||||||
return sum
|
|
||||||
}
|
|
||||||
|
|
||||||
// AvgUptime will return the average amount of time for a service to response back successfully
|
|
||||||
func (s *Service) AvgUptime(since time.Time) float64 {
|
|
||||||
sum := s.AllHits().Sum()
|
|
||||||
return sum
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnlineDaysPercent returns the service's uptime percent within last 24 hours
|
// OnlineDaysPercent returns the service's uptime percent within last 24 hours
|
||||||
func (s *Service) OnlineDaysPercent(days int) float32 {
|
func (s *Service) OnlineDaysPercent(days int) float32 {
|
||||||
ago := time.Now().UTC().Add((-24 * time.Duration(days)) * time.Hour)
|
ago := utils.Now().Add((-24 * time.Duration(days)) * time.Hour)
|
||||||
return s.OnlineSince(ago)
|
return s.OnlineSince(ago)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ type Service struct {
|
||||||
PingTime float64 `gorm:"-" json:"ping_time"`
|
PingTime float64 `gorm:"-" json:"ping_time"`
|
||||||
Online24Hours float32 `gorm:"-" json:"online_24_hours"`
|
Online24Hours float32 `gorm:"-" json:"online_24_hours"`
|
||||||
Online7Days float32 `gorm:"-" json:"online_7_days"`
|
Online7Days float32 `gorm:"-" json:"online_7_days"`
|
||||||
AvgResponse float64 `gorm:"-" json:"avg_response"`
|
AvgResponse int64 `gorm:"-" json:"avg_response"`
|
||||||
FailuresLast24Hours int `gorm:"-" json:"failures_24_hours"`
|
FailuresLast24Hours int `gorm:"-" json:"failures_24_hours"`
|
||||||
Running chan bool `gorm:"-" json:"-"`
|
Running chan bool `gorm:"-" json:"-"`
|
||||||
Checkpoint time.Time `gorm:"-" json:"-"`
|
Checkpoint time.Time `gorm:"-" json:"-"`
|
||||||
|
@ -57,14 +57,14 @@ type Service struct {
|
||||||
DownText string `gorm:"-" json:"-"` // Contains the current generated Downtime Text
|
DownText string `gorm:"-" json:"-"` // Contains the current generated Downtime Text
|
||||||
SuccessNotified bool `gorm:"-" json:"-"` // Is 'true' if the user has already be informed that the Services now again available
|
SuccessNotified bool `gorm:"-" json:"-"` // Is 'true' if the user has already be informed that the Services now again available
|
||||||
LastStatusCode int `gorm:"-" json:"status_code"`
|
LastStatusCode int `gorm:"-" json:"status_code"`
|
||||||
LastOnline time.Time `gorm:"-" json:"last_success"`
|
|
||||||
LastOffline time.Time `gorm:"-" json:"last_error"`
|
|
||||||
Failures []*failures.Failure `gorm:"-" json:"failures,omitempty" scope:"user,admin"`
|
Failures []*failures.Failure `gorm:"-" json:"failures,omitempty" scope:"user,admin"`
|
||||||
AllCheckins []*checkins.Checkin `gorm:"-" json:"checkins,omitempty" scope:"user,admin"`
|
AllCheckins []*checkins.Checkin `gorm:"-" json:"checkins,omitempty" scope:"user,admin"`
|
||||||
Stats *Stats `gorm:"-" json:"stats,omitempty"`
|
|
||||||
LastLookupTime int64 `gorm:"-" json:"-"`
|
LastLookupTime int64 `gorm:"-" json:"-"`
|
||||||
LastLatency int64 `gorm:"-" json:"-"`
|
LastLatency int64 `gorm:"-" json:"-"`
|
||||||
LastCheck time.Time `gorm:"-" json:"-"`
|
LastCheck time.Time `gorm:"-" json:"-"`
|
||||||
|
LastOnline time.Time `gorm:"-" json:"last_success"`
|
||||||
|
LastOffline time.Time `gorm:"-" json:"last_error"`
|
||||||
|
Stats *Stats `gorm:"-" json:"stats,omitempty"`
|
||||||
|
|
||||||
SecondsOnline int64 `gorm:"-" json:"-"`
|
SecondsOnline int64 `gorm:"-" json:"-"`
|
||||||
SecondsOffline int64 `gorm:"-" json:"-"`
|
SecondsOffline int64 `gorm:"-" json:"-"`
|
||||||
|
@ -73,6 +73,9 @@ type Service struct {
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
Failures int `gorm:"-" json:"failures"`
|
Failures int `gorm:"-" json:"failures"`
|
||||||
Hits int `gorm:"-" json:"hits"`
|
Hits int `gorm:"-" json:"hits"`
|
||||||
|
LastLookupTime int64 `gorm:"-" json:"last_lookup"`
|
||||||
|
LastLatency int64 `gorm:"-" json:"last_latency"`
|
||||||
|
FirstHit time.Time `gorm:"-" json:"first_hit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BeforeCreate for Service will set CreatedAt to UTC
|
// BeforeCreate for Service will set CreatedAt to UTC
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,31 +37,29 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func FixedTime(t time.Time, d time.Duration) string {
|
func FixedTime(t time.Time, d time.Duration) string {
|
||||||
switch d {
|
|
||||||
case Month:
|
|
||||||
month := fmt.Sprintf("%v", int(t.Month()))
|
|
||||||
if int(t.Month()) < 10 {
|
|
||||||
month = fmt.Sprintf("0%v", int(t.Month()))
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%v-%v-01T00:00:00Z", t.Year(), month)
|
|
||||||
case Year:
|
|
||||||
return fmt.Sprintf("%v-01-01T00:00:00Z", t.Year())
|
|
||||||
default:
|
|
||||||
return t.Format(durationStr(d))
|
return t.Format(durationStr(d))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func durationStr(d time.Duration) string {
|
func durationStr(d time.Duration) string {
|
||||||
switch d {
|
|
||||||
case Second:
|
switch m := d.Seconds(); {
|
||||||
return "2006-01-02T15:04:05Z"
|
|
||||||
case Minute:
|
case m >= Month.Seconds():
|
||||||
return "2006-01-02T15:04:00Z"
|
return "2006-01-01T00:00:00Z"
|
||||||
case Hour:
|
|
||||||
|
case m >= Week.Seconds():
|
||||||
|
return "2006-01-02T00:00:00Z"
|
||||||
|
|
||||||
|
case m >= Day.Seconds():
|
||||||
return "2006-01-02T15:00:00Z"
|
return "2006-01-02T15:00:00Z"
|
||||||
case Day:
|
|
||||||
return "2006-01-02T00:00:00Z"
|
case m >= Hour.Seconds():
|
||||||
|
return "2006-01-02T15:04:00Z"
|
||||||
|
|
||||||
|
case m >= Minute.Seconds():
|
||||||
|
return "2006-01-02T15:04:00Z"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "2006-01-02T00:00:00Z"
|
return "2006-01-02T15:04:05Z"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package users
|
package users
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"github.com/hunterlong/statping/database"
|
"github.com/hunterlong/statping/database"
|
||||||
"github.com/hunterlong/statping/utils"
|
"github.com/hunterlong/statping/utils"
|
||||||
"github.com/prometheus/common/log"
|
"github.com/prometheus/common/log"
|
||||||
|
@ -32,13 +31,11 @@ func All() []*User {
|
||||||
|
|
||||||
func (u *User) Create() error {
|
func (u *User) Create() error {
|
||||||
u.CreatedAt = time.Now().UTC()
|
u.CreatedAt = time.Now().UTC()
|
||||||
if u.Password == "" {
|
|
||||||
return errors.New("did not supply user password")
|
|
||||||
}
|
|
||||||
u.Password = utils.HashPassword(u.Password)
|
u.Password = utils.HashPassword(u.Password)
|
||||||
|
if u.ApiKey == "" || u.ApiSecret == "" {
|
||||||
u.ApiKey = utils.NewSHA1Hash(16)
|
u.ApiKey = utils.NewSHA1Hash(16)
|
||||||
u.ApiSecret = utils.NewSHA1Hash(16)
|
u.ApiSecret = utils.NewSHA1Hash(16)
|
||||||
|
}
|
||||||
db := DB().Create(u)
|
db := DB().Create(u)
|
||||||
if db.Error() == nil {
|
if db.Error() == nil {
|
||||||
log.Warnf("User #%d (%s) has been created", u.Id, u.Username)
|
log.Warnf("User #%d (%s) has been created", u.Id, u.Username)
|
||||||
|
|
Loading…
Reference in New Issue