@cryptotaxi247 / netdata-1 / commits / 18ba6d174

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)