netdata/netdata

View on GitHub
src/go/collectors/go.d.plugin/modules/bind/xml3_client.go

Summary

Maintainability
A
40 mins
Test Coverage
// SPDX-License-Identifier: GPL-3.0-or-later

package bind

import (
    "encoding/xml"
    "fmt"
    "net/http"
    "net/url"
    "path"

    "github.com/netdata/netdata/go/go.d.plugin/pkg/web"
)

type xml3Stats struct {
    Server xml3Server `xml:"server"`
    Views  []xml3View `xml:"views>view"`
}

type xml3Server struct {
    CounterGroups []xml3CounterGroup `xml:"counters"`
}

type xml3CounterGroup struct {
    Type     string `xml:"type,attr"`
    Counters []struct {
        Name  string `xml:"name,attr"`
        Value int64  `xml:",chardata"`
    } `xml:"counter"`
}

type xml3View struct {
    Name          string             `xml:"name,attr"`
    CounterGroups []xml3CounterGroup `xml:"counters"`
}

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

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

func (c xml3Client) serverStats() (*serverStats, error) {
    req := c.request.Copy()
    u, err := url.Parse(req.URL)
    if err != nil {
        return nil, fmt.Errorf("error on parsing URL: %v", err)
    }

    u.Path = path.Join(u.Path, "/server")
    req.URL = u.String()

    httpReq, err := web.NewHTTPRequest(req)
    if err != nil {
        return nil, fmt.Errorf("error on creating HTTP request: %v", err)
    }

    resp, err := c.httpClient.Do(httpReq)
    if err != nil {
        return nil, fmt.Errorf("error on request : %v", err)
    }
    defer closeBody(resp)

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

    stats := xml3Stats{}
    if err = xml.NewDecoder(resp.Body).Decode(&stats); err != nil {
        return nil, fmt.Errorf("error on decoding response from %s : %v", httpReq.URL, err)
    }
    return convertXML(stats), nil
}

func convertXML(xmlStats xml3Stats) *serverStats {
    stats := serverStats{
        OpCodes:   make(map[string]int64),
        NSStats:   make(map[string]int64),
        QTypes:    make(map[string]int64),
        SockStats: make(map[string]int64),
        Views:     make(map[string]jsonView),
    }

    var m map[string]int64

    for _, group := range xmlStats.Server.CounterGroups {
        switch group.Type {
        default:
            continue
        case "opcode":
            m = stats.OpCodes
        case "qtype":
            m = stats.QTypes
        case "nsstat":
            m = stats.NSStats
        case "sockstat":
            m = stats.SockStats
        }

        for _, v := range group.Counters {
            m[v.Name] = v.Value
        }
    }

    for _, view := range xmlStats.Views {
        stats.Views[view.Name] = jsonView{
            Resolver: jsonViewResolver{
                Stats:      make(map[string]int64),
                QTypes:     make(map[string]int64),
                CacheStats: make(map[string]int64),
            },
        }
        for _, viewGroup := range view.CounterGroups {
            switch viewGroup.Type {
            default:
                continue
            case "resqtype":
                m = stats.Views[view.Name].Resolver.QTypes
            case "resstats":
                m = stats.Views[view.Name].Resolver.Stats
            case "cachestats":
                m = stats.Views[view.Name].Resolver.CacheStats
            }
            for _, viewCounter := range viewGroup.Counters {
                m[viewCounter.Name] = viewCounter.Value
            }
        }
    }
    return &stats
}