From 1584deaca8b3f618f4c96a05e8acc51c9eac37e7 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Fri, 20 Mar 2026 08:20:44 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20richer=20error=20telemetry=20=E2=80=94?= =?UTF-8?q?=20error=5Fmessage=20+=20failed=5Fstep=20fields?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds error_message (max 200 chars, e.g. "bun test: 3 tests failed") and failed_step (e.g. "run_tests", "create_pr") to telemetry events. Schema, ingest function, and local logger all updated. Makes crash reports actionable instead of just "timeout — 252 occurrences". Co-Authored-By: Claude Opus 4.6 (1M context) --- bin/gstack-telemetry-log | 29 ++++++++++++++------ supabase/functions/telemetry-ingest/index.ts | 4 +++ supabase/migrations/002_community_tier.sql | 6 +++- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/bin/gstack-telemetry-log b/bin/gstack-telemetry-log index edcbdbab..5edde6dd 100755 --- a/bin/gstack-telemetry-log +++ b/bin/gstack-telemetry-log @@ -32,17 +32,21 @@ OUTCOME="unknown" USED_BROWSE="false" SESSION_ID="" ERROR_CLASS="" +ERROR_MESSAGE="" +FAILED_STEP="" EVENT_TYPE="skill_run" while [ $# -gt 0 ]; do case "$1" in - --skill) SKILL="$2"; shift 2 ;; - --duration) DURATION="$2"; shift 2 ;; - --outcome) OUTCOME="$2"; shift 2 ;; - --used-browse) USED_BROWSE="$2"; shift 2 ;; - --session-id) SESSION_ID="$2"; shift 2 ;; - --error-class) ERROR_CLASS="$2"; shift 2 ;; - --event-type) EVENT_TYPE="$2"; shift 2 ;; + --skill) SKILL="$2"; shift 2 ;; + --duration) DURATION="$2"; shift 2 ;; + --outcome) OUTCOME="$2"; shift 2 ;; + --used-browse) USED_BROWSE="$2"; shift 2 ;; + --session-id) SESSION_ID="$2"; shift 2 ;; + --error-class) ERROR_CLASS="$2"; shift 2 ;; + --error-message) ERROR_MESSAGE="$2"; shift 2 ;; + --failed-step) FAILED_STEP="$2"; shift 2 ;; + --event-type) EVENT_TYPE="$2"; shift 2 ;; *) shift ;; esac done @@ -135,6 +139,12 @@ mkdir -p "$ANALYTICS_DIR" ERR_FIELD="null" [ -n "$ERROR_CLASS" ] && ERR_FIELD="\"$ERROR_CLASS\"" +ERR_MSG_FIELD="null" +[ -n "$ERROR_MESSAGE" ] && ERR_MSG_FIELD="\"$(echo "$ERROR_MESSAGE" | head -c 200 | sed 's/"/\\"/g')\"" + +STEP_FIELD="null" +[ -n "$FAILED_STEP" ] && STEP_FIELD="\"$(echo "$FAILED_STEP" | head -c 30)\"" + DUR_FIELD="null" [ -n "$DURATION" ] && DUR_FIELD="$DURATION" @@ -144,9 +154,10 @@ INSTALL_FIELD="null" BROWSE_BOOL="false" [ "$USED_BROWSE" = "true" ] && BROWSE_BOOL="true" -printf '{"v":1,"ts":"%s","event_type":"%s","skill":"%s","session_id":"%s","gstack_version":"%s","os":"%s","arch":"%s","duration_s":%s,"outcome":"%s","error_class":%s,"used_browse":%s,"sessions":%s,"installation_id":%s,"_repo_slug":"%s","_branch":"%s"}\n' \ +printf '{"v":1,"ts":"%s","event_type":"%s","skill":"%s","session_id":"%s","gstack_version":"%s","os":"%s","arch":"%s","duration_s":%s,"outcome":"%s","error_class":%s,"error_message":%s,"failed_step":%s,"used_browse":%s,"sessions":%s,"installation_id":%s,"_repo_slug":"%s","_branch":"%s"}\n' \ "$TS" "$EVENT_TYPE" "$SKILL" "$SESSION_ID" "$GSTACK_VERSION" "$OS" "$ARCH" \ - "$DUR_FIELD" "$OUTCOME" "$ERR_FIELD" "$BROWSE_BOOL" "${SESSIONS:-1}" \ + "$DUR_FIELD" "$OUTCOME" "$ERR_FIELD" "$ERR_MSG_FIELD" "$STEP_FIELD" \ + "$BROWSE_BOOL" "${SESSIONS:-1}" \ "$INSTALL_FIELD" "$REPO_SLUG" "$BRANCH" >> "$JSONL_FILE" 2>/dev/null || true # ─── Trigger sync if tier is not off ───────────────────────── diff --git a/supabase/functions/telemetry-ingest/index.ts b/supabase/functions/telemetry-ingest/index.ts index 07d65d36..248c7d91 100644 --- a/supabase/functions/telemetry-ingest/index.ts +++ b/supabase/functions/telemetry-ingest/index.ts @@ -16,6 +16,8 @@ interface TelemetryEvent { duration_s?: number; outcome: string; error_class?: string; + error_message?: string; + failed_step?: string; used_browse?: boolean; sessions?: number; installation_id?: string; @@ -77,6 +79,8 @@ Deno.serve(async (req) => { duration_s: typeof event.duration_s === "number" ? event.duration_s : null, outcome: String(event.outcome).slice(0, 20), error_class: event.error_class ? String(event.error_class).slice(0, 100) : null, + error_message: event.error_message ? String(event.error_message).slice(0, 200) : null, + failed_step: event.failed_step ? String(event.failed_step).slice(0, 30) : null, used_browse: event.used_browse === true, concurrent_sessions: typeof event.sessions === "number" ? event.sessions : 1, installation_id: event.installation_id ? String(event.installation_id).slice(0, 64) : null, diff --git a/supabase/migrations/002_community_tier.sql b/supabase/migrations/002_community_tier.sql index 5bf0b789..3b46d847 100644 --- a/supabase/migrations/002_community_tier.sql +++ b/supabase/migrations/002_community_tier.sql @@ -1,5 +1,9 @@ -- gstack community tier schema --- Adds authenticated backup, benchmarks, and email to the telemetry platform. +-- Adds authenticated backup, benchmarks, email, and richer error telemetry. + +-- Add error context columns to telemetry_events +ALTER TABLE telemetry_events ADD COLUMN error_message TEXT; +ALTER TABLE telemetry_events ADD COLUMN failed_step TEXT; -- Add columns to installations for backup + email + auth identity ALTER TABLE installations ADD COLUMN user_id UUID;