Skip to content

Commit 3df1157

Browse files
authored
Merge pull request #42 from x-wf/master
Scrape release metrics from repositories
2 parents 5e0b087 + b5727d6 commit 3df1157

File tree

5 files changed

+57
-10
lines changed

5 files changed

+57
-10
lines changed

METRICS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ github_repo_stars{archived="false",fork="false",language="Go",license="mit",priv
2727
# HELP github_repo_watchers Total number of watchers/subscribers for given repository
2828
# TYPE github_repo_watchers gauge
2929
github_repo_watchers{archived="false",fork="false",language="Go",license="mit",private="false",repo="github-exporter",user="infinityworks"} 10
30+
# TYPE github_repo_release_downloads gauge
31+
github_repo_release_downloads{name="release1.0.0",repo="github-exporter",user="infinityworks"} 3500
3032
```
3133

3234
<!--

exporter/gather.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"fmt"
66
"strconv"
7+
"strings"
78

89
log "github.com/sirupsen/logrus"
910
)
@@ -29,6 +30,11 @@ func (e *Exporter) gatherData() ([]*Datum, *RateLimits, error) {
2930
data = append(data, ds...)
3031
} else {
3132
d := new(Datum)
33+
34+
// Get releases
35+
if strings.Contains(response.url, "/repos/") {
36+
getReleases(e, response.url, &d.Releases)
37+
}
3238
json.Unmarshal(response.body, &d)
3339
data = append(data, d)
3440
}
@@ -43,6 +49,7 @@ func (e *Exporter) gatherData() ([]*Datum, *RateLimits, error) {
4349
log.Errorf("Unable to obtain rate limit data from API, Error: %s", err)
4450
}
4551

52+
4653
//return data, rates, err
4754
return data, rates, nil
4855

@@ -92,6 +99,19 @@ func getRates(baseURL string, token string) (*RateLimits, error) {
9299

93100
}
94101

102+
func getReleases(e *Exporter, url string, data *[]Release) {
103+
i := strings.Index(url, "?")
104+
baseURL := url[:i]
105+
releasesURL := baseURL + "/releases"
106+
releasesResponse, err := asyncHTTPGets([]string{releasesURL}, e.APIToken)
107+
108+
if err != nil {
109+
log.Errorf("Unable to obtain releases from API, Error: %s", err)
110+
}
111+
112+
json.Unmarshal(releasesResponse[0].body, &data)
113+
}
114+
95115
// isArray simply looks for key details that determine if the JSON response is an array or not.
96116
func isArray(body []byte) bool {
97117

exporter/metrics.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package exporter
33
import "github.com/prometheus/client_golang/prometheus"
44
import "strconv"
55

6+
67
// AddMetrics - Add's all of the metrics to a map of strings, returns the map.
78
func AddMetrics() map[string]*prometheus.Desc {
89

@@ -33,6 +34,11 @@ func AddMetrics() map[string]*prometheus.Desc {
3334
"Size in KB for given repository",
3435
[]string{"repo", "user", "private", "fork", "archived", "license", "language"}, nil,
3536
)
37+
APIMetrics["ReleaseDownloads"] = prometheus.NewDesc(
38+
prometheus.BuildFQName("github", "repo", "release_downloads"),
39+
"Download count for a given release",
40+
[]string{"repo", "user", "release", "name", "created_at"}, nil,
41+
)
3642
APIMetrics["Limit"] = prometheus.NewDesc(
3743
prometheus.BuildFQName("github", "rate", "limit"),
3844
"Number of API queries allowed in a 60 minute window",
@@ -63,6 +69,11 @@ func (e *Exporter) processMetrics(data []*Datum, rates *RateLimits, ch chan<- pr
6369
ch <- prometheus.MustNewConstMetric(e.APIMetrics["Watchers"], prometheus.GaugeValue, x.Watchers, x.Name, x.Owner.Login, strconv.FormatBool(x.Private), strconv.FormatBool(x.Fork), strconv.FormatBool(x.Archived), x.License.Key, x.Language)
6470
ch <- prometheus.MustNewConstMetric(e.APIMetrics["Size"], prometheus.GaugeValue, x.Size, x.Name, x.Owner.Login, strconv.FormatBool(x.Private), strconv.FormatBool(x.Fork), strconv.FormatBool(x.Archived), x.License.Key, x.Language)
6571

72+
for _, release := range x.Releases {
73+
for _, asset := range release.Assets {
74+
ch <- prometheus.MustNewConstMetric(e.APIMetrics["ReleaseDownloads"], prometheus.GaugeValue, float64(asset.Downloads), x.Name, x.Owner.Login, release.Name, asset.Name, asset.CreatedAt)
75+
}
76+
}
6677
}
6778

6879
// Set Rate limit stats

exporter/structs.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,28 @@ type Datum struct {
2828
License struct {
2929
Key string `json:"key"`
3030
} `json:"license"`
31-
Language string `json:"language"`
32-
Archived bool `json:"archived"`
33-
Private bool `json:"private"`
34-
Fork bool `json:"fork"`
35-
Forks float64 `json:"forks"`
36-
Stars float64 `json:"stargazers_count"`
37-
OpenIssues float64 `json:"open_issues"`
38-
Watchers float64 `json:"subscribers_count"`
39-
Size float64 `json:"size"`
31+
Language string `json:"language"`
32+
Archived bool `json:"archived"`
33+
Private bool `json:"private"`
34+
Fork bool `json:"fork"`
35+
Forks float64 `json:"forks"`
36+
Stars float64 `json:"stargazers_count"`
37+
OpenIssues float64 `json:"open_issues"`
38+
Watchers float64 `json:"subscribers_count"`
39+
Size float64 `json:"size"`
40+
Releases []Release
41+
}
42+
43+
type Release struct {
44+
Name string `json:"name"`
45+
Assets []Asset `json:"assets"`
46+
}
47+
48+
type Asset struct {
49+
Name string `json:"name"`
50+
Size int64 `json:"size"`
51+
Downloads int32 `json:"download_count"`
52+
CreatedAt string `json:"created_at"`
4053
}
4154

4255
// RateLimits is used to store rate limit data into a struct

main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/infinityworks/github-exporter/exporter"
99
"github.com/infinityworks/go-common/logger"
1010
"github.com/prometheus/client_golang/prometheus"
11+
"github.com/prometheus/client_golang/prometheus/promhttp"
1112
"github.com/sirupsen/logrus"
1213
)
1314

@@ -37,7 +38,7 @@ func main() {
3738
prometheus.MustRegister(&exporter)
3839

3940
// Setup HTTP handler
40-
http.Handle(applicationCfg.MetricsPath(), prometheus.Handler())
41+
http.Handle(applicationCfg.MetricsPath(), promhttp.Handler())
4142
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
4243
w.Write([]byte(`<html>
4344
<head><title>Github Exporter</title></head>

0 commit comments

Comments
 (0)