From 3d7e0057bc150a6972e3ed5472f8294f9477bc59 Mon Sep 17 00:00:00 2001 From: Dominic Green Date: Wed, 28 Feb 2018 14:51:59 +0000 Subject: [PATCH 1/4] fixing vet issues ... most relating to the Examples --- auth/DOC.md | 57 +++++++++ auth/auth_test.go | 4 +- auth/examples_test.go | 2 +- logging/logrus/DOC.md | 79 +++++++++++++ logging/logrus/ctxlogrus/DOC.md | 35 ++++++ logging/logrus/ctxlogrus/examples_test.go | 19 ++- logging/logrus/examples_test.go | 6 +- logging/zap/DOC.md | 137 +++++++++++++++++----- logging/zap/ctxzap/DOC.md | 40 +++++++ logging/zap/ctxzap/examples_test.go | 2 +- logging/zap/examples_test.go | 8 +- retry/DOC.md | 79 +++++++++++++ retry/examples_test.go | 8 +- tags/DOC.md | 39 ++++++ tags/examples_test.go | 4 +- 15 files changed, 461 insertions(+), 58 deletions(-) diff --git a/auth/DOC.md b/auth/DOC.md index e31288aa8..5834112b0 100644 --- a/auth/DOC.md +++ b/auth/DOC.md @@ -4,6 +4,7 @@ * [Overview](#pkg-overview) * [Imported Packages](#pkg-imports) * [Index](#pkg-index) +* [Examples](#pkg-examples) ## Overview `grpc_auth` a generic server-side auth middleware for gRPC. @@ -20,6 +21,59 @@ It also allows for per-service implementation overrides of `AuthFunc`. See `Serv Please see examples for simple examples of use. +#### Example: + +
+Click to expand code. + +```go +package grpc_auth_test + +import ( + "github.com/grpc-ecosystem/go-grpc-middleware/auth" + "github.com/grpc-ecosystem/go-grpc-middleware/tags" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" +) + +var ( + cc *grpc.ClientConn +) + +func parseToken(token string) (struct{}, error) { + return struct{}{}, nil +} + +func userClaimFromToken(struct{}) string { + return "foobar" +} + +// Simple example of server initialization code. +func Example_serverConfig() { + exampleAuthFunc := func(ctx context.Context) (context.Context, error) { + token, err := grpc_auth.AuthFromMD(ctx, "bearer") + if err != nil { + return nil, err + } + tokenInfo, err := parseToken(token) + if err != nil { + return nil, grpc.Errorf(codes.Unauthenticated, "invalid auth token: %v", err) + } + grpc_ctxtags.Extract(ctx).Set("auth.sub", userClaimFromToken(tokenInfo)) + newCtx := context.WithValue(ctx, "tokenInfo", tokenInfo) + return newCtx, nil + } + + _ = grpc.NewServer( + grpc.StreamInterceptor(grpc_auth.StreamServerInterceptor(exampleAuthFunc)), + grpc.UnaryInterceptor(grpc_auth.UnaryServerInterceptor(exampleAuthFunc)), + ) +} +``` + +
+ ## Imported Packages - [github.com/grpc-ecosystem/go-grpc-middleware](./..) @@ -35,6 +89,9 @@ Please see examples for simple examples of use. * [type AuthFunc](#AuthFunc) * [type ServiceAuthFuncOverride](#ServiceAuthFuncOverride) +#### Examples +* [Package (ServerConfig)](#example__serverConfig) + #### Package files [auth.go](./auth.go) [doc.go](./doc.go) [metadata.go](./metadata.go) diff --git a/auth/auth_test.go b/auth/auth_test.go index 8b62ea2f0..6ca7683f6 100644 --- a/auth/auth_test.go +++ b/auth/auth_test.go @@ -110,7 +110,7 @@ func (s *AuthTestSuite) TestUnary_PassesAuth() { } func (s *AuthTestSuite) TestUnary_PassesWithPerRpcCredentials() { - grpcCreds := oauth.TokenSource{&fakeOAuth2TokenSource{accessToken: commonAuthToken}} + grpcCreds := oauth.TokenSource{TokenSource: &fakeOAuth2TokenSource{accessToken: commonAuthToken}} client := s.NewClient(grpc.WithPerRPCCredentials(grpcCreds)) _, err := client.Ping(s.SimpleCtx(), goodPing) require.NoError(s.T(), err, "no error must occur") @@ -141,7 +141,7 @@ func (s *AuthTestSuite) TestStream_PassesAuth() { } func (s *AuthTestSuite) TestStream_PassesWithPerRpcCredentials() { - grpcCreds := oauth.TokenSource{&fakeOAuth2TokenSource{accessToken: commonAuthToken}} + grpcCreds := oauth.TokenSource{TokenSource: &fakeOAuth2TokenSource{accessToken: commonAuthToken}} client := s.NewClient(grpc.WithPerRPCCredentials(grpcCreds)) stream, err := client.PingList(s.SimpleCtx(), goodPing) require.NoError(s.T(), err, "should not fail on establishing the stream") diff --git a/auth/examples_test.go b/auth/examples_test.go index 12299da55..916daa931 100644 --- a/auth/examples_test.go +++ b/auth/examples_test.go @@ -21,7 +21,7 @@ func userClaimFromToken(struct{}) string { } // Simple example of server initialization code. -func Example_ServerConfig() { +func Example_serverConfig() { exampleAuthFunc := func(ctx context.Context) (context.Context, error) { token, err := grpc_auth.AuthFromMD(ctx, "bearer") if err != nil { diff --git a/logging/logrus/DOC.md b/logging/logrus/DOC.md index 1f631cb25..333149347 100644 --- a/logging/logrus/DOC.md +++ b/logging/logrus/DOC.md @@ -75,6 +75,63 @@ Note - due to implementation ZAP differs from Logrus in the "grpc.request.conten Please see examples and tests for examples of use. +#### Example: + +
+Click to expand code. + +```go +// Logrus entry is used, allowing pre-definition of certain fields by the user. +logrusEntry := logrus.NewEntry(logrusLogger) +// Shared options for the logger, with a custom gRPC code to log level function. +opts := []grpc_logrus.Option{ + grpc_logrus.WithLevels(customFunc), +} +// Make sure that log statements internal to gRPC library are logged using the zapLogger as well. +grpc_logrus.ReplaceGrpcLogger(logrusEntry) +// Create a server, make sure we put the grpc_ctxtags context before everything else. +_ = grpc.NewServer( + grpc_middleware.WithUnaryServerChain( + grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)), + grpc_logrus.UnaryServerInterceptor(logrusEntry, opts...), + ), + grpc_middleware.WithStreamServerChain( + grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)), + grpc_logrus.StreamServerInterceptor(logrusEntry, opts...), + ), +) +``` + +
+ +#### Example: + +
+Click to expand code. + +```go +// Logrus entry is used, allowing pre-definition of certain fields by the user. +logrusEntry := logrus.NewEntry(logrusLogger) +// Shared options for the logger, with a custom duration to log field function. +opts := []grpc_logrus.Option{ + grpc_logrus.WithDurationField(func(duration time.Duration) (key string, value interface{}) { + return "grpc.time_ns", duration.Nanoseconds() + }), +} +_ = grpc.NewServer( + grpc_middleware.WithUnaryServerChain( + grpc_ctxtags.UnaryServerInterceptor(), + grpc_logrus.UnaryServerInterceptor(logrusEntry, opts...), + ), + grpc_middleware.WithStreamServerChain( + grpc_ctxtags.StreamServerInterceptor(), + grpc_logrus.StreamServerInterceptor(logrusEntry, opts...), + ), +) +``` + +
+ ## Imported Packages - [github.com/golang/protobuf/jsonpb](https://godoc.org/github.com/golang/protobuf/jsonpb) @@ -115,7 +172,10 @@ Please see examples and tests for examples of use. * [func WithLevels(f CodeToLevel) Option](#WithLevels) #### Examples +* [Extract (Unary)](#example_Extract_unary) * [WithDecider](#example_WithDecider) +* [Package (Initialization)](#example__initialization) +* [Package (InitializationWithDurationFieldOverride)](#example__initializationWithDurationFieldOverride) #### Package files [client_interceptors.go](./client_interceptors.go) [context.go](./context.go) [doc.go](./doc.go) [grpclogger.go](./grpclogger.go) [options.go](./options.go) [payload_interceptors.go](./payload_interceptors.go) [server_interceptors.go](./server_interceptors.go) @@ -180,6 +240,25 @@ func Extract(ctx context.Context) *logrus.Entry Extract takes the call-scoped logrus.Entry from grpc_logrus middleware. Deprecated: should use the ctxlogrus.Extract instead +#### Example: + +
+Click to expand code. + +```go +_ = func(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) { + // Add fields the ctxtags of the request which will be added to all extracted loggers. + grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) + // Extract a single request-scoped logrus.Logger and log messages. + l := ctx_logrus.Extract(ctx) + l.Info("some ping") + l.Info("another ping") + return &pb_testproto.PingResponse{Value: ping.Value}, nil +} +``` + +
+ ## func [PayloadStreamClientInterceptor](./payload_interceptors.go#L74) ``` go func PayloadStreamClientInterceptor(entry *logrus.Entry, decider grpc_logging.ClientPayloadLoggingDecider) grpc.StreamClientInterceptor diff --git a/logging/logrus/ctxlogrus/DOC.md b/logging/logrus/ctxlogrus/DOC.md index 4061f288f..fb5cb3ae0 100644 --- a/logging/logrus/ctxlogrus/DOC.md +++ b/logging/logrus/ctxlogrus/DOC.md @@ -4,6 +4,7 @@ * [Overview](#pkg-overview) * [Imported Packages](#pkg-imports) * [Index](#pkg-index) +* [Examples](#pkg-examples) ## Overview `ctxlogrus` is a ctxlogger that is backed by logrus @@ -29,6 +30,9 @@ Please see examples and tests for examples of use. * [func Extract(ctx context.Context) \*logrus.Entry](#Extract) * [func ToContext(ctx context.Context, entry \*logrus.Entry) context.Context](#ToContext) +#### Examples +* [Extract (Unary)](#example_Extract_unary) + #### Package files [context.go](./context.go) [doc.go](./doc.go) [noop.go](./noop.go) @@ -47,6 +51,37 @@ Extract takes the call-scoped logrus.Entry from ctx_logrus middleware. If the ctx_logrus middleware wasn't used, a no-op `logrus.Entry` is returned. This makes it safe to use regardless. +#### Example: + +
+Click to expand code. + +```go +package ctxlogrus_test + +import ( + "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus" + "github.com/grpc-ecosystem/go-grpc-middleware/tags" + "github.com/sirupsen/logrus" + "golang.org/x/net/context" +) + +var logrusLogger *logrus.Logger + +// Simple unary handler that adds custom fields to the requests's context. These will be used for all log statements. +func ExampleExtract_unary() { + ctx := context.Background() + // setting tags will be added to the loggerr as log fields + grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) + // Extract a single request-scoped logrus.Logger and log messages. + l := ctxlogrus.Extract(ctx) + l.Info("some ping") + l.Info("another ping") +} +``` + +
+ ## func [ToContext](./context.go#L59) ``` go func ToContext(ctx context.Context, entry *logrus.Entry) context.Context diff --git a/logging/logrus/ctxlogrus/examples_test.go b/logging/logrus/ctxlogrus/examples_test.go index 9af2af9f2..87a179940 100644 --- a/logging/logrus/ctxlogrus/examples_test.go +++ b/logging/logrus/ctxlogrus/examples_test.go @@ -3,7 +3,6 @@ package ctxlogrus_test import ( "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus" "github.com/grpc-ecosystem/go-grpc-middleware/tags" - pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/testing/testproto" "github.com/sirupsen/logrus" "golang.org/x/net/context" ) @@ -11,14 +10,12 @@ import ( var logrusLogger *logrus.Logger // Simple unary handler that adds custom fields to the requests's context. These will be used for all log statements. -func Example_HandlerUsageUnaryPing() { - _ = func(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) { - // Add fields the ctxtags of the request which will be added to all extracted loggers. - grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) - // Extract a single request-scoped logrus.Logger and log messages. - l := ctxlogrus.Extract(ctx) - l.Info("some ping") - l.Info("another ping") - return &pb_testproto.PingResponse{Value: ping.Value}, nil - } +func ExampleExtract_unary() { + ctx := context.Background() + // setting tags will be added to the loggerr as log fields + grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) + // Extract a single request-scoped logrus.Logger and log messages. + l := ctxlogrus.Extract(ctx) + l.Info("some ping") + l.Info("another ping") } diff --git a/logging/logrus/examples_test.go b/logging/logrus/examples_test.go index 5fe42bfac..b361a8974 100644 --- a/logging/logrus/examples_test.go +++ b/logging/logrus/examples_test.go @@ -19,7 +19,7 @@ var ( ) // Initialization shows a relatively complex initialization sequence. -func Example_Initialization() { +func Example_initialization() { // Logrus entry is used, allowing pre-definition of certain fields by the user. logrusEntry := logrus.NewEntry(logrusLogger) // Shared options for the logger, with a custom gRPC code to log level function. @@ -41,7 +41,7 @@ func Example_Initialization() { ) } -func Example_InitializationWithDurationFieldOverride() { +func Example_initializationWithDurationFieldOverride() { // Logrus entry is used, allowing pre-definition of certain fields by the user. logrusEntry := logrus.NewEntry(logrusLogger) // Shared options for the logger, with a custom duration to log field function. @@ -63,7 +63,7 @@ func Example_InitializationWithDurationFieldOverride() { } // Simple unary handler that adds custom fields to the requests's context. These will be used for all log statements. -func Example_HandlerUsageUnaryPing() { +func ExampleExtract_unary() { _ = func(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) { // Add fields the ctxtags of the request which will be added to all extracted loggers. grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) diff --git a/logging/zap/DOC.md b/logging/zap/DOC.md index efe2fd496..0b389d161 100644 --- a/logging/zap/DOC.md +++ b/logging/zap/DOC.md @@ -77,6 +77,89 @@ Note - due to implementation ZAP differs from Logrus in the "grpc.request.conten Please see examples and tests for examples of use. +#### Example: + +
+Click to expand code. + +```go +// Shared options for the logger, with a custom gRPC code to log level function. +opts := []grpc_zap.Option{ + grpc_zap.WithLevels(customFunc), +} +// Make sure that log statements internal to gRPC library are logged using the zapLogger as well. +grpc_zap.ReplaceGrpcLogger(zapLogger) +// Create a server, make sure we put the grpc_ctxtags context before everything else. +_ = grpc.NewServer( + grpc_middleware.WithUnaryServerChain( + grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)), + grpc_zap.UnaryServerInterceptor(zapLogger, opts...), + ), + grpc_middleware.WithStreamServerChain( + grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)), + grpc_zap.StreamServerInterceptor(zapLogger, opts...), + ), +) +``` + +
+ +#### Example: + +
+Click to expand code. + +```go +opts := []grpc_zap.Option{ + grpc_zap.WithDecider(func(fullMethodName string, err error) bool { + // will not log gRPC calls if it was a call to healthcheck and no error was raised + if err == nil && fullMethodName == "foo.bar.healthcheck" { + return false + } + + // by default everything will be logged + return true + }), +} + +_ = []grpc.ServerOption{ + grpc_middleware.WithStreamServerChain( + grpc_ctxtags.StreamServerInterceptor(), + grpc_zap.StreamServerInterceptor(zap.NewNop(), opts...)), + grpc_middleware.WithUnaryServerChain( + grpc_ctxtags.UnaryServerInterceptor(), + grpc_zap.UnaryServerInterceptor(zap.NewNop(), opts...)), +} +``` + +
+ +#### Example: + +
+Click to expand code. + +```go +opts := []grpc_zap.Option{ + grpc_zap.WithDurationField(func(duration time.Duration) zapcore.Field { + return zap.Int64("grpc.time_ns", duration.Nanoseconds()) + }), +} + +_ = grpc.NewServer( + grpc_middleware.WithUnaryServerChain( + grpc_ctxtags.UnaryServerInterceptor(), + grpc_zap.UnaryServerInterceptor(zapLogger, opts...), + ), + grpc_middleware.WithStreamServerChain( + grpc_ctxtags.StreamServerInterceptor(), + grpc_zap.StreamServerInterceptor(zapLogger, opts...), + ), +) +``` + +
+ ## Imported Packages - [github.com/golang/protobuf/jsonpb](https://godoc.org/github.com/golang/protobuf/jsonpb) @@ -118,7 +201,10 @@ Please see examples and tests for examples of use. * [func WithLevels(f CodeToLevel) Option](#WithLevels) #### Examples -* [WithDecider](#example_WithDecider) +* [Extract (Unary)](#example_Extract_unary) +* [Package (Initialization)](#example__initialization) +* [Package (InitializationWithDecider)](#example__initializationWithDecider) +* [Package (InitializationWithDurationFieldOverride)](#example__initializationWithDurationFieldOverride) #### Package files [client_interceptors.go](./client_interceptors.go) [context.go](./context.go) [doc.go](./doc.go) [grpclogger.go](./grpclogger.go) [options.go](./options.go) [payload_interceptors.go](./payload_interceptors.go) [server_interceptors.go](./server_interceptors.go) @@ -190,6 +276,26 @@ func Extract(ctx context.Context) *zap.Logger Extract takes the call-scoped Logger from grpc_zap middleware. Deprecated: should use the ctxzap.Extract instead +#### Example: + +
+Click to expand code. + +```go +_ = func(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) { + // Add fields the ctxtags of the request which will be added to all extracted loggers. + grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) + + // Extract a single request-scoped zap.Logger and log messages. (containing the grpc.xxx tags) + l := ctx_zap.Extract(ctx) + l.Info("some ping") + l.Info("another ping") + return &pb_testproto.PingResponse{Value: ping.Value}, nil +} +``` + +
+ ## func [PayloadStreamClientInterceptor](./payload_interceptors.go#L74) ``` go func PayloadStreamClientInterceptor(logger *zap.Logger, decider grpc_logging.ClientPayloadLoggingDecider) grpc.StreamClientInterceptor @@ -280,35 +386,6 @@ func WithDecider(f grpc_logging.Decider) Option ``` WithDecider customizes the function for deciding if the gRPC interceptor logs should log. -#### Example: - -
-Click to expand code. - -```go -opts := []grpc_zap.Option{ - grpc_zap.WithDecider(func(fullMethodName string, err error) bool { - // will not log gRPC calls if it was a call to healthcheck and no error was raised - if err == nil && fullMethodName == "foo.bar.healthcheck" { - return false - } - - // by default everything will be logged - return true - }), -} - -_ = []grpc.ServerOption{ - grpc_middleware.WithStreamServerChain( - grpc_ctxtags.StreamServerInterceptor(), - grpc_zap.StreamServerInterceptor(zap.NewNop(), opts...)), - grpc_middleware.WithUnaryServerChain( - grpc_ctxtags.UnaryServerInterceptor(), - grpc_zap.UnaryServerInterceptor(zap.NewNop(), opts...)), -} -``` - -
### func [WithDurationField](./options.go#L78) ``` go func WithDurationField(f DurationToField) Option diff --git a/logging/zap/ctxzap/DOC.md b/logging/zap/ctxzap/DOC.md index 86ecf2398..bfe4e7880 100644 --- a/logging/zap/ctxzap/DOC.md +++ b/logging/zap/ctxzap/DOC.md @@ -4,6 +4,7 @@ * [Overview](#pkg-overview) * [Imported Packages](#pkg-imports) * [Index](#pkg-index) +* [Examples](#pkg-examples) ## Overview `ctxzap` is a ctxlogger that is backed by Zap @@ -31,6 +32,9 @@ Please see examples and tests for examples of use. * [func TagsToFields(ctx context.Context) []zapcore.Field](#TagsToFields) * [func ToContext(ctx context.Context, logger \*zap.Logger) context.Context](#ToContext) +#### Examples +* [Extract (Unary)](#example_Extract_unary) + #### Package files [context.go](./context.go) [doc.go](./doc.go) @@ -48,6 +52,42 @@ Extract takes the call-scoped Logger from grpc_zap middleware. It always returns a Logger that has all the grpc_ctxtags updated. +#### Example: + +
+Click to expand code. + +```go +package ctxzap_test + +import ( + "context" + + "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap" + "github.com/grpc-ecosystem/go-grpc-middleware/tags" + pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/testing/testproto" + "go.uber.org/zap" +) + +var zapLogger *zap.Logger + +// Simple unary handler that adds custom fields to the requests's context. These will be used for all log statements. +func ExampleExtract_unary() { + _ = func(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) { + // Add fields the ctxtags of the request which will be added to all extracted loggers. + grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) + + // Extract a single request-scoped zap.Logger and log messages. + l := ctxzap.Extract(ctx) + l.Info("some ping") + l.Info("another ping") + return &pb_testproto.PingResponse{Value: ping.Value}, nil + } +} +``` + +
+ ## func [TagsToFields](./context.go#L48) ``` go func TagsToFields(ctx context.Context) []zapcore.Field diff --git a/logging/zap/ctxzap/examples_test.go b/logging/zap/ctxzap/examples_test.go index f5db24190..c96d83c4d 100644 --- a/logging/zap/ctxzap/examples_test.go +++ b/logging/zap/ctxzap/examples_test.go @@ -12,7 +12,7 @@ import ( var zapLogger *zap.Logger // Simple unary handler that adds custom fields to the requests's context. These will be used for all log statements. -func Example_HandlerUsageUnaryPing() { +func ExampleExtract_unary() { _ = func(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) { // Add fields the ctxtags of the request which will be added to all extracted loggers. grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) diff --git a/logging/zap/examples_test.go b/logging/zap/examples_test.go index 0963bec00..264192bf2 100644 --- a/logging/zap/examples_test.go +++ b/logging/zap/examples_test.go @@ -20,7 +20,7 @@ var ( ) // Initialization shows a relatively complex initialization sequence. -func Example_Initialization() { +func Example_initialization() { // Shared options for the logger, with a custom gRPC code to log level function. opts := []grpc_zap.Option{ grpc_zap.WithLevels(customFunc), @@ -41,7 +41,7 @@ func Example_Initialization() { } // Initialization shows an initialization sequence with the duration field generation overridden. -func Example_InitializationWithDurationFieldOverride() { +func Example_initializationWithDurationFieldOverride() { opts := []grpc_zap.Option{ grpc_zap.WithDurationField(func(duration time.Duration) zapcore.Field { return zap.Int64("grpc.time_ns", duration.Nanoseconds()) @@ -61,7 +61,7 @@ func Example_InitializationWithDurationFieldOverride() { } // Simple unary handler that adds custom fields to the requests's context. These will be used for all log statements. -func Example_HandlerUsageUnaryPing() { +func ExampleExtract_unary() { _ = func(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) { // Add fields the ctxtags of the request which will be added to all extracted loggers. grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) @@ -74,7 +74,7 @@ func Example_HandlerUsageUnaryPing() { } } -func ExampleWithDecider() { +func Example_initializationWithDecider() { opts := []grpc_zap.Option{ grpc_zap.WithDecider(func(fullMethodName string, err error) bool { // will not log gRPC calls if it was a call to healthcheck and no error was raised diff --git a/retry/DOC.md b/retry/DOC.md index c88775a2b..bc62ed0a4 100644 --- a/retry/DOC.md +++ b/retry/DOC.md @@ -4,6 +4,7 @@ * [Overview](#pkg-overview) * [Imported Packages](#pkg-imports) * [Index](#pkg-index) +* [Examples](#pkg-examples) ## Overview `grpc_retry` provides client-side request retry logic for gRPC. @@ -25,6 +26,60 @@ whenever when a retry happens. Please see examples for more advanced use. +#### Example: + +
+Click to expand code. + +```go +grpc.Dial("myservice.example.com", + grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor()), + grpc.WithUnaryInterceptor(grpc_retry.UnaryClientInterceptor()), +) +``` + +
+ +#### Example: + +
+Click to expand code. + +```go +opts := []grpc_retry.CallOption{ + grpc_retry.WithBackoff(grpc_retry.BackoffLinear(100 * time.Millisecond)), + grpc_retry.WithCodes(codes.NotFound, codes.Aborted), +} +grpc.Dial("myservice.example.com", + grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor(opts...)), + grpc.WithUnaryInterceptor(grpc_retry.UnaryClientInterceptor(opts...)), +) +``` + +
+ +#### Example: + +
+Click to expand code. + +```go +client := pb_testproto.NewTestServiceClient(cc) +stream, _ := client.PingList(newCtx(1*time.Second), &pb_testproto.PingRequest{}, grpc_retry.WithMax(3)) + +for { + pong, err := stream.Recv() // retries happen here + if err == io.EOF { + break + } else if err != nil { + return + } + fmt.Printf("got pong: %v", pong) +} +``` + +
+ ## Imported Packages - [github.com/grpc-ecosystem/go-grpc-middleware/util/backoffutils](./../util/backoffutils) @@ -50,6 +105,12 @@ Please see examples for more advanced use. * [func WithMax(maxRetries uint) CallOption](#WithMax) * [func WithPerRetryTimeout(timeout time.Duration) CallOption](#WithPerRetryTimeout) +#### Examples +* [WithPerRetryTimeout](#example_WithPerRetryTimeout) +* [Package (Initialization)](#example__initialization) +* [Package (InitializationWithOptions)](#example__initializationWithOptions) +* [Package (SimpleCall)](#example__simpleCall) + #### Package files [backoff.go](./backoff.go) [doc.go](./doc.go) [options.go](./options.go) [retry.go](./retry.go) @@ -172,5 +233,23 @@ of the retry calls (including the initial one) will have a deadline of now + 3s. A value of 0 disables the timeout overrides completely and returns to each retry call using the parent `context.Deadline`. +#### Example: + +
+Click to expand code. + +```go +client := pb_testproto.NewTestServiceClient(cc) +pong, _ := client.Ping( + newCtx(5*time.Second), + &pb_testproto.PingRequest{}, + grpc_retry.WithMax(3), + grpc_retry.WithPerRetryTimeout(1*time.Second)) + +fmt.Printf("got pong: %v", pong) +``` + +
+ - - - Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd) \ No newline at end of file diff --git a/retry/examples_test.go b/retry/examples_test.go index 953bbd13c..7ca3cd9b8 100644 --- a/retry/examples_test.go +++ b/retry/examples_test.go @@ -23,7 +23,7 @@ func newCtx(timeout time.Duration) context.Context { } // Simple example of using the default interceptor configuration. -func Example_DialSimple() { +func Example_initialization() { grpc.Dial("myservice.example.com", grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor()), grpc.WithUnaryInterceptor(grpc_retry.UnaryClientInterceptor()), @@ -31,7 +31,7 @@ func Example_DialSimple() { } // Complex example with a 100ms linear backoff interval, and retry only on NotFound and Unavailable. -func Example_DialComplex() { +func Example_initializationWithOptions() { opts := []grpc_retry.CallOption{ grpc_retry.WithBackoff(grpc_retry.BackoffLinear(100 * time.Millisecond)), grpc_retry.WithCodes(codes.NotFound, codes.Aborted), @@ -43,7 +43,7 @@ func Example_DialComplex() { } // Simple example of an idempotent `ServerStream` call, that will be retried automatically 3 times. -func Example_SimpleCall() { +func Example_simpleCall() { client := pb_testproto.NewTestServiceClient(cc) stream, _ := client.PingList(newCtx(1*time.Second), &pb_testproto.PingRequest{}, grpc_retry.WithMax(3)) @@ -67,7 +67,7 @@ func Example_SimpleCall() { // // `WithPerRetryTimeout` allows you to shorten the deadline of each retry call, allowing you to fit // multiple retries in the single parent deadline. -func Example_DeadlineCall() { +func ExampleWithPerRetryTimeout() { client := pb_testproto.NewTestServiceClient(cc) pong, _ := client.Ping( newCtx(5*time.Second), diff --git a/tags/DOC.md b/tags/DOC.md index 3025f966c..b954b1f9f 100644 --- a/tags/DOC.md +++ b/tags/DOC.md @@ -4,6 +4,7 @@ * [Overview](#pkg-overview) * [Imported Packages](#pkg-imports) * [Index](#pkg-index) +* [Examples](#pkg-examples) ## Overview `grpc_ctxtags` adds a Tag object to the context that can be used by other middleware to add context about a request. @@ -25,6 +26,40 @@ will be no-ops. This is to ensure that code doesn't panic if the interceptors we Tags fields are typed, and shallow and should follow the OpenTracing semantics convention: https://github.com/opentracing/specification/blob/master/semantic_conventions.md +#### Example: + +
+Click to expand code. + +```go +opts := []grpc_ctxtags.Option{ + grpc_ctxtags.WithFieldExtractorForInitialReq(grpc_ctxtags.TagBasedRequestFieldExtractor("log_fields")), +} +_ = grpc.NewServer( + grpc.StreamInterceptor(grpc_ctxtags.StreamServerInterceptor(opts...)), + grpc.UnaryInterceptor(grpc_ctxtags.UnaryServerInterceptor(opts...)), +) +``` + +
+ +#### Example: + +
+Click to expand code. + +```go +opts := []grpc_ctxtags.Option{ + grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.TagBasedRequestFieldExtractor("log_fields")), +} +_ = grpc.NewServer( + grpc.StreamInterceptor(grpc_ctxtags.StreamServerInterceptor(opts...)), + grpc.UnaryInterceptor(grpc_ctxtags.UnaryServerInterceptor(opts...)), +) +``` + +
+ ## Imported Packages - [github.com/grpc-ecosystem/go-grpc-middleware](./..) @@ -47,6 +82,10 @@ Tags fields are typed, and shallow and should follow the OpenTracing semantics c * [func (t \*Tags) Set(key string, value interface{}) \*Tags](#Tags.Set) * [func (t \*Tags) Values() map[string]interface{}](#Tags.Values) +#### Examples +* [Package (InitialisationWithOptions)](#example__initialisationWithOptions) +* [Package (Initialization)](#example__initialization) + #### Package files [context.go](./context.go) [doc.go](./doc.go) [fieldextractor.go](./fieldextractor.go) [interceptors.go](./interceptors.go) [options.go](./options.go) diff --git a/tags/examples_test.go b/tags/examples_test.go index 10c443d68..f58e1abc4 100644 --- a/tags/examples_test.go +++ b/tags/examples_test.go @@ -6,7 +6,7 @@ import ( ) // Simple example of server initialization code, with data automatically populated from `log_fields` Golang tags. -func Example_Initialization() { +func Example_initialization() { opts := []grpc_ctxtags.Option{ grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.TagBasedRequestFieldExtractor("log_fields")), } @@ -17,7 +17,7 @@ func Example_Initialization() { } // Example using WithFieldExtractorForInitialReq -func Example_InitializationForInitialReq() { +func Example_initialisationWithOptions() { opts := []grpc_ctxtags.Option{ grpc_ctxtags.WithFieldExtractorForInitialReq(grpc_ctxtags.TagBasedRequestFieldExtractor("log_fields")), } From ae645d6efb8d074f7f14dd8390319cfef28ea6d4 Mon Sep 17 00:00:00 2001 From: Yifan Zhao Date: Thu, 1 Mar 2018 14:17:37 +0000 Subject: [PATCH 2/4] Fixed up comments --- logging/logrus/ctxlogrus/examples_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logging/logrus/ctxlogrus/examples_test.go b/logging/logrus/ctxlogrus/examples_test.go index 87a179940..ac61b9df0 100644 --- a/logging/logrus/ctxlogrus/examples_test.go +++ b/logging/logrus/ctxlogrus/examples_test.go @@ -12,7 +12,7 @@ var logrusLogger *logrus.Logger // Simple unary handler that adds custom fields to the requests's context. These will be used for all log statements. func ExampleExtract_unary() { ctx := context.Background() - // setting tags will be added to the loggerr as log fields + // setting tags will be added to the logger as log fields grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) // Extract a single request-scoped logrus.Logger and log messages. l := ctxlogrus.Extract(ctx) From d353591c58f45409cebcd542423253710bfe93c6 Mon Sep 17 00:00:00 2001 From: Dominic Green Date: Thu, 1 Mar 2018 14:34:36 +0000 Subject: [PATCH 3/4] fixing comment --- logging/logrus/DOC.md | 59 ++++++++++++++++----------------- logging/logrus/doc.go | 57 +++++++++++++++---------------- logging/logrus/examples_test.go | 2 +- 3 files changed, 56 insertions(+), 62 deletions(-) diff --git a/logging/logrus/DOC.md b/logging/logrus/DOC.md index 333149347..78c22f59d 100644 --- a/logging/logrus/DOC.md +++ b/logging/logrus/DOC.md @@ -13,7 +13,7 @@ It accepts a user-configured `logrus.Entry` that will be used for logging comple `logrus.Entry` will be used for logging completed gRPC calls, and be populated into the `context.Context` passed into gRPC handler code. On calling `StreamServerInterceptor` or `UnaryServerInterceptor` this logging middleware will add gRPC call information -to the ctx so that it will be present on subsequent use of the `ctx_zap` logger. +to the ctx so that it will be present on subsequent use of the `ctxlogrus` logger. This package also implements request and response *payload* logging, both for server-side and client-side. These will be logged as structured `jsonbp` fields for every message received/sent (both unary and streaming). For that please use @@ -29,46 +29,43 @@ Logrus can also be made as a backend for gRPC library internals. For that use `R Below is a JSON formatted example of a log that would be logged by the server interceptor: { - "level": "info", // string logrus log levels - "msg": "finished unary call", // string log message - - "grpc.code": "OK", // string grpc status code - "grpc.method": "Ping", // string method name - "grpc.service": "mwitkow.testproto.TestService", // string full name of the called service - "grpc.start_time": "2006-01-02T15:04:05Z07:00", // string RFC3339 representation of the start time - "grpc.request.deadline" // string RFC3339 deadline of the current request if supplied - "grpc.request.value": "something", // string value on the request - "grpc.time_ms": 1.234, // float32 run time of the call in ms - + "level": "info", // string logrus log levels + "msg": "finished unary call", // string log message + "grpc.code": "OK", // string grpc status code + "grpc.method": "Ping", // string method name + "grpc.service": "mwitkow.testproto.TestService", // string full name of the called service + "grpc.start_time": "2006-01-02T15:04:05Z07:00", // string RFC3339 representation of the start time + "grpc.request.deadline" // string RFC3339 deadline of the current request if supplied + "grpc.request.value": "something", // string value on the request + "grpc.time_ms": 1.234, // float32 run time of the call in ms "peer.address": { - "IP": "127.0.0.1", // string IP address of calling party - "Port": 60216, // int port call is coming in on - "Zone": "" // string peer zone for caller + "IP": "127.0.0.1", // string IP address of calling party + "Port": 60216, // int port call is coming in on + "Zone": "" // string peer zone for caller }, - "span.kind": "server", // string client | server - "system": "grpc" // string + "span.kind": "server", // string client | server + "system": "grpc" // string - "custom_field": "custom_value", // string user defined field - "custom_tags.int": 1337, // int user defined tag on the ctx - "custom_tags.string": "something", // string user defined tag on the ctx + "custom_field": "custom_value", // string user defined field + "custom_tags.int": 1337, // int user defined tag on the ctx + "custom_tags.string": "something", // string user defined tag on the ctx } *Payload Interceptor* Below is a JSON formatted example of a log that would be logged by the payload interceptor: { - "level": "info", // string logrus log levels - "msg": "client request payload logged as grpc.request.content", // string log message + "level": "info", // string logrus log levels + "msg": "client request payload logged as grpc.request.content", // string log message - "grpc.request.content": { // object content of RPC request - "value": "something", // string defined by caller - "sleepTimeMs": 9999 // int defined by caller + "grpc.request.content": { // object content of RPC request + "value": "something", // string defined by caller + "sleepTimeMs": 9999 // int defined by caller }, - "grpc.method": "Ping", // string method being called - "grpc.service": "mwitkow.testproto.TestService", // string service being called - - "span.kind": "client", // string client | server - "system": "grpc" // string + "grpc.method": "Ping", // string method being called + "grpc.service": "mwitkow.testproto.TestService", // string service being called + "span.kind": "client", // string client | server + "system": "grpc" // string } Note - due to implementation ZAP differs from Logrus in the "grpc.request.content" object by having an inner "msg" object. @@ -87,7 +84,7 @@ logrusEntry := logrus.NewEntry(logrusLogger) opts := []grpc_logrus.Option{ grpc_logrus.WithLevels(customFunc), } -// Make sure that log statements internal to gRPC library are logged using the zapLogger as well. +// Make sure that log statements internal to gRPC library are logged using the logrus Logger as well. grpc_logrus.ReplaceGrpcLogger(logrusEntry) // Create a server, make sure we put the grpc_ctxtags context before everything else. _ = grpc.NewServer( diff --git a/logging/logrus/doc.go b/logging/logrus/doc.go index 933abb9ae..a11bf26b5 100644 --- a/logging/logrus/doc.go +++ b/logging/logrus/doc.go @@ -5,7 +5,7 @@ It accepts a user-configured `logrus.Entry` that will be used for logging comple `logrus.Entry` will be used for logging completed gRPC calls, and be populated into the `context.Context` passed into gRPC handler code. On calling `StreamServerInterceptor` or `UnaryServerInterceptor` this logging middleware will add gRPC call information -to the ctx so that it will be present on subsequent use of the `ctx_zap` logger. +to the ctx so that it will be present on subsequent use of the `ctxlogrus` logger. This package also implements request and response *payload* logging, both for server-side and client-side. These will be logged as structured `jsonbp` fields for every message received/sent (both unary and streaming). For that please use @@ -21,46 +21,43 @@ Logrus can also be made as a backend for gRPC library internals. For that use `R Below is a JSON formatted example of a log that would be logged by the server interceptor: { - "level": "info", // string logrus log levels - "msg": "finished unary call", // string log message - - "grpc.code": "OK", // string grpc status code - "grpc.method": "Ping", // string method name - "grpc.service": "mwitkow.testproto.TestService", // string full name of the called service - "grpc.start_time": "2006-01-02T15:04:05Z07:00", // string RFC3339 representation of the start time - "grpc.request.deadline" // string RFC3339 deadline of the current request if supplied - "grpc.request.value": "something", // string value on the request - "grpc.time_ms": 1.234, // float32 run time of the call in ms - + "level": "info", // string logrus log levels + "msg": "finished unary call", // string log message + "grpc.code": "OK", // string grpc status code + "grpc.method": "Ping", // string method name + "grpc.service": "mwitkow.testproto.TestService", // string full name of the called service + "grpc.start_time": "2006-01-02T15:04:05Z07:00", // string RFC3339 representation of the start time + "grpc.request.deadline" // string RFC3339 deadline of the current request if supplied + "grpc.request.value": "something", // string value on the request + "grpc.time_ms": 1.234, // float32 run time of the call in ms "peer.address": { - "IP": "127.0.0.1", // string IP address of calling party - "Port": 60216, // int port call is coming in on - "Zone": "" // string peer zone for caller + "IP": "127.0.0.1", // string IP address of calling party + "Port": 60216, // int port call is coming in on + "Zone": "" // string peer zone for caller }, - "span.kind": "server", // string client | server - "system": "grpc" // string + "span.kind": "server", // string client | server + "system": "grpc" // string - "custom_field": "custom_value", // string user defined field - "custom_tags.int": 1337, // int user defined tag on the ctx - "custom_tags.string": "something", // string user defined tag on the ctx + "custom_field": "custom_value", // string user defined field + "custom_tags.int": 1337, // int user defined tag on the ctx + "custom_tags.string": "something", // string user defined tag on the ctx } *Payload Interceptor* Below is a JSON formatted example of a log that would be logged by the payload interceptor: { - "level": "info", // string logrus log levels - "msg": "client request payload logged as grpc.request.content", // string log message + "level": "info", // string logrus log levels + "msg": "client request payload logged as grpc.request.content", // string log message - "grpc.request.content": { // object content of RPC request - "value": "something", // string defined by caller - "sleepTimeMs": 9999 // int defined by caller + "grpc.request.content": { // object content of RPC request + "value": "something", // string defined by caller + "sleepTimeMs": 9999 // int defined by caller }, - "grpc.method": "Ping", // string method being called - "grpc.service": "mwitkow.testproto.TestService", // string service being called - - "span.kind": "client", // string client | server - "system": "grpc" // string + "grpc.method": "Ping", // string method being called + "grpc.service": "mwitkow.testproto.TestService", // string service being called + "span.kind": "client", // string client | server + "system": "grpc" // string } Note - due to implementation ZAP differs from Logrus in the "grpc.request.content" object by having an inner "msg" object. diff --git a/logging/logrus/examples_test.go b/logging/logrus/examples_test.go index b361a8974..e0f9e1af2 100644 --- a/logging/logrus/examples_test.go +++ b/logging/logrus/examples_test.go @@ -26,7 +26,7 @@ func Example_initialization() { opts := []grpc_logrus.Option{ grpc_logrus.WithLevels(customFunc), } - // Make sure that log statements internal to gRPC library are logged using the zapLogger as well. + // Make sure that log statements internal to gRPC library are logged using the logrus Logger as well. grpc_logrus.ReplaceGrpcLogger(logrusEntry) // Create a server, make sure we put the grpc_ctxtags context before everything else. _ = grpc.NewServer( From 5c4470029ae3c5b6a03681ad6a9bb324270a2d51 Mon Sep 17 00:00:00 2001 From: Dominic Green Date: Thu, 1 Mar 2018 14:36:49 +0000 Subject: [PATCH 4/4] generating md --- logging/logrus/ctxlogrus/DOC.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logging/logrus/ctxlogrus/DOC.md b/logging/logrus/ctxlogrus/DOC.md index fb5cb3ae0..909180292 100644 --- a/logging/logrus/ctxlogrus/DOC.md +++ b/logging/logrus/ctxlogrus/DOC.md @@ -71,7 +71,7 @@ var logrusLogger *logrus.Logger // Simple unary handler that adds custom fields to the requests's context. These will be used for all log statements. func ExampleExtract_unary() { ctx := context.Background() - // setting tags will be added to the loggerr as log fields + // setting tags will be added to the logger as log fields grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337) // Extract a single request-scoped logrus.Logger and log messages. l := ctxlogrus.Extract(ctx)