Skip to content

Commit ebc3512

Browse files
committed
fix: improve error trace propagation for telemetry
- post_update_to_api: Attempts 2/3 now send medium_error (16KB truncated log) instead of short_error (generic description only). This is the primary fix — when attempt 1 fails (120KB payload too large/timeout), attempts 2/3 no longer discard all log data. - _send_abort_telemetry: Increased container fallback from 20 to 200 log lines (capped at 16KB). Added SILENT_LOGFILE as fallback source. Added exit code explanation header and error_category to payload. - get_error_text/get_full_log: Added SILENT_LOGFILE as last-resort fallback when INSTALL_LOG, combined log, and BUILD_LOG are all empty/missing.
1 parent 564a813 commit ebc3512

2 files changed

Lines changed: 57 additions & 7 deletions

File tree

misc/api.func

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,11 @@ get_error_text() {
393393
logfile="$BUILD_LOG"
394394
fi
395395

396+
# Try SILENT_LOGFILE as last resort (captures $STD command output)
397+
if [[ -z "$logfile" || ! -s "$logfile" ]] && [[ -n "${SILENT_LOGFILE:-}" && -s "${SILENT_LOGFILE}" ]]; then
398+
logfile="$SILENT_LOGFILE"
399+
fi
400+
396401
if [[ -n "$logfile" && -s "$logfile" ]]; then
397402
tail -n 20 "$logfile" 2>/dev/null | sed 's/\r$//' | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g'
398403
fi
@@ -438,6 +443,13 @@ get_full_log() {
438443
fi
439444
fi
440445

446+
# Fall back to SILENT_LOGFILE (captures $STD command output)
447+
if [[ -z "$logfile" || ! -s "$logfile" ]]; then
448+
if [[ -n "${SILENT_LOGFILE:-}" && -s "${SILENT_LOGFILE}" ]]; then
449+
logfile="$SILENT_LOGFILE"
450+
fi
451+
fi
452+
441453
if [[ -n "$logfile" && -s "$logfile" ]]; then
442454
# Strip ANSI codes, carriage returns, and anonymize IP addresses (GDPR)
443455
sed 's/\r$//' "$logfile" 2>/dev/null |
@@ -876,7 +888,7 @@ post_update_to_api() {
876888
esac
877889

878890
# For failed/unknown status, resolve exit code and error description
879-
local short_error=""
891+
local short_error="" medium_error=""
880892
if [[ "$pb_status" == "failed" ]] || [[ "$pb_status" == "unknown" ]]; then
881893
if [[ "$raw_exit_code" =~ ^[0-9]+$ ]]; then
882894
exit_code="$raw_exit_code"
@@ -896,6 +908,18 @@ post_update_to_api() {
896908
short_error=$(json_escape "$(explain_exit_code "$exit_code")")
897909
error_category=$(categorize_error "$exit_code")
898910
[[ -z "$error" ]] && error="Unknown error"
911+
912+
# Build medium error for attempt 2: explanation + last 100 log lines (≤16KB)
913+
# This is the critical middle ground between full 120KB log and generic-only description
914+
local medium_log=""
915+
medium_log=$(get_full_log 16384) || true # 16KB max
916+
if [[ -z "$medium_log" ]]; then
917+
medium_log=$(get_error_text) || true
918+
fi
919+
local medium_full
920+
medium_full=$(build_error_string "$exit_code" "$medium_log")
921+
medium_error=$(json_escape "$medium_full")
922+
[[ -z "$medium_error" ]] && medium_error="$short_error"
899923
fi
900924

901925
# Calculate duration if timer was started
@@ -954,7 +978,7 @@ EOF
954978
return 0
955979
fi
956980

957-
# ── Attempt 2: Short error text (no full log) ──
981+
# ── Attempt 2: Medium error text (truncated log ≤16KB instead of full 120KB) ──
958982
sleep 1
959983
local RETRY_PAYLOAD
960984
RETRY_PAYLOAD=$(
@@ -974,7 +998,7 @@ EOF
974998
"pve_version": "${pve_version}",
975999
"method": "${METHOD:-default}",
9761000
"exit_code": ${exit_code},
977-
"error": "${short_error}",
1001+
"error": "${medium_error}",
9781002
"error_category": "${error_category}",
9791003
"install_duration": ${duration},
9801004
"cpu_vendor": "${cpu_vendor}",
@@ -997,7 +1021,7 @@ EOF
9971021
return 0
9981022
fi
9991023

1000-
# ── Attempt 3: Minimal payload (bare minimum to set status) ──
1024+
# ── Attempt 3: Minimal payload with medium error (bare minimum to set status) ──
10011025
sleep 2
10021026
local MINIMAL_PAYLOAD
10031027
MINIMAL_PAYLOAD=$(
@@ -1009,7 +1033,7 @@ EOF
10091033
"nsapp": "${NSAPP:-unknown}",
10101034
"status": "${pb_status}",
10111035
"exit_code": ${exit_code},
1012-
"error": "${short_error}",
1036+
"error": "${medium_error}",
10131037
"error_category": "${error_category}",
10141038
"install_duration": ${duration}
10151039
}

misc/error_handler.func

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,10 +408,29 @@ _send_abort_telemetry() {
408408
[[ "${DIAGNOSTICS:-no}" == "no" ]] && return 0
409409
[[ -z "${RANDOM_UUID:-}" ]] && return 0
410410

411-
# Collect last 20 log lines for error diagnosis (best-effort)
411+
# Collect last 200 log lines for error diagnosis (best-effort)
412+
# Container context has no get_full_log(), so we gather as much as possible
412413
local error_text=""
414+
local logfile=""
413415
if [[ -n "${INSTALL_LOG:-}" && -s "${INSTALL_LOG}" ]]; then
414-
error_text=$(tail -n 20 "$INSTALL_LOG" 2>/dev/null | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\\/\\\\/g; s/"/\\"/g; s/\r//g' | tr '\n' '|' | sed 's/|$//' | tr -d '\000-\010\013\014\016-\037\177') || true
416+
logfile="${INSTALL_LOG}"
417+
elif [[ -n "${SILENT_LOGFILE:-}" && -s "${SILENT_LOGFILE}" ]]; then
418+
logfile="${SILENT_LOGFILE}"
419+
fi
420+
421+
if [[ -n "$logfile" ]]; then
422+
error_text=$(tail -n 200 "$logfile" 2>/dev/null | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\\/\\\\/g; s/"/\\"/g; s/\r//g' | tr '\n' '|' | sed 's/|$//' | head -c 16384 | tr -d '\000-\010\013\014\016-\037\177') || true
423+
fi
424+
425+
# Prepend exit code explanation header (like build_error_string does on host)
426+
local explanation=""
427+
if declare -f explain_exit_code &>/dev/null; then
428+
explanation=$(explain_exit_code "$exit_code" 2>/dev/null) || true
429+
fi
430+
if [[ -n "$explanation" && -n "$error_text" ]]; then
431+
error_text="exit_code=${exit_code} | ${explanation}|---|${error_text}"
432+
elif [[ -n "$explanation" && -z "$error_text" ]]; then
433+
error_text="exit_code=${exit_code} | ${explanation}"
415434
fi
416435

417436
# Calculate duration if start time is available
@@ -420,10 +439,17 @@ _send_abort_telemetry() {
420439
duration=$(($(date +%s) - DIAGNOSTICS_START_TIME))
421440
fi
422441

442+
# Categorize error if function is available (may not be in minimal container context)
443+
local error_category=""
444+
if declare -f categorize_error &>/dev/null; then
445+
error_category=$(categorize_error "$exit_code" 2>/dev/null) || true
446+
fi
447+
423448
# Build JSON payload with error context
424449
local payload
425450
payload="{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"${TELEMETRY_TYPE:-lxc}\",\"nsapp\":\"${NSAPP:-${app:-unknown}}\",\"status\":\"failed\",\"exit_code\":${exit_code}"
426451
[[ -n "$error_text" ]] && payload="${payload},\"error\":\"${error_text}\""
452+
[[ -n "$error_category" ]] && payload="${payload},\"error_category\":\"${error_category}\""
427453
[[ -n "$duration" ]] && payload="${payload},\"duration\":${duration}"
428454
payload="${payload}}"
429455

0 commit comments

Comments
 (0)