# =============================================================== # call_file — Timed JSON logger for Zsh config execution # =============================================================== # Source this file early (e.g. in ~/.zshenv). It defines a function: # call_file /path/to/script.zsh [label] # Logs NDJSON lines to $outfile (default: ~/zshrc-log.json) function call_file() { # No set -u here; be tolerant during early boot local filepath="$1" local label="${2:-}" local resolved_path exit_code=0 duration_ms start_time end_time LOGFILE json_entry [[ -z "$filepath" ]] && return 0 LOGFILE="${outfile:-$HOME/zshrc-log.json}" : "${CALL_FILE_DEBUG:=0}" # Resolve path (follow symlinks if present), fallback safely on macOS if [[ -L "$filepath" ]]; then if command -v readlink >/dev/null 2>&1 && readlink -f / >/dev/null 2>&1; then resolved_path="$(readlink -f "$filepath" 2>/dev/null || echo "$filepath")" elif command -v realpath >/dev/null 2>&1; then resolved_path="$(realpath "$filepath" 2>/dev/null || echo "$filepath")" else resolved_path="$filepath" fi else resolved_path="$filepath" fi # Derive label if not provided: config.zsh -> parent dir name, else file stem if [[ -z "$label" ]]; then local fname="${resolved_path:t}" local dname="${resolved_path:h:t}" if [[ "$fname" == "config.zsh" ]]; then label="$dname" else label="${fname:r}" fi fi # Guard if file missing [[ ! -r "$resolved_path" ]] && { print -u2 "call_file: missing or unreadable: $resolved_path" return 1 } # Timestamps (μs precision). Fall back if EPOCHREALTIME is unavailable. start_time="${EPOCHREALTIME:-$(perl -MTime::HiRes=time -e 'printf "%.6f\n", time()')}" [[ "$CALL_FILE_DEBUG" != "0" ]] && print -- "▶️ Starting $resolved_path (label: $label)" { # source quietly; the config can print if it wants—logs stay clean source "$resolved_path" } >/dev/null 2>&1 || exit_code=$? end_time="${EPOCHREALTIME:-$(perl -MTime::HiRes=time -e 'printf "%.6f\n", time()')}" # Floating math via awk to avoid zsh int math pitfalls duration_ms=$(awk -v s="$start_time" -v e="$end_time" 'BEGIN {printf "%.5f", (e - s) * 1000}') [[ "$CALL_FILE_DEBUG" != "0" ]] && print -- "⏱ Finished $resolved_path in ${duration_ms}ms (exit:${exit_code})" # Ensure logfile dir exists mkdir -p -- "$(dirname -- "$LOGFILE")" 2>/dev/null # NDJSON entry (numbers are real numbers via --argjson) json_entry=$(jq -nc \ --arg file "$resolved_path" \ --arg label "$label" \ --argjson start "$(printf "%.5f" "$start_time")" \ --argjson end "$(printf "%.5f" "$end_time")" \ --argjson duration "$(printf "%.5f" "$duration_ms")" \ --argjson code "$exit_code" \ '{file:$file, label:$label, start:$start, end:$end, duration_ms:$duration, exit_code:$code}') # Append (don’t fail if file doesn’t exist yet) if [[ -w "$LOGFILE" || ! -e "$LOGFILE" ]]; then print -- "$json_entry" >>"$LOGFILE" fi }