Skip to content

Commit

Permalink
Add pagination support for Sentry endpoints (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
olegpixel authored Oct 13, 2023
1 parent 263e9d2 commit 0bd40eb
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 8 deletions.
3 changes: 2 additions & 1 deletion cspell.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"testid",
"typecheck",
"Unmarshaling",
"proxying"
"proxying",
"peterhellberg"
]
}
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/perimeterx/marshmallow v1.1.5 // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ 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/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
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
47 changes: 46 additions & 1 deletion 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,8 +35,52 @@ 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, err := http.NewRequest(http.MethodGet, fullURL, nil)
if err != nil {
return "", err
}
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)
req, err := http.NewRequest(http.MethodGet, sc.BaseURL+path, nil)
if err != nil {
return err
}
res, err := sc.sentryHttpClient.Do(req)
if err != nil {
return err
Expand Down

0 comments on commit 0bd40eb

Please sign in to comment.