Skip to content

Commit

Permalink
refactor logging
Browse files Browse the repository at this point in the history
  • Loading branch information
ybizeul committed Jan 15, 2024
1 parent 5e0e91a commit eb46ee8
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 93 deletions.
87 changes: 44 additions & 43 deletions internal/feed/feed.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package feed implements
package feed

import (
Expand All @@ -15,23 +16,43 @@ import (
"time"

"github.com/google/uuid"
"github.com/ybizeul/ybfeed/pkg/yblog"
"golang.org/x/exp/slog"
)

type NotificationSettings struct {
VAPIDPublicKey string
VAPIDPrivateKey string
// PublicFeed is a version of a feed meant to provide a json representation of
// a feed that does not expose private informations
// In this context, the feed secret is not a private information as it needs to
// be transmitted as a cookie to the browser
type PublicFeed struct {
Name string `json:"name"`
Items []PublicFeedItem `json:"items"`
Secret string `json:"secret"`
VAPIDPublicKey string `json:"vapidpublickey"`
}

var fLogLevel = new(slog.LevelVar)
var fLogger = slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: fLogLevel})).WithGroup("feedManager")

func init() {
if os.Getenv("DEBUG") != "" || os.Getenv("DEBUG_FEED") != "" {
fLogLevel.Set(slog.LevelDebug)
}
// PublicFeedItem is used to provide a json representation of a feed item.
type PublicFeedItem struct {
Name string `json:"name"`
Date time.Time `json:"date"`
Type FeedItemType `json:"type"`
Feed *PublicFeed `json:"feed"`
}

// FeedItemType defines the type of an item in the feed
type FeedItemType int

const (
Text = iota
Image
Binary
)

// var fLogLevel = new(slog.LevelVar)
// var fLogger = slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: fLogLevel})).WithGroup("feedManager")

var fL = yblog.NewYBLogger("feed", []string{"DEBUG", "DEBUG_FEED"})

var FeedErrorNotFound = errors.New("feed not found")
var FeedErrorInvalidSecret = errors.New("invalid Secret")
var FeedErrorAlreadyExists = errors.New("feed already exists")
Expand All @@ -44,14 +65,6 @@ var FeedErrorItemEmpty = errors.New("feed item is empty")
var FeedErrorErrorReading = errors.New("error while reading new item")
var FeedErrorErrorWriting = errors.New("error while reading new item")

type FeedItemType int

const (
Text = iota
Image
Binary
)

// Feed is the internal representation of a Feed and contains all the
// informations needed to perform its tasks
type Feed struct {
Expand All @@ -61,8 +74,13 @@ type Feed struct {
WebSocketManager *WebSocketManager
}

type NotificationSettings struct {
VAPIDPublicKey string
VAPIDPrivateKey string
}

func NewFeed(feedPath string) (*Feed, error) {
fLogger.Info("Creating new feed", slog.String("feed", feedPath))
fL.Logger.Info("Creating new feed", slog.String("feed", feedPath))

_, err := os.Stat(feedPath)
if err == nil {
Expand All @@ -71,7 +89,7 @@ func NewFeed(feedPath string) (*Feed, error) {

err = os.Mkdir(feedPath, 0700)
if err != nil {
fLogger.Error("Error creating feed directory", slog.String("directory", feedPath))
fL.Logger.Error("Error creating feed directory", slog.String("directory", feedPath))
return nil, err
}

Expand Down Expand Up @@ -112,23 +130,6 @@ func GetFeed(feedPath string) (*Feed, error) {
return result, nil
}

// PublicFeed is a version of a feed that does not expose private informations
// In this context, the feed secret is not a private information as it needs to
// be transmitted as a cookie to the browser
type PublicFeed struct {
Name string `json:"name"`
Items []PublicFeedItem `json:"items"`
Secret string `json:"secret"`
VAPIDPublicKey string `json:"vapidpublickey"`
}

type PublicFeedItem struct {
Name string `json:"name"`
Date time.Time `json:"date"`
Type FeedItemType `json:"type"`
Feed *PublicFeed `json:"feed"`
}

func (feed *Feed) Name() string {
return path.Base(feed.Path)
}
Expand Down Expand Up @@ -159,7 +160,7 @@ func (feed *Feed) publicItems() ([]PublicFeedItem, error) {
var err error

if d, err = os.ReadDir(feed.Path); err != nil {
fLogger.Error("Unable to read feed content")
fL.Logger.Error("Unable to read feed content")

return nil, FeedErrorUnableToReadContent
}
Expand All @@ -173,7 +174,7 @@ func (feed *Feed) publicItems() ([]PublicFeedItem, error) {
code := 500
e := "Unable to read file info"

fLogger.Error(e, slog.Int("return", code))
fL.Logger.Error(e, slog.Int("return", code))

return nil, fmt.Errorf("%w: %s", FeedErrorUnableToReadItemInfo, f.Name())
}
Expand Down Expand Up @@ -232,7 +233,7 @@ func (feed *Feed) GetPublicItem(i string) (*PublicFeedItem, error) {

func (feed *Feed) GetItemData(item string) ([]byte, error) {
// Read item content
fLogger.Debug("Getting Item", slog.String("feed", feed.Name()), slog.String("name", item))
fL.Logger.Debug("Getting Item", slog.String("feed", feed.Name()), slog.String("name", item))
var content []byte
filePath := path.Join(feed.Path, item)
content, err := os.ReadFile(filePath)
Expand All @@ -252,7 +253,7 @@ func (feed *Feed) IsSecretValid(secret string) error {

if len(secret) != 4 {
if feed.Config.Secret != secret {
fLogger.Error("Invalid secret")
fL.Logger.Error("Invalid secret")
return FeedErrorInvalidSecret
}
} else {
Expand All @@ -266,7 +267,7 @@ func (feed *Feed) IsSecretValid(secret string) error {
}

func (f *Feed) AddItem(contentType string, r io.ReadCloser) error {
fLogger.Debug("Adding Item", slog.String("feed", f.Name()), slog.String("content-type", contentType))
fL.Logger.Debug("Adding Item", slog.String("feed", f.Name()), slog.String("content-type", contentType))
fileExtensions := map[string]string{
"image/png": "png",
"image/jpeg": "jpg",
Expand Down Expand Up @@ -331,7 +332,7 @@ func (f *Feed) AddItem(contentType string, r io.ReadCloser) error {
return err
}

fLogger.Debug("Added Item", slog.String("name", filename+"."+ext), slog.String("feed", f.Path), slog.String("content-type", contentType))
fL.Logger.Debug("Added Item", slog.String("name", filename+"."+ext), slog.String("feed", f.Path), slog.String("content-type", contentType))

return nil
}
Expand Down
12 changes: 0 additions & 12 deletions internal/feed/feedmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,9 @@ package feed

import (
"fmt"
"os"
"path"

"golang.org/x/exp/slog"
)

var fmLogLevel = new(slog.LevelVar)
var fmLogger = slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: fmLogLevel})).WithGroup("feedManager")

func init() {
if os.Getenv("DEBUG") != "" || os.Getenv("DEBUG_FEEDMANAGER") != "" {
fmLogLevel.Set(slog.LevelDebug)
}
}

type FeedManager struct {
path string
websocketManager *WebSocketManager
Expand Down
21 changes: 7 additions & 14 deletions internal/feed/pushnotifications.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,31 @@ package feed
import (
"fmt"
"io"
"os"

"github.com/Appboy/webpush-go"
"github.com/ybizeul/ybfeed/pkg/yblog"
"golang.org/x/exp/slog"
)

var pnLogLevel = new(slog.LevelVar)
var pnLogger = slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: pnLogLevel})).WithGroup("pushNotification")

func init() {
if os.Getenv("DEBUG") != "" || os.Getenv("DEBUG_NOTIFICATIONS") != "" {
pnLogLevel.Set(slog.LevelDebug)
}
}
var pnL = yblog.NewYBLogger("push", []string{"DEBUG", "DEBUG_NOTIFICATIONS"})

func (f *Feed) sendPushNotification() error {
// Send push notifications
if f.NotificationSettings == nil {
pnLogger.Debug("Feed has no notifications settings")
pnL.Logger.Debug("Feed has no notifications settings")
return nil
}
for _, subscription := range f.Config.Subscriptions {
pnLogger.Debug("Sending push notification", slog.String("endpoint", subscription.Endpoint))
pnL.Logger.Debug("Sending push notification", slog.String("endpoint", subscription.Endpoint))
resp, _ := webpush.SendNotification([]byte(fmt.Sprintf("New item posted to feed %s", f.Name())), &subscription, &webpush.Options{
Subscriber: "example@example.com", // Do not include "mailto:"
Subscriber: "ybfeed@tynsoe.org", // Do not include "mailto:"
VAPIDPublicKey: f.NotificationSettings.VAPIDPublicKey,
VAPIDPrivateKey: f.NotificationSettings.VAPIDPrivateKey,
TTL: 30,
})
if pnLogLevel.Level() == slog.LevelDebug {
if pnL.Level() == slog.LevelDebug {
b, _ := io.ReadAll(resp.Body)
pnLogger.Debug("Response", slog.String("resp", string(b)), slog.String("status", resp.Status))
pnL.Logger.Debug("Response", slog.String("resp", string(b)), slog.String("status", resp.Status))
}
defer resp.Body.Close()
}
Expand Down
41 changes: 17 additions & 24 deletions internal/feed/websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,16 @@ import (
"errors"
"fmt"
"net/http"
"os"
"strings"

"github.com/gorilla/websocket"
ws "github.com/gorilla/websocket"
"github.com/ybizeul/ybfeed/internal/utils"
"github.com/ybizeul/ybfeed/pkg/yblog"
"golang.org/x/exp/slog"
)

var logLevel = new(slog.LevelVar)
var logger = slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: logLevel}))

func init() {
if os.Getenv("DEBUG_WEBSOCKET") != "" {
logLevel.Set(slog.LevelDebug)
}
}
var wsL = yblog.NewYBLogger("push", []string{"DEBUG", "DEBUG_WEBSOCKET"})

type FeedSockets struct {
feedName string
Expand All @@ -33,14 +26,14 @@ type FeedNotification struct {
}

func (fs *FeedSockets) RemoveConn(c *ws.Conn) {
logger.Debug("Removing connection",
wsL.Logger.Debug("Removing connection",
slog.Int("count", len(fs.websockets)),
slog.Any("connections", fs.websockets),
slog.String("connection", fmt.Sprintf("%p", c)))
for i, conn := range fs.websockets {
logger.Debug("Current connection", slog.String("connection", fmt.Sprintf("%p", conn)))
wsL.Logger.Debug("Current connection", slog.String("connection", fmt.Sprintf("%p", conn)))
if conn == c {
logger.Debug("Found connection", slog.String("connection", fmt.Sprintf("%p", conn)))
wsL.Logger.Debug("Found connection", slog.String("connection", fmt.Sprintf("%p", conn)))
fs.websockets[i] = fs.websockets[len(fs.websockets)-1]
fs.websockets = fs.websockets[:len(fs.websockets)-1]
}
Expand All @@ -61,7 +54,7 @@ func NewWebSocketManager(fm *FeedManager) *WebSocketManager {
var upgrader = websocket.Upgrader{} // use default options

func (m *WebSocketManager) FeedSocketsForFeed(feedName string) *FeedSockets {
logger.Debug("Searching FeedSockets", slog.Int("count", len(m.FeedSockets)), slog.String("feedName", feedName))
wsL.Logger.Debug("Searching FeedSockets", slog.Int("count", len(m.FeedSockets)), slog.String("feedName", feedName))

for _, fs := range m.FeedSockets {
if fs.feedName == feedName {
Expand All @@ -77,18 +70,18 @@ func (m *WebSocketManager) RunSocketForFeed(feedName string, w http.ResponseWrit
feedSockets := m.FeedSocketsForFeed(feedName)

if feedSockets == nil {
logger.Debug("Adding FeedSockets", slog.Int("count_before", len(m.FeedSockets)), slog.String("feedName", feedName))
wsL.Logger.Debug("Adding FeedSockets", slog.Int("count_before", len(m.FeedSockets)), slog.String("feedName", feedName))
feedSockets = &FeedSockets{
feedName: feedName,
}
m.FeedSockets = append(m.FeedSockets, feedSockets)
}

logger.Debug("Adding connection", slog.Int("count", len(feedSockets.websockets)))
wsL.Logger.Debug("Adding connection", slog.Int("count", len(feedSockets.websockets)))
feedSockets.websockets = append(feedSockets.websockets, c)
logger.Debug("Added connection", slog.Int("count", len(feedSockets.websockets)))
wsL.Logger.Debug("Added connection", slog.Int("count", len(feedSockets.websockets)))

logger.Debug("WebSocket added", slog.Int("array size", len(feedSockets.websockets)))
wsL.Logger.Debug("WebSocket added", slog.Int("array size", len(feedSockets.websockets)))

if err != nil {
utils.CloseWithCodeAndMessage(w, 500, "Unable to upgrade WebSocket")
Expand All @@ -102,7 +95,7 @@ func (m *WebSocketManager) RunSocketForFeed(feedName string, w http.ResponseWrit

for {
mt, message, err := c.ReadMessage()
logger.Debug("Message Received", slog.String("message", string(message)), slog.Int("messageType", mt))
wsL.Logger.Debug("Message Received", slog.String("message", string(message)), slog.Int("messageType", mt))
if err != nil {
slog.Error("Error reading message", slog.String("error", err.Error()), slog.Int("messageType", mt))
break
Expand Down Expand Up @@ -131,11 +124,11 @@ func (m *WebSocketManager) RunSocketForFeed(feedName string, w http.ResponseWrit
}

func (m *WebSocketManager) NotifyAdd(item *PublicFeedItem) error {
logger.Debug("Notify websocket", slog.Any("item", item), slog.Int("ws count", len(m.FeedSockets)))
wsL.Logger.Debug("Notify websocket", slog.Any("item", item), slog.Int("ws count", len(m.FeedSockets)))
for _, f := range m.FeedSockets {
logger.Debug("checking feed", slog.String("feedName", f.feedName))
wsL.Logger.Debug("checking feed", slog.String("feedName", f.feedName))
if f.feedName == item.Feed.Name {
logger.Debug("Found feed", slog.String("feedName", f.feedName))
wsL.Logger.Debug("Found feed", slog.String("feedName", f.feedName))
for _, w := range f.websockets {
if err := w.WriteJSON(FeedNotification{
Action: "add",
Expand All @@ -150,11 +143,11 @@ func (m *WebSocketManager) NotifyAdd(item *PublicFeedItem) error {
}

func (m *WebSocketManager) NotifyRemove(item *PublicFeedItem) error {
logger.Debug("Notify websocket", slog.Any("item", item), slog.Int("ws count", len(m.FeedSockets)))
wsL.Logger.Debug("Notify websocket", slog.Any("item", item), slog.Int("ws count", len(m.FeedSockets)))
for _, f := range m.FeedSockets {
logger.Debug("checking feed", slog.String("feedName", f.feedName))
wsL.Logger.Debug("checking feed", slog.String("feedName", f.feedName))
if f.feedName == item.Feed.Name {
logger.Debug("Found feed", slog.String("feedName", f.feedName))
wsL.Logger.Debug("Found feed", slog.String("feedName", f.feedName))
for _, w := range f.websockets {
if err := w.WriteJSON(FeedNotification{
Action: "remove",
Expand Down
38 changes: 38 additions & 0 deletions pkg/yblog/yblog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package yblog

import (
"os"

"golang.org/x/exp/slog"
)

type YBLogger struct {
Name string
Logger *slog.Logger
loglevel *slog.LevelVar
}

func NewYBLogger(name string, env []string) *YBLogger {
ll := new(slog.LevelVar)
lg := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: ll})).WithGroup(name)

for _, e := range env {
if os.Getenv(e) != "" {
ll.Set(slog.LevelDebug)
}
}

return &YBLogger{
Name: name,
Logger: lg,
loglevel: ll,
}
}

func (lg *YBLogger) SetLevel(l slog.Level) {
lg.loglevel.Set(l)
}

func (lg *YBLogger) Level() slog.Level {
return lg.loglevel.Level()
}

0 comments on commit eb46ee8

Please sign in to comment.