openreplay/backend/cmd/canvases/main.go
Alexander 3b3e95a413
Observability upgrade (#3146)
* feat(metrics): grand update

* feat(metrics): fixed missing part in ee tracer

* feat(assets): added missing arg

* feat(metrics): fixed naming problems
2025-03-13 08:09:29 +01:00

129 lines
3.4 KiB
Go

package main
import (
"context"
"os"
"os/signal"
"strings"
"syscall"
"time"
"openreplay/backend/internal/canvases"
config "openreplay/backend/internal/config/canvases"
"openreplay/backend/pkg/logger"
"openreplay/backend/pkg/messages"
"openreplay/backend/pkg/metrics"
canvasesMetrics "openreplay/backend/pkg/metrics/canvas"
"openreplay/backend/pkg/objectstorage/store"
"openreplay/backend/pkg/queue"
)
func main() {
ctx := context.Background()
log := logger.New()
cfg := config.New(log)
// Observability
canvasMetrics := canvasesMetrics.New("canvases")
metrics.New(log, canvasMetrics.List())
objStore, err := store.NewStore(&cfg.ObjectsConfig)
if err != nil {
log.Fatal(ctx, "can't init object storage: %s", err)
}
producer := queue.NewProducer(cfg.MessageSizeLimit, true)
defer producer.Close(15000)
srv, err := canvases.New(cfg, log, objStore, producer, canvasMetrics)
if err != nil {
log.Fatal(ctx, "can't init canvases service: %s", err)
}
canvasConsumer := queue.NewConsumer(
cfg.GroupCanvasImage,
[]string{
cfg.TopicCanvasImages,
cfg.TopicCanvasTrigger,
},
messages.NewImagesMessageIterator(func(data []byte, sessID uint64) {
isSessionEnd := func(data []byte) bool {
reader := messages.NewBytesReader(data)
msgType, err := reader.ReadUint()
if err != nil {
return false
}
if msgType != messages.MsgSessionEnd {
return false
}
_, err = messages.ReadMessage(msgType, reader)
if err != nil {
return false
}
return true
}
isTriggerEvent := func(data []byte) (string, string, bool) {
reader := messages.NewBytesReader(data)
msgType, err := reader.ReadUint()
if err != nil {
return "", "", false
}
if msgType != messages.MsgCustomEvent {
return "", "", false
}
msg, err := messages.ReadMessage(msgType, reader)
if err != nil {
return "", "", false
}
customEvent := msg.(*messages.CustomEvent)
return customEvent.Payload, customEvent.Name, true
}
sessCtx := context.WithValue(context.Background(), "sessionID", sessID)
if isSessionEnd(data) {
if err := srv.PrepareSessionCanvases(sessCtx, sessID); err != nil {
if !strings.Contains(err.Error(), "no such file or directory") {
log.Error(sessCtx, "can't pack session's canvases: %s", err)
}
}
} else if path, name, ok := isTriggerEvent(data); ok {
if err := srv.ProcessSessionCanvas(sessCtx, sessID, path, name); err != nil {
log.Error(sessCtx, "can't process session's canvas: %s", err)
}
} else {
if err := srv.SaveCanvasToDisk(sessCtx, sessID, data); err != nil {
log.Error(sessCtx, "can't process canvas image: %s", err)
}
}
}, nil, true),
false,
cfg.MessageSizeLimit,
)
log.Info(ctx, "canvases service started")
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM)
counterTick := time.Tick(time.Second * 30)
for {
select {
case sig := <-sigchan:
log.Info(ctx, "caught signal %v: terminating", sig)
srv.Wait()
canvasConsumer.Close()
os.Exit(0)
case <-counterTick:
srv.Wait()
if err := canvasConsumer.Commit(); err != nil {
log.Error(ctx, "can't commit messages: %s", err)
}
case msg := <-canvasConsumer.Rebalanced():
log.Info(ctx, "consumer group rebalanced: %+v", msg)
default:
err = canvasConsumer.ConsumeNext()
if err != nil {
log.Fatal(ctx, "can't consume next message: %s", err)
}
}
}
}