MCPcopy
hub / github.com/docker/docker-agent / performHTTPRequest

Method performHTTPRequest

pkg/telemetry/http.go:114–180  ·  view source on GitHub ↗

performHTTPRequest handles the actual HTTP request to the telemetry API

(ctx context.Context, event *EventPayload, version string)

Source from the content-addressed store, hash-verified

112
113// performHTTPRequest handles the actual HTTP request to the telemetry API
114func (tc *Client) performHTTPRequest(ctx context.Context, event *EventPayload, version string) error {
115 // Wrap event in records array to match MarlinRequest format
116 requestBody := map[string]any{
117 "records": []any{event},
118 }
119
120 // Serialize request to JSON
121 jsonData, err := json.Marshal(requestBody)
122 if err != nil {
123 return fmt.Errorf("failed to marshal request to JSON: %w", err)
124 }
125
126 // Send request with timeout context. Telemetry sends should outlive a
127 // cancelled caller, but keep its trace context for correlation.
128 ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 10*time.Second)
129 defer cancel()
130
131 // Create HTTP request
132 req, err := http.NewRequestWithContext(ctx, http.MethodPost, tc.endpoint, bytes.NewBuffer(jsonData))
133 if err != nil {
134 return fmt.Errorf("failed to create HTTP request: %w", err)
135 }
136
137 // Set headers
138 req.Header.Set("Content-Type", "application/json")
139 req.Header.Set("User-Agent", "cagent/"+version)
140 if tc.apiKey != "" && tc.header != "" {
141 req.Header.Set(tc.header, tc.apiKey)
142 }
143
144 // Debug: log request details
145 tc.logger.Debug("HTTP request details",
146 "method", req.Method,
147 "url", req.URL.String(),
148 "content_type", req.Header.Get("Content-Type"),
149 "user_agent", req.Header.Get("User-Agent"),
150 "has_header", req.Header.Get(tc.header) != "",
151 "header_length", len(req.Header.Get(tc.header)),
152 "payload_size", len(jsonData),
153 "payload", string(jsonData),
154 )
155
156 resp, err := tc.httpClient.Do(req)
157 if err != nil {
158 return fmt.Errorf("HTTP request failed: %w", err)
159 }
160 defer resp.Body.Close()
161
162 // Check response status
163 if resp.StatusCode < 200 || resp.StatusCode >= 300 {
164 body := make([]byte, 1024) // Read up to 1KB of error response
165 n, _ := resp.Body.Read(body)
166
167 // Enhanced error logging with response details
168 tc.logger.Debug("HTTP error response details",
169 "status_code", resp.StatusCode,
170 "status_text", resp.Status,
171 "content_type", resp.Header.Get("Content-Type"),

Callers 1

sendEventMethod · 0.95

Calls 7

DebugMethod · 0.80
GetMethod · 0.65
DoMethod · 0.65
CloseMethod · 0.65
ReadMethod · 0.65
SetMethod · 0.45
StringMethod · 0.45

Tested by

no test coverage detected