From 8e7a8be0de81ad0b89e3e34a5d455b54adf0b0f7 Mon Sep 17 00:00:00 2001 From: whywaita Date: Fri, 6 Dec 2024 01:31:33 +0900 Subject: [PATCH] Add a metrics of GitHub Apps installation --- pkg/gh/installation.go | 56 ++++++++++++++++++++++++++++++++++ pkg/gh/jwt.go | 27 ---------------- pkg/metric/scrape_datastore.go | 14 +++++++++ pkg/metric/scrape_github.go | 38 +++++++++++++++++++++++ 4 files changed, 108 insertions(+), 27 deletions(-) create mode 100644 pkg/gh/installation.go diff --git a/pkg/gh/installation.go b/pkg/gh/installation.go new file mode 100644 index 0000000..5ea5295 --- /dev/null +++ b/pkg/gh/installation.go @@ -0,0 +1,56 @@ +package gh + +import ( + "context" + "fmt" + "time" + + "github.com/google/go-github/v47/github" + "github.com/whywaita/myshoes/pkg/logger" +) + +func listInstallations(ctx context.Context) ([]*github.Installation, error) { + if cachedRs, found := responseCache.Get(getCacheInstallationsKey()); found { + return cachedRs.([]*github.Installation), nil + } + + inst, err := _listInstallations(ctx) + if err != nil { + return nil, fmt.Errorf("failed to list installations: %w", err) + } + + responseCache.Set(getCacheInstallationsKey(), inst, 1*time.Hour) + + return _listInstallations(ctx) +} + +func getCacheInstallationsKey() string { + return "installations" +} + +func _listInstallations(ctx context.Context) ([]*github.Installation, error) { + clientApps, err := NewClientGitHubApps() + if err != nil { + return nil, fmt.Errorf("failed to create a client Apps: %w", err) + } + + var opts = &github.ListOptions{ + Page: 0, + PerPage: 100, + } + + var installations []*github.Installation + for { + logger.Logf(true, "get installations from GitHub, page: %d, now all installations: %d", opts.Page, len(installations)) + is, resp, err := clientApps.Apps.ListInstallations(ctx, opts) + if err != nil { + return nil, fmt.Errorf("failed to list installations: %w", err) + } + installations = append(installations, is...) + if resp.NextPage == 0 { + break + } + opts.Page = resp.NextPage + } + return installations, nil +} diff --git a/pkg/gh/jwt.go b/pkg/gh/jwt.go index 5ca92d9..a0f7c12 100644 --- a/pkg/gh/jwt.go +++ b/pkg/gh/jwt.go @@ -121,30 +121,3 @@ func listAppsInstalledRepo(ctx context.Context, installationID int64) ([]*github return repositories, nil } - -func listInstallations(ctx context.Context) ([]*github.Installation, error) { - clientApps, err := NewClientGitHubApps() - if err != nil { - return nil, fmt.Errorf("failed to create a client Apps: %w", err) - } - - var opts = &github.ListOptions{ - Page: 0, - PerPage: 100, - } - - var installations []*github.Installation - for { - logger.Logf(true, "get installations from GitHub, page: %d, now all installations: %d", opts.Page, len(installations)) - is, resp, err := clientApps.Apps.ListInstallations(ctx, opts) - if err != nil { - return nil, fmt.Errorf("failed to list installations: %w", err) - } - installations = append(installations, is...) - if resp.NextPage == 0 { - break - } - opts.Page = resp.NextPage - } - return installations, nil -} diff --git a/pkg/metric/scrape_datastore.go b/pkg/metric/scrape_datastore.go index 55f6493..a668867 100644 --- a/pkg/metric/scrape_datastore.go +++ b/pkg/metric/scrape_datastore.go @@ -28,6 +28,15 @@ var ( "Number of targets", []string{"resource_type"}, nil, ) + datastoreTargetDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, datastoreName, "target_describe"), + "Target", + []string{ + "target_id", + "scope", + "resource_type", + }, nil, + ) datastoreJobDurationOldest = prometheus.NewDesc( prometheus.BuildFQName(namespace, datastoreName, "job_duration_oldest_seconds"), "Duration time of oldest job", @@ -172,6 +181,11 @@ func scrapeTargets(ctx context.Context, ds datastore.Datastore, ch chan<- promet result := map[string]float64{} // key: resource_type, value: number for _, t := range targets { + ch <- prometheus.MustNewConstMetric( + datastoreTargetDesc, prometheus.GaugeValue, 1, + t.UUID.String(), t.Scope, t.ResourceType.String(), + ) + result[t.ResourceType.String()]++ } for rt, number := range result { diff --git a/pkg/metric/scrape_github.go b/pkg/metric/scrape_github.go index a21b375..67e910e 100644 --- a/pkg/metric/scrape_github.go +++ b/pkg/metric/scrape_github.go @@ -19,6 +19,19 @@ var ( "Number of pending runs", []string{"target_id", "scope"}, nil, ) + githubInstallationDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, githubName, "installation"), + "installations", + []string{ + "installation_id", + "account_login", + "account_type", + "target_type", + "repository_selection", + "html_url", + }, + nil, + ) ) // ScraperGitHub is scraper implement for GitHub @@ -39,6 +52,9 @@ func (s ScraperGitHub) Scrape(ctx context.Context, ds datastore.Datastore, ch ch if err := scrapePendingRuns(ctx, ds, ch); err != nil { return fmt.Errorf("failed to scrape pending runs: %w", err) } + if err := scrapeInstallation(ctx, ch); err != nil { + return fmt.Errorf("failed to scrape installations: %w", err) + } return nil } @@ -80,3 +96,25 @@ func scrapePendingRuns(ctx context.Context, ds datastore.Datastore, ch chan<- pr }) return nil } + +func scrapeInstallation(ctx context.Context, ch chan<- prometheus.Metric) error { + installations, err := gh.GHlistInstallations(ctx) + if err != nil { + return fmt.Errorf("failed to list installations: %w", err) + } + + for _, installation := range installations { + ch <- prometheus.MustNewConstMetric( + githubInstallationDesc, + prometheus.GaugeValue, + 1, + fmt.Sprint(installation.GetID()), + installation.GetAccount().GetLogin(), + installation.GetAccount().GetType(), + installation.GetTargetType(), + installation.GetRepositorySelection(), + installation.GetHTMLURL(), + ) + } + return nil +}