Use db to store view count

This commit is contained in:
2021-01-23 08:45:22 +11:00
parent 7e38bdf838
commit f47c219513
6 changed files with 114 additions and 30 deletions
+61 -21
View File
@@ -54,7 +54,7 @@ const (
type Metric struct {
Label string
Value float64
Value int
Time time.Time
}
@@ -121,7 +121,7 @@ func (handler *BadgesHandler) generateSVG(c *gin.Context, colorScheme ColorSchem
prometheusOptions := badge.OptionStruct.(*models.PrometheusOptions)
metric, _ := queryMetric(handler.PrometheusAPIClient, prometheusOptions)
metric, _ := handler.queryMetric(badge, handler.PrometheusAPIClient, prometheusOptions)
metricValue := int(metric.Value)
label := metric.Label
@@ -149,7 +149,7 @@ func (handler *BadgesHandler) generateSVG(c *gin.Context, colorScheme ColorSchem
canvas.Rect(0, 0, int(labelContainerWidth), badgeHeight, string(colorScheme))
//when there is metric label then use default label
//when there is a metric label then use default label
if len(prometheusOptions.ValueField) == 0 {
label = badge.Label
}
@@ -247,26 +247,66 @@ func (handler *BadgesHandler) CreateBadge(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"id": newID})
}
func queryMetric(client api.Client, options *models.PrometheusOptions) (*Metric, error) {
v1api := v1.NewAPI(client)
ctx, cancel := context.WithTimeout(context.Background(), metricRequestTimeout)
defer cancel()
result, warnings, err := v1api.Query(ctx, options.Query, time.Now())
func (handler *BadgesHandler) queryMetric(badge *models.Badge, client api.Client, options *models.PrometheusOptions) (*Metric, error) {
viewCount, err := handler.fetchViewCountFromDB(badge)
if err != nil {
sentry.CaptureException(err)
return nil, fmt.Errorf("error querying Prometheus: %w", err)
return nil, err
}
if len(warnings) > 0 {
fmt.Printf("Warnings: %v\n", warnings)
}
var metric Metric
for _, v := range result.(model.Vector) {
metric = Metric{
Label: string(v.Metric[model.LabelName(options.ValueField)]),
Value: float64(v.Value),
Time: v.Timestamp.Time(),
if viewCount.Count == 0 {
v1api := v1.NewAPI(client)
ctx, cancel := context.WithTimeout(context.Background(), metricRequestTimeout)
defer cancel()
result, warnings, err := v1api.Query(ctx, options.Query, time.Now())
if err != nil {
sentry.CaptureException(err)
return nil, fmt.Errorf("error querying Prometheus: %w", err)
}
if len(warnings) > 0 {
logrus.Warnf("Warnings: %v\n", warnings)
}
for _, v := range result.(model.Vector) {
viewCount.Count = int(float64(v.Value))
}
}
return &metric, nil
if err = handler.updateMetric(viewCount); err != nil {
return nil, err
}
return &Metric{
Label: viewCount.BadgeULID,
Value: viewCount.Count,
Time: viewCount.UpdatedAt,
}, nil
}
func (handler *BadgesHandler) fetchViewCountFromDB(badge *models.Badge) (*models.BadgeViewCount, error) {
var viewCount models.BadgeViewCount
err := handler.DB.Find(&viewCount, "ulid = ?", badge.ULID).Error
if err != nil {
if err != gorm.ErrRecordNotFound {
return nil, err
}
logrus.Infof("no db viewcount for %s", badge.ULID)
return &models.BadgeViewCount{
BadgeULID: badge.ULID,
Count: 0,
}, nil
}
return &viewCount, nil
}
func (handler *BadgesHandler) updateMetric(viewCount *models.BadgeViewCount) error {
viewCount.Count++
err := handler.DB.Save(&viewCount).Error
if err != nil {
sentry.CaptureException(err)
logrus.Errorf("failed to update badge %s viewcount %v", viewCount.BadgeULID, err)
return err
}
handler.DB.Save(&models.ViewRecord{ULID: viewCount.BadgeULID})
return nil
}
+6 -1
View File
@@ -55,7 +55,12 @@ func main() {
defer db.Close()
// Migrate the schema
db.AutoMigrate(&models.Badge{}, &models.Token{}, &models.User{})
db.AutoMigrate(
&models.Badge{},
&models.Token{},
&models.User{},
&models.ViewRecord{},
&models.BadgeViewCount{})
client, err := api.NewClient(api.Config{
Address: "https://prometheus-api.home.toozhao.com",
+9
View File
@@ -0,0 +1,9 @@
package models
import "github.com/jinzhu/gorm"
type BadgeViewCount struct {
gorm.Model
BadgeULID string `gorm:"column:ulid;type:varchar;not null;unique_index" json:"ulid"`
Count int `json:"count" gorm:"not null;"`
}
+10
View File
@@ -0,0 +1,10 @@
package models
import (
"github.com/jinzhu/gorm"
)
type ViewRecord struct {
gorm.Model
ULID string `gorm:"column:ulid;type:varchar;not null;" json:"ulid"`
}
+28
View File
@@ -0,0 +1,28 @@
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: apps
name: badger-ops
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["monitoring.coreos.com"]
resources: ["servicemonitors"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: badger-role-binding
namespace: apps
subjects:
- kind: ServiceAccount
name: cd-robot
namespace: apps
roleRef:
kind: Role
name: badger-ops
apiGroup: rbac.authorization.k8s.io
-8
View File
@@ -161,14 +161,6 @@
>
</b-col>
</b-row>
<b-row>
<b-col>
<p class="warnning">
Note: The page view count data may take up to 3 minutes to be
initialized.
</p>
</b-col>
</b-row>
</b-container>
</div>
</template>