Skip to content

Commit

Permalink
feature: adding a log interface where, if not nil, will log errors in…
Browse files Browse the repository at this point in the history
… the handler execution chain (both middleware and core usecasefunc) (#3)
  • Loading branch information
shairozan authored Aug 29, 2022
1 parent 696a576 commit c11c8e8
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 20 deletions.
2 changes: 0 additions & 2 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ func main() {
log.Fatal(err.Error())
}

//logger.Print(dognode.Routes())

api.Nodes = []*node.Node{
dognode,
}
Expand Down
5 changes: 3 additions & 2 deletions example/nodes/dog/dog.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dog
import (
"github.com/muverum/usecase"
usecase2 "github.com/muverum/usecase/example/usecase"
log2 "github.com/muverum/usecase/log"
"github.com/muverum/usecase/node"
"github.com/swaggest/rest/web"
"log"
Expand All @@ -12,12 +13,12 @@ import (
func New(service *web.Service, logger *log.Logger) (*node.Node, error) {
var dogUseCase usecase.UseCase[usecase2.DogWalkRequest, *usecase2.DogWalkResponse]
var err error
if dogUseCase, err = usecase2.MakeDogWalkUseCase(logger); err != nil {
if dogUseCase, err = usecase2.MakeDogWalkUseCase(logger, log2.NewLogWrapper(logger)); err != nil {
return nil, err
}

var dogFeedUseCase usecase.UseCase[usecase2.DogFeedRequest, *usecase2.DogFeedResponse]
if dogFeedUseCase, err = usecase2.MakeDogFeedUseCase(); err != nil {
if dogFeedUseCase, err = usecase2.MakeDogFeedUseCase(log2.NewLogWrapper(logger)); err != nil {
return nil, err
}

Expand Down
2 changes: 1 addition & 1 deletion example/usecase/cat.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ func MakeCatUsecase() (usecase.UseCase[ConcatenateRequest, *ConcatenateResponse]
i.SetDescription("Concatenates your request data with a fixed string")
}

return usecase.New(ConcatenateRequest{}, &ConcatenateResponse{}, catUseCase(), decorationFunc)
return usecase.New(ConcatenateRequest{}, &ConcatenateResponse{}, catUseCase(), decorationFunc, nil)
}
11 changes: 6 additions & 5 deletions example/usecase/dog.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package usecase
import (
"context"
"github.com/muverum/usecase"
log2 "github.com/muverum/usecase/log"
usecase2 "github.com/swaggest/usecase"
"log"
)
Expand All @@ -13,7 +14,7 @@ type DogWalkRequest struct {
Times int `json:"times" path:"times" description:"The number of times to walk said dog"`
}

//Not expecting anything so a 204 is ok
// Not expecting anything so a 204 is ok
type DogWalkResponse struct {
Walked bool `json:"walked"`
Times int `json:"times"`
Expand Down Expand Up @@ -55,7 +56,7 @@ func dogWalkUseCase() usecase.UseCaseFunc[DogWalkRequest, *DogWalkResponse] {
}
}

func MakeDogWalkUseCase(logger *log.Logger) (usecase.UseCase[DogWalkRequest, *DogWalkResponse], error) {
func MakeDogWalkUseCase(logger *log.Logger, l2 log2.UseCaseLogger) (usecase.UseCase[DogWalkRequest, *DogWalkResponse], error) {

var decorationFunc = func(i *usecase2.IOInteractor) {
i.SetTags("dog")
Expand All @@ -79,7 +80,7 @@ func MakeDogWalkUseCase(logger *log.Logger) (usecase.UseCase[DogWalkRequest, *Do
Per request
*/

return usecase.New(DogWalkRequest{}, &DogWalkResponse{}, dogWalkUseCase(), decorationFunc, middleware...)
return usecase.New(DogWalkRequest{}, &DogWalkResponse{}, dogWalkUseCase(), decorationFunc, l2, middleware...)
}

// Dog Feed
Expand All @@ -96,13 +97,13 @@ func dogFeed(ctx context.Context, input DogFeedRequest, output *DogFeedResponse)
return nil
}

func MakeDogFeedUseCase() (usecase.UseCase[DogFeedRequest, *DogFeedResponse], error) {
func MakeDogFeedUseCase(logger log2.UseCaseLogger) (usecase.UseCase[DogFeedRequest, *DogFeedResponse], error) {

decorator := func(i *usecase2.IOInteractor) {
i.SetTags("dog")
i.SetTitle("FeedDog")
i.SetDescription("Feeds the dog X times and sees if it's happy")
}

return usecase.New(DogFeedRequest{}, &DogFeedResponse{}, dogFeed, decorator)
return usecase.New(DogFeedRequest{}, &DogFeedResponse{}, dogFeed, decorator, logger)
}
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ go 1.18

require (
github.com/go-chi/chi/v5 v5.0.7
github.com/metrumresearchgroup/wrapt v0.0.2
github.com/sirupsen/logrus v1.9.0
github.com/swaggest/openapi-go v0.2.18
github.com/swaggest/rest v0.2.28
github.com/swaggest/swgui v1.4.5
Expand All @@ -14,7 +16,6 @@ require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1 // indirect
github.com/metrumresearchgroup/wrapt v0.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/santhosh-tekuri/jsonschema/v3 v3.1.0 // indirect
github.com/stretchr/testify v1.7.1 // indirect
Expand All @@ -23,7 +24,7 @@ require (
github.com/swaggest/refl v1.0.2 // indirect
github.com/vearutop/statigz v1.1.5 // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/tools v0.1.7 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
14 changes: 11 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,29 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1 h1:hZD/8vBuw7x1WqRXD/WGjVjipbbo/HcDBgySYYbrUSk=
github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1/go.mod h1:DK1Cjkc0E49ShgRVs5jy5ASrM15svSnem3K/hiSGD8o=
github.com/metrumresearchgroup/wrapt v0.0.2 h1:e6Y4OlxLH72CHTkBR2ESdnk7ZZa8zeg6wL+Nus2AQ84=
github.com/metrumresearchgroup/wrapt v0.0.2/go.mod h1:9Ubjd80vx7KMhbLFJug3EF0poD92KLlfuzadIPUmBK4=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug=
github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg=
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/santhosh-tekuri/jsonschema/v3 v3.1.0 h1:levPcBfnazlA1CyCMC3asL/QLZkq9pa8tQZOH513zQw=
github.com/santhosh-tekuri/jsonschema/v3 v3.1.0/go.mod h1:8kzK2TC0k0YjOForaAHdNEa7ik0fokNa2k30BKJ/W7Y=
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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=
Expand Down Expand Up @@ -79,6 +85,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211105192438-b53810dc28af h1:SMeNJG/vclJ5wyBBd4xupMsSJIHTd1coW9g7q6KOjmY=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand All @@ -91,12 +98,13 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
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.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
Expand All @@ -113,8 +121,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
Expand Down
38 changes: 38 additions & 0 deletions log/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package log

import (
"github.com/sirupsen/logrus"
"log"
)

type UseCaseLogger interface {
Log(args ...any)
}

type LogrusWrapLogger struct {
logger *logrus.Logger
}

func (l *LogrusWrapLogger) Log(args ...any) {
l.logger.Info(args...)
}

func NewWrappedLogrus(l *logrus.Logger) *LogrusWrapLogger {
return &LogrusWrapLogger{
logger: l,
}
}

type LogWrapper struct {
Logger *log.Logger
}

func (l *LogWrapper) Log(args ...any) {
l.Logger.Println(args...)
}

func NewLogWrapper(l *log.Logger) *LogWrapper {
return &LogWrapper{
Logger: l,
}
}
2 changes: 1 addition & 1 deletion node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func ptr[I any](input I) *I {
}

func TestNode_Routes(tt *testing.T) {
uc1, _ := usecase.New[string, *string]("", ptr(""), func(ctx context.Context, input string, output *string) error { return nil }, nil)
uc1, _ := usecase.New[string, *string]("", ptr(""), func(ctx context.Context, input string, output *string) error { return nil }, nil, nil)

type fields struct {
Root string
Expand Down
23 changes: 21 additions & 2 deletions usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package usecase
import (
"context"
"errors"
"github.com/muverum/usecase/log"
"github.com/swaggest/rest/nethttp"
"github.com/swaggest/usecase"
"net/http"
Expand All @@ -18,6 +19,7 @@ type Middleware[I any, O any] func(ctx context.Context, input I, output O) (cont
type UseCase[I any, O any] struct {
input I
output O
logger log.UseCaseLogger
usecase UseCaseFunc[I, O]
// Middleware are to be wrapped during the interaction phase such that they are executed in order
// before the actual use case func is called.
Expand Down Expand Up @@ -61,14 +63,23 @@ func (i UseCase[I, O]) interactor() usecase.Interact {
for _, v := range i.middleware {
var err error
if outContext, err = v(outContext, input, output); err != nil {
if i.logger != nil {
i.logger.Log(err.Error())
}
return err
}
}

return i.usecase(outContext, in, out)
}

return outFn(outContext, in, out)
err := outFn(outContext, in, out)

if err != nil && i.logger != nil {
i.logger.Log(err.Error())
}

return err
}
}

Expand All @@ -82,7 +93,14 @@ func (i UseCase[I, O]) Interactor() usecase.Interactor {
return u
}

func New[I any, O any](input I, output O, interactor UseCaseFunc[I, O], decorationFunc func(IOInteractor *usecase.IOInteractor), m ...Middleware[I, O]) (UseCase[I, O], error) {
func New[I any, O any](input I,
output O,
interactor UseCaseFunc[I, O],
decorationFunc func(IOInteractor *usecase.IOInteractor),
logger log.UseCaseLogger,
m ...Middleware[I, O],
) (UseCase[I, O], error) {

//Check to make sure the Output is a pointer type
if reflect.ValueOf(output).Kind() != reflect.Ptr {
return UseCase[I, O]{}, errors.New("a pointer type must be provided as your output type for the interaction to apply it correctly")
Expand All @@ -93,5 +111,6 @@ func New[I any, O any](input I, output O, interactor UseCaseFunc[I, O], decorati
usecase: interactor,
apiDecorationFunc: decorationFunc,
middleware: m,
logger: logger,
}, nil
}
4 changes: 2 additions & 2 deletions usecase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func TestNewWithoutPointer(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := New(tt.args.input, tt.args.output, tt.args.interactor, tt.args.decorationFunc, tt.args.m...)
_, err := New(tt.args.input, tt.args.output, tt.args.interactor, tt.args.decorationFunc, nil, tt.args.m...)
if (err != nil) != tt.wantErr {
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down Expand Up @@ -242,7 +242,7 @@ func TestNewWithPointer(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := New(tt.args.input, tt.args.output, tt.args.interactor, tt.args.decorationFunc, tt.args.m...)
_, err := New(tt.args.input, tt.args.output, tt.args.interactor, tt.args.decorationFunc, nil, tt.args.m...)
if (err != nil) != tt.wantErr {
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down

0 comments on commit c11c8e8

Please sign in to comment.