bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/scollector/collectors/github.go (about)

     1  package collectors
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strings"
     7  	"time"
     8  
     9  	"bosun.org/cmd/scollector/conf"
    10  	"bosun.org/metadata"
    11  	"bosun.org/opentsdb"
    12  	"bosun.org/slog"
    13  	"github.com/google/go-github/github"
    14  )
    15  
    16  func init() {
    17  	registerInit(startGithubCollectors)
    18  }
    19  
    20  type githubRoundTripper struct {
    21  	accessToken string
    22  }
    23  
    24  func (rt githubRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
    25  	r.Header.Set("Authorization", fmt.Sprintf("token %s", rt.accessToken))
    26  	return http.DefaultTransport.RoundTrip(r)
    27  }
    28  
    29  func startGithubCollectors(c *conf.Conf) {
    30  	for _, gh := range c.Github {
    31  		client := github.NewClient(&http.Client{Transport: githubRoundTripper{gh.Token}})
    32  		split := strings.Split(gh.Repo, "/")
    33  		if len(split) != 2 {
    34  			slog.Fatal("Repo must have two parts (owner/repo)")
    35  		}
    36  		owner, repo := split[0], split[1]
    37  		collectors = append(collectors, &IntervalCollector{
    38  			F: func() (opentsdb.MultiDataPoint, error) {
    39  				return githubCollect(client, owner, repo)
    40  			},
    41  			name:     fmt.Sprintf("github-%s", gh.Repo),
    42  			Interval: 10 * time.Minute, //10 minutes to respect api limits
    43  		})
    44  	}
    45  }
    46  
    47  const (
    48  	descGithubOpenIssues = "Number of currently open issues"
    49  	descGithubOpenPrs    = "Number of currently open pull requests"
    50  )
    51  
    52  func githubCollect(client *github.Client, owner, repo string) (o opentsdb.MultiDataPoint, e error) {
    53  	var md opentsdb.MultiDataPoint
    54  	opts := &github.IssueListByRepoOptions{
    55  		ListOptions: github.ListOptions{
    56  			PerPage: 100,
    57  			Page:    1,
    58  		},
    59  	}
    60  	openIssueCount := 0
    61  	openPrCount := 0
    62  	issueLabelCounts := make(map[string]int)
    63  	prLabelCounts := make(map[string]int)
    64  	for {
    65  		issues, resp, err := client.Issues.ListByRepo(owner, repo, opts)
    66  		if err != nil {
    67  			return md, err
    68  		}
    69  		for _, i := range issues {
    70  			if i.PullRequestLinks != nil {
    71  				openPrCount++
    72  				for _, label := range i.Labels {
    73  					prLabelCounts[*label.Name] = prLabelCounts[*label.Name] + 1
    74  				}
    75  			} else {
    76  				openIssueCount++
    77  				for _, label := range i.Labels {
    78  					issueLabelCounts[*label.Name] = issueLabelCounts[*label.Name] + 1
    79  				}
    80  			}
    81  		}
    82  		if resp.NextPage == 0 {
    83  			break
    84  		}
    85  		opts.Page = resp.NextPage
    86  	}
    87  	Add(&md, "github.open_issues", openIssueCount, opentsdb.TagSet{"repo": repo}, metadata.Gauge, metadata.Count, descGithubOpenIssues)
    88  	for name, count := range issueLabelCounts {
    89  		Add(&md, "github.open_issues_label", count, opentsdb.TagSet{"repo": repo, "label": name}, metadata.Gauge, metadata.Count, descGithubOpenIssues)
    90  	}
    91  	Add(&md, "github.open_prs", openPrCount, opentsdb.TagSet{"repo": repo}, metadata.Gauge, metadata.Count, descGithubOpenPrs)
    92  	for name, count := range prLabelCounts {
    93  		Add(&md, "github.open_prs_label", count, opentsdb.TagSet{"repo": repo, "label": name}, metadata.Gauge, metadata.Count, descGithubOpenPrs)
    94  	}
    95  	return md, nil
    96  }