From 11ea0858bba24becb7cb674bf4b83c51d553e17c Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Tue, 17 Dec 2024 16:23:52 +0100 Subject: [PATCH] feat(services): Logging --- main.go | 8 ++++++-- services/barcode.go | 24 ++++++++++++++++++++---- services/converter.go | 24 ++++++++++++++++++++++++ services/templater.go | 6 ++++++ services/templates.go | 23 ++++++++++++++++------- 5 files changed, 72 insertions(+), 13 deletions(-) diff --git a/main.go b/main.go index 2977dc5..df51f4e 100644 --- a/main.go +++ b/main.go @@ -137,9 +137,11 @@ func main() { barcodeGenerator := &services.DefaultBarcodeService{ RedisClient: redisClient, + Logger: logger.Named("DefaultBarcodeService"), } staticService := &services.DefaultStaticService{ - Cache: make(map[string]string), + Cache: make(map[string]string), + Logger: logger.Named("DefaultStaticService"), } handler := handlers.DefaultHandler{ Config: config, @@ -148,11 +150,13 @@ func main() { Templater: &services.DefaultTemplater{ BarcodeService: barcodeGenerator, StaticService: staticService, + Logger: logger.Named("DefaultTemplater"), }, Converter: &services.GotenbergConverter{ BaseUrl: config.GotenbergBaseUrl, + Logger: logger.Named("GotenbergConverter"), }, - Logger: logger, + Logger: logger.Named("DefaultHandler"), } logger.Debug("Initialized services") diff --git a/services/barcode.go b/services/barcode.go index cdcd9d1..d741375 100644 --- a/services/barcode.go +++ b/services/barcode.go @@ -8,7 +8,6 @@ import ( "image/color" "image/draw" "image/png" - "log" "slices" "time" @@ -17,6 +16,7 @@ import ( "github.com/boombuler/barcode/ean" "github.com/boombuler/barcode/qr" "github.com/redis/go-redis/v9" + "go.uber.org/zap" ) type BarcodeService interface { @@ -26,19 +26,26 @@ type BarcodeService interface { type DefaultBarcodeService struct { RedisClient *redis.Client + Logger *zap.SugaredLogger } func (b *DefaultBarcodeService) GenerateBarcode(format string, content string, width int, height int, padding int) (bytes.Buffer, error) { ctx := context.Background() + logger := b.Logger.Named("GenerateBarcode") if !b.IsTypeSupported(format) { + logger.Errorw("Unsupported barcode type", "type", format) return bytes.Buffer{}, fmt.Errorf("unsupported barcode type: %s", format) } + logger = logger.With("type", format, "content", content, "width", width, "height", height, "padding", padding) + cacheKey := fmt.Sprintf("barcode:%s:%s:%d:%d:%d", format, content, width, height, padding) + if b.RedisClient != nil { - cachedBarcode, err := b.RedisClient.Get(ctx, fmt.Sprintf("barcode:%s:%s:%d:%d:%d", format, content, width, height, padding)).Result() + logger.Debugw("Checking cache for barcode", "key", cacheKey) + cachedBarcode, err := b.RedisClient.Get(ctx, cacheKey).Result() if err == nil { - log.Printf("Cache hit for barcode:%s:%s:%d:%d", format, content, width, height) + logger.Infow("Barcode found in cache", "key", cacheKey) buf := bytes.Buffer{} buf.Write([]byte(cachedBarcode)) return buf, nil @@ -73,6 +80,7 @@ func (b *DefaultBarcodeService) GenerateBarcode(format string, content string, w bg := image.NewRGBA(image.Rect(0, 0, width, height)) white := color.RGBA{255, 255, 255, 255} draw.Draw(bg, bg.Bounds(), &image.Uniform{white}, image.Point{}, draw.Src) + logger.Debug("Created white background") // Calculate the new size for the barcode to fit within the padding newWidth := width - 2*padding @@ -81,24 +89,32 @@ func (b *DefaultBarcodeService) GenerateBarcode(format string, content string, w // Scale the barcode to the new size scaledCode, err := barcode.Scale(generatedCode, newWidth, newHeight) if err != nil { + logger.Errorw("Failed to scale barcode", "error", err) return bytes.Buffer{}, err } + logger.Debug("Scaled barcode") // Draw the barcode on top of the white background with padding draw.Draw(bg, scaledCode.Bounds().Add(image.Point{padding, padding}), scaledCode, image.Point{}, draw.Over) + logger.Debug("Drew barcode on background") var buf bytes.Buffer err = png.Encode(&buf, bg) if err != nil { + logger.Errorw("Failed to encode barcode to PNG", "error", err) return bytes.Buffer{}, err } + logger.Debug("Encoded barcode to PNG") if b.RedisClient != nil { - err = b.RedisClient.Set(ctx, fmt.Sprintf("barcode:%s:%s:%d:%d", format, content, width, height), buf.String(), 10*time.Minute).Err() + err = b.RedisClient.Set(ctx, cacheKey, buf.String(), 10*time.Minute).Err() + logger.Debugw("Cached barcode", "key", cacheKey) if err != nil { + logger.Errorw("Failed to cache barcode", "error", err) return bytes.Buffer{}, err } } + logger.Info("Generated barcode") return buf, nil } diff --git a/services/converter.go b/services/converter.go index dd56eda..94e16c4 100644 --- a/services/converter.go +++ b/services/converter.go @@ -8,6 +8,7 @@ import ( "strconv" "github.com/oxplot/papersizes" + "go.uber.org/zap" ) type Converter interface { @@ -16,92 +17,115 @@ type Converter interface { type GotenbergConverter struct { BaseUrl string + Logger *zap.SugaredLogger } func (g *GotenbergConverter) ToPdf(html string, pageSize string, landscape bool) ([]byte, error) { + logger := g.Logger.Named("ToPdf").With("page_size", pageSize, "landscape", landscape, "base_url", g.BaseUrl) + client := &http.Client{} defer client.CloseIdleConnections() + logger.Debug("Created HTTP client") body := &bytes.Buffer{} writer := multipart.NewWriter(body) part, err := writer.CreateFormFile("files", "index.html") if err != nil { + logger.Errorw("Failed to create form file", "error", err) return nil, err } _, err = part.Write([]byte(html)) if err != nil { + logger.Errorw("Failed to write to form file", "error", err) return nil, err } size := papersizes.FromName(pageSize) if size == nil { + logger.Errorw("Invalid page size", "size", pageSize) return nil, fmt.Errorf("invalid page size: %s", pageSize) } err = writer.WriteField("paperWidth", strconv.Itoa(size.Width)+"mm") if err != nil { + logger.Errorw("Failed to write paper width", "error", err) return nil, err } err = writer.WriteField("paperHeight", strconv.Itoa(size.Height)+"mm") if err != nil { + logger.Errorw("Failed to write paper height", "error", err) return nil, err } err = writer.WriteField("landscape", strconv.FormatBool(landscape)) if err != nil { + logger.Errorw("Failed to write landscape", "error", err) return nil, err } err = writer.WriteField("marginTop", "0") if err != nil { + logger.Errorw("Failed to write margin top", "error", err) return nil, err } err = writer.WriteField("marginBottom", "0") if err != nil { + logger.Errorw("Failed to write margin bottom", "error", err) return nil, err } err = writer.WriteField("marginLeft", "0") if err != nil { + logger.Errorw("Failed to write margin left", "error", err) return nil, err } err = writer.WriteField("marginRight", "0") if err != nil { + logger.Errorw("Failed to write margin right", "error", err) return nil, err } err = writer.WriteField("preferCssPageSize", "true") if err != nil { + logger.Errorw("Failed to write prefer css page size", "error", err) return nil, err } err = writer.Close() if err != nil { + logger.Errorw("Failed to close writer", "error", err) return nil, err } + logger.Debug("Created form data") + logger.Debug("Creating HTTP request") req, err := http.NewRequest("POST", g.BaseUrl+"/forms/chromium/convert/html", body) if err != nil { return nil, err } req.Header.Set("Content-Type", writer.FormDataContentType()) + logger.Debug("Sending HTTP request") resp, err := client.Do(req) if err != nil { + logger.Errorw("Failed to send request", "error", err) return nil, err } + logger.Debug("Received HTTP response") defer resp.Body.Close() data := new(bytes.Buffer) _, err = data.ReadFrom(resp.Body) if err != nil { + logger.Errorw("Failed to read response body", "error", err) return nil, err } + logger.Debug("Returning PDF data") return data.Bytes(), nil } diff --git a/services/templater.go b/services/templater.go index fa644ae..4f3cf38 100644 --- a/services/templater.go +++ b/services/templater.go @@ -7,6 +7,8 @@ import ( "fmt" "html/template" "strings" + + "go.uber.org/zap" ) type Templater interface { @@ -17,6 +19,7 @@ type Templater interface { type DefaultTemplater struct { BarcodeService BarcodeService StaticService StaticService + Logger *zap.SugaredLogger } func idToEan13(id string, prefix string) (string, error) { @@ -48,10 +51,13 @@ func (t *DefaultTemplater) GenerateBarcode(code string, format string, prefix st } func (t *DefaultTemplater) SelectSponsorImage(id int) (string, error) { + logger := t.Logger.Named("SelectSponsorImage") sponsors, err := t.StaticService.ListFilesInStaticSubFolder("images/sponsors") if err != nil { + logger.Errorw("Failed to list sponsors", "error", err) return "", err } + logger.Debugw("Selected sponsor", "sponsors", sponsors, "id", id, "selected", sponsors[id%len(sponsors)]) return t.StaticService.GetImage("sponsors/" + strings.TrimSuffix(sponsors[id%len(sponsors)], ".base64")), nil } diff --git a/services/templates.go b/services/templates.go index 2799305..61ee90c 100644 --- a/services/templates.go +++ b/services/templates.go @@ -3,8 +3,9 @@ package services import ( _ "embed" "fmt" - "log" "os" + + "go.uber.org/zap" ) type StaticService interface { @@ -14,47 +15,55 @@ type StaticService interface { } type DefaultStaticService struct { - Cache map[string]string + Cache map[string]string + Logger *zap.SugaredLogger } func (s *DefaultStaticService) GetTemplate(locale, templateName string) (string, error) { + logger := s.Logger.Named("GetTemplate").With("locale", locale, "template_name", templateName) if s.Cache[locale+templateName] != "" { - log.Printf("returning cached template %s with locale %s", templateName, locale) + logger.Debugw("Template found in cache", "key", locale+templateName) return s.Cache[locale+templateName], nil } content, err := os.ReadFile(fmt.Sprintf("static/templates/%s/%s.html", templateName, locale)) if content == nil || err != nil { - log.Printf("error reading template %s with locale %s: %v", templateName, locale, err) + logger.Errorw("Failed to read template", "error", err) return "", err } s.Cache[locale+templateName] = string(content) + logger.Debugw("Saved template to cache", "key", locale+templateName) return string(content), nil } func (s *DefaultStaticService) ListFilesInStaticSubFolder(folderName string) ([]string, error) { + logger := s.Logger.Named("ListFilesInStaticSubFolder").With("folder_name", folderName) + files, err := os.ReadDir(fmt.Sprintf("static/%s", folderName)) if err != nil { - log.Printf("error reading files from folder %s: %v", folderName, err) + logger.Errorw("Failed to list files", "error", err) return nil, err } var images []string for _, file := range files { if file.IsDir() { - continue + logger.Debugw("Skipping directory", "file", file.Name()) } images = append(images, file.Name()) } + logger.Debugw("Listed files", "files", images) return images, nil } func (s *DefaultStaticService) GetImage(imageName string) string { + logger := s.Logger.Named("GetImage").With("image_name", imageName) + content, err := os.ReadFile("static/images/" + imageName + ".base64") if content == nil || err != nil { - log.Printf("error reading image %s: %v", imageName, err) + logger.Errorw("Failed to read image", "error", err) return ImageErrorBase64 } return string(content)