Skip to content

Commit 34fa870

Browse files
authored
Merge pull request #14 from d-Rickyy-b/prometheus
Implement prometheus support
2 parents e1f48de + dd20ea1 commit 34fa870

10 files changed

Lines changed: 136 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
### Added
10+
### Changed
11+
### Fixed
12+
### Docs
13+
14+
## [1.1.0] - 2022-03-28
15+
16+
### Added
17+
- Support for prometheus database
18+
19+
## [1.0.0] - 2022-02-14
20+
Initial release! First stable version of GoGeizhalsBot is published as v1.0.0
21+
22+
[unreleased]: https://github.com/d-Rickyy-b/GoGeizhalsBot/compare/v1.1.0...HEAD
23+
[1.1.0]: https://github.com/d-Rickyy-b/GoGeizhalsBot/compare/v1.0.0...v1.1.0
24+
[1.0.0]: https://github.com/d-Rickyy-b/GoGeizhalsBot/tree/v1.0.0

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.16
55
require (
66
github.com/PaulSonOfLars/gotgbot/v2 v2.0.0-rc.4
77
github.com/PuerkitoBio/goquery v1.8.0
8+
github.com/VictoriaMetrics/metrics v1.18.1
89
github.com/davecgh/go-spew v1.1.1 // indirect
910
github.com/glebarez/sqlite v1.3.3
1011
github.com/jinzhu/now v1.1.4 // indirect

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ github.com/PaulSonOfLars/gotgbot/v2 v2.0.0-rc.4 h1:1hKv9DvEwn//VsJgcCGt9+IAq4n+P
22
github.com/PaulSonOfLars/gotgbot/v2 v2.0.0-rc.4/go.mod h1:r815fYWTudnU9JhtsJAxUtuV7QrSgKpChJkfTSMFpfg=
33
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
44
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
5+
github.com/VictoriaMetrics/metrics v1.18.1 h1:OZ0+kTTto8oPfHnVAnTOoyl0XlRhRkoQrD2n2cOuRw0=
6+
github.com/VictoriaMetrics/metrics v1.18.1/go.mod h1:ArjwVz7WpgpegX/JpB0zpNF2h2232kErkEnzH1sxMmA=
57
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
68
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
79
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -33,6 +35,10 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qq
3335
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
3436
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
3537
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
38+
github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8=
39+
github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
40+
github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ=
41+
github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY=
3642
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
3743
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
3844
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

internal/bot/bot.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import (
66
"GoGeizhalsBot/internal/config"
77
"GoGeizhalsBot/internal/database"
88
"GoGeizhalsBot/internal/geizhals"
9+
"GoGeizhalsBot/internal/prometheus"
910
"fmt"
1011
"log"
1112
"net/http"
1213
"net/url"
14+
"time"
1315

1416
"github.com/PaulSonOfLars/gotgbot/v2/ext/handlers/filters/message"
1517

@@ -218,6 +220,7 @@ func showPriceagentDetail(b *gotgbot.Bot, ctx *ext.Context) error {
218220
},
219221
}
220222

223+
// Check if the initial message contained a photo, if yes, we're coming from the price history graph
221224
if len(cb.Message.Photo) > 0 {
222225
bot.DeleteMessage(ctx.EffectiveChat.Id, cb.Message.MessageId)
223226

@@ -344,6 +347,7 @@ func deletePriceagentHandler(b *gotgbot.Bot, ctx *ext.Context) error {
344347
}
345348

346349
func newUserHandler(_ *gotgbot.Bot, ctx *ext.Context) error {
350+
prometheus.TotalUserInteractions.Inc()
347351
// Create user in databse if they don't exist already
348352
if !ctx.EffectiveSender.IsUser() {
349353
return nil
@@ -480,5 +484,22 @@ func Start(botConfig config.Config) {
480484

481485
log.Printf("Bot has been started as @%s...\n", bot.User.Username)
482486

487+
if botConfig.Prometheus.Enabled {
488+
// Periodically update the metrics from the database
489+
go func() {
490+
for {
491+
prometheus.TotalUniquePriceagentsValue = database.GetPriceAgentCount()
492+
prometheus.TotalUniqueUsersValue = database.GetUserCount()
493+
prometheus.TotalUniqueWishlistPriceagentsValue = database.GetPriceAgentWishlistCount()
494+
prometheus.TotalUniqueProductPriceagentsValue = database.GetPriceAgentProductCount()
495+
time.Sleep(time.Second * 60)
496+
}
497+
}()
498+
499+
exportAddr := fmt.Sprintf("%s:%d", botConfig.Prometheus.ExportIP, botConfig.Prometheus.ExportPort)
500+
log.Printf("Starting prometheus exporter on %s...\n", exportAddr)
501+
prometheus.StartPrometheusExporter(exportAddr)
502+
}
503+
483504
updater.Idle()
484505
}

internal/bot/notification.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"GoGeizhalsBot/internal/bot/models"
55
"GoGeizhalsBot/internal/database"
66
"GoGeizhalsBot/internal/geizhals"
7+
"GoGeizhalsBot/internal/prometheus"
78
"fmt"
89
"log"
910
"time"
@@ -23,7 +24,7 @@ func updateEntityPrices() {
2324
// For each price agent, update prices and store updated prices in the entity in the database.
2425
// Also update price history with the new prices.
2526
for _, entity := range allEntities {
26-
log.Println("Updating prices for:", entity.Name)
27+
log.Println("Updating prices for:", entity.URL)
2728

2829
// If there are two price agents with the same entity, we currently fetch it twice
2930
updatedEntity, updateErr := geizhals.UpdateEntity(entity)
@@ -84,6 +85,7 @@ func notifyUsers(priceAgent models.PriceAgent, oldEntity, updatedEntity geizhals
8485
}
8586

8687
log.Println("Sending notification to user:", user.ID)
88+
prometheus.PriceagentNotifications.Inc()
8789

8890
markup := gotgbot.InlineKeyboardMarkup{
8991
InlineKeyboard: [][]gotgbot.InlineKeyboardButton{

internal/bot/pricehistory.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"GoGeizhalsBot/internal/bot/models"
55
"GoGeizhalsBot/internal/database"
66
"GoGeizhalsBot/internal/geizhals"
7+
"GoGeizhalsBot/internal/prometheus"
78
"bytes"
89
"fmt"
910
"io"
@@ -145,6 +146,7 @@ func getPriceagentFromContext(ctx *ext.Context) (models.PriceAgent, error) {
145146

146147
// renderChart renders a price history chart to the given writer.
147148
func renderChart(priceagent models.PriceAgent, history geizhals.PriceHistory, since time.Time, w io.Writer) {
149+
prometheus.GraphsRendered.Inc()
148150
darkFontColor := drawing.ColorFromHex("c2c2c2")
149151
fontColor := darkFontColor
150152

internal/bot/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
package bot
22

3-
var version = "1.0.0-dev (compiled manually)"
3+
var version = "1.1.0-dev (compiled manually)"

internal/database/database.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,41 @@ func GetPriceAgentCountForUser(userID int64) int64 {
5353
return count
5454
}
5555

56+
func GetPriceAgentCount() int64 {
57+
var count int64
58+
db.Model(&models.PriceAgent{}).Count(&count)
59+
return count
60+
}
61+
62+
func GetPriceAgentProductCount() int64 {
63+
var count int64
64+
db.Model(&models.PriceAgent{}).Joins("JOIN entities on price_agents.entity_id = entities.id").Where("entities.type = ?", geizhals.Product).Count(&count)
65+
return count
66+
}
67+
68+
func GetPriceAgentWishlistCount() int64 {
69+
var count int64
70+
db.Model(&models.PriceAgent{}).Joins("JOIN entities on price_agents.entity_id = entities.id").Where("entities.type = ?", geizhals.Wishlist).Count(&count)
71+
return count
72+
}
73+
74+
func GetUserCount() int64 {
75+
var count int64
76+
db.Model(&models.User{}).Count(&count)
77+
return count
78+
}
79+
5680
func CreateUser(user models.User) error {
5781
tx := db.Create(&user)
5882
return tx.Error
5983
}
6084

85+
func GetAllUsers() []models.User {
86+
var users []models.User
87+
db.Find(&users)
88+
return users
89+
}
90+
6191
func DeletePriceAgentForUser(priceAgent models.PriceAgent) error {
6292
log.Println("Delete priceagent!")
6393

internal/geizhals/geizhals.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package geizhals
22

33
import (
4+
"GoGeizhalsBot/internal/prometheus"
45
"fmt"
56
"log"
67
"net/http"
@@ -72,9 +73,11 @@ func downloadHTML(entityURL string) (*goquery.Document, int, error) {
7273
log.Println("Using proxy: ", proxyURL)
7374
}
7475

76+
prometheus.GeizhalsHTTPRequests.Inc()
7577
resp, getErr := httpClient.Get(entityURL)
7678
if getErr != nil {
7779
log.Println(getErr)
80+
prometheus.HttpErrors.Inc()
7881
return nil, 0, fmt.Errorf("error while downloading content from Geizhals: %w", getErr)
7982
}
8083
// Cleanup when this function ends

internal/prometheus/prometheus.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package prometheus
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/VictoriaMetrics/metrics"
7+
)
8+
9+
var (
10+
TotalUniqueUsersValue int64
11+
totalUniqueUsers = metrics.NewGauge("gogeizhalsbot_unique_users_total", func() float64 {
12+
return float64(TotalUniqueUsersValue)
13+
})
14+
15+
TotalUniquePriceagentsValue int64
16+
totalUniquePriceagents = metrics.NewGauge("gogeizhalsbot_unique_priceagents", func() float64 {
17+
return float64(TotalUniquePriceagentsValue)
18+
})
19+
20+
TotalUniqueProductPriceagentsValue int64
21+
totalUniqueProductPriceagents = metrics.NewGauge("gogeizhalsbot_unique_priceagents{type=\"product\"}", func() float64 {
22+
return float64(TotalUniqueProductPriceagentsValue)
23+
})
24+
25+
TotalUniqueWishlistPriceagentsValue int64
26+
totalUniqueWishlistPriceagents = metrics.NewGauge("gogeizhalsbot_unique_priceagents{type=\"wishlist\"}", func() float64 {
27+
return float64(TotalUniqueWishlistPriceagentsValue)
28+
})
29+
30+
TotalUserInteractions = metrics.NewCounter("gogeizhalsbot_user_interactions_total")
31+
GeizhalsHTTPRequests = metrics.NewCounter("gogeizhalsbot_geizhals_http_requests_total")
32+
PriceagentNotifications = metrics.NewCounter("gogeizhalsbot_priceagent_notifications_total")
33+
HttpErrors = metrics.NewCounter("gogeizhalsbot_http_errors_total")
34+
GraphsRendered = metrics.NewCounter("gogeizhalsbot_graphs_rendered_total")
35+
)
36+
37+
// var backgroundUpdateChecks = metrics.NewSummary("gogeizhalsbot_total_requests")
38+
39+
func StartPrometheusExporter(addr string) {
40+
// Expose the registered metrics at `/metrics` path.
41+
http.HandleFunc("/metrics", func(w http.ResponseWriter, req *http.Request) {
42+
metrics.WritePrometheus(w, true)
43+
})
44+
http.ListenAndServe(addr, nil)
45+
}

0 commit comments

Comments
 (0)