#!/bin/bash
# CCacheMunin -- plugin to show CCache statistics in Munin
# (C) 2016 Stephane Charette <stephanecharette@gmail.com>
# $Id: ccache-counters_ 1703 2016-03-15 06:49:39Z stephane $
#
# Use "ccache --show-stats" to graph information on how ccache is performing.
#
# Munin magic markers for automated installation
# - http://munin-monitoring.org/wiki/HowToWritePlugins
# - http://guide.munin-monitoring.org/en/latest/architecture/syntax.html
# - http://munin-monitoring.org/wiki/PluginConcise#suggest
#%# family=auto
#%# capabilities=autoconf suggest


ARG0=$(basename $0)
STATEFILE_DIR=${MUNIN_PLUGSTATE:-/var/lib/munin-node/plugin-state/root}
STATEFILE_NAME=${STATEFILE_DIR}/${ARG0}


if [ "$1" = "autoconf" ]; then
	# tell Munin this plugin supports automatic configuration
	echo "yes"
	exit 0
fi


if [ "$1" = "suggest" ]; then

	# Find all of the user CCache caches.  This should give us a list that looks something like this:
	#		/home/bob/.ccache/ccache.conf
	#		/home/doug/.ccache/ccache.conf
	conf_files=$(find /home -maxdepth 3 -type f -name ccache.conf | sort)

	# ...or on older installations, we have TAG files such as
	#		/home/bob/.ccache/CACHEDIR.TAG
	tag_files=$(find /home -maxdepth 3 -type f -name CACHEDIR.TAG | sort)

	# From this list, we extract the unique usernames:
	names=$(echo "${conf_files}${tag_files}" | cut -d'/' -f3 | uniq)

	# Let munin know how many plugins are needed and the names of each one:
	echo "${names}"

	# When it comes time to gather the stats, we'll need to know all the users who we just identified have a
	# ccache.conf file, and the exact location of those conf files.  This is done by storing the exact location
	# of each file we found into a munin stats file.
	for name in ${names}
	do
		# The ccache_filename should be something like /home/bob/.ccache/ccache.conf:
		ccache_filename=$(echo "${conf_files}${tag_files}" | grep ${name} | head -1)

		# The statefile should be something like /var/lib/munin-node/plugin-state/root/ccache-munin_bob.
		# This will help us run ccache with the correct configuration when it comes time to gather stats.
		STATEFILE_NAME=${STATEFILE_DIR}/${ARG0}${name}
		echo "${ccache_filename}" > ${STATEFILE_NAME}
	done

	exit 0
fi


if [ "$1" = "config" ]; then
	# Munin auto-configuration (http://munin.readthedocs.org/en/latest/reference/plugin.html)
	cat <<-EOT
		graph_category ccache
		graph_args --base 1000 --lower-limit 0
		graph_scale yes
		graph_info CCache call statistics for ${ARG0}
		graph_title CCache Call Statistics for ${ARG0}
		graph_vlabel number of calls
		graph_order cache_hit_direct cache_hit_preprocessed cache_miss called_for_link compiler_produced_no_output compile_failed no_input_file
		graph_printf %.0lf
		EOT

	declare -A aa
	aa["cache_hit_direct"]="Number of ccache hits (direct)."
	aa["cache_hit_preprocessed"]="Number of ccache hits (preprocessed)."
	aa["cache_miss"]="Number of ccache miss."
	aa["called_for_link"]="Number of ccache calls for link."
	aa["cache_file_missing"]="Cache file missing."
	aa["compiler_produced_no_output"]="Compiler produced no output."
	aa["compile_failed"]="Compile failed."
	aa["no_input_file"]="No input file."

	for key in "${!aa[@]}"
	do
		echo "ccache_${key}.label ${key}"
		echo "ccache_${key}.draw LINE1"
		echo "ccache_${key}.info ${aa[$key]}"
		echo "ccache_${key}.type GAUGE"
	done

	exit 0
fi

# this next part is called every 5 minutes by Munin to generate the values stored in the rrd

# read the full name of the ccache configuration file from the munin state file
# this should give us something like:		/home/bob/.ccache/ccache.conf
ccache_filename=$(head -1 ${STATEFILE_NAME})
if [ -z "${ccache_filename}" ]; then
	exit 1
fi
if [ ! -r "${ccache_filename}" ]; then
	exit 1
fi

# get the actual statistics directly from ccache
#export CCACHE_CONFIGPATH=${ccache_conf_filename}
export CCACHE_DIR=$(dirname "${ccache_filename}")
ccache_output=$(ccache --show-stats)
if [ $? -ne 0 ]; then
	exit 1
fi

# extract the stats we want to output by applying a regular expression for each "key" to the ccache output
declare -A aa
aa["cache_hit_direct"]="cache hit \(direct\)"
aa["cache_hit_preprocessed"]="cache hit \(preprocessed\)"
aa["cache_miss"]="cache miss"
aa["called_for_link"]="called for link"
aa["cache_file_missing"]="cache file missing"
aa["compiler_produced_no_output"]="compiler produced no output"
aa["compile_failed"]="compile failed"
aa["no_input_file"]="no input file"
for key in "${!aa[@]}"
do
	regex="${aa[${key}]} +([0-9]+)"
	[[ ${ccache_output} =~ ${regex} ]]
	stats="${BASH_REMATCH[1]:-0}"
	echo "ccache_${key}.value ${stats}"
done

exit 0
