Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pagination support for Sentry endpoints #77

Merged
Merged
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ require (
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/peterhellberg/link v1.2.0 // indirect
github.com/pierrec/lz4/v4 v4.1.8 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DV
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/peterhellberg/link v1.2.0 h1:UA5pg3Gp/E0F2WdX7GERiNrPQrM1K6CVJUUWfHa4t6c=
github.com/peterhellberg/link v1.2.0/go.mod h1:gYfAh+oJgQu2SrZHg5hROVRQe1ICoK0/HHJTcE0edxc=
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4=
Expand Down
2 changes: 1 addition & 1 deletion pkg/plugin/handlers_healthcheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func (ds *SentryDatasource) CheckHealth(ctx context.Context, req *backend.CheckH
}

func CheckHealth(sentryClient sentry.SentryClient) (*backend.CheckHealthResult, error) {
projects, err := sentryClient.GetProjects(sentryClient.OrgSlug)
projects, err := sentryClient.GetProjects(sentryClient.OrgSlug, false)
if err != nil {
errorMessage := err.Error()
return &backend.CheckHealthResult{
Expand Down
2 changes: 1 addition & 1 deletion pkg/plugin/handlers_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func GetProjectsHandler(client *sentry.SentryClient) http.HandlerFunc {
http.Error(rw, "invalid orgSlug", http.StatusBadRequest)
return
}
orgs, err := client.GetProjects(orgSlug)
orgs, err := client.GetProjects(orgSlug, true)
writeResponse(orgs, err, rw)
}
}
Expand Down
24 changes: 20 additions & 4 deletions pkg/sentry/projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,29 @@ type SentryProject struct {
} `json:"teams"`
}

func (sc *SentryClient) GetProjects(organizationSlug string) ([]SentryProject, error) {
out := []SentryProject{}
func (sc *SentryClient) GetProjects(organizationSlug string, withPagination bool) ([]SentryProject, error) {
projects := []SentryProject{}
if organizationSlug == "" {
organizationSlug = sc.OrgSlug
}
url := "/api/0/organizations/" + organizationSlug + "/projects/"

if (withPagination) {
for (url != "") {
batch := []SentryProject{}
nextURL, err := sc.FetchWithPagination(url, &batch)
if err != nil {
return nil, err
}

projects = append(projects, batch...)
url = nextURL
}
return projects, nil
} else {
err := sc.Fetch(url, &projects)
return projects, err
}
err := sc.Fetch("/api/0/organizations/"+organizationSlug+"/projects/", &out)
return out, err
}

func (sc *SentryClient) GetTeamsProjects(organizationSlug string, teamSlug string) ([]SentryProject, error) {
Expand Down
39 changes: 39 additions & 0 deletions pkg/sentry/sentry.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"

"github.com/grafana/grafana-plugin-sdk-go/build"
"github.com/peterhellberg/link"
)

type SentryClient struct {
Expand All @@ -34,6 +35,44 @@ type SentryErrorResponse struct {
Detail string `json:"detail"`
}

func (sc *SentryClient) FetchWithPagination(path string, out interface{}) (string, error) {
fullURL := path
if !strings.HasPrefix(path, sc.BaseURL) {
fullURL = sc.BaseURL + path
}
req, _ := http.NewRequest(http.MethodGet, fullURL, nil)
olegpixel marked this conversation as resolved.
Show resolved Hide resolved
res, err := sc.sentryHttpClient.Do(req)
if err != nil {
return "", err
}
defer res.Body.Close()

nextURL := ""
header := res.Header
links := link.ParseHeader(header)

if links != nil {
if nextLink, found := links["next"]; found && nextLink.Extra["results"] == "true" {
nextURL = nextLink.URI
}
}

if res.StatusCode == http.StatusOK {
if err := json.NewDecoder(res.Body).Decode(&out); err != nil {
return "", err
}
} else {
var errResponse SentryErrorResponse
if err := json.NewDecoder(res.Body).Decode(&errResponse); err != nil {
errorMessage := strings.TrimSpace(fmt.Sprintf("%s %s", res.Status, err.Error()))
return "", errors.New(errorMessage)
}
errorMessage := strings.TrimSpace(fmt.Sprintf("%s %s", res.Status, errResponse.Detail))
return "", errors.New(errorMessage)
}
return nextURL, nil
}

func (sc *SentryClient) Fetch(path string, out interface{}) error {
req, _ := http.NewRequest(http.MethodGet, sc.BaseURL+path, nil)
res, err := sc.sentryHttpClient.Do(req)
Expand Down