binarylog.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. var grpclogLogger = grpclog.Component("binarylog")
  28. // Logger specifies MethodLoggers for method names with a Log call that
  29. // takes a context.
  30. //
  31. // This is used in the 1.0 release of gcp/observability, and thus must not be
  32. // deleted or changed.
  33. type Logger interface {
  34. GetMethodLogger(methodName string) MethodLogger
  35. }
  36. // binLogger is the global binary logger for the binary. One of this should be
  37. // built at init time from the configuration (environment variable or flags).
  38. //
  39. // It is used to get a MethodLogger for each individual method.
  40. var binLogger Logger
  41. // SetLogger sets the binary logger.
  42. //
  43. // Only call this at init time.
  44. func SetLogger(l Logger) {
  45. binLogger = l
  46. }
  47. // GetLogger gets the binary logger.
  48. //
  49. // Only call this at init time.
  50. func GetLogger() Logger {
  51. return binLogger
  52. }
  53. // GetMethodLogger returns the MethodLogger for the given methodName.
  54. //
  55. // methodName should be in the format of "/service/method".
  56. //
  57. // Each MethodLogger returned by this method is a new instance. This is to
  58. // generate sequence id within the call.
  59. func GetMethodLogger(methodName string) MethodLogger {
  60. if binLogger == nil {
  61. return nil
  62. }
  63. return binLogger.GetMethodLogger(methodName)
  64. }
  65. func init() {
  66. const envStr = "GRPC_BINARY_LOG_FILTER"
  67. configStr := os.Getenv(envStr)
  68. binLogger = NewLoggerFromConfigString(configStr)
  69. }
  70. // MethodLoggerConfig contains the setting for logging behavior of a method
  71. // logger. Currently, it contains the max length of header and message.
  72. type MethodLoggerConfig struct {
  73. // Max length of header and message.
  74. Header, Message uint64
  75. }
  76. // LoggerConfig contains the config for loggers to create method loggers.
  77. type LoggerConfig struct {
  78. All *MethodLoggerConfig
  79. Services map[string]*MethodLoggerConfig
  80. Methods map[string]*MethodLoggerConfig
  81. Blacklist map[string]struct{}
  82. }
  83. type logger struct {
  84. config LoggerConfig
  85. }
  86. // NewLoggerFromConfig builds a logger with the given LoggerConfig.
  87. func NewLoggerFromConfig(config LoggerConfig) Logger {
  88. return &logger{config: config}
  89. }
  90. // newEmptyLogger creates an empty logger. The map fields need to be filled in
  91. // using the set* functions.
  92. func newEmptyLogger() *logger {
  93. return &logger{}
  94. }
  95. // Set method logger for "*".
  96. func (l *logger) setDefaultMethodLogger(ml *MethodLoggerConfig) error {
  97. if l.config.All != nil {
  98. return fmt.Errorf("conflicting global rules found")
  99. }
  100. l.config.All = ml
  101. return nil
  102. }
  103. // Set method logger for "service/*".
  104. //
  105. // New MethodLogger with same service overrides the old one.
  106. func (l *logger) setServiceMethodLogger(service string, ml *MethodLoggerConfig) error {
  107. if _, ok := l.config.Services[service]; ok {
  108. return fmt.Errorf("conflicting service rules for service %v found", service)
  109. }
  110. if l.config.Services == nil {
  111. l.config.Services = make(map[string]*MethodLoggerConfig)
  112. }
  113. l.config.Services[service] = ml
  114. return nil
  115. }
  116. // Set method logger for "service/method".
  117. //
  118. // New MethodLogger with same method overrides the old one.
  119. func (l *logger) setMethodMethodLogger(method string, ml *MethodLoggerConfig) error {
  120. if _, ok := l.config.Blacklist[method]; ok {
  121. return fmt.Errorf("conflicting blacklist rules for method %v found", method)
  122. }
  123. if _, ok := l.config.Methods[method]; ok {
  124. return fmt.Errorf("conflicting method rules for method %v found", method)
  125. }
  126. if l.config.Methods == nil {
  127. l.config.Methods = make(map[string]*MethodLoggerConfig)
  128. }
  129. l.config.Methods[method] = ml
  130. return nil
  131. }
  132. // Set blacklist method for "-service/method".
  133. func (l *logger) setBlacklist(method string) error {
  134. if _, ok := l.config.Blacklist[method]; ok {
  135. return fmt.Errorf("conflicting blacklist rules for method %v found", method)
  136. }
  137. if _, ok := l.config.Methods[method]; ok {
  138. return fmt.Errorf("conflicting method rules for method %v found", method)
  139. }
  140. if l.config.Blacklist == nil {
  141. l.config.Blacklist = make(map[string]struct{})
  142. }
  143. l.config.Blacklist[method] = struct{}{}
  144. return nil
  145. }
  146. // getMethodLogger returns the MethodLogger for the given methodName.
  147. //
  148. // methodName should be in the format of "/service/method".
  149. //
  150. // Each MethodLogger returned by this method is a new instance. This is to
  151. // generate sequence id within the call.
  152. func (l *logger) GetMethodLogger(methodName string) MethodLogger {
  153. s, m, err := grpcutil.ParseMethod(methodName)
  154. if err != nil {
  155. grpclogLogger.Infof("binarylogging: failed to parse %q: %v", methodName, err)
  156. return nil
  157. }
  158. if ml, ok := l.config.Methods[s+"/"+m]; ok {
  159. return NewTruncatingMethodLogger(ml.Header, ml.Message)
  160. }
  161. if _, ok := l.config.Blacklist[s+"/"+m]; ok {
  162. return nil
  163. }
  164. if ml, ok := l.config.Services[s]; ok {
  165. return NewTruncatingMethodLogger(ml.Header, ml.Message)
  166. }
  167. if l.config.All == nil {
  168. return nil
  169. }
  170. return NewTruncatingMethodLogger(l.config.All.Header, l.config.All.Message)
  171. }