mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	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:
		@@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
					;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
					;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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`)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user