Add metrics to get issues by label (#17201)

* Add metrics to get issues by label

* Add comment on IssueByLabelCount

* Code review - Unify "AS" in SQL (#17201)

* Code review - Remove useless join (#17201)

* Code review - Disable issue_by_label by default in settings (#17201)

* use e

* restore empty line

* update docs

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: techknowlogick <matti@mdranta.net>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
Romain 2021-10-04 00:46:44 +02:00 committed by GitHub
parent 89ddbe9699
commit fc5ee1edf9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 5 deletions

View file

@ -2041,6 +2041,8 @@ PATH =
;ENABLED = false ;ENABLED = false
;; If you want to add authorization, specify a token here ;; If you want to add authorization, specify a token here
;TOKEN = ;TOKEN =
;; Enable issue by label metrics; default is false
;ENABLED_ISSUE_BY_LABEL = false
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -853,6 +853,7 @@ NB: You must have `DISABLE_ROUTER_LOG` set to `false` for this option to take ef
## Metrics (`metrics`) ## Metrics (`metrics`)
- `ENABLED`: **false**: Enables /metrics endpoint for prometheus. - `ENABLED`: **false**: Enables /metrics endpoint for prometheus.
- `ENABLED_ISSUE_BY_LABEL`: **false**: Enable issue by label metrics
- `TOKEN`: **\<empty\>**: You need to specify the token, if you want to include in the authorization the metrics . The same token need to be used in prometheus parameters `bearer_token` or `bearer_token_file`. - `TOKEN`: **\<empty\>**: You need to specify the token, if you want to include in the authorization the metrics . The same token need to be used in prometheus parameters `bearer_token` or `bearer_token_file`.
## API (`api`) ## API (`api`)

View file

@ -7,6 +7,7 @@ package models
import ( import (
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/login" "code.gitea.io/gitea/models/login"
"code.gitea.io/gitea/modules/setting"
) )
// Statistic contains the database statistics // Statistic contains the database statistics
@ -20,9 +21,16 @@ type Statistic struct {
Milestone, Label, HookTask, Milestone, Label, HookTask,
Team, UpdateTask, Project, Team, UpdateTask, Project,
ProjectBoard, Attachment int64 ProjectBoard, Attachment int64
IssueByLabel []IssueByLabelCount
} }
} }
// IssueByLabelCount contains the number of issue group by label
type IssueByLabelCount struct {
Count int64
Label string
}
// GetStatistic returns the database statistics // GetStatistic returns the database statistics
func GetStatistic() (stats Statistic) { func GetStatistic() (stats Statistic) {
e := db.GetEngine(db.DefaultContext) e := db.GetEngine(db.DefaultContext)
@ -39,6 +47,17 @@ func GetStatistic() (stats Statistic) {
Count int64 Count int64
IsClosed bool IsClosed bool
} }
if setting.Metrics.EnabledIssueByLabel {
stats.Counter.IssueByLabel = []IssueByLabelCount{}
_ = e.Select("COUNT(*) AS count, l.name AS label").
Join("LEFT", "label l", "l.id=il.label_id").
Table("issue_label il").
GroupBy("l.name").
Find(&stats.Counter.IssueByLabel)
}
issueCounts := []IssueCount{} issueCounts := []IssueCount{}
_ = e.Select("COUNT(*) AS count, is_closed").Table("issue").GroupBy("is_closed").Find(&issueCounts) _ = e.Select("COUNT(*) AS count, is_closed").Table("issue").GroupBy("is_closed").Find(&issueCounts)

View file

@ -24,6 +24,7 @@ type Collector struct {
Issues *prometheus.Desc Issues *prometheus.Desc
IssuesOpen *prometheus.Desc IssuesOpen *prometheus.Desc
IssuesClosed *prometheus.Desc IssuesClosed *prometheus.Desc
IssuesByLabel *prometheus.Desc
Labels *prometheus.Desc Labels *prometheus.Desc
LoginSources *prometheus.Desc LoginSources *prometheus.Desc
Milestones *prometheus.Desc Milestones *prometheus.Desc
@ -45,6 +46,7 @@ type Collector struct {
// NewCollector returns a new Collector with all prometheus.Desc initialized // NewCollector returns a new Collector with all prometheus.Desc initialized
func NewCollector() Collector { func NewCollector() Collector {
return Collector{ return Collector{
Accesses: prometheus.NewDesc( Accesses: prometheus.NewDesc(
namespace+"accesses", namespace+"accesses",
@ -81,6 +83,11 @@ func NewCollector() Collector {
"Number of Issues", "Number of Issues",
nil, nil, nil, nil,
), ),
IssuesByLabel: prometheus.NewDesc(
namespace+"issues_by_label",
"Number of Issues",
[]string{"label"}, nil,
),
IssuesOpen: prometheus.NewDesc( IssuesOpen: prometheus.NewDesc(
namespace+"issues_open", namespace+"issues_open",
"Number of open Issues", "Number of open Issues",
@ -177,7 +184,6 @@ func NewCollector() Collector {
nil, nil, nil, nil,
), ),
} }
} }
// Describe returns all possible prometheus.Desc // Describe returns all possible prometheus.Desc
@ -189,6 +195,7 @@ func (c Collector) Describe(ch chan<- *prometheus.Desc) {
ch <- c.Follows ch <- c.Follows
ch <- c.HookTasks ch <- c.HookTasks
ch <- c.Issues ch <- c.Issues
ch <- c.IssuesByLabel
ch <- c.IssuesOpen ch <- c.IssuesOpen
ch <- c.IssuesClosed ch <- c.IssuesClosed
ch <- c.Labels ch <- c.Labels
@ -249,6 +256,14 @@ func (c Collector) Collect(ch chan<- prometheus.Metric) {
prometheus.GaugeValue, prometheus.GaugeValue,
float64(stats.Counter.Issue), float64(stats.Counter.Issue),
) )
for _, il := range stats.Counter.IssueByLabel {
ch <- prometheus.MustNewConstMetric(
c.IssuesByLabel,
prometheus.GaugeValue,
float64(il.Count),
il.Label,
)
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.IssuesClosed, c.IssuesClosed,
prometheus.GaugeValue, prometheus.GaugeValue,

View file

@ -390,11 +390,13 @@ var (
// Metrics settings // Metrics settings
Metrics = struct { Metrics = struct {
Enabled bool Enabled bool
Token string Token string
EnabledIssueByLabel bool
}{ }{
Enabled: false, Enabled: false,
Token: "", Token: "",
EnabledIssueByLabel: false,
} }
// I18n settings // I18n settings