137 lines
3.3 KiB
Go
137 lines
3.3 KiB
Go
package clients
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
)
|
|
|
|
type sentryClient struct {
|
|
//
|
|
}
|
|
|
|
func NewSentryClient() Client {
|
|
return &sentryClient{}
|
|
}
|
|
|
|
type sentryConfig struct {
|
|
OrganizationSlug string `json:"organization_slug"`
|
|
ProjectSlug string `json:"project_slug"`
|
|
Token string `json:"token"`
|
|
URL string `json:"url"`
|
|
}
|
|
|
|
type SentryEvent struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
Message string `json:"message"`
|
|
Environment string `json:"environment"`
|
|
}
|
|
|
|
func (s *sentryClient) FetchSessionData(credentials interface{}, sessionID uint64) (interface{}, error) {
|
|
cfg, err := parseSentryConfig(credentials)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// Fetch sentry events
|
|
requestUrl := prepareURLWithParams(cfg, sessionID, true)
|
|
list, err := makeRequest(cfg, requestUrl)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if list == nil || len(list) == 0 {
|
|
// Fetch sentry issues if no events found
|
|
requestUrl = prepareURLWithParams(cfg, sessionID, false)
|
|
list, err = makeRequest(cfg, requestUrl)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if list == nil || len(list) == 0 {
|
|
return nil, fmt.Errorf("no logs found")
|
|
}
|
|
}
|
|
result, err := json.Marshal(list)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func parseSentryConfig(credentials interface{}) (sentryConfig, error) {
|
|
cfg, ok := credentials.(sentryConfig)
|
|
if !ok {
|
|
strCfg, ok := credentials.(map[string]interface{})
|
|
if !ok {
|
|
return cfg, fmt.Errorf("invalid credentials")
|
|
}
|
|
cfg = sentryConfig{}
|
|
if val, ok := strCfg["organization_slug"].(string); ok {
|
|
cfg.OrganizationSlug = val
|
|
}
|
|
if val, ok := strCfg["project_slug"].(string); ok {
|
|
cfg.ProjectSlug = val
|
|
}
|
|
if val, ok := strCfg["token"].(string); ok {
|
|
cfg.Token = val
|
|
}
|
|
if val, ok := strCfg["url"].(string); ok {
|
|
cfg.URL = val
|
|
}
|
|
}
|
|
if cfg.URL == "" {
|
|
cfg.URL = "https://sentry.io"
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
func prepareURLWithParams(cfg sentryConfig, sessionID uint64, isEvents bool) string {
|
|
entities := "issues"
|
|
if isEvents {
|
|
entities = "events"
|
|
}
|
|
requestUrl := fmt.Sprintf("%s/api/0/projects/%s/%s/%s/", cfg.URL, cfg.OrganizationSlug, cfg.ProjectSlug, entities)
|
|
params := url.Values{}
|
|
querySign := ":"
|
|
if isEvents {
|
|
querySign = "="
|
|
}
|
|
if sessionID != 0 {
|
|
params.Add("query", fmt.Sprintf("openReplaySession.id%s%d", querySign, sessionID))
|
|
} else {
|
|
params.Add("per_page", "1")
|
|
}
|
|
return requestUrl + "?" + params.Encode()
|
|
}
|
|
|
|
func makeRequest(cfg sentryConfig, requestUrl string) ([]SentryEvent, error) {
|
|
req, err := http.NewRequest("GET", requestUrl, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create request: %v", err)
|
|
}
|
|
req.Header.Set("Authorization", "Bearer "+cfg.Token)
|
|
|
|
client := &http.Client{}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to send request: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("failed to fetch logs, status code: %v", resp.StatusCode)
|
|
}
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read response body: %v", err)
|
|
}
|
|
|
|
var events []SentryEvent
|
|
err = json.Unmarshal(body, &events)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse JSON: %v", err)
|
|
}
|
|
return events, nil
|
|
}
|