mirror of https://github.com/goharbor/harbor.git
177 lines
5.4 KiB
Go
177 lines
5.4 KiB
Go
// Copyright Project Harbor Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package exporter
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
"github.com/goharbor/harbor/src/controller/blob"
|
|
"github.com/goharbor/harbor/src/controller/project"
|
|
"github.com/goharbor/harbor/src/controller/repository"
|
|
"github.com/goharbor/harbor/src/lib/log"
|
|
"github.com/goharbor/harbor/src/lib/orm"
|
|
"github.com/goharbor/harbor/src/lib/q"
|
|
"github.com/goharbor/harbor/src/pkg/systemartifact"
|
|
)
|
|
|
|
const StatisticsCollectorName = "StatisticsCollector"
|
|
|
|
var (
|
|
totalUsage = typedDesc{
|
|
desc: newDescWithLables("", "statistics_total_storage_consumption", "Total storage used"),
|
|
valueType: prometheus.GaugeValue,
|
|
}
|
|
totalProjectAmount = typedDesc{
|
|
desc: newDescWithLables("", "statistics_total_project_amount", "Total amount of projects"),
|
|
valueType: prometheus.GaugeValue,
|
|
}
|
|
publicProjectAmount = typedDesc{
|
|
desc: newDescWithLables("", "statistics_public_project_amount", "Amount of public projects"),
|
|
valueType: prometheus.GaugeValue,
|
|
}
|
|
privateProjectAmount = typedDesc{
|
|
desc: newDescWithLables("", "statistics_private_project_amount", "Amount of private projects"),
|
|
valueType: prometheus.GaugeValue,
|
|
}
|
|
totalRepoAmount = typedDesc{
|
|
desc: newDescWithLables("", "statistics_total_repo_amount", "Total amount of repositories"),
|
|
valueType: prometheus.GaugeValue,
|
|
}
|
|
publicRepoAmount = typedDesc{
|
|
desc: newDescWithLables("", "statistics_public_repo_amount", "Amount of public repositories"),
|
|
valueType: prometheus.GaugeValue,
|
|
}
|
|
privateRepoAmount = typedDesc{
|
|
desc: newDescWithLables("", "statistics_private_repo_amount", "Amount of private repositories"),
|
|
valueType: prometheus.GaugeValue,
|
|
}
|
|
)
|
|
|
|
type StatisticsCollector struct {
|
|
proCtl project.Controller
|
|
repoCtl repository.Controller
|
|
blobCtl blob.Controller
|
|
systemArtifactMgr systemartifact.Manager
|
|
}
|
|
|
|
func NewStatisticsCollector() *StatisticsCollector {
|
|
return &StatisticsCollector{
|
|
blobCtl: blob.Ctl,
|
|
systemArtifactMgr: systemartifact.Mgr,
|
|
proCtl: project.Ctl,
|
|
repoCtl: repository.Ctl,
|
|
}
|
|
}
|
|
|
|
func (g StatisticsCollector) GetName() string {
|
|
return StatisticsCollectorName
|
|
}
|
|
|
|
func (g StatisticsCollector) Describe(c chan<- *prometheus.Desc) {
|
|
c <- totalUsage.Desc()
|
|
}
|
|
|
|
func (g StatisticsCollector) getTotalUsageMetric(ctx context.Context) prometheus.Metric {
|
|
sum, _ := g.blobCtl.CalculateTotalSize(ctx, true)
|
|
sysArtifactStorageSize, _ := g.systemArtifactMgr.GetStorageSize(ctx)
|
|
return totalUsage.MustNewConstMetric(float64(sum + sysArtifactStorageSize))
|
|
}
|
|
|
|
func (g StatisticsCollector) getTotalRepoAmount(ctx context.Context) int64 {
|
|
n, err := g.repoCtl.Count(ctx, nil)
|
|
if err != nil {
|
|
log.Errorf("get total repositories error: %v", err)
|
|
return 0
|
|
}
|
|
return n
|
|
}
|
|
|
|
func (g StatisticsCollector) getTotalProjectsAmount(ctx context.Context) int64 {
|
|
count, err := g.proCtl.Count(ctx, nil)
|
|
if err != nil {
|
|
log.Errorf("get total projects error: %v", err)
|
|
return 0
|
|
}
|
|
return count
|
|
}
|
|
|
|
func (g StatisticsCollector) getPublicProjectsAndRepositories(ctx context.Context) (int64, int64) {
|
|
pubProjects, err := g.proCtl.List(ctx, q.New(q.KeyWords{"public": true}), project.Metadata(false))
|
|
if err != nil {
|
|
log.Errorf("get public projects error: %v", err)
|
|
}
|
|
pubProjectsAmount := int64(len(pubProjects))
|
|
|
|
if pubProjectsAmount == 0 {
|
|
return pubProjectsAmount, 0
|
|
}
|
|
var ids []interface{}
|
|
for _, p := range pubProjects {
|
|
ids = append(ids, p.ProjectID)
|
|
}
|
|
n, err := g.repoCtl.Count(ctx, &q.Query{
|
|
Keywords: map[string]interface{}{
|
|
"ProjectID": q.NewOrList(ids),
|
|
},
|
|
})
|
|
if err != nil {
|
|
log.Errorf("get public repo error: %v", err)
|
|
return pubProjectsAmount, 0
|
|
}
|
|
return pubProjectsAmount, n
|
|
}
|
|
|
|
// Collect implements prometheus.Collector
|
|
func (g StatisticsCollector) Collect(c chan<- prometheus.Metric) {
|
|
for _, m := range g.getStatistics() {
|
|
c <- m
|
|
}
|
|
}
|
|
|
|
func (g StatisticsCollector) getStatistics() []prometheus.Metric {
|
|
if CacheEnabled() {
|
|
value, ok := CacheGet(StatisticsCollectorName)
|
|
if ok {
|
|
return value.([]prometheus.Metric)
|
|
}
|
|
}
|
|
var (
|
|
result []prometheus.Metric
|
|
ctx = orm.Context()
|
|
)
|
|
|
|
var (
|
|
publicProjects, publicRepos = g.getPublicProjectsAndRepositories(ctx)
|
|
totalProjects = g.getTotalProjectsAmount(ctx)
|
|
totalRepos = g.getTotalRepoAmount(ctx)
|
|
)
|
|
|
|
result = []prometheus.Metric{
|
|
totalRepoAmount.MustNewConstMetric(float64(totalRepos)),
|
|
publicRepoAmount.MustNewConstMetric(float64(publicRepos)),
|
|
privateRepoAmount.MustNewConstMetric(float64(totalRepos) - float64(publicRepos)),
|
|
totalProjectAmount.MustNewConstMetric(float64(totalProjects)),
|
|
publicProjectAmount.MustNewConstMetric(float64(publicProjects)),
|
|
privateProjectAmount.MustNewConstMetric(float64(totalProjects) - float64(publicProjects)),
|
|
g.getTotalUsageMetric(ctx),
|
|
}
|
|
if CacheEnabled() {
|
|
CachePut(StatisticsCollectorName, result)
|
|
}
|
|
return result
|
|
}
|