From b30122defa48ec909f3275d98d118360903aba5f Mon Sep 17 00:00:00 2001 From: trinhdaiphuc Date: Sun, 17 Oct 2021 16:37:30 +0700 Subject: [PATCH] add readme --- README.md | 285 +++++++++++++++++++++++++++++++++ echo.go | 2 +- echo_test.go | 7 +- examples/echo/echo.go | 22 +++ examples/fiber/fiber.go | 22 +++ examples/gin/gin.go | 22 +++ examples/grpc/client/client.go | 30 ++++ examples/grpc/grpc.go | 57 +++++++ fiber.go | 2 +- fiber_test.go | 8 +- gin.go | 2 +- gin_test.go | 8 +- go.mod | 8 + go.sum | 16 ++ grpc.go | 6 +- logger.go | 25 ++- logger_test.go | 7 +- 17 files changed, 500 insertions(+), 29 deletions(-) create mode 100644 README.md create mode 100644 examples/echo/echo.go create mode 100644 examples/fiber/fiber.go create mode 100644 examples/gin/gin.go create mode 100644 examples/grpc/client/client.go create mode 100644 examples/grpc/grpc.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..e64fc2f --- /dev/null +++ b/README.md @@ -0,0 +1,285 @@ +# Logger + +## Introduce: + +A wrapper [Logrus](https://github.com/sirupsen/logrus) library which make logger attached in request context, log should +be showed as steps and in only one line for every request. + +Support Logger middleware for [Echo](https://echo.labstack.com/), [Fiber](https://gofiber.io/) +, [Gin](https://github.com/gin-gonic/gin) and [GRPC](https://grpc.io/docs/languages/go/basics/) framework. You can make +your own Logger middleware by adding your logger into request context and getting it by `logger.GetLogger(ctx)` +function. You can follow my middlewares and create yours. + +## Usages: + +**Install the package:** + +```shell +go get -u github.com/trinhdaiphuc/logger +``` + +### Echo + +Example code: + +```go +package main + +import ( + "github.com/labstack/echo/v4" + "github.com/trinhdaiphuc/logger" +) + +func main() { + server := echo.New() + server.Use(logger.EchoMiddleware) + + server.GET("/hello/:name", func(ctx echo.Context) error { + log := logger.GetLogger(ctx.Request().Context()) + name := ctx.Param("name") + log.AddLog("request name %v", name) + return ctx.String(200, "Hello "+name) + }) + + if err := server.Start(":8080"); err != nil { + panic(err) + } +} +``` + +Try logger with request: + +```shell +for i in {0..5}; do curl :8080/hello/user-${i}; done +``` + +Logger output: + +```shell + ____ __ + / __/___/ / ___ + / _// __/ _ \/ _ \ +/___/\__/_//_/\___/ v4.6.1 +High performance, minimalist Go web framework +https://echo.labstack.com +____________________________________O/_______ + O\ +⇨ http server started on [::]:8080 +{"STEP_1":"request name user-0","Status":200,"client_ip":"::1","end":"2021-10-17T16:27:10.717449+07:00","level":"info","msg":"latency: 25.637µs","request_method":"GET","time":"2021-10-17T16:27:10+07:00","uri":"/hello/user-0","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-1","Status":200,"client_ip":"::1","end":"2021-10-17T16:27:10.728884+07:00","level":"info","msg":"latency: 13.214µs","request_method":"GET","time":"2021-10-17T16:27:10+07:00","uri":"/hello/user-1","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-2","Status":200,"client_ip":"::1","end":"2021-10-17T16:27:10.740955+07:00","level":"info","msg":"latency: 33.484µs","request_method":"GET","time":"2021-10-17T16:27:10+07:00","uri":"/hello/user-2","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-3","Status":200,"client_ip":"::1","end":"2021-10-17T16:27:10.752934+07:00","level":"info","msg":"latency: 23.883µs","request_method":"GET","time":"2021-10-17T16:27:10+07:00","uri":"/hello/user-3","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-4","Status":200,"client_ip":"::1","end":"2021-10-17T16:27:10.765675+07:00","level":"info","msg":"latency: 27.749µs","request_method":"GET","time":"2021-10-17T16:27:10+07:00","uri":"/hello/user-4","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-5","Status":200,"client_ip":"::1","end":"2021-10-17T16:27:10.778096+07:00","level":"info","msg":"latency: 30.309µs","request_method":"GET","time":"2021-10-17T16:27:10+07:00","uri":"/hello/user-5","user_agent":"curl/7.64.1"} +``` + +### Fiber + +Example code: + +```go +package main + +import ( + "github.com/gofiber/fiber/v2" + "github.com/trinhdaiphuc/logger" +) + +func main() { + app := fiber.New() + app.Use(logger.FiberMiddleware()) + + app.Get("/hello/:name", func(ctx *fiber.Ctx) error { + log := logger.GetLogger(ctx.Context()) + name := ctx.Params("name") + log.AddLog("request name %v", name) + return ctx.Status(200).SendString("Hello " + name) + }) + + if err := app.Listen(":8080"); err != nil { + panic(err) + } +} +``` + +Try logger with request: + +```shell +for i in {0..5}; do curl :8080/hello/user-${i}; done +``` + +Logger output: + +```shell + ┌───────────────────────────────────────────────────┐ + │ Fiber v2.20.2 │ + │ http://127.0.0.1:8080 │ + │ (bound on host 0.0.0.0 and port 8080) │ + │ │ + │ Handlers ............. 3 Processes ........... 1 │ + │ Prefork ....... Disabled PID ............. 42319 │ + └───────────────────────────────────────────────────┘ + +{"STEP_1":"request name user-0","Status":200,"client_ip":"127.0.0.1","end":"2021-10-17T16:28:24.268446+07:00","level":"info","msg":"latency: 26.555µs","request_method":"GET","time":"2021-10-17T16:28:24+07:00","uri":"/hello/user-0","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-1","Status":200,"client_ip":"127.0.0.1","end":"2021-10-17T16:28:24.274605+07:00","level":"info","msg":"latency: 9.141µs","request_method":"GET","time":"2021-10-17T16:28:24+07:00","uri":"/hello/user-1","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-2","Status":200,"client_ip":"127.0.0.1","end":"2021-10-17T16:28:24.280196+07:00","level":"info","msg":"latency: 9.223µs","request_method":"GET","time":"2021-10-17T16:28:24+07:00","uri":"/hello/user-2","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-3","Status":200,"client_ip":"127.0.0.1","end":"2021-10-17T16:28:24.286032+07:00","level":"info","msg":"latency: 12.195µs","request_method":"GET","time":"2021-10-17T16:28:24+07:00","uri":"/hello/user-3","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-4","Status":200,"client_ip":"127.0.0.1","end":"2021-10-17T16:28:24.292232+07:00","level":"info","msg":"latency: 17.991µs","request_method":"GET","time":"2021-10-17T16:28:24+07:00","uri":"/hello/user-4","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-5","Status":200,"client_ip":"127.0.0.1","end":"2021-10-17T16:28:24.301115+07:00","level":"info","msg":"latency: 41.77µs","request_method":"GET","time":"2021-10-17T16:28:24+07:00","uri":"/hello/user-5","user_agent":"curl/7.64.1"} +``` + +### Gin + +Example code: + +```go +package main + +import ( + "github.com/gin-gonic/gin" + "github.com/trinhdaiphuc/logger" +) + +func main() { + gin.SetMode(gin.ReleaseMode) + server := gin.New() + server.Use(logger.GinMiddleware()) + server.GET("/hello/:name", func(ctx *gin.Context) { + log := logger.GetLogger(ctx) + name := ctx.Param("name") + log.AddLog("request name %v", name) + ctx.String(200, "Hello "+name) + }) + + if err := server.Run(":8080"); err != nil { + panic(err) + } +} +``` + +Try logger with request: + +```shell +for i in {0..5}; do curl :8080/hello/user-${i}; done +``` + +Logger output: + +```shell +{"STEP_1":"request name user-0","Status":200,"client_ip":"::1","end":"2021-10-17T16:28:52.836854+07:00","level":"info","msg":"latency: 26.574µs","request_method":"GET","time":"2021-10-17T16:28:52+07:00","uri":"/hello/user-0","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-1","Status":200,"client_ip":"::1","end":"2021-10-17T16:28:52.842935+07:00","level":"info","msg":"latency: 9.643µs","request_method":"GET","time":"2021-10-17T16:28:52+07:00","uri":"/hello/user-1","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-2","Status":200,"client_ip":"::1","end":"2021-10-17T16:28:52.848682+07:00","level":"info","msg":"latency: 14.542µs","request_method":"GET","time":"2021-10-17T16:28:52+07:00","uri":"/hello/user-2","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-3","Status":200,"client_ip":"::1","end":"2021-10-17T16:28:52.855196+07:00","level":"info","msg":"latency: 10.794µs","request_method":"GET","time":"2021-10-17T16:28:52+07:00","uri":"/hello/user-3","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-4","Status":200,"client_ip":"::1","end":"2021-10-17T16:28:52.863981+07:00","level":"info","msg":"latency: 24.512µs","request_method":"GET","time":"2021-10-17T16:28:52+07:00","uri":"/hello/user-4","user_agent":"curl/7.64.1"} +{"STEP_1":"request name user-5","Status":200,"client_ip":"::1","end":"2021-10-17T16:28:52.874219+07:00","level":"info","msg":"latency: 12.744µs","request_method":"GET","time":"2021-10-17T16:28:52+07:00","uri":"/hello/user-5","user_agent":"curl/7.64.1"} +``` + +### GRPC + +Example code: + +```go +package main + +import ( + "context" + "fmt" + "github.com/trinhdaiphuc/logger" + pb "github.com/trinhdaiphuc/logger/proto/hello" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "net" + "os" + "os/signal" + "syscall" +) + +type HelloService struct{} + +var _ pb.HelloServiceServer = (*HelloService)(nil) + +func (h HelloService) Hello(ctx context.Context, request *pb.HelloRequest) (*pb.HelloResponse, error) { + log := logger.GetLogger(ctx) + log.AddLog("Hello service") + if len(request.Name) == 0 { + log.AddLog("empty name") + return nil, status.Error(codes.InvalidArgument, "empty name") + } + return &pb.HelloResponse{Message: "Hello " + request.Name}, nil +} + +func main() { + listener, err := net.Listen("tcp", ":50051") + if err != nil { + panic(err) + } + server := grpc.NewServer(grpc.UnaryInterceptor( + logger.GrpcInterceptor, + )) + + pb.RegisterHelloServiceServer(server, &HelloService{}) + + go func() { + if err := server.Serve(listener); err != nil { + panic(err) + } + }() + + // Block main routine until a signal is received + c := make(chan os.Signal) + signal.Notify(c, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL, syscall.SIGHUP, syscall.SIGQUIT) + <-c + + fmt.Println("Gracefully shutting down...") + server.GracefulStop() + listener.Close() + fmt.Println("GRPC was successful shutdown.") +} +``` + +Try logger with request client: + +```go +package main + +import ( + "context" + "fmt" + "github.com/trinhdaiphuc/logger" + pb "github.com/trinhdaiphuc/logger/proto/hello" + "google.golang.org/grpc" +) + +func main() { + conn, err := grpc.Dial(":50051", grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + log := logger.New(logger.WithFormatter(&logger.TextFormatter{})) + client := pb.NewHelloServiceClient(conn) + + for i := 0; i <= 5; i++ { + req := &pb.HelloRequest{ + Name: fmt.Sprintf("user-%d", i), + } + resp, err := client.Hello(context.Background(), req) + if err != nil { + log.Error(err) + } + log.Info("resp", log.ToJsonString(resp)) + } +} +``` + +Logger output: + +```shell +{"STEP_1":"Hello service","client_ip":"127.0.0.1:62328","code":"OK","level":"info","msg":"latency: 9.363µs","request":{"name":"user-0"},"response":{"message":"Hello user-0"},"start":"2021-10-17T16:34:56.495895+07:00","time":"2021-10-17T16:34:56+07:00","uri":"/hello.HelloService/Hello"} +{"STEP_1":"Hello service","client_ip":"127.0.0.1:62328","code":"OK","level":"info","msg":"latency: 34.926µs","request":{"name":"user-1"},"response":{"message":"Hello user-1"},"start":"2021-10-17T16:34:56.496685+07:00","time":"2021-10-17T16:34:56+07:00","uri":"/hello.HelloService/Hello"} +{"STEP_1":"Hello service","client_ip":"127.0.0.1:62328","code":"OK","level":"info","msg":"latency: 26.017µs","request":{"name":"user-2"},"response":{"message":"Hello user-2"},"start":"2021-10-17T16:34:56.497186+07:00","time":"2021-10-17T16:34:56+07:00","uri":"/hello.HelloService/Hello"} +{"STEP_1":"Hello service","client_ip":"127.0.0.1:62328","code":"OK","level":"info","msg":"latency: 23.865µs","request":{"name":"user-3"},"response":{"message":"Hello user-3"},"start":"2021-10-17T16:34:56.497793+07:00","time":"2021-10-17T16:34:56+07:00","uri":"/hello.HelloService/Hello"} +{"STEP_1":"Hello service","client_ip":"127.0.0.1:62328","code":"OK","level":"info","msg":"latency: 16.271µs","request":{"name":"user-4"},"response":{"message":"Hello user-4"},"start":"2021-10-17T16:34:56.498207+07:00","time":"2021-10-17T16:34:56+07:00","uri":"/hello.HelloService/Hello"} +{"STEP_1":"Hello service","client_ip":"127.0.0.1:62328","code":"OK","level":"info","msg":"latency: 17.859µs","request":{"name":"user-5"},"response":{"message":"Hello user-5"},"start":"2021-10-17T16:34:56.498731+07:00","time":"2021-10-17T16:34:56+07:00","uri":"/hello.HelloService/Hello"} +``` diff --git a/echo.go b/echo.go index 47eea76..7831ca4 100644 --- a/echo.go +++ b/echo.go @@ -9,7 +9,7 @@ import ( func EchoMiddleware(next echo.HandlerFunc) echo.HandlerFunc { return func(ctx echo.Context) error { - logger := New(&JSONFormatter{}) + logger := New(WithFormatter(&JSONFormatter{})) var ( clientIP = ctx.RealIP() method = ctx.Request().Method diff --git a/echo_test.go b/echo_test.go index 5ee245e..4883773 100644 --- a/echo_test.go +++ b/echo_test.go @@ -14,12 +14,11 @@ import ( func TestEchoMiddleware(t *testing.T) { var ( - l = New(&JSONFormatter{}) buf = &bytes.Buffer{} ) + New(WithFormatter(&JSONFormatter{}),WithOutput(buf)) server := echo.New() server.Use(EchoMiddleware) - l.Logger.SetOutput(buf) server.GET("/hello/:name", func(ctx echo.Context) error { logger := GetLogger(ctx.Request().Context()) name := ctx.Param("name") @@ -57,13 +56,13 @@ func TestEchoMiddleware(t *testing.T) { func TestEchoMiddlewareError(t *testing.T) { var ( - l = New(&JSONFormatter{}) buf = &bytes.Buffer{} testErr = errors.New("test err") ) + New(WithFormatter(&JSONFormatter{}),WithOutput(buf)) server := echo.New() server.Use(EchoMiddleware) - l.Logger.SetOutput(buf) + server.GET("/hello/:name", func(ctx echo.Context) error { logger := GetLogger(ctx.Request().Context()) name := ctx.Param("name") diff --git a/examples/echo/echo.go b/examples/echo/echo.go new file mode 100644 index 0000000..6459a27 --- /dev/null +++ b/examples/echo/echo.go @@ -0,0 +1,22 @@ +package main + +import ( + "github.com/labstack/echo/v4" + "github.com/trinhdaiphuc/logger" +) + +func main() { + server := echo.New() + server.Use(logger.EchoMiddleware) + + server.GET("/hello/:name", func(ctx echo.Context) error { + log := logger.GetLogger(ctx.Request().Context()) + name := ctx.Param("name") + log.AddLog("request name %v", name) + return ctx.String(200, "Hello "+name) + }) + + if err := server.Start(":8080"); err != nil { + panic(err) + } +} diff --git a/examples/fiber/fiber.go b/examples/fiber/fiber.go new file mode 100644 index 0000000..ead240f --- /dev/null +++ b/examples/fiber/fiber.go @@ -0,0 +1,22 @@ +package main + +import ( + "github.com/gofiber/fiber/v2" + "github.com/trinhdaiphuc/logger" +) + +func main() { + app := fiber.New() + app.Use(logger.FiberMiddleware()) + + app.Get("/hello/:name", func(ctx *fiber.Ctx) error { + log := logger.GetLogger(ctx.Context()) + name := ctx.Params("name") + log.AddLog("request name %v", name) + return ctx.Status(200).SendString("Hello " + name) + }) + + if err := app.Listen(":8080"); err != nil { + panic(err) + } +} diff --git a/examples/gin/gin.go b/examples/gin/gin.go new file mode 100644 index 0000000..1ba90eb --- /dev/null +++ b/examples/gin/gin.go @@ -0,0 +1,22 @@ +package main + +import ( + "github.com/gin-gonic/gin" + "github.com/trinhdaiphuc/logger" +) + +func main() { + gin.SetMode(gin.ReleaseMode) + server := gin.New() + server.Use(logger.GinMiddleware()) + server.GET("/hello/:name", func(ctx *gin.Context) { + log := logger.GetLogger(ctx) + name := ctx.Param("name") + log.AddLog("request name %v", name) + ctx.String(200, "Hello "+name) + }) + + if err := server.Run(":8080"); err != nil { + panic(err) + } +} diff --git a/examples/grpc/client/client.go b/examples/grpc/client/client.go new file mode 100644 index 0000000..d6066e1 --- /dev/null +++ b/examples/grpc/client/client.go @@ -0,0 +1,30 @@ +package main + +import ( + "context" + "fmt" + "github.com/trinhdaiphuc/logger" + pb "github.com/trinhdaiphuc/logger/proto/hello" + "google.golang.org/grpc" +) + +func main() { + conn, err := grpc.Dial(":50051", grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + log := logger.New(logger.WithFormatter(&logger.TextFormatter{})) + client := pb.NewHelloServiceClient(conn) + + for i := 0; i <= 5; i++ { + req := &pb.HelloRequest{ + Name: fmt.Sprintf("user-%d", i), + } + resp, err := client.Hello(context.Background(), req) + if err != nil { + log.Error(err) + } + log.Info("resp", log.ToJsonString(resp)) + } +} diff --git a/examples/grpc/grpc.go b/examples/grpc/grpc.go new file mode 100644 index 0000000..6fade35 --- /dev/null +++ b/examples/grpc/grpc.go @@ -0,0 +1,57 @@ +package main + +import ( + "context" + "fmt" + "github.com/trinhdaiphuc/logger" + pb "github.com/trinhdaiphuc/logger/proto/hello" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "net" + "os" + "os/signal" + "syscall" +) + +type HelloService struct{} + +var _ pb.HelloServiceServer = (*HelloService)(nil) + +func (h HelloService) Hello(ctx context.Context, request *pb.HelloRequest) (*pb.HelloResponse, error) { + log := logger.GetLogger(ctx) + log.AddLog("Hello service") + if len(request.Name) == 0 { + log.AddLog("empty name") + return nil, status.Error(codes.InvalidArgument, "empty name") + } + return &pb.HelloResponse{Message: "Hello " + request.Name}, nil +} + +func main() { + listener, err := net.Listen("tcp", ":50051") + if err != nil { + panic(err) + } + server := grpc.NewServer(grpc.UnaryInterceptor( + logger.GrpcInterceptor, + )) + + pb.RegisterHelloServiceServer(server, &HelloService{}) + + go func() { + if err := server.Serve(listener); err != nil { + panic(err) + } + }() + + // Block main routine until a signal is received + c := make(chan os.Signal) + signal.Notify(c, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL, syscall.SIGHUP, syscall.SIGQUIT) + <-c + + fmt.Println("Gracefully shutting down...") + server.GracefulStop() + listener.Close() + fmt.Println("GRPC was successful shutdown.") +} diff --git a/fiber.go b/fiber.go index 65f9c83..c70b990 100644 --- a/fiber.go +++ b/fiber.go @@ -8,7 +8,7 @@ import ( func FiberMiddleware() fiber.Handler { return func(ctx *fiber.Ctx) error { - logger := New(&JSONFormatter{}) + logger := New(WithFormatter(&JSONFormatter{})) var ( clientIP = ctx.IP() method = ctx.Method() diff --git a/fiber_test.go b/fiber_test.go index 3e397a0..fc1985f 100644 --- a/fiber_test.go +++ b/fiber_test.go @@ -14,12 +14,12 @@ import ( func TestFiberMiddleware(t *testing.T) { var ( - l = New(&JSONFormatter{}) buf = &bytes.Buffer{} ) + New(WithFormatter(&JSONFormatter{}),WithOutput(buf)) server := fiber.New() server.Use(FiberMiddleware()) - l.Logger.SetOutput(buf) + server.Get("/hello/:name", func(ctx *fiber.Ctx) error { logger := GetLogger(ctx.Context()) name := ctx.Params("name") @@ -57,13 +57,13 @@ func TestFiberMiddleware(t *testing.T) { func TestFiberMiddlewareError(t *testing.T) { var ( - l = New(&JSONFormatter{}) buf = &bytes.Buffer{} testErr = errors.New("test err") ) + New(WithFormatter(&JSONFormatter{}),WithOutput(buf)) server := fiber.New() server.Use(FiberMiddleware()) - l.Logger.SetOutput(buf) + server.Get("/hello/:name", func(ctx *fiber.Ctx) error { logger := GetLogger(ctx.Context()) name := ctx.Params("name") diff --git a/gin.go b/gin.go index c7a035b..131bcf3 100644 --- a/gin.go +++ b/gin.go @@ -9,7 +9,7 @@ import ( func GinMiddleware() gin.HandlerFunc { return func(ctx *gin.Context) { - logger := New(&JSONFormatter{}) + logger := New(WithFormatter(&JSONFormatter{})) var ( clientIP = ctx.ClientIP() method = ctx.Request.Method diff --git a/gin_test.go b/gin_test.go index f513ec7..a6a7a2c 100644 --- a/gin_test.go +++ b/gin_test.go @@ -13,12 +13,12 @@ import ( func TestGinMiddleware(t *testing.T) { var ( - l = New(&JSONFormatter{}) buf = &bytes.Buffer{} ) + New(WithFormatter(&JSONFormatter{}),WithOutput(buf)) server := gin.New() server.Use(GinMiddleware()) - l.Logger.SetOutput(buf) + server.GET("/hello/:name", func(ctx *gin.Context) { logger := GetLogger(ctx) name := ctx.Param("name") @@ -56,13 +56,13 @@ func TestGinMiddleware(t *testing.T) { func TestGinMiddlewareError(t *testing.T) { var ( - l = New(&JSONFormatter{}) buf = &bytes.Buffer{} testErr = errors.New("test err") ) + New(WithFormatter(&JSONFormatter{}),WithOutput(buf)) server := gin.New() server.Use(GinMiddleware()) - l.Logger.SetOutput(buf) + server.GET("/hello/:name", func(ctx *gin.Context) { logger := GetLogger(ctx) name := ctx.Param("name") diff --git a/go.mod b/go.mod index 740cf77..78a12e7 100644 --- a/go.mod +++ b/go.mod @@ -4,16 +4,24 @@ go 1.16 require ( github.com/andybalholm/brotli v1.0.3 // indirect + github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect github.com/gin-gonic/gin v1.7.4 github.com/go-playground/validator/v10 v10.9.0 // indirect github.com/gofiber/fiber/v2 v2.20.2 + github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.13.6 // indirect github.com/labstack/echo/v4 v4.6.1 + github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 // indirect + github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f + github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 // indirect github.com/mattn/go-colorable v0.1.11 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.0 + github.com/tebeka/strftime v0.1.5 // indirect github.com/ugorji/go v1.2.6 // indirect github.com/valyala/fasthttp v1.31.0 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect diff --git a/go.sum b/go.sum index b3451c7..68e1b38 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 h1:Ghm4eQYC0nEPnSJdVkTrXpu9KtoVCSo1hg7mtI7G9KU= +github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -71,6 +73,10 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4= +github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -92,6 +98,12 @@ github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 h1:0iQektZGS248WXmGIYOwRXSQhD4qn3icjMpuxwO7qlo= +github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570/go.mod h1:BLt8L9ld7wVsvEWQbuLrUZnCMnUmLZ+CGDzKtclrTlE= +github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f h1:sgUSP4zdTUZYZgAGGtN5Lxk92rK+JUFOwf+FT99EEI4= +github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f/go.mod h1:UGmTpUd3rjbtfIpwAPrcfmGf/Z1HS95TATB+m57TPB8= +github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 h1:Bvq8AziQ5jFF4BHGAEDSqwPW1NJS3XshxbRCxtjFAZc= +github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042/go.mod h1:TPpsiPUEh0zFL1Snz4crhMlBe60PYxRHr5oFF3rRYg0= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= @@ -108,6 +120,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -126,6 +140,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 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/tebeka/strftime v0.1.5 h1:1NQKN1NiQgkqd/2moD6ySP/5CoZQsKa1d3ZhJ44Jpmg= +github.com/tebeka/strftime v0.1.5/go.mod h1:29/OidkoWHdEKZqzyDLUyC+LmgDgdHo4WAFCDT7D/Ig= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= diff --git a/grpc.go b/grpc.go index 5ca0c49..9d06396 100644 --- a/grpc.go +++ b/grpc.go @@ -12,19 +12,19 @@ import ( func GrpcInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { var ( - log = New(&JSONFormatter{}) + log = New(WithFormatter(&JSONFormatter{})) start = time.Now() panicking = true ) p, ok := peer.FromContext(ctx) if ok { - log.WithField("request_ip", p.Addr.String()) + log.WithField(ClientIPField, p.Addr.String()) } log.WithFields(map[string]interface{}{ StartField: start, URIField: info.FullMethod, - RequestField: log.ToJsonString(req), + RequestField: req, }) defer func() { diff --git a/logger.go b/logger.go index 5fa5ec6..3511997 100644 --- a/logger.go +++ b/logger.go @@ -5,8 +5,8 @@ import ( "encoding/json" "fmt" "github.com/sirupsen/logrus" + "io" "sync" - "time" ) type Log struct { @@ -18,6 +18,7 @@ type Log struct { type TextFormatter = logrus.TextFormatter type JSONFormatter = logrus.JSONFormatter type Formatter = logrus.Formatter +type Option func() const ( Key = "Logger" @@ -35,13 +36,25 @@ const ( ) // New return a new log object with log start time -func New(formatter ...Formatter) *Log { - if len(formatter) > 0 { - logrus.SetFormatter(formatter[0]) +func New(opts ...Option) *Log { + for _, opt := range opts { + opt() } - logTime := time.Now().Format(time.RFC3339) + return &Log{ - Entry: logrus.WithField("Time", logTime), + Entry: logrus.NewEntry(logrus.StandardLogger()), + } +} + +func WithFormatter(formatter Formatter) Option { + return func() { + logrus.SetFormatter(formatter) + } +} + +func WithOutput(output io.Writer) Option { + return func() { + logrus.SetOutput(output) } } diff --git a/logger_test.go b/logger_test.go index a790f98..e8b728c 100644 --- a/logger_test.go +++ b/logger_test.go @@ -23,8 +23,7 @@ const ( func TestFieldValueError(t *testing.T) { buf := &bytes.Buffer{} - l := New(&JSONFormatter{}) - l.Logger.SetOutput(buf) + l := New(WithFormatter(&JSONFormatter{}), WithOutput(buf)) l.WithField("func", func() {}).Info("test") t.Log("buffer", buf.String()) var data map[string]interface{} @@ -56,12 +55,10 @@ func TestContextWithNoLogger(t *testing.T) { func TestContextWithLogger(t *testing.T) { var ( buf = &bytes.Buffer{} - l = New() + l = New(WithFormatter(&TextFormatter{}), WithOutput(buf)) ctx = context.WithValue(context.Background(), Key, l) ) logger := GetLogger(ctx) - logger.Logger.SetFormatter(&TextFormatter{}) - logger.Logger.SetOutput(buf) logger.AddLog("hello %v", "world") logger.WithFields(map[string]interface{}{ "K1": "V1",