From 47e7d8847e89e73792d7af1323ce58f4ee7385a2 Mon Sep 17 00:00:00 2001 From: Andrey Ivanov Date: Tue, 1 Sep 2020 12:21:21 +0300 Subject: [PATCH] HW12 config & logger is completed --- hw12_13_14_15_calendar/cmd/calendar/config.go | 14 ---- hw12_13_14_15_calendar/cmd/calendar/main.go | 25 ++++--- hw12_13_14_15_calendar/configs/config.toml | 10 ++- hw12_13_14_15_calendar/go.mod | 11 ++- hw12_13_14_15_calendar/internal/app/app.go | 7 +- .../internal/config/config.go | 35 +++++++++ .../internal/config/config_test.go | 54 +++++++++++++ .../internal/logger/logger.go | 75 +++++++++++++++++-- .../internal/logger/logger_test.go | 56 +++++++++++++- .../internal/server/http/server.go | 6 +- .../internal/storage/sql/storage.go | 2 + 11 files changed, 253 insertions(+), 42 deletions(-) delete mode 100644 hw12_13_14_15_calendar/cmd/calendar/config.go create mode 100644 hw12_13_14_15_calendar/internal/config/config.go create mode 100644 hw12_13_14_15_calendar/internal/config/config_test.go diff --git a/hw12_13_14_15_calendar/cmd/calendar/config.go b/hw12_13_14_15_calendar/cmd/calendar/config.go deleted file mode 100644 index 1d35a47..0000000 --- a/hw12_13_14_15_calendar/cmd/calendar/config.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -// При желании конфигурацию можно вынести в internal/config. -// Организация конфига в main принуждает нас сужать API компонентов, использовать -// при их конструировании только необходимые параметры, а также уменьшает вероятность циклической зависимости. -type Config struct { - // TODO -} - -func NewConfig() Config { - return Config{} -} - -// TODO diff --git a/hw12_13_14_15_calendar/cmd/calendar/main.go b/hw12_13_14_15_calendar/cmd/calendar/main.go index ceaa900..91a04dc 100644 --- a/hw12_13_14_15_calendar/cmd/calendar/main.go +++ b/hw12_13_14_15_calendar/cmd/calendar/main.go @@ -2,27 +2,32 @@ package main import ( "flag" + oslog "log" "os" "os/signal" - - "github.com/fixme_my_friend/hw12_13_14_15_calendar/internal/app" - "github.com/fixme_my_friend/hw12_13_14_15_calendar/internal/logger" - internalhttp "github.com/fixme_my_friend/hw12_13_14_15_calendar/internal/server/http" - memorystorage "github.com/fixme_my_friend/hw12_13_14_15_calendar/internal/storage/memory" + "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/config" + "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/app" + "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/logger" + internalhttp "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/server/http" + memorystorage "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/memory" ) var configFile string func init() { flag.StringVar(&configFile, "config", "/etc/calendar/config.toml", "Path to configuration file") + flag.Parse() } func main() { - config := NewConfig() - logg := logger.New(config.Logger.Level) + conf, err := config.NewConfig(configFile) + if err != nil { oslog.Fatal("не удалось открыть файл конфигурации:", err.Error())} + + log, err := logger.New(conf) + if err != nil { oslog.Fatal("не удалось запустить логер:", err.Error())} storage := memorystorage.New() - calendar := app.New(logg, storage) + calendar := app.New(log, storage) server := internalhttp.NewServer(calendar) @@ -34,12 +39,12 @@ func main() { signal.Stop(signals) if err := server.Stop(); err != nil { - logger.Error("failed to stop http server: " + err.String()) + log.Error("failed to stop http server: " + err.Error()) } }() if err := server.Start(); err != nil { - logger.Error("failed to start http server: " + err.String()) + log.Error("failed to start http server: " + err.Error()) os.Exit(1) } } diff --git a/hw12_13_14_15_calendar/configs/config.toml b/hw12_13_14_15_calendar/configs/config.toml index 5b33eb0..dc28273 100644 --- a/hw12_13_14_15_calendar/configs/config.toml +++ b/hw12_13_14_15_calendar/configs/config.toml @@ -1,5 +1,11 @@ [logger] +file = "./calendar.log" level = "INFO" -# TODO -# ... +[storage] +in_memory = false +sql_host = "localhost" +sql_port = "5432" +sql_dbase = "calendar" +sql_user = "calendar" +sql_pass = "12345678" \ No newline at end of file diff --git a/hw12_13_14_15_calendar/go.mod b/hw12_13_14_15_calendar/go.mod index 3eb18a3..db45e6a 100644 --- a/hw12_13_14_15_calendar/go.mod +++ b/hw12_13_14_15_calendar/go.mod @@ -1,3 +1,12 @@ -module github.com/fixme_my_friend/hw12_13_14_15_calendar +module github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar go 1.14 + +require ( + github.com/BurntSushi/toml v0.3.1 + github.com/amitrai48/logger v0.0.0-20190214092904-448001c055ec + github.com/stretchr/testify v1.4.0 + go.uber.org/zap v1.15.0 + golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 + gopkg.in/yaml.v2 v2.3.0 // indirect +) diff --git a/hw12_13_14_15_calendar/internal/app/app.go b/hw12_13_14_15_calendar/internal/app/app.go index bbbdaea..e34970b 100644 --- a/hw12_13_14_15_calendar/internal/app/app.go +++ b/hw12_13_14_15_calendar/internal/app/app.go @@ -2,8 +2,6 @@ package app import ( "context" - - "github.com/fixme_my_friend/hw12_13_14_15_calendar/internal/storage" ) type App struct { @@ -22,8 +20,9 @@ func New(logger Logger, storage Storage) *App { return &App{} } -func (a *App) CreateEvent(ctx context.Context, id string, title string) error { - return a.storage.CreateEvent(storage.Event{ID: id, Title: title}) +func (a *App) CreateEvent(ctx context.Context, id string, title string) (err error) { + //err = a.storage.CreateEvent(storage.Event{ID: id, Title: title}) + return err } // TODO diff --git a/hw12_13_14_15_calendar/internal/config/config.go b/hw12_13_14_15_calendar/internal/config/config.go new file mode 100644 index 0000000..d876311 --- /dev/null +++ b/hw12_13_14_15_calendar/internal/config/config.go @@ -0,0 +1,35 @@ +package config + +import ( + "github.com/BurntSushi/toml" + "io/ioutil" + "os" +) + +type Config struct { + Logger struct{ + File string + Level string + MuteStdout bool + } + Storage struct { + In_memory bool + Sql_host string + Sql_port string + Sql_dbase string + Sql_user string + Sql_pass string + } +} + +// Confita может быти и хороша, но она не возвращает ошибки, если не может распарсить файл в структуру. Мне не нравится такая "молчаливость" +func NewConfig(configFile string) (Config, error) { + f,err:= os.Open(configFile) + if err != nil {return Config{}, err} + defer f.Close() + s,err := ioutil.ReadAll(f) + if err != nil {return Config{}, err} + var config Config + _, err = toml.Decode(string(s), &config) + return config, err +} diff --git a/hw12_13_14_15_calendar/internal/config/config_test.go b/hw12_13_14_15_calendar/internal/config/config_test.go new file mode 100644 index 0000000..9d9d14c --- /dev/null +++ b/hw12_13_14_15_calendar/internal/config/config_test.go @@ -0,0 +1,54 @@ +package config + +import ( + "github.com/stretchr/testify/require" + "io/ioutil" + oslog "log" + "os" + "testing" +) + +var _ = func() bool { + testing.Init() + return true +}() + +func TestNewConfig(t *testing.T) { + + badfile, err := ioutil.TempFile("", "conf.") + if err != nil { oslog.Fatal(err) } + defer os.Remove(badfile.Name()) + badfile.WriteString(`aefSD +sadfg +RFABND FYGUMG +V`) + badfile.Sync() + + goodfile, err := ioutil.TempFile("", "conf.") + if err != nil { oslog.Fatal(err) } + defer os.Remove(goodfile.Name()) + goodfile.WriteString(`[storage] +in_memory = true +sql_host = "localhost"`) + goodfile.Sync() + + t.Run("No such file", func(t *testing.T) { + c,e := NewConfig("adfergdth") + require.Equal(t,Config{},c) + require.Error(t,e) + }) + + t.Run("Bad file", func(t *testing.T) { + c,e := NewConfig(badfile.Name()) + require.Equal(t,Config{},c) + require.Error(t,e) + }) + + t.Run("TOML reading", func(t *testing.T) { + c,e := NewConfig(goodfile.Name()) + require.Equal(t,true,c.Storage.In_memory) + require.Equal(t,"localhost",c.Storage.Sql_host) + require.NoError(t,e) + }) + +} diff --git a/hw12_13_14_15_calendar/internal/logger/logger.go b/hw12_13_14_15_calendar/internal/logger/logger.go index bdba951..459c010 100644 --- a/hw12_13_14_15_calendar/internal/logger/logger.go +++ b/hw12_13_14_15_calendar/internal/logger/logger.go @@ -1,11 +1,76 @@ package logger -type Logger struct { - // TODO +import ( + "errors" + amitralog "github.com/amitrai48/logger" + "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/config" + "log" + "os" + "strings" +) + +type Logger interface { + Debug(msg string) + Info(msg string) + Warn(msg string) + Error(msg string) + Fatal(msg string) } -func New(level string) *Logger { - return &Logger{} +type Log struct { + Logger amitralog.Logger } -// TODO +func New(conf config.Config) (Log, error) { + + if conf.Logger.File=="" || !validLevel(conf.Logger.Level) { + return Log{}, errors.New("invalid logger config") + } + + c := amitralog.Configuration{ + EnableConsole: !conf.Logger.MuteStdout, + ConsoleLevel: amitralog.Fatal, + ConsoleJSONFormat: false, + EnableFile: true, + FileLevel: strings.ToLower(conf.Logger.Level), + FileJSONFormat: true, + FileLocation: conf.Logger.File, + } + + if err := amitralog.NewLogger(c, amitralog.InstanceZapLogger); err != nil { + log.Fatalf("Could not instantiate log %s", err.Error()) + } + l := amitralog.WithFields(amitralog.Fields{"hw": "12"}) + return Log{Logger: l}, nil +} + +func (l Log) Debug(format string, args ...interface{}) { + l.Logger.Debugf(format, args) +} + +func (l *Log) Info(format string, args ...interface{}) { + l.Logger.Infof(format, args) +} + +func (l *Log) Warn(format string, args ...interface{}) { + l.Logger.Warnf(format, args) +} + +func (l *Log) Error(format string, args ...interface{}) { + l.Logger.Errorf(format, args) +} + +func (l *Log) Fatal(format string, args ...interface{}) { + l.Logger.Fatalf(format, args) + os.Exit(2) +} + +func validLevel(level string) bool { + l := []string{"debug","info","warn","error","fatal"} + for _,v:=range l { + if strings.ToLower(level)==v { + return true + } + } + return false +} \ No newline at end of file diff --git a/hw12_13_14_15_calendar/internal/logger/logger_test.go b/hw12_13_14_15_calendar/internal/logger/logger_test.go index 34bb72c..f7dd5fb 100644 --- a/hw12_13_14_15_calendar/internal/logger/logger_test.go +++ b/hw12_13_14_15_calendar/internal/logger/logger_test.go @@ -1,7 +1,57 @@ package logger -import "testing" +import ( + "github.com/stretchr/testify/require" + "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/config" + "io/ioutil" + oslog "log" + "os" + "strings" + "testing" +) -func TestLogger(t *testing.T) { - // TODO +func TestLoggerLogic(t *testing.T) { + tmpfile, err := ioutil.TempFile("", "log.") + if err != nil { oslog.Fatal(err) } + defer os.Remove(tmpfile.Name()) + + conf := config.Config{Logger: struct { + File string + Level string + MuteStdout bool + }{File: tmpfile.Name(), Level: "warn", MuteStdout: false}} + log, err := New(conf) + if err != nil { oslog.Fatal(err) } + + t.Run("Messages arround the level", func(t *testing.T) { + log.Debug("debug message") + log.Error("error message") + + res,err := ioutil.ReadAll(tmpfile) + if err != nil { oslog.Fatal(err) } + require.Less(t,strings.Index(string(res),"debug message"),0) + require.Greater(t,strings.Index(string(res),"error message"),0) + }) } + +func TestLoggerNegative(t *testing.T) { + t.Run("Bad file name", func(t *testing.T) { + conf := config.Config{Logger: struct { + File string + Level string + MuteStdout bool + }{File: "", Level: "debug", MuteStdout: true}} + _, err := New(conf) + require.Error(t,err, "invalid logger config") + }) + + t.Run("Bad level", func(t *testing.T) { + conf := config.Config{Logger: struct { + File string + Level string + MuteStdout bool + }{File: "asdafad", Level: "wegretryjt", MuteStdout: true}} + _, err := New(conf) + require.Error(t,err,"invalid logger config") + }) +} \ No newline at end of file diff --git a/hw12_13_14_15_calendar/internal/server/http/server.go b/hw12_13_14_15_calendar/internal/server/http/server.go index cdbefb8..b94faf3 100644 --- a/hw12_13_14_15_calendar/internal/server/http/server.go +++ b/hw12_13_14_15_calendar/internal/server/http/server.go @@ -1,7 +1,5 @@ package internalhttp -import "context" - type Server struct { // TODO } @@ -16,11 +14,13 @@ func NewServer(app Application) *Server { func (s *Server) Start() error { // TODO + return nil } func (s *Server) Stop() error { - ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout) + //ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout) // TODO + return nil } // TODO diff --git a/hw12_13_14_15_calendar/internal/storage/sql/storage.go b/hw12_13_14_15_calendar/internal/storage/sql/storage.go index 5845045..550e449 100644 --- a/hw12_13_14_15_calendar/internal/storage/sql/storage.go +++ b/hw12_13_14_15_calendar/internal/storage/sql/storage.go @@ -12,8 +12,10 @@ func New() *Storage { func (s *Storage) Connect(ctx context.Context) error { // TODO + return nil } func (s *Storage) Close(ctx context.Context) error { // TODO + return nil }