func()

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
}