clean access logging (#996)

pull/999/head
Tony Chen 4 years ago committed by GitHub
parent af14c07762
commit 5ed0c006a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 28
      examples/helloworld/client/main.go
  2. 54
      middleware/logging/grpc.go
  3. 56
      middleware/logging/http.go
  4. 204
      middleware/logging/logging.go

@ -2,11 +2,13 @@ package main
import ( import (
"context" "context"
"log" "fmt"
pb "github.com/go-kratos/kratos/examples/helloworld/helloworld" pb "github.com/go-kratos/kratos/examples/helloworld/helloworld"
"github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/middleware" "github.com/go-kratos/kratos/v2/middleware"
"github.com/go-kratos/kratos/v2/middleware/logging"
"github.com/go-kratos/kratos/v2/middleware/recovery" "github.com/go-kratos/kratos/v2/middleware/recovery"
transgrpc "github.com/go-kratos/kratos/v2/transport/grpc" transgrpc "github.com/go-kratos/kratos/v2/transport/grpc"
transhttp "github.com/go-kratos/kratos/v2/transport/http" transhttp "github.com/go-kratos/kratos/v2/transport/http"
@ -18,59 +20,63 @@ func main() {
} }
func callHTTP() { func callHTTP() {
logger := log.DefaultLogger
conn, err := transhttp.NewClient( conn, err := transhttp.NewClient(
context.Background(), context.Background(),
transhttp.WithMiddleware( transhttp.WithMiddleware(
recovery.Recovery(), recovery.Recovery(),
logging.Client(logger),
), ),
transhttp.WithEndpoint("127.0.0.1:8000"), transhttp.WithEndpoint("127.0.0.1:8000"),
) )
if err != nil { if err != nil {
log.Fatal(err) panic(err)
} }
client := pb.NewGreeterHTTPClient(conn) client := pb.NewGreeterHTTPClient(conn)
reply, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "kratos"}) reply, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "kratos"})
if err != nil { if err != nil {
log.Fatal(err) panic(err)
} }
log.Printf("[http] SayHello %s\n", reply.Message) logger.Log(log.LevelInfo, fmt.Sprintf("[http] SayHello %s\n", reply.Message))
// returns error // returns error
reply, err = client.SayHello(context.Background(), &pb.HelloRequest{Name: "error"}) reply, err = client.SayHello(context.Background(), &pb.HelloRequest{Name: "error"})
if err != nil { if err != nil {
log.Printf("[http] SayHello error: %v\n", err) logger.Log(log.LevelInfo, fmt.Sprintf("[http] SayHello error: %v\n", err))
} }
if errors.IsBadRequest(err) { if errors.IsBadRequest(err) {
log.Printf("[http] SayHello error is invalid argument: %v\n", err) logger.Log(log.LevelInfo, fmt.Sprintf("[http] SayHello error is invalid argument: %v\n", err))
} }
} }
func callGRPC() { func callGRPC() {
logger := log.DefaultLogger
conn, err := transgrpc.DialInsecure( conn, err := transgrpc.DialInsecure(
context.Background(), context.Background(),
transgrpc.WithEndpoint("127.0.0.1:9000"), transgrpc.WithEndpoint("127.0.0.1:9000"),
transgrpc.WithMiddleware( transgrpc.WithMiddleware(
middleware.Chain( middleware.Chain(
recovery.Recovery(), recovery.Recovery(),
logging.Client(logger),
), ),
), ),
) )
if err != nil { if err != nil {
log.Fatal(err) panic(err)
} }
client := pb.NewGreeterClient(conn) client := pb.NewGreeterClient(conn)
reply, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "kratos"}) reply, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "kratos"})
if err != nil { if err != nil {
log.Fatal(err) panic(err)
} }
log.Printf("[grpc] SayHello %+v\n", reply) logger.Log(log.LevelInfo, fmt.Sprintf("[grpc] SayHello %+v", reply))
// returns error // returns error
_, err = client.SayHello(context.Background(), &pb.HelloRequest{Name: "error"}) _, err = client.SayHello(context.Background(), &pb.HelloRequest{Name: "error"})
if err != nil { if err != nil {
log.Printf("[grpc] SayHello error: %v\n", err) logger.Log(log.LevelInfo, fmt.Sprintf("[grpc] SayHello error: %v", err))
} }
if errors.IsBadRequest(err) { if errors.IsBadRequest(err) {
log.Printf("[grpc] SayHello error is invalid argument: %v\n", err) logger.Log(log.LevelInfo, fmt.Sprintf("[grpc] SayHello error is invalid argument: %v", err))
} }
} }

@ -0,0 +1,54 @@
package logging
import (
"context"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/transport/grpc"
)
func grpcServerLog(logger log.Logger, ctx context.Context, args string, err error) {
info, ok := grpc.FromServerContext(ctx)
if !ok {
return
}
traceID, spanID := extractTrace(ctx)
code, errMsg := extractError(err)
level := log.LevelInfo
if err != nil {
level = log.LevelError
}
logger.Log(level,
"kind", "server",
"component", "grpc",
"trace_id", traceID,
"span_id", spanID,
"grpc.target", info.FullMethod,
"grpc.args", args,
"grpc.code", code,
"grpc.error", errMsg,
)
}
func grpcClientLog(logger log.Logger, ctx context.Context, args string, err error) {
info, ok := grpc.FromClientContext(ctx)
if !ok {
return
}
traceID, spanID := extractTrace(ctx)
code, errMsg := extractError(err)
level := log.LevelInfo
if err != nil {
level = log.LevelError
}
logger.Log(level,
"kind", "client",
"component", "grpc",
"trace_id", traceID,
"span_id", spanID,
"grpc.target", info.FullMethod,
"grpc.args", args,
"grpc.code", code,
"grpc.error", errMsg,
)
}

@ -0,0 +1,56 @@
package logging
import (
"context"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/transport/http"
)
func httpServerLog(logger log.Logger, ctx context.Context, args string, err error) {
info, ok := http.FromServerContext(ctx)
if !ok {
return
}
traceID, spanID := extractTrace(ctx)
code, errMsg := extractError(err)
level := log.LevelInfo
if err != nil {
level = log.LevelError
}
logger.Log(level,
"kind", "server",
"component", "http",
"trace_id", traceID,
"span_id", spanID,
"http.target", info.Request.RequestURI,
"http.method", info.Request.Method,
"http.args", args,
"http.code", code,
"http.error", errMsg,
)
}
func httpClientLog(logger log.Logger, ctx context.Context, args string, err error) {
info, ok := http.FromClientContext(ctx)
if !ok {
return
}
traceID, spanID := extractTrace(ctx)
code, errMsg := extractError(err)
level := log.LevelInfo
if err != nil {
level = log.LevelError
}
logger.Log(level,
"kind", "client",
"component", "http",
"trace_id", traceID,
"span_id", spanID,
"http.target", info.Request.RequestURI,
"http.method", info.Request.Method,
"http.args", args,
"http.code", code,
"http.error", errMsg,
)
}

@ -9,175 +9,67 @@ import (
"github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/middleware" "github.com/go-kratos/kratos/v2/middleware"
"github.com/go-kratos/kratos/v2/transport/grpc" "github.com/go-kratos/kratos/v2/transport"
"github.com/go-kratos/kratos/v2/transport/http"
) )
// Server is an server logging middleware. // Server is an server logging middleware.
func Server(l log.Logger) middleware.Middleware { func Server(logger log.Logger) middleware.Middleware {
logger := log.NewHelper(l)
return func(handler middleware.Handler) middleware.Handler { return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{}) (interface{}, error) { return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
var ( reply, err = handler(ctx, req)
path string if tr, ok := transport.FromContext(ctx); ok {
method string switch tr.Kind {
args string case transport.KindHTTP:
component string httpServerLog(logger, ctx, extractArgs(req), err)
query string case transport.KindGRPC:
traceID string grpcServerLog(logger, ctx, extractArgs(req), err)
)
if tid := trace.SpanContextFromContext(ctx).TraceID(); tid.IsValid() {
traceID = tid.String()
} }
if stringer, ok := req.(fmt.Stringer); ok {
args = stringer.String()
} else {
args = fmt.Sprintf("%+v", req)
}
if info, ok := http.FromServerContext(ctx); ok {
component = "HTTP"
path = info.Request.URL.Path
method = info.Request.Method
query = info.Request.URL.RawQuery
} else if info, ok := grpc.FromServerContext(ctx); ok {
component = "gRPC"
path = info.FullMethod
method = "POST"
}
reply, err := handler(ctx, req)
if component == "HTTP" {
if err != nil {
logger.Errorw(
"kind", "server",
"component", component,
"traceID", traceID,
"path", path,
"method", method,
"args", args,
"query", query,
"code", uint32(errors.Code(err)),
"error", err.Error(),
)
return nil, err
}
logger.Infow(
"kind", "server",
"component", component,
"traceID", traceID,
"path", path,
"method", method,
"args", args,
"query", query,
"code", 0,
)
} else {
if err != nil {
logger.Errorw(
"kind", "server",
"component", component,
"traceID", traceID,
"path", path,
"method", method,
"args", args,
"code", uint32(errors.Code(err)),
"error", err.Error(),
)
return nil, err
}
logger.Infow(
"kind", "server",
"component", component,
"traceID", traceID,
"path", path,
"method", method,
"args", args,
"code", 0,
)
} }
return reply, nil return
} }
} }
} }
// Client is an client logging middleware. // Client is an client logging middleware.
func Client(l log.Logger) middleware.Middleware { func Client(logger log.Logger) middleware.Middleware {
logger := log.NewHelper(l)
return func(handler middleware.Handler) middleware.Handler { return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{}) (interface{}, error) { return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
var ( reply, err = handler(ctx, req)
path string if tr, ok := transport.FromContext(ctx); ok {
method string switch tr.Kind {
args string case transport.KindHTTP:
component string httpClientLog(logger, ctx, extractArgs(req), err)
query string case transport.KindGRPC:
traceID string grpcClientLog(logger, ctx, extractArgs(req), err)
) }
if tid := trace.SpanContextFromContext(ctx).TraceID(); tid.IsValid() { }
traceID = tid.String() return
} }
if info, ok := http.FromClientContext(ctx); ok { }
component = "HTTP" }
path = info.Request.URL.Path
method = info.Request.Method func extractArgs(req interface{}) string {
args = req.(fmt.Stringer).String() if stringer, ok := req.(fmt.Stringer); ok {
query = info.Request.URL.RawQuery return stringer.String()
} else if info, ok := grpc.FromClientContext(ctx); ok { }
path = info.FullMethod return fmt.Sprintf("%+v", req)
method = "POST" }
component = "gRPC"
args = req.(fmt.Stringer).String() func extractTrace(ctx context.Context) (traceID, spanID string) {
} span := trace.SpanContextFromContext(ctx)
reply, err := handler(ctx, req) if span.HasTraceID() {
if component == "HTTP" { traceID = span.TraceID().String()
if err != nil {
logger.Errorw(
"kind", "client",
"component", component,
"traceID", traceID,
"path", path,
"method", method,
"args", args,
"query", query,
"code", uint32(errors.Code(err)),
"error", err.Error(),
)
return nil, err
}
logger.Infow(
"kind", "client",
"component", component,
"traceID", traceID,
"path", path,
"method", method,
"args", args,
"query", query,
"code", 0,
)
} else {
if err != nil {
logger.Errorw(
"kind", "client",
"component", component,
"traceID", traceID,
"path", path,
"method", method,
"args", args,
"code", uint32(errors.Code(err)),
"error", err.Error(),
)
return nil, err
}
logger.Infow(
"kind", "client",
"component", component,
"traceID", traceID,
"path", path,
"method", method,
"args", args,
"code", 0,
)
} }
return reply, nil if span.HasSpanID() {
spanID = span.SpanID().String()
} }
return
}
func extractError(err error) (code int, errMsg string) {
if err != nil {
code = errors.Code(err)
errMsg = fmt.Sprintf("%+v", err)
} }
return
} }

Loading…
Cancel
Save