小草林(田梓萱)
90db12dfc0
Some checks failed
Lock closed issues/PRs / lock (push) Has been cancelled
Test / Sentry self-hosted end-to-end tests (push) Has been cancelled
Test / unit tests (push) Has been cancelled
Test / Sentry upgrade test (push) Has been cancelled
Test / integration test v2.19.0 - customizations disabled (push) Has been cancelled
Test / integration test v2.19.0 - customizations enabled (push) Has been cancelled
Test / integration test v2.26.0 - customizations disabled (push) Has been cancelled
Test / integration test v2.26.0 - customizations enabled (push) Has been cancelled
Signed-off-by: 小草林(田梓萱) <xcl@xuegao-tzx.top>
236 lines
7.9 KiB
Bash
236 lines
7.9 KiB
Bash
echo "${_group}Setting up error handling ..."
|
|
|
|
if [ -z "${SENTRY_DSN:-}" ]; then
|
|
export SENTRY_DSN='https://19555c489ded4769978daae92f2346ca@self-hosted.getsentry.net/3'
|
|
fi
|
|
|
|
$dbuild -t sentry-self-hosted-jq-local --platform="$DOCKER_PLATFORM" jq
|
|
|
|
jq="docker run --rm -i sentry-self-hosted-jq-local"
|
|
sentry_cli="docker run --rm -v /tmp:/work -e SENTRY_DSN=$SENTRY_DSN getsentry/sentry-cli"
|
|
|
|
send_envelope() {
|
|
# Send envelope
|
|
$sentry_cli send-envelope "$envelope_file"
|
|
}
|
|
|
|
generate_breadcrumb_json() {
|
|
cat $log_file | $jq -R -c 'split("\n") | {"message": (.[0]//""), "category": "log", "level": "info"}'
|
|
}
|
|
|
|
send_event() {
|
|
# Use traceback hash as the UUID since it is 32 characters long
|
|
local cmd_exit=$1
|
|
local error_msg=$2
|
|
local traceback=$3
|
|
local traceback_json=$4
|
|
local breadcrumbs=$5
|
|
local fingerprint_value=$(
|
|
echo -n "$cmd_exit $error_msg $traceback" |
|
|
docker run -i --rm busybox md5sum |
|
|
cut -d' ' -f1
|
|
)
|
|
local envelope_file="sentry-envelope-${fingerprint_value}"
|
|
local envelope_file_path="/tmp/$envelope_file"
|
|
# If the envelope file exists, we've already sent it
|
|
if [[ -f $envelope_file_path ]]; then
|
|
echo "Looks like you've already sent this error to us, we're on it :)"
|
|
return
|
|
fi
|
|
# If we haven't sent the envelope file, make it and send to Sentry
|
|
# The format is documented at https://develop.sentry.dev/sdk/envelopes/
|
|
# Grab length of log file, needed for the envelope header to send an attachment
|
|
local file_length=$(wc -c <$log_file | awk '{print $1}')
|
|
|
|
# Add header for initial envelope information
|
|
$jq -n -c --arg event_id "$fingerprint_value" \
|
|
--arg dsn "$SENTRY_DSN" \
|
|
'$ARGS.named' >"$envelope_file_path"
|
|
# Add header to specify the event type of envelope to be sent
|
|
echo '{"type":"event"}' >>"$envelope_file_path"
|
|
|
|
# Next we construct the meat of the event payload, which we build up
|
|
# inside out using jq
|
|
# See https://develop.sentry.dev/sdk/event-payloads/
|
|
# for details about the event payload
|
|
|
|
# Then we need the exception payload
|
|
# https://develop.sentry.dev/sdk/event-payloads/exception/
|
|
# but first we need to make the stacktrace which goes in the exception payload
|
|
frames=$(echo "$traceback_json" | $jq -s -c)
|
|
stacktrace=$($jq -n -c --argjson frames "$frames" '$ARGS.named')
|
|
exception=$(
|
|
$jq -n -c --arg "type" Error \
|
|
--arg value "$error_msg" \
|
|
--argjson stacktrace "$stacktrace" \
|
|
'$ARGS.named'
|
|
)
|
|
|
|
# It'd be a bit cleaner in the Sentry UI if we passed the inputs to
|
|
# fingerprint_value hash rather than the hash itself (I believe the ultimate
|
|
# hash ends up simply being a hash of our hash), but we want the hash locally
|
|
# so that we can avoid resending the same event (design decision to avoid
|
|
# spam in the system). It was also futzy to figure out how to get the
|
|
# traceback in there properly. Meh.
|
|
event_body=$(
|
|
$jq -n -c --arg level error \
|
|
--argjson exception "{\"values\":[$exception]}" \
|
|
--argjson breadcrumbs "{\"values\": $breadcrumbs}" \
|
|
--argjson fingerprint "[\"$fingerprint_value\"]" \
|
|
'$ARGS.named'
|
|
)
|
|
echo "$event_body" >>$envelope_file_path
|
|
# Add attachment to the event
|
|
attachment=$(
|
|
$jq -n -c --arg "type" attachment \
|
|
--arg length "$file_length" \
|
|
--arg content_type "text/plain" \
|
|
--arg filename install_log.txt \
|
|
'{"type": $type,"length": $length|tonumber,"content_type": $content_type,"filename": $filename}'
|
|
)
|
|
echo "$attachment" >>$envelope_file_path
|
|
cat $log_file >>$envelope_file_path
|
|
# Send envelope
|
|
send_envelope $envelope_file
|
|
}
|
|
|
|
if [[ -z "${REPORT_SELF_HOSTED_ISSUES:-}" ]]; then
|
|
echo
|
|
echo "Hey, so ... we would love to automatically find out about issues with your"
|
|
echo "Sentry instance so that we can improve the product. Turns out there is an app"
|
|
echo "for that, called Sentry. Would you be willing to let us automatically send data"
|
|
echo "about your instance upstream to Sentry for development and debugging purposes?"
|
|
echo
|
|
echo " y / yes / 1"
|
|
echo " n / no / 0"
|
|
echo
|
|
echo "(Btw, we send this to our own self-hosted Sentry instance, not to Sentry SaaS,"
|
|
echo "so that we can be in this together.)"
|
|
echo
|
|
echo "Here's the info we may collect:"
|
|
echo
|
|
echo " - OS username"
|
|
echo " - IP address"
|
|
echo " - install log"
|
|
echo " - runtime errors"
|
|
echo " - performance data"
|
|
echo
|
|
echo "Thirty (30) day retention. No marketing. Privacy policy at sentry.io/privacy."
|
|
echo
|
|
|
|
yn=""
|
|
until [ ! -z "$yn" ]; do
|
|
read -p "y or n? " yn
|
|
case $yn in
|
|
y | yes | 1)
|
|
export REPORT_SELF_HOSTED_ISSUES=1
|
|
echo
|
|
echo -n "Thank you."
|
|
;;
|
|
n | no | 0)
|
|
export REPORT_SELF_HOSTED_ISSUES=0
|
|
echo
|
|
echo -n "Understood."
|
|
;;
|
|
*) yn="" ;;
|
|
esac
|
|
done
|
|
|
|
echo " To avoid this prompt in the future, use one of these flags:"
|
|
echo
|
|
echo " --report-self-hosted-issues"
|
|
echo " --no-report-self-hosted-issues"
|
|
echo
|
|
echo "or set the REPORT_SELF_HOSTED_ISSUES environment variable:"
|
|
echo
|
|
echo " REPORT_SELF_HOSTED_ISSUES=1 to send data"
|
|
echo " REPORT_SELF_HOSTED_ISSUES=0 to not send data"
|
|
echo
|
|
sleep 5
|
|
fi
|
|
|
|
# Make sure we can use sentry-cli if we need it.
|
|
if [ "$REPORT_SELF_HOSTED_ISSUES" == 1 ]; then
|
|
if ! docker pull getsentry/sentry-cli:latest; then
|
|
echo "Failed to pull sentry-cli, won't report to Sentry after all."
|
|
export REPORT_SELF_HOSTED_ISSUES=0
|
|
fi
|
|
fi
|
|
|
|
# Courtesy of https://stackoverflow.com/a/2183063/90297
|
|
trap_with_arg() {
|
|
func="$1"
|
|
shift
|
|
for sig; do
|
|
trap "$func $sig" "$sig"
|
|
done
|
|
}
|
|
|
|
DID_CLEAN_UP=0
|
|
# the cleanup function will be the exit point
|
|
cleanup() {
|
|
local retcode=$?
|
|
local cmd="${BASH_COMMAND}"
|
|
if [[ "$DID_CLEAN_UP" -eq 1 ]]; then
|
|
return 0
|
|
fi
|
|
DID_CLEAN_UP=1
|
|
if [[ "$1" != "EXIT" ]]; then
|
|
set +o xtrace
|
|
# Save the error message that comes from the last line of the log file
|
|
error_msg=$(tail -n 1 "$log_file")
|
|
# Create the breadcrumb payload now before stacktrace is printed
|
|
# https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/
|
|
# Use sed to remove the last line, that is reported through the error message
|
|
breadcrumbs=$(generate_breadcrumb_json | sed '$d' | $jq -s -c)
|
|
printf -v err '%s' "Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}."
|
|
printf -v cmd_exit '%s' "'$cmd' exited with status $retcode"
|
|
printf '%s\n%s\n' "$err" "$cmd_exit"
|
|
local stack_depth=${#FUNCNAME[@]}
|
|
local traceback=""
|
|
local traceback_json=""
|
|
if [ $stack_depth -gt 2 ]; then
|
|
for ((i = $(($stack_depth - 1)), j = 1; i > 0; i--, j++)); do
|
|
local indent="$(yes a | head -$j | tr -d '\n')"
|
|
local src=${BASH_SOURCE[$i]}
|
|
local lineno=${BASH_LINENO[$i - 1]}
|
|
local funcname=${FUNCNAME[$i]}
|
|
JSON=$(
|
|
$jq -n -c --arg filename "$src" \
|
|
--arg "function" "$funcname" \
|
|
--arg lineno "$lineno" \
|
|
'{"filename": $filename, "function": $function, "lineno": $lineno|tonumber}'
|
|
)
|
|
# If we're in the stacktrace of the file we failed on, we can add a context line with the command run that failed
|
|
if [[ $i -eq 1 ]]; then
|
|
JSON=$(
|
|
$jq -n -c --arg cmd "$cmd" \
|
|
--argjson json "$JSON" \
|
|
'$json + {"context_line": $cmd}'
|
|
)
|
|
fi
|
|
printf -v traceback_json '%s\n' "$traceback_json$JSON"
|
|
printf -v traceback '%s\n' "$traceback${indent//a/-}> $src:$funcname:$lineno"
|
|
done
|
|
fi
|
|
echo "$traceback"
|
|
|
|
# Only send event when report issues flag is set and if trap signal is not INT (ctrl+c)
|
|
if [[ "$REPORT_SELF_HOSTED_ISSUES" == 1 && "$1" != "INT" ]]; then
|
|
send_event "$cmd_exit" "$error_msg" "$traceback" "$traceback_json" "$breadcrumbs"
|
|
fi
|
|
|
|
if [[ -n "$MINIMIZE_DOWNTIME" ]]; then
|
|
echo "*NOT* cleaning up, to clean your environment run \"docker compose stop\"."
|
|
else
|
|
echo "Cleaning up..."
|
|
fi
|
|
fi
|
|
|
|
if [[ -z "$MINIMIZE_DOWNTIME" ]]; then
|
|
$dc stop -t $STOP_TIMEOUT &>/dev/null
|
|
fi
|
|
}
|
|
|
|
echo "${_endgroup}"
|