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