@@ -30,6 +30,7 @@ import argparse
30
30
import threading
31
31
import subprocess
32
32
import sys
33
+ from urllib.parse import urlparse
33
34
from ctypes import c_int
34
35
from socket import gethostname
35
36
from stat import ST_MODE, S_IXUSR
@@ -908,7 +909,6 @@ class Source(object):
908
909
# clear cached values from all my metrics
909
910
for _, m in self.metrics_by_name.items():
910
911
m.clear_values()
911
- # TODO: ditch metrics no longer found in document
912
912
913
913
# bump the fetch call counter for this source, and for the total (cluster 0)
914
914
self.pmda.stats_fetch_calls[self.cluster] += 1
@@ -948,6 +948,24 @@ class Source(object):
948
948
# NB: the requests package automatically enables http keep-alive and compression
949
949
self.document = r.text
950
950
951
+ # ditch metrics no longer found in document
952
+ for name, metric in self.pmda.all_metrics.items():
953
+ split_metric = name.split(".")
954
+ stripped_metric = name.replace("openmetrics.%s." % self.name, "")
955
+ self.pmda.debug("stripped metric --> %s" % stripped_metric) if self.pmda.dbg else None
956
+ if stripped_metric == "metric2":
957
+ self.pmda.debug("self.document: %s" % self.document) if self.pmda.dbg else None
958
+ if split_metric[1] == self.name and stripped_metric not in self.document:
959
+ self.pmda.debug("true") if self.pmda.dbg else None
960
+ try:
961
+ self.pmda.remove_metric(name, metric)
962
+ self.pmda.removed_metrics[name] = metric
963
+ self.pmda.set_need_refresh()
964
+ self.pmda.debug("removed metric from existing source: %s" % name) if self.pmda.dbg else None
965
+ del self.pmda.all_metrics[name]
966
+ except Exception as e:
967
+ self.pmda.debug("can't remove metric: %s, see error: %s" % (name, e)) if self.pmda.dbg else None
968
+
951
969
# update fetch time counter stats, in ms
952
970
incr = int(1000 * (time.time() - fetch_time))
953
971
self.pmda.stats_fetch_time[self.cluster] += incr
@@ -1040,6 +1058,10 @@ class OpenMetricsPMDA(PMDA):
1040
1058
self.all_metrics = {}
1041
1059
# keep track of removed metrics, in case of re-addition
1042
1060
self.removed_metrics = {}
1061
+ # keep track of control initialization
1062
+ self.controls = {0:0}
1063
+ # keep track of modified sources, in need of extra refresh
1064
+ self.modified_files = []
1043
1065
1044
1066
# compiled regex cache
1045
1067
self.regex_cache = {}
@@ -1147,12 +1169,40 @@ class OpenMetricsPMDA(PMDA):
1147
1169
if mtime is None or m > mtime:
1148
1170
mtime = m
1149
1171
ret.append(fname)
1172
+ fname = os.path.join(path, f)
1173
+ with open(fname, 'r') as name:
1174
+ f_path = name.readline().strip()
1175
+ if f_path.startswith("file:///"):
1176
+ parsed = urlparse(f_path)
1177
+ m = os.path.getmtime(parsed.path)
1178
+ if mtime is None or m > mtime:
1179
+ mtime = m
1180
+ self.modified_files.append(fname)
1150
1181
for d in subdirs:
1151
1182
m, _ = self.traverse(os.path.join(path, d), mtime)
1152
1183
if mtime is None or m > mtime:
1153
1184
mtime = m
1154
1185
return mtime, ret
1155
1186
1187
+ def initialize_controls(self, cluster):
1188
+ # initialize statistics
1189
+ self.stats_fetch_calls[cluster] = 0
1190
+ self.stats_fetch_time[cluster] = 0
1191
+ self.stats_parse_time[cluster] = 0
1192
+ self.stats_status[cluster] = "unknown"
1193
+ self.stats_status_code[cluster] = 0
1194
+
1195
+ self.controls[cluster] = 1
1196
+
1197
+ def delete_controls(self, cluster):
1198
+ del self.stats_fetch_calls[cluster]
1199
+ del self.stats_fetch_time[cluster]
1200
+ del self.stats_parse_time[cluster]
1201
+ del self.stats_status[cluster]
1202
+ del self.stats_status_code[cluster]
1203
+
1204
+ self.controls[cluster] = 0
1205
+
1156
1206
def rescan_confdir(self):
1157
1207
'''Scan the configuration directories for any new .url files
1158
1208
or scripts. Ensure there is a Source registered in the
@@ -1163,6 +1213,10 @@ class OpenMetricsPMDA(PMDA):
1163
1213
invoked frequently by src/python/pmda.c.
1164
1214
'''
1165
1215
1216
+ # re-initialize variables to keep track of modified files before new traversal
1217
+ self.modified_files = []
1218
+ m_files = []
1219
+
1166
1220
traverse_time = time.time()
1167
1221
dir_mtime, conf_filelist = self.traverse(self.config_dir, self.config_dir_mtime)
1168
1222
traverse_time = time.time() - traverse_time
@@ -1183,6 +1237,11 @@ class OpenMetricsPMDA(PMDA):
1183
1237
name = file_split[0].replace(self.config_dir + "/", "").replace("/", ".")
1184
1238
nicknames.append(name)
1185
1239
1240
+ for file in self.modified_files:
1241
+ file_split = os.path.splitext(file)
1242
+ name = file_split[0].replace(self.config_dir + "/", "").replace("/", ".")
1243
+ m_files.append(name)
1244
+
1186
1245
# check if config change adds a previously removed source
1187
1246
for key in self.removed_metrics:
1188
1247
split_name = key.split(".")
@@ -1197,6 +1256,9 @@ class OpenMetricsPMDA(PMDA):
1197
1256
try:
1198
1257
remove_name = key
1199
1258
remove_obj = value
1259
+ cluster = self.cluster_table.intern_lookup_value(split_name[1])
1260
+ if self.controls[cluster] == 1:
1261
+ self.delete_controls(cluster)
1200
1262
self.remove_metric(remove_name, remove_obj)
1201
1263
self.removed_metrics[remove_name] = remove_obj
1202
1264
self.debug("removed metric name: %s" % remove_name) if self.dbg else None
@@ -1236,13 +1298,16 @@ class OpenMetricsPMDA(PMDA):
1236
1298
# this source is already known
1237
1299
self.assert_source_invariants(name=name)
1238
1300
s = self.source_by_name[name]
1301
+ self.debug("m files : %s" % m_files) if self.dbg else None
1239
1302
cluster_for_refresh = []
1240
1303
cluster_for_refresh_names = []
1241
- if name in self.re_add_list:
1304
+ if name in self.re_add_list or name in m_files :
1242
1305
for key,value in self.source_by_cluster.items():
1243
1306
if value == s:
1244
1307
cluster_for_refresh.append(key)
1245
1308
cluster_for_refresh_names.append(name)
1309
+ if self.controls[key] == 0:
1310
+ self.initialize_controls(key)
1246
1311
self.debug("refreshing cluster list: %s" % cluster_for_refresh_names) if self.dbg else None
1247
1312
self.refresh_some_clusters_for_fetch(cluster_for_refresh)
1248
1313
else:
@@ -1253,12 +1318,7 @@ class OpenMetricsPMDA(PMDA):
1253
1318
self.source_by_name[source.name] = source
1254
1319
self.source_by_cluster[source.cluster] = source
1255
1320
1256
- # initialize statistics
1257
- self.stats_fetch_calls[cluster] = 0
1258
- self.stats_fetch_time[cluster] = 0
1259
- self.stats_parse_time[cluster] = 0
1260
- self.stats_status[cluster] = "unknown"
1261
- self.stats_status_code[cluster] = 0
1321
+ self.initialize_controls(cluster)
1262
1322
1263
1323
save_cluster_table = True
1264
1324
self.log("Found source %s cluster %d" % (name, cluster))
0 commit comments