Merge ~jacekn/prometheus-charm:snmp into prometheus-charm:master

Proposed by Jacek Nykis
Status: Merged
Approved by: Jamon Camisso
Approved revision: 9e29423aaa6888342c279020af5f603b73fc940f
Merge reported by: Jamon Camisso
Merged at revision: not available
Proposed branch: ~jacekn/prometheus-charm:snmp
Merge into: prometheus-charm:master
Diff against target: 177 lines (+81/-5)
4 files modified
config.yaml (+31/-0)
metadata.yaml (+2/-2)
reactive/prometheus.py (+39/-0)
templates/prometheus.yml.j2 (+9/-3)
Reviewer Review Type Date Requested Status
Jamon Camisso (community) Approve
Review via email: mp+311624@code.launchpad.net

Description of the change

Add snmp-exporter relation support

Add scrape-jobs config option to allow arbitrary SNMP jobs to be added. This is needed because SNMP config is non trivial. Targets can belong to one of a few different "modules". For each module or group of targets we likely need different scrape interval and timeout options.

We could try to do it like this:
juju set prometheus snmp_targets='["target1[module_name1][30s][30s]", "target2[module_name2][90s][90s]"'

but this can become unmanageable quickly and would require logic to programmatically split targets into separate scrape jobs.

To post a comment you must log in.
Revision history for this message
Jamon Camisso (jamon) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/config.yaml b/config.yaml
2index 8a2007b..a8497c0 100644
3--- a/config.yaml
4+++ b/config.yaml
5@@ -37,6 +37,37 @@ options:
6 - 'my-production-site:443'
7 label: production
8 default: ""
9+ scrape-jobs:
10+ type: string
11+ default: ""
12+ description: |
13+ Can be used to add custom scrape jobs, for example SNMP exporter config.
14+ This will be parsed as YAML, format is a list of dicts as shown in the example.
15+ For convenience "{{ snmp_exporter }}" will be replaced with SNMP exporter address.
16+ Example:
17+ - job_name: 'snmp'
18+ scrape_interval: 1m
19+ scrape_timeout: 1m
20+ static_configs:
21+ - targets:
22+ - device1.example.com
23+ - device2.example.com
24+ params:
25+ module: [default]
26+ relabel_configs:
27+ - source_labels: [__address__]
28+ target_label: __param_target
29+ - source_labels: [__param_target]
30+ target_label: instance
31+ - target_label: __address__
32+ replacement: "{{ snmp_exporter }}" # SNMP exporter.
33+ - job_name: 'my-job'
34+ scrape_interval: 30s
35+ scrape_timeout: 30s
36+ static_configs:
37+ - targets:
38+ - server1.example.com
39+ - server2.example.com
40 monitor-name:
41 type: string
42 description: |
43diff --git a/metadata.yaml b/metadata.yaml
44index 2dec74f..1eba152 100644
45--- a/metadata.yaml
46+++ b/metadata.yaml
47@@ -11,8 +11,6 @@ series:
48 - xenial
49 tags:
50 - monitoring
51-categories:
52- - misc
53 subordinate: false
54 provides:
55 grafana-source:
56@@ -27,6 +25,8 @@ requires:
57 interface: prometheus
58 alertmanager-service:
59 interface: http
60+ snmp-exporter:
61+ interface: http
62 storage:
63 metrics-filesystem:
64 type: filesystem
65diff --git a/reactive/prometheus.py b/reactive/prometheus.py
66index 917b575..021c9f4 100644
67--- a/reactive/prometheus.py
68+++ b/reactive/prometheus.py
69@@ -3,6 +3,7 @@ import pwd
70 import subprocess
71 import yaml
72 import re
73+from jinja2 import Template
74
75 from charmhelpers import fetch
76 from charmhelpers.core import host, hookenv, unitdata
77@@ -133,6 +134,20 @@ def get_version():
78 return (1, 0, 0)
79
80
81+def get_manual_jobs():
82+ config = hookenv.config()
83+ if not config.get('scrape-jobs', False):
84+ return None
85+ try:
86+ yaml.safe_load(config.get('scrape-jobs'))
87+ except:
88+ return None
89+ else:
90+ snmp_exporter = unitdata.kv().get('snmp_exporter_address', '127.0.0.1:9116')
91+ t = Template(config.get('scrape-jobs'))
92+ return t.render(snmp_exporter=snmp_exporter)
93+
94+
95 @when('prometheus.do-reconfig-yml')
96 def write_prometheus_config_yml():
97 hookenv.status_set('maintenance', 'Updating configuration')
98@@ -141,6 +156,7 @@ def write_prometheus_config_yml():
99 ver_major, ver_minor, ver_patch = get_version()
100 target_jobs = unitdata.kv().get('target_jobs', [])
101 scrape_jobs = unitdata.kv().get('scrape_jobs', [])
102+ manual_jobs = get_manual_jobs()
103
104 # transform eg. 'h1:p1 , h2:p2' (string), to ['h1:p1', 'h2:p2'] (list)
105 static_targets = None
106@@ -162,6 +178,7 @@ def write_prometheus_config_yml():
107 'jobs': target_jobs,
108 'federate': federate_config,
109 'scrape_jobs': scrape_jobs,
110+ 'manual_jobs': manual_jobs,
111 'ver_major': ver_major,
112 'ver_minor': ver_minor,
113 'ver_patch': ver_patch,
114@@ -371,6 +388,28 @@ def update_prometheus_alertmanager(alertmanager):
115
116
117 @when('prometheus.started')
118+@when_not('snmp-exporter.available')
119+def update_prometheus_no_snmp_exporter():
120+ unitdata.kv().unset('snmp_exporter_address')
121+ set_state('prometheus.do-check-reconfig')
122+
123+
124+@when('prometheus.started')
125+@when('snmp-exporter.available')
126+def update_prometheus_snmp_exporter(snmp_exporter):
127+ services = snmp_exporter.services()
128+ if not (data_changed('snmp-exporter.related_services', services)):
129+ return
130+ # At this point we only support single snmp exporter target
131+ for service in services:
132+ for unit in service['hosts']:
133+ hookenv.log('{} has a unit {}:{}'.format(
134+ service['service_name'], unit['hostname'], unit['port']))
135+ unitdata.kv().set('snmp_exporter_address', '{hostname}:{port}'.format(**unit))
136+ set_state('prometheus.do-check-reconfig')
137+
138+
139+@when('prometheus.started')
140 @when('nrpe-external-master.available')
141 def update_nrpe_config(svc):
142 # python-dbus is used by check_upstart_job
143diff --git a/templates/prometheus.yml.j2 b/templates/prometheus.yml.j2
144index d2ba919..0e39110 100644
145--- a/templates/prometheus.yml.j2
146+++ b/templates/prometheus.yml.j2
147@@ -1,7 +1,9 @@
148 {%- if ver_major == 0 and ver_minor < 20 %}
149 {%- set static_config_option_text = "target_groups" %}
150+{%- set file_sd_configs_option_text = "names" %}
151 {%- else %}
152 {%- set static_config_option_text = "static_configs" %}
153+{%- set file_sd_configs_option_text = "files" %}
154 {%- endif %}
155 # my global config
156 global:
157@@ -67,13 +69,17 @@ scrape_configs:
158 group: 'promoagents-juju'
159 {%- endfor %}
160
161+{% if manual_jobs %}
162+# Manually configured scrape jobs eg. SNMP exporter
163+# We need to paste raw because we don't know all future option names
164+{{ manual_jobs|indent(2, True) }}
165+{% endif %}
166+
167 {%- if promreg %}
168 # Prometheus registration
169 - job_name: 'prometheus-registration'
170 file_sd_configs:
171-# After version 0.2.0 files is correct not names
172-# - files: ['/etc/prometheus/promreg/targets.yaml']
173- - names: ['/etc/prometheus/promreg/targets.yaml']
174+ - {{ file_sd_configs_option_text }}: ['/etc/prometheus/promreg/targets.yaml']
175 {%- endif %}
176
177 # federate jobs

Subscribers

People subscribed via source and target branches