logging.sh 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #!/bin/bash
  2. # Copyright 2014 The Kubernetes Authors.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. # Controls verbosity of the script output and logging.
  16. KUBE_VERBOSE="${KUBE_VERBOSE:-5}"
  17. # Handler for when we exit automatically on an error.
  18. # Borrowed from https://gist.github.com/ahendrix/7030300
  19. kube::log::errexit() {
  20. local err="${PIPESTATUS[@]}"
  21. # If the shell we are in doesn't have errexit set (common in subshells) then
  22. # don't dump stacks.
  23. set +o | grep -qe "-o errexit" || return
  24. set +o xtrace
  25. local code="${1:-1}"
  26. kube::log::error_exit "'${BASH_COMMAND}' exited with status $err" "${1:-1}" 1
  27. }
  28. kube::log::install_errexit() {
  29. # trap ERR to provide an error handler whenever a command exits nonzero this
  30. # is a more verbose version of set -o errexit
  31. trap 'kube::log::errexit' ERR
  32. # setting errtrace allows our ERR trap handler to be propagated to functions,
  33. # expansions and subshells
  34. set -o errtrace
  35. }
  36. # Print out the stack trace
  37. #
  38. # Args:
  39. # $1 The number of stack frames to skip when printing.
  40. kube::log::stack() {
  41. local stack_skip=${1:-0}
  42. stack_skip=$((stack_skip + 1))
  43. if [[ ${#FUNCNAME[@]} -gt $stack_skip ]]; then
  44. echo "Call stack:" >&2
  45. local i
  46. for ((i=1 ; i <= ${#FUNCNAME[@]} - $stack_skip ; i++))
  47. do
  48. local frame_no=$((i - 1 + stack_skip))
  49. local source_file=${BASH_SOURCE[$frame_no]}
  50. local source_lineno=${BASH_LINENO[$((frame_no - 1))]}
  51. local funcname=${FUNCNAME[$frame_no]}
  52. echo " $i: ${source_file}:${source_lineno} ${funcname}(...)" >&2
  53. done
  54. fi
  55. }
  56. # Log an error and exit.
  57. # Args:
  58. # $1 Message to log with the error
  59. # $2 The error code to return
  60. # $3 The number of stack frames to skip when printing.
  61. kube::log::error_exit() {
  62. local message="${1:-}"
  63. local code="${2:-1}"
  64. local stack_skip="${3:-0}"
  65. stack_skip=$((stack_skip + 1))
  66. if [[ ${KUBE_VERBOSE} -ge 4 ]]; then
  67. local source_file=${BASH_SOURCE[$stack_skip]}
  68. local source_line=${BASH_LINENO[$((stack_skip - 1))]}
  69. echo "!!! Error in ${source_file}:${source_line}" >&2
  70. [[ -z ${1-} ]] || {
  71. echo " ${1}" >&2
  72. }
  73. kube::log::stack $stack_skip
  74. echo "Exiting with status ${code}" >&2
  75. fi
  76. exit "${code}"
  77. }
  78. # Log an error but keep going. Don't dump the stack or exit.
  79. kube::log::error() {
  80. timestamp=$(date +"[%m%d %H:%M:%S]")
  81. echo "!!! $timestamp ${1-}" >&2
  82. shift
  83. for message; do
  84. echo " $message" >&2
  85. done
  86. }
  87. # Print an usage message to stderr. The arguments are printed directly.
  88. kube::log::usage() {
  89. echo >&2
  90. local message
  91. for message; do
  92. echo "$message" >&2
  93. done
  94. echo >&2
  95. }
  96. kube::log::usage_from_stdin() {
  97. local messages=()
  98. while read -r line; do
  99. messages+=("$line")
  100. done
  101. kube::log::usage "${messages[@]}"
  102. }
  103. # Print out some info that isn't a top level status line
  104. kube::log::info() {
  105. local V="${V:-0}"
  106. if [[ $KUBE_VERBOSE < $V ]]; then
  107. return
  108. fi
  109. for message; do
  110. echo "$message"
  111. done
  112. }
  113. # Just like kube::log::info, but no \n, so you can make a progress bar
  114. kube::log::progress() {
  115. for message; do
  116. echo -e -n "$message"
  117. done
  118. }
  119. kube::log::info_from_stdin() {
  120. local messages=()
  121. while read -r line; do
  122. messages+=("$line")
  123. done
  124. kube::log::info "${messages[@]}"
  125. }
  126. # Print a status line. Formatted to show up in a stream of output.
  127. kube::log::status() {
  128. local V="${V:-0}"
  129. if [[ $KUBE_VERBOSE < $V ]]; then
  130. return
  131. fi
  132. timestamp=$(date +"[%m%d %H:%M:%S]")
  133. echo "+++ $timestamp $1"
  134. shift
  135. for message; do
  136. echo " $message"
  137. done
  138. }