blob: c52ad09991371303116ab23c8ca8041f1530d363 [file] [log] [blame]
#!/bin/bash
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# A helper to query build_log data contained in internal analysis_service
# events.
# Make sure we have prod access so we don't fail without getting any work done.
prodcertstatus 1>/dev/null 2>/dev/null || prodaccess
when="last3days"
count_data=""
limit=30
field_limit=80
verbose=0
only_stdout=0
case_insensitive=1
string_data_array=()
not_string_data_array=()
print_usage() {
cat <<HELP_USAGE
Usage: $0 -c|--count <search_string>
OR -s|--string <search_string>|-ns <search_string>
[-w|-when] <when_string>
[-l|--limit] <limit_string> [--field_limit <field_limit>]
[--case_sensitive)]
[-v|--verbose] [--usage|-u|--help|-h]
If -c is specified, count the occurrences of the search string.
If -s is specified, display the matching occurences based on the other
arguments (-l, --field_limit, etc).
Multiple -s arguments can be supplied, which allows an AND query,
so that
query_build_logs -s "String1" -s "String2" -s "String3"
returns run where the output contains all 3 search strings.
The -ns species results that do NOT match. An -ns args can
be used alone but is typically paired with a -s arg to eliminate some
matches, such as
query_build_logs -s "String1" -s "String2" -ns "string3"
to find logs that contain String1 and String2 but not String3
search_string : What to search for in build_cmd logs.
when_string : Which dremel table, such as last7days, last1days, etc.
(default=last3days)
limit_string : Limits numbers of rows to this value (default=30).
field_limit : Show <field_limit> characters of stdout starting with
<search_string> (default=80).
only_stdout : Show only stdout and date, not buildId, stepName, etc.
case_sensitive: Match (or for 'ns', don't match) case sensitive.
Note that case-insensitive is the default.
verbose : Show dremel query before executing it.
HELP_USAGE
exit 0
}
while (( "$#" )); do
case "$1" in
-s|--string)
string_data_array=( "${string_data_array[@]}" "$2" )
shift 2
;;
-ns|--not_string)
not_string_data_array=( "${not_string_data_array[@]}" "$2" )
shift 2
;;
-c|--count)
count_data=$2
shift 2
;;
-w|--when)
when=$2
shift 2
;;
-l|--limit)
limit=$2
shift 2
;;
--field_limit)
field_limit=$2
shift 2
;;
--only_stdout)
only_stdout=1
shift 1
;;
--case_sensitive)
case_insensitive=0
shift 1
;;
-v|--verbose)
verbose=1
shift
;;
--usage|-u|--help|-h)
print_usage
shift
;;
*)
echo "Unknown arg: $1"
print_usage
shift
esac
done
string_data_arraylen=${#string_data_array[@]}
not_string_data_arraylen=${#not_string_data_array[@]}
if [[ $string_data_arraylen -ne 0 ]] && [[ ! -z ${count_data} ]]; then
echo "Specifying both -s and -c is not allowed."
print_usage
fi
source_data="stdout"
if [[ ${case_insensitive} -eq 1 ]]; then
source_data="LOWER(stdout)"
fi
# If a count was requested, build and execute the query. This code path is
# separate because it is much simpler than search queries.
if [[ ! -z ${count_data} ]]; then
# Note that we use count(stdout) regardless of case-sensitivity. The WHERE
# part of the query will use ${source_data} to handle case-sensitivity.
query="SELECT count(stdout) AS Count FROM
chromeos_ci_eng.analysis_event_log.${when} WHERE ${source_data} LIKE "
if [[ ${case_insensitive} -eq 1 ]]; then
query="${query} LOWER(\"%${count_data}%\");"
else
query="${query} \"%${count_data}%\";"
fi
if [ "${verbose}" -eq 1 ]; then
echo "QUERY: ${query}"
echo "Executing..."
fi
echo "${query}" | dremel --min_completion_ratio 1
exit 0
fi
if [[ $string_data_arraylen -eq 0 && $not_string_data_arraylen -eq 0 ]]; then
echo "No search string specified."
echo " -s|--string <search_string> or -ns <search_string> is required."
print_usage
fi
select_fields=""
for (( index=0; index < $string_data_arraylen; index++ ))
do
string_data=${string_data_array[$index]}
# Field_limit is always set (even w/o cmd line arg), so set select_field
# based on array and field_limit.
select_field="SUBSTR(${source_data}, STRPOS(${source_data},"
select_field="${select_field} \"${string_data}\"),"
select_field="${select_field} ${field_limit}) AS Stdout$index,"
select_fields="$select_fields $select_field"
done
if [ "${only_stdout}" -eq 1 ]; then
query="SELECT ${select_fields}
DATETIME(TIMESTAMP_SECONDS(request_time.seconds)) AS DateTime"
else
query="SELECT ${select_fields}
CONCAT('https://ci.chromium.org/b/', CAST(build_id AS STRING)) as BuildId,step_name,
DATETIME(TIMESTAMP_SECONDS(request_time.seconds)) AS DateTime"
fi
query="$query FROM chromeos_ci_eng.analysis_event_log.${when}"
for (( index=0; index < $string_data_arraylen; index++ ))
do
string_data=${string_data_array[$index]}
if [[ $index -eq 0 ]]; then
query="$query WHERE ${source_data}"
else
query="$query AND ${source_data}"
fi
if [[ ${case_insensitive} -eq 1 ]]; then
query="$query LIKE LOWER(\"%${string_data}%\")"
else
query="$query LIKE \"%${string_data}%\""
fi
done
for (( index=0; index < $not_string_data_arraylen; index++ ))
do
not_string_data=${not_string_data_array[$index]}
if [[ $index -eq 0 && $string_data_arraylen -eq 0 ]]; then
query="$query WHERE ${source_data}"
else
query="$query AND ${source_data}"
fi
if [[ ${case_insensitive} -eq 1 ]]; then
query="${query} NOT LIKE LOWER(\"%${not_string_data}%\")"
else
query="${query} NOT LIKE \"%${not_string_data}%\""
fi
done
query="$query ORDER BY DateTime DESC LIMIT ${limit};"
if [ "${verbose}" -eq 1 ]; then
echo "QUERY: ${query}"
echo "Executing..."
fi
echo "${query}" | dremel --min_completion_ratio 1