[#307] add package trace, integrate it with logging, and adopt it throughout zrepl
package trace:
- introduce the concept of tasks and spans, tracked as linked list within ctx
- see package-level docs for an overview of the concepts
- **main feature 1**: unique stack of task and span IDs
- makes it easy to follow a series of log entries in concurrent code
- **main feature 2**: ability to produce a chrome://tracing-compatible trace file
- either via an env variable or a `zrepl pprof` subcommand
- this is not a CPU profile, we already have go pprof for that
- but it is very useful to visually inspect where the
replication / snapshotter / pruner spends its time
( fixes #307 )
usage in package daemon/logging:
- goal: every log entry should have a trace field with the ID stack from package trace
- make `logging.GetLogger(ctx, Subsys)` the authoritative `logger.Logger` factory function
- the context carries a linked list of injected fields which
`logging.GetLogger` adds to the logger it returns
- `logging.GetLogger` also uses package `trace` to get the
task-and-span-stack and injects it into the returned logger's fields
This commit is contained in:
@@ -99,10 +99,23 @@ func (*transportCredentials) OverrideServerName(string) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
type ContextInterceptor = func(ctx context.Context) context.Context
|
||||
type ContextInterceptorData interface {
|
||||
FullMethod() string
|
||||
ClientIdentity() string
|
||||
}
|
||||
|
||||
func NewInterceptors(logger Logger, clientIdentityKey interface{}, ctxInterceptor ContextInterceptor) (unary grpc.UnaryServerInterceptor, stream grpc.StreamServerInterceptor) {
|
||||
unary = func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
type contextInterceptorData struct {
|
||||
fullMethod string
|
||||
clientIdentity string
|
||||
}
|
||||
|
||||
func (d contextInterceptorData) FullMethod() string { return d.fullMethod }
|
||||
func (d contextInterceptorData) ClientIdentity() string { return d.clientIdentity }
|
||||
|
||||
type Interceptor = func(ctx context.Context, data ContextInterceptorData, handler func(ctx context.Context))
|
||||
|
||||
func NewInterceptors(logger Logger, clientIdentityKey interface{}, interceptor Interceptor) (unary grpc.UnaryServerInterceptor, stream grpc.StreamServerInterceptor) {
|
||||
unary = func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
logger.WithField("fullMethod", info.FullMethod).Debug("request")
|
||||
p, ok := peer.FromContext(ctx)
|
||||
if !ok {
|
||||
@@ -115,10 +128,18 @@ func NewInterceptors(logger Logger, clientIdentityKey interface{}, ctxIntercepto
|
||||
}
|
||||
logger.WithField("peer_client_identity", a.clientIdentity).Debug("peer client identity")
|
||||
ctx = context.WithValue(ctx, clientIdentityKey, a.clientIdentity)
|
||||
if ctxInterceptor != nil {
|
||||
ctx = ctxInterceptor(ctx)
|
||||
data := contextInterceptorData{
|
||||
fullMethod: info.FullMethod,
|
||||
clientIdentity: a.clientIdentity,
|
||||
}
|
||||
return handler(ctx, req)
|
||||
var (
|
||||
resp interface{}
|
||||
err error
|
||||
)
|
||||
interceptor(ctx, data, func(ctx context.Context) {
|
||||
resp, err = handler(ctx, req) // no-shadow
|
||||
})
|
||||
return resp, err
|
||||
}
|
||||
stream = func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
panic("unimplemented")
|
||||
|
||||
@@ -50,7 +50,7 @@ func ClientConn(cn transport.Connecter, log Logger) *grpc.ClientConn {
|
||||
}
|
||||
|
||||
// NewServer is a convenience interface around the TransportCredentials and Interceptors interface.
|
||||
func NewServer(authListener transport.AuthenticatedListener, clientIdentityKey interface{}, logger grpcclientidentity.Logger, ctxInterceptor grpcclientidentity.ContextInterceptor) (srv *grpc.Server, serve func() error) {
|
||||
func NewServer(authListener transport.AuthenticatedListener, clientIdentityKey interface{}, logger grpcclientidentity.Logger, ctxInterceptor grpcclientidentity.Interceptor) (srv *grpc.Server, serve func() error) {
|
||||
ka := grpc.KeepaliveParams(keepalive.ServerParameters{
|
||||
Time: StartKeepalivesAfterInactivityDuration,
|
||||
Timeout: KeepalivePeerTimeout,
|
||||
|
||||
Reference in New Issue
Block a user