binarylog: generalize binarylog's MethodLogger preparing for new observability features (#5244)

This commit is contained in:
Lidi Zheng 2022-03-21 14:00:02 -07:00 committed by GitHub
parent 63bdcbcce5
commit 1ffd63de37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 21 deletions

View File

@ -31,7 +31,7 @@ import (
// Logger is the global binary logger. It can be used to get binary logger for // Logger is the global binary logger. It can be used to get binary logger for
// each method. // each method.
type Logger interface { type Logger interface {
getMethodLogger(methodName string) *MethodLogger GetMethodLogger(methodName string) MethodLogger
} }
// binLogger is the global binary logger for the binary. One of this should be // binLogger is the global binary logger for the binary. One of this should be
@ -49,17 +49,24 @@ func SetLogger(l Logger) {
binLogger = l binLogger = l
} }
// GetLogger gets the binarg logger.
//
// Only call this at init time.
func GetLogger() Logger {
return binLogger
}
// GetMethodLogger returns the methodLogger for the given methodName. // GetMethodLogger returns the methodLogger for the given methodName.
// //
// methodName should be in the format of "/service/method". // methodName should be in the format of "/service/method".
// //
// Each methodLogger returned by this method is a new instance. This is to // Each methodLogger returned by this method is a new instance. This is to
// generate sequence id within the call. // generate sequence id within the call.
func GetMethodLogger(methodName string) *MethodLogger { func GetMethodLogger(methodName string) MethodLogger {
if binLogger == nil { if binLogger == nil {
return nil return nil
} }
return binLogger.getMethodLogger(methodName) return binLogger.GetMethodLogger(methodName)
} }
func init() { func init() {
@ -148,7 +155,7 @@ func (l *logger) setBlacklist(method string) error {
// //
// Each methodLogger returned by this method is a new instance. This is to // Each methodLogger returned by this method is a new instance. This is to
// generate sequence id within the call. // generate sequence id within the call.
func (l *logger) getMethodLogger(methodName string) *MethodLogger { func (l *logger) GetMethodLogger(methodName string) MethodLogger {
s, m, err := grpcutil.ParseMethod(methodName) s, m, err := grpcutil.ParseMethod(methodName)
if err != nil { if err != nil {
grpclogLogger.Infof("binarylogging: failed to parse %q: %v", methodName, err) grpclogLogger.Infof("binarylogging: failed to parse %q: %v", methodName, err)

View File

@ -93,7 +93,7 @@ func (s) TestGetMethodLogger(t *testing.T) {
t.Errorf("in: %q, failed to create logger from config string", tc.in) t.Errorf("in: %q, failed to create logger from config string", tc.in)
continue continue
} }
ml := l.getMethodLogger(tc.method) ml := l.GetMethodLogger(tc.method).(*methodLogger)
if ml == nil { if ml == nil {
t.Errorf("in: %q, method logger is nil, want non-nil", tc.in) t.Errorf("in: %q, method logger is nil, want non-nil", tc.in)
continue continue
@ -149,7 +149,7 @@ func (s) TestGetMethodLoggerOff(t *testing.T) {
t.Errorf("in: %q, failed to create logger from config string", tc.in) t.Errorf("in: %q, failed to create logger from config string", tc.in)
continue continue
} }
ml := l.getMethodLogger(tc.method) ml := l.GetMethodLogger(tc.method)
if ml != nil { if ml != nil {
t.Errorf("in: %q, method logger is non-nil, want nil", tc.in) t.Errorf("in: %q, method logger is non-nil, want nil", tc.in)
} }

View File

@ -48,7 +48,11 @@ func (g *callIDGenerator) reset() {
var idGen callIDGenerator var idGen callIDGenerator
// MethodLogger is the sub-logger for each method. // MethodLogger is the sub-logger for each method.
type MethodLogger struct { type MethodLogger interface {
Log(LogEntryConfig)
}
type methodLogger struct {
headerMaxLen, messageMaxLen uint64 headerMaxLen, messageMaxLen uint64
callID uint64 callID uint64
@ -57,8 +61,8 @@ type MethodLogger struct {
sink Sink // TODO(blog): make this plugable. sink Sink // TODO(blog): make this plugable.
} }
func newMethodLogger(h, m uint64) *MethodLogger { func newMethodLogger(h, m uint64) *methodLogger {
return &MethodLogger{ return &methodLogger{
headerMaxLen: h, headerMaxLen: h,
messageMaxLen: m, messageMaxLen: m,
@ -69,8 +73,10 @@ func newMethodLogger(h, m uint64) *MethodLogger {
} }
} }
// Log creates a proto binary log entry, and logs it to the sink. // Build is an internal only method for building the proto message out of the
func (ml *MethodLogger) Log(c LogEntryConfig) { // input event. It's made public to enable other library to reuse as much logic
// in methodLogger as possible.
func (ml *methodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry {
m := c.toProto() m := c.toProto()
timestamp, _ := ptypes.TimestampProto(time.Now()) timestamp, _ := ptypes.TimestampProto(time.Now())
m.Timestamp = timestamp m.Timestamp = timestamp
@ -85,11 +91,15 @@ func (ml *MethodLogger) Log(c LogEntryConfig) {
case *pb.GrpcLogEntry_Message: case *pb.GrpcLogEntry_Message:
m.PayloadTruncated = ml.truncateMessage(pay.Message) m.PayloadTruncated = ml.truncateMessage(pay.Message)
} }
return m
ml.sink.Write(m)
} }
func (ml *MethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) { // Log creates a proto binary log entry, and logs it to the sink.
func (ml *methodLogger) Log(c LogEntryConfig) {
ml.sink.Write(ml.Build(c))
}
func (ml *methodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) {
if ml.headerMaxLen == maxUInt { if ml.headerMaxLen == maxUInt {
return false return false
} }
@ -119,7 +129,7 @@ func (ml *MethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) {
return truncated return truncated
} }
func (ml *MethodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) { func (ml *methodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) {
if ml.messageMaxLen == maxUInt { if ml.messageMaxLen == maxUInt {
return false return false
} }

View File

@ -350,7 +350,7 @@ func (s) TestLog(t *testing.T) {
func (s) TestTruncateMetadataNotTruncated(t *testing.T) { func (s) TestTruncateMetadataNotTruncated(t *testing.T) {
testCases := []struct { testCases := []struct {
ml *MethodLogger ml *methodLogger
mpPb *pb.Metadata mpPb *pb.Metadata
}{ }{
{ {
@ -417,7 +417,7 @@ func (s) TestTruncateMetadataNotTruncated(t *testing.T) {
func (s) TestTruncateMetadataTruncated(t *testing.T) { func (s) TestTruncateMetadataTruncated(t *testing.T) {
testCases := []struct { testCases := []struct {
ml *MethodLogger ml *methodLogger
mpPb *pb.Metadata mpPb *pb.Metadata
entryLen int entryLen int
@ -478,7 +478,7 @@ func (s) TestTruncateMetadataTruncated(t *testing.T) {
func (s) TestTruncateMessageNotTruncated(t *testing.T) { func (s) TestTruncateMessageNotTruncated(t *testing.T) {
testCases := []struct { testCases := []struct {
ml *MethodLogger ml *methodLogger
msgPb *pb.Message msgPb *pb.Message
}{ }{
{ {
@ -511,7 +511,7 @@ func (s) TestTruncateMessageNotTruncated(t *testing.T) {
func (s) TestTruncateMessageTruncated(t *testing.T) { func (s) TestTruncateMessageTruncated(t *testing.T) {
testCases := []struct { testCases := []struct {
ml *MethodLogger ml *methodLogger
msgPb *pb.Message msgPb *pb.Message
oldLength uint32 oldLength uint32

View File

@ -462,7 +462,7 @@ type clientStream struct {
retryThrottler *retryThrottler // The throttler active when the RPC began. retryThrottler *retryThrottler // The throttler active when the RPC began.
binlog *binarylog.MethodLogger // Binary logger, can be nil. binlog binarylog.MethodLogger // Binary logger, can be nil.
// serverHeaderBinlogged is a boolean for whether server header has been // serverHeaderBinlogged is a boolean for whether server header has been
// logged. Server header will be logged when the first time one of those // logged. Server header will be logged when the first time one of those
// happens: stream.Header(), stream.Recv(). // happens: stream.Header(), stream.Recv().
@ -1434,7 +1434,7 @@ type serverStream struct {
statsHandler stats.Handler statsHandler stats.Handler
binlog *binarylog.MethodLogger binlog binarylog.MethodLogger
// serverHeaderBinlogged indicates whether server header has been logged. It // serverHeaderBinlogged indicates whether server header has been logged. It
// will happen when one of the following two happens: stream.SendHeader(), // will happen when one of the following two happens: stream.SendHeader(),
// stream.Send(). // stream.Send().