diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c83c3a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/dist +tmp/** + +# Editor directories and files +.idea +.vscode +.history \ No newline at end of file diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..084a637 --- /dev/null +++ b/TODO.md @@ -0,0 +1 @@ +1. Remove colors from file logs, they should be filtered before writing to file! \ No newline at end of file diff --git a/appLog/logs.go b/appLog/logs.go new file mode 100644 index 0000000..d96a956 --- /dev/null +++ b/appLog/logs.go @@ -0,0 +1,63 @@ +package appLog + +import ( + "github.com/kyaxcorp/go-logger" + "github.com/kyaxcorp/go-logger/model" + "github.com/rs/zerolog" +) + +func getApp() *model.Logger { + return logger.GetAppLogger() +} + +//--------------------------\\ + +func Info() *zerolog.Event { + return getApp().Info() +} + +func Warn() *zerolog.Event { + return getApp().Warn() +} + +func Error() *zerolog.Event { + return getApp().Error() +} + +func Debug() *zerolog.Event { + return getApp().Debug() +} + +func Fatal() *zerolog.Event { + return getApp().Fatal() +} + +func Panic() *zerolog.Event { + return getApp().Panic() +} + +//--------------------------\\ + +func InfoF(functionName string) *zerolog.Event { + return getApp().InfoF(functionName) +} + +func WarnF(functionName string) *zerolog.Event { + return getApp().WarnF(functionName) +} + +func ErrorF(functionName string) *zerolog.Event { + return getApp().ErrorF(functionName) +} + +func DebugF(functionName string) *zerolog.Event { + return getApp().DebugF(functionName) +} + +func FatalF(functionName string) *zerolog.Event { + return getApp().FatalF(functionName) +} + +func PanicF(functionName string) *zerolog.Event { + return getApp().PanicF(functionName) +} diff --git a/application/app.go b/application/app.go new file mode 100644 index 0000000..b4e5e2f --- /dev/null +++ b/application/app.go @@ -0,0 +1,67 @@ +package application + +import ( + "os" + + configEvents "github.com/kyaxcorp/go-core/core/config/events" + "github.com/kyaxcorp/go-helper/conv" + "github.com/kyaxcorp/go-logger" + "github.com/kyaxcorp/go-logger/application/vars" + loggerConfig "github.com/kyaxcorp/go-logger/config" + loggerPaths "github.com/kyaxcorp/go-logger/paths" +) + +// Define variables +var applicationLoggerConfig loggerConfig.Config +var coreLoggerConfig loggerConfig.Config + +type MainLogOptions struct { + Level int +} + +func CreateAppLogger(o MainLogOptions) { + applicationLoggerConfig, _ = loggerConfig.DefaultConfig(&loggerConfig.Config{ + IsEnabled: "yes", + Name: "application", + ModuleName: "Application", + Description: "saving all application logs...", + Level: o.Level, + DirLogPath: loggerPaths.GetApplicationLogsPath(), + // We set to yes, because this is the main Application Logger from which others will extend + IsApplication: "yes", + }) + // This is the Application Logger, it will save all logs + vars.ApplicationLogger = logger.New(applicationLoggerConfig) +} + +func RegisterAppLogger() { + var _, _ = configEvents.OnLoaded(func() { + CreateAppLogger(MainLogOptions{}) + }) +} + +func CreateCoreLogger() bool { + logLevel := os.Getenv("GO_CORE_LOG_LEVEL") + var lvl int + if logLevel == "" { + lvl = 4 + } else { + lvl = conv.StrToInt(logLevel) + } + + coreLoggerConfig, _ = loggerConfig.DefaultConfig(&loggerConfig.Config{ + IsEnabled: "yes", + Name: "core", + ModuleName: "Core", + Description: "saving all core logs...", + Level: lvl, // take from the environment + + FileIsEnabled: "no", + ConsoleIsEnabled: "yes", + }) + // This is the Application Logger, it will save all logs + vars.CoreLogger = logger.New(coreLoggerConfig) + return true +} + +var _ = CreateCoreLogger() diff --git a/application/vars/logger.go b/application/vars/logger.go new file mode 100644 index 0000000..62c688c --- /dev/null +++ b/application/vars/logger.go @@ -0,0 +1,10 @@ +package vars + +import "github.com/kyaxcorp/go-logger/model" + +// ApplicationLogger -> This is the app logger which handles all logs writing to a single file +var ApplicationLogger *model.Logger + +// CoreLogger -> this is the first logger which is been created... +// it's more for debugging lib things +var CoreLogger *model.Logger diff --git a/channel/channel.go b/channel/channel.go new file mode 100644 index 0000000..91be9dc --- /dev/null +++ b/channel/channel.go @@ -0,0 +1,76 @@ +package channel + +import ( + mainConfig "github.com/kyaxcorp/go-core/core/config" + "github.com/kyaxcorp/go-helper/errors2" + "github.com/kyaxcorp/go-logger" + "github.com/kyaxcorp/go-logger/model" + loggerPaths "github.com/kyaxcorp/go-logger/paths" + "github.com/rs/zerolog" +) + +type Config struct { + ChannelName string + ReturnDefaultIfNotExists bool +} + +// GetDefaultChannel -> gets the default logger based on the current configuration +// Finds the default one +// checks if the object is created in memory +// if yes then returns it, if not it creates it based on the configuration +func GetDefaultChannel() (*model.Logger, error) { + cfg := mainConfig.GetConfig() + if cfg.Logging.DefaultChannel == "" { + msg := "logger default channel name is empty" + l().Warn().Msg(msg) + return nil, errors2.New(0, msg) + } + return GetChannel(Config{ + ChannelName: cfg.Logging.DefaultChannel, + }) +} + +// GetChannel -> Get channel based on instance name (the key from the config) +// Check if there is a channel like this... +// If there is not, then return an error... +// If there is, return the logger based on the config found +func GetChannel(c Config) (*model.Logger, error) { + cfg := mainConfig.GetConfig() + // Check if exists + if _, ok := cfg.Logging.Channels[c.ChannelName]; !ok { + // Doesn't exist + if c.ReturnDefaultIfNotExists { + // Return the default one! + return GetDefaultChannel() + } + + msg := "logger channel doesn't exist" + l().Warn().Str("logger_channel", c.ChannelName).Msg(msg) + return nil, errors2.New(0, msg) + } + + // Exists + instanceConfig := cfg.Logging.Channels[c.ChannelName] + + // Setting default values if some of them are missing in the config! + // Setting instance name by key + if instanceConfig.Name == "" { + instanceConfig.Name = c.ChannelName + } + // If DirLogPath is not defined, it will set the default folder! + if instanceConfig.DirLogPath == "" { + instanceConfig.DirLogPath = loggerPaths.GetLogsPathForChannels("websocket/" + instanceConfig.Name) + } + + // Set Module Name + if instanceConfig.ModuleName == "" { + instanceConfig.ModuleName = instanceConfig.Name + } + + return logger.New(instanceConfig), nil +} + +// log -> This is for local use only +func l() *zerolog.Logger { + return logger.GetAppLogger().Logger +} diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..5adbb45 --- /dev/null +++ b/config/config.go @@ -0,0 +1,90 @@ +package config + +import ( + "io" + + "github.com/kyaxcorp/go-helper/_struct" + "github.com/rs/zerolog" +) + +type Logger interface { + GetLogger() *zerolog.Logger +} + +type Config struct { + // IsEnabled -> enable/disable the logging (this is generally) + // By default will be enabled, and the default level will be 4 -> which is Warn! + IsEnabled string `yaml:"is_enabled" mapstructure:"is_enabled" default:"yes"` + // Name -> this is the identifier of the instance + Name string + // ModuleName -> identifies the module in logs...Each component should set its own module name + ModuleName string `yaml:"module_name" mapstructure:"module_name" default:""` + + // Description -> something about it + Description string + + EncodeLogsAsJson string `yaml:"encode_logs_as_json" mapstructure:"encode_logs_as_json" default:"yes"` + + // CliIsEnabled -> If console logging is enabled + ConsoleIsEnabled string `yaml:"console_is_enabled" mapstructure:"console_is_enabled" default:"yes"` + + ConsoleTimeFormat string `yaml:"console_time_format" mapstructure:"console_time_format" default:"002 15:04:05.000"` + + // Level -> the level which should be for the output, it's for Console and for the file log! + // For more specific levels: + /* + 1: zerolog.TraceLevel, + 2: zerolog.DebugLevel, + 3: zerolog.InfoLevel, + 4: zerolog.WarnLevel, + 5: zerolog.ErrorLevel, + 6: zerolog.FatalLevel, + 7: zerolog.PanicLevel, + */ + // The default one is INFO! + // We will not set the default value... so it will be by default 0 -> meaning DEBUG, we don't set, because when it's 0 + // it's counted as initial value! + // We will set the default value to 2 -> Debug Level + Level int `yaml:"level" mapstructure:"level" default:"4"` + + // FileName -> is optional, and can be set only if the user wants to override the default name, or to override the full + // path of the writing file... it can be user with DirLogPath + FileName string `yaml:"file_name" mapstructure:"file_name" default:"-"` + + // FileIsEnabled -> if file logging is enabled + FileIsEnabled string `yaml:"file_is_enabled" mapstructure:"file_is_enabled" default:"yes"` + // LogPath -> where the logs should be saved + DirLogPath string `yaml:"dir_log_path" mapstructure:"dir_log_path" default:""` + // RotateMaxFiles -> how many files should be in the same folder, it will auto delete the old ones + FileRotateMaxFiles int `yaml:"file_rotate_max_files" mapstructure:"file_rotate_max_files" default:"50"` + // LogMaxSize -> the maximum size of a log file, if it's getting big, it will be created a new one -> default 5 MB + FileLogMaxSize int `yaml:"file_log_max_size_mb" mapstructure:"file_log_max_size_mb" default:"5"` + // MaxAge the max age in days to keep a logfile + FileMaxAge int `yaml:"file_max_age_days" mapstructure:"file_max_age_days" default:"30"` + // Is the main logger from which everyone will extend!? We don't need to export it! + IsApplication string `yaml:"-" mapstructure:"-" default:"-"` + + // This is the parent... so the child can write to parent log + //ParentLogger Config + ParentWriter io.Writer `yaml:"-" mapstructure:"-" default:"-"` + // WriteToParent -> also write to parent log file + WriteToParent string `yaml:"write_to_parent" mapstructure:"write_to_parent" default:"yes"` + + // This is an interface to get to logger object directly + Logger Logger `yaml:"-" mapstructure:"-" default:"-"` +} + +// DefaultConfig -> it will return the default config with default values +func DefaultConfig(configObj ...*Config) (Config, error) { + var c *Config + if len(configObj) > 0 { + c = configObj[0] + } + + if c == nil { + c = &Config{} + } + // Set the default values for the object! + _err := _struct.SetDefaultValues(c) + return *c, _err +} diff --git a/constructor.go b/constructor.go new file mode 100644 index 0000000..c74cd23 --- /dev/null +++ b/constructor.go @@ -0,0 +1,222 @@ +package logger + +import ( + "io" + "os" + "path" + "sync" + "time" + + "github.com/kyaxcorp/go-helper/conv" + "github.com/kyaxcorp/go-helper/file" + "github.com/kyaxcorp/go-helper/io/writer" + "github.com/kyaxcorp/go-logger/application/vars" + "github.com/kyaxcorp/go-logger/config" + "github.com/kyaxcorp/go-logger/model" + "github.com/kyaxcorp/go-logger/multi_writer" + "github.com/mattn/go-colorable" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + +// GetAppLogger -> it returns the instance which is the main logger of the app, it centralizes all the data together +func GetAppLogger() *model.Logger { + return vars.ApplicationLogger +} + +// GetCoreLogger -> it returns the instance which is the main logger of the app, it centralizes all the data together +func GetCoreLogger() *model.Logger { + // TODO: we can switch loggers when the app logger has started... but there should be a logic of levels... + return vars.CoreLogger +} + +//func New(ctx context.Context, config config.Config) *Logger { + +// Here we will store writers which handle writing to file, if we don't want to create multiple handlers and have conflict, +// between them, it's better to have here unique handlers for each file +var writersByFileFullPath = make(map[string]io.Writer) + +// This Lock is for doing operations on writersByFileFullPath +var writersByFileFullPathLock sync.Mutex + +// We create and save 1 instance of console writer! Why? Because if having multiple, dangerous things like +// overlapped messages can occur! +var consoleWriter *zerolog.ConsoleWriter + +// Here we store the main application writer instance +var applicationWriter *io.Writer + +var conversionLevels = map[int]zerolog.Level{ + 1: zerolog.TraceLevel, + 2: zerolog.DebugLevel, + 3: zerolog.InfoLevel, + 4: zerolog.WarnLevel, + 5: zerolog.ErrorLevel, + 6: zerolog.FatalLevel, + 7: zerolog.PanicLevel, +} + +// New -> creates a new logger client +func New(config config.Config) *model.Logger { + // The context + //if ctx == nil { + // ctx = _context.GetRootContext() + //} + // The Writers + var writers []multi_writer.CustomWriter + + // We have set this format because it doesn't show us milliseconds when setting this format 15:04:05.000 + zerolog.TimeFieldFormat = time.RFC3339Nano + // Check if console writer has being created + if consoleWriter == nil { + // Create the console writer + colorStdOut := colorable.NewColorableStdout() + + // Set the time format from the config! + timeFormat := "002 15:04:05.000" + if config.ConsoleTimeFormat != "" { + timeFormat = config.ConsoleTimeFormat + } + consoleWriter = &zerolog.ConsoleWriter{ + Out: colorStdOut, + TimeFormat: timeFormat, + } + } + + // Is console logging is enabled + if conv.ParseBool(config.IsEnabled) && conv.ParseBool(config.ConsoleIsEnabled) { + //writers = append(writers, zerolog.ConsoleWriter{Out: os.Stderr}) + writers = append(writers, multi_writer.CustomWriter{ + Writer: *consoleWriter, + }) + } + + // Is File logging is enabled + var mainWriter io.Writer + if conv.ParseBool(config.IsEnabled) && conv.ParseBool(config.FileIsEnabled) { + mainWriter = getFileHandler(config) + writers = append(writers, multi_writer.CustomWriter{ + Writer: mainWriter, + // We don't need colors in file + FilterColors: true, + }) + } + + // If it's not the master app + // Check also if the master app logger is available! + var mainAppLogger = GetAppLogger() + if conv.ParseBool(config.IsEnabled) && !conv.ParseBool(config.IsApplication) && mainAppLogger != nil { + // Add additional writer to master, take the ApplicationLogger Config + // We should get an existent instance of Application writer + // Don't know what will happen if multiple processes of the same application will work, but don't see + // any problems here! + + if applicationWriter == nil { + appWriter := getFileHandler(mainAppLogger.Config) + applicationWriter = &appWriter + } + + writers = append(writers, multi_writer.CustomWriter{ + Writer: *applicationWriter, + // We don't need colors in file + FilterColors: true, + }) + } + + // Check if there is the main writer and if write to parent is enabled + if conv.ParseBool(config.IsEnabled) && + config.ParentWriter != nil && + conv.ParseBool(config.WriteToParent) { + // Add to writers parent's writer + writers = append(writers, multi_writer.CustomWriter{ + Writer: config.ParentWriter, + // We don't need colors in file + FilterColors: true, + }) + } + + // Create the multi writers + mw := multi_writer.MultiWriter(writers) + + // zerolog.SetGlobalLevel(zerolog.DebugLevel) + // Create the logger itself + //logger := zerolog.New(mw).With().Timestamp().Logger().WithContext(ctx) + + logger := zerolog.New(mw). + With(). + Str("module", config.ModuleName). + Timestamp(). + Logger(). + Level(ConvertConfigLogLevel(config.Level)) + + return &model.Logger{ + Config: config, + Logger: &logger, + // Set Main File Writer as reference! + MainWriter: mainWriter, + //parentCtx: ctx, + } +} + +func ConvertConfigLogLevel(level int) zerolog.Level { + + // panic (zerolog.PanicLevel, 5) + // fatal (zerolog.FatalLevel, 4) + // error (zerolog.ErrorLevel, 3) + // warn (zerolog.WarnLevel, 2) + // info (zerolog.InfoLevel, 1) + // debug (zerolog.DebugLevel, 0) + // trace (zerolog.TraceLevel, -1) + + if val, ok := conversionLevels[level]; ok { + return val + } else { + // Return the default value if it's an indicated an incorrect one + return zerolog.WarnLevel + } +} + +func getFileHandler(config config.Config) io.Writer { + fileName := config.Name + ".log" + if config.FileName != "" { + fileName = config.FileName + } + fullFilePath := file.FilterPath(path.Join(config.DirLogPath, fileName)) + writersByFileFullPathLock.Lock() + defer writersByFileFullPathLock.Unlock() + if _writer, ok := writersByFileFullPath[fullFilePath]; ok { + return _writer + } else { + _writer := newRollingFile(config) + // Save the writer + writersByFileFullPath[fullFilePath] = _writer + // Return in! + return _writer + } +} + +func newRollingFile(config config.Config) io.Writer { + // TODO: maybe this creation is useless because the logger auto creates... + + if config.DirLogPath == "" { + // TODO: should we return an error?! + } + + if _err := os.MkdirAll(config.DirLogPath, 0744); _err != nil { + log.Error().Err(_err).Str("path", config.DirLogPath).Msg("can't create log directory") + return nil + } + + // Override the file name if there is one... + fileName := config.Name + ".log" + if config.FileName != "" { + fileName = config.FileName + } + + return &writer.Logger{ + Filename: file.FilterPath(path.Join(config.DirLogPath, fileName)), + MaxBackups: config.FileRotateMaxFiles, // files + MaxSize: config.FileLogMaxSize, // megabytes + MaxAge: config.FileMaxAge, // days + } +} diff --git a/coreLog/logs.go b/coreLog/logs.go new file mode 100644 index 0000000..20cf5a2 --- /dev/null +++ b/coreLog/logs.go @@ -0,0 +1,63 @@ +package coreLog + +import ( + "github.com/kyaxcorp/go-logger" + "github.com/kyaxcorp/go-logger/model" + "github.com/rs/zerolog" +) + +func getApp() *model.Logger { + return logger.GetCoreLogger() +} + +//--------------------------\\ + +func Info() *zerolog.Event { + return getApp().Info() +} + +func Warn() *zerolog.Event { + return getApp().Warn() +} + +func Error() *zerolog.Event { + return getApp().Error() +} + +func Debug() *zerolog.Event { + return getApp().Debug() +} + +func Fatal() *zerolog.Event { + return getApp().Fatal() +} + +func Panic() *zerolog.Event { + return getApp().Panic() +} + +//--------------------------\\ + +func InfoF(functionName string) *zerolog.Event { + return getApp().InfoF(functionName) +} + +func WarnF(functionName string) *zerolog.Event { + return getApp().WarnF(functionName) +} + +func ErrorF(functionName string) *zerolog.Event { + return getApp().ErrorF(functionName) +} + +func DebugF(functionName string) *zerolog.Event { + return getApp().DebugF(functionName) +} + +func FatalF(functionName string) *zerolog.Event { + return getApp().FatalF(functionName) +} + +func PanicF(functionName string) *zerolog.Event { + return getApp().PanicF(functionName) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..61b8bf6 --- /dev/null +++ b/go.mod @@ -0,0 +1,53 @@ +module github.com/kyaxcorp/go-logger + +go 1.21.0 + +require ( + github.com/gookit/color v1.5.4 + github.com/kyaxcorp/go-core v0.0.1-20240805-0001 + github.com/kyaxcorp/go-helper v1.0.0 + github.com/mattn/go-colorable v0.1.13 + github.com/rs/zerolog v1.33.0 + github.com/tidwall/gjson v1.18.0 + github.com/tidwall/sjson v1.2.5 +) + +require ( + github.com/99designs/gqlgen v0.17.9 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/getsentry/sentry-go v0.29.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgx/v5 v5.3.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/kyaxcorp/gofile v0.0.1-20220602-0002 // indirect + github.com/kyaxcorp/gofm v0.0.1-20220602-0003 // indirect + github.com/magiconair/properties v1.8.5 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/pelletier/go-toml v1.9.4 // indirect + github.com/spf13/afero v1.6.0 // indirect + github.com/spf13/cast v1.4.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.10.1 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/vektah/gqlparser/v2 v2.4.4 // indirect + github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect + go.szostok.io/version v1.2.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.14.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gorm.io/driver/mysql v1.5.0 // indirect + gorm.io/driver/postgres v1.5.0 // indirect + gorm.io/gorm v1.25.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2c14407 --- /dev/null +++ b/go.sum @@ -0,0 +1,225 @@ +github.com/99designs/gqlgen v0.17.9 h1:0XvE3nMaTaLYq7XbBz1MY0t9BFcntydlt1zzNa4eY+4= +github.com/99designs/gqlgen v0.17.9/go.mod h1:PThAZAK9t2pAat7g8QdSI4dCBMOhBO+t2qj+0jvDqps= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/getsentry/sentry-go v0.29.0 h1:YtWluuCFg9OfcqnaujpY918N/AhCCwarIDWOYSBAjCA= +github.com/getsentry/sentry-go v0.29.0/go.mod h1:jhPesDAL0Q0W2+2YEuVOvdWmVtdsr1+jtBrlDEVWwLY= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= +github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.3.0 h1:/NQi8KHMpKWHInxXesC8yD4DhkXPrVhmnwYkjp9AmBA= +github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= +github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/kevinmbeaulieu/eq-go v1.0.0/go.mod h1:G3S8ajA56gKBZm4UB9AOyoOS37JO3roToPzKNM8dtdM= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kyaxcorp/go-core v0.0.1-20240805-0001 h1:SMtTmpnpi6q/ZiSTDRZ6WV9MKkBQULMnHyfwDWF4xJ8= +github.com/kyaxcorp/go-core v0.0.1-20240805-0001/go.mod h1:q2BjOd7wvWYiIHf6ozGQ/kiQS8jg5zS6WRwc0g+bJt4= +github.com/kyaxcorp/go-helper v1.0.0 h1:eV6KcQiWo4WNxsnoY3fgELpSRCexdSDvzCBfzz8FyEg= +github.com/kyaxcorp/go-helper v1.0.0/go.mod h1:jHEneTXY8zoPvfYnXpYbz6YUylUPwuO0lC4F404twec= +github.com/kyaxcorp/gofile v0.0.1-20220602-0002 h1:BIkIoD2S0fsHNcuX04ZOL3sdNAxZEFNEXxCJKAUu3cI= +github.com/kyaxcorp/gofile v0.0.1-20220602-0002/go.mod h1:2No3+xz1EdDUOL7ThD+NQZ0bBVx7G+1BqWAd0iEz5r0= +github.com/kyaxcorp/gofm v0.0.1-20220602-0003 h1:WQIX9hJl+7KjFTcML8k8fhUmJZ0C1oUqm3PI82c1CBs= +github.com/kyaxcorp/gofm v0.0.1-20220602-0003/go.mod h1:95x6CZ5/zn3q6xCmAgg7I7zbwc8XlViuvfApNEqh3BA= +github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc= +github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= +github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY= +github.com/vektah/gqlparser/v2 v2.4.4 h1:rh9hwZ5Jx9cCq88zXz2YHKmuQBuwY1JErHU8GywFdwE= +github.com/vektah/gqlparser/v2 v2.4.4/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.szostok.io/version v1.2.0 h1:8eMMdfsonjbibwZRLJ8TnrErY8bThFTQsZYV16mcXms= +go.szostok.io/version v1.2.0/go.mod h1:EiU0gPxaXb6MZ+apSN0WgDO6F4JXyC99k9PIXf2k2E8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.5.0 h1:6hSAT5QcyIaty0jfnff0z0CLDjyRgZ8mlMHLqSt7uXM= +gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo= +gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= +gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= +gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU= +gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= diff --git a/helper/model.go b/helper/model.go new file mode 100644 index 0000000..1617576 --- /dev/null +++ b/helper/model.go @@ -0,0 +1,270 @@ +package helper + +import ( + "github.com/kyaxcorp/go-logger/channel" + "github.com/kyaxcorp/go-logger/model" + "github.com/rs/zerolog" +) + +/* +This helper may be used when you need to have a Logger inside your existing model without calling +many times Logger.Logger... +*/ + +type Logger struct { + // Logger -> you can set the logger by yourself, or you can indicate a channel name + // and it will bind automatically with it + Logger *model.Logger + + // ChannelName -> it's automatically binding with the config file if exists! + ChannelName string + // These are additional info/params + ModuleName string + SubModuleName string + FunctionName string + // + VersionNr string + + // These are additional keys + AdditionalInfo map[string]string + isAdditionalInfoSet bool +} + +func New(l *Logger) (*Logger, error) { + // If logger is nil, then create it + if l == nil { + l = &Logger{} + } + // Create the map + l.AdditionalInfo = make(map[string]string) + + // Check if the channel has been set + if l.ChannelName != "" { + c, _err := channel.GetChannel(channel.Config{ + ChannelName: l.ChannelName, + ReturnDefaultIfNotExists: true, + }) + if _err != nil { + return nil, _err + } + // Set the Logger + l.Logger = c + } else { + // Check if the Logger has been set! + // If not then set the default one! + + if l.Logger == nil { + c, _err := channel.GetDefaultChannel() + if _err != nil { + return nil, _err + } + // Set the Logger + l.Logger = c + } else { + // has been set! + } + } + + return l, nil +} +func (l *Logger) SetModuleName(moduleName string) *Logger { + l.ModuleName = moduleName + return l +} + +func (l *Logger) SetSubModuleName(subModuleName string) *Logger { + l.SubModuleName = subModuleName + return l +} + +func (l *Logger) SetFunctionName(functionName string) *Logger { + l.FunctionName = functionName + return l +} + +func (l *Logger) SetVersionNr(versionNr string) *Logger { + l.VersionNr = versionNr + return l +} + +func (l *Logger) SetAddInfo(k, v string) *Logger { + l.AdditionalInfo[k] = v + l.isAdditionalInfoSet = true + return l +} + +func (l *Logger) AddAdditionalInfo(e *zerolog.Event) *zerolog.Event { + if l.ModuleName != "" { + e.Str("module_name", l.ModuleName) + } + if l.SubModuleName != "" { + e.Str("sub_module_name", l.SubModuleName) + } + if l.FunctionName != "" { + e.Str("function_name", l.FunctionName) + } + if l.VersionNr != "" { + e.Str("version_nr", l.VersionNr) + } + if l.isAdditionalInfoSet { + for k, v := range l.AdditionalInfo { + e.Str(k, v) + } + } + + return e +} + +// LDebug -> 0 +func (l *Logger) LDebug() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Debug()) +} + +// LInfo -> 1 +func (l *Logger) LInfo() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Info()) +} + +// LWarn -> 2 +func (l *Logger) LWarn() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Warn()) +} + +// LError -> 3 +func (l *Logger) LError() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Error()) +} + +// LFatal -> 4 +func (l *Logger) LFatal() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Fatal()) +} + +// LPanic -> 5 +func (l *Logger) LPanic() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Panic()) +} + +// + +// + +//-------------------------------------\\ + +// LD -> 0 +func (l *Logger) LD() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Debug()) +} + +// LI -> 1 +func (l *Logger) LI() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Info()) +} + +// LW -> 2 +func (l *Logger) LW() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Warn()) +} + +// LE -> 3 +func (l *Logger) LE() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Error()) +} + +// LF -> 4 +func (l *Logger) LF() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Fatal()) +} + +// LP -> 5 +func (l *Logger) LP() *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.Panic()) +} + +// + +//-------------------------------------\\ + +// + +func (l *Logger) LEvent(eventType string, eventName string, beforeMsg func(event *zerolog.Event)) { + l.Logger.InfoEvent(eventType, eventName, beforeMsg) +} + +func (l *Logger) LEventCustom(eventType string, eventName string) *zerolog.Event { + return l.Logger.InfoEventCustom(eventType, eventName) +} + +func (l *Logger) LEventF(eventType string, eventName string, functionName string) *zerolog.Event { + return l.Logger.InfoEventF(eventType, eventName, functionName) +} + +// + +//-------------------------------------\\ + +// + +// LWarnF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LWarnF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.WarnF(functionName)) +} + +// LInfoF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LInfoF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.InfoF(functionName)) +} + +// LDebugF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LDebugF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.DebugF(functionName)) +} + +// LErrorF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LErrorF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.ErrorF(functionName)) +} + +// LFatalF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LFatalF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.FatalF(functionName)) +} + +// LPanicF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LPanicF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.PanicF(functionName)) +} + +// + +// + +// LWF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LWF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.WarnF(functionName)) +} + +// LIF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LIF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.InfoF(functionName)) +} + +// LDF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LDF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.DebugF(functionName)) +} + +// LEF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LEF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.ErrorF(functionName)) +} + +// LFF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LFF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.FatalF(functionName)) +} + +// LPF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) LPF(functionName string) *zerolog.Event { + return l.AddAdditionalInfo(l.Logger.PanicF(functionName)) +} diff --git a/model/functions.go b/model/functions.go new file mode 100644 index 0000000..1315f05 --- /dev/null +++ b/model/functions.go @@ -0,0 +1,118 @@ +package model + +import ( + "github.com/kyaxcorp/go-helper/function" + "github.com/rs/zerolog" +) + +const funcName = "function_name" + +func (l *Logger) GetLogger() *zerolog.Logger { + return l.Logger +} + +// Debug -> 0 +func (l *Logger) Debug() *zerolog.Event { + return l.Logger.Debug() +} + +// DebugF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) DebugF(functionName string) *zerolog.Event { + return l.Debug().Str(funcName, functionName) +} + +// Info -> 1 +func (l *Logger) Info() *zerolog.Event { + return l.Logger.Info() +} + +// InfoF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) InfoF(functionName string) *zerolog.Event { + return l.Info().Str(funcName, functionName) +} + +// Warn -> 2 +func (l *Logger) Warn() *zerolog.Event { + return l.Logger.Warn() +} + +// WarnF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) WarnF(functionName string) *zerolog.Event { + return l.Warn().Str(funcName, functionName) +} + +// Error -> 3 +func (l *Logger) Error() *zerolog.Event { + return l.Logger.Error() +} + +// ErrorF -> when you need specifically to indicate in what function the logging is happening +func (l *Logger) ErrorF(functionName string) *zerolog.Event { + return l.Error().Str(funcName, functionName) +} + +// Fatal -> 4 +func (l *Logger) Fatal() *zerolog.Event { + return l.Logger.Fatal() +} + +func (l *Logger) FatalF(functionName string) *zerolog.Event { + return l.Fatal().Str(funcName, functionName) +} + +func (l *Logger) PanicF(functionName string) *zerolog.Event { + return l.Panic().Str(funcName, functionName) +} + +// Panic -> 5 +func (l *Logger) Panic() *zerolog.Event { + return l.Logger.Panic() +} + +// InfoEvent -> when executing some events +func (l *Logger) InfoEvent( + eventType string, + eventName string, + beforeMsg func(event *zerolog.Event), +) { + if eventType == "" { + eventType = "no_event_type" + } + if eventName == "" { + eventName = "no_event_name" + } + info := l.Info() + if function.IsCallable(beforeMsg) { + beforeMsg(info) + } + info.Str("event_type", eventType). + Str("event_name", eventName). + Msg("event.execution") +} + +// InfoEventF -> with function name +func (l *Logger) InfoEventF( + eventType string, + eventName string, + functionName string, +) *zerolog.Event { + return l.InfoEventCustom(eventType, eventName).Str(funcName, functionName) +} + +// InfoEventCustom -> when executing some events +func (l *Logger) InfoEventCustom( + eventType string, + eventName string, +) *zerolog.Event { + if eventType == "" { + eventType = "no_event_type" + } + if eventName == "" { + eventName = "no_event_name" + } + info := l.Info() + return info. + Str("event_type", eventType). + Str("event_name", eventName). + Str("action", "event.execution") +} diff --git a/model/model.go b/model/model.go new file mode 100644 index 0000000..37d6230 --- /dev/null +++ b/model/model.go @@ -0,0 +1,26 @@ +package model + +import ( + "io" + + "github.com/kyaxcorp/go-logger/config" + "github.com/rs/zerolog" +) + +type Logger struct { + // This is where the entire config lies... + Config config.Config + + // Usually we would like to create logs to: StdOut, In some file, or event output elsewhere! + // Logrus has only 1 output, so we decided to create multiple of them! + // We should create a default channel with stdout + // And additional if the user wants to other different outputs + Logger *zerolog.Logger + + // Main Writer + MainWriter io.Writer + + // Context is possibly not needed here... because we are not doing any goroutines + //parentCtx context.Context + //ctx _context.CancelCtx +} diff --git a/multi_writer/multi_writer.go b/multi_writer/multi_writer.go new file mode 100644 index 0000000..ed0a1fa --- /dev/null +++ b/multi_writer/multi_writer.go @@ -0,0 +1,64 @@ +package multi_writer + +import ( + "io" + + "github.com/gookit/color" + "github.com/kyaxcorp/go-helper/conv" + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +// This is a writer which has a method Write and returns the interface of io.Writer +type multiWriter struct { + //writers []io.Writer + writers []CustomWriter +} + +type CustomWriter struct { + Writer io.Writer + // Should colors be filtered for this writer + FilterColors bool + // Here we define what type of writer is this, like stdout, file etc... + Type string +} + +// MultiWriter -> create the instance which will handle the writing +func MultiWriter(multiWriters []CustomWriter) io.Writer { + return &multiWriter{ + writers: multiWriters, + } +} + +// Write -> This is the main function which will handle the writing +func (t *multiWriter) Write(p []byte) (n int, err error) { + for _, w := range t.writers { + // Remove stdout colors + if w.FilterColors { + // Convert from bytes to string + msg := conv.BytesToStr(p) + // Read the json value + _msg := gjson.Get(msg, "message").String() + // Remove the color codes + _msg = color.ClearCode(_msg) + //log.Println("found value", _msg) + // Set back to json the message value + newMsg, _err := sjson.Set(msg, "message", _msg) + if _err != nil { + // Take the original... + newMsg = msg + } + // convert back to bytes + p = conv.StrToBytes(newMsg) + } + n, err = w.Writer.Write(p) + if err != nil { + return + } + if n != len(p) { + err = io.ErrShortWrite + return + } + } + return len(p), nil +} diff --git a/paths/paths.go b/paths/paths.go new file mode 100644 index 0000000..62948d7 --- /dev/null +++ b/paths/paths.go @@ -0,0 +1,81 @@ +package paths + +import ( + "github.com/kyaxcorp/go-core/core/config" + "github.com/kyaxcorp/go-helper/file" + "github.com/kyaxcorp/go-helper/filesystem" + fsPath "github.com/kyaxcorp/go-helper/filesystem/path" + "github.com/kyaxcorp/go-helper/folder" +) + +// cum sa fac ca valoarea interfetilor date sa ajunga in alta parte?!!... +// De asemenea aceste interfete pot sa le mut in alta parte!!! dar cum insasi metodele vor fi apelate?!... + +type Ddqdqw interface { + GetLogsPath() string + GetApplicationErrorLogsPath() string + GetApplicationLogsPath() string + GetLogsPathForChannels(optFolder string) string + GetLogsPathForClients(optFolder string) string + GetDatabasePath(optFolder string) string + GetLogsPathForServers(optFolder string) string +} + +func GetLogsPath() string { + LogsPath := config.GetConfig().Logging.LogsPath + //log.Println("LOGS PATH",LogsPath); + logsPath, _err := fsPath.GenRealPath(LogsPath, true) + if _err != nil { + return "" + } + + // Create the backup folder + if !folder.Exists(logsPath) { + folder.MkDir(logsPath) + } + return logsPath +} + +// GetApplicationErrorPath -> gets the path where error logs will be stored from the entire app +func GetApplicationErrorLogsPath() string { + return file.FilterPath(GetLogsPath() + "errors" + filesystem.DirSeparator()) +} + +func GetApplicationLogsPath() string { + return file.FilterPath(GetLogsPath() + "application" + filesystem.DirSeparator()) +} + +// GetLogsPathForChannels -> channels are additional logging based on the configuration provided in the config file +func GetLogsPathForChannels(optFolder string) string { + _path := file.FilterPath(GetLogsPath() + "channels" + filesystem.DirSeparator()) + if optFolder != "" { + _path += file.FilterPath(optFolder) + filesystem.DirSeparator() + } + return _path +} + +// GetLogsPathForClients -> gets the path for clients, param: optional folder +func GetLogsPathForClients(optFolder string) string { + _path := file.FilterPath(GetLogsPath() + "clients" + filesystem.DirSeparator()) + if optFolder != "" { + _path += file.FilterPath(optFolder) + filesystem.DirSeparator() + } + return _path +} + +func GetDatabasePath(optFolder string) string { + _path := file.FilterPath(GetLogsPath() + "db" + filesystem.DirSeparator()) + if optFolder != "" { + _path += file.FilterPath(optFolder) + filesystem.DirSeparator() + } + return _path +} + +// GetLogsPathForServers -> gets the path for servers, param: optional folder +func GetLogsPathForServers(optFolder string) string { + _path := file.FilterPath(GetLogsPath() + "servers" + filesystem.DirSeparator()) + if optFolder != "" { + _path += file.FilterPath(optFolder) + filesystem.DirSeparator() + } + return _path +}