binarylog.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. *
  3. * Copyright 2018 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. // Package binarylog implementation binary logging as defined in
  19. // https://github.com/grpc/proposal/blob/master/A16-binary-logging.md.
  20. package binarylog
  21. import (
  22. "fmt"
  23. "os"
  24. "google.golang.org/grpc/grpclog"
  25. "google.golang.org/grpc/internal/grpcutil"
  26. )
  27. // Logger is the global binary logger. It can be used to get binary logger for
  28. // each method.
  29. type Logger interface {
  30. getMethodLogger(methodName string) *MethodLogger
  31. }
  32. // binLogger is the global binary logger for the binary. One of this should be
  33. // built at init time from the configuration (environment variable or flags).
  34. //
  35. // It is used to get a methodLogger for each individual method.
  36. var binLogger Logger
  37. var grpclogLogger = grpclog.Component("binarylog")
  38. // SetLogger sets the binarg logger.
  39. //
  40. // Only call this at init time.
  41. func SetLogger(l Logger) {
  42. binLogger = l
  43. }
  44. // GetMethodLogger returns the methodLogger for the given methodName.
  45. //
  46. // methodName should be in the format of "/service/method".
  47. //
  48. // Each methodLogger returned by this method is a new instance. This is to
  49. // generate sequence id within the call.
  50. func GetMethodLogger(methodName string) *MethodLogger {
  51. if binLogger == nil {
  52. return nil
  53. }
  54. return binLogger.getMethodLogger(methodName)
  55. }
  56. func init() {
  57. const envStr = "GRPC_BINARY_LOG_FILTER"
  58. configStr := os.Getenv(envStr)
  59. binLogger = NewLoggerFromConfigString(configStr)
  60. }
  61. type methodLoggerConfig struct {
  62. // Max length of header and message.
  63. hdr, msg uint64
  64. }
  65. type logger struct {
  66. all *methodLoggerConfig
  67. services map[string]*methodLoggerConfig
  68. methods map[string]*methodLoggerConfig
  69. blacklist map[string]struct{}
  70. }
  71. // newEmptyLogger creates an empty logger. The map fields need to be filled in
  72. // using the set* functions.
  73. func newEmptyLogger() *logger {
  74. return &logger{}
  75. }
  76. // Set method logger for "*".
  77. func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error {
  78. if l.all != nil {
  79. return fmt.Errorf("conflicting global rules found")
  80. }
  81. l.all = ml
  82. return nil
  83. }
  84. // Set method logger for "service/*".
  85. //
  86. // New methodLogger with same service overrides the old one.
  87. func (l *logger) setServiceMethodLogger(service string, ml *methodLoggerConfig) error {
  88. if _, ok := l.services[service]; ok {
  89. return fmt.Errorf("conflicting service rules for service %v found", service)
  90. }
  91. if l.services == nil {
  92. l.services = make(map[string]*methodLoggerConfig)
  93. }
  94. l.services[service] = ml
  95. return nil
  96. }
  97. // Set method logger for "service/method".
  98. //
  99. // New methodLogger with same method overrides the old one.
  100. func (l *logger) setMethodMethodLogger(method string, ml *methodLoggerConfig) error {
  101. if _, ok := l.blacklist[method]; ok {
  102. return fmt.Errorf("conflicting blacklist rules for method %v found", method)
  103. }
  104. if _, ok := l.methods[method]; ok {
  105. return fmt.Errorf("conflicting method rules for method %v found", method)
  106. }
  107. if l.methods == nil {
  108. l.methods = make(map[string]*methodLoggerConfig)
  109. }
  110. l.methods[method] = ml
  111. return nil
  112. }
  113. // Set blacklist method for "-service/method".
  114. func (l *logger) setBlacklist(method string) error {
  115. if _, ok := l.blacklist[method]; ok {
  116. return fmt.Errorf("conflicting blacklist rules for method %v found", method)
  117. }
  118. if _, ok := l.methods[method]; ok {
  119. return fmt.Errorf("conflicting method rules for method %v found", method)
  120. }
  121. if l.blacklist == nil {
  122. l.blacklist = make(map[string]struct{})
  123. }
  124. l.blacklist[method] = struct{}{}
  125. return nil
  126. }
  127. // getMethodLogger returns the methodLogger for the given methodName.
  128. //
  129. // methodName should be in the format of "/service/method".
  130. //
  131. // Each methodLogger returned by this method is a new instance. This is to
  132. // generate sequence id within the call.
  133. func (l *logger) getMethodLogger(methodName string) *MethodLogger {
  134. s, m, err := grpcutil.ParseMethod(methodName)
  135. if err != nil {
  136. grpclogLogger.Infof("binarylogging: failed to parse %q: %v", methodName, err)
  137. return nil
  138. }
  139. if ml, ok := l.methods[s+"/"+m]; ok {
  140. return newMethodLogger(ml.hdr, ml.msg)
  141. }
  142. if _, ok := l.blacklist[s+"/"+m]; ok {
  143. return nil
  144. }
  145. if ml, ok := l.services[s]; ok {
  146. return newMethodLogger(ml.hdr, ml.msg)
  147. }
  148. if l.all == nil {
  149. return nil
  150. }
  151. return newMethodLogger(l.all.hdr, l.all.msg)
  152. }