in internal/sourcemap/elasticsearch.go [68:122]
func (s *esFetcher) Fetch(ctx context.Context, name, version, path string) (*sourcemap.Consumer, error) {
resp, err := s.runSearchQuery(ctx, name, version, path)
if err != nil {
var networkErr net.Error
if errors.As(err, &networkErr) {
return nil, fmt.Errorf("failed to reach elasticsearch: %w: %v ", errFetcherUnvailable, err)
}
return nil, fmt.Errorf("failure querying ES: %w", err)
}
defer resp.Body.Close()
// handle error response
if resp.StatusCode >= http.StatusMultipleChoices {
b, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read ES response body: %w", err)
}
if resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden {
// http.StatusNotFound -> the index is missing
// http.StatusForbidden -> we don't have permission to read from the index
// In both cases we consider the fetcher unavailable so that APM Server can
// fallback to other fetchers
return nil, fmt.Errorf("%w: %s: %s", errFetcherUnvailable, resp.Status, string(b))
}
return nil, fmt.Errorf("ES returned unknown status code: %s", resp.Status)
}
// parse response
body, err := parse(resp.Body, name, version, path, s.logger)
if err != nil {
return nil, err
}
if body == "" {
return nil, nil
}
decodedBody, err := base64.StdEncoding.DecodeString(body)
if err != nil {
return nil, fmt.Errorf("failed to base64 decode string: %w", err)
}
r, err := zlib.NewReader(bytes.NewReader(decodedBody))
if err != nil {
return nil, fmt.Errorf("failed to create zlib reader: %w", err)
}
defer r.Close()
uncompressedBody, err := io.ReadAll(r)
if err != nil {
return nil, fmt.Errorf("failed to read sourcemap content: %w", err)
}
return parseSourceMap(uncompressedBody)
}