github.com/netdata/go.d.plugin@v0.58.1/modules/solr/parser.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package solr 4 5 import ( 6 "encoding/json" 7 "errors" 8 "fmt" 9 "net/http" 10 "strings" 11 ) 12 13 type count struct { 14 Count int64 15 } 16 17 type common struct { 18 Count int64 19 MeanRate float64 `json:"meanRate"` 20 MinRate1min float64 `json:"1minRate"` 21 MinRate5min float64 `json:"5minRate"` 22 MinRate15min float64 `json:"15minRate"` 23 } 24 25 type requestTimes struct { 26 Count int64 27 MeanRate float64 `json:"meanRate"` 28 MinRate1min float64 `json:"1minRate"` 29 MinRate5min float64 `json:"5minRate"` 30 MinRate15min float64 `json:"15minRate"` 31 MinMS float64 `json:"min_ms"` 32 MaxMS float64 `json:"max_ms"` 33 MeanMS float64 `json:"mean_ms"` 34 MedianMS float64 `json:"median_ms"` 35 StdDevMS float64 `json:"stddev_ms"` 36 P75MS float64 `json:"p75_ms"` 37 P95MS float64 `json:"p95_ms"` 38 P99MS float64 `json:"p99_ms"` 39 P999MS float64 `json:"p999_ms"` 40 } 41 42 type coresMetrics struct { 43 Metrics map[string]map[string]json.RawMessage 44 } 45 46 func (s *Solr) parse(resp *http.Response) (map[string]int64, error) { 47 var cm coresMetrics 48 var metrics = make(map[string]int64) 49 50 if err := json.NewDecoder(resp.Body).Decode(&cm); err != nil { 51 return nil, err 52 } 53 54 if len(cm.Metrics) == 0 { 55 return nil, errors.New("unparsable data") 56 } 57 58 for core, data := range cm.Metrics { 59 coreName := core[10:] 60 61 if !s.cores[coreName] { 62 s.addCoreCharts(coreName) 63 s.cores[coreName] = true 64 } 65 66 if err := s.parseCore(coreName, data, metrics); err != nil { 67 return nil, err 68 } 69 } 70 71 return metrics, nil 72 } 73 74 func (s *Solr) parseCore(core string, data map[string]json.RawMessage, metrics map[string]int64) error { 75 var ( 76 simpleCount int64 77 count count 78 common common 79 requestTimes requestTimes 80 ) 81 82 for metric, stats := range data { 83 parts := strings.Split(metric, ".") 84 85 if len(parts) != 3 { 86 continue 87 } 88 89 typ, handler, stat := strings.ToLower(parts[0]), parts[1], parts[2] 90 91 if handler == "updateHandler" { 92 // TODO: 93 continue 94 } 95 96 switch stat { 97 case "clientErrors", "errors", "serverErrors", "timeouts": 98 if err := json.Unmarshal(stats, &common); err != nil { 99 return err 100 } 101 metrics[format("%s_%s_%s_count", core, typ, stat)] += common.Count 102 case "requests", "totalTime": 103 var c int64 104 if s.version < 7.0 { 105 if err := json.Unmarshal(stats, &count); err != nil { 106 return err 107 } 108 c = count.Count 109 } else { 110 if err := json.Unmarshal(stats, &simpleCount); err != nil { 111 return err 112 } 113 c = simpleCount 114 } 115 metrics[format("%s_%s_%s_count", core, typ, stat)] += c 116 case "requestTimes": 117 if err := json.Unmarshal(stats, &requestTimes); err != nil { 118 return err 119 } 120 metrics[format("%s_%s_%s_count", core, typ, stat)] += requestTimes.Count 121 metrics[format("%s_%s_%s_min_ms", core, typ, stat)] += int64(requestTimes.MinMS * 1e6) 122 metrics[format("%s_%s_%s_mean_ms", core, typ, stat)] += int64(requestTimes.MeanMS * 1e6) 123 metrics[format("%s_%s_%s_median_ms", core, typ, stat)] += int64(requestTimes.MedianMS * 1e6) 124 metrics[format("%s_%s_%s_max_ms", core, typ, stat)] += int64(requestTimes.MaxMS * 1e6) 125 metrics[format("%s_%s_%s_p75_ms", core, typ, stat)] += int64(requestTimes.P75MS * 1e6) 126 metrics[format("%s_%s_%s_p95_ms", core, typ, stat)] += int64(requestTimes.P95MS * 1e6) 127 metrics[format("%s_%s_%s_p99_ms", core, typ, stat)] += int64(requestTimes.P99MS * 1e6) 128 metrics[format("%s_%s_%s_p999_ms", core, typ, stat)] += int64(requestTimes.P999MS * 1e6) 129 } 130 } 131 132 return nil 133 } 134 135 func (s *Solr) addCoreCharts(core string) { 136 charts := charts.Copy() 137 138 for _, chart := range *charts { 139 chart.ID = format("%s_%s", core, chart.ID) 140 chart.Fam = format("core %s", core) 141 142 for _, dim := range chart.Dims { 143 dim.ID = format("%s_%s", core, dim.ID) 144 } 145 } 146 147 _ = s.charts.Add(*charts...) 148 149 } 150 151 var format = fmt.Sprintf