fix: add detailed watch-order logs

This commit is contained in:
2026-04-11 22:20:06 +02:00
parent 704b446216
commit 600698e12a
3 changed files with 80 additions and 1 deletions

View File

@@ -50,8 +50,21 @@ func (c *Client) getWatchOrder(ctx context.Context, id int) (watchorder.WatchOrd
result, err := watchorder.FetchWatchOrder(requestCtx, c.httpClient, watchOrderURL)
if err != nil {
var statusError *watchorder.HTTPStatusError
if errors.Is(err, watchorder.ErrWatchOrderMarkupNotFound) {
log.Printf("relations: watch-order markup missing for %d (%s): %v", id, watchOrderURL, err)
} else if errors.As(err, &statusError) {
log.Printf(
"relations: watch-order http error for %d (%s): status=%d server=%q cf_ray=%q location=%q content_type=%q body=%q",
id,
watchOrderURL,
statusError.StatusCode,
statusError.Server,
statusError.CFRay,
statusError.Location,
statusError.ContentType,
statusError.BodyPreview,
)
} else {
log.Printf("relations: watch-order fetch failed for %d (%s): %v", id, watchOrderURL, err)
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"io"
"net/http"
"regexp"
"strconv"
@@ -19,6 +20,29 @@ var idPattern = regexp.MustCompile(`/id/(\d+)`)
var ErrInvalidWatchOrderURL = errors.New("invalid watch order url")
var ErrWatchOrderMarkupNotFound = errors.New("watch order markup not found")
type HTTPStatusError struct {
StatusCode int
URL string
Server string
CFRay string
Location string
ContentType string
BodyPreview string
}
func (e *HTTPStatusError) Error() string {
return fmt.Sprintf(
"unexpected status code: %d (url=%s server=%s cf_ray=%s location=%s content_type=%s body=%q)",
e.StatusCode,
e.URL,
e.Server,
e.CFRay,
e.Location,
e.ContentType,
e.BodyPreview,
)
}
type WatchOrderEntry struct {
ID int `json:"id"`
Type string `json:"type"`
@@ -76,7 +100,16 @@ func fetchDocument(ctx context.Context, httpClient *http.Client, url string) (*g
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode)
body, _ := io.ReadAll(io.LimitReader(response.Body, 512))
return nil, &HTTPStatusError{
StatusCode: response.StatusCode,
URL: url,
Server: strings.TrimSpace(response.Header.Get("Server")),
CFRay: strings.TrimSpace(response.Header.Get("CF-Ray")),
Location: strings.TrimSpace(response.Header.Get("Location")),
ContentType: strings.TrimSpace(response.Header.Get("Content-Type")),
BodyPreview: strings.Join(strings.Fields(strings.TrimSpace(string(body))), " "),
}
}
document, err := goquery.NewDocumentFromReader(response.Body)

View File

@@ -5,6 +5,7 @@ import (
"errors"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
)
@@ -125,3 +126,35 @@ func TestFetchWatchOrder_MissingMarkupReturnsError(t *testing.T) {
t.Fatalf("expected ErrWatchOrderMarkupNotFound, got %v", err)
}
}
func TestFetchWatchOrder_HTTPStatusErrorIncludesContext(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", "cloudflare")
w.Header().Set("CF-Ray", "abc123")
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusForbidden)
_, _ = w.Write([]byte("<html><body>access denied</body></html>"))
}))
defer server.Close()
url := server.URL + "/?/tools/watch_order/id/1"
_, err := FetchWatchOrder(context.Background(), &http.Client{Timeout: time.Second}, url)
if err == nil {
t.Fatalf("expected error, got nil")
}
var statusError *HTTPStatusError
if !errors.As(err, &statusError) {
t.Fatalf("expected HTTPStatusError, got %T", err)
}
if statusError.StatusCode != http.StatusForbidden {
t.Fatalf("expected 403, got %d", statusError.StatusCode)
}
if statusError.CFRay != "abc123" {
t.Fatalf("expected cf-ray abc123, got %q", statusError.CFRay)
}
if !strings.Contains(statusError.BodyPreview, "access denied") {
t.Fatalf("expected body preview to include access denied, got %q", statusError.BodyPreview)
}
}