Skip to content

Commit

Permalink
Me mamé con el logger
Browse files Browse the repository at this point in the history
  • Loading branch information
Franco Ferraguti committed Nov 3, 2023
1 parent a5c20ae commit 4b7597e
Show file tree
Hide file tree
Showing 14 changed files with 132 additions and 93 deletions.
96 changes: 50 additions & 46 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,73 +13,77 @@ import (
"github.com/gin-gonic/gin"
)

// TODO
// - Redis
// - More tests
// - Batch insert
// - Reset password
// - Roles to DB
// - Prometheus enable flag
// - Request IDs
// - Logic from DeleteUser to service layer
// - Search & Fix TODOs
// - Replace user.Exists when you can
// - Change in config JWT -> Auth
// - OpenAPI (Swagger)

// Note: This is the entrypoint of the application.
// The HTTP Requests entrypoint is the Prometheus HandlerFunc in prometheus.go

func main() {

log.Println("Server starting ;)")

// Setup dependencies
var (
// Load configuration settings
config = config.New()
/*-------------------------
// DEPENDENCIES
//-----------------------*/

// Initialize logger
logger = middleware.NewLogger()
config := config.New()
log.Println("Config OK")

// Initialize middlewares
middlewares = []gin.HandlerFunc{
gin.Recovery(), // Panic recovery
middleware.NewRateLimiterMiddleware(middleware.NewRateLimiter(200)), // Rate Limiter
middleware.NewCORSConfigMiddleware(), // CORS
middleware.NewNewRelicMiddleware(middleware.NewNewRelic(config.Monitoring, logger)), // New Relic (monitoring)
middleware.NewPrometheusMiddleware(middleware.NewPrometheus(config.Monitoring, logger)), // Prometheus (metrics)
middleware.NewTimeoutMiddleware(config.General.Timeout), // Timeout
middleware.NewErrorHandlerMiddleware(logger), // Error Handler
}
logger := middleware.NewLogger()
logger.Info("Logger OK", nil)

middlewares := []gin.HandlerFunc{
gin.Recovery(), // Panic recovery
middleware.NewRateLimiterMiddleware(middleware.NewRateLimiter(200)), // Rate Limiter
middleware.NewCORSConfigMiddleware(), // CORS
middleware.NewNewRelicMiddleware(middleware.NewNewRelic(config.Monitoring, logger)), // New Relic (monitoring)
middleware.NewPrometheusMiddleware(middleware.NewPrometheus(config.Monitoring, logger)), // Prometheus (metrics)
middleware.NewTimeoutMiddleware(config.General.Timeout), // Timeout
middleware.NewErrorHandlerMiddleware(logger), // Error Handler
}
logger.Info("Middlewares OK", nil)

// Initialize authentication module
auth = auth.New(config.Auth.JWTSecret, config.Auth.SessionDurationDays)
auth := auth.New(config.Auth.JWTSecret, config.Auth.SessionDurationDays)
logger.Info("Auth OK", nil)

// Establish database connection
database = repository.NewDatabase(config, repository.NewDBLogger(logger.Out))
database := repository.NewDatabase(config, repository.NewDBLogger(logger.Out))
logger.Info("Database OK", nil)

// Initialize repositoryLayer layer with the database connection
repositoryLayer = repository.New(database)
repositoryLayer := repository.New(database)
logger.Info("Repository Layer OK", nil)

// Setup the main serviceLayer layer
serviceLayer = service.New(repositoryLayer, auth, config)
serviceLayer := service.New(repositoryLayer, auth, config)
logger.Info("Service Layer OK", nil)

// Setup endpoints & transport layer
transportLayer = transport.New(serviceLayer)
transportLayer := transport.New(serviceLayer)
logger.Info("Transport Layer OK", nil)

// Initialize the router with the endpoints
router = transport.NewRouter(transportLayer, *config, auth, middlewares...)
)
router := transport.NewRouter(transportLayer, config, auth, logger, middlewares...)
logger.Info("Router & Endpoints OK", nil)

/*-------------------------
// START SERVER
//------------------------*/

// Start server
port := config.General.Port
log.Println("Running server on port " + port)
logger.Info("Running server on port "+port, nil)

err := router.Run(":" + port)
if err != nil {
log.Fatalf("Failed to start server: %v", err)
}

// Have a nice day!
/* Have a great day! :) */
}

// TODO
// - Redis
// - More tests
// - Batch insert
// - Reset password
// - Roles to DB
// - Prometheus enable flag
// - Request IDs
// - Logic from DeleteUser to service layer
// - Search & Fix TODOs
// - Replace user.Exists when you can
// - Change in config JWT -> Auth
// - OpenAPI (Swagger)
3 changes: 0 additions & 3 deletions pkg/common/auth/auth.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package auth

import (
"log"

"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v4"
)
Expand All @@ -13,7 +11,6 @@ type AuthI interface {
}

func New(secret string, sessionDurationDays int) *Auth {
log.Println("Auth OK")
return &Auth{
secret: secret,
sessionDurationDays: sessionDurationDays,
Expand Down
1 change: 1 addition & 0 deletions pkg/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ const (
RedBold = "\033[31;1m"
YellowBold = "\033[33;1m"
WhiteBold = "\033[37;1m"
GreenBold = "\033[32;1m"
Gray = "\033[90m"
)
1 change: 0 additions & 1 deletion pkg/common/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ type Config struct {
func New() *Config {
config := Config{}
config.setup()
log.Println("Config OK")
return &config
}

Expand Down
4 changes: 0 additions & 4 deletions pkg/common/middleware/error_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package middleware

import (
"errors"
"log"
"net/http"

"github.com/gilperopiola/go-rest-example/pkg/common"
Expand All @@ -11,9 +10,6 @@ import (
)

func NewErrorHandlerMiddleware(logger *Logger) gin.HandlerFunc {

log.Println("ErrorHandler OK")

return func(c *gin.Context) {

// Wait until the request is finished
Expand Down
60 changes: 55 additions & 5 deletions pkg/common/middleware/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package middleware
import (
"encoding/json"
"fmt"
"log"
"os"
"regexp"
"strings"

c "github.com/gilperopiola/go-rest-example/pkg/common"

Expand All @@ -21,7 +21,6 @@ func NewLogger() *Logger {
Out: os.Stdout, Formatter: &CustomJSONFormatter{},
Hooks: make(logrus.LevelHooks), Level: logrus.InfoLevel,
}
log.Println("Logger OK")
return &Logger{l}
}

Expand All @@ -40,11 +39,31 @@ type CustomJSONFormatter struct{}
// -
func (f *CustomJSONFormatter) Format(entry *logrus.Entry) ([]byte, error) {

if entry.Message == "" {
return nil, nil
}

// We always output first the time
formattedTime := entry.Time.Format("2006-01-02 15:04:05")

// If it's a New Relic log, we put it in BlueBold
if isNewRelicLog(entry.Message) {
return []byte(fmt.Sprintf("%s%s %s[New Relic]%s %s%s", c.WhiteBold, formattedTime, c.BlueBold, c.Reset, c.White, entry.Message)), nil
}

// If it's a Prometheus log, we put it in MagentaBold
if isPrometheusLog(entry.Data) {
return []byte(fmt.Sprintf("%s%s %s[Prometheus]%s %s%s", c.WhiteBold, formattedTime, c.MagentaBold, c.Reset, c.White, entry.Message)), nil
}

if isGinLog(entry.Message) {
message, _ := strings.CutPrefix(entry.Message, "[GIN-debug]")
return []byte(fmt.Sprintf("%s%s %s[GIN]%s %s%s\n", c.WhiteBold, formattedTime, c.GreenBold, c.Reset, c.White, message)), nil
}

// We only use the custom formatter for errors. TODO rework this!
if entry.Level > logrus.ErrorLevel {
return []byte(fmt.Sprintf("%s %s", formattedTime, entry.Message)), nil
return []byte(fmt.Sprintf("%s%s%s %s%s%s", c.WhiteBold, formattedTime, c.Reset, c.White, entry.Message, c.Reset)), nil
}

// Entry to JSON
Expand Down Expand Up @@ -91,11 +110,42 @@ func (l *Logger) Warn(msg string, context map[string]interface{}) {
l.Logger.Warn(msg, context)
}
func (l *Logger) Info(msg string, context map[string]interface{}) {
l.Logger.Info(msg, context)
log := l.Logger.WithField("msg", msg)
for k, v := range context {
log = log.WithField(k, v)
}

if !strings.Contains(msg, "\n") {
msg += "\n"
}

log.Info(msg)
}
func (l *Logger) Debug(msg string, context map[string]interface{}) {
l.Logger.Debug(msg, context)
log := l.Logger.WithField("msg", msg)
for k, v := range context {
log = log.WithField(k, v)
}

if !strings.Contains(msg, "\n") {
msg += "\n"
}

log.Debug(msg)
}
func (l *Logger) DebugEnabled() bool {
return l.IsLevelEnabled(logrus.DebugLevel)
}

func isNewRelicLog(msg string) bool {
return msg == "application created\n" || msg == "final configuration\n" || msg == "application connected\n" || msg == "collector message\n"
}

func isPrometheusLog(data logrus.Fields) bool {
val, ok := data["from"]
return ok && val == "Prometheus"
}

func isGinLog(msg string) bool {
return strings.Contains(msg, "[GIN-debug]") || strings.Contains(msg, "GIN_MODE") || strings.Contains(msg, "gin.SetMode")
}
4 changes: 1 addition & 3 deletions pkg/common/middleware/new_relic.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,15 @@ func NewNewRelic(config config.Monitoring, logger *Logger) *newrelic.Application
newRelicApp, err := newrelic.NewApplication(
newrelic.ConfigAppName(config.NewRelicAppName),
newrelic.ConfigLicense(license),
newrelic.ConfigLogger(logger),
newrelic.ConfigAppLogForwardingEnabled(true),
newrelic.ConfigDistributedTracerEnabled(true),
newrelic.ConfigLogger(logger),
)

// Panic on failure
if err != nil {
log.Fatalf("Failed to start New Relic: %v", err)
}

log.Println("New Relic OK")

return newRelicApp
}
6 changes: 3 additions & 3 deletions pkg/common/middleware/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ func NewPrometheus(cfg config.Monitoring, logger *Logger) *Prometheus {
}

// Register metrics with prefix
p.registerMetrics(cfg.PrometheusAppName) // TODO this to config

log.Println("Prometheus OK")
p.registerMetrics(cfg.PrometheusAppName)

return p
}
Expand Down Expand Up @@ -236,6 +234,8 @@ func (p *Prometheus) registerMetrics(subsystem string) {
}
metricDefinition.MetricCollector = metric
}

p.logger.Info("Prometheus metrics registered", map[string]interface{}{"from": "Prometheus"})
}

// From https://github.com/DanielHeckrath/gin-prometheus/blob/master/gin_prometheus.go
Expand Down
8 changes: 5 additions & 3 deletions pkg/repository/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ type database struct {
db *gorm.DB
}

func NewDatabase(config *config.Config, logger *DBLogger) database {
func NewDatabase(config *config.Config, logger *DBLogger) *database {
var database database
database.setup(config, logger)
log.Println("Database OK")
return database
return &database
}

func (database *database) DB() *gorm.DB {
Expand Down Expand Up @@ -103,6 +102,9 @@ func (database *database) configure(config *config.Config) {
fmt.Println(err.Error())
}
}

// Just for formatting the logs :)
fmt.Println("")
}

func makeAdminModel(email, password string) *models.User {
Expand Down
7 changes: 2 additions & 5 deletions pkg/repository/repository.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package repository

import (
"log"

"github.com/gilperopiola/go-rest-example/pkg/common/models"
"github.com/gilperopiola/go-rest-example/pkg/repository/options"
)
Expand All @@ -21,11 +19,10 @@ type RepositoryLayer interface {
CreateUserPost(post models.UserPost) (models.UserPost, error)
}

func New(database database) *repository {
log.Println("Repository OK")
func New(database *database) *repository {
return &repository{database: database}
}

type repository struct {
database database
database *database
}
Loading

0 comments on commit 4b7597e

Please sign in to comment.