bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/scollector/collectors/httpunit.go (about) 1 package collectors 2 3 import ( 4 "fmt" 5 "time" 6 7 "bosun.org/slog" 8 9 "bosun.org/metadata" 10 "bosun.org/opentsdb" 11 "github.com/BurntSushi/toml" 12 "github.com/StackExchange/httpunit" 13 ) 14 15 func HTTPUnitTOML(filename string, freq time.Duration) error { 16 var plans httpunit.Plans 17 if _, err := toml.DecodeFile(filename, &plans); err != nil { 18 return err 19 } 20 HTTPUnitPlans(filename, &plans, freq) 21 return nil 22 } 23 24 func HTTPUnitHiera(filename string, freq time.Duration) error { 25 plans, err := httpunit.ExtractHiera(filename) 26 if err != nil { 27 return err 28 } 29 HTTPUnitPlans(filename, &httpunit.Plans{Plans: plans}, freq) 30 return nil 31 } 32 33 func HTTPUnitPlans(name string, plans *httpunit.Plans, freq time.Duration) { 34 collectors = append(collectors, &IntervalCollector{ 35 F: func() (opentsdb.MultiDataPoint, error) { 36 return cHTTPUnit(plans) 37 }, 38 name: fmt.Sprintf("c_httpunit_%s", name), 39 Interval: freq, 40 }) 41 } 42 43 func cHTTPUnit(plans *httpunit.Plans) (opentsdb.MultiDataPoint, error) { 44 ch, _, err := plans.Test("", false, nil, nil) 45 if err != nil { 46 return nil, err 47 } 48 unix_now := time.Now().Unix() 49 var md opentsdb.MultiDataPoint 50 for r := range ch { 51 if r == nil || r.Case == nil || r.Plan == nil { 52 slog.Errorf("httpunit: unexpected test plan on channel, the plan result, the case, and/or the plan result is missing.") 53 continue 54 } 55 tags := opentsdb.TagSet{ 56 "protocol": r.Case.URL.Scheme, 57 "ip": r.Case.IP.String(), 58 "url_host": r.Case.URL.Host, 59 "hc_test_case": r.Plan.Label, 60 } 61 metadata.AddMeta("", opentsdb.TagSet{"hc_test_case": r.Plan.Label}, "url", r.Case.URL.String(), false) 62 if r.Result == nil || r.Result.Result != nil { 63 Add(&md, "hu.error", true, tags, metadata.Gauge, metadata.Bool, descHTTPUnitError) 64 if r.Result == nil { 65 continue 66 } 67 } 68 Add(&md, "hu.error", false, tags, metadata.Gauge, metadata.Bool, descHTTPUnitError) 69 ms := int64(r.Result.TimeTotal / time.Millisecond) 70 Add(&md, "hu.socket_connected", r.Result.Connected, tags, metadata.Gauge, metadata.Bool, descHTTPUnitSocketConnected) 71 Add(&md, "hu.time_total", ms, tags, metadata.Gauge, metadata.MilliSecond, descHTTPUnitTotalTime) 72 code := 0 73 if r.Result.Resp != nil { 74 code = r.Result.Resp.StatusCode 75 } 76 Add(&md, "hu.response_code", code, tags, metadata.Gauge, metadata.StatusCode, descHTTPUnitStatusCode) 77 switch r.Case.URL.Scheme { 78 case "http", "https": 79 Add(&md, "hu.http.got_expected_code", r.Result.GotCode, tags, metadata.Gauge, metadata.Bool, descHTTPUnitExpectedCode) 80 Add(&md, "hu.http.got_expected_text", r.Result.GotText, tags, metadata.Gauge, metadata.Bool, descHTTPUnitExpectedText) 81 Add(&md, "hu.http.got_expected_regex", r.Result.GotRegex, tags, metadata.Gauge, metadata.Bool, descHTTPUnitExpectedRegex) 82 if r.Case.URL.Scheme == "https" { 83 Add(&md, "hu.cert.valid", !r.Result.InvalidCert, tags, metadata.Gauge, metadata.Bool, descHTTPUnitCertValid) 84 if resp := r.Result.Resp; resp != nil && resp.TLS != nil && len(resp.TLS.PeerCertificates) > 0 { 85 expiration := resp.TLS.PeerCertificates[0].NotAfter.Unix() 86 Add(&md, "hu.cert.expires", expiration, tags, metadata.Gauge, metadata.Timestamp, descHTTPUnitCertExpires) 87 Add(&md, "hu.cert.valid_for", expiration-unix_now, tags, metadata.Gauge, metadata.Second, descHTTPUnitCertValidFor) 88 } 89 } 90 } 91 } 92 return md, nil 93 } 94 95 const ( 96 descHTTPUnitError = "1 if any error (no connection, unexpected code or text) occurred, else 0." 97 descHTTPUnitSocketConnected = "1 if a connection was made, else 0." 98 descHTTPUnitExpectedCode = "1 if the HTTP status code was expected, else 0." 99 descHTTPUnitExpectedText = "1 if the response contained expected text, else 0." 100 descHTTPUnitExpectedRegex = "1 if the response matched expected regex, else 0." 101 descHTTPUnitCertValid = "1 if the SSL certificate is valid, else 0." 102 descHTTPUnitCertExpires = "Unix epoch time of the certificate expiration." 103 descHTTPUnitCertValidFor = "Number of seconds until certificate expiration." 104 descHTTPUnitTotalTime = "Total time consumed by test case." 105 descHTTPUnitStatusCode = "The HTTP status response code of the response, or 0 if no response." 106 )