Initial commit: Open sourcing all of the Maple Open Technologies code.

This commit is contained in:
Bartlomiej Mika 2025-12-02 14:33:08 -05:00
commit 755d54a99d
2010 changed files with 448675 additions and 0 deletions

View file

@ -0,0 +1,120 @@
package logger
import (
"fmt"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/config"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// emojiCore wraps a zapcore.Core to add emoji icon field
type emojiCore struct {
zapcore.Core
}
func (c *emojiCore) With(fields []zapcore.Field) zapcore.Core {
return &emojiCore{c.Core.With(fields)}
}
func (c *emojiCore) Check(entry zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if c.Enabled(entry.Level) {
return ce.AddCore(entry, c)
}
return ce
}
func (c *emojiCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
// Only add emoji icon field for warnings and errors
// Skip for info and debug to keep output clean
var emoji string
var addEmoji bool
switch entry.Level {
case zapcore.WarnLevel:
emoji = "🟡" // Yellow circle for warnings
addEmoji = true
case zapcore.ErrorLevel:
emoji = "🔴" // Red circle for errors
addEmoji = true
case zapcore.DPanicLevel:
emoji = "🔴" // Red circle for panic
addEmoji = true
case zapcore.PanicLevel:
emoji = "🔴" // Red circle for panic
addEmoji = true
case zapcore.FatalLevel:
emoji = "🔴" // Red circle for fatal
addEmoji = true
default:
// No emoji for debug and info levels
addEmoji = false
}
// Only prepend emoji field if we're adding one
if addEmoji {
fieldsWithEmoji := make([]zapcore.Field, 0, len(fields)+1)
fieldsWithEmoji = append(fieldsWithEmoji, zap.String("ico", emoji))
fieldsWithEmoji = append(fieldsWithEmoji, fields...)
return c.Core.Write(entry, fieldsWithEmoji)
}
// For debug/info, write as-is without emoji
return c.Core.Write(entry, fields)
}
// ProvideLogger creates a new zap logger based on configuration
func ProvideLogger(cfg *config.Config) (*zap.Logger, error) {
var zapConfig zap.Config
// Set config based on environment
if cfg.App.Environment == "production" {
zapConfig = zap.NewProductionConfig()
} else {
zapConfig = zap.NewDevelopmentConfig()
}
// Set log level
level, err := zapcore.ParseLevel(cfg.Logger.Level)
if err != nil {
return nil, fmt.Errorf("invalid log level %s: %w", cfg.Logger.Level, err)
}
zapConfig.Level = zap.NewAtomicLevelAt(level)
// Set encoding format
if cfg.Logger.Format == "console" {
zapConfig.Encoding = "console"
zapConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
} else {
zapConfig.Encoding = "json"
}
// Build logger with environment-specific options
var loggerOptions []zap.Option
// Enable caller information in development for easier debugging
if cfg.App.Environment != "production" {
loggerOptions = append(loggerOptions, zap.AddCaller())
loggerOptions = append(loggerOptions, zap.AddCallerSkip(0))
}
// Add stack traces for error level and above
loggerOptions = append(loggerOptions, zap.AddStacktrace(zapcore.ErrorLevel))
// Wrap core with emoji core to add icon field
loggerOptions = append(loggerOptions, zap.WrapCore(func(core zapcore.Core) zapcore.Core {
return &emojiCore{core}
}))
logger, err := zapConfig.Build(loggerOptions...)
if err != nil {
return nil, fmt.Errorf("failed to build logger: %w", err)
}
logger.Info("✓ Logger initialized",
zap.String("level", cfg.Logger.Level),
zap.String("format", cfg.Logger.Format),
zap.String("environment", cfg.App.Environment))
return logger, nil
}