diff --git a/backend/TODO b/backend/TODO index e1e51ae..23996d6 100644 --- a/backend/TODO +++ b/backend/TODO @@ -1 +1,2 @@ -* implement a way to store current unsolved puzzle \ No newline at end of file +* implement a way to store current unsolved puzzle +* check that solved api call uuid is found in the seen list \ No newline at end of file diff --git a/backend/TODO1 b/backend/TODO1 deleted file mode 100644 index 2485806..0000000 --- a/backend/TODO1 +++ /dev/null @@ -1,21 +0,0 @@ -/solved?cid=44-44-444&pid=1234&sh=okokokokkokkookok -1) check the hash received against the ramstore -2) hit mongo with uuid and add it to set - -/seen?cid=44-44-444&pid=1234 -1) directly hit mongo with uuid and store it as a set - -/load -1) set pid to ramstore and calculate hash - - -hash equation: -exp : d5f7, h1h4, a8g2 [arr] - 5*7 + 1*4 + 8*2 = 55 [uniq] - 123455d5f7h1h4a8g2 [pid][uniq][arr] - db2bea72fe15509fe830982d9b057f2b4a873b6714e45d5d6430707e24ebc7c3 [hash SHA256] - - -the ramstore: -key: pid, value: hash - diff --git a/backend/go.mod b/backend/go.mod index a5a4d07..4fa5b29 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -9,15 +9,24 @@ require ( require ( github.com/ahmed-debbech/go_chess_puzzle v0.0.0-20241227112814-7e4e3e6b89a8 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/klauspost/compress v1.13.6 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/montanaflynn/stats v0.7.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/notnil/chess v1.9.0 // indirect + github.com/prometheus/client_golang v1.20.5 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect golang.org/x/crypto v0.26.0 // indirect golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.23.0 // indirect golang.org/x/text v0.17.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index bbe99df..30e9a31 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -7,14 +7,30 @@ github.com/ahmed-debbech/go_chess_puzzle/generator v0.0.0-20250103134145-8e8a8af github.com/ahmed-debbech/go_chess_puzzle/generator v0.0.0-20250109214724-6b0c7875d733 h1:IPoZo5TpbPFc3/gGnyJzyx7B8GwcdTPK71vpS0rh4YM= github.com/ahmed-debbech/go_chess_puzzle/generator v0.0.0-20250109214724-6b0c7875d733/go.mod h1:h7rdtIN/l62JTh9v0VGX+l62NmKpOceGWZcgNeTUbn0= github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/notnil/chess v1.9.0 h1:YMxR5kUVjtwcuFptGU0/3q7eG3MSHQNbg0VUekvRKV0= github.com/notnil/chess v1.9.0/go.mod h1:cRuJUIBFq9Xki05TWHJxHYkC+fFpq45IWwk94DdlCrA= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= @@ -43,6 +59,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -55,3 +73,5 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/backend/logic/puzzles.go b/backend/logic/puzzles.go index 29cf765..c5c5c93 100644 --- a/backend/logic/puzzles.go +++ b/backend/logic/puzzles.go @@ -3,6 +3,7 @@ package logic import ( "errors" "github.com/ahmed-debbech/go_chess_puzzle/backend/mongo" + "github.com/ahmed-debbech/go_chess_puzzle/backend/prometheus" ) @@ -12,6 +13,7 @@ func GetRandomPuzzle() (*PuzzleDto, error){ return &PuzzleDto{}, errors.New("Could not find a random puzzle.") } pdto := fromPuzzleDao(dat) + go prometheus.Publish("load") return pdto, nil } @@ -25,8 +27,10 @@ func PuzzleToJson(puzzle PuzzleDto) ([]byte, error){ func IncrementSolvedCounter(puzzleId string) { mongo.IncrementSolved(puzzleId) + go prometheus.Publish("solved") } func MarkPuzzleAsSeen(pid string, uuid string){ mongo.MarkAsSeen(pid, uuid) + go prometheus.Publish("seen") } \ No newline at end of file diff --git a/backend/main.go b/backend/main.go index c059ad7..2e72123 100644 --- a/backend/main.go +++ b/backend/main.go @@ -7,9 +7,12 @@ import ( "io/fs" _"time" "errors" + "log" "github.com/ahmed-debbech/go_chess_puzzle/backend/logic" "github.com/ahmed-debbech/go_chess_puzzle/backend/ramstore" + "github.com/ahmed-debbech/go_chess_puzzle/backend/prometheus" + ) //go:embed views/*.html @@ -95,9 +98,17 @@ func seenHandler(w http.ResponseWriter, r *http.Request) { } func rootHandle(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" { + w.WriteHeader(http.StatusNotFound) + p := loadPage("404.html") + fmt.Fprintf(w, string(p.Body)) + return + } + p := loadPage("index.html") if p == nil { return } + go prometheus.Publish("root") fmt.Fprintln(w,string(p.Body)) } @@ -106,7 +117,6 @@ func main(){ fmt.Println("Hello world") logic.ConnectDb() - defer logic.StopDb() staticFiles, _ := fs.Sub(assets, "views/assets") @@ -122,5 +132,11 @@ func main(){ http.HandleFunc("/solved", solvedHandler) http.HandleFunc("/seen", seenHandler) - fmt.Println(http.ListenAndServe(":5530", nil)) + go func() { + log.Fatal(http.ListenAndServe(":5530", nil)) + }() + go func() { + log.Fatal(prometheus.BuildServer()) + }() + for {} } \ No newline at end of file diff --git a/backend/prometheus/exporter.go b/backend/prometheus/exporter.go new file mode 100644 index 0000000..0894e9b --- /dev/null +++ b/backend/prometheus/exporter.go @@ -0,0 +1,87 @@ +package prometheus + +import ( + "net/http" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +var ( + totalRequests = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "backend_total_hits", + Help: "Number of get requests to /", + }, + []string{"value"}, + ) + totalLoad = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "backend_total_load", + Help: "Number of get requests to /load that get puzzle from MongoDb", + }, + []string{"value"}, + ) + totalSeen = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "backend_total_seen", + Help: "Number of seen on puzzles", + }, + []string{"value"}, + ) + totalSolved = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "backend_total_solved", + Help: "Number of people solved the puzles", + }, + []string{"value"}, + ) +) + +var ( + root = make(chan int, 1000) + load = make(chan int, 1000) + seen = make(chan int, 1000) + solved = make(chan int, 1000) +) + +func Publish(ack_type string){ + switch ack_type { + case "root": + root <- 1 + case "load": + load <- 1 + case "seen": + seen <- 1 + case "solved": + solved <- 1 + } +} + +func ExecLoop(){ + for{ + select { + case _= <- root: + totalRequests.WithLabelValues("value").Inc() + case _= <- load: + totalLoad.WithLabelValues("value").Inc() + case _= <- seen: + totalSeen.WithLabelValues("value").Inc() + case _= <- solved: + totalSolved.WithLabelValues("value").Inc() + } + } +} + +func BuildServer() error{ + + prometheus.MustRegister(totalRequests) + prometheus.MustRegister(totalLoad) + prometheus.MustRegister(totalSeen) + prometheus.MustRegister(totalSolved) + + go ExecLoop() + + http.Handle("/metrics", promhttp.Handler()) + return http.ListenAndServe("localhost:22211", nil) +} \ No newline at end of file diff --git a/backend/views/404.html b/backend/views/404.html new file mode 100644 index 0000000..0945d37 --- /dev/null +++ b/backend/views/404.html @@ -0,0 +1,77 @@ + + +
+ + +