From 3ea663c8dcba84a931224e3c7e829214a7cc83d3 Mon Sep 17 00:00:00 2001 From: Head of Product & Engineering Date: Mon, 6 Apr 2026 11:56:10 +0200 Subject: [PATCH] debug: add panic recovery and verbose logging to processOutbound Adds per-step log entries so we can trace exactly where the outbound SMS flow breaks: goroutine start, phone normalization result, Cast API call attempt, and Cast API result. Also adds panic recovery so a crash in the goroutine is captured in structured logs instead of lost silently. Co-Authored-By: Paperclip --- internal/ghl/webhook.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/internal/ghl/webhook.go b/internal/ghl/webhook.go index ef2fc7f..4d7a82d 100644 --- a/internal/ghl/webhook.go +++ b/internal/ghl/webhook.go @@ -120,9 +120,17 @@ func (h *WebhookHandler) HandleWebhook(w http.ResponseWriter, r *http.Request) { } func (h *WebhookHandler) processOutbound(webhook OutboundMessageWebhook) { + defer func() { + if r := recover(); r != nil { + slog.Error("webhook: processOutbound panic", "message_id", webhook.MessageID, "panic", r) + } + }() + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() + slog.Info("webhook: processing outbound SMS", "message_id", webhook.MessageID, "location_id", webhook.LocationID, "phone", webhook.Phone) + localPhone, err := phone.ToLocal(webhook.Phone) if err != nil { slog.Error("webhook: phone normalization failed", "phone", webhook.Phone, "err", err) @@ -130,9 +138,10 @@ func (h *WebhookHandler) processOutbound(webhook OutboundMessageWebhook) { return } + slog.Info("webhook: calling cast api", "message_id", webhook.MessageID, "to", localPhone) _, err = h.castClient.SendSMS(ctx, localPhone, webhook.Message) if err != nil { - slog.Error("webhook: cast send failed", "message_id", webhook.MessageID, "err", err) + slog.Error("webhook: cast send failed", "message_id", webhook.MessageID, "to", localPhone, "err", err) h.updateStatus(ctx, webhook, "failed") return }