Skip to content

Commit ad84dab

Browse files
authored
Use cvmfs_talk metrics prometheus when possible (#5)
The script that gathers the repo information scales not so well with the number of repositories mounted on a machine. On my machine with 21 repos mounted, it takes about 13s. This PR takes it down to 2.5s by doing the following * Use the new `cvmfs_talk metrics prometheus` command when possible. This gathers all of the metrics (except maxfd, which is awkward to get in talk) in one batched operation, removing the overhead of repeated calls to cvmfs_talk * Getting the list of mounted repos via cvmfs_config status is a surprisingly slow operation. I bypass this to just parse findmnt and assume all repos are mounted under their name in /cvmfs . There's an option to use the old behavior in case you use non-standard mountpoints. For a future release of cvmfs I think I'll fix this properly by exposing the repository name as a subtype. As a bonus, this pr includes a bugfix: the `expires` magic xattr can have the non-numeric value `never (fixed root catalog)` when mounting the repo with `CVMFS_ROOT_HASH` set. The script would throw an error in this case. I change the metric to show -1 if the catalog never expires (not sure if that's the idiomatic choice or 0 is preferred).
1 parent 5955554 commit ad84dab

File tree

1 file changed

+92
-6
lines changed

1 file changed

+92
-6
lines changed

cvmfs-client-prometheus.sh

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/bin/bash -u
22

33
HTTP_HEADER='FALSE'
4+
USE_NON_STANDARD_MOUNTPOINTS='FALSE'
45

56
TMPFILE=$(mktemp)
67

@@ -27,12 +28,15 @@ declare -A CVMFS_EXTENDED_ATTRIBUTE_GAUGES=(
2728

2829
#############################################################
2930
usage() {
30-
echo "Usage: $0 [-h|--help] [--http]" >&2
31+
echo "Usage: $0 [-h|--help] [--http] [--non-standard-mountpoints]" >&2
3132
echo '' >&2
3233
echo ' --http: add the HTTP protocol header to the output' >&2
34+
echo ' --non-standard-mountpoints: use cvmfs_config status instead of findmnt to discover repositories' >&2
3335
echo '' >&2
3436
echo 'NOTE: The user running this script must have read access' >&2
3537
echo ' to the CVMFS cache files!' >&2
38+
echo 'NOTE: By default, repositories are discovered using findmnt to find fuse filesystems' >&2
39+
echo ' mounted under /cvmfs. Use --non-standard-mountpoints for non-standard setups.' >&2
3640
exit 1
3741
}
3842

@@ -187,8 +191,12 @@ get_cvmfs_repo_metrics() {
187191
local cvmfs_repo_expires_min
188192
cvmfs_repo_expires_min=$(attr -g expires "${repomountpoint}" | tail -n +2)
189193
local cvmfs_repo_expires
190-
cvmfs_repo_expires=$((cvmfs_repo_expires_min * 60))
191-
generate_metric 'cvmfs_repo_expires_seconds' 'gauge' 'Shows the remaining life time of the mounted root file catalog in seconds.' "repo=\"${fqrn}\"" "${cvmfs_repo_expires}"
194+
if case $cvmfs_repo_expires_min in never*) ;; *) false;; esac; then
195+
cvmfs_repo_expires="-1"
196+
else
197+
cvmfs_repo_expires=$((cvmfs_repo_expires_min * 60))
198+
fi
199+
generate_metric 'cvmfs_repo_expires_seconds' 'gauge' 'Shows the remaining life time of the mounted root file catalog in seconds. -1 if never expires.' "repo=\"${fqrn}\"" "${cvmfs_repo_expires}"
192200

193201
local cvmfs_mount_ndownload
194202
cvmfs_mount_ndownload=$(attr -g ndownload "${repomountpoint}" | tail -n +2)
@@ -234,6 +242,63 @@ get_cvmfs_repo_metrics() {
234242
get_cvmfs_repo_proxy_metrics "${reponame}"
235243
}
236244

245+
get_cvmfs_repo_metrics_new() {
246+
local reponame
247+
reponame="$1"
248+
249+
local repomountpoint
250+
repomountpoint=$(mountpoint_for_cvmfs_repo "${reponame}")
251+
252+
# Use the new "metrics prometheus" command to get most metrics
253+
cvmfs_talk -i "${reponame}" "metrics prometheus" >> "${TMPFILE}"
254+
255+
# Still need to get maxfd via xattr since it was removed from metrics prometheus
256+
local maxfd_value
257+
maxfd_value=$(attr -g maxfd "${repomountpoint}" | tail -n +2)
258+
local fqrn
259+
fqrn=$(fqrn_for_cvmfs_repo "${reponame}")
260+
generate_metric 'cvmfs_maxfd' 'gauge' 'Shows the maximum number of file descriptors available to file system clients.' "repo=\"${fqrn}\"" "${maxfd_value}"
261+
}
262+
263+
get_repos_from_findmnt() {
264+
# Parse findmnt output to find fuse filesystems mounted under /cvmfs
265+
findmnt -o FSTYPE,TARGET --raw | \
266+
awk '$1 == "fuse" && $2 ~ /^\/cvmfs\// { gsub(/^\/cvmfs\//, "", $2); print $2 }' | \
267+
tr '\n' ' '
268+
}
269+
270+
get_repos_from_cvmfs_config() {
271+
cvmfs_config status | cut -d ' ' -f 1 | tr '\n' ' '
272+
}
273+
274+
check_cvmfs_version() {
275+
# Check if cvmfs2 version is >= 2.13.2
276+
local version_output
277+
version_output=$(cvmfs2 --version 2>/dev/null | head -n 1)
278+
if [ $? -ne 0 ]; then
279+
# cvmfs2 command not found, assume old version
280+
return 1
281+
fi
282+
283+
local version
284+
version=$(echo "$version_output" | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -n 1)
285+
if [ -z "$version" ]; then
286+
# Could not parse version, assume old version
287+
return 1
288+
fi
289+
290+
# Convert version to comparable format (e.g., 2.13.2 -> 20130200)
291+
local major minor patch
292+
major=$(echo "$version" | cut -d. -f1)
293+
minor=$(echo "$version" | cut -d. -f2)
294+
patch=$(echo "$version" | cut -d. -f3)
295+
296+
local version_num=$((major * 10000000 + minor * 100000 + patch * 1000))
297+
local min_version_num=$((2 * 10000000 + 13 * 100000 + 2 * 1000)) # 2.13.2
298+
299+
[ $version_num -ge $min_version_num ]
300+
}
301+
237302
#############################################################
238303
# List "uncommon" commands we expect
239304
for cmd in attr bc cvmfs_config cvmfs_talk grep; do
@@ -246,7 +311,7 @@ done
246311
#############################################################
247312
# setup args in the right order for making getopt evaluation
248313
# nice and easy. You'll need to read the manpages for more info
249-
args=$(getopt --options 'h' --longoptions 'help,http' -- "$@")
314+
args=$(getopt --options 'h' --longoptions 'help,http,non-standard-mountpoints' -- "$@")
250315
eval set -- "$args"
251316

252317
for arg in $@; do
@@ -261,6 +326,11 @@ for arg in $@; do
261326
HTTP_HEADER='TRUE'
262327
shift
263328
;;
329+
--non-standard-mountpoints)
330+
# Use cvmfs_config status to discover repositories
331+
USE_NON_STANDARD_MOUNTPOINTS='TRUE'
332+
shift
333+
;;
264334
-h | --help)
265335
# get help
266336
shift
@@ -271,8 +341,24 @@ done
271341

272342
CLOCK_TICK=$(getconf CLK_TCK)
273343

274-
for REPO in $(cvmfs_config status | cut -d ' ' -f 1); do
275-
get_cvmfs_repo_metrics "${REPO}"
344+
# Determine which method to use for getting metrics
345+
if check_cvmfs_version; then
346+
# CVMFS version >= 2.13.2, use new metrics prometheus command
347+
METRICS_FUNCTION="get_cvmfs_repo_metrics_new"
348+
else
349+
# Older CVMFS version, use legacy method
350+
METRICS_FUNCTION="get_cvmfs_repo_metrics"
351+
fi
352+
353+
# Get repository list based on selected method
354+
if [[ "${USE_NON_STANDARD_MOUNTPOINTS}" == 'TRUE' ]]; then
355+
REPO_LIST=$(get_repos_from_cvmfs_config)
356+
else
357+
REPO_LIST=$(get_repos_from_findmnt)
358+
fi
359+
360+
for REPO in $REPO_LIST; do
361+
$METRICS_FUNCTION "${REPO}"
276362
done
277363

278364
if [[ "${HTTP_HEADER}" == 'TRUE' ]]; then

0 commit comments

Comments
 (0)