github.com/netdata/go.d.plugin@v0.58.1/modules/energid/collect.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package energid 4 5 import ( 6 "bytes" 7 "encoding/json" 8 "fmt" 9 "io" 10 "net/http" 11 12 "github.com/netdata/go.d.plugin/pkg/stm" 13 "github.com/netdata/go.d.plugin/pkg/web" 14 ) 15 16 const ( 17 jsonRPCVersion = "1.1" 18 19 methodGetBlockchainInfo = "getblockchaininfo" 20 methodGetMemPoolInfo = "getmempoolinfo" 21 methodGetNetworkInfo = "getnetworkinfo" 22 methodGetTXOutSetInfo = "gettxoutsetinfo" 23 methodGetMemoryInfo = "getmemoryinfo" 24 ) 25 26 var infoRequests = rpcRequests{ 27 {JSONRPC: jsonRPCVersion, ID: 1, Method: methodGetBlockchainInfo}, 28 {JSONRPC: jsonRPCVersion, ID: 2, Method: methodGetMemPoolInfo}, 29 {JSONRPC: jsonRPCVersion, ID: 3, Method: methodGetNetworkInfo}, 30 {JSONRPC: jsonRPCVersion, ID: 4, Method: methodGetTXOutSetInfo}, 31 {JSONRPC: jsonRPCVersion, ID: 5, Method: methodGetMemoryInfo}, 32 } 33 34 func (e *Energid) collect() (map[string]int64, error) { 35 responses, err := e.scrapeEnergid(infoRequests) 36 if err != nil { 37 return nil, err 38 } 39 40 info, err := e.collectInfoResponse(infoRequests, responses) 41 if err != nil { 42 return nil, err 43 } 44 45 return stm.ToMap(info), nil 46 } 47 48 func (e *Energid) collectInfoResponse(requests rpcRequests, responses rpcResponses) (*energidInfo, error) { 49 var info energidInfo 50 for _, req := range requests { 51 resp := responses.getByID(req.ID) 52 if resp == nil { 53 e.Warningf("method '%s' (id %d) not in responses", req.Method, req.ID) 54 continue 55 } 56 57 if resp.Error != nil { 58 e.Warningf("server returned an error on method '%s': %v", req.Method, resp.Error) 59 continue 60 } 61 62 var err error 63 switch req.Method { 64 case methodGetBlockchainInfo: 65 info.Blockchain, err = parseBlockchainInfo(resp.Result) 66 case methodGetMemPoolInfo: 67 info.MemPool, err = parseMemPoolInfo(resp.Result) 68 case methodGetNetworkInfo: 69 info.Network, err = parseNetworkInfo(resp.Result) 70 case methodGetTXOutSetInfo: 71 info.TxOutSet, err = parseTXOutSetInfo(resp.Result) 72 case methodGetMemoryInfo: 73 info.Memory, err = parseMemoryInfo(resp.Result) 74 } 75 if err != nil { 76 return nil, fmt.Errorf("parse '%s' method result: %v", req.Method, err) 77 } 78 } 79 80 return &info, nil 81 } 82 83 func parseBlockchainInfo(result []byte) (*blockchainInfo, error) { 84 var m blockchainInfo 85 if err := json.Unmarshal(result, &m); err != nil { 86 return nil, err 87 } 88 return &m, nil 89 } 90 91 func parseMemPoolInfo(result []byte) (*memPoolInfo, error) { 92 var m memPoolInfo 93 if err := json.Unmarshal(result, &m); err != nil { 94 return nil, err 95 } 96 return &m, nil 97 } 98 99 func parseNetworkInfo(result []byte) (*networkInfo, error) { 100 var m networkInfo 101 if err := json.Unmarshal(result, &m); err != nil { 102 return nil, err 103 } 104 return &m, nil 105 } 106 107 func parseTXOutSetInfo(result []byte) (*txOutSetInfo, error) { 108 var m txOutSetInfo 109 if err := json.Unmarshal(result, &m); err != nil { 110 return nil, err 111 } 112 return &m, nil 113 } 114 115 func parseMemoryInfo(result []byte) (*memoryInfo, error) { 116 var m memoryInfo 117 if err := json.Unmarshal(result, &m); err != nil { 118 return nil, err 119 } 120 return &m, nil 121 } 122 123 func (e *Energid) scrapeEnergid(requests rpcRequests) (rpcResponses, error) { 124 req, _ := web.NewHTTPRequest(e.Request) 125 req.Method = http.MethodPost 126 req.Header.Set("Content-Type", "application/json") 127 body, _ := json.Marshal(requests) 128 req.Body = io.NopCloser(bytes.NewReader(body)) 129 130 var resp rpcResponses 131 if err := e.doOKDecode(req, &resp); err != nil { 132 return nil, err 133 } 134 135 return resp, nil 136 } 137 138 func (e *Energid) doOKDecode(req *http.Request, in interface{}) error { 139 resp, err := e.httpClient.Do(req) 140 if err != nil { 141 return fmt.Errorf("error on HTTP request '%s': %v", req.URL, err) 142 } 143 defer closeBody(resp) 144 145 if resp.StatusCode != http.StatusOK { 146 return fmt.Errorf("'%s' returned HTTP status code: %d", req.URL, resp.StatusCode) 147 } 148 149 if err := json.NewDecoder(resp.Body).Decode(in); err != nil { 150 return fmt.Errorf("error on decoding response from '%s': %v", req.URL, err) 151 } 152 153 return nil 154 } 155 156 func closeBody(resp *http.Response) { 157 if resp != nil && resp.Body != nil { 158 _, _ = io.Copy(io.Discard, resp.Body) 159 _ = resp.Body.Close() 160 } 161 }