@cryptotaxi247 / netdata-1 / commits / f2addf353

Port puppet collector from Python to Go (#18088)

* cmakelists remove python puppet * nuke puppet collector directory * readme addition * turn off puppet from python.d.conf * conf file addition, collector conf file, collector module dir * fix leftover comments * net_listeners.conf * format * simplify * check url query in test * update service discovery * new line * Update src/go/plugin/go.d/config/go.d/sd/docker.conf --------- Co-authored-by: ilyam8 <ilya@netdata.cloud>

Fotis Voutsas committed Jul 11, 2024 at 09:28 UTC f2addf3534e06b013b8973f4a118b5058dd455d8
23 files changed +1490 -653
CMakeLists.txt
-2
@@ -2863,7 +2863,6 @@ install(FILES
2863 src/collectors/python.d.plugin/openldap/openldap.conf
2864 src/collectors/python.d.plugin/oracledb/oracledb.conf
2865 src/collectors/python.d.plugin/pandas/pandas.conf
2866 - src/collectors/python.d.plugin/puppet/puppet.conf
2866 src/collectors/python.d.plugin/rethinkdbs/rethinkdbs.conf
2867 src/collectors/python.d.plugin/retroshare/retroshare.conf
2868 src/collectors/python.d.plugin/riakkv/riakkv.conf
@@ -2902,7 +2901,6 @@ install(FILES
2901 src/collectors/python.d.plugin/openldap/openldap.chart.py
2902 src/collectors/python.d.plugin/oracledb/oracledb.chart.py
2903 src/collectors/python.d.plugin/pandas/pandas.chart.py
2905 - src/collectors/python.d.plugin/puppet/puppet.chart.py
2904 src/collectors/python.d.plugin/rethinkdbs/rethinkdbs.chart.py
2905 src/collectors/python.d.plugin/retroshare/retroshare.chart.py
2906 src/collectors/python.d.plugin/riakkv/riakkv.chart.py
src/collectors/python.d.plugin/puppet/README.md deleted
-1
@@ -1 +0,0 @@
1 -integrations/puppet.md
\ No newline at end of file
src/collectors/python.d.plugin/puppet/integrations/puppet.md deleted
-248
@@ -1,248 +0,0 @@
1 -<!--startmeta
2 -custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/collectors/python.d.plugin/puppet/README.md"
3 -meta_yaml: "https://github.com/netdata/netdata/edit/master/src/collectors/python.d.plugin/puppet/metadata.yaml"
4 -sidebar_label: "Puppet"
5 -learn_status: "Published"
6 -learn_rel_path: "Collecting Metrics/CICD Platforms"
7 -most_popular: False
8 -message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE COLLECTOR'S metadata.yaml FILE"
9 -endmeta-->
10 -
11 -# Puppet
12 -
13 -
14 -<img src="https://netdata.cloud/img/puppet.svg" width="150"/>
15 -
16 -
17 -Plugin: python.d.plugin
18 -Module: puppet
19 -
20 -<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" />
21 -
22 -## Overview
23 -
24 -This collector monitors Puppet metrics about JVM Heap, Non-Heap, CPU usage and file descriptors.'
25 -
26 -
27 -It uses Puppet's metrics API endpoint to gather the metrics.
28 -
29 -
30 -This collector is supported on all platforms.
31 -
32 -This collector supports collecting metrics from multiple instances of this integration, including remote instances.
33 -
34 -
35 -### Default Behavior
36 -
37 -#### Auto-Detection
38 -
39 -By default, this collector will use `https://fqdn.example.com:8140` as the URL to look for metrics.
40 -
41 -#### Limits
42 -
43 -The default configuration for this integration does not impose any limits on data collection.
44 -
45 -#### Performance Impact
46 -
47 -The default configuration for this integration is not expected to impose a significant performance impact on the system.
48 -
49 -
50 -## Metrics
51 -
52 -Metrics grouped by *scope*.
53 -
54 -The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels.
55 -
56 -
57 -
58 -### Per Puppet instance
59 -
60 -These metrics refer to the entire monitored application.
61 -
62 -This scope has no labels.
63 -
64 -Metrics:
65 -
66 -| Metric | Dimensions | Unit |
67 -|:------|:----------|:----|
68 -| puppet.jvm_heap | committed, used | MiB |
69 -| puppet.jvm_nonheap | committed, used | MiB |
70 -| puppet.cpu | execution, GC | percentage |
71 -| puppet.fdopen | used | descriptors |
72 -
73 -
74 -
75 -## Alerts
76 -
77 -There are no alerts configured by default for this integration.
78 -
79 -
80 -## Setup
81 -
82 -### Prerequisites
83 -
84 -No action required.
85 -
86 -### Configuration
87 -
88 -#### File
89 -
90 -The configuration file name for this integration is `python.d/puppet.conf`.
91 -
92 -
93 -You can edit the configuration file using the `edit-config` script from the
94 -Netdata [config directory](/docs/netdata-agent/configuration/README.md#the-netdata-config-directory).
95 -
96 -```bash
97 -cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata
98 -sudo ./edit-config python.d/puppet.conf
99 -```
100 -#### Options
101 -
102 -This particular collector does not need further configuration to work if permissions are satisfied, but you can always customize it's data collection behavior.
103 -
104 -There are 2 sections:
105 -
106 -* Global variables
107 -* One or more JOBS that can define multiple different instances to monitor.
108 -
109 -The following options can be defined globally: priority, penalty, autodetection_retry, update_every, but can also be defined per JOB to override the global values.
110 -
111 -Additionally, the following collapsed table contains all the options that can be configured inside a JOB definition.
112 -
113 -Every configuration JOB starts with a `job_name` value which will appear in the dashboard, unless a `name` parameter is specified.
114 -
115 -> Notes:
116 -> - Exact Fully Qualified Domain Name of the node should be used.
117 -> - Usually Puppet Server/DB startup time is VERY long. So, there should be quite reasonable retry count.
118 -> - A secured PuppetDB config may require a client certificate. This does not apply to the default PuppetDB configuration though.
119 -
120 -
121 -<details open><summary>Config options</summary>
122 -
123 -| Name | Description | Default | Required |
124 -|:----|:-----------|:-------|:--------:|
125 -| url | HTTP or HTTPS URL, exact Fully Qualified Domain Name of the node should be used. | https://fqdn.example.com:8081 | yes |
126 -| tls_verify | Control HTTPS server certificate verification. | False | no |
127 -| tls_ca_file | Optional CA (bundle) file to use | | no |
128 -| tls_cert_file | Optional client certificate file | | no |
129 -| tls_key_file | Optional client key file | | no |
130 -| update_every | Sets the default data collection frequency. | 30 | no |
131 -| priority | Controls the order of charts at the netdata dashboard. | 60000 | no |
132 -| autodetection_retry | Sets the job re-check interval in seconds. | 0 | no |
133 -| penalty | Indicates whether to apply penalty to update_every in case of failures. | yes | no |
134 -| name | Job name. This value will overwrite the `job_name` value. JOBS with the same name are mutually exclusive. Only one of them will be allowed running at any time. This allows autodetection to try several alternatives and pick the one that works. | | no |
135 -
136 -</details>
137 -
138 -#### Examples
139 -
140 -##### Basic
141 -
142 -A basic example configuration
143 -
144 -```yaml
145 -puppetserver:
146 - url: 'https://fqdn.example.com:8140'
147 - autodetection_retry: 1
148 -
149 -```
150 -##### TLS Certificate
151 -
152 -An example using a TLS certificate
153 -
154 -<details open><summary>Config</summary>
155 -
156 -```yaml
157 -puppetdb:
158 - url: 'https://fqdn.example.com:8081'
159 - tls_cert_file: /path/to/client.crt
160 - tls_key_file: /path/to/client.key
161 - autodetection_retry: 1
162 -
163 -```
164 -</details>
165 -
166 -##### Multi-instance
167 -
168 -> **Note**: When you define multiple jobs, their names must be unique.
169 -
170 -Collecting metrics from local and remote instances.
171 -
172 -
173 -<details open><summary>Config</summary>
174 -
175 -```yaml
176 -puppetserver1:
177 - url: 'https://fqdn.example.com:8140'
178 - autodetection_retry: 1
179 -
180 -puppetserver2:
181 - url: 'https://fqdn.example2.com:8140'
182 - autodetection_retry: 1
183 -
184 -```
185 -</details>
186 -
187 -
188 -
189 -## Troubleshooting
190 -
191 -### Debug Mode
192 -
193 -To troubleshoot issues with the `puppet` collector, run the `python.d.plugin` with the debug option enabled. The output
194 -should give you clues as to why the collector isn't working.
195 -
196 -- Navigate to the `plugins.d` directory, usually at `/usr/libexec/netdata/plugins.d/`. If that's not the case on
197 - your system, open `netdata.conf` and look for the `plugins` setting under `[directories]`.
198 -
199 - ```bash
200 - cd /usr/libexec/netdata/plugins.d/
201 - ```
202 -
203 -- Switch to the `netdata` user.
204 -
205 - ```bash
206 - sudo -u netdata -s
207 - ```
208 -
209 -- Run the `python.d.plugin` to debug the collector:
210 -
211 - ```bash
212 - ./python.d.plugin puppet debug trace
213 - ```
214 -
215 -### Getting Logs
216 -
217 -If you're encountering problems with the `puppet` collector, follow these steps to retrieve logs and identify potential issues:
218 -
219 -- **Run the command** specific to your system (systemd, non-systemd, or Docker container).
220 -- **Examine the output** for any warnings or error messages that might indicate issues. These messages should provide clues about the root cause of the problem.
221 -
222 -#### System with systemd
223 -
224 -Use the following command to view logs generated since the last Netdata service restart:
225 -
226 -```bash
227 -journalctl _SYSTEMD_INVOCATION_ID="$(systemctl show --value --property=InvocationID netdata)" --namespace=netdata --grep puppet
228 -```
229 -
230 -#### System without systemd
231 -
232 -Locate the collector log file, typically at `/var/log/netdata/collector.log`, and use `grep` to filter for collector's name:
233 -
234 -```bash
235 -grep puppet /var/log/netdata/collector.log
236 -```
237 -
238 -**Note**: This method shows logs from all restarts. Focus on the **latest entries** for troubleshooting current issues.
239 -
240 -#### Docker Container
241 -
242 -If your Netdata runs in a Docker container named "netdata" (replace if different), use this command:
243 -
244 -```bash
245 -docker logs netdata 2>&1 | grep puppet
246 -```
247 -
248 -
src/collectors/python.d.plugin/puppet/metadata.yaml deleted
-185
@@ -1,185 +0,0 @@
1 -plugin_name: python.d.plugin
2 -modules:
3 - - meta:
4 - plugin_name: python.d.plugin
5 - module_name: puppet
6 - monitored_instance:
7 - name: Puppet
8 - link: "https://www.puppet.com/"
9 - categories:
10 - - data-collection.ci-cd-systems
11 - icon_filename: "puppet.svg"
12 - related_resources:
13 - integrations:
14 - list: []
15 - info_provided_to_referring_integrations:
16 - description: ""
17 - keywords:
18 - - puppet
19 - - jvm heap
20 - most_popular: false
21 - overview:
22 - data_collection:
23 - metrics_description: |
24 - This collector monitors Puppet metrics about JVM Heap, Non-Heap, CPU usage and file descriptors.'
25 - method_description: |
26 - It uses Puppet's metrics API endpoint to gather the metrics.
27 - supported_platforms:
28 - include: []
29 - exclude: []
30 - multi_instance: true
31 - additional_permissions:
32 - description: ""
33 - default_behavior:
34 - auto_detection:
35 - description: By default, this collector will use `https://fqdn.example.com:8140` as the URL to look for metrics.
36 - limits:
37 - description: ""
38 - performance_impact:
39 - description: ""
40 - setup:
41 - prerequisites:
42 - list: []
43 - configuration:
44 - file:
45 - name: "python.d/puppet.conf"
46 - options:
47 - description: |
48 - This particular collector does not need further configuration to work if permissions are satisfied, but you can always customize it's data collection behavior.
49 -
50 - There are 2 sections:
51 -
52 - * Global variables
53 - * One or more JOBS that can define multiple different instances to monitor.
54 -
55 - The following options can be defined globally: priority, penalty, autodetection_retry, update_every, but can also be defined per JOB to override the global values.
56 -
57 - Additionally, the following collapsed table contains all the options that can be configured inside a JOB definition.
58 -
59 - Every configuration JOB starts with a `job_name` value which will appear in the dashboard, unless a `name` parameter is specified.
60 -
61 - > Notes:
62 - > - Exact Fully Qualified Domain Name of the node should be used.
63 - > - Usually Puppet Server/DB startup time is VERY long. So, there should be quite reasonable retry count.
64 - > - A secured PuppetDB config may require a client certificate. This does not apply to the default PuppetDB configuration though.
65 - folding:
66 - title: "Config options"
67 - enabled: true
68 - list:
69 - - name: url
70 - description: HTTP or HTTPS URL, exact Fully Qualified Domain Name of the node should be used.
71 - default_value: https://fqdn.example.com:8081
72 - required: true
73 - - name: tls_verify
74 - description: Control HTTPS server certificate verification.
75 - default_value: "False"
76 - required: false
77 - - name: tls_ca_file
78 - description: Optional CA (bundle) file to use
79 - default_value: ""
80 - required: false
81 - - name: tls_cert_file
82 - description: Optional client certificate file
83 - default_value: ""
84 - required: false
85 - - name: tls_key_file
86 - description: Optional client key file
87 - default_value: ""
88 - required: false
89 - - name: update_every
90 - description: Sets the default data collection frequency.
91 - default_value: 30
92 - required: false
93 - - name: priority
94 - description: Controls the order of charts at the netdata dashboard.
95 - default_value: 60000
96 - required: false
97 - - name: autodetection_retry
98 - description: Sets the job re-check interval in seconds.
99 - default_value: 0
100 - required: false
101 - - name: penalty
102 - description: Indicates whether to apply penalty to update_every in case of failures.
103 - default_value: yes
104 - required: false
105 - - name: name
106 - description: >
107 - Job name. This value will overwrite the `job_name` value. JOBS with the same name are mutually exclusive. Only one of them will be allowed running at any time. This allows autodetection to try several alternatives and pick the one that works.
108 - default_value: ""
109 - required: false
110 - examples:
111 - folding:
112 - enabled: true
113 - title: "Config"
114 - list:
115 - - name: Basic
116 - description: A basic example configuration
117 - folding:
118 - enabled: false
119 - config: |
120 - puppetserver:
121 - url: 'https://fqdn.example.com:8140'
122 - autodetection_retry: 1
123 - - name: TLS Certificate
124 - description: An example using a TLS certificate
125 - config: |
126 - puppetdb:
127 - url: 'https://fqdn.example.com:8081'
128 - tls_cert_file: /path/to/client.crt
129 - tls_key_file: /path/to/client.key
130 - autodetection_retry: 1
131 - - name: Multi-instance
132 - description: |
133 - > **Note**: When you define multiple jobs, their names must be unique.
134 -
135 - Collecting metrics from local and remote instances.
136 - config: |
137 - puppetserver1:
138 - url: 'https://fqdn.example.com:8140'
139 - autodetection_retry: 1
140 -
141 - puppetserver2:
142 - url: 'https://fqdn.example2.com:8140'
143 - autodetection_retry: 1
144 - troubleshooting:
145 - problems:
146 - list: []
147 - alerts: []
148 - metrics:
149 - folding:
150 - title: Metrics
151 - enabled: false
152 - description: ""
153 - availability: []
154 - scopes:
155 - - name: global
156 - description: "These metrics refer to the entire monitored application."
157 - labels: []
158 - metrics:
159 - - name: puppet.jvm_heap
160 - description: JVM Heap
161 - unit: "MiB"
162 - chart_type: area
163 - dimensions:
164 - - name: committed
165 - - name: used
166 - - name: puppet.jvm_nonheap
167 - description: JVM Non-Heap
168 - unit: "MiB"
169 - chart_type: area
170 - dimensions:
171 - - name: committed
172 - - name: used
173 - - name: puppet.cpu
174 - description: CPU usage
175 - unit: "percentage"
176 - chart_type: stacked
177 - dimensions:
178 - - name: execution
179 - - name: GC
180 - - name: puppet.fdopen
181 - description: File Descriptors
182 - unit: "descriptors"
183 - chart_type: line
184 - dimensions:
185 - - name: used
src/collectors/python.d.plugin/puppet/puppet.chart.py deleted
-121
@@ -1,121 +0,0 @@
1 -# -*- coding: utf-8 -*-
2 -# Description: puppet netdata python.d module
3 -# Author: Andrey Galkin <andrey@futoin.org> (andvgal)
4 -# SPDX-License-Identifier: GPL-3.0-or-later
5 -#
6 -# This module should work both with OpenSource and PE versions
7 -# of PuppetServer and PuppetDB.
8 -#
9 -# NOTE: PuppetDB may be configured to require proper TLS
10 -# client certificate for security reasons. Use tls_key_file
11 -# and tls_cert_file options then.
12 -#
13 -
14 -import socket
15 -from json import loads
16 -
17 -from bases.FrameworkServices.UrlService import UrlService
18 -
19 -update_every = 5
20 -
21 -MiB = 1 << 20
22 -CPU_SCALE = 1000
23 -
24 -ORDER = [
25 - 'jvm_heap',
26 - 'jvm_nonheap',
27 - 'cpu',
28 - 'fd_open',
29 -]
30 -
31 -CHARTS = {
32 - 'jvm_heap': {
33 - 'options': [None, 'JVM Heap', 'MiB', 'resources', 'puppet.jvm_heap', 'area'],
34 - 'lines': [
35 - ['jvm_heap_committed', 'committed', 'absolute', 1, MiB],
36 - ['jvm_heap_used', 'used', 'absolute', 1, MiB],
37 - ],
38 - 'variables': [
39 - ['jvm_heap_max'],
40 - ['jvm_heap_init'],
41 - ],
42 - },
43 - 'jvm_nonheap': {
44 - 'options': [None, 'JVM Non-Heap', 'MiB', 'resources', 'puppet.jvm_nonheap', 'area'],
45 - 'lines': [
46 - ['jvm_nonheap_committed', 'committed', 'absolute', 1, MiB],
47 - ['jvm_nonheap_used', 'used', 'absolute', 1, MiB],
48 - ],
49 - 'variables': [
50 - ['jvm_nonheap_max'],
51 - ['jvm_nonheap_init'],
52 - ],
53 - },
54 - 'cpu': {
55 - 'options': [None, 'CPU usage', 'percentage', 'resources', 'puppet.cpu', 'stacked'],
56 - 'lines': [
57 - ['cpu_time', 'execution', 'absolute', 1, CPU_SCALE],
58 - ['gc_time', 'GC', 'absolute', 1, CPU_SCALE],
59 - ]
60 - },
61 - 'fd_open': {
62 - 'options': [None, 'File Descriptors', 'descriptors', 'resources', 'puppet.fdopen', 'line'],
63 - 'lines': [
64 - ['fd_used', 'used', 'absolute'],
65 - ],
66 - 'variables': [
67 - ['fd_max'],
68 - ],
69 - },
70 -}
71 -
72 -
73 -class Service(UrlService):
74 - def __init__(self, configuration=None, name=None):
75 - UrlService.__init__(self, configuration=configuration, name=name)
76 - self.order = ORDER
77 - self.definitions = CHARTS
78 - self.url = self.configuration.get('url', 'https://{0}:8140'.format(socket.getfqdn()))
79 -
80 - def _get_data(self):
81 - # NOTE: there are several ways to retrieve data
82 - # 1. Only PE versions:
83 - # https://puppet.com/docs/pe/2018.1/api_status/status_api_metrics_endpoints.html
84 - # 2. Individual Metrics API (JMX):
85 - # https://puppet.com/docs/pe/2018.1/api_status/metrics_api.html
86 - # 3. Extended status at debug level:
87 - # https://puppet.com/docs/pe/2018.1/api_status/status_api_json_endpoints.html
88 - #
89 - # For sake of simplicity and efficiency the status one is used..
90 -
91 - raw_data = self._get_raw_data(self.url + '/status/v1/services?level=debug')
92 -
93 - if raw_data is None:
94 - return None
95 -
96 - raw_data = loads(raw_data)
97 - data = {}
98 -
99 - try:
100 - try:
101 - jvm_metrics = raw_data['status-service']['status']['experimental']['jvm-metrics']
102 - except KeyError:
103 - jvm_metrics = raw_data['status-service']['status']['jvm-metrics']
104 -
105 - heap_mem = jvm_metrics['heap-memory']
106 - non_heap_mem = jvm_metrics['non-heap-memory']
107 -
108 - for k in ['max', 'committed', 'used', 'init']:
109 - data['jvm_heap_' + k] = heap_mem[k]
110 - data['jvm_nonheap_' + k] = non_heap_mem[k]
111 -
112 - fd_open = jvm_metrics['file-descriptors']
113 - data['fd_max'] = fd_open['max']
114 - data['fd_used'] = fd_open['used']
115 -
116 - data['cpu_time'] = int(jvm_metrics['cpu-usage'] * CPU_SCALE)
117 - data['gc_time'] = int(jvm_metrics['gc-cpu-usage'] * CPU_SCALE)
118 - except KeyError:
119 - pass
120 -
121 - return data or None
src/collectors/python.d.plugin/puppet/puppet.conf deleted
-94
@@ -1,94 +0,0 @@
1 -# netdata python.d.plugin configuration for Puppet Server and Puppet DB
2 -#
3 -# This file is in YaML format. Generally the format is:
4 -#
5 -# name: value
6 -#
7 -# There are 2 sections:
8 -# - global variables
9 -# - one or more JOBS
10 -#
11 -# JOBS allow you to collect values from multiple sources.
12 -# Each source will have its own set of charts.
13 -#
14 -# JOB parameters have to be indented (using spaces only, example below).
15 -
16 -# ----------------------------------------------------------------------
17 -# Global Variables
18 -# These variables set the defaults for all JOBs, however each JOB
19 -# may define its own, overriding the defaults.
20 -
21 -# update_every sets the default data collection frequency.
22 -# If unset, the python.d.plugin default is used.
23 -# update_every: 1
24 -
25 -# priority controls the order of charts at the netdata dashboard.
26 -# Lower numbers move the charts towards the top of the page.
27 -# If unset, the default for python.d.plugin is used.
28 -# priority: 60000
29 -
30 -# penalty indicates whether to apply penalty to update_every in case of failures.
31 -# Penalty will increase every 5 failed updates in a row. Maximum penalty is 10 minutes.
32 -# penalty: yes
33 -
34 -# autodetection_retry sets the job re-check interval in seconds.
35 -# The job is not deleted if check fails.
36 -# Attempts to start the job are made once every autodetection_retry.
37 -# This feature is disabled by default.
38 -# autodetection_retry: 0
39 -
40 -# ----------------------------------------------------------------------
41 -# JOBS (data collection sources)
42 -#
43 -# The default JOBS share the same *name*. JOBS with the same name
44 -# are mutually exclusive. Only one of them will be allowed running at
45 -# any time. This allows autodetection to try several alternatives and
46 -# pick the one that works.
47 -#
48 -# Any number of jobs is supported.
49 -#
50 -# All python.d.plugin JOBS (for all its modules) support a set of
51 -# predefined parameters. These are:
52 -#
53 -# job_name:
54 -# name: myname # the JOB's name as it will appear at the
55 -# # dashboard (by default is the job_name)
56 -# # JOBs sharing a name are mutually exclusive
57 -# update_every: 1 # the JOB's data collection frequency
58 -# priority: 60000 # the JOB's order on the dashboard
59 -# penalty: yes # the JOB's penalty
60 -# autodetection_retry: 0 # the JOB's re-check interval in seconds
61 -#
62 -# These configuration comes from UrlService base:
63 -# url: # HTTP or HTTPS URL
64 -# tls_verify: False # Control HTTPS server certificate verification
65 -# tls_ca_file: # Optional CA (bundle) file to use
66 -# tls_cert_file: # Optional client certificate file
67 -# tls_key_file: # Optional client key file
68 -#
69 -# ----------------------------------------------------------------------
70 -# AUTO-DETECTION JOBS
71 -# only one of them will run (they have the same name)
72 -# puppet:
73 -# url: 'https://<FQDN>:8140'
74 -#
75 -
76 -#
77 -# Production configuration should look like below.
78 -#
79 -# NOTE: usually Puppet Server/DB startup time is VERY long. So, there should
80 -# be quite reasonable retry count.
81 -#
82 -# NOTE: secure PuppetDB config may require client certificate.
83 -# Not applies to default PuppetDB configuration though.
84 -#
85 -# puppetdb:
86 -# url: 'https://fqdn.example.com:8081'
87 -# tls_cert_file: /path/to/client.crt
88 -# tls_key_file: /path/to/client.key
89 -# autodetection_retry: 1
90 -#
91 -# puppetserver:
92 -# url: 'https://fqdn.example.com:8140'
93 -# autodetection_retry: 1
94 -#
src/collectors/python.d.plugin/python.d.conf
+1 -1
@@ -47,7 +47,6 @@ go_expvar: no
47 # openldap: yes
48 # oracledb: yes
49 # pandas: yes
50 -# puppet: yes
50 # rethinkdbs: yes
51 # retroshare: yes
52 # riakkv: yes
@@ -83,3 +82,4 @@ postgres: no # Removed (replaced with go.d/postgres).
82 proxysql: no # Removed (replaced with go.d/proxysql).
83 redis: no # Removed (replaced with go.d/redis).
84 sensors: no # Removed (replaced with go.d/sensors).
85 +puppet: no # Removed (replaced with go.d/puppet).
src/go/plugin/go.d/README.md
+2 -1
@@ -114,7 +114,8 @@ see the appropriate collector readme.
114 | [powerdns](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/powerdns) | PowerDNS Authoritative Server |
115 | [powerdns_recursor](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/powerdns_recursor) | PowerDNS Recursor |
116 | [proxysql](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/proxysql) | ProxySQL |
117 -| [pulsar](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/portcheck) | Apache Pulsar |
117 +| [pulsar](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/pulsar) | Apache Pulsar |
118 +| [puppet](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/puppet) | Puppet |
119 | [rabbitmq](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/rabbitmq) | RabbitMQ |
120 | [redis](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/redis) | Redis |
121 | [rspamd](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/rspamd) | Rspamd |
src/go/plugin/go.d/config/go.d.conf
+1
@@ -80,6 +80,7 @@ modules:
80 # powerdns_recursor: yes
81 # prometheus: yes
82 # pulsar: yes
83 +# puppet: yes
84 # rabbitmq: yes
85 # redis: yes
86 # rspamd: yes
src/go/plugin/go.d/config/go.d/puppet.conf new
+7
@@ -0,0 +1,7 @@
1 +## All available configuration options, their descriptions and default values:
2 +## https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/puppet#readme
3 +
4 +#jobs:
5 +# - name: local
6 +# url: https://127.0.0.1:8140
7 +# tls_skip_verify: yes
\ No newline at end of file
src/go/plugin/go.d/config/go.d/sd/docker.conf
+8
@@ -56,6 +56,8 @@ classify:
56 expr: '{{ or (eq .PrivatePort "5432") (match "sp" .Image "postgres postgres:* */postgres */postgres:* */postgresql */postgresql:*") }}'
57 - tags: "proxysql"
58 expr: '{{ or (eq .PrivatePort "6032") (match "sp" .Image "*/proxysql */proxysql:*") }}'
59 + - tags: "puppet"
60 + expr: '{{ or (eq .PrivatePort "8140") (match "sp" .Image "puppet/puppetserver puppet/puppetserver:*") }}'
61 - tags: "rabbitmq"
62 expr: '{{ or (eq .PrivatePort "15672") (match "sp" .Image "rabbitmq rabbitmq:* */rabbitmq */rabbitmq:*") }}'
63 - tags: "redis"
@@ -171,6 +173,12 @@ compose:
173 module: proxysql
174 name: docker_{{.Name}}
175 dsn: stats:stats@tcp({{.Address}})/
176 + - selector: "puppet"
177 + template: |
178 + module: puppet
179 + name: docker_{{.Name}}
180 + url: https://{{.Address}}
181 + tls_skip_verify: yes
182 - selector: "rabbitmq"
183 template: |
184 module: rabbitmq
src/go/plugin/go.d/config/go.d/sd/net_listeners.conf
+8
@@ -92,6 +92,8 @@ classify:
92 expr: '{{ and (eq .Port "8081") (eq .Comm "pdns_recursor") }}'
93 - tags: "proxysql"
94 expr: '{{ or (eq .Port "6032") (eq .Comm "proxysql") }}'
95 + - tags: "puppet"
96 + expr: '{{ or (eq .Port "8140") (glob .Cmdline "*puppet-server*") }}'
97 - tags: "rabbitmq"
98 expr: '{{ or (eq .Port "15672") (glob .Cmdline "*rabbitmq*") }}'
99 - tags: "redis"
@@ -372,6 +374,12 @@ compose:
374 module: proxysql
375 name: local
376 dsn: stats:stats@tcp({{.Address}})/
377 + - selector: "puppet"
378 + template: |
379 + module: puppet
380 + name: local
381 + url: https://{{.Address}}
382 + tls_skip_verify: yes
383 - selector: "rabbitmq"
384 template: |
385 module: rabbitmq
src/go/plugin/go.d/modules/init.go
+1
@@ -72,6 +72,7 @@ import (
72 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/prometheus"
73 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/proxysql"
74 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/pulsar"
75 + _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/puppet"
76 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/rabbitmq"
77 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/redis"
78 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/rspamd"
src/go/plugin/go.d/modules/puppet/charts.go new
+93
@@ -0,0 +1,93 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package puppet
4 +
5 +import (
6 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
7 +)
8 +
9 +const (
10 + prioJVMHeap = module.Priority + iota
11 + prioJVMNonHeap
12 + prioCPUUsage
13 + prioFileDescriptors
14 +)
15 +
16 +const (
17 + byteToMiB = 1 << 20
18 +)
19 +
20 +var charts = module.Charts{
21 + jvmHeapChart.Copy(),
22 + jvmNonHeapChart.Copy(),
23 + cpuUsageChart.Copy(),
24 + fileDescriptorsChart.Copy(),
25 +}
26 +
27 +var (
28 + jvmHeapChart = module.Chart{
29 + ID: "jvm_heap",
30 + Title: "JVM Heap",
31 + Units: "MiB",
32 + Fam: "resources",
33 + Ctx: "puppet.jvm_heap",
34 + Type: module.Area,
35 + Priority: prioJVMHeap,
36 + Dims: module.Dims{
37 + {ID: "jvm_heap_committed", Name: "committed", Div: byteToMiB},
38 + {ID: "jvm_heap_used", Name: "used", Div: byteToMiB},
39 + },
40 + Vars: module.Vars{
41 + {ID: "jvm_heap_max"},
42 + {ID: "jvm_heap_init"},
43 + },
44 + }
45 +
46 + jvmNonHeapChart = module.Chart{
47 + ID: "jvm_nonheap",
48 + Title: "JVM Non-Heap",
49 + Units: "MiB",
50 + Fam: "resources",
51 + Ctx: "puppet.jvm_nonheap",
52 + Type: module.Area,
53 + Priority: prioJVMNonHeap,
54 + Dims: module.Dims{
55 + {ID: "jvm_nonheap_committed", Name: "committed", Div: byteToMiB},
56 + {ID: "jvm_nonheap_used", Name: "used", Div: byteToMiB},
57 + },
58 + Vars: module.Vars{
59 + {ID: "jvm_nonheap_max"},
60 + {ID: "jvm_nonheap_init"},
61 + },
62 + }
63 +
64 + cpuUsageChart = module.Chart{
65 + ID: "cpu",
66 + Title: "CPU usage",
67 + Units: "percentage",
68 + Fam: "resources",
69 + Ctx: "puppet.cpu",
70 + Type: module.Stacked,
71 + Priority: prioCPUUsage,
72 + Dims: module.Dims{
73 + {ID: "cpu_usage", Name: "execution", Div: 1000},
74 + {ID: "gc_cpu_usage", Name: "GC", Div: 1000},
75 + },
76 + }
77 +
78 + fileDescriptorsChart = module.Chart{
79 + ID: "fd_open",
80 + Title: "File Descriptors",
81 + Units: "descriptors",
82 + Fam: "resources",
83 + Ctx: "puppet.fdopen",
84 + Type: module.Line,
85 + Priority: prioFileDescriptors,
86 + Dims: module.Dims{
87 + {ID: "fd_used", Name: "used"},
88 + },
89 + Vars: module.Vars{
90 + {ID: "fd_max"},
91 + },
92 + }
93 +)
src/go/plugin/go.d/modules/puppet/collect.go new
+76
@@ -0,0 +1,76 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package puppet
4 +
5 +import (
6 + "encoding/json"
7 + "fmt"
8 + "io"
9 + "net/http"
10 + "net/url"
11 +
12 + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/stm"
13 + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
14 +)
15 +
16 +var (
17 + //https://puppet.com/docs/puppet/8/server/status-api/v1/services
18 + urlPathStatusService = "/status/v1/services"
19 + urlQueryStatusService = url.Values{"level": {"debug"}}.Encode()
20 +)
21 +
22 +func (p *Puppet) collect() (map[string]int64, error) {
23 + stats, err := p.queryStatsService()
24 + if err != nil {
25 + return nil, err
26 + }
27 +
28 + mx := stm.ToMap(stats)
29 +
30 + return mx, nil
31 +}
32 +
33 +func (p *Puppet) queryStatsService() (*statusServiceResponse, error) {
34 + req, err := web.NewHTTPRequest(p.Request)
35 + if err != nil {
36 + return nil, err
37 + }
38 +
39 + req.URL.Path = urlPathStatusService
40 + req.URL.RawQuery = urlQueryStatusService
41 +
42 + var stats statusServiceResponse
43 + if err := p.doOKDecode(req, &stats); err != nil {
44 + return nil, err
45 + }
46 +
47 + if stats.StatusService == nil {
48 + return nil, fmt.Errorf("unexpected response: not puppet service status data")
49 + }
50 +
51 + return &stats, nil
52 +}
53 +
54 +func (p *Puppet) doOKDecode(req *http.Request, in interface{}) error {
55 + resp, err := p.httpClient.Do(req)
56 + if err != nil {
57 + return fmt.Errorf("error on HTTP request '%s': %v", req.URL, err)
58 + }
59 + defer closeBody(resp)
60 +
61 + if resp.StatusCode != http.StatusOK {
62 + return fmt.Errorf("'%s' returned HTTP status code: %d", req.URL, resp.StatusCode)
63 + }
64 +
65 + if err := json.NewDecoder(resp.Body).Decode(in); err != nil {
66 + return fmt.Errorf("error on decoding response from '%s': %v", req.URL, err)
67 + }
68 + return nil
69 +}
70 +
71 +func closeBody(resp *http.Response) {
72 + if resp != nil && resp.Body != nil {
73 + _, _ = io.Copy(io.Discard, resp.Body)
74 + _ = resp.Body.Close()
75 + }
76 +}
src/go/plugin/go.d/modules/puppet/config_schema.json new
+177
@@ -0,0 +1,177 @@
1 +{
2 + "jsonSchema": {
3 + "$schema": "http://json-schema.org/draft-07/schema#",
4 + "title": "Puppet collector configuration.",
5 + "type": "object",
6 + "properties": {
7 + "update_every": {
8 + "title": "Update every",
9 + "description": "Data collection interval, measured in seconds.",
10 + "type": "integer",
11 + "minimum": 1,
12 + "default": 1
13 + },
14 + "url": {
15 + "title": "URL",
16 + "description": "The base URL where the Puppet instance can be accessed.",
17 + "type": "string",
18 + "default": "https://127.0.0.1:8140",
19 + "format": "uri"
20 + },
21 + "timeout": {
22 + "title": "Timeout",
23 + "description": "The timeout in seconds for the HTTP request.",
24 + "type": "number",
25 + "minimum": 0.5,
26 + "default": 1
27 + },
28 + "not_follow_redirects": {
29 + "title": "Not follow redirects",
30 + "description": "If set, the client will not follow HTTP redirects automatically.",
31 + "type": "boolean"
32 + },
33 + "username": {
34 + "title": "Username",
35 + "description": "The username for basic authentication.",
36 + "type": "string",
37 + "sensitive": true
38 + },
39 + "password": {
40 + "title": "Password",
41 + "description": "The password for basic authentication.",
42 + "type": "string",
43 + "sensitive": true
44 + },
45 + "proxy_url": {
46 + "title": "Proxy URL",
47 + "description": "The URL of the proxy server.",
48 + "type": "string"
49 + },
50 + "proxy_username": {
51 + "title": "Proxy username",
52 + "description": "The username for proxy authentication.",
53 + "type": "string",
54 + "sensitive": true
55 + },
56 + "proxy_password": {
57 + "title": "Proxy password",
58 + "description": "The password for proxy authentication.",
59 + "type": "string",
60 + "sensitive": true
61 + },
62 + "headers": {
63 + "title": "Headers",
64 + "description": "Additional HTTP headers to include in the request.",
65 + "type": [
66 + "object",
67 + "null"
68 + ],
69 + "additionalProperties": {
70 + "type": "string"
71 + }
72 + },
73 + "tls_skip_verify": {
74 + "title": "Skip TLS verification",
75 + "description": "If set, TLS certificate verification will be skipped.",
76 + "type": "boolean"
77 + },
78 + "tls_ca": {
79 + "title": "TLS CA",
80 + "description": "The path to the CA certificate file for TLS verification.",
81 + "type": "string",
82 + "pattern": "^$|^/"
83 + },
84 + "tls_cert": {
85 + "title": "TLS certificate",
86 + "description": "The path to the client certificate file for TLS authentication.",
87 + "type": "string",
88 + "pattern": "^$|^/"
89 + },
90 + "tls_key": {
91 + "title": "TLS key",
92 + "description": "The path to the client key file for TLS authentication.",
93 + "type": "string",
94 + "pattern": "^$|^/"
95 + },
96 + "body": {
97 + "title": "Body",
98 + "type": "string"
99 + },
100 + "method": {
101 + "title": "Method",
102 + "type": "string"
103 + }
104 + },
105 + "required": [
106 + "url"
107 + ],
108 + "additionalProperties": false,
109 + "patternProperties": {
110 + "^name$": {}
111 + }
112 + },
113 + "uiSchema": {
114 + "uiOptions": {
115 + "fullPage": true
116 + },
117 + "body": {
118 + "ui:widget": "hidden"
119 + },
120 + "method": {
121 + "ui:widget": "hidden"
122 + },
123 + "timeout": {
124 + "ui:help": "Accepts decimals for precise control (e.g., type 1.5 for 1.5 seconds)."
125 + },
126 + "password": {
127 + "ui:widget": "password"
128 + },
129 + "proxy_password": {
130 + "ui:widget": "password"
131 + },
132 + "ui:flavour": "tabs",
133 + "ui:options": {
134 + "tabs": [
135 + {
136 + "title": "Base",
137 + "fields": [
138 + "update_every",
139 + "url",
140 + "timeout",
141 + "not_follow_redirects"
142 + ]
143 + },
144 + {
145 + "title": "Auth",
146 + "fields": [
147 + "username",
148 + "password"
149 + ]
150 + },
151 + {
152 + "title": "TLS",
153 + "fields": [
154 + "tls_skip_verify",
155 + "tls_ca",
156 + "tls_cert",
157 + "tls_key"
158 + ]
159 + },
160 + {
161 + "title": "Proxy",
162 + "fields": [
163 + "proxy_url",
164 + "proxy_username",
165 + "proxy_password"
166 + ]
167 + },
168 + {
169 + "title": "Headers",
170 + "fields": [
171 + "headers"
172 + ]
173 + }
174 + ]
175 + }
176 + }
177 +}
src/go/plugin/go.d/modules/puppet/metadata.yaml new
+184
@@ -0,0 +1,184 @@
1 +plugin_name: go.d.plugin
2 +modules:
3 + - meta:
4 + id: collector-go.d.plugin-puppet
5 + plugin_name: go.d.plugin
6 + module_name: puppet
7 + monitored_instance:
8 + name: Puppet
9 + link: "https://www.puppet.com/"
10 + categories:
11 + - data-collection.ci-cd-systems
12 + icon_filename: "puppet.svg"
13 + related_resources:
14 + integrations:
15 + list: []
16 + info_provided_to_referring_integrations:
17 + description: ""
18 + keywords:
19 + - puppet
20 + most_popular: false
21 + overview:
22 + data_collection:
23 + metrics_description: |
24 + This collector monitors Puppet metrics, including JVM heap and non-heap memory, CPU usage, and file descriptors.
25 + method_description: |
26 + It uses Puppet's metrics API endpoint [/status/v1/services](https://www.puppet.com/docs/puppetserver/5.3/status-api/v1/services.html) to gather the metrics.
27 + supported_platforms:
28 + include: []
29 + exclude: []
30 + multi_instance: true
31 + additional_permissions:
32 + description: ""
33 + default_behavior:
34 + auto_detection:
35 + description: |
36 + By default, it detects Puppet instances running on localhost that are listening on port 8140.
37 + On startup, it tries to collect metrics from:
38 +
39 + - https://127.0.0.1:8140
40 + limits:
41 + description: ""
42 + performance_impact:
43 + description: ""
44 + setup:
45 + prerequisites:
46 + list: []
47 + configuration:
48 + file:
49 + name: "go.d/puppet.conf"
50 + options:
51 + description: |
52 + The following options can be defined globally: update_every, autodetection_retry.
53 + folding:
54 + title: ""
55 + enabled: true
56 + list:
57 + - name: url
58 + description: The base URL where the Puppet instance can be accessed.
59 + default_value: https://127.0.0.1:8140
60 + required: true
61 + - name: timeout
62 + description: HTTPS request timeout.
63 + default_value: 1
64 + required: false
65 + - name: username
66 + description: Username for basic HTTPS authentication.
67 + default_value: ""
68 + required: false
69 + - name: password
70 + description: Password for basic HTTPS authentication.
71 + default_value: ""
72 + required: false
73 + - name: proxy_url
74 + description: Proxy URL.
75 + default_value: ""
76 + required: false
77 + - name: proxy_username
78 + description: Username for proxy basic HTTPS authentication.
79 + default_value: ""
80 + required: false
81 + - name: proxy_password
82 + description: Password for proxy basic HTTPS authentication.
83 + default_value: ""
84 + required: false
85 + - name: method
86 + description: HTTPS request method.
87 + default_value: POST
88 + required: false
89 + - name: body
90 + description: HTTPS request body.
91 + default_value: ""
92 + required: false
93 + - name: headers
94 + description: HTTPS request headers.
95 + default_value: ""
96 + required: false
97 + - name: not_follow_redirects
98 + description: Redirect handling policy. Controls whether the client follows redirects.
99 + default_value: false
100 + required: false
101 + - name: tls_skip_verify
102 + description: Server certificate chain and hostname validation policy. Controls whether the client performs this check.
103 + default_value: false
104 + required: false
105 + - name: tls_ca
106 + description: Certification authority that the client uses when verifying the server's certificates.
107 + default_value: ""
108 + required: false
109 + - name: tls_cert
110 + description: Client TLS certificate.
111 + default_value: ""
112 + required: false
113 + - name: tls_key
114 + description: Client TLS key.
115 + default_value: ""
116 + required: false
117 + examples:
118 + folding:
119 + enabled: true
120 + title: "Config"
121 + list:
122 + - name: Basic with self-signed certificate
123 + description: Puppet with self-signed TLS certificate.
124 + config: |
125 + jobs:
126 + - name: local
127 + url: https://127.0.0.1:8140
128 + tls_skip_verify: yes
129 + - name: Multi-instance
130 + description: |
131 + > **Note**: When you define multiple jobs, their names must be unique.
132 +
133 + Collecting metrics from local and remote instances.
134 + config: |
135 + jobs:
136 + - name: local
137 + url: https://127.0.0.1:8140
138 + tls_skip_verify: yes
139 +
140 + - name: remote
141 + url: https://192.0.2.1:8140
142 + tls_skip_verify: yes
143 + troubleshooting:
144 + problems:
145 + list: []
146 + alerts: []
147 + metrics:
148 + folding:
149 + title: Metrics
150 + enabled: false
151 + description: ""
152 + availability: []
153 + scopes:
154 + - name: global
155 + description: "These metrics refer to the entire monitored application."
156 + labels: []
157 + metrics:
158 + - name: puppet.jvm_heap
159 + description: JVM Heap
160 + unit: "MiB"
161 + chart_type: area
162 + dimensions:
163 + - name: committed
164 + - name: used
165 + - name: puppet.jvm_nonheap
166 + description: JVM Non-Heap
167 + unit: "MiB"
168 + chart_type: area
169 + dimensions:
170 + - name: committed
171 + - name: used
172 + - name: puppet.cpu
173 + description: CPU usage
174 + unit: "percentage"
175 + chart_type: stacked
176 + dimensions:
177 + - name: execution
178 + - name: GC
179 + - name: puppet.fdopen
180 + description: File Descriptors
181 + unit: "descriptors"
182 + chart_type: line
183 + dimensions:
184 + - name: used
src/go/plugin/go.d/modules/puppet/puppet.go new
+114
@@ -0,0 +1,114 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package puppet
4 +
5 +import (
6 + _ "embed"
7 + "errors"
8 + "net/http"
9 + "time"
10 +
11 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
12 + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
13 +)
14 +
15 +//go:embed "config_schema.json"
16 +var configSchema string
17 +
18 +func init() {
19 + module.Register("puppet", module.Creator{
20 + JobConfigSchema: configSchema,
21 + Create: func() module.Module { return New() },
22 + Config: func() any { return &Config{} },
23 + })
24 +}
25 +
26 +func New() *Puppet {
27 + return &Puppet{
28 + Config: Config{
29 + HTTP: web.HTTP{
30 + Request: web.Request{
31 + URL: "https://127.0.0.1:8140",
32 + },
33 + Client: web.Client{
34 + Timeout: web.Duration(time.Second * 1),
35 + },
36 + },
37 + },
38 + charts: charts.Copy(),
39 + }
40 +}
41 +
42 +type Config struct {
43 + UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
44 + web.HTTP `yaml:",inline" json:""`
45 +}
46 +
47 +type Puppet struct {
48 + module.Base
49 + Config `yaml:",inline" json:""`
50 +
51 + charts *module.Charts
52 +
53 + httpClient *http.Client
54 +}
55 +
56 +func (p *Puppet) Configuration() any {
57 + return p.Config
58 +}
59 +
60 +func (p *Puppet) Init() error {
61 + if p.URL == "" {
62 + p.Error("URL not set")
63 + return errors.New("url not set")
64 + }
65 +
66 + client, err := web.NewHTTPClient(p.Client)
67 + if err != nil {
68 + p.Error(err)
69 + return err
70 + }
71 + p.httpClient = client
72 +
73 + p.Debugf("using URL %s", p.URL)
74 + p.Debugf("using timeout: %s", p.Timeout)
75 +
76 + return nil
77 +}
78 +
79 +func (p *Puppet) Check() error {
80 + mx, err := p.collect()
81 + if err != nil {
82 + p.Error(err)
83 + return err
84 + }
85 +
86 + if len(mx) == 0 {
87 + return errors.New("no metrics collected")
88 + }
89 +
90 + return nil
91 +}
92 +
93 +func (p *Puppet) Charts() *module.Charts {
94 + return p.charts
95 +}
96 +
97 +func (p *Puppet) Collect() map[string]int64 {
98 + mx, err := p.collect()
99 + if err != nil {
100 + p.Error(err)
101 + }
102 +
103 + if len(mx) == 0 {
104 + return nil
105 + }
106 +
107 + return mx
108 +}
109 +
110 +func (p *Puppet) Cleanup() {
111 + if p.httpClient != nil {
112 + p.httpClient.CloseIdleConnections()
113 + }
114 +}
src/go/plugin/go.d/modules/puppet/puppet_test.go new
+252
@@ -0,0 +1,252 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package puppet
4 +
5 +import (
6 + "net/http"
7 + "net/http/httptest"
8 + "os"
9 + "testing"
10 +
11 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
12 + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
13 +
14 + "github.com/stretchr/testify/assert"
15 + "github.com/stretchr/testify/require"
16 +)
17 +
18 +var (
19 + dataConfigJSON, _ = os.ReadFile("testdata/config.json")
20 + dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
21 +
22 + serviceStatusResponse, _ = os.ReadFile("testdata/serviceStatusResponse.json")
23 +)
24 +
25 +func Test_testDataIsValid(t *testing.T) {
26 + for name, data := range map[string][]byte{
27 + "dataConfigJSON": dataConfigJSON,
28 + "dataConfigYAML": dataConfigYAML,
29 + "serviceStatusResponse": serviceStatusResponse,
30 + } {
31 + require.NotNil(t, data, name)
32 + }
33 +}
34 +
35 +func TestPuppet_ConfigurationSerialize(t *testing.T) {
36 + module.TestConfigurationSerialize(t, &Puppet{}, dataConfigJSON, dataConfigYAML)
37 +}
38 +
39 +func TestPuppet_Init(t *testing.T) {
40 + tests := map[string]struct {
41 + wantFail bool
42 + config Config
43 + }{
44 + "success with default": {
45 + wantFail: false,
46 + config: New().Config,
47 + },
48 + "fail when URL not set": {
49 + wantFail: true,
50 + config: Config{
51 + HTTP: web.HTTP{
52 + Request: web.Request{URL: ""},
53 + },
54 + },
55 + },
56 + }
57 +
58 + for name, test := range tests {
59 + t.Run(name, func(t *testing.T) {
60 + puppet := New()
61 + puppet.Config = test.config
62 +
63 + if test.wantFail {
64 + assert.Error(t, puppet.Init())
65 + } else {
66 + assert.NoError(t, puppet.Init())
67 + }
68 + })
69 + }
70 +}
71 +
72 +func TestPuppet_Charts(t *testing.T) {
73 + assert.NotNil(t, New().Charts())
74 +}
75 +
76 +func TestPuppet_Check(t *testing.T) {
77 + tests := map[string]struct {
78 + wantFail bool
79 + prepare func(t *testing.T) (*Puppet, func())
80 + }{
81 + "success default config": {
82 + wantFail: false,
83 + prepare: prepareCaseOkDefault,
84 + },
85 + "fails on unexpected json response": {
86 + wantFail: true,
87 + prepare: prepareCaseUnexpectedJsonResponse,
88 + },
89 + "fails on invalid format response": {
90 + wantFail: true,
91 + prepare: prepareCaseInvalidFormatResponse,
92 + },
93 + "fails on connection refused": {
94 + wantFail: true,
95 + prepare: prepareCaseConnectionRefused,
96 + },
97 + }
98 +
99 + for name, test := range tests {
100 + t.Run(name, func(t *testing.T) {
101 + puppet, cleanup := test.prepare(t)
102 + defer cleanup()
103 +
104 + if test.wantFail {
105 + assert.Error(t, puppet.Check())
106 + } else {
107 + assert.NoError(t, puppet.Check())
108 + }
109 + })
110 + }
111 +}
112 +
113 +func TestPuppet_Collect(t *testing.T) {
114 + tests := map[string]struct {
115 + prepare func(t *testing.T) (*Puppet, func())
116 + wantMetrics map[string]int64
117 + }{
118 + "success default config": {
119 + prepare: prepareCaseOkDefault,
120 + wantMetrics: map[string]int64{
121 + "cpu_usage": 49,
122 + "fd_max": 524288,
123 + "fd_used": 234,
124 + "gc_cpu_usage": 0,
125 + "jvm_heap_committed": 1073741824,
126 + "jvm_heap_init": 1073741824,
127 + "jvm_heap_max": 1073741824,
128 + "jvm_heap_used": 550502400,
129 + "jvm_nonheap_committed": 334102528,
130 + "jvm_nonheap_init": 7667712,
131 + "jvm_nonheap_max": -1,
132 + "jvm_nonheap_used": 291591160,
133 + },
134 + },
135 + "fails on unexpected json response": {
136 + prepare: prepareCaseUnexpectedJsonResponse,
137 + },
138 + "fails on invalid format response": {
139 + prepare: prepareCaseInvalidFormatResponse,
140 + },
141 + "fails on connection refused": {
142 + prepare: prepareCaseConnectionRefused,
143 + },
144 + }
145 +
146 + for name, test := range tests {
147 + t.Run(name, func(t *testing.T) {
148 + puppet, cleanup := test.prepare(t)
149 + defer cleanup()
150 +
151 + mx := puppet.Collect()
152 +
153 + require.Equal(t, test.wantMetrics, mx)
154 + if len(test.wantMetrics) > 0 {
155 + testMetricsHasAllChartsDims(t, puppet, mx)
156 + }
157 + })
158 + }
159 +}
160 +
161 +func testMetricsHasAllChartsDims(t *testing.T, puppet *Puppet, mx map[string]int64) {
162 + for _, chart := range *puppet.Charts() {
163 + if chart.Obsolete {
164 + continue
165 + }
166 + for _, dim := range chart.Dims {
167 + _, ok := mx[dim.ID]
168 + assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID)
169 + }
170 + for _, v := range chart.Vars {
171 + _, ok := mx[v.ID]
172 + assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID)
173 + }
174 + }
175 +}
176 +
177 +func prepareCaseOkDefault(t *testing.T) (*Puppet, func()) {
178 + t.Helper()
179 + srv := httptest.NewServer(http.HandlerFunc(
180 + func(w http.ResponseWriter, r *http.Request) {
181 + switch r.URL.Path {
182 + case "/status/v1/services":
183 + if r.URL.RawQuery != urlQueryStatusService {
184 + w.WriteHeader(http.StatusNotFound)
185 + } else {
186 + _, _ = w.Write(serviceStatusResponse)
187 + }
188 + default:
189 + w.WriteHeader(http.StatusNotFound)
190 + }
191 + }))
192 +
193 + puppet := New()
194 + puppet.URL = srv.URL
195 + require.NoError(t, puppet.Init())
196 +
197 + return puppet, srv.Close
198 +}
199 +
200 +func prepareCaseUnexpectedJsonResponse(t *testing.T) (*Puppet, func()) {
201 + t.Helper()
202 + resp := `
203 +{
204 + "elephant": {
205 + "burn": false,
206 + "mountain": true,
207 + "fog": false,
208 + "skin": -1561907625,
209 + "burst": "anyway",
210 + "shadow": 1558616893
211 + },
212 + "start": "ever",
213 + "base": 2093056027,
214 + "mission": -2007590351,
215 + "victory": 999053756,
216 + "die": false
217 +}
218 +`
219 + srv := httptest.NewServer(http.HandlerFunc(
220 + func(w http.ResponseWriter, r *http.Request) {
221 + _, _ = w.Write([]byte(resp))
222 + }))
223 +
224 + puppet := New()
225 + puppet.URL = srv.URL
226 + require.NoError(t, puppet.Init())
227 +
228 + return puppet, srv.Close
229 +}
230 +
231 +func prepareCaseInvalidFormatResponse(t *testing.T) (*Puppet, func()) {
232 + t.Helper()
233 + srv := httptest.NewServer(http.HandlerFunc(
234 + func(w http.ResponseWriter, r *http.Request) {
235 + _, _ = w.Write([]byte("hello and\n goodbye"))
236 + }))
237 +
238 + puppet := New()
239 + puppet.URL = srv.URL
240 + require.NoError(t, puppet.Init())
241 +
242 + return puppet, srv.Close
243 +}
244 +
245 +func prepareCaseConnectionRefused(t *testing.T) (*Puppet, func()) {
246 + t.Helper()
247 + puppet := New()
248 + puppet.URL = "http://127.0.0.1:65001"
249 + require.NoError(t, puppet.Init())
250 +
251 + return puppet, func() {}
252 +}
src/go/plugin/go.d/modules/puppet/response.go new
+32
@@ -0,0 +1,32 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package puppet
4 +
5 +type statusServiceResponse struct {
6 + StatusService *struct {
7 + Status struct {
8 + Experimental struct {
9 + JVMMetrics *struct {
10 + CPUUsage float64 `json:"cpu-usage" stm:"cpu_usage,1000,1"`
11 + GCCPUUsage float64 `json:"gc-cpu-usage" stm:"gc_cpu_usage,1000,1"`
12 + HeapMemory struct {
13 + Committed int64 `json:"committed" stm:"committed"`
14 + Init int64 `json:"init" stm:"init"`
15 + Max int64 `json:"max" stm:"max"`
16 + Used int64 `json:"used" stm:"used"`
17 + } `json:"heap-memory" stm:"jvm_heap"`
18 + FileDescriptors struct {
19 + Used int `json:"used" stm:"used"`
20 + Max int `json:"max" stm:"max"`
21 + } `json:"file-descriptors" stm:"fd"`
22 + NonHeapMemory struct {
23 + Committed int64 `json:"committed" stm:"committed"`
24 + Init int64 `json:"init" stm:"init"`
25 + Max int64 `json:"max" stm:"max"`
26 + Used int64 `json:"used" stm:"used"`
27 + } `json:"non-heap-memory" stm:"jvm_nonheap"`
28 + } `json:"jvm-metrics" stm:""`
29 + } `json:"experimental" stm:""`
30 + } `json:"status" stm:""`
31 + } `json:"status-service" stm:""`
32 +}
src/go/plugin/go.d/modules/puppet/testdata/config.json new
+20
@@ -0,0 +1,20 @@
1 +{
2 + "update_every": 123,
3 + "url": "ok",
4 + "body": "ok",
5 + "method": "ok",
6 + "headers": {
7 + "ok": "ok"
8 + },
9 + "username": "ok",
10 + "password": "ok",
11 + "proxy_url": "ok",
12 + "proxy_username": "ok",
13 + "proxy_password": "ok",
14 + "timeout": 123.123,
15 + "not_follow_redirects": true,
16 + "tls_ca": "ok",
17 + "tls_cert": "ok",
18 + "tls_key": "ok",
19 + "tls_skip_verify": true
20 +}
src/go/plugin/go.d/modules/puppet/testdata/config.yaml new
+17
@@ -0,0 +1,17 @@
1 +update_every: 123
2 +url: "ok"
3 +body: "ok"
4 +method: "ok"
5 +headers:
6 + ok: "ok"
7 +username: "ok"
8 +password: "ok"
9 +proxy_url: "ok"
10 +proxy_username: "ok"
11 +proxy_password: "ok"
12 +timeout: 123.123
13 +not_follow_redirects: yes
14 +tls_ca: "ok"
15 +tls_cert: "ok"
16 +tls_key: "ok"
17 +tls_skip_verify: yes
src/go/plugin/go.d/modules/puppet/testdata/serviceStatusResponse.json new
+497
@@ -0,0 +1,497 @@
1 +{
2 + "puppet-profiler": {
3 + "service_version": "8.4.0",
4 + "service_status_version": 1,
5 + "detail_level": "debug",
6 + "state": "running",
7 + "status": {
8 + "experimental": {
9 + "function-metrics": [],
10 + "resource-metrics": [],
11 + "catalog-metrics": [],
12 + "puppetdb-metrics": [],
13 + "inline-metrics": []
14 + }
15 + },
16 + "active_alerts": []
17 + },
18 + "jruby-metrics": {
19 + "service_version": "8.4.0",
20 + "service_status_version": 1,
21 + "detail_level": "debug",
22 + "state": "running",
23 + "status": {
24 + "experimental": {
25 + "jruby-pool-lock-status": {
26 + "current-state": ":not-in-use",
27 + "last-change-time": "2024-07-05T06:23:20.120Z"
28 + },
29 + "metrics": {
30 + "average-lock-wait-time": 0,
31 + "num-free-jrubies": 4,
32 + "borrow-count": 0,
33 + "average-requested-jrubies": 0.0,
34 + "borrow-timeout-count": 0,
35 + "return-count": 0,
36 + "borrow-timers": {
37 + "total": {
38 + "count": 0,
39 + "mean": 0,
40 + "max": 0,
41 + "rate": 0.0
42 + }
43 + },
44 + "borrow-retry-count": 0,
45 + "borrowed-instances": [],
46 + "average-borrow-time": 0,
47 + "num-jrubies": 4,
48 + "requested-count": 0,
49 + "queue-limit-hit-rate": 0.0,
50 + "average-lock-held-time": 0,
51 + "requested-instances": [],
52 + "queue-limit-hit-count": 0,
53 + "average-free-jrubies": 3.3019592583652217,
54 + "num-pool-locks": 0,
55 + "average-wait-time": 0
56 + }
57 + }
58 + },
59 + "active_alerts": []
60 + },
61 + "ca": {
62 + "service_version": "8.4.0",
63 + "service_status_version": 1,
64 + "detail_level": "debug",
65 + "state": "running",
66 + "status": {},
67 + "active_alerts": []
68 + },
69 + "master": {
70 + "service_version": "8.4.0",
71 + "service_status_version": 1,
72 + "detail_level": "debug",
73 + "state": "running",
74 + "status": {
75 + "experimental": {
76 + "http-metrics": [
77 + {
78 + "route-id": "puppet-v3-static_file_content-/*/",
79 + "count": 0,
80 + "mean": 0,
81 + "aggregate": 0
82 + },
83 + {
84 + "route-id": "puppet-v3-file_content-/*/",
85 + "count": 0,
86 + "mean": 0,
87 + "aggregate": 0
88 + },
89 + {
90 + "route-id": "puppet-v3-environments",
91 + "count": 0,
92 + "mean": 0,
93 + "aggregate": 0
94 + },
95 + {
96 + "route-id": "puppet-v3-tasks-:module-name-:task-name",
97 + "count": 0,
98 + "mean": 0,
99 + "aggregate": 0
100 + },
101 + {
102 + "route-id": "puppet-v3-file_metadata-/*/",
103 + "count": 0,
104 + "mean": 0,
105 + "aggregate": 0
106 + },
107 + {
108 + "route-id": "puppet-v3-facts-/*/",
109 + "count": 0,
110 + "mean": 0,
111 + "aggregate": 0
112 + },
113 + {
114 + "route-id": "other",
115 + "count": 0,
116 + "mean": 0,
117 + "aggregate": 0
118 + },
119 + {
120 + "route-id": "puppet-v3-tasks",
121 + "count": 0,
122 + "mean": 0,
123 + "aggregate": 0
124 + },
125 + {
126 + "route-id": "puppet-v3-compile",
127 + "count": 0,
128 + "mean": 0,
129 + "aggregate": 0
130 + },
131 + {
132 + "route-id": "puppet-v3-report-/*/",
133 + "count": 0,
134 + "mean": 0,
135 + "aggregate": 0
136 + },
137 + {
138 + "route-id": "puppet-v3-node-/*/",
139 + "count": 0,
140 + "mean": 0,
141 + "aggregate": 0
142 + },
143 + {
144 + "route-id": "puppet-v3-catalog-/*/",
145 + "count": 0,
146 + "mean": 0,
147 + "aggregate": 0
148 + },
149 + {
150 + "route-id": "puppet-v3-plans-:module-name-:plan-name",
151 + "count": 0,
152 + "mean": 0,
153 + "aggregate": 0
154 + },
155 + {
156 + "route-id": "puppet-v3-file_metadatas-/*/",
157 + "count": 0,
158 + "mean": 0,
159 + "aggregate": 0
160 + },
161 + {
162 + "route-id": "puppet-v3-file_bucket_file-/*/",
163 + "count": 0,
164 + "mean": 0,
165 + "aggregate": 0
166 + },
167 + {
168 + "route-id": "puppet-v4-catalog",
169 + "count": 0,
170 + "mean": 0,
171 + "aggregate": 0
172 + },
173 + {
174 + "route-id": "total",
175 + "count": 0,
176 + "mean": 0,
177 + "aggregate": 0
178 + },
179 + {
180 + "route-id": "puppet-v3-environment_modules-/*/",
181 + "count": 0,
182 + "mean": 0,
183 + "aggregate": 0
184 + },
185 + {
186 + "route-id": "puppet-v3-environment_classes-/*/",
187 + "count": 0,
188 + "mean": 0,
189 + "aggregate": 0
190 + },
191 + {
192 + "route-id": "puppet-v3-plans",
193 + "count": 0,
194 + "mean": 0,
195 + "aggregate": 0
196 + },
197 + {
198 + "route-id": "puppet-v3-environment_transports-/*/",
199 + "count": 0,
200 + "mean": 0,
201 + "aggregate": 0
202 + }
203 + ],
204 + "http-client-metrics": []
205 + }
206 + },
207 + "active_alerts": []
208 + },
209 + "server": {
210 + "service_version": "8.4.0",
211 + "service_status_version": 1,
212 + "detail_level": "debug",
213 + "state": "running",
214 + "status": {
215 + "experimental": {
216 + "http-metrics": [
217 + {
218 + "route-id": "puppet-v3-static_file_content-/*/",
219 + "count": 0,
220 + "mean": 0,
221 + "aggregate": 0
222 + },
223 + {
224 + "route-id": "puppet-v3-file_content-/*/",
225 + "count": 0,
226 + "mean": 0,
227 + "aggregate": 0
228 + },
229 + {
230 + "route-id": "puppet-v3-environments",
231 + "count": 0,
232 + "mean": 0,
233 + "aggregate": 0
234 + },
235 + {
236 + "route-id": "puppet-v3-tasks-:module-name-:task-name",
237 + "count": 0,
238 + "mean": 0,
239 + "aggregate": 0
240 + },
241 + {
242 + "route-id": "puppet-v3-file_metadata-/*/",
243 + "count": 0,
244 + "mean": 0,
245 + "aggregate": 0
246 + },
247 + {
248 + "route-id": "puppet-v3-facts-/*/",
249 + "count": 0,
250 + "mean": 0,
251 + "aggregate": 0
252 + },
253 + {
254 + "route-id": "other",
255 + "count": 0,
256 + "mean": 0,
257 + "aggregate": 0
258 + },
259 + {
260 + "route-id": "puppet-v3-tasks",
261 + "count": 0,
262 + "mean": 0,
263 + "aggregate": 0
264 + },
265 + {
266 + "route-id": "puppet-v3-compile",
267 + "count": 0,
268 + "mean": 0,
269 + "aggregate": 0
270 + },
271 + {
272 + "route-id": "puppet-v3-report-/*/",
273 + "count": 0,
274 + "mean": 0,
275 + "aggregate": 0
276 + },
277 + {
278 + "route-id": "puppet-v3-node-/*/",
279 + "count": 0,
280 + "mean": 0,
281 + "aggregate": 0
282 + },
283 + {
284 + "route-id": "puppet-v3-catalog-/*/",
285 + "count": 0,
286 + "mean": 0,
287 + "aggregate": 0
288 + },
289 + {
290 + "route-id": "puppet-v3-plans-:module-name-:plan-name",
291 + "count": 0,
292 + "mean": 0,
293 + "aggregate": 0
294 + },
295 + {
296 + "route-id": "puppet-v3-file_metadatas-/*/",
297 + "count": 0,
298 + "mean": 0,
299 + "aggregate": 0
300 + },
301 + {
302 + "route-id": "puppet-v3-file_bucket_file-/*/",
303 + "count": 0,
304 + "mean": 0,
305 + "aggregate": 0
306 + },
307 + {
308 + "route-id": "puppet-v4-catalog",
309 + "count": 0,
310 + "mean": 0,
311 + "aggregate": 0
312 + },
313 + {
314 + "route-id": "total",
315 + "count": 0,
316 + "mean": 0,
317 + "aggregate": 0
318 + },
319 + {
320 + "route-id": "puppet-v3-environment_modules-/*/",
321 + "count": 0,
322 + "mean": 0,
323 + "aggregate": 0
324 + },
325 + {
326 + "route-id": "puppet-v3-environment_classes-/*/",
327 + "count": 0,
328 + "mean": 0,
329 + "aggregate": 0
330 + },
331 + {
332 + "route-id": "puppet-v3-plans",
333 + "count": 0,
334 + "mean": 0,
335 + "aggregate": 0
336 + },
337 + {
338 + "route-id": "puppet-v3-environment_transports-/*/",
339 + "count": 0,
340 + "mean": 0,
341 + "aggregate": 0
342 + }
343 + ],
344 + "http-client-metrics": []
345 + }
346 + },
347 + "active_alerts": []
348 + },
349 + "status-service": {
350 + "service_version": "1.1.1",
351 + "service_status_version": 1,
352 + "detail_level": "debug",
353 + "state": "running",
354 + "status": {
355 + "experimental": {
356 + "jvm-metrics": {
357 + "cpu-usage": 0.04997002,
358 + "up-time-ms": 51328,
359 + "memory-pools": {
360 + "Metaspace": {
361 + "type": "NON_HEAP",
362 + "usage": {
363 + "committed": 214106112,
364 + "init": 0,
365 + "max": -1,
366 + "used": 183450600
367 + }
368 + },
369 + "CodeHeap 'non-nmethods'": {
370 + "type": "NON_HEAP",
371 + "usage": {
372 + "committed": 2555904,
373 + "init": 2555904,
374 + "max": 5840896,
375 + "used": 1923072
376 + }
377 + },
378 + "CodeHeap 'profiled nmethods'": {
379 + "type": "NON_HEAP",
380 + "usage": {
381 + "committed": 52559872,
382 + "init": 2555904,
383 + "max": 122908672,
384 + "used": 52545664
385 + }
386 + },
387 + "Compressed Class Space": {
388 + "type": "NON_HEAP",
389 + "usage": {
390 + "committed": 49020928,
391 + "init": 0,
392 + "max": 1073741824,
393 + "used": 37887856
394 + }
395 + },
396 + "G1 Eden Space": {
397 + "type": "HEAP",
398 + "usage": {
399 + "committed": 542113792,
400 + "init": 53477376,
401 + "max": -1,
402 + "used": 146800640
403 + }
404 + },
405 + "G1 Old Gen": {
406 + "type": "HEAP",
407 + "usage": {
408 + "committed": 462422016,
409 + "init": 1020264448,
410 + "max": 1073741824,
411 + "used": 335020032
412 + }
413 + },
414 + "G1 Survivor Space": {
415 + "type": "HEAP",
416 + "usage": {
417 + "committed": 69206016,
418 + "init": 0,
419 + "max": -1,
420 + "used": 68681728
421 + }
422 + },
423 + "CodeHeap 'non-profiled nmethods'": {
424 + "type": "NON_HEAP",
425 + "usage": {
426 + "committed": 15597568,
427 + "init": 2555904,
428 + "max": 122908672,
429 + "used": 15588736
430 + }
431 + }
432 + },
433 + "gc-cpu-usage": 0.0,
434 + "threading": {
435 + "thread-count": 59,
436 + "peak-thread-count": 59
437 + },
438 + "heap-memory": {
439 + "committed": 1073741824,
440 + "init": 1073741824,
441 + "max": 1073741824,
442 + "used": 550502400
443 + },
444 + "gc-stats": {
445 + "G1 Young Generation": {
446 + "count": 18,
447 + "total-time-ms": 550,
448 + "last-gc-info": {
449 + "duration-ms": 75
450 + }
451 + },
452 + "G1 Old Generation": {
453 + "count": 0,
454 + "total-time-ms": 0
455 + },
456 + "G1 Concurrent GC": {
457 + "count": 10,
458 + "total-time-ms": 49,
459 + "last-gc-info": {
460 + "duration-ms": 0
461 + }
462 + }
463 + },
464 + "start-time-ms": 1720160584298,
465 + "file-descriptors": {
466 + "used": 234,
467 + "max": 524288
468 + },
469 + "non-heap-memory": {
470 + "committed": 334102528,
471 + "init": 7667712,
472 + "max": -1,
473 + "used": 291591160
474 + },
475 + "nio-buffer-pools": {
476 + "mapped": {
477 + "count": 0,
478 + "memory-used": 0,
479 + "total-capacity": 0
480 + },
481 + "direct": {
482 + "count": 11,
483 + "memory-used": 197631,
484 + "total-capacity": 197631
485 + },
486 + "mapped - 'non-volatile memory'": {
487 + "count": 0,
488 + "memory-used": 0,
489 + "total-capacity": 0
490 + }
491 + }
492 + }
493 + }
494 + },
495 + "active_alerts": []
496 + }
497 +}