Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
lighttpd2 fix (#154)
Browse files Browse the repository at this point in the history
* refactor

* minor config
  • Loading branch information
ilyam8 authored Feb 17, 2019
1 parent 8423ee0 commit 9ac5b81
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 205 deletions.
2 changes: 1 addition & 1 deletion config/go.d/apache.conf
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
#
# [ JOB defaults ]:
# url: http://localhost/server-status?auto
# timeout: 1
# timeout: 2
# method: GET
# not_follow_redirects: no
# tls_skip_verify: no
Expand Down
2 changes: 1 addition & 1 deletion config/go.d/lighttpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
#
# [ JOB defaults ]:
# url: http://localhost/server-status?auto
# timeout: 1
# timeout: 2
# method: GET
# not_follow_redirects: no
# tls_skip_verify: no
Expand Down
2 changes: 1 addition & 1 deletion config/go.d/lighttpd2.conf
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
#
# [ JOB defaults ]:
# url: http://localhost/server-status?auto
# timeout: 1
# timeout: 2
# method: GET
# not_follow_redirects: no
# tls_skip_verify: no
Expand Down
249 changes: 154 additions & 95 deletions modules/lighttpd2/apiclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,37 @@ import (
"github.com/netdata/go.d.plugin/pkg/web"
)

var validStatusKeys = map[string]bool{
"uptime": true,
"memory_usage": true,
"requests_abs": true,
"traffic_out_abs": true,
"traffic_in_abs": true,
"connections_abs": true,
"requests_avg": true,
"traffic_out_avg": true,
"traffic_in_avg": true,
"connections_avg": true,
"requests_avg_5sec": true,
"traffic_out_avg_5sec": true,
"traffic_in_avg_5sec": true,
"connections_avg_5sec": true,
"connection_state_start": true,
"connection_state_read_header": true,
"connection_state_handle_request": true,
"connection_state_write_response": true,
"connection_state_keep_alive": true,
"connection_state_upgraded": true,
"status_1xx": true,
"status_2xx": true,
"status_3xx": true,
"status_4xx": true,
"status_5xx": true,
type serverStatus struct {
Uptime *int `stm:"uptime"`
RequestsAbs *int `stm:"requests_abs"`
Status1xx *int `stm:"status_1xx"`
Status2xx *int `stm:"status_2xx"`
Status3xx *int `stm:"status_3xx"`
Status4xx *int `stm:"status_4xx"`
Status5xx *int `stm:"status_5xx"`
TrafficInAbs *int `stm:"traffic_in_abs"`
TrafficOutAbs *int `stm:"traffic_out_abs"`
ConnectionsAbs *int `stm:"connections_abs"`
ConnectionStateStart *int `stm:"connection_state_start"`
ConnectionStateReadHeader *int `stm:"connection_state_read_header"`
ConnectionStateHandleRequest *int `stm:"connection_state_handle_request"`
ConnectionStateWriteResponse *int `stm:"connection_state_write_response"`
ConnectionStateKeepAlive *int `stm:"connection_state_keepalive"`
ConnectionStateUpgraded *int `stm:"connection_state_upgraded"`
MemoryUsage *int `stm:"memory_usage"`
}

func newAPIClient(client *http.Client, request web.Request) *apiClient {
return &apiClient{httpClient: client, request: request}
}

type apiClient struct {
req web.Request
httpClient *http.Client
request web.Request
}

func (a apiClient) serverStatus() (map[string]int64, error) {
req, err := a.createRequest()
func (a apiClient) getServerStatus() (*serverStatus, error) {
req, err := web.NewHTTPRequest(a.request)

if err != nil {
return nil, fmt.Errorf("error on creating request : %v", err)
Expand All @@ -60,9 +56,29 @@ func (a apiClient) serverStatus() (map[string]int64, error) {
return nil, err
}

s := bufio.NewScanner(resp.Body)
status, err := parseResponse(resp.Body)

if err != nil {
return nil, fmt.Errorf("error on parsing response from %s : %v", req.URL, err)
}

return status, nil
}

func (a apiClient) doRequestOK(req *http.Request) (*http.Response, error) {
resp, err := a.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("error on request: %v", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%s returned HTTP status %d", req.URL, resp.StatusCode)
}
return resp, nil
}

status := make(map[string]string)
func parseResponse(respBody io.Reader) (*serverStatus, error) {
s := bufio.NewScanner(respBody)
status := &serverStatus{}

for s.Scan() {
line := s.Text()
Expand All @@ -72,77 +88,120 @@ func (a apiClient) serverStatus() (map[string]int64, error) {
}

parts := strings.Split(line, ":")

if len(parts) != 2 {
continue
}

status[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
}

metrics, err := a.parseStatus(status)

if err != nil {
return nil, fmt.Errorf("error on parsing status : %v", err)
}

return metrics, nil
}

func (a *apiClient) parseStatus(status map[string]string) (map[string]int64, error) {
metrics := make(map[string]int64)

for key, value := range status {

if _, ok := validStatusKeys[key]; !ok {
return nil, fmt.Errorf("unknown value : %s", key)
}

v, err := strconv.Atoi(value)

if err != nil {
return nil, err
key, value := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])

switch key {
default:
case "requests_abs":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.RequestsAbs = &v
}
case "memory_usage":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.MemoryUsage = &v
}
case "status_1xx":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.Status1xx = &v
}
case "status_2xx":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.Status2xx = &v
}
case "status_3xx":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.Status3xx = &v
}
case "status_4xx":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.Status4xx = &v
}
case "status_5xx":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.Status5xx = &v
}
case "traffic_in_abs":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.TrafficInAbs = &v
}
case "traffic_out_abs":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.TrafficOutAbs = &v
}
case "connections_abs":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.ConnectionsAbs = &v
}
case "connection_state_start":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.ConnectionStateStart = &v
}
case "connection_state_read_header":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.ConnectionStateReadHeader = &v
}
case "connection_state_handle_request":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.ConnectionStateHandleRequest = &v
}
case "connection_state_write_response":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.ConnectionStateWriteResponse = &v
}
case "connection_state_keep_alive":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.ConnectionStateKeepAlive = &v
}
case "connection_state_upgraded":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.ConnectionStateUpgraded = &v
}
case "uptime":
if v, err := strconv.Atoi(value); err != nil {
return nil, err
} else {
status.Uptime = &v
}
}

metrics[key] = int64(v)
}

return metrics, nil
}

func (a apiClient) doRequest(req *http.Request) (*http.Response, error) {
return a.httpClient.Do(req)
}

func (a apiClient) doRequestOK(req *http.Request) (*http.Response, error) {
var (
resp *http.Response
err error
)

if resp, err = a.doRequest(req); err != nil {
return resp, fmt.Errorf("error on request to %s : %v", req.URL, err)

}

if resp.StatusCode != http.StatusOK {
return resp, fmt.Errorf("%s returned HTTP status %d", req.URL, resp.StatusCode)
}

return resp, err
}

func (a apiClient) createRequest() (*http.Request, error) {
var (
req *http.Request
err error
)

if req, err = web.NewHTTPRequest(a.req); err != nil {
return nil, err
}

return req, nil
return status, nil
}

func closeBody(resp *http.Response) {
Expand Down
Loading

0 comments on commit 9ac5b81

Please sign in to comment.