summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/solr
diff options
context:
space:
mode:
authorAustin S. Hemmelgarn <austin@netdata.cloud>2024-02-13 06:56:20 -0500
committerGitHub <noreply@github.com>2024-02-13 06:56:20 -0500
commit3a29b66132f561c910d827e8c7ae82997f7c1f30 (patch)
treea9306156631b6b188de8877f7c1dbdbe8b067804 /src/go/collectors/go.d.plugin/modules/solr
parent57eec3da0e51baa400037ccc4b547cb839ab6ffa (diff)
Include Go plugin sources in main repository. (#16997)
* Include Go plugin sources in main repository. * Fix CI issues. * Rename source tree.
Diffstat (limited to 'src/go/collectors/go.d.plugin/modules/solr')
l---------src/go/collectors/go.d.plugin/modules/solr/README.md1
-rw-r--r--src/go/collectors/go.d.plugin/modules/solr/charts.go141
-rw-r--r--src/go/collectors/go.d.plugin/modules/solr/config_schema.json59
-rw-r--r--src/go/collectors/go.d.plugin/modules/solr/integrations/solr.md223
-rw-r--r--src/go/collectors/go.d.plugin/modules/solr/metadata.yaml268
-rw-r--r--src/go/collectors/go.d.plugin/modules/solr/parser.go151
-rw-r--r--src/go/collectors/go.d.plugin/modules/solr/solr.go212
-rw-r--r--src/go/collectors/go.d.plugin/modules/solr/solr_test.go274
-rw-r--r--src/go/collectors/go.d.plugin/modules/solr/testdata/core-metrics-v6.txt794
-rw-r--r--src/go/collectors/go.d.plugin/modules/solr/testdata/core-metrics-v7.txt732
10 files changed, 2855 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/solr/README.md b/src/go/collectors/go.d.plugin/modules/solr/README.md
new file mode 120000
index 0000000000..0bca1b31a6
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/solr/README.md
@@ -0,0 +1 @@
+integrations/solr.md \ No newline at end of file
diff --git a/src/go/collectors/go.d.plugin/modules/solr/charts.go b/src/go/collectors/go.d.plugin/modules/solr/charts.go
new file mode 100644
index 0000000000..caaa72489b
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/solr/charts.go
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package solr
+
+import (
+ "github.com/netdata/go.d.plugin/agent/module"
+)
+
+type (
+ // Charts is an alias for module.Charts
+ Charts = module.Charts
+ // Dims is an alias for module.Dims
+ Dims = module.Dims
+)
+
+var charts = Charts{
+ {
+ ID: "search_requests",
+ Title: "Search Requests",
+ Units: "requests/s",
+ Ctx: "solr.search_requests",
+ Dims: Dims{
+ {ID: "query_requests_count", Name: "search", Algo: module.Incremental},
+ },
+ },
+ {
+ ID: "search_errors",
+ Title: "Search Errors",
+ Units: "errors/s",
+ Ctx: "solr.search_errors",
+ Dims: Dims{
+ {ID: "query_errors_count", Name: "errors", Algo: module.Incremental},
+ },
+ },
+ {
+ ID: "search_errors_by_type",
+ Title: "Search Errors By Type",
+ Units: "errors/s",
+ Ctx: "solr.search_errors_by_type",
+ Dims: Dims{
+ {ID: "query_clientErrors_count", Name: "client", Algo: module.Incremental},
+ {ID: "query_serverErrors_count", Name: "server", Algo: module.Incremental},
+ {ID: "query_timeouts_count", Name: "timeouts", Algo: module.Incremental},
+ },
+ },
+ {
+ ID: "search_requests_processing_time",
+ Title: "Search Requests Processing Time",
+ Units: "milliseconds",
+ Ctx: "solr.search_requests_processing_time",
+ Dims: Dims{
+ {ID: "query_totalTime_count", Name: "time", Algo: module.Incremental},
+ },
+ },
+ {
+ ID: "search_requests_timings",
+ Title: "Search Requests Timings",
+ Units: "milliseconds",
+ Ctx: "solr.search_requests_timings",
+ Dims: Dims{
+ {ID: "query_requestTimes_min_ms", Name: "min", Div: 1000000},
+ {ID: "query_requestTimes_median_ms", Name: "median", Div: 1000000},
+ {ID: "query_requestTimes_mean_ms", Name: "mean", Div: 1000000},
+ {ID: "query_requestTimes_max_ms", Name: "max", Div: 1000000},
+ },
+ },
+ {
+ ID: "search_requests_processing_time_percentile",
+ Title: "Search Requests Processing Time Percentile",
+ Units: "milliseconds",
+ Ctx: "solr.search_requests_processing_time_percentile",
+ Dims: Dims{
+ {ID: "query_requestTimes_p75_ms", Name: "p75", Div: 1000000},
+ {ID: "query_requestTimes_p95_ms", Name: "p95", Div: 1000000},
+ {ID: "query_requestTimes_p99_ms", Name: "p99", Div: 1000000},
+ {ID: "query_requestTimes_p999_ms", Name: "p999", Div: 1000000},
+ },
+ },
+ {
+ ID: "update_requests",
+ Title: "Update Requests",
+ Units: "requests/s",
+ Ctx: "solr.update_requests",
+ Dims: Dims{
+ {ID: "update_requests_count", Name: "update", Algo: module.Incremental},
+ },
+ },
+ {
+ ID: "update_errors",
+ Title: "Update Errors",
+ Units: "errors/s",
+ Ctx: "solr.update_errors",
+ Dims: Dims{
+ {ID: "update_errors_count", Name: "errors", Algo: module.Incremental},
+ },
+ },
+ {
+ ID: "update_errors_by_type",
+ Title: "Update Errors By Type",
+ Units: "errors/s",
+ Ctx: "solr.update_errors_by_type",
+ Dims: Dims{
+ {ID: "update_clientErrors_count", Name: "client", Algo: module.Incremental},
+ {ID: "update_serverErrors_count", Name: "server", Algo: module.Incremental},
+ {ID: "update_timeouts_count", Name: "timeouts", Algo: module.Incremental},
+ },
+ },
+ {
+ ID: "update_requests_processing_time",
+ Title: "Update Requests Processing Time",
+ Units: "milliseconds",
+ Ctx: "solr.update_requests_processing_time",
+ Dims: Dims{
+ {ID: "update_totalTime_count", Name: "time", Algo: module.Incremental},
+ },
+ },
+ {
+ ID: "update_requests_timings",
+ Title: "Update Requests Timings",
+ Units: "milliseconds",
+ Ctx: "solr.update_requests_timings",
+ Dims: Dims{
+ {ID: "update_requestTimes_min_ms", Name: "min", Div: 1000000},
+ {ID: "update_requestTimes_median_ms", Name: "median", Div: 1000000},
+ {ID: "update_requestTimes_mean_ms", Name: "mean", Div: 1000000},
+ {ID: "update_requestTimes_max_ms", Name: "max", Div: 1000000},
+ },
+ },
+ {
+ ID: "update_requests_processing_time_percentile",
+ Title: "Update Requests Processing Time Percentile",
+ Units: "milliseconds",
+ Ctx: "solr.update_requests_processing_time_percentile",
+ Dims: Dims{
+ {ID: "update_requestTimes_p75_ms", Name: "p75", Div: 1000000},
+ {ID: "update_requestTimes_p95_ms", Name: "p95", Div: 1000000},
+ {ID: "update_requestTimes_p99_ms", Name: "p99", Div: 1000000},
+ {ID: "update_requestTimes_p999_ms", Name: "p999", Div: 1000000},
+ },
+ },
+}
diff --git a/src/go/collectors/go.d.plugin/modules/solr/config_schema.json b/src/go/collectors/go.d.plugin/modules/solr/config_schema.json
new file mode 100644
index 0000000000..66dde58bf8
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/solr/config_schema.json
@@ -0,0 +1,59 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "go.d/solr job configuration schema.",
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ },
+ "timeout": {
+ "type": [
+ "string",
+ "integer"
+ ]
+ },
+ "username": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "proxy_url": {
+ "type": "string"
+ },
+ "proxy_username": {
+ "type": "string"
+ },
+ "proxy_password": {
+ "type": "string"
+ },
+ "headers": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "not_follow_redirects": {
+ "type": "boolean"
+ },
+ "tls_ca": {
+ "type": "string"
+ },
+ "tls_cert": {
+ "type": "string"
+ },
+ "tls_key": {
+ "type": "string"
+ },
+ "insecure_skip_verify": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "name",
+ "url"
+ ]
+}
diff --git a/src/go/collectors/go.d.plugin/modules/solr/integrations/solr.md b/src/go/collectors/go.d.plugin/modules/solr/integrations/solr.md
new file mode 100644
index 0000000000..9afebfd17e
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/solr/integrations/solr.md
@@ -0,0 +1,223 @@
+<!--startmeta
+custom_edit_url: "https://github.com/netdata/go.d.plugin/edit/master/modules/solr/README.md"
+meta_yaml: "https://github.com/netdata/go.d.plugin/edit/master/modules/solr/metadata.yaml"
+sidebar_label: "Solr"
+learn_status: "Published"
+learn_rel_path: "Data Collection/Search Engines"
+most_popular: False
+message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE COLLECTOR'S metadata.yaml FILE"
+endmeta-->
+
+# Solr
+
+
+<img src="https://netdata.cloud/img/solr.svg" width="150"/>
+
+
+Plugin: go.d.plugin
+Module: solr
+
+<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" />
+
+## Overview
+
+This collector monitors Solr instances.
+
+
+
+
+This collector is supported on all platforms.
+
+This collector supports collecting metrics from multiple instances of this integration, including remote instances.
+
+
+### Default Behavior
+
+#### Auto-Detection
+
+This integration doesn't support auto-detection.
+
+#### Limits
+
+The default configuration for this integration does not impose any limits on data collection.
+
+#### Performance Impact
+
+The default configuration for this integration is not expected to impose a significant performance impact on the system.
+
+
+## Metrics
+
+Metrics grouped by *scope*.
+
+The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels.
+
+
+
+### Per Solr instance
+
+These metrics refer to the entire monitored application.
+
+This scope has no labels.
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| solr.search_requests | search | requests/s |
+| solr.search_errors | errors | errors/s |
+| solr.search_errors_by_type | client, server, timeouts | errors/s |
+| solr.search_requests_processing_time | time | milliseconds |
+| solr.search_requests_timings | min, median, mean, max | milliseconds |
+| solr.search_requests_processing_time_percentile | p75, p95, p99, p999 | milliseconds |
+| solr.update_requests | search | requests/s |
+| solr.update_errors | errors | errors/s |
+| solr.update_errors_by_type | client, server, timeouts | errors/s |
+| solr.update_requests_processing_time | time | milliseconds |
+| solr.update_requests_timings | min, median, mean, max | milliseconds |
+| solr.update_requests_processing_time_percentile | p75, p95, p99, p999 | milliseconds |
+
+
+
+## Alerts
+
+There are no alerts configured by default for this integration.
+
+
+## Setup
+
+### Prerequisites
+
+#### Solr version 6.4+
+
+This collector does not work with Solr versions lower 6.4.
+
+
+
+### Configuration
+
+#### File
+
+The configuration file name for this integration is `go.d/solr.conf`.
+
+
+You can edit the configuration file using the `edit-config` script from the
+Netdata [config directory](https://github.com/netdata/netdata/blob/master/docs/configure/nodes.md#the-netdata-config-directory).
+
+```bash
+cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata
+sudo ./edit-config go.d/solr.conf
+```
+#### Options
+
+The following options can be defined globally: update_every, autodetection_retry.
+
+
+<details><summary>All options</summary>
+
+| Name | Description | Default | Required |
+|:----|:-----------|:-------|:--------:|
+| update_every | Data collection frequency. | 1 | no |
+| autodetection_retry | Recheck interval in seconds. Zero means no recheck will be scheduled. | 0 | no |
+| url | Server URL. | http://127.0.0.1:8983 | yes |
+| socket | Server Unix socket. | | no |
+| address | Server address in IP:PORT format. | | no |
+| fcgi_path | Status path. | /status | no |
+| timeout | HTTP request timeout. | 1 | no |
+| username | Username for basic HTTP authentication. | | no |
+| password | Password for basic HTTP authentication. | | no |
+| proxy_url | Proxy URL. | | no |
+| proxy_username | Username for proxy basic HTTP authentication. | | no |
+| proxy_password | Password for proxy basic HTTP authentication. | | no |
+| method | HTTP request method. | GET | no |
+| body | HTTP request body. | | no |
+| headers | HTTP request headers. | | no |
+| not_follow_redirects | Redirect handling policy. Controls whether the client follows redirects. | no | no |
+| tls_skip_verify | Server certificate chain and hostname validation policy. Controls whether the client performs this check. | no | no |
+| tls_ca | Certification authority that the client uses when verifying the server's certificates. | | no |
+| tls_cert | Client TLS certificate. | | no |
+| tls_key | Client TLS key. | | no |
+
+</details>
+
+#### Examples
+
+##### Basic
+
+An example configuration.
+
+<details><summary>Config</summary>
+
+```yaml
+jobs:
+ - name: local
+ url: http://localhost:8983
+
+```
+</details>
+
+##### Basic HTTP auth
+
+Local Solr instance with basic HTTP authentication.
+
+<details><summary>Config</summary>
+
+```yaml
+jobs:
+ - name: local
+ url: http://localhost:8983
+ username: foo
+ password: bar
+
+```
+</details>
+
+##### Multi-instance
+
+> **Note**: When you define multiple jobs, their names must be unique.
+
+Local and remote instances.
+
+
+<details><summary>Config</summary>
+
+```yaml
+jobs:
+ - name: local
+ url: http://localhost:8983
+
+ - name: remote
+ url: http://203.0.113.10:8983
+
+```
+</details>
+
+
+
+## Troubleshooting
+
+### Debug Mode
+
+To troubleshoot issues with the `solr` collector, run the `go.d.plugin` with the debug option enabled. The output
+should give you clues as to why the collector isn't working.
+
+- Navigate to the `plugins.d` directory, usually at `/usr/libexec/netdata/plugins.d/`. If that's not the case on
+ your system, open `netdata.conf` and look for the `plugins` setting under `[directories]`.
+
+ ```bash
+ cd /usr/libexec/netdata/plugins.d/
+ ```
+
+- Switch to the `netdata` user.
+
+ ```bash
+ sudo -u netdata -s
+ ```
+
+- Run the `go.d.plugin` to debug the collector:
+
+ ```bash
+ ./go.d.plugin -d -m solr
+ ```
+
+
diff --git a/src/go/collectors/go.d.plugin/modules/solr/metadata.yaml b/src/go/collectors/go.d.plugin/modules/solr/metadata.yaml
new file mode 100644
index 0000000000..066744f634
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/solr/metadata.yaml
@@ -0,0 +1,268 @@
+plugin_name: go.d.plugin
+modules:
+ - meta:
+ id: collector-go.d.plugin-solr
+ plugin_name: go.d.plugin
+ module_name: solr
+ monitored_instance:
+ name: Solr
+ link: https://lucene.apache.org/solr/
+ icon_filename: solr.svg
+ categories:
+ - data-collection.search-engines
+ keywords:
+ - solr
+ related_resources:
+ integrations:
+ list: []
+ info_provided_to_referring_integrations:
+ description: ""
+ most_popular: false
+ overview:
+ data_collection:
+ metrics_description: |
+ This collector monitors Solr instances.
+ method_description: ""
+ supported_platforms:
+ include: []
+ exclude: []
+ multi_instance: true
+ additional_permissions:
+ description: ""
+ default_behavior:
+ auto_detection:
+ description: ""
+ limits:
+ description: ""
+ performance_impact:
+ description: ""
+ setup:
+ prerequisites:
+ list:
+ - title: Solr version 6.4+
+ description: |
+ This collector does not work with Solr versions lower 6.4.
+ configuration:
+ file:
+ name: go.d/solr.conf
+ options:
+ description: |
+ The following options can be defined globally: update_every, autodetection_retry.
+ folding:
+ title: All options
+ enabled: true
+ list:
+ - name: update_every
+ description: Data collection frequency.
+ default_value: 1
+ required: false
+ - name: autodetection_retry
+ description: Recheck interval in seconds. Zero means no recheck will be scheduled.
+ default_value: 0
+ required: false
+ - name: url
+ description: Server URL.
+ default_value: http://127.0.0.1:8983
+ required: true
+ - name: socket
+ description: Server Unix socket.
+ default_value: ""
+ required: false
+ - name: address
+ description: Server address in IP:PORT format.
+ default_value: ""
+ required: false
+ - name: fcgi_path
+ description: Status path.
+ default_value: /status
+ required: false
+ - name: timeout
+ description: HTTP request timeout.
+ default_value: 1
+ required: false
+ - name: username
+ description: Username for basic HTTP authentication.
+ default_value: ""
+ required: false
+ - name: password
+ description: Password for basic HTTP authentication.
+ default_value: ""
+ required: false
+ - name: proxy_url
+ description: Proxy URL.
+ default_value: ""
+ required: false
+ - name: proxy_username
+ description: Username for proxy basic HTTP authentication.
+ default_value: ""
+ required: false
+ - name: proxy_password
+ description: Password for proxy basic HTTP authentication.
+ default_value: ""
+ required: false
+ - name: method
+ description: HTTP request method.
+ default_value: GET
+ required: false
+ - name: body
+ description: HTTP request body.
+ default_value: ""
+ required: false
+ - name: headers
+ description: HTTP request headers.
+ default_value: ""
+ required: false
+ - name: not_follow_redirects
+ description: Redirect handling policy. Controls whether the client follows redirects.
+ default_value: false
+ required: false
+ - name: tls_skip_verify
+ description: Server certificate chain and hostname validation policy. Controls whether the client performs this check.
+ default_value: false
+ required: false
+ - name: tls_ca
+ description: Certification authority that the client uses when verifying the server's certificates.
+ default_value: ""
+ required: false
+ - name: tls_cert
+ description: Client TLS certificate.
+ default_value: ""
+ required: false
+ - name: tls_key
+ description: Client TLS key.
+ default_value: ""
+ required: false
+ examples:
+ folding:
+ title: Config
+ enabled: true
+ list:
+ - name: Basic
+ description: An example configuration.
+ config: |
+ jobs:
+ - name: local
+ url: http://localhost:8983
+ - name: Basic HTTP auth
+ description: Local Solr instance with basic HTTP authentication.
+ config: |
+ jobs:
+ - name: local
+ url: http://localhost:8983
+ username: foo
+ password: bar
+ - name: Multi-instance
+ description: |
+ > **Note**: When you define multiple jobs, their names must be unique.
+
+ Local and remote instances.
+ config: |
+ jobs:
+ - name: local
+ url: http://localhost:8983
+
+ - name: remote
+ url: http://203.0.113.10:8983
+ troubleshooting:
+ problems:
+ list: []
+ alerts: []
+ metrics:
+ folding:
+ title: Metrics
+ enabled: false
+ description: ""
+ availability: []
+ scopes:
+ - name: global
+ description: These metrics refer to the entire monitored application.
+ labels: []
+ metrics:
+ - name: solr.search_requests
+ description: Search Requests
+ unit: requests/s
+ chart_type: line
+ dimensions:
+ - name: search
+ - name: solr.search_errors
+ description: Search Errors
+ unit: errors/s
+ chart_type: line
+ dimensions:
+ - name: errors
+ - name: solr.search_errors_by_type
+ description: Search Errors By Type
+ unit: errors/s
+ chart_type: line
+ dimensions:
+ - name: client
+ - name: server
+ - name: timeouts
+ - name: solr.search_requests_processing_time
+ description: Search Requests Processing Time
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: time
+ - name: solr.search_requests_timings
+ description: Search Requests Timings
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: min
+ - name: median
+ - name: mean
+ - name: max
+ - name: solr.search_requests_processing_time_percentile
+ description: Search Requests Processing Time Percentile
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: p75
+ - name: p95
+ - name: p99
+ - name: p999
+ - name: solr.update_requests
+ description: Update Requests
+ unit: requests/s
+ chart_type: line
+ dimensions:
+ - name: search
+ - name: solr.update_errors
+ description: Update Errors
+ unit: errors/s
+ chart_type: line
+ dimensions:
+ - name: errors
+ - name: solr.update_errors_by_type
+ description: Update Errors By Type
+ unit: errors/s
+ chart_type: line
+ dimensions:
+ - name: client
+ - name: server
+ - name: timeouts
+ - name: solr.update_requests_processing_time
+ description: Update Requests Processing Time
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: time
+ - name: solr.update_requests_timings
+ description: Update Requests Timings
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: min
+ - name: median
+ - name: mean
+ - name: max
+ - name: solr.update_requests_processing_time_percentile
+ description: Update Requests Processing Time Percentile
+ unit: milliseconds
+ chart_type: line
+ dimensions:
+ - name: p75
+ - name: p95
+ - name: p99
+ - name: p999
diff --git a/src/go/collectors/go.d.plugin/modules/solr/parser.go b/src/go/collectors/go.d.plugin/modules/solr/parser.go
new file mode 100644
index 0000000000..c8a9eaa54a
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/solr/parser.go
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package solr
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "strings"
+)
+
+type count struct {
+ Count int64
+}
+
+type common struct {
+ Count int64
+ MeanRate float64 `json:"meanRate"`
+ MinRate1min float64 `json:"1minRate"`
+ MinRate5min float64 `json:"5minRate"`
+ MinRate15min float64 `json:"15minRate"`
+}
+
+type requestTimes struct {
+ Count int64
+ MeanRate float64 `json:"meanRate"`
+ MinRate1min float64 `json:"1minRate"`
+ MinRate5min float64 `json:"5minRate"`
+ MinRate15min float64 `json:"15minRate"`
+ MinMS float64 `json:"min_ms"`
+ MaxMS float64 `json:"max_ms"`
+ MeanMS float64 `json:"mean_ms"`
+ MedianMS float64 `json:"median_ms"`
+ StdDevMS float64 `json:"stddev_ms"`
+ P75MS float64 `json:"p75_ms"`
+ P95MS float64 `json:"p95_ms"`
+ P99MS float64 `json:"p99_ms"`
+ P999MS float64 `json:"p999_ms"`
+}
+
+type coresMetrics struct {
+ Metrics map[string]map[string]json.RawMessage
+}
+
+func (s *Solr) parse(resp *http.Response) (map[string]int64, error) {
+ var cm coresMetrics
+ var metrics = make(map[string]int64)
+
+ if err := json.NewDecoder(resp.Body).Decode(&cm); err != nil {
+ return nil, err
+ }
+
+ if len(cm.Metrics) == 0 {
+ return nil, errors.New("unparsable data")
+ }
+
+ for core, data := range cm.Metrics {
+ coreName := core[10:]
+
+ if !s.cores[coreName] {
+ s.addCoreCharts(coreName)
+ s.cores[coreName] = true
+ }
+
+ if err := s.parseCore(coreName, data, metrics); err != nil {
+ return nil, err
+ }
+ }
+
+ return metrics, nil
+}
+
+func (s *Solr) parseCore(core string, data map[string]json.RawMessage, metrics map[string]int64) error {
+ var (
+ simpleCount int64
+ count count
+ common common
+ requestTimes requestTimes
+ )
+
+ for metric, stats := range data {
+ parts := strings.Split(metric, ".")
+
+ if len(parts) != 3 {
+ continue
+ }
+
+ typ, handler, stat := strings.ToLower(parts[0]), parts[1], parts[2]
+
+ if handler == "updateHandler" {
+ // TODO:
+ continue
+ }
+
+ switch stat {
+ case "clientErrors", "errors", "serverErrors", "timeouts":
+ if err := json.Unmarshal(stats, &common); err != nil {
+ return err
+ }
+ metrics[format("%s_%s_%s_count", core, typ, stat)] += common.Count
+ case "requests", "totalTime":
+ var c int64
+ if s.version < 7.0 {
+ if err := json.Unmarshal(stats, &count); err != nil {
+ return err
+ }
+ c = count.Count
+ } else {
+ if err := json.Unmarshal(stats, &simpleCount); err != nil {
+ return err
+ }
+ c = simpleCount
+ }
+ metrics[format("%s_%s_%s_count", core, typ, stat)] += c
+ case "requestTimes":
+ if err := json.Unmarshal(stats, &requestTimes); err != nil {
+ return err
+ }
+ metrics[format("%s_%s_%s_count", core, typ, stat)] += requestTimes.Count
+ metrics[format("%s_%s_%s_min_ms", core, typ, stat)] += int64(requestTimes.MinMS * 1e6)
+ metrics[format("%s_%s_%s_mean_ms", core, typ, stat)] += int64(requestTimes.MeanMS * 1e6)
+ metrics[format("%s_%s_%s_median_ms", core, typ, stat)] += int64(requestTimes.MedianMS * 1e6)
+ metrics[format("%s_%s_%s_max_ms", core, typ, stat)] += int64(requestTimes.MaxMS * 1e6)
+ metrics[format("%s_%s_%s_p75_ms", core, typ, stat)] += int64(requestTimes.P75MS * 1e6)
+ metrics[format("%s_%s_%s_p95_ms", core, typ, stat)] += int64(requestTimes.P95MS * 1e6)
+ metrics[format("%s_%s_%s_p99_ms", core, typ, stat)] += int64(requestTimes.P99MS * 1e6)
+ metrics[format("%s_%s_%s_p999_ms", core, typ, stat)] += int64(requestTimes.P999MS * 1e6)
+ }
+ }
+
+ return nil
+}
+
+func (s *Solr) addCoreCharts(core string) {
+ charts := charts.Copy()
+
+ for _, chart := range *charts {
+ chart.ID = format("%s_%s", core, chart.ID)
+ chart.Fam = format("core %s", core)
+
+ for _, dim := range chart.Dims {
+ dim.ID = format("%s_%s", core, dim.ID)
+ }
+ }
+
+ _ = s.charts.Add(*charts...)
+
+}
+
+var format = fmt.Sprintf
diff --git a/src/go/collectors/go.d.plugin/modules/solr/solr.go b/src/go/collectors/go.d.plugin/modules/solr/solr.go
new file mode 100644
index 0000000000..57f2d7083b
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/solr/solr.go
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package solr
+
+import (
+ _ "embed"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/netdata/go.d.plugin/pkg/web"
+
+ "github.com/netdata/go.d.plugin/agent/module"
+)
+
+//go:embed "config_schema.json"
+var configSchema string
+
+func init() {
+ module.Register("solr", module.Creator{
+ JobConfigSchema: configSchema,
+ Create: func() module.Module { return New() },
+ })
+}
+
+const (
+ defaultURL = "http://127.0.0.1:8983"
+ defaultHTTPTimeout = time.Second
+)
+
+const (
+ minSupportedVersion = 6.4
+ coresHandlersURLPath = "/solr/admin/metrics"
+ coresHandlersURLQuery = "group=core&prefix=UPDATE,QUERY&wt=json"
+ infoSystemURLPath = "/solr/admin/info/system"
+ infoSystemURLQuery = "wt=json"
+)
+
+type infoSystem struct {
+ Lucene struct {
+ Version string `json:"solr-spec-version"`
+ }
+}
+
+// New creates Solr with default values
+func New() *Solr {
+ config := Config{
+ HTTP: web.HTTP{
+ Request: web.Request{
+ URL: defaultURL,
+ },
+ Client: web.Client{
+ Timeout: web.Duration{Duration: defaultHTTPTimeout},
+ },
+ },
+ }
+ return &Solr{
+ Config: config,
+ cores: make(map[string]bool),
+ }
+}
+
+// Config is the Solr module configuration.
+type Config struct {
+ web.HTTP `yaml:",inline"`
+}
+
+// Solr solr module
+type Solr struct {
+ module.Base
+ Config `yaml:",inline"`
+
+ cores map[string]bool
+ client *http.Client
+ version float64
+ charts *Charts
+}
+
+func (s *Solr) doRequest(req *http.Request) (*http.Response, error) {
+ return s.client.Do(req)
+}
+
+// Cleanup makes cleanup
+func (Solr) Cleanup() {}
+
+// Init makes initialization
+func (s *Solr) Init() bool {
+ if s.URL == "" {
+ s.Error("URL not set")
+ return false
+ }
+
+ cli