blob: d37e59396d32e560703fc35de85c4c3a7f01b054 [file] [log] [blame]
#!/bin/bash
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
### common methods for metrics collection
### this script assumes that vars.sh has already been sourced, since it
### depends on FUCHSIA_DIR being defined correctly.
declare -r GA_PROPERTY_ID="UA-127897021-6"
declare -r TRACK_ALL_ARGS="set,fidlcat"
declare -r TRACK_RESULTS="set,build"
declare -r DEBUG_LOG_CONFIG="/tmp/.fx_metrics_debugfile"
# To properly enable unit testing, METRICS_CONFIG is not read-only
METRICS_CONFIG="${FUCHSIA_DIR}/.fx-metrics-config"
_METRICS_DEBUG=0
_METRICS_DEBUG_LOG_FILE=""
_METRICS_USE_VALIDATION_SERVER=0
INIT_WARNING=$'Please opt in or out of fx metrics collection.\n'
INIT_WARNING+=$'You will receive this warning until an option is selected.\n'
INIT_WARNING+=$'To check what data we collect, run `fx metrics`\n'
INIT_WARNING+=$'To opt in or out, run `fx metrics <enable|disable>\n'
function metrics-read-config {
METRICS_UUID=""
METRICS_ENABLED=0
if [[ ! -f "${METRICS_CONFIG}" ]]; then
return 1
fi
source "${METRICS_CONFIG}"
if [[ $METRICS_ENABLED == 1 && -z "$METRICS_UUID" ]]; then
METRICS_ENABLED=0
return 1
fi
return 0
}
function metrics-write-config {
enabled=$1
if [[ "$enabled" -eq "1" ]]; then
uuid="$2"
fi
local -r tempfile="$(mktemp)"
# Exit trap to clean up temp file
trap "[[ -f \"${tempfile}\" ]] && rm -f \"${tempfile}\"" EXIT
{
echo "# Autogenerated config file for fx metrics. Run 'fx help metrics' for more information."
echo "METRICS_ENABLED=${enabled}"
echo "METRICS_UUID=\"${uuid}\""
} >> "${tempfile}"
# Only rewrite the config file if content has changed
if ! cmp --silent "${tempfile}" "${METRICS_CONFIG}" ; then
mv -f "${tempfile}" "${METRICS_CONFIG}"
fi
}
function metrics-read-and-validate {
local hide_init_warning=$1
if ! metrics-read-config; then
if [[ $hide_init_warning -ne 1 ]]; then
fx-warn "${INIT_WARNING}"
fi
return 1
fi
return 0
}
function metrics-set-debug-logfile {
debug_logfile="$1"
# make sure that either DEBUG_LOG_CONFIG is writable or it doesn't exist
# and its directory is writable
if [[ -w "${DEBUG_LOG_CONFIG}" || \
( ! -f "${DEBUG_LOG_CONFIG}" &&
-w "$(dirname "${DEBUG_LOG_CONFIG}")" ) ]]; then
echo "$debug_logfile" > "$DEBUG_LOG_CONFIG"
return 0
else
fx-warn "Cannot persist the metrics log filename to ${DEBUG_LOG_CONFIG}"
fx-warn "Ignoring debug logging of metrics collection"
fi
return 1
}
function metrics-get-debug-logfile {
if [[ $_METRICS_DEBUG == 1 ]]; then
echo "$_METRICS_DEBUG_LOG_FILE"
elif [[ -f "$DEBUG_LOG_CONFIG" ]]; then
head -1 "$DEBUG_LOG_CONFIG"
fi
}
function metrics-maybe-log {
local filename="$(metrics-get-debug-logfile)"
if [[ $filename ]]; then
if [[ ! -f "$filename" && -w $(dirname "$filename") ]]; then
touch "$filename"
fi
if [[ -w "$filename" ]]; then
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
shift # remove the function name from $@
echo "${TIMESTAMP}:" "$@" >> "$filename"
fi
fi
}
# Arguments:
# - the name of the fx subcommand
# - args of the subcommand
function track-command-execution {
subcommand="$1"
shift
args="$*"
local hide_init_warning=0
if [[ "$subcommand" == "metrics" ]]; then
hide_init_warning=1
fi
metrics-read-and-validate $hide_init_warning
if [[ $METRICS_ENABLED == 0 ]]; then
return 0
fi
# Only track arguments to the subcommands in $TRACK_ALL_ARGS
if [[ $TRACK_ALL_ARGS != *"$subcommand"* ]]; then
args=""
else
# Limit to the first 100 characters of arguments.
# The Analytics API supports up to 500 bytes, but it is likely that
# anything larger than 100 characters is an invalid execution and/or not
# what we want to track.
args=${args:0:100}
fi
user_agent="Fuchsia-fx $(_os_data)"
analytics_args=(
"v=1" \
"tid=${GA_PROPERTY_ID}" \
"an=fx" \
"cid=${METRICS_UUID}" \
"t=event" \
"ec=fx" \
"ea=${subcommand}"\
"el=${args}"\
)
curl_args=()
for a in "${analytics_args[@]}"; do
curl_args+=(--data-urlencode)
curl_args+=("$a")
done
local url_path="/collect"
local result=""
if [[ $_METRICS_DEBUG == 1 && $_METRICS_USE_VALIDATION_SERVER == 1 ]]; then
url_path="/debug/collect"
fi
if [[ $_METRICS_DEBUG == 1 && $_METRICS_USE_VALIDATION_SERVER == 1 ]]; then
# if testing and not using the validation server, always return 202
result="202"
elif [[ $_METRICS_DEBUG == 0 || $_METRICS_USE_VALIDATION_SERVER == 1 ]]; then
result=$(curl -s -o /dev/null -w "%{http_code}" "${curl_args[@]}" \
-H "User-Agent: $user_agent" \
"https://www.google-analytics.com/${url_path}")
fi
metrics-maybe-log event_hit "${analytics_args[@]}" "RESULT=$result"
return 0
}
# TODO(mangini): NOOP at this moment
# Arguments:
# - the name of the fx subcommand
# - args of the subcommand
# - time taken to complete (milliseconds)
# - exit status
function track-command-finished {
subcommand=$1
args=$2
timing=$3
exit_status=$4
if [[ $METRICS_ENABLED == 0 || $TRACK_RESULTS != *"$subcommand"* ]]; then
return 0
fi
}
function _os_data {
if command -v uname >/dev/null 2>&1 ; then
uname -rs
else
echo "Unknown"
fi
}
# Args:
# debug_log_file: string with a filename to save logs
# use_validation_hit_server:
# 0 do not hit any Analytics server (for local tests)
# 1 use the Analytics validation Hit server (for integration tests)
# config_file: string with a filename to save the config file. Defaults to
# METRICS_CONFIG
function _enable_testing {
_METRICS_DEBUG_LOG_FILE="$1"
_METRICS_USE_VALIDATION_SERVER=$2
if [[ $# -gt 2 ]]; then
METRICS_CONFIG="$3"
fi
_METRICS_DEBUG=1
METRICS_UUID="TEST"
}