package client import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "strings" "time" ) type SelfGameH5Event struct { AppCode string `json:"app_code"` EventID string `json:"event_id"` EventName string `json:"event_name"` GameID string `json:"game_id"` Page string `json:"page"` SessionID string `json:"session_id"` MatchID string `json:"match_id"` UserID int64 `json:"user_id"` CountryID int64 `json:"country_id"` RegionID int64 `json:"region_id"` Language string `json:"language"` ClientVersion string `json:"client_version"` H5Version string `json:"h5_version"` EntrySource string `json:"entry_source"` DurationMS int64 `json:"duration_ms"` Success bool `json:"success"` ErrorCode string `json:"error_code"` OccurredAtMS int64 `json:"occurred_at_ms"` } type StatisticsClient interface { ReportSelfGameH5Event(ctx context.Context, event SelfGameH5Event) error } type HTTPStatisticsClient struct { baseURL string httpClient *http.Client } func NewHTTPStatisticsClient(baseURL string, timeout time.Duration) *HTTPStatisticsClient { baseURL = strings.TrimRight(strings.TrimSpace(baseURL), "/") if baseURL == "" { return nil } if timeout <= 0 { timeout = 2 * time.Second } return &HTTPStatisticsClient{ baseURL: baseURL, httpClient: &http.Client{Timeout: timeout}, } } func (c *HTTPStatisticsClient) ReportSelfGameH5Event(ctx context.Context, event SelfGameH5Event) error { if c == nil || c.httpClient == nil || c.baseURL == "" { return fmt.Errorf("statistics client is not configured") } body, err := json.Marshal(event) if err != nil { return err } req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL+"/internal/v1/statistics/self-game/events", bytes.NewReader(body)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") resp, err := c.httpClient.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode >= 200 && resp.StatusCode < 300 { return nil } payload, _ := io.ReadAll(io.LimitReader(resp.Body, 512)) return fmt.Errorf("statistics report failed: status=%d body=%s", resp.StatusCode, strings.TrimSpace(string(payload))) }