Skip to content

Commit efd5ea0

Browse files
authored
Merge pull request #8 from codebude/master
Added metrics for service health status
2 parents 13f5dd9 + 5c329cb commit efd5ea0

1 file changed

Lines changed: 66 additions & 8 deletions

File tree

code/exporter.py

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@
2626
SCRAPE_INTERVAL = 30
2727

2828

29-
HETZNER_CLOUD_API_URL = 'https://api.hetzner.cloud/v1/load_balancers/'
29+
HETZNER_CLOUD_API_URL_BASE = 'https://api.hetzner.cloud/v1'
30+
HETZNER_CLOUD_API_URL_LB = f'{HETZNER_CLOUD_API_URL_BASE}/load_balancers/'
31+
HETZNER_CLOUD_API_URL_SERVER = f'{HETZNER_CLOUD_API_URL_BASE}/servers/'
3032

31-
def get_all_load_balancers_ids():
32-
url = f'{HETZNER_CLOUD_API_URL}'
33+
34+
def get_all_load_balancers_ids() -> dict:
35+
url = f'{HETZNER_CLOUD_API_URL_LB}'
3336
headers = {
3437
'Content-type': "application/json",
3538
'Authorization': f"Bearer {access_token}"
@@ -39,8 +42,8 @@ def get_all_load_balancers_ids():
3942
return get.json()['load_balancers']
4043

4144

42-
def get_load_balancer_info(lbid):
43-
url = f'{HETZNER_CLOUD_API_URL}{lbid}'
45+
def get_load_balancer_info(lbid) -> dict:
46+
url = f'{HETZNER_CLOUD_API_URL_LB}{lbid}'
4447

4548
headers = {
4649
'Content-type': "application/json",
@@ -51,12 +54,51 @@ def get_load_balancer_info(lbid):
5154
return get.json()
5255

5356

57+
def get_all_server_names() -> dict:
58+
url = f'{HETZNER_CLOUD_API_URL_SERVER}'
59+
60+
headers = {
61+
'Content-type': "application/json",
62+
'Authorization': f"Bearer {access_token}"
63+
}
64+
65+
get = requests.get(url, headers=headers)
66+
return {x['id']: x['name'] for x in get.json()['servers']}
67+
68+
69+
def get_server_info(server_id) -> dict:
70+
url = f'{HETZNER_CLOUD_API_URL_SERVER}{server_id}'
71+
72+
headers = {
73+
'Content-type': "application/json",
74+
'Authorization': f"Bearer {access_token}"
75+
}
76+
77+
get = requests.get(url, headers=headers)
78+
return get.json()
79+
80+
81+
def get_server_name_from_cache(server_id: str) -> str:
82+
global server_name_cache
83+
if server_id in server_name_cache:
84+
return server_name_cache[server_id]
85+
else:
86+
# Refresh cache
87+
server_name_cache = get_all_server_names()
88+
# Check again
89+
if server_id in server_name_cache:
90+
return server_name_cache[server_id]
91+
else:
92+
# If still not found, return id as name
93+
return server_id
94+
95+
5496
def get_metrics(metrics_type, lbid):
5597
utc_offset_sec = time.altzone if time.localtime().tm_isdst else time.timezone
5698
utc_offset = datetime.timedelta(seconds=-utc_offset_sec)
5799
hetzner_date = datetime.datetime.now().replace(tzinfo=datetime.timezone(offset=utc_offset)).isoformat()
58100

59-
url = f"{HETZNER_CLOUD_API_URL}{lbid}/metrics"
101+
url = f"{HETZNER_CLOUD_API_URL_LB}{lbid}/metrics"
60102

61103
headers = {
62104
'Content-type': "application/json",
@@ -95,7 +137,7 @@ def get_metrics(metrics_type, lbid):
95137
try:
96138
load_balancer_name = load_balancer['name']
97139
except Exception as e:
98-
print('Couldnt get field', e )
140+
print("Couldn't get field", e )
99141
sys.exit(1)
100142

101143

@@ -111,18 +153,24 @@ def get_metrics(metrics_type, lbid):
111153

112154
print(f'\nScrape intreval: {SCRAPE_INTERVAL} seconds')
113155

156+
print('\nBuilding server name cache from Hetzner for labeling ...')
157+
server_name_cache = get_all_server_names()
158+
print(f'Retrieved {len(server_name_cache.keys())} server names from Hetzner ...\n')
159+
114160
id_name_list = ['hetzner_load_balancer_id', 'hetzner_load_balancer_name']
115161
hetzner_load_balancer_info = Info('hetzner_load_balancer', 'Hetzner Load Balancer Exporter build info')
116162
hetzner_openconnections = Gauge('hetzner_load_balancer_open_connections', 'Open Connections on Hetzner Load Balancer', id_name_list)
117163
hetzner_connections_per_second = Gauge('hetzner_load_balancer_connections_per_second', 'Connections per Second on Hetzner Load Balancer', id_name_list)
118164
hetzner_requests_per_second = Gauge('hetzner_load_balancer_requests_per_second', 'Requests per Second on Hetzner Load Balancer', id_name_list)
119165
hetzner_bandwidth_in = Gauge('hetzner_load_balancer_bandwidth_in', 'Bandwidth in on Hetzner Load Balancer', id_name_list)
120166
hetzner_bandwidth_out = Gauge('hetzner_load_balancer_bandwidth_out', 'Bandwidth out on Hetzner Load Balancer', id_name_list)
167+
id_name_service_list = id_name_list + ['hetzner_target_id', 'hetzner_target_name', 'hetzner_target_port']
168+
hetzner_service_state = Gauge('hetzner_load_balancer_service_state', 'Health status of Load Balancer\'s services', id_name_service_list)
121169

122170
start_http_server(8000)
123171
print('\nHetzner Load Balancer Exporter started')
124172
print('Visit http://localhost:8000/ to view the metrics')
125-
hetzner_load_balancer_info.info({'version': '2.0.0', 'buildhost': 'drake0103@gmail.com'})
173+
hetzner_load_balancer_info.info({'version': '2.0.0', 'buildhost': 'netblognet@gmail.com'})
126174

127175
while True:
128176
for load_balancer_id, lb_name, load_balancer_type in load_balancer_full_list:
@@ -137,4 +185,14 @@ def get_metrics(metrics_type, lbid):
137185
hetzner_load_balancer_name=lb_name).set(get_metrics('bandwidth',load_balancer_id)["metrics"]["time_series"]["bandwidth.in"]["values"][0][1])
138186
hetzner_bandwidth_out.labels(hetzner_load_balancer_id=load_balancer_id,
139187
hetzner_load_balancer_name=lb_name).set(get_metrics('bandwidth',load_balancer_id)["metrics"]["time_series"]["bandwidth.out"]["values"][0][1])
188+
189+
lb_info = get_load_balancer_info(load_balancer_id)['load_balancer']
190+
for target in [x for x in lb_info['targets'] if x['type'] == 'server']:
191+
for health_status in target['health_status']:
192+
hetzner_service_state.labels(hetzner_load_balancer_id=load_balancer_id,
193+
hetzner_load_balancer_name=lb_name,
194+
hetzner_target_id=target['server']['id'],
195+
hetzner_target_name=get_server_name_from_cache(target['server']['id']),
196+
hetzner_target_port=health_status['listen_port'])\
197+
.set((1 if health_status['status'] == 'healthy' else 0))
140198
time.sleep(int(SCRAPE_INTERVAL))

0 commit comments

Comments
 (0)