diff --git a/antlr/GruleParserV3Listener.go b/antlr/GruleParserV3Listener.go index ad079669..497f2be0 100755 --- a/antlr/GruleParserV3Listener.go +++ b/antlr/GruleParserV3Listener.go @@ -16,6 +16,8 @@ package antlr import ( "fmt" + "github.com/sirupsen/logrus" + "go.uber.org/zap" "strconv" "strings" @@ -24,17 +26,43 @@ import ( "github.com/hyperjumptech/grule-rule-engine/ast" "github.com/hyperjumptech/grule-rule-engine/logger" "github.com/hyperjumptech/grule-rule-engine/pkg" - "github.com/sirupsen/logrus" ) var ( - // LoggerV3 is a logrus instance twith default fields for grule - LoggerV3 = logger.Log.WithFields(logrus.Fields{ + // loggerV3Fields default fields for grule + loggerV3Fields = logger.Fields{ "lib": "grule", "struct": "GruleParserV3Listener", - }) + } + + // LoggerV3 is a logger instance twith default fields for grule + LoggerV3 = logger.Log.WithFields(loggerV3Fields) ) +// SetLogger changes default logger on external +func SetLogger(log interface{}) { + var entry logger.LogEntry + + switch log.(type) { + case *zap.Logger: + log, ok := log.(*zap.Logger) + if !ok { + return + } + entry = logger.NewZap(log) + case *logrus.Logger: + log, ok := log.(*logrus.Logger) + if !ok { + return + } + entry = logger.NewLogrus(log) + default: + return + } + + LoggerV3 = entry.WithFields(loggerV3Fields) +} + // NewGruleV3ParserListener create new instance of GruleV3ParserListener func NewGruleV3ParserListener(KnowledgeBase *ast.KnowledgeBase, errorCallBack *pkg.GruleErrorReporter) *GruleV3ParserListener { return &GruleV3ParserListener{ diff --git a/ast/Ast.go b/ast/Ast.go index 0f1e445e..b0274689 100755 --- a/ast/Ast.go +++ b/ast/Ast.go @@ -17,6 +17,7 @@ package ast import ( "github.com/hyperjumptech/grule-rule-engine/logger" "github.com/sirupsen/logrus" + "go.uber.org/zap" ) const ( @@ -49,12 +50,40 @@ const ( ) var ( - // AstLog is a logrus instance twith default fields for grule - AstLog = logger.Log.WithFields(logrus.Fields{ + // astLogFields default fields for grule + astLogFields = logger.Fields{ "package": "ast", - }) + } + + // AstLog is a logger instance twith default fields for grule + AstLog = logger.Log.WithFields(astLogFields) ) +// SetLogger changes default logger on external +func SetLogger(log interface{}) { + var entry logger.LogEntry + + switch log.(type) { + case *zap.Logger: + log, ok := log.(*zap.Logger) + if !ok { + return + } + entry = logger.NewZap(log) + case *logrus.Logger: + log, ok := log.(*logrus.Logger) + if !ok { + return + } + entry = logger.NewLogrus(log) + default: + return + } + + AstLog = entry.WithFields(astLogFields) + GrlLogger = entry.WithFields(grlLoggerFields) +} + // Node defines interface to implement by all AST node models type Node interface { GetAstID() string diff --git a/ast/BuiltInFunctions.go b/ast/BuiltInFunctions.go index d84a5a2e..96a15758 100755 --- a/ast/BuiltInFunctions.go +++ b/ast/BuiltInFunctions.go @@ -22,15 +22,17 @@ import ( "time" "github.com/hyperjumptech/grule-rule-engine/pkg" - "github.com/sirupsen/logrus" ) var ( - // GrlLogger is the logger that be used from within the rule engine GRL - GrlLogger = logger.Log.WithFields(logrus.Fields{ + // grlLoggerFields default fields for grule + grlLoggerFields = logger.Fields{ "package": "AST", "source": "GRL", - }) + } + + // GrlLogger is the logger that be used from within the rule engine GRL + GrlLogger = logger.Log.WithFields(grlLoggerFields) ) // BuiltInFunctions struct hosts the built-in functions ready to invoke from the rule engine execution. diff --git a/ast/WorkingMemory.go b/ast/WorkingMemory.go index cffa1f2e..1007d23c 100755 --- a/ast/WorkingMemory.go +++ b/ast/WorkingMemory.go @@ -17,8 +17,8 @@ package ast import ( "fmt" "github.com/hyperjumptech/grule-rule-engine/ast/unique" + "github.com/hyperjumptech/grule-rule-engine/logger" "github.com/hyperjumptech/grule-rule-engine/pkg" - "github.com/sirupsen/logrus" "strings" "time" ) @@ -83,7 +83,7 @@ func (e *WorkingMemory) MakeCatalog(cat *Catalog) { // DebugContent will shows the working memory mapping content func (e *WorkingMemory) DebugContent() { - if AstLog.Level <= logrus.DebugLevel { + if AstLog.Level <= logger.DebugLevel { for varName, vari := range e.variableSnapshotMap { AstLog.Debugf("Variable %s : %s : %s", varName, vari.GrlText, vari.AstID) @@ -218,7 +218,7 @@ func (e *WorkingMemory) Clone(cloneTable *pkg.CloneTable) *WorkingMemory { // IndexVariables will index all expression and expression atoms that contains a speciffic variable name func (e *WorkingMemory) IndexVariables() { - if AstLog.Level <= logrus.DebugLevel { + if AstLog.Level <= logger.DebugLevel { AstLog.Debugf("Indexing %d expressions, %d expression atoms and %d variables.", len(e.expressionSnapshotMap), len(e.expressionAtomSnapshotMap), len(e.variableSnapshotMap)) } start := time.Now() @@ -318,7 +318,7 @@ func (e *WorkingMemory) Reset(name string) bool { // Returns true if any expression was reset, false if otherwise func (e *WorkingMemory) ResetVariable(variable *Variable) bool { AstLog.Tracef("------- resetting variable %s : %s", variable.GrlText, variable.AstID) - if AstLog.Level == logrus.TraceLevel { + if AstLog.Level == logger.TraceLevel { AstLog.Tracef("%s : Resetting %s", e.ID, variable.GetSnapshot()) } reseted := false diff --git a/builder/RuleBuilder.go b/builder/RuleBuilder.go index 315d4cd5..349534d1 100755 --- a/builder/RuleBuilder.go +++ b/builder/RuleBuilder.go @@ -19,6 +19,7 @@ import ( "github.com/hyperjumptech/grule-rule-engine/ast" "github.com/hyperjumptech/grule-rule-engine/logger" "github.com/sirupsen/logrus" + "go.uber.org/zap" "time" "github.com/antlr/antlr4/runtime/Go/antlr" @@ -28,12 +29,39 @@ import ( ) var ( - // BuilderLog is a logrus instance twith default fields for grule - BuilderLog = logger.Log.WithFields(logrus.Fields{ + // builderLogFields default fields for grule + builderLogFields = logger.Fields{ "package": "builder", - }) + } + + // BuilderLog is a logger instance twith default fields for grule + BuilderLog = logger.Log.WithFields(builderLogFields) ) +// SetLogger changes default logger on external +func SetLogger(log interface{}) { + var entry logger.LogEntry + + switch log.(type) { + case *zap.Logger: + log, ok := log.(*zap.Logger) + if !ok { + return + } + entry = logger.NewZap(log) + case *logrus.Logger: + log, ok := log.(*logrus.Logger) + if !ok { + return + } + entry = logger.NewLogrus(log) + default: + return + } + + BuilderLog = entry.WithFields(builderLogFields) +} + // NewRuleBuilder creates new RuleBuilder instance. This builder will add all loaded rules into the specified knowledgebase. func NewRuleBuilder(KnowledgeLibrary *ast.KnowledgeLibrary) *RuleBuilder { return &RuleBuilder{ diff --git a/engine/GruleEngine.go b/engine/GruleEngine.go index 2fd1333d..dacccbf0 100755 --- a/engine/GruleEngine.go +++ b/engine/GruleEngine.go @@ -17,21 +17,49 @@ package engine import ( "context" "fmt" + "github.com/sirupsen/logrus" + "go.uber.org/zap" "sort" "time" "github.com/hyperjumptech/grule-rule-engine/ast" "github.com/hyperjumptech/grule-rule-engine/logger" - "github.com/sirupsen/logrus" ) var ( - // Logger is a logrus instance with default fields for grule - log = logger.Log.WithFields(logrus.Fields{ + // logFields default fields for grule + logFields = logger.Fields{ "package": "engine", - }) + } + + // Logger is a logger instance with default fields for grule + log = logger.Log.WithFields(logFields) ) +// SetLogger changes default logger on external +func SetLogger(externalLog interface{}) { + var entry logger.LogEntry + + switch externalLog.(type) { + case *zap.Logger: + log, ok := externalLog.(*zap.Logger) + if !ok { + return + } + entry = logger.NewZap(log) + case *logrus.Logger: + log, ok := externalLog.(*logrus.Logger) + if !ok { + return + } + entry = logger.NewLogrus(log) + default: + return + } + + log = entry.WithFields(logFields) +} + // NewGruleEngine will create new instance of GruleEngine struct. // It will set the max cycle to 5000 func NewGruleEngine() *GruleEngine { diff --git a/examples/Concurrency_test.go b/examples/Concurrency_test.go index 9d3929ad..50cd03e7 100644 --- a/examples/Concurrency_test.go +++ b/examples/Concurrency_test.go @@ -21,7 +21,6 @@ import ( "github.com/hyperjumptech/grule-rule-engine/engine" "github.com/hyperjumptech/grule-rule-engine/logger" "github.com/hyperjumptech/grule-rule-engine/pkg" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "sync" "testing" @@ -57,7 +56,7 @@ var ( // syncD is a mutex object to protect threadFinishMap from concurrent map read/write syncD = sync.Mutex{} - concurrencyTestlog = logger.Log.WithFields(logrus.Fields{ + concurrencyTestlog = logger.Log.WithFields(logger.Fields{ "lib": "grule", "file": "examples/Concurrency_test.go", }) diff --git a/go.mod b/go.mod index 8a2701ab..42034b77 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ require ( github.com/bmatcuk/doublestar v1.3.2 github.com/google/uuid v1.1.1 github.com/sirupsen/logrus v1.8.1 - github.com/stretchr/testify v1.6.1 - golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect + github.com/stretchr/testify v1.7.0 + go.uber.org/zap v1.21.0 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect gopkg.in/src-d/go-billy.v4 v4.3.2 diff --git a/go.sum b/go.sum index 0e6134ab..c3dab87d 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220527190237-ee62e23da966 h1:m github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220527190237-ee62e23da966/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/bmatcuk/doublestar v1.3.2 h1:mzUncgFmpzNUhIITFqGdZ8nUU0O7JTJzRO8VdkeLCSo= github.com/bmatcuk/doublestar v1.3.2/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -49,37 +51,60 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 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.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/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-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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/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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -91,5 +116,8 @@ gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/logger/Logger.go b/logger/Logger.go index c3e0e195..bde6cfee 100644 --- a/logger/Logger.go +++ b/logger/Logger.go @@ -14,19 +14,102 @@ package logger -import "github.com/sirupsen/logrus" +import ( + "github.com/sirupsen/logrus" + "go.uber.org/zap" +) + +// Level type +type Level uint32 + +const ( + // PanicLevel level, highest level of severity. Logs and then calls panic with the + // message passed to Debug, Info, ... + PanicLevel Level = iota + // FatalLevel level. Logs and then calls `logger.Exit(1)`. It will exit even if the + // logging level is set to Panic. + FatalLevel + // ErrorLevel level. Logs. Used for errors that should definitely be noted. + // Commonly used for hooks to send errors to an error tracking service. + ErrorLevel + // WarnLevel level. Non-critical entries that deserve eyes. + WarnLevel + // InfoLevel level. General operational entries about what's going on inside the + // application. + InfoLevel + // DebugLevel level. Usually only enabled when debugging. Very verbose logging. + DebugLevel + // TraceLevel level. Designates finer-grained informational events than the Debug. + TraceLevel +) + +type LogEntry struct { + Logger + Level Level +} + +type Fields map[string]interface{} + +type Logger interface { + Debug(args ...interface{}) + Info(args ...interface{}) + Warn(args ...interface{}) + Error(args ...interface{}) + Panic(args ...interface{}) + Fatal(args ...interface{}) + + Debugf(template string, args ...interface{}) + Infof(template string, args ...interface{}) + Warnf(template string, args ...interface{}) + Errorf(template string, args ...interface{}) + Panicf(template string, args ...interface{}) + Fatalf(template string, args ...interface{}) + + Trace(args ...interface{}) + Tracef(format string, args ...interface{}) + + Print(args ...interface{}) + Println(args ...interface{}) + Printf(format string, args ...interface{}) + + WithFields(keyValues Fields) LogEntry +} var ( - Log = logrus.WithFields(logrus.Fields{ - "lib": "grule-rule-engine", - }) + Log LogEntry ) func init() { - Log.Level = logrus.InfoLevel + logger := logrus.New() + logger.Level = logrus.InfoLevel + + Log = LogEntry{ + Logger: NewLogrus(logger).WithFields(Fields{"lib": "grule-rule-engine"}), + Level: DebugLevel, + } +} + +// SetLogger changes default logger on external +func SetLogger(externalLog interface{}) { + switch externalLog.(type) { + case *zap.Logger: + log, ok := externalLog.(*zap.Logger) + if !ok { + return + } + Log = NewZap(log) + case *logrus.Logger: + log, ok := externalLog.(*logrus.Logger) + if !ok { + return + } + Log = NewLogrus(log) + default: + return + } } -// SetLogLevel will set the logrus log level -func SetLogLevel(lvl logrus.Level) { +// SetLogLevel will set the logger log level +func SetLogLevel(lvl Level) { Log.Level = lvl } diff --git a/logger/Logrus.go b/logger/Logrus.go new file mode 100644 index 00000000..cb6d54ae --- /dev/null +++ b/logger/Logrus.go @@ -0,0 +1,217 @@ +// Copyright hyperjumptech/grule-rule-engine Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package logger + +import ( + "github.com/sirupsen/logrus" +) + +type logrusLogEntry struct { + entry *logrus.Entry +} + +type logrusLogger struct { + logger *logrus.Logger +} + +func NewLogrus(logger *logrus.Logger) LogEntry { + l := logrusLogger{logger: logger} + return l.WithFields(Fields{"lib": "grule-rule-engine"}) +} + +func (l *logrusLogger) Debug(args ...interface{}) { + l.logger.Debug(args...) +} + +func (l *logrusLogger) Info(args ...interface{}) { + l.logger.Info(args...) +} + +func (l *logrusLogger) Warn(args ...interface{}) { + l.logger.Warn(args...) +} + +func (l *logrusLogger) Error(args ...interface{}) { + l.logger.Error(args...) +} + +func (l *logrusLogger) Panic(args ...interface{}) { + l.logger.Panic(args...) +} + +func (l *logrusLogger) Fatal(args ...interface{}) { + l.logger.Fatal(args...) +} + +func (l *logrusLogger) Debugf(template string, args ...interface{}) { + l.logger.Debugf(template, args...) +} + +func (l *logrusLogger) Infof(template string, args ...interface{}) { + l.logger.Infof(template, args...) +} + +func (l *logrusLogger) Warnf(template string, args ...interface{}) { + l.logger.Warnf(template, args...) +} + +func (l *logrusLogger) Errorf(template string, args ...interface{}) { + l.logger.Errorf(template, args...) +} + +func (l *logrusLogger) Panicf(template string, args ...interface{}) { + l.logger.Panicf(template, args...) +} + +func (l *logrusLogger) Fatalf(template string, args ...interface{}) { + l.logger.Fatalf(template, args...) +} + +func (l *logrusLogger) WithFields(fields Fields) LogEntry { + return LogEntry{ + Logger: &logrusLogEntry{ + entry: l.logger.WithFields(convertToLogrusFields(fields)), + }, + Level: convertLogrusToInternalLevel(l.logger.GetLevel()), + } +} + +func (l *logrusLogEntry) Trace(args ...interface{}) { + l.entry.Trace(args...) +} + +func (l *logrusLogEntry) Tracef(format string, args ...interface{}) { + l.entry.Tracef(format, args...) +} + +func (l *logrusLogEntry) Print(args ...interface{}) { + l.entry.Info(args...) +} + +func (l *logrusLogEntry) Println(args ...interface{}) { + l.entry.Infoln(args...) +} + +func (l *logrusLogEntry) Printf(format string, args ...interface{}) { + l.entry.Infof(format, args...) +} + +func (l *logrusLogEntry) Debug(args ...interface{}) { + l.entry.Debug(args...) +} + +func (l *logrusLogEntry) Info(args ...interface{}) { + l.entry.Info(args...) +} + +func (l *logrusLogEntry) Warn(args ...interface{}) { + l.entry.Warn(args...) +} + +func (l *logrusLogEntry) Error(args ...interface{}) { + l.entry.Error(args...) +} + +func (l *logrusLogEntry) Panic(args ...interface{}) { + l.entry.Panic(args...) +} + +func (l *logrusLogEntry) Fatal(args ...interface{}) { + l.entry.Fatal(args...) +} + +func (l *logrusLogEntry) Debugf(template string, args ...interface{}) { + l.entry.Debugf(template, args...) +} + +func (l *logrusLogEntry) Infof(template string, args ...interface{}) { + l.entry.Infof(template, args...) +} + +func (l *logrusLogEntry) Warnf(template string, args ...interface{}) { + l.entry.Warnf(template, args...) +} + +func (l *logrusLogEntry) Errorf(template string, args ...interface{}) { + l.entry.Errorf(template, args...) +} + +func (l *logrusLogEntry) Panicf(template string, args ...interface{}) { + l.entry.Panicf(template, args...) +} + +func (l *logrusLogEntry) Fatalf(template string, args ...interface{}) { + l.entry.Fatalf(template, args...) +} + +func (l *logrusLogEntry) WithFields(fields Fields) LogEntry { + return LogEntry{ + Logger: &logrusLogEntry{ + entry: l.entry.WithFields(convertToLogrusFields(fields)), + }, + Level: convertLogrusToInternalLevel(l.entry.Level), + } +} + +func (l *logrusLogger) Trace(args ...interface{}) { + l.logger.Trace(args...) +} + +func (l *logrusLogger) Tracef(format string, args ...interface{}) { + l.logger.Tracef(format, args...) +} + +func (l *logrusLogger) Print(args ...interface{}) { + l.logger.Info(args...) +} + +func (l *logrusLogger) Println(args ...interface{}) { + l.logger.Infoln(args...) +} + +func (l *logrusLogger) Printf(format string, args ...interface{}) { + l.logger.Infof(format, args...) +} + +func convertToLogrusFields(fields Fields) logrus.Fields { + logrusFields := logrus.Fields{} + + for index, val := range fields { + logrusFields[index] = val + } + + return logrusFields +} + +func convertLogrusToInternalLevel(level logrus.Level) Level { + switch level { + case logrus.TraceLevel: + return TraceLevel + case logrus.DebugLevel: + return DebugLevel + case logrus.InfoLevel: + return InfoLevel + case logrus.WarnLevel: + return WarnLevel + case logrus.ErrorLevel: + return ErrorLevel + case logrus.FatalLevel: + return FatalLevel + case logrus.PanicLevel: + return PanicLevel + default: + return DebugLevel + } +} diff --git a/logger/Zap.go b/logger/Zap.go new file mode 100644 index 00000000..61fb671d --- /dev/null +++ b/logger/Zap.go @@ -0,0 +1,160 @@ +// Copyright hyperjumptech/grule-rule-engine Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package logger + +import ( + "fmt" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +type zapLogger struct { + sugaredLogger *zap.SugaredLogger +} + +func NewZap(logger *zap.Logger) LogEntry { + sugaredLogger := logger.WithOptions(zap.AddCallerSkip(1)).Sugar() + l := zapLogger{sugaredLogger: sugaredLogger} + return l.WithFields(Fields{"lib": "grule-rule-engine"}) +} + +func (l *zapLogger) Print(args ...interface{}) { + l.sugaredLogger.Info(args...) +} + +func (l *zapLogger) Println(args ...interface{}) { + msg := fmt.Sprintln(args...) + l.sugaredLogger.Info(msg[:len(msg)-1]) +} + +func (l *zapLogger) Trace(args ...interface{}) { + l.sugaredLogger.Debug(args...) +} + +func (l *zapLogger) Debug(args ...interface{}) { + l.sugaredLogger.Debug(args...) +} + +func (l *zapLogger) Info(args ...interface{}) { + l.sugaredLogger.Info(args...) +} + +func (l *zapLogger) Warn(args ...interface{}) { + l.sugaredLogger.Warn(args...) +} + +func (l *zapLogger) Error(args ...interface{}) { + l.sugaredLogger.Error(args...) +} + +func (l *zapLogger) Panic(args ...interface{}) { + l.sugaredLogger.Panic(args...) +} + +func (l *zapLogger) Fatal(args ...interface{}) { + l.sugaredLogger.Fatal(args...) +} + +func (l *zapLogger) Printf(template string, args ...interface{}) { + l.sugaredLogger.Infof(template, args...) +} + +func (l *zapLogger) Tracef(template string, args ...interface{}) { + l.sugaredLogger.Debugf(template, args...) +} + +func (l *zapLogger) Debugf(template string, args ...interface{}) { + l.sugaredLogger.Debugf(template, args...) +} + +func (l *zapLogger) Infof(template string, args ...interface{}) { + l.sugaredLogger.Infof(template, args...) +} + +func (l *zapLogger) Warnf(template string, args ...interface{}) { + l.sugaredLogger.Warnf(template, args...) +} + +func (l *zapLogger) Errorf(template string, args ...interface{}) { + l.sugaredLogger.Errorf(template, args...) +} + +func (l *zapLogger) Panicf(template string, args ...interface{}) { + l.sugaredLogger.Panicf(template, args...) +} + +func (l *zapLogger) Fatalf(template string, args ...interface{}) { + l.sugaredLogger.Fatalf(template, args...) +} + +func (l *zapLogger) WithFields(fields Fields) LogEntry { + var f = make([]interface{}, 0) + for k, v := range fields { + f = append(f, k) + f = append(f, v) + } + newLogger := l.sugaredLogger.With(f...) + + level := GetLevel(l.sugaredLogger.Desugar().Core()) + return LogEntry{ + Logger: &zapLogger{newLogger}, + Level: convertZapToInternalLevel(level), + } +} +func GetLevel(core zapcore.Core) zapcore.Level { + if core.Enabled(zapcore.DebugLevel) { + return zapcore.DebugLevel + } + if core.Enabled(zapcore.InfoLevel) { + return zapcore.InfoLevel + } + if core.Enabled(zapcore.WarnLevel) { + return zapcore.WarnLevel + } + if core.Enabled(zapcore.ErrorLevel) { + return zapcore.ErrorLevel + } + if core.Enabled(zapcore.DPanicLevel) { + return zapcore.DPanicLevel + } + if core.Enabled(zapcore.PanicLevel) { + return zapcore.PanicLevel + } + if core.Enabled(zapcore.FatalLevel) { + return zapcore.FatalLevel + } + return zapcore.DebugLevel +} + +func convertZapToInternalLevel(level zapcore.Level) Level { + switch level { + case zapcore.DebugLevel: + return DebugLevel + case zapcore.InfoLevel: + return InfoLevel + case zapcore.WarnLevel: + return WarnLevel + case zapcore.ErrorLevel: + return ErrorLevel + case zapcore.DPanicLevel: + return PanicLevel + case zapcore.PanicLevel: + return PanicLevel + case zapcore.FatalLevel: + return FatalLevel + default: + return DebugLevel + } +}