github.com/netdata/go.d.plugin@v0.58.1/modules/bind/xml3_client.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package bind
     4  
     5  import (
     6  	"encoding/xml"
     7  	"fmt"
     8  	"net/http"
     9  	"net/url"
    10  	"path"
    11  
    12  	"github.com/netdata/go.d.plugin/pkg/web"
    13  )
    14  
    15  type xml3Stats struct {
    16  	Server xml3Server `xml:"server"`
    17  	Views  []xml3View `xml:"views>view"`
    18  }
    19  
    20  type xml3Server struct {
    21  	CounterGroups []xml3CounterGroup `xml:"counters"`
    22  }
    23  
    24  type xml3CounterGroup struct {
    25  	Type     string `xml:"type,attr"`
    26  	Counters []struct {
    27  		Name  string `xml:"name,attr"`
    28  		Value int64  `xml:",chardata"`
    29  	} `xml:"counter"`
    30  }
    31  
    32  type xml3View struct {
    33  	Name          string             `xml:"name,attr"`
    34  	CounterGroups []xml3CounterGroup `xml:"counters"`
    35  }
    36  
    37  func newXML3Client(client *http.Client, request web.Request) *xml3Client {
    38  	return &xml3Client{httpClient: client, request: request}
    39  }
    40  
    41  type xml3Client struct {
    42  	httpClient *http.Client
    43  	request    web.Request
    44  }
    45  
    46  func (c xml3Client) serverStats() (*serverStats, error) {
    47  	req := c.request.Copy()
    48  	u, err := url.Parse(req.URL)
    49  	if err != nil {
    50  		return nil, fmt.Errorf("error on parsing URL: %v", err)
    51  	}
    52  
    53  	u.Path = path.Join(u.Path, "/server")
    54  	req.URL = u.String()
    55  
    56  	httpReq, err := web.NewHTTPRequest(req)
    57  	if err != nil {
    58  		return nil, fmt.Errorf("error on creating HTTP request: %v", err)
    59  	}
    60  
    61  	resp, err := c.httpClient.Do(httpReq)
    62  	if err != nil {
    63  		return nil, fmt.Errorf("error on request : %v", err)
    64  	}
    65  	defer closeBody(resp)
    66  
    67  	if resp.StatusCode != http.StatusOK {
    68  		return nil, fmt.Errorf("%s returned HTTP status %d", httpReq.URL, resp.StatusCode)
    69  	}
    70  
    71  	stats := xml3Stats{}
    72  	if err = xml.NewDecoder(resp.Body).Decode(&stats); err != nil {
    73  		return nil, fmt.Errorf("error on decoding response from %s : %v", httpReq.URL, err)
    74  	}
    75  	return convertXML(stats), nil
    76  }
    77  
    78  func convertXML(xmlStats xml3Stats) *serverStats {
    79  	stats := serverStats{
    80  		OpCodes:   make(map[string]int64),
    81  		NSStats:   make(map[string]int64),
    82  		QTypes:    make(map[string]int64),
    83  		SockStats: make(map[string]int64),
    84  		Views:     make(map[string]jsonView),
    85  	}
    86  
    87  	var m map[string]int64
    88  
    89  	for _, group := range xmlStats.Server.CounterGroups {
    90  		switch group.Type {
    91  		default:
    92  			continue
    93  		case "opcode":
    94  			m = stats.OpCodes
    95  		case "qtype":
    96  			m = stats.QTypes
    97  		case "nsstat":
    98  			m = stats.NSStats
    99  		case "sockstat":
   100  			m = stats.SockStats
   101  		}
   102  
   103  		for _, v := range group.Counters {
   104  			m[v.Name] = v.Value
   105  		}
   106  	}
   107  
   108  	for _, view := range xmlStats.Views {
   109  		stats.Views[view.Name] = jsonView{
   110  			Resolver: jsonViewResolver{
   111  				Stats:      make(map[string]int64),
   112  				QTypes:     make(map[string]int64),
   113  				CacheStats: make(map[string]int64),
   114  			},
   115  		}
   116  		for _, viewGroup := range view.CounterGroups {
   117  			switch viewGroup.Type {
   118  			default:
   119  				continue
   120  			case "resqtype":
   121  				m = stats.Views[view.Name].Resolver.QTypes
   122  			case "resstats":
   123  				m = stats.Views[view.Name].Resolver.Stats
   124  			case "cachestats":
   125  				m = stats.Views[view.Name].Resolver.CacheStats
   126  			}
   127  			for _, viewCounter := range viewGroup.Counters {
   128  				m[viewCounter.Name] = viewCounter.Value
   129  			}
   130  		}
   131  	}
   132  	return &stats
   133  }