springboot charts
Wing924 committed
Feb 23, 2018 at 11:29 UTC
18ba6d1745e4b255f10d8a4d7625518e95dc6b48
2 files changed
+263
conf.d/python.d/springboot.conf
new
+121
@@ -0,0 +1,121 @@
1
+# netdata python.d.plugin configuration for springboot
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
+# retries sets the number of retries to be made in case of failures.
31
+# If unset, the default for python.d.plugin is used.
32
+# Attempts to restore the service are made once every update_every
33
+# and only if the module has collected values in the past.
34
+# retries: 60
35
+
36
+# autodetection_retry sets the job re-check interval in seconds.
37
+# The job is not deleted if check fails.
38
+# Attempts to start the job are made once every autodetection_retry.
39
+# This feature is disabled by default.
40
+# autodetection_retry: 0
41
+
42
+# ----------------------------------------------------------------------
43
+# JOBS (data collection sources)
44
+#
45
+# Any number of jobs is supported.
46
+#
47
+# All python.d.plugin JOBS (for all its modules) support a set of
48
+# predefined parameters. These are:
49
+#
50
+# job_name:
51
+# name: myname # the JOB's name as it will appear at the
52
+# # dashboard (by default is the job_name)
53
+# # JOBs sharing a name are mutually exclusive
54
+# update_every: 1 # the JOB's data collection frequency
55
+# priority: 60000 # the JOB's order on the dashboard
56
+# retries: 60 # the JOB's number of restoration attempts
57
+# autodetection_retry: 0 # the JOB's re-check interval in seconds
58
+#
59
+# Additionally to the above, this plugin also supports the following:
60
+#
61
+# url: 'http://127.0.0.1/metrics' # the URL of the spring boot actuator metrics
62
+#
63
+# if the URL is password protected, the following are supported:
64
+#
65
+# user: 'username'
66
+# pass: 'password'
67
+#
68
+# defaults:
69
+# [chart_id]: true | false # enables/disables default charts, defaults true.
70
+# extras: {} # defines extra charts to monitor, please see the example below
71
+# - id: [chart_id]
72
+# options: {}
73
+# lines: []
74
+#
75
+# If all defaults is disabled and no extra charts are defined, this module will disable itself, as it has no data to
76
+# collect.
77
+#
78
+# Configuration example
79
+# ---------------------
80
+# expample:
81
+#
82
+# name: 'example'
83
+# url: 'http://localhost:8080/metrics'
84
+# defaults:
85
+# response_code: true
86
+# threads: true
87
+# gc_time: true
88
+# gc_ope: true
89
+# heap: false
90
+# extras:
91
+# - id: 'heap'
92
+# options: { title: 'Heap Memory Usage', units: 'KB', family: 'heap memory', context: 'springboot.heap', charttype: 'stacked' }
93
+# lines:
94
+# - { dimension: 'mem.free', name: 'free'}
95
+# - { dimension: 'mempool.eden.used', name: 'eden', algorithm: 'absolute', multiplier: 1, divisor: 1}
96
+# - { dimension: 'mempool.survivor.used', name: 'survivor', algorithm: 'absolute', multiplier: 1, divisor: 1}
97
+# - { dimension: 'mempool.tenured.used', name: 'tenured', algorithm: 'absolute', multiplier: 1, divisor: 1}
98
+# - id: 'heap_eden'
99
+# options: { title: 'Eden Memory Usage', units: 'KB', family: 'heap memory', context: 'springboot.heap_eden', charttype: 'area' }
100
+# lines:
101
+# - { dimension: 'mempool.eden.used', name: 'used'}
102
+# - { dimension: 'mempool.eden.committed', name: 'commited'}
103
+# - id: 'heap_survivor'
104
+# options: { title: 'Survivor Memory Usage', units: 'KB', family: 'heap memory', context: 'springboot.heap_survivor', charttype: 'area' }
105
+# lines:
106
+# - { dimension: 'mempool.survivor.used', name: 'used'}
107
+# - { dimension: 'mempool.survivor.committed', name: 'commited'}
108
+# - id: 'heap_tenured'
109
+# options: { title: 'Tenured Memory Usage', units: 'KB', family: 'heap memory', context: 'springboot.heap_tenured', charttype: 'area' }
110
+# lines:
111
+# - { dimension: 'mempool.tenured.used', name: 'used'}
112
+# - { dimension: 'mempool.tenured.committed', name: 'commited'}
113
+#
114
+
115
+local:
116
+ name: 'local'
117
+ url: 'http://localhost:8080/metrics'
118
+
119
+local_ip:
120
+ name: 'local'
121
+ url: 'http://127.0.0.1:8080/metrics'
python.d/springboot.chart.py
new
+142
@@ -0,0 +1,142 @@
1
+# -*- coding: utf-8 -*-
2
+# Description: tomcat netdata python.d module
3
+# Author: Wing924
4
+
5
+import json
6
+from bases.FrameworkServices.UrlService import UrlService
7
+
8
+# default module values (can be overridden per job in `config`)
9
+# update_every = 2
10
+priority = 60000
11
+retries = 60
12
+
13
+
14
+DEFAULT_ORDER = ['response_code', 'threads', 'gc_time', 'gc_ope', 'heap']
15
+
16
+DEFAULT_CHARTS = {
17
+ 'response_code': {
18
+ 'options': [None, "Response Codes", "requests/s", "response", "springboot.response_code", "stacked"],
19
+ 'lines': [
20
+ ["resp.other", 'Other', 'incremental'],
21
+ ["resp.1xx", '1xx', 'incremental'],
22
+ ["resp.2xx", '2xx', 'incremental'],
23
+ ["resp.3xx", '3xx', 'incremental'],
24
+ ["resp.4xx", '4xx', 'incremental'],
25
+ ["resp.5xx", '5xx', 'incremental'],
26
+ ]},
27
+ 'threads': {
28
+ 'options': [None, "Threads", "current threads", "threads", "springboot.threads", "area"],
29
+ 'lines': [
30
+ ["threads.daemon", 'daemon', 'absolute'],
31
+ ["threads", 'total', 'absolute'],
32
+ ]},
33
+ 'gc_time': {
34
+ 'options': [None, "GC Time", "milliseconds", "garbage collection", "springboot.gc_time", "area"],
35
+ 'lines': [
36
+ ["gc.copy.time", 'Copy', 'incremental'],
37
+ ["gc.marksweepcompact.time", 'MarkSweepCompact', 'incremental'],
38
+ ["gc.parnew.time", 'ParNew', 'incremental'],
39
+ ["gc.concurrentmarksweep.time", 'ConcurrentMarkSweep', 'incremental'],
40
+ ["gc.ps_scavenge.time", 'PS Scavenge', 'incremental'],
41
+ ["gc.ps_marksweep.time", 'PS MarkSweep', 'incremental'],
42
+ ["gc.g1_young_generation.time", 'G1 Young Generation', 'incremental'],
43
+ ["gc.g1_old_generation.time", 'G1 Old Generation', 'incremental'],
44
+ ]},
45
+ 'gc_ope': {
46
+ 'options': [None, "GC Operations", "operations/s", "garbage collection", "springboot.gc_ope", "area"],
47
+ 'lines': [
48
+ ["gc.copy.count", 'Copy', 'incremental'],
49
+ ["gc.marksweepcompact.count", 'MarkSweepCompact', 'incremental'],
50
+ ["gc.parnew.count", 'ParNew', 'incremental'],
51
+ ["gc.concurrentmarksweep.count", 'ConcurrentMarkSweep', 'incremental'],
52
+ ["gc.ps_scavenge.count", 'PS Scavenge', 'incremental'],
53
+ ["gc.ps_marksweep.count", 'PS MarkSweep', 'incremental'],
54
+ ["gc.g1_young_generation.count", 'G1 Young Generation', 'incremental'],
55
+ ["gc.g1_old_generation.count", 'G1 Old Generation', 'incremental'],
56
+ ]},
57
+ 'heap': {
58
+ 'options': [None, "Heap Memory Usage", "KB", "heap memory", "springboot.heap", "area"],
59
+ 'lines': [
60
+ ["heap.committed", 'committed', "absolute"],
61
+ ["heap.used", 'used', "absolute"],
62
+ ]},
63
+}
64
+
65
+class Service(UrlService):
66
+ def __init__(self, configuration=None, name=None):
67
+ UrlService.__init__(self, configuration=configuration, name=name)
68
+ self.url = self.configuration.get('url', "http://localhost:8080/metrics")
69
+ self._setup_charts()
70
+
71
+ def _get_data(self):
72
+ """
73
+ Format data received from http request
74
+ :return: dict
75
+ """
76
+ data = None
77
+ raw_data = self._get_raw_data()
78
+ if raw_data:
79
+ try:
80
+ data = json.loads(raw_data)
81
+ except:
82
+ self.debug('%s is not a vaild JSON page' % self.url)
83
+ return None
84
+
85
+ for key in ['1xx', '2xx', '3xx', '4xx', '5xx', 'other']:
86
+ data['resp.' + key] = 0
87
+ for key, value in data.iteritems():
88
+ if 'counter.status.' in key:
89
+ try:
90
+ status_type = key[15:16] + 'xx'
91
+ except:
92
+ status_type = 'other'
93
+
94
+ data['resp.' + status_type] += value
95
+
96
+ return data or None
97
+
98
+ def _setup_charts(self):
99
+ order = []
100
+ definitions = {}
101
+ defaults = self.configuration.get('defaults', {})
102
+
103
+ for chart in DEFAULT_ORDER:
104
+ if defaults.get(chart, True):
105
+ order.append(chart)
106
+ definitions[chart] = DEFAULT_CHARTS[chart]
107
+
108
+ for extra in self.configuration.get('extras', []):
109
+ self._add_extra_chart(definitions, extra)
110
+ order.append(extra['id'])
111
+
112
+ self.order = order
113
+ self.definitions = definitions
114
+
115
+ def _add_extra_chart(self, charts, chart):
116
+ chart_id = chart.get('id', None) or self.die('id is not defined in extra chart')
117
+ options = chart.get('options', None) or self.die('option is not defined in extra chart: %s' % chart_id)
118
+ lines = chart.get('lines', None) or self.die('lines is not defined in extra chart: %s' % chart_id)
119
+
120
+ title = options.get('title', None) or self.die('title is missing: %s', chart_id)
121
+ units = options.get('units', None) or self.die('units is missing: %s', chart_id)
122
+ family = options.get('family', title)
123
+ context = options.get('context', 'springboot.' + title)
124
+ charttype = options.get('charttype', 'line')
125
+
126
+ result = {
127
+ 'options': [None, title, units, family, context, charttype],
128
+ 'lines': [],
129
+ }
130
+
131
+ for line in lines:
132
+ dimension = line.get('dimension', None) or self.die('dimension is missing: %s', chart_id)
133
+ name = line.get('name', dimension)
134
+ algorithm = line.get('algorithm', 'absolute')
135
+ multiplier = line.get('multiplier', 1)
136
+ divisor = line.get('divisor', 1)
137
+ result['lines'].append([dimension, name, algorithm, multiplier, divisor])
138
+
139
+ charts[chart_id] = result
140
+
141
+ def die(self, error_message):
142
+ raise Exception(error_message)