Skip to content

Commit 7267dfe

Browse files
committed
pmdaopenmetrics metric removal qa bug fix
addresses multiple qa test failures. all qa tests now pass, and updated test #1976 checks for metric removal from a modified source that still persists in the config directory.
1 parent 5f82c94 commit 7267dfe

File tree

3 files changed

+81
-8
lines changed

3 files changed

+81
-8
lines changed

qa/1976

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,17 @@ $sudo touch -t 197001010000 $urlfile
7878
pminfo openmetrics.simple_metric
7979
echo
8080

81+
echo "-- metric removal by modifying source file, source persists -- "
82+
path=$tmp'.simple_metric.txt'
83+
$sudo cp $here/openmetrics/samples/simple_metric.txt $tmp.saved_metric2
84+
$sudo cp $here/openmetrics/samples/simple_metric.txt $tmp2.saved_metric2
85+
$sudo sed -i -e "/metric2/d" $path
86+
$sudo sed -i -e "/metric2/d" $here/openmetrics/samples/simple_metric.txt
87+
pminfo openmetrics.simple_metric
88+
$sudo mv $tmp.saved_metric2 $path
89+
$sudo mv $tmp2.saved_metric2 $here/openmetrics/samples/simple_metric.txt
90+
91+
8192
_pmdaopenmetrics_remove >/dev/null 2>&1
8293

8394
# success, all done

qa/1976.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ Error: openmetrics.simple_metric: Unknown metric name
1515
openmetrics.simple_metric.metric2
1616
openmetrics.simple_metric.metric1
1717

18+
-- metric removal by modifying source file, source persists --
19+
openmetrics.simple_metric.metric1

src/pmdas/openmetrics/pmdaopenmetrics.python

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import argparse
3030
import threading
3131
import subprocess
3232
import sys
33+
from urllib.parse import urlparse
3334
from ctypes import c_int
3435
from socket import gethostname
3536
from stat import ST_MODE, S_IXUSR
@@ -908,7 +909,6 @@ class Source(object):
908909
# clear cached values from all my metrics
909910
for _, m in self.metrics_by_name.items():
910911
m.clear_values()
911-
# TODO: ditch metrics no longer found in document
912912

913913
# bump the fetch call counter for this source, and for the total (cluster 0)
914914
self.pmda.stats_fetch_calls[self.cluster] += 1
@@ -948,6 +948,24 @@ class Source(object):
948948
# NB: the requests package automatically enables http keep-alive and compression
949949
self.document = r.text
950950

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+
951969
# update fetch time counter stats, in ms
952970
incr = int(1000 * (time.time() - fetch_time))
953971
self.pmda.stats_fetch_time[self.cluster] += incr
@@ -1040,6 +1058,10 @@ class OpenMetricsPMDA(PMDA):
10401058
self.all_metrics = {}
10411059
# keep track of removed metrics, in case of re-addition
10421060
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 = []
10431065

10441066
# compiled regex cache
10451067
self.regex_cache = {}
@@ -1147,12 +1169,40 @@ class OpenMetricsPMDA(PMDA):
11471169
if mtime is None or m > mtime:
11481170
mtime = m
11491171
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)
11501181
for d in subdirs:
11511182
m, _ = self.traverse(os.path.join(path, d), mtime)
11521183
if mtime is None or m > mtime:
11531184
mtime = m
11541185
return mtime, ret
11551186

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+
11561206
def rescan_confdir(self):
11571207
'''Scan the configuration directories for any new .url files
11581208
or scripts. Ensure there is a Source registered in the
@@ -1163,6 +1213,10 @@ class OpenMetricsPMDA(PMDA):
11631213
invoked frequently by src/python/pmda.c.
11641214
'''
11651215

1216+
# re-initialize variables to keep track of modified files before new traversal
1217+
self.modified_files = []
1218+
m_files = []
1219+
11661220
traverse_time = time.time()
11671221
dir_mtime, conf_filelist = self.traverse(self.config_dir, self.config_dir_mtime)
11681222
traverse_time = time.time() - traverse_time
@@ -1183,6 +1237,11 @@ class OpenMetricsPMDA(PMDA):
11831237
name = file_split[0].replace(self.config_dir + "/", "").replace("/", ".")
11841238
nicknames.append(name)
11851239

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+
11861245
# check if config change adds a previously removed source
11871246
for key in self.removed_metrics:
11881247
split_name = key.split(".")
@@ -1197,6 +1256,9 @@ class OpenMetricsPMDA(PMDA):
11971256
try:
11981257
remove_name = key
11991258
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)
12001262
self.remove_metric(remove_name, remove_obj)
12011263
self.removed_metrics[remove_name] = remove_obj
12021264
self.debug("removed metric name: %s" % remove_name) if self.dbg else None
@@ -1236,13 +1298,16 @@ class OpenMetricsPMDA(PMDA):
12361298
# this source is already known
12371299
self.assert_source_invariants(name=name)
12381300
s = self.source_by_name[name]
1301+
self.debug("m files : %s" % m_files) if self.dbg else None
12391302
cluster_for_refresh = []
12401303
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:
12421305
for key,value in self.source_by_cluster.items():
12431306
if value == s:
12441307
cluster_for_refresh.append(key)
12451308
cluster_for_refresh_names.append(name)
1309+
if self.controls[key] == 0:
1310+
self.initialize_controls(key)
12461311
self.debug("refreshing cluster list: %s" % cluster_for_refresh_names) if self.dbg else None
12471312
self.refresh_some_clusters_for_fetch(cluster_for_refresh)
12481313
else:
@@ -1253,12 +1318,7 @@ class OpenMetricsPMDA(PMDA):
12531318
self.source_by_name[source.name] = source
12541319
self.source_by_cluster[source.cluster] = source
12551320

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)
12621322

12631323
save_cluster_table = True
12641324
self.log("Found source %s cluster %d" % (name, cluster))

0 commit comments

Comments
 (0)