pull/429/head
hunterlong 2020-02-20 23:15:48 -08:00
parent da34fc179c
commit 7d0501823d
6 changed files with 88 additions and 19 deletions

View File

@ -283,7 +283,7 @@ func GraphHitsDataRaw(service types.ServiceInterface, start, end time.Time, grou
} }
// GraphDataRaw will return all the hits between 2 times for a Service // GraphDataRaw will return all the hits between 2 times for a Service
func GraphFailuresDataRaw(service types.ServiceInterface, start, end time.Time, group string) []types.TimeValue { func GraphFailuresDataRaw(service types.ServiceInterface, start, end time.Time, group string) []*types.TimeValue {
srv := service.(*Service) srv := service.(*Service)
query := Database(&types.Failure{}). query := Database(&types.Failure{}).
@ -292,7 +292,7 @@ func GraphFailuresDataRaw(service types.ServiceInterface, start, end time.Time,
MultipleSelects(types.SelectByTime(group), types.CountAmount()). MultipleSelects(types.SelectByTime(group), types.CountAmount()).
GroupByTimeframe().Debug() GroupByTimeframe().Debug()
outgoing, err := query.ToTimeValue() outgoing, err := query.ToTimeValue(start, end)
if err != nil { if err != nil {
log.Error(err) log.Error(err)
} }

View File

@ -133,6 +133,24 @@ HTML,BODY {
border-radius: $global-border-radius; border-radius: $global-border-radius;
} }
.mini_success {
background-color: #f3f3f3;
}
.no-decoration {
color: black;
text-decoration: none;
}
.no-decoration:HOVER {
color: #2b2b2b;
text-decoration: none;
}
.mini_error {
background-color: #ffbbbb;
}
.card { .card {
background-color: $service-background; background-color: $service-background;
border: $service-border; border: $service-border;

View File

@ -1,10 +1,10 @@
<template> <template>
<div class="col-12 full-col-12"> <div class="col-12 full-col-12">
<h4 v-if="group.name !== 'Empty Group'" class="group_header">{{group.name}}</h4> <h4 v-if="group.name !== 'Empty Group'" class="group_header mb-2 mt-4">{{group.name}}</h4>
<div class="list-group online_list mb-3"> <div class="list-group online_list mb-4">
<a v-for="(service, index) in $store.getters.servicesInGroup(group.id)" v-bind:key="index" class="service_li list-group-item list-group-item-action"> <a v-for="(service, index) in $store.getters.servicesInGroup(group.id)" v-bind:key="index" class="service_li list-group-item list-group-item-action">
{{service.name}} <router-link class="no-decoration" :to="serviceLink(service)">{{service.name}}</router-link>
<span class="badge bg-success float-right pulse-glow">{{service.online ? "ONLINE" : "OFFLINE"}}</span> <span class="badge bg-success float-right pulse-glow">{{service.online ? "ONLINE" : "OFFLINE"}}</span>
<GroupServiceFailures :service="service"/> <GroupServiceFailures :service="service"/>

View File

@ -1,8 +1,12 @@
<template> <template>
<div class="row"> <div>
<div class="d-flex mt-3 mb-2">
<span class="bg-danger">o</span> <div class="flex-fill service_day" v-for="(d, index) in failureData" :class="{'mini_error': d.amount > 0, 'mini_success': d.amount === 0}"></div>
</div>
<div class="row mt-2">
<div class="col-6 text-left font-2 text-muted">30 Days Ago</div>
<div class="col-6 text-right font-2 text-muted">Today</div>
</div>
</div> </div>
</template> </template>
@ -16,7 +20,7 @@ export default {
}, },
data() { data() {
return { return {
failureData: null failureData: null,
} }
}, },
props: { props: {
@ -30,7 +34,7 @@ export default {
}, },
methods: { methods: {
async lastDaysFailures() { async lastDaysFailures() {
const start = this.nowSubtract((3600 * 24) * 30) const start = this.nowSubtract(86400 * 30)
this.failureData = await Api.service_failures_data(this.service.id, this.toUnix(start), this.toUnix(this.now()), "day") this.failureData = await Api.service_failures_data(this.service.id, this.toUnix(start), this.toUnix(this.now()), "day")
} }
} }
@ -39,6 +43,12 @@ export default {
<!-- Add "scoped" attribute to limit CSS to this component only --> <!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped> <style scoped>
.service_day {
height: 20px;
margin-right: 2px;
border-radius: 4px;
}
@keyframes pulse_animation { @keyframes pulse_animation {
0% { transform: scale(1); } 0% { transform: scale(1); }
30% { transform: scale(1); } 30% { transform: scale(1); }

View File

@ -235,8 +235,8 @@ func apiServiceFailureDataHandler(w http.ResponseWriter, r *http.Request) {
startField := utils.ToInt(fields.Get("start")) startField := utils.ToInt(fields.Get("start"))
endField := utils.ToInt(fields.Get("end")) endField := utils.ToInt(fields.Get("end"))
start := time.Unix(startField, 0) start := time.Unix(startField, 0).UTC()
end := time.Unix(endField, 0) end := time.Unix(endField, 0).UTC()
obj := core.GraphFailuresDataRaw(service, start, end, grouping) obj := core.GraphFailuresDataRaw(service, start, end, grouping)
returnJson(obj, w, r) returnJson(obj, w, r)

View File

@ -111,7 +111,7 @@ type Database interface {
ToChart() ([]*DateScan, error) ToChart() ([]*DateScan, error)
GroupByTimeframe() Database GroupByTimeframe() Database
ToTimeValue() ([]TimeValue, error) ToTimeValue(time.Time, time.Time) ([]*TimeValue, error)
MultipleSelects(args ...string) Database MultipleSelects(args ...string) Database
@ -509,12 +509,12 @@ type TimeValue struct {
Amount int64 `json:"amount"` Amount int64 `json:"amount"`
} }
func (it *Db) ToTimeValue() ([]TimeValue, error) { func (it *Db) ToTimeValue(start, end time.Time) ([]*TimeValue, error) {
rows, err := it.Database.Rows() rows, err := it.Database.Rows()
if err != nil { if err != nil {
return nil, err return nil, err
} }
var data []TimeValue var data []*TimeValue
for rows.Next() { for rows.Next() {
var timeframe string var timeframe string
var amount int64 var amount int64
@ -522,12 +522,53 @@ func (it *Db) ToTimeValue() ([]TimeValue, error) {
return nil, err return nil, err
} }
createdTime, _ := time.Parse(TIME, timeframe) createdTime, _ := time.Parse(TIME, timeframe)
data = append(data, TimeValue{ fmt.Println("got: ", createdTime.UTC(), amount)
Timeframe: createdTime, data = append(data, &TimeValue{
Timeframe: createdTime.UTC(),
Amount: amount, Amount: amount,
}) })
} }
return data, nil return fillMissing(data, start, end), nil
}
func parseTime(t time.Time) string {
return t.Format("2006-01-02T00:00:00Z")
}
func reparseTime(t string) time.Time {
re, _ := time.Parse("2006-01-02T00:00:00Z", t)
return re.UTC()
}
func fillMissing(vals []*TimeValue, start, end time.Time) []*TimeValue {
timeMap := make(map[string]*TimeValue)
var validSet []*TimeValue
for _, v := range vals {
timeMap[parseTime(v.Timeframe)] = v
}
current := start.UTC()
maxTime := end
for {
amount := int64(0)
currentStr := parseTime(current)
if timeMap[currentStr] != nil {
amount = timeMap[currentStr].Amount
}
validSet = append(validSet, &TimeValue{
Timeframe: reparseTime(currentStr),
Amount: amount,
})
if current.After(maxTime) {
break
}
current = current.Add(24 * time.Hour)
}
return validSet
} }
func (it *Db) ToChart() ([]*DateScan, error) { func (it *Db) ToChart() ([]*DateScan, error) {