diff --git a/README.md b/README.md index f44532af..3069b6bd 100644 --- a/README.md +++ b/README.md @@ -259,12 +259,16 @@ Check the [Notification Configuration](#38-notification-configuration) to see h - HTML: `http://localhost:8181/` - JSON: `http://localhost:8181/api/v1/sla` -For the HTML report, you can use the following URL query options: - - - `refresh`: report refresh rate (ex. `?refresh=30s` refreshes the page every 30 seconds) - - `status`: only shows the probers with specific status, accepted values `up` or `down` (ex. `?status=up` list only probers with status `up`). - - `gte`: only shows the probers with SLA greater than or equal to the given percentage (ex. `?gte=50` filter only hosts with SLA percentage `>= 50%`) - - `lte`: only shows the probers with SLA less than or equal to the given percentage (ex. `?lte=90` filter only hosts with SLA percentage `<= 90%` ) +You can use the following URL query options for both HTML and JSON: + - `refresh`: (_HTML only_) refresh the page every given seconds (ex, `?refresh=30s` refreshes the page every 30 seconds) + - `pg` & `sz`: page number and page size (ex, `?pg=2&sz=10` shows the second page with 10 probers), default page size is `100` + - `name`: filter the probers that contain the value of name (ex, `?name=probe1` list the probers which name containing `probe1`) + - `kind`: filter the probers with the kind (ex, `?kind=http` list the probers with kind `http`) + - `ep`: filter the probers with the endpoint (ex, `?ep=example.com` list the probers which endpoint containing `example.com`) + - `msg`: filter the probers with the message (ex, `?msg=example` list the probers which message containing `example`) + - `status`: filter the probers with specific status, accepted values `up` or `down` (ex. `?status=up` list only probers with status `up`). + - `gte`: filter the probers with SLA greater than or equal to the given percentage (ex. `?gte=50` filter only hosts with SLA percentage `>= 50%`) + - `lte`:filter the probers with SLA less than or equal to the given percentage (ex. `?lte=90` filter only hosts with SLA percentage `<= 90%` ) Refer to the [Global Setting Configuration](#39-global-setting-configuration) to see how to configure the access log. @@ -283,7 +287,7 @@ For the HTML report, you can use the following URL query options: data: /path/to/data/file.yaml ``` -For more information, please check the [Global Setting Configuration](#38-global-setting-configuration) +For more information, please check the [Global Setting Configuration](#39-global-setting-configuration) ### 1.4 Channel diff --git a/global/global.go b/global/global.go index 807c99a7..b87bd39d 100644 --- a/global/global.go +++ b/global/global.go @@ -68,6 +68,8 @@ const ( DefaultHTTPServerIP = "0.0.0.0" // DefaultHTTPServerPort is the default port of the HTTP server DefaultHTTPServerPort = "8181" + // DefaultPageSize is the default page size + DefaultPageSize = 100 // DefaultAccessLogFile is the default access log file name DefaultAccessLogFile = "access.log" // DefaultDataFile is the default data file name diff --git a/report/filter.go b/report/filter.go new file mode 100644 index 00000000..361b86af --- /dev/null +++ b/report/filter.go @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2022, MegaEase + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package report + +import ( + "fmt" + "strings" + + "github.com/megaease/easeprobe/global" + "github.com/megaease/easeprobe/probe" + + log "github.com/sirupsen/logrus" +) + +// SLAFilter filter the probers +type SLAFilter struct { + Name string + Kind string + Endpoint string + Status *probe.Status + SLAGreater float64 + SLALess float64 + Message string + PageNum int + PageSize int + total int // the total number of probers + cnt int // the number of probers that match the filter +} + +// NewEmptyFilter create a new SLAFilter +func NewEmptyFilter() *SLAFilter { + return &SLAFilter{ + Name: "", + Kind: "", + Endpoint: "", + Status: nil, + SLAGreater: 0, + SLALess: 100, + Message: "", + PageNum: 1, + PageSize: global.DefaultPageSize, + total: 0, + cnt: 0, + } +} + +// Check check the filter is valid or not +func (f *SLAFilter) Check() error { + log.Debugf("[Web] Check filter: %+v", f) + if f.SLAGreater > f.SLALess { + return fmt.Errorf("Error: Invalid SLA filter: gte(%0.2f) > (%0.2f)", f.SLAGreater, f.SLALess) + } + if f.SLAGreater > 100 || f.SLAGreater < 0 { + return fmt.Errorf("Error: Invalid SLA filter: gte(%0.2f), it must be between 0 - 100", f.SLAGreater) + } + if f.SLALess > 100 || f.SLALess < 0 { + return fmt.Errorf("Error: Invalid SLA filter: lte(%0.2f), it must be between 0 - 100", f.SLALess) + } + if f.PageNum < 1 { + return fmt.Errorf("Error: Invalid page number: %d, it must be greater than 0", f.PageNum) + } + if f.PageSize < 1 { + return fmt.Errorf("Error: Invalid page size: %d, it must be greater than 0", f.PageSize) + } + return nil +} + +// HTML return the HTML format string +func (f *SLAFilter) HTML() string { + + span := "" + _span := " " + + result := "" + + if strings.TrimSpace(f.Name) != "" { + result += fmt.Sprintf(span+"Name: %s"+_span, f.Name) + } + if strings.TrimSpace(f.Kind) != "" { + result += fmt.Sprintf(span+"Kind: %s"+_span, f.Kind) + } + if strings.TrimSpace(f.Endpoint) != "" { + result += fmt.Sprintf(span+"Endpoint: %s"+_span, f.Endpoint) + } + if f.Status != nil { + result += fmt.Sprintf(span+"Status: %s"+_span, f.Status.String()) + } + if strings.TrimSpace(f.Message) != "" { + result += fmt.Sprintf(span+"Message: %s"+_span, f.Message) + } + if f.SLAGreater > 0 || f.SLALess < 100 { + result += fmt.Sprintf(span+"SLA: %.2f%% - %.2f%% "+_span, f.SLAGreater, f.SLALess) + } + + color := "#c00" + if f.PageNum <= f.cnt/f.PageSize+1 { + color = "#4E944F" + } + span = `` + result += fmt.Sprintf(span+"Page %d / %d"+_span, f.PageNum, f.cnt/f.PageSize+1) + + span = `` + result += fmt.Sprintf(span+"%d / %d Probers found!"+_span, f.cnt, f.total) + + result += "

" + + return result +} + +func (f *SLAFilter) getIndics() (start int, end int) { + start = (f.PageNum - 1) * f.PageSize + end = f.PageNum*f.PageSize - 1 + return start, end +} + +// Filter filter the probers +func (f *SLAFilter) Filter(probers []probe.Prober) []probe.Prober { + start, end := f.getIndics() + f.cnt = 0 + result := make([]probe.Prober, 0) + for _, p := range probers { + // if the name is not empty then filter by name + if f.Name != "" && !strings.Contains(p.Name(), f.Name) { + continue + } + // if the kind is not empty then filter by kind + if f.Kind != "" && p.Kind() != f.Kind { + continue + } + // if the endpoint is not empty then filter by endpoint + if f.Endpoint != "" && !strings.Contains(p.Result().Endpoint, f.Endpoint) { + continue + } + // if the status is not right then ignore it + if f.Status != nil && p.Result().Status != *f.Status { + continue + } + // if the message is not empty then filter by message + if f.Message != "" && !strings.Contains(p.Result().Message, f.Message) { + continue + } + //if the SLA is not right then ignore it + percent := p.Result().SLAPercent() + if percent < f.SLAGreater || percent > f.SLALess { + continue + } + + if f.cnt >= start && f.cnt <= end { // if the prober is in the page + result = append(result, p) + } + f.cnt++ // how many probers are filtered + } + f.total = len(probers) + return result +} diff --git a/report/filter_test.go b/report/filter_test.go new file mode 100644 index 00000000..d7ba4fd7 --- /dev/null +++ b/report/filter_test.go @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2022, MegaEase + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package report + +import ( + "fmt" + "testing" + + "github.com/megaease/easeprobe/probe" + "github.com/megaease/easeprobe/probe/base" + "github.com/stretchr/testify/assert" +) + +func initData() []probe.Prober { + var probes = []probe.Prober{ + &dummyProber{ + DefaultProbe: base.DefaultProbe{ + ProbeKind: "http", + ProbeName: "probe_001", + ProbeResult: &probe.Result{ + Endpoint: "http://probe_001", + }, + }, + }, + &dummyProber{ + DefaultProbe: base.DefaultProbe{ + ProbeKind: "tcp", + ProbeName: "probe_002", + ProbeResult: &probe.Result{ + Endpoint: "probe_002:443", + }, + }, + }, + &dummyProber{ + DefaultProbe: base.DefaultProbe{ + ProbeKind: "http", + ProbeName: "probe_003", + ProbeResult: &probe.Result{ + Endpoint: "https://probe_003:443", + }, + }, + }, + &dummyProber{ + DefaultProbe: base.DefaultProbe{ + ProbeKind: "tcp", + ProbeName: "probe_004", + ProbeResult: &probe.Result{ + Endpoint: "probe_004:443", + }, + }, + }, + } + probes[0].Result().Status = probe.StatusUp + probes[1].Result().Status = probe.StatusDown + probes[2].Result().Status = probe.StatusUp + probes[3].Result().Status = probe.StatusDown + + for i := 0; i < len(probes); i++ { + probes[i].Result().Message = fmt.Sprintf("%s %s %s", probes[i].Kind(), probes[i].Name(), "message") + } + + // 80% SLA + probes[0].Result().Stat.UpTime = 80 + probes[0].Result().Stat.DownTime = 20 + + // 60% SLA + probes[1].Result().Stat.UpTime = 60 + probes[1].Result().Stat.DownTime = 40 + + // 40% SLA + probes[2].Result().Stat.UpTime = 40 + probes[2].Result().Stat.DownTime = 60 + + // 20% SLA + probes[3].Result().Stat.UpTime = 20 + probes[3].Result().Stat.DownTime = 80 + + return probes +} +func TestFilter(t *testing.T) { + _probes := initData() + filter := NewEmptyFilter() + + probes := filter.Filter(_probes) + assert.Equal(t, len(_probes), len(probes)) + assert.Equal(t, _probes, probes) + + // sla >= 60 && sla <= 40 + filter.SLAGreater = 60 + filter.SLALess = 40 + err := filter.Check() + assert.NotNil(t, err) + // sla >= 60 && sla <= 200 + filter.SLALess = 200 + err = filter.Check() + assert.NotNil(t, err) + // sla >= -100 && sla <= 60 + filter.SLALess = 60 + filter.SLAGreater = -100 + err = filter.Check() + assert.NotNil(t, err) + //sla >= 40 && sla <= 60 + filter.SLAGreater = 40 + err = filter.Check() + assert.Nil(t, err) + + // sla >= 60 && sla <= 40 + probes = filter.Filter(_probes) + assert.Equal(t, 2, len(probes)) + assert.Equal(t, _probes[1], probes[0]) + assert.Equal(t, _probes[2], probes[1]) + + html := filter.HTML() + assert.Contains(t, html, "SLA: 40.00% - 60.00%") + + // filter by message + filter = NewEmptyFilter() + filter.Message = "http" + probes = filter.Filter(_probes) + assert.Equal(t, 2, len(probes)) + assert.Equal(t, _probes[0], probes[0]) + assert.Equal(t, _probes[2], probes[1]) + + html = filter.HTML() + assert.Contains(t, html, "Message: http") + + // filter by status + filter = NewEmptyFilter() + s := probe.StatusUp + filter.Status = &s + probes = filter.Filter(_probes) + assert.Equal(t, 2, len(probes)) + assert.Equal(t, _probes[0], probes[0]) + assert.Equal(t, _probes[2], probes[1]) + + html = filter.HTML() + assert.Contains(t, html, "Status: up") + + // filter by endpoint + filter = NewEmptyFilter() + filter.Endpoint = ":443" + probes = filter.Filter(_probes) + assert.Equal(t, 3, len(probes)) + assert.Equal(t, _probes[1], probes[0]) + assert.Equal(t, _probes[2], probes[1]) + assert.Equal(t, _probes[3], probes[2]) + + html = filter.HTML() + assert.Contains(t, html, "Endpoint: :443") + + // filter by kind + filter = NewEmptyFilter() + filter.Kind = "tcp" + probes = filter.Filter(_probes) + assert.Equal(t, 2, len(probes)) + assert.Equal(t, _probes[1], probes[0]) + assert.Equal(t, _probes[3], probes[1]) + + html = filter.HTML() + assert.Contains(t, html, "Kind: tcp") + + // filter by name + filter = NewEmptyFilter() + filter.Name = "probe_001" + probes = filter.Filter(_probes) + assert.Equal(t, 1, len(probes)) + assert.Equal(t, _probes[0], probes[0]) + + html = filter.HTML() + assert.Contains(t, html, "Name: probe_001") + + // filter by name and kind + filter = NewEmptyFilter() + filter.Name = "probe" + filter.Kind = "http" + probes = filter.Filter(_probes) + assert.Equal(t, 2, len(probes)) + assert.Equal(t, _probes[0], probes[0]) + assert.Equal(t, _probes[2], probes[1]) + + // filter by status and kind + filter = NewEmptyFilter() + filter.Status = &s + filter.Kind = "tcp" + probes = filter.Filter(_probes) + assert.Equal(t, 0, len(probes)) + + filter.Kind = "http" + probes = filter.Filter(_probes) + assert.Equal(t, 2, len(probes)) + assert.Equal(t, _probes[0], probes[0]) + assert.Equal(t, _probes[2], probes[1]) + + // filter by status and sla + filter = NewEmptyFilter() + filter.Status = &s + filter.SLAGreater = 20 + filter.SLALess = 100 + probes = filter.Filter(_probes) + assert.Equal(t, 2, len(probes)) + assert.Equal(t, _probes[0], probes[0]) + assert.Equal(t, _probes[2], probes[1]) + + // filter by status and sla and endpoint + filter.Endpoint = ":443" + probes = filter.Filter(_probes) + assert.Equal(t, 1, len(probes)) + assert.Equal(t, _probes[2], probes[0]) +} + +func NewFilterWithPage(pg, sz int) *SLAFilter { + filter := NewEmptyFilter() + filter.PageNum = pg + filter.PageSize = sz + return filter +} +func TestPage(t *testing.T) { + _probes := initData() + filter := NewEmptyFilter() + probes := filter.Filter(_probes) + assert.Equal(t, _probes, probes) + + filter = NewFilterWithPage(1, 2) + probes = filter.Filter(_probes) + assert.Equal(t, 2, len(probes)) + assert.Equal(t, _probes[0], probes[0]) + assert.Equal(t, _probes[1], probes[1]) + + filter = NewFilterWithPage(2, 2) + probes = filter.Filter(_probes) + assert.Equal(t, 2, len(probes)) + assert.Equal(t, _probes[2], probes[0]) + assert.Equal(t, _probes[3], probes[1]) + + filter = NewFilterWithPage(2, 3) + probes = filter.Filter(_probes) + assert.Equal(t, 1, len(probes)) + assert.Equal(t, _probes[3], probes[0]) + +} diff --git a/report/sla.go b/report/sla.go index 2223e420..974709ff 100644 --- a/report/sla.go +++ b/report/sla.go @@ -115,7 +115,7 @@ func SLATextSection(r *probe.Result) string { return fmt.Sprintf(text, r.Name, r.Endpoint, DurationStr(r.Stat.UpTime), DurationStr(r.Stat.DownTime), r.SLAPercent(), r.Stat.Total, SLAStatusText(r.Stat, Text), - time.Now().UTC().Format(r.TimeFormat), + r.StartTime.UTC().Format(r.TimeFormat), r.Status.Emoji()+" "+r.Status.String(), JSONEscape(r.Message)) } @@ -134,7 +134,7 @@ func SLALogSection(r *probe.Result) string { return fmt.Sprintf(text, r.Name, r.Endpoint, DurationStr(r.Stat.UpTime), DurationStr(r.Stat.DownTime), r.SLAPercent(), r.Stat.Total, SLAStatusText(r.Stat, Log), - time.Now().UTC().Format(r.TimeFormat), + r.StartTime.UTC().Format(r.TimeFormat), r.Status.String(), r.Message) } @@ -164,7 +164,7 @@ func SLAMarkdownSection(r *probe.Result, f Format) string { return fmt.Sprintf(text, r.Name, r.Endpoint, DurationStr(r.Stat.UpTime), DurationStr(r.Stat.DownTime), r.SLAPercent(), r.Stat.Total, SLAStatusText(r.Stat, MarkdownSocial), - time.Now().UTC().Format(r.TimeFormat), + r.StartTime.UTC().Format(r.TimeFormat), r.Status.Emoji()+" "+r.Status.String(), r.Message) } @@ -214,27 +214,10 @@ func SLAHTMLSection(r *probe.Result) string { DurationStr(r.Stat.UpTime), DurationStr(r.Stat.DownTime), r.SLAPercent(), r.Stat.Total, SLAStatusText(r.Stat, HTML), - time.Now().UTC().Format(r.TimeFormat), + r.StartTime.UTC().Format(r.TimeFormat), r.Status.Emoji()+" "+r.Status.String(), JSONEscape(r.Message)) } -// SLAFilter filter the probers -type SLAFilter struct { - Status *probe.Status - SLAGreater float64 - SLALess float64 -} - -// HTML return the HTML format string -func (f *SLAFilter) HTML() string { - result := fmt.Sprintf("SLA: %.2f%% - %.2f%% ", f.SLAGreater, f.SLALess) - if f.Status != nil { - result += fmt.Sprintf(" Status: %s", f.Status.String()) - } - - return result -} - // SLAHTML return a full stat report func SLAHTML(probers []probe.Prober) string { return SLAHTMLFilter(probers, nil) @@ -244,27 +227,18 @@ func SLAHTML(probers []probe.Prober) string { func SLAHTMLFilter(probers []probe.Prober, filter *SLAFilter) string { html := HTMLHeader("Overall SLA Report") - cnt := 0 + if filter == nil { + filter = NewEmptyFilter() + } + + probers = filter.Filter(probers) table := `` for _, p := range probers { - if filter == nil { - table += SLAHTMLSection(p.Result()) - cnt++ - } else if p.Result().SLAPercent() >= filter.SLAGreater && p.Result().SLAPercent() <= filter.SLALess { - if filter.Status == nil || p.Result().Status == *filter.Status { - table += SLAHTMLSection(p.Result()) - cnt++ - } - } + table += SLAHTMLSection(p.Result()) } table += `
` - summary := "" - if filter != nil { - summary += filter.HTML() + " : " - } - summary += fmt.Sprintf(`( %d Probers found! )`, cnt) - html = html + summary + table + html = html + filter.HTML() + table timeFmt := "2006-01-02 15:04:05" if len(probers) > 0 { @@ -407,7 +381,7 @@ func SLALarkSection(r *probe.Result) string { return fmt.Sprintf(text, r.Name, r.Endpoint, DurationStr(r.Stat.UpTime), DurationStr(r.Stat.DownTime), r.SLAPercent(), r.Stat.Total, SLAStatusText(r.Stat, Lark), - time.Now().UTC().Format(r.TimeFormat), + r.StartTime.UTC().Format(r.TimeFormat), r.Status.Emoji()+" "+r.Status.String(), JSONEscape(r.Message)) } diff --git a/report/sla_test.go b/report/sla_test.go index 77451f96..d37de891 100644 --- a/report/sla_test.go +++ b/report/sla_test.go @@ -41,14 +41,14 @@ func (d *dummyProber) Config(g global.ProbeSettings) error { func (d *dummyProber) DoProbe() (bool, string) { return rand.Int()%2 == 0, "hello world" } - -var probes = []probe.Prober{ - newDummyProber("probe1"), - newDummyProber("probe2"), - newDummyProber("probe3"), - newDummyProber("probe4"), +func getProbers() []probe.Prober { + return []probe.Prober{ + newDummyProber("probe1"), + newDummyProber("probe2"), + newDummyProber("probe3"), + newDummyProber("probe4"), + } } - func newDummyProber(name string) probe.Prober { r := newDummyResult(name) return &dummyProber{ @@ -63,6 +63,7 @@ func newDummyProber(name string) probe.Prober { func TestSLA(t *testing.T) { global.InitEaseProbe("DummyProbe", "icon") + probes := getProbers() for f, fn := range FormatFuncs { sla := fn.StatFn(probes) assert.NotEmpty(t, sla) @@ -85,6 +86,7 @@ func TestSLAJSONSection(t *testing.T) { } func TestSLAFilter(t *testing.T) { + probes := getProbers() probes[0].Result().Status = probe.StatusUp probes[1].Result().Status = probe.StatusDown probes[2].Result().Status = probe.StatusUp @@ -95,19 +97,15 @@ func TestSLAFilter(t *testing.T) { assert.Contains(t, html, p.Name()) } - filter := SLAFilter{ - Status: nil, - SLAGreater: 0, - SLALess: 100, - } - html = SLAHTMLFilter(probes, &filter) + filter := NewEmptyFilter() + html = SLAHTMLFilter(probes, filter) for _, p := range probes { assert.Contains(t, html, p.Name()) } status := probe.StatusUp filter.Status = &status - html = SLAHTMLFilter(probes, &filter) + html = SLAHTMLFilter(probes, filter) assert.Contains(t, html, probes[0].Name()) assert.NotContains(t, html, probes[1].Name()) assert.Contains(t, html, probes[2].Name()) @@ -132,7 +130,7 @@ func TestSLAFilter(t *testing.T) { // sla between 50 - 90, status is up filter.SLAGreater = 50 filter.SLALess = 90 - html = SLAHTMLFilter(probes, &filter) + html = SLAHTMLFilter(probes, filter) assert.Contains(t, html, probes[0].Name()) assert.NotContains(t, html, probes[1].Name()) assert.NotContains(t, html, probes[2].Name()) diff --git a/web/server.go b/web/server.go index cc56658a..e4b714a8 100644 --- a/web/server.go +++ b/web/server.go @@ -18,6 +18,7 @@ package web import ( + "encoding/json" "fmt" "net" "net/http" @@ -52,6 +53,9 @@ func getRefreshInterval(refersh string) time.Duration { } func getStatus(status string) *probe.Status { + if status == "" { + return nil + } var s probe.Status s.Status(status) return &s @@ -63,53 +67,74 @@ func getFloat(f string, _default float64) float64 { } flt, err := strconv.ParseFloat(f, 64) if err != nil { - log.Errorf("[Web] Invalid float value: %s", err) + log.Debugf("[Web] Invalid float value: %s", err) return _default } return flt } -func checkFilter(filter report.SLAFilter) error { - log.Debugf("[Web] Check filter: %+v", filter) - if filter.SLAGreater > filter.SLALess { - return fmt.Errorf("Error: Invalid SLA filter: gte(%0.2f) > (%0.2f)", filter.SLAGreater, filter.SLALess) - } - if filter.SLAGreater > 100 || filter.SLAGreater < 0 { - return fmt.Errorf("Error: Invalid SLA filter: gte(%0.2f), it must be between 0 - 100", filter.SLAGreater) +func getInt(i string, _default int) int { + if i == "" { + return _default } - if filter.SLALess > 100 || filter.SLALess < 0 { - return fmt.Errorf("Error: Invalid SLA filter: lte(%0.2f), it must be between 0 - 100", filter.SLALess) + it, err := strconv.Atoi(i) + if err != nil { + log.Debugf("[Web] Invalid int value: %s", err) + return _default } - return nil + return it } -func slaHTML(w http.ResponseWriter, req *http.Request) { - interval := getRefreshInterval(req.URL.Query().Get("refresh")) - - filter := report.SLAFilter{} +func getFilter(req *http.Request) (*report.SLAFilter, error) { + filter := &report.SLAFilter{} - if req.URL.Query().Get("status") != "" { - filter.Status = getStatus(req.URL.Query().Get("status")) - } + filter.Name = strings.TrimSpace(req.URL.Query().Get("name")) + filter.Kind = strings.TrimSpace(req.URL.Query().Get("kind")) + filter.Endpoint = strings.TrimSpace(req.URL.Query().Get("ep")) + filter.Status = getStatus(req.URL.Query().Get("status")) + filter.Message = strings.TrimSpace(req.URL.Query().Get("msg")) filter.SLAGreater = getFloat(req.URL.Query().Get("gte"), 0) filter.SLALess = getFloat(req.URL.Query().Get("lte"), 100) + filter.PageNum = getInt(req.URL.Query().Get("pg"), 1) + filter.PageSize = getInt(req.URL.Query().Get("sz"), global.DefaultPageSize) - if err := checkFilter(filter); err != nil { + if err := filter.Check(); err != nil { log.Errorf(err.Error()) + return nil, err + } + return filter, nil +} + +func slaHTML(w http.ResponseWriter, req *http.Request) { + interval := getRefreshInterval(req.URL.Query().Get("refresh")) + + filter, err := getFilter(req) + if err != nil { w.Write([]byte(err.Error())) return } refresh := fmt.Sprintf("%d", interval.Milliseconds()) - html := []byte(report.SLAHTMLFilter(*probers, &filter) + report.AutoRefreshJS(refresh)) + html := []byte(report.SLAHTMLFilter(*probers, filter) + report.AutoRefreshJS(refresh)) w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Write(html) } func slaJSON(w http.ResponseWriter, req *http.Request) { + filter, err := getFilter(req) + if err != nil { + buf, e := json.Marshal(err) + if e != nil { + w.Write([]byte(err.Error())) + return + } + w.Write(buf) + return + } w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.Write([]byte(report.SLAJSON(*probers))) + _probers := filter.Filter(*probers) + w.Write([]byte(report.SLAJSON(_probers))) } // SetProbers set the probers