in pkg/middleware/arm_error_collector.go [83:140]
func (p *ArmRequestMetricPolicy) Do(req *policy.Request) (*http.Response, error) {
httpReq := req.Raw()
if httpReq == nil || httpReq.URL == nil {
// not able to collect telemetry, just pass through
return req.Next()
}
armResId, err := arm.ParseResourceID(httpReq.URL.Path)
if err != nil {
// TODO: error handling without break the request.
}
connTracking := &HttpConnTracking{}
// have to add to the context at first - then clone the policy.Request struct
// this allows the connection tracing to happen
// otherwise we can't change the underlying http request of req, we have to use
// newARMReq
newCtx := addConnectionTracingToRequestContext(httpReq.Context(), connTracking)
newARMReq := req.Clone(newCtx)
requestInfo := newRequestInfo(httpReq, armResId)
started := time.Now()
p.requestStarted(requestInfo)
var resp *http.Response
var reqErr error
// defer this function in case there's a panic somewhere down the pipeline.
// It's the calling user's responsibility to handle panics, not this policy
defer func() {
latency := time.Since(started)
respInfo := &ResponseInfo{
Response: resp,
Latency: latency,
ConnTracking: connTracking,
}
if reqErr != nil {
// either it's a transport error
// or it is already handled by previous policy
respInfo.Error = parseTransportError(reqErr)
} else {
respInfo.Error = parseArmErrorFromResponse(resp)
}
// need to get the request id and correlation id from the response.request header
// because the headers were added by policy and might be called after this policy
if resp != nil && resp.Request != nil {
respInfo.RequestId = resp.Request.Header.Get(headerKeyRequestID)
respInfo.CorrelationId = resp.Request.Header.Get(headerKeyCorrelationID)
}
p.requestCompleted(requestInfo, respInfo)
}()
resp, reqErr = newARMReq.Next()
return resp, reqErr
}