Skip to content

Commit

Permalink
Add example generation to docs. (grpc-ecosystem#46)
Browse files Browse the repository at this point in the history
* docs with examples generated

* better structured docs

* Readme fixups
  • Loading branch information
Michal Witkowski authored May 13, 2017
1 parent 63bfe19 commit fb1b862
Show file tree
Hide file tree
Showing 14 changed files with 362 additions and 9 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

[gRPC Go](https://github.com/grpc/grpc-go) Middleware: interceptors, helpers, utilities.

**Important** The repo recently moved from `github.com/grpc-ecosystem/go-grpc-middleware`, please update your import paths.
**Important** The repo recently moved to `github.com/grpc-ecosystem/go-grpc-middleware`, please update your import paths.

## Middleware

Expand All @@ -24,7 +24,7 @@ These are generic building blocks that make it easy to build multiple microservi
The purpose of this repository is to act as a go-to point for such reusable functionality. It contains
some of them itself, but also will link to useful external repos.

`grpc_middleware` itself provides support for chaining interceptors. Se [Documentation](DOC.md), but here's an example:
`grpc_middleware` itself provides support for chaining interceptors. See [Documentation](DOC.md), but here's an example:

```go
import "github.com/grpc-ecosystem/go-grpc-middleware"
Expand Down
36 changes: 36 additions & 0 deletions auth/DOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,42 @@ It also allows for per-service implementation overrides of `AuthFunc`. See `Serv

Please see examples for simple examples of use.

#### Example:

<details>
<summary>Click to expand code.</summary>

```go
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
```

</details>

#### Example:

<details>
<summary>Click to expand code.</summary>

```go
server := grpc.NewServer(
grpc.StreamInterceptor(grpc_auth.StreamServerInterceptor(Example_authfunc)),
grpc.UnaryInterceptor(grpc_auth.UnaryServerInterceptor(Example_authfunc)),
)
return server
```

</details>

## <a name="pkg-imports">Imported Packages</a>

- [github.com/grpc-ecosystem/go-grpc-middleware](./..)
Expand Down
2 changes: 1 addition & 1 deletion fixup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function generate_markdown {
package=${realdir##${GOPATH}/src/}
echo "$package"
cd ${dir}
${GOBIN}/godoc2ghmd -file DOC.md ${package}
${GOBIN}/godoc2ghmd -ex -file DOC.md ${package}
ln -s DOC.md README.md 2> /dev/null # can fail
cd ${oldpwd}
done;
Expand Down
82 changes: 82 additions & 0 deletions logging/logrus/DOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,92 @@ It accepts a user-configured `logrus.Entry` that will be used for logging comple
You can use `Extract` to log into a request-scoped `logrus.Entry` instance in your handler code. The fields set on the
logger correspond to the grpc_ctxtags.Tags attached to the context.

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
`Payload*Interceptor` functions for that. Please note that the user-provided function that determines whetether to log
the full request/response payload needs to be written with care, this can significantly slow down gRPC.

Logrus can also be made as a backend for gRPC library internals. For that use `ReplaceGrpcLogger`.

Please see examples and tests for examples of use.

#### Example:

<details>
<summary>Click to expand code.</summary>

```go
x := 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 request-scoped zap.Logger and log a message.
grpc_logrus.Extract(ctx).Info("some ping")
return &pb_testproto.PingResponse{Value: ping.Value}, nil
}
return x
```

</details>

#### Example:

<details>
<summary>Click to expand code.</summary>

```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.
server := 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...),
),
)
return server
```

</details>

#### Example:

<details>
<summary>Click to expand code.</summary>

```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()
}),
}
server := grpc.NewServer(
grpc_middleware.WithUnaryServerChain(
grpc_ctxtags.UnaryServerInterceptor(),
grpc_logrus.UnaryServerInterceptor(logrusEntry, opts...),
),
grpc_middleware.WithStreamServerChain(
grpc_ctxtags.StreamServerInterceptor(),
grpc_logrus.StreamServerInterceptor(logrusEntry, opts...),
),
)
return server
```

</details>

## <a name="pkg-imports">Imported Packages</a>

- github.com/Sirupsen/logrus
Expand Down
5 changes: 5 additions & 0 deletions logging/logrus/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ It accepts a user-configured `logrus.Entry` that will be used for logging comple
You can use `Extract` to log into a request-scoped `logrus.Entry` instance in your handler code. The fields set on the
logger correspond to the grpc_ctxtags.Tags attached to the context.
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
`Payload*Interceptor` functions for that. Please note that the user-provided function that determines whetether to log
the full request/response payload needs to be written with care, this can significantly slow down gRPC.
Logrus can also be made as a backend for gRPC library internals. For that use `ReplaceGrpcLogger`.
Please see examples and tests for examples of use.
Expand Down
79 changes: 79 additions & 0 deletions logging/zap/DOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,89 @@ be used for logging completed gRPC calls, and be populated into the `context.Con
You can use `Extract` to log into a request-scoped `zap.Logger` instance in your handler code. The fields set on the
logger correspond to the grpc_ctxtags.Tags attached to the context.

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
`Payload*Interceptor` functions for that. Please note that the user-provided function that determines whetether to log
the full request/response payload needs to be written with care, this can significantly slow down gRPC.

ZAP can also be made as a backend for gRPC library internals. For that use `ReplaceGrpcLogger`.

Please see examples and tests for examples of use.

#### Example:

<details>
<summary>Click to expand code.</summary>

```go
x := 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 request-scoped zap.Logger and log a message.
grpc_zap.Extract(ctx).Info("some ping")
return &pb_testproto.PingResponse{Value: ping.Value}, nil
}
return x
```

</details>

#### Example:

<details>
<summary>Click to expand code.</summary>

```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.
server := 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...),
),
)
return server
```

</details>

#### Example:

<details>
<summary>Click to expand code.</summary>

```go
opts := []grpc_zap.Option{
grpc_zap.WithDurationField(func(duration time.Duration) zapcore.Field {
return zap.Int64("grpc.time_ns", duration.Nanoseconds())
}),
}

server := grpc.NewServer(
grpc_middleware.WithUnaryServerChain(
grpc_ctxtags.UnaryServerInterceptor(),
grpc_zap.UnaryServerInterceptor(zapLogger, opts...),
),
grpc_middleware.WithStreamServerChain(
grpc_ctxtags.StreamServerInterceptor(),
grpc_zap.StreamServerInterceptor(zapLogger, opts...),
),
)

return server
```

</details>

## <a name="pkg-imports">Imported Packages</a>

- [github.com/golang/protobuf/jsonpb](https://godoc.org/github.com/golang/protobuf/jsonpb)
Expand Down
5 changes: 5 additions & 0 deletions logging/zap/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ be used for logging completed gRPC calls, and be populated into the `context.Con
You can use `Extract` to log into a request-scoped `zap.Logger` instance in your handler code. The fields set on the
logger correspond to the grpc_ctxtags.Tags attached to the context.
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
`Payload*Interceptor` functions for that. Please note that the user-provided function that determines whetether to log
the full request/response payload needs to be written with care, this can significantly slow down gRPC.
ZAP can also be made as a backend for gRPC library internals. For that use `ReplaceGrpcLogger`.
Please see examples and tests for examples of use.
Expand Down
27 changes: 26 additions & 1 deletion recovery/DOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* [Examples](#pkg-examples)

## <a name="pkg-overview">Overview</a>
`grpc_recovery` conversion of panics into gRPC errors
`grpc_recovery` are intereceptors that recover from gRPC handler panics.

### Server Side Recovery Middleware
By default a panic will be converted into a gRPC error with `code.Internal`.
Expand All @@ -16,6 +16,31 @@ Handling can be customised by providing an alternate recovery function.

Please see examples for simple examples of use.

#### Example:

<details>
<summary>Click to expand code.</summary>

```go
// Shared options for the logger, with a custom gRPC code to log level function.
opts := []grpc_recovery.Option{
grpc_recovery.WithRecoveryHandler(customFunc),
}
// Create a server. Recovery handlers should typically be last in the chain so that other middleware
// (e.g. logging) can operate on the recovered state instead of being directly affected by any panic
server := grpc.NewServer(
grpc_middleware.WithUnaryServerChain(
grpc_recovery.UnaryServerInterceptor(opts...),
),
grpc_middleware.WithStreamServerChain(
grpc_recovery.StreamServerInterceptor(opts...),
),
)
return server
```

</details>

## <a name="pkg-imports">Imported Packages</a>

- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
Expand Down
2 changes: 1 addition & 1 deletion recovery/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// See LICENSE for licensing terms.

/*
`grpc_recovery` conversion of panics into gRPC errors
`grpc_recovery` are intereceptors that recover from gRPC handler panics.
Server Side Recovery Middleware
Expand Down
Loading

0 comments on commit fb1b862

Please sign in to comment.