func captureSearchStatement()

in module/apmelasticsearch/client.go [173:235]


func captureSearchStatement(req *http.Request) (string, *http.Request) {
	if !isSearchURL(req.URL) {
		return "", req
	}

	// If "q" is in query params, use that for statement.
	if req.URL.RawQuery != "" {
		query := req.URL.Query()
		if statement := query.Get("q"); statement != "" {
			return statement, req
		}
	}
	if req.Body == nil || req.Body == http.NoBody {
		return "", req
	}

	var bodyBuf bytes.Buffer
	if req.GetBody != nil {
		// req.GetBody is defined, so we can read a copy of the
		// request body instead of messing with the original request
		// body.
		body, err := req.GetBody()
		if err != nil {
			return "", req
		}
		if _, err := bodyBuf.ReadFrom(limitedBody(body, req.ContentLength)); err != nil {
			body.Close()
			return "", req
		}
		if err := body.Close(); err != nil {
			return "", req
		}
	} else {
		type readCloser struct {
			io.Reader
			io.Closer
		}
		newBody := &readCloser{Closer: req.Body}
		reqCopy := *req
		reqCopy.Body = newBody
		if _, err := bodyBuf.ReadFrom(limitedBody(req.Body, req.ContentLength)); err != nil {
			// Continue with the request, ensuring that req.Body returns
			// the same content and error, but don't use the consumed body
			// for the statement.
			newBody.Reader = io.MultiReader(bytes.NewReader(bodyBuf.Bytes()), errorReader{err: err})
			return "", &reqCopy
		}
		newBody.Reader = io.MultiReader(bytes.NewReader(bodyBuf.Bytes()), req.Body)
		req = &reqCopy
	}

	var statement string
	if req.Header.Get("Content-Encoding") == "gzip" {
		if r, err := gzip.NewReader(&bodyBuf); err == nil {
			if content, err := ioutil.ReadAll(r); err == nil {
				statement = string(content)
			}
		}
	} else {
		statement = bodyBuf.String()
	}
	return statement, req
}