mirror of
https://github.com/zrepl/zrepl.git
synced 2025-08-10 15:37:35 +02:00
[#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:
@ -7,6 +7,7 @@ import (
|
||||
"github.com/zrepl/zrepl/endpoint"
|
||||
"github.com/zrepl/zrepl/replication/logic/pdu"
|
||||
"github.com/zrepl/zrepl/rpc/dataconn"
|
||||
"github.com/zrepl/zrepl/rpc/grpcclientidentity"
|
||||
"github.com/zrepl/zrepl/rpc/grpcclientidentity/grpchelper"
|
||||
"github.com/zrepl/zrepl/rpc/versionhandshake"
|
||||
"github.com/zrepl/zrepl/transport"
|
||||
@ -30,7 +31,20 @@ type Server struct {
|
||||
dataServerServe serveFunc
|
||||
}
|
||||
|
||||
type HandlerContextInterceptor func(ctx context.Context) context.Context
|
||||
type HandlerContextInterceptorData interface {
|
||||
FullMethod() string
|
||||
ClientIdentity() string
|
||||
}
|
||||
|
||||
type interceptorData struct {
|
||||
prefixMethod string
|
||||
wrapped HandlerContextInterceptorData
|
||||
}
|
||||
|
||||
func (d interceptorData) ClientIdentity() string { return d.wrapped.ClientIdentity() }
|
||||
func (d interceptorData) FullMethod() string { return d.prefixMethod + d.wrapped.FullMethod() }
|
||||
|
||||
type HandlerContextInterceptor func(ctx context.Context, data HandlerContextInterceptorData, handler func(ctx context.Context))
|
||||
|
||||
// config must be valid (use its Validate function).
|
||||
func NewServer(handler Handler, loggers Loggers, ctxInterceptor HandlerContextInterceptor) *Server {
|
||||
@ -38,7 +52,10 @@ func NewServer(handler Handler, loggers Loggers, ctxInterceptor HandlerContextIn
|
||||
// setup control server
|
||||
controlServerServe := func(ctx context.Context, controlListener transport.AuthenticatedListener, errOut chan<- error) {
|
||||
|
||||
controlServer, serve := grpchelper.NewServer(controlListener, endpoint.ClientIdentityKey, loggers.Control, ctxInterceptor)
|
||||
var controlCtxInterceptor grpcclientidentity.Interceptor = func(ctx context.Context, data grpcclientidentity.ContextInterceptorData, handler func(ctx context.Context)) {
|
||||
ctxInterceptor(ctx, interceptorData{"control://", data}, handler)
|
||||
}
|
||||
controlServer, serve := grpchelper.NewServer(controlListener, endpoint.ClientIdentityKey, loggers.Control, controlCtxInterceptor)
|
||||
pdu.RegisterReplicationServer(controlServer, handler)
|
||||
|
||||
// give time for graceful stop until deadline expires, then hard stop
|
||||
@ -59,12 +76,12 @@ func NewServer(handler Handler, loggers Loggers, ctxInterceptor HandlerContextIn
|
||||
dataServerClientIdentitySetter := func(ctx context.Context, wire *transport.AuthConn) (context.Context, *transport.AuthConn) {
|
||||
ci := wire.ClientIdentity()
|
||||
ctx = context.WithValue(ctx, endpoint.ClientIdentityKey, ci)
|
||||
if ctxInterceptor != nil {
|
||||
ctx = ctxInterceptor(ctx) // SHADOWING
|
||||
}
|
||||
return ctx, wire
|
||||
}
|
||||
dataServer := dataconn.NewServer(dataServerClientIdentitySetter, loggers.Data, handler)
|
||||
var dataCtxInterceptor dataconn.ContextInterceptor = func(ctx context.Context, data dataconn.ContextInterceptorData, handler func(ctx context.Context)) {
|
||||
ctxInterceptor(ctx, interceptorData{"data://", data}, handler)
|
||||
}
|
||||
dataServer := dataconn.NewServer(dataServerClientIdentitySetter, dataCtxInterceptor, loggers.Data, handler)
|
||||
dataServerServe := func(ctx context.Context, dataListener transport.AuthenticatedListener, errOut chan<- error) {
|
||||
dataServer.Serve(ctx, dataListener)
|
||||
errOut <- nil // TODO bad design of dataServer?
|
||||
|
Reference in New Issue
Block a user