diff options
Diffstat (limited to 'tools/warnstats.sh')
-rwxr-xr-x | tools/warnstats.sh | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/tools/warnstats.sh b/tools/warnstats.sh new file mode 100755 index 000000000..e38a734f1 --- /dev/null +++ b/tools/warnstats.sh @@ -0,0 +1,528 @@ +#!/bin/bash + +#set -x # uncomment for bash script debugging + +# ============================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END===================================================== + +### +### warnstats +### +### AUTHOR(S): +### Thomas Kulik, Deutsche Telekom AG, 2020 +### +### DESCRIPTION: +### warnstat helps to find the onap modules (projects) and rst-files which are +### responsible for the most warnings during the documentation build process. +### it requires a tox build logfile, parses it line by line, prints out some +### statistics and provides links to the local rst file, its html version, the +### related link to readthedocs and as well the doc8 test result for the rst. +### + +### +### CHANGELOG (LATEST ON TOP) +### +### 1.5.0 (2020-03-23) - doc8 test now executed for every rst file. result is +### provided in the output as "doc8_(nnnnn)" where nnnnn +### is the total number of accumulated doc8 errors. +### - improved readability of output +### 1.4.0 (2020-03-18) - the link to the local html and rst file is provided in +### the output. this may help to ease the debug process. +### use mouse-over/context menu functionality of bash to +### easily open files with your browser or rst editor. +### - improved handling for module names (in case they are +### no real onap projects/modules but directories which +### contain additional documentation in rst format). +### 1.3.1 (2020-03-10) - fixed minor typo in usage message +### 1.3.0 (2020-03-09) - initial release +### + +script_version="1.5.0 (2020-03-23)" +doc8_dir=$(pwd)/doc8_results +logfile=$1; +doc8_command="doc8 --verbose"; #add options if required +web_base_url="https://docs.onap.org/en/latest"; + +echo " "; +echo " warnstats version ${script_version}"; + +declare -A module_array +declare -A message_short_array +declare -A message_long_array +declare -A rstfile_array +declare -A rstfilepath_array +declare -A htmlfilepath_array +declare -A webpath_array +declare -A doc8_result_array + +### +### simple script argument handling +### + +# check if there is an argument at all +if [[ "$logfile" == "" ]] ; then + echo 'Usage: warnstats [tox-logfile]' + exit 1 +fi + +# check if argument is a file +if [ ! -f $logfile ] ; then + echo "Error: can't find tox-logfile \"$logfile\"" + exit 1 +fi + +# create and clean doc8 directory +if [ ! -d "$doc8_dir" ]; then + mkdir $doc8_dir; +else + rm ${doc8_dir}/*.txt 2>/dev/null; +fi + +# get local html build directory +html_build_dir=$(grep "Generated docs available in" $logfile); +html_build_dir=$(echo "$html_build_dir" | grep -oP " /.*/doc/docs/_build/html$"); +html_build_dir=$(echo "$html_build_dir" | sed -r 's:^ ::'); +echo " html build directory ..... $html_build_dir" +echo " web base url ............. $web_base_url"; +echo " doc8 command ............. $doc8_command"; +echo " doc8 results directory ... $doc8_dir"; +echo " tox logfile .............. $logfile"; + +# read in the tox build logfile - use only lines which contain a warning +readarray -t logfile_array < <(grep ": WARNING:" $logfile); + +# process filtered logfile line by line +for line in "${logfile_array[@]}" +do + + # count warning lines + (( counter++ )); + echo -n -e " lines processed .......... $counter (doc8 check may take a while ...)\r"; + + # + # extract path to local rst file + # + path_rst=$line; + #echo "DBUG line: $line" + # remove problematic text in line that causes regex to fail + path_rst=$(echo "$path_rst" | sed -r 's:, other instance in.*::'); + #echo "DBUG path_rst: $path_rst" + # grep the rst file path + path_rst=$(echo "$path_rst" | grep -oP "^/.*\.rst"); + #echo "DBUG path_rst: $path_rst" + if [[ "$path_rst" == "" ]] ; then + path_rst="path_to_rst_missing" + #echo "DBUG path_rst: $path_rst" + fi + # finally embed the full rst path in a message to use mouse-over/context menu of bash to open file + path_rst_link='\e]8;;file:'$path_rst'\arst\e]8;;\a'; + #echo -e "DBUG path_rst: "$path_rst; + + # + # extract path to the html version of the local rst file + # + path_html=$line; + #echo "DBUG line: $line" + # remove problematic text in line that causes regex to fail + path_html=$(echo "$path_html" | sed -r 's:, other instance in.*::'); + #echo "DBUG path_html: $path_html" + # grep the rst file path and modify it so we get the local html build path; grep a little bit more to be save + path_html=$(echo "$path_html" | grep -oP "(^|/)docs(/.*|)/[\w -]*\.rst"); + #echo "DBUG path_html: $path_html" + path_html=$(echo "$path_html" | sed -r 's:^/docs::'); + #echo "DBUG path_html: $path_html" + path_html=$(echo "$path_html" | sed -r 's:.rst:.html:'); + #echo "DBUG path_html: $path_html" + # create also the path to the web version + path_web_link='\e]8;;'${web_base_url}${path_html}'\aweb\e]8;;\a'; + #echo "DBUG path_web_link: $path_web_link" + # finally embed the full html path in a message to use mouse-over/context menu of bash to open file + path_html_link='\e]8;;file:'${html_build_dir}${path_html}'\ahtml\e]8;;\a'; + #echo -e "DBUG path_html_link: "$path_html_link; + + # extract module name from line (remove all text before module name; then cut out module name) + module=$(echo "$line" | sed -r 's:(^.*/doc/docs/submodules/|^docs/submodules/|checking consistency... )::' | cut -f1 -d\/); + #echo "DBUG line: $line" + #echo "DBUG module: $module" + + # in case the extraction has not lead to a valid module name do some additional investigation + if [[ "$module" == "" ]] ; then + + if [[ $line =~ doc/docs/release ]] ; then + module="docs_release" + #echo "DBUG line: $line" + #echo "DBUG module: $module" + elif [[ $line =~ doc/docs/use-cases ]] ; then + module="docs_use-cases" + #echo "DBUG line: $line" + #echo "DBUG module: $module" + elif [[ $line =~ doc/docs/guides ]] ; then + module="docs_guides" + #echo "DBUG line: $line" + #echo "DBUG module: $module" + else + module="docs" + #echo "DBUG line: $line" + #echo "DBUG module: $module" + fi + + fi + #echo "DBUG line: $line"; + #echo "DBUG module: $module"; + + # get the maximum length of the variable entries to adjust table width later on + if [[ ${#module} -gt "$maxlength_module" ]]; then + maxlength_module=${#module}; + fi + #echo "DBUG maxlength_module=$maxlength_module"; + + # extract rst file name from line and do some formatting to use it later as an array name + #echo "DBUG line: $line"; + rstfile=$(echo "$line" | grep -oP "[\w -]*\.rst"); + rstfile=$(echo -e ${rstfile} | tr '[:blank:]' '_'); + #echo "DBUG rst-file: $rstfile"; + + # get the maximum length of the variable entries to adjust table width later on + if [[ ${#rstfile} -gt "$maxlength_rstfile" ]]; then + maxlength_rstfile=${#rstfile}; + fi + #echo "DBUG maxlength_rstfile=$maxlength_rstfile"; + + # count the number of warnings for the module/rstfile combination + (( rstfile_array[$module | $rstfile]++ )); + + # count the number of warnings for the single module + #echo "DBUG $module | $rstfile | $message"; + (( module_array[$module]++ )); + + # now we have all the information to fill the html/rst/web (file) path arrays + htmlfilepath_array[$module | $rstfile]=$path_html_link; + rstfilepath_array[$module | $rstfile]=$path_rst_link; + webpath_array[$module | $rstfile]=$path_web_link; + + # extract the warning message and do some formatting + #message=$(echo "$line" | sed -r 's:^/.+WARNING\:\ ::'); + message=$(echo "$line" | sed -r 's:^.+WARNING\:\ ::'); + message=$(echo -e ${message} | tr '[:blank:]' '_'); + message=$(echo -e ${message} | tr '/' '_'); + message=$(echo -e ${message} | tr '.' '_'); + + # remove all characters from message which may cause problems in the shell + message="$(echo -e "${message}" | sed -e 's/[^A-Za-z0-9_-]//g')"; + #echo "DBUG message=\"$message\"" + + # count the number of warnings for the single message (long version) + message_long="$(echo -e "${message}")"; + (( message_long_array[$message_long]++ )) + + # reduce length of message to group them more easily and then ... + # count the number of warnings for the single message (short version) + message_short="$(echo -e "${message}" | cut -c -16)"; + (( message_short_array[$message_short]++ )) + + # check rst files with doc8 and store results + doc8_result_path="${doc8_dir}/${module}-${rstfile}.txt"; + #echo "DBUG ---------------------------------------------" + #echo "DBUG doc8_result_path=\"$doc8_result_path\"" + # doc8 check only if result file does not exists yet AND if rst file is valid (exists) + if [[ ! -f "$doc8_result_path" && -f "$path_rst" ]] ; then + echo "FILE:$path_rst" >$doc8_result_path; + $doc8_command "$path_rst" >>$doc8_result_path; + total_acc_err=$(grep "Total accumulated errors = " $doc8_result_path); + #echo "DBUG total_acc_err=$total_acc_err"; + total_acc_err=$(echo $total_acc_err | sed 's:Total accumulated errors = ::'); + #echo "DBUG total_acc_err=$total_acc_err"; + total_acc_err=$(printf "%05d" $total_acc_err); + #echo "DBUG command:doc8 ${path_rst} >>${doc8_result_path}"; + #echo "DBUG total_acc_err=$total_acc_err"; + fi + doc8_result='\e]8;;file:'${doc8_result_path}'\adoc8_('$total_acc_err')\e]8;;\a'; + doc8_result_array[$module | $rstfile]=$doc8_result; + +done + +#format counter to have always x digits +counter=$(printf "%05d" $counter); +echo " "; +echo " $counter LINES WITH WARNING IN FILE '$logfile'"; + +echo " "; +echo "################################################################################"; +echo "~~~ MESSAGES LONG ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; +echo "################################################################################"; +echo " "; + +#print array content and append to temporary outfile +for i in "${!message_long_array[@]}" +do + m=$i; + n=${message_long_array[$i]}; + ((nc += n)) + #format counter to have always x digits + n=$(printf "%05d" $n); + echo " $n | $m" >>tempoutfile; +done + +#format counter to have always x digits +nc=$(printf "%05d" $nc); +echo " $nc WARNINGS IN TOTAL WITH ${#message_long_array[@]} UNIQUE MESSAGES" >>tempoutfile; + +#print a sorted version of the temporary outfile +sort -br tempoutfile + +# clean up +rm tempoutfile +nc=0 + +echo " "; +echo "################################################################################"; +echo "~~~ MESSAGES SHORTENED (FOR SIMPLE GROUPING) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; +echo "################################################################################"; +echo " "; + +#print array content and append to temporary outfile +for i in "${!message_short_array[@]}" +do + m=$i; + n=${message_short_array[$i]}; + ((nc += n)) + #format counter to have always x digits + n=$(printf "%05d" $n); + echo " $n | $m" >>tempoutfile; +done + +#format counter to have always x digits +nc=$(printf "%05d" $nc); +echo " $nc WARNINGS IN TOTAL WITH ${#message_short_array[@]} UNIQUE MESSAGES" >>tempoutfile; + +#print a sorted version of the temporary outfile +sort -br tempoutfile + +# clean up +rm tempoutfile +nc=0 + +echo " "; +echo "################################################################################"; +echo "~~~ MODULES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; +echo "################################################################################"; +echo " "; + +#create temporary outfile +for i in "${!module_array[@]}" +do + m=$i; + n=${module_array[$i]}; + ((nc += n)) + n=$(printf "%05d" $n); + echo " $n | $m" >>tempoutfile; +done + +#format counter to have always x digits +nc=$(printf "%05d" $nc); +echo " $nc WARNINGS IN TOTAL IN ${#module_array[@]} MODULES" >>tempoutfile; + +#print a sorted version of the temporary outfile +sort -br tempoutfile +rm tempoutfile +nc=0 + +echo " "; +echo "################################################################################"; +echo "~~~ MODULES WITH RSTFILES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; +echo "################################################################################"; +echo " "; + +#print array content and append to temporary outfile +for i in "${!rstfile_array[@]}" +do + m=$i; + n=${rstfile_array[$i]}; + p=${htmlfilepath_array[$i]} + r=${rstfilepath_array[$i]} + w=${webpath_array[$i]} + d=${doc8_result_array[$i]}; + #echo "DBUG -------------------------------" + #echo "DBUG i=$i" + #echo "DBUG m=$m" + #echo "DBUG n=$n" + #echo "DBUG p=$p" + #echo -e "DBUG p=$p" + ((nc += n)) + #format counter to have always x digits + n=$(printf "%05d" $n); + + # extend module name to the max for better readability + tmp_mod=$(echo "$m" | sed -r 's: \|.+$::'); + #echo "DBUG tmp_mod=$tmp_mod" + len_tmp_mod=${#tmp_mod} + to_add="$(($maxlength_module-$len_tmp_mod))" + #echo "DBUG to_add=$to_add" + while [ $to_add -gt 0 ]; do + tmp_mod="${tmp_mod} "; + ((to_add--)); + #echo "DBUG to_add=$to_add" + #echo "DBUG tmp_mod=\"$tmp_mod\"" + done + + # extend rst name to the max for better readability + tmp_rst=$(echo "$m" | sed -r 's:^.+ \| ::'); + #echo "DBUG tmp_rst=$tmp_rst" + len_tmp_rst=${#tmp_rst} + to_add="$(($maxlength_rstfile-$len_tmp_rst))" + #echo "DBUG to_add=$to_add" + while [ $to_add -gt 0 ]; do + tmp_rst="${tmp_rst} "; + ((to_add--)); + #echo "DBUG to_add=$to_add" + #echo "DBUG tmp_rst=\"$tmp_rst\"" + done + + # recombine module and rst names + m="${tmp_mod} | ${tmp_rst}"; + + # print out to temp file + echo -e " $m | $r $p $w $d | $n" >>tempoutfile; +done + +#format counter to have always x digits +nc=$(printf "%05d" $nc); +#in case the name (e.g) index.rst is used multiple times in the same module warnings are combined +echo " $nc WARNINGS IN TOTAL IN APPROX. ${#rstfile_array[@]} RST FILES" >>tempoutfile; + +#print a sorted version of the temporary outfile +sort -b tempoutfile + +# clean up +rm tempoutfile +nc=0 + +echo " "; +echo "################################################################################"; +echo "~~~ RSTFILES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; +echo "################################################################################"; +echo " "; + +#print array content and append to temporary outfile +for i in "${!rstfile_array[@]}" +do + m=$i; + n=${rstfile_array[$i]}; + p=${htmlfilepath_array[$i]} + r=${rstfilepath_array[$i]} + w=${webpath_array[$i]} + d=${doc8_result_array[$i]}; + ((nc += n)) + #format counter to have always x digits + n=$(printf "%05d" $n); + + # extend module name to the max for better readability + tmp_mod=$(echo "$m" | sed -r 's: \|.+$::'); + #echo "DBUG tmp_mod=$tmp_mod" + len_tmp_mod=${#tmp_mod} + to_add="$(($maxlength_module-$len_tmp_mod))" + #echo "DBUG to_add=$to_add" + while [ $to_add -gt 0 ]; do + tmp_mod="${tmp_mod} "; + ((to_add--)); + #echo "DBUG to_add=$to_add" + #echo "DBUG tmp_mod=\"$tmp_mod\"" + done + + # extend rst name to the max for better readability + tmp_rst=$(echo "$m" | sed -r 's:^.+ \| ::'); + #echo "DBUG tmp_rst=$tmp_rst" + len_tmp_rst=${#tmp_rst} + to_add="$(($maxlength_rstfile-$len_tmp_rst))" + #echo "DBUG to_add=$to_add" + while [ $to_add -gt 0 ]; do + tmp_rst="${tmp_rst} "; + ((to_add--)); + #echo "DBUG to_add=$to_add" + #echo "DBUG tmp_rst=\"$tmp_rst\"" + done + + # recombine module and rst names + m="${tmp_mod} | ${tmp_rst}"; + + # print out to temp file + echo -e " $n | $m | $r $p $w $d" >>tempoutfile; +done + +#format counter to have always x digits +nc=$(printf "%05d" $nc); +#in case the name (e.g) index.rst is used multiple times in the same module warnings are combined +echo " $nc WARNINGS IN TOTAL IN APPROX. ${#rstfile_array[@]} RST FILES" >>tempoutfile; + +#print a sorted version of the temporary outfile +sort -br tempoutfile + +# clean up +rm tempoutfile +nc=0 + +echo " "; +exit + +### +### backup code for future extensions +### + +# +# Block_quote_ends_without_a_blank_line_unexpected_unindent +# Bullet_list_ends_without_a_blank_line_unexpected_unindent +# Citation_[\w-]_is_not_referenced +# Citation_unit_test_is_not_referenced +# Content_block_expected_for_the_code_directive_none_found +# Content_block_expected_for_the_container_directive_none_found +# Could_not_lex_literal_block_as_bash__Highlighting_skipped +# Could_not_lex_literal_block_as_console__Highlighting_skipped +# Could_not_lex_literal_block_as_guess__Highlighting_skipped +# Could_not_lex_literal_block_as_json__Highlighting_skipped +# Could_not_lex_literal_block_as_yaml__Highlighting_skipped +# Definition_list_ends_without_a_blank_line_unexpected_unindent +# document_isnt_included_in_any_toctree +# download_file_not_readable +# Duplicate_explicit_target_name +# duplicate_label +# Enumerated_list_ends_without_a_blank_line_unexpected_unindent +# Error_in_code_directive +# Error_in_code-block_directive +# Error_in_image_directive +# Explicit_markup_ends_without_a_blank_line_unexpected_unindent +# Field_list_ends_without_a_blank_line_unexpected_unindent +# Footnote_[0-9.*]_is_not_referenced +# image_file_not_readable +# Include_file +# Inconsistent_literal_block_quoting +# Inline_emphasis_start-string_without_end-string +# Inline_interpreted_text_or_phrase_reference_start-string_without_end-string +# Inline_strong_start-string_without_end-string +# Inline_substitution_reference_start-string_without_end-string +# Literal_block_ends_without_a_blank_line_unexpected_unindent +# Literal_block_expected_none_found +# Malformed_table +# Pygments_lexer_name_asn_is_not_known +# Title_level_inconsistent +# Title_overline__underline_mismatch +# Title_overline_too_short +# Title_underline_too_short +# toctree_contains_reference_to_nonexisting_document +# Too_many_autonumbered_footnote_references_only_0_corresponding_footnotes_available +# undecodable_source_characters_replacing_with +# undefined_label +# Unexpected_indentation +# Unknown_directive_type_clode-block +# unknown_document +# Unknown_target_name |