From b20380b1f64388c1182a4803e5db9feaeb5eceb5 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 20 Aug 2025 09:36:13 +0700 Subject: [PATCH] feat (user): add logger on crud --- internal/use-case/main-use-case/user/case.go | 279 ++++++++++++++++--- internal/use-case/main-use-case/user/lib.go | 2 +- pkg/logger/logger.go | 15 +- 3 files changed, 251 insertions(+), 45 deletions(-) diff --git a/internal/use-case/main-use-case/user/case.go b/internal/use-case/main-use-case/user/case.go index bba503db..0086fa32 100644 --- a/internal/use-case/main-use-case/user/case.go +++ b/internal/use-case/main-use-case/user/case.go @@ -26,17 +26,13 @@ func Create(input e.CreateDto) (*d.Data, error) { } // Start log - event.Action = "Create" - event.Status = "started" - pl.SetLogInfo(event, input) + pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { for i := range createPreMw { mwName := fmt.Sprintf("createPreMw[%d]", i) - event.Action = mwName - event.Status = "started" - pl.SetLogInfo(event, data) + pl.SetLogInfo(&event, data, "started", mwName) if err := createPreMw[i](&input, &data, tx); err != nil { event.Status = "failed" @@ -48,13 +44,10 @@ func Create(input e.CreateDto) (*d.Data, error) { return pl.SetLogError(event, data) } - event.Status = "completed" - pl.SetLogInfo(event, nil) + pl.SetLogInfo(&event, nil, "complete") } - event.Action = "DBCreate" - event.Status = "started" - pl.SetLogInfo(event, data) + pl.SetLogInfo(&event, data, "started", "DBCreate") _, err := CreateData(&data, tx) if err != nil { event.Status = "failed" @@ -66,15 +59,12 @@ func Create(input e.CreateDto) (*d.Data, error) { return pl.SetLogError(event, data) } - event.Status = "completed" - pl.SetLogInfo(event, nil) + pl.SetLogInfo(&event, nil, "complete") for i := range createPostMw { mwName := fmt.Sprintf("createPostMw[%d]", i) - event.Action = mwName - event.Status = "started" - pl.SetLogInfo(event, input) + pl.SetLogInfo(&event, input, "started", mwName) if err := createPostMw[i](&input, &data, tx); err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ @@ -86,8 +76,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } } - event.Status = "completed" - pl.SetLogInfo(event, nil) + pl.SetLogInfo(&event, nil, "complete") return nil }) @@ -111,22 +100,64 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { var dataList []e.User var metaList *e.MetaDto var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + err = dg.I.Transaction(func(tx *gorm.DB) error { for i := range readListPreMw { + mwName := fmt.Sprintf("readListPreMw[%d]", i) + + pl.SetLogInfo(&event, input, "started", mwName) + if err := readListPreMw[i](&input, data, tx); err != nil { - return nil + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "MW_PRE_FAILED", // TODO: add to lang json + Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), + Raw: err, + } + return pl.SetLogError(event, input) } + + pl.SetLogInfo(&event, nil, "complete") } + pl.SetLogInfo(&event, input, "started", "DBReadList") dataList, metaList, err = ReadListData(input, tx) if err != nil { - return err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-read-list-fail", + Detail: "Database read list failed", + Raw: err, + } + return pl.SetLogError(event, input) } + pl.SetLogInfo(&event, nil, "complete") + for i := range readListPostMw { + mwName := fmt.Sprintf("readListPostMw[%d]", i) + + pl.SetLogInfo(&event, input, "started", mwName) + if err := readListPostMw[i](&input, data, tx); err != nil { - return nil + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "MW_POST_FAILED", // TODO: add to lang json + Detail: fmt.Sprintf("Post-middleware %s failed", mwName), + Raw: err, + } + return pl.SetLogError(event, input) } + + pl.SetLogInfo(&event, nil, "complete") } return nil @@ -152,21 +183,66 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { var data *e.User var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readDetail") + err = dg.I.Transaction(func(tx *gorm.DB) error { for i := range readDetailPreMw { + mwName := fmt.Sprintf("readDetailPreMw[%d]", i) + + pl.SetLogInfo(&event, input, "started", mwName) + if err := readDetailPreMw[i](&input, data, tx); err != nil { - return nil + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "MW_PRE_FAILED", // TODO: add to lang json + Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), + Raw: err, + } + return pl.SetLogError(event, input) } + + pl.SetLogInfo(&event, nil, "complete") } + + pl.SetLogInfo(&event, input, "started", "DBReadDetail") data, err = ReadDetailData(input, tx) if err != nil { - return err - } - for i := range readDetailPostMw { - if err := readDetailPostMw[i](&input, data, tx); err != nil { - return nil + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-read-detail-fail", + Detail: "Database read detail failed", + Raw: err, } + return pl.SetLogError(event, input) } + + pl.SetLogInfo(&event, nil, "complete") + + for i := range readDetailPostMw { + mwName := fmt.Sprintf("readDetailPostMw[%d]", i) + + pl.SetLogInfo(&event, data, "started", mwName) + + if err := readDetailPostMw[i](&input, data, tx); err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "MW_POST_FAILED", // TODO: add to lang json + Detail: fmt.Sprintf("Post-middleware %s failed", mwName), + Raw: err, + } + return pl.SetLogError(event, data) + } + + pl.SetLogInfo(&event, nil, "complete") + } + return nil }) @@ -188,29 +264,93 @@ func Update(input e.UpdateDto) (*d.Data, error) { rdDto := e.ReadDetailDto{Id: input.Id} var data *e.User var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") data, err = ReadDetailData(rdDto, tx) if err != nil { - return nil + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-read-detail-fail", + Detail: "Database read detail failed", + Raw: err, + } + return pl.SetLogError(event, rdDto) } + pl.SetLogInfo(&event, nil, "complete") + + pl.SetLogInfo(&event, input, "started", "setUpdate") err = setUpdate(input, data) if err != nil { - return err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "set-update-fail", + Detail: "Set update data failed", + Raw: err, + } + return pl.SetLogError(event, input) } + + pl.SetLogInfo(&event, nil, "complete") + for i := range updatePreMw { + mwName := fmt.Sprintf("updatePreMw[%d]", i) + + pl.SetLogInfo(&event, data, "started", mwName) + if err := updatePreMw[i](&rdDto, data, tx); err != nil { - return nil + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "MW_PRE_FAILED", // TODO: add to lang json + Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), + Raw: err, + } + return pl.SetLogError(event, data) } + + pl.SetLogInfo(&event, nil, "complete") } + + pl.SetLogInfo(&event, data, "started", "DBUpdate") if err := UpdateData(*data, tx); err != nil { - return nil - } - for i := range updatePostMw { - if err := updatePostMw[i](&rdDto, data, tx); err != nil { - return nil + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-update-fail", + Detail: "Database update failed", + Raw: err, } + return pl.SetLogError(event, data) } + + pl.SetLogInfo(&event, nil, "complete") + + for i := range updatePostMw { + mwName := fmt.Sprintf("updatePostMw[%d]", i) + + pl.SetLogInfo(&event, data, "started", mwName) + + if err := updatePostMw[i](&rdDto, data, tx); err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "MW_POST_FAILED", // TODO: add to lang json + Detail: fmt.Sprintf("Post-middleware %s failed", mwName), + Raw: err, + } + return pl.SetLogError(event, data) + } + + pl.SetLogInfo(&event, nil, "complete") + } + return nil }) @@ -233,24 +373,79 @@ func Delete(input e.DeleteDto) (*d.Data, error) { rdDto := e.ReadDetailDto{Id: input.Id} var data *e.User var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") data, err = ReadDetailData(rdDto, tx) if err != nil { - return nil + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-read-detail-fail", + Detail: "Database read detail failed", + Raw: err, + } + return pl.SetLogError(event, rdDto) } + + pl.SetLogInfo(&event, nil, "complete") + for i := range deletePreMw { + mwName := fmt.Sprintf("deletePreMw[%d]", i) + + pl.SetLogInfo(&event, data, "started", mwName) + if err := deletePreMw[i](&rdDto, data, tx); err != nil { - return nil + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "MW_PRE_FAILED", // TODO: add to lang json + Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), + Raw: err, + } + return pl.SetLogError(event, data) } + + pl.SetLogInfo(&event, nil, "complete") } + + pl.SetLogInfo(&event, data, "started", "DBDelete") if err := DeleteData(data, tx); err != nil { - return nil - } - for i := range deletePostMw { - if err := deletePostMw[i](&rdDto, data, tx); err != nil { - return nil + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, } + return pl.SetLogError(event, data) } + + pl.SetLogInfo(&event, nil, "complete") + + for i := range deletePostMw { + mwName := fmt.Sprintf("deletePostMw[%d]", i) + + pl.SetLogInfo(&event, data, "started", mwName) + + if err := deletePostMw[i](&rdDto, data, tx); err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "MW_POST_FAILED", // TODO: add to lang json + Detail: fmt.Sprintf("Post-middleware %s failed", mwName), + Raw: err, + } + return pl.SetLogError(event, data) + } + + pl.SetLogInfo(&event, nil, "complete") + } + return nil }) diff --git a/internal/use-case/main-use-case/user/lib.go b/internal/use-case/main-use-case/user/lib.go index 30f6213d..c767bdf1 100644 --- a/internal/use-case/main-use-case/user/lib.go +++ b/internal/use-case/main-use-case/user/lib.go @@ -43,7 +43,7 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.User, *e.MetaDto, e Scopes(gh.Filter(input)). Count(&count). Scopes(gh.Paginate(input, &pagination)). - Order("CreatedAt DESC") + Order("\"CreatedAt\" DESC") if err := tx.Debug().Find(&data).Error; err != nil { if err == gorm.ErrRecordNotFound { diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index f65f35b4..73f884bd 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -27,13 +27,24 @@ type ErrorInfo struct { Raw error } -func SetLogInfo(e Event, data any) { +// SetLogInfo updates the event and logs it. +// The first argument is the event, the second is the data. +// Variadic arguments: +// - first (optional): status +// - second (optional): action +func SetLogInfo(e *Event, data any, args ...string) { dataString, _ := json.Marshal(data) + if len(args) > 0 { + e.Status = args[0] + } + if len(args) > 1 { + e.Action = args[1] + } lz.O.Info(). String("source", e.Source). String("feature", e.Feature). String("action", e.Action). - String("status", "started"). + String("status", e.Status). String("input", string(dataString)). Send() }