You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

168 lines
4.6 KiB

  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. )
  26. // Logger is the global binary logger. It can be used to get binary logger for
  27. // each method.
  28. type Logger interface {
  29. getMethodLogger(methodName string) *MethodLogger
  30. }
  31. // binLogger is the global binary logger for the binary. One of this should be
  32. // built at init time from the configuration (environment varialbe or flags).
  33. //
  34. // It is used to get a methodLogger for each individual method.
  35. var binLogger Logger
  36. // SetLogger sets the binarg logger.
  37. //
  38. // Only call this at init time.
  39. func SetLogger(l Logger) {
  40. binLogger = l
  41. }
  42. // GetMethodLogger returns the methodLogger for the given methodName.
  43. //
  44. // methodName should be in the format of "/service/method".
  45. //
  46. // Each methodLogger returned by this method is a new instance. This is to
  47. // generate sequence id within the call.
  48. func GetMethodLogger(methodName string) *MethodLogger {
  49. if binLogger == nil {
  50. return nil
  51. }
  52. return binLogger.getMethodLogger(methodName)
  53. }
  54. func init() {
  55. const envStr = "GRPC_BINARY_LOG_FILTER"
  56. configStr := os.Getenv(envStr)
  57. binLogger = NewLoggerFromConfigString(configStr)
  58. }
  59. type methodLoggerConfig struct {
  60. // Max length of header and message.
  61. hdr, msg uint64
  62. }
  63. type logger struct {
  64. all *methodLoggerConfig
  65. services map[string]*methodLoggerConfig
  66. methods map[string]*methodLoggerConfig
  67. blacklist map[string]struct{}
  68. }
  69. // newEmptyLogger creates an empty logger. The map fields need to be filled in
  70. // using the set* functions.
  71. func newEmptyLogger() *logger {
  72. return &logger{}
  73. }
  74. // Set method logger for "*".
  75. func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error {
  76. if l.all != nil {
  77. return fmt.Errorf("conflicting global rules found")
  78. }
  79. l.all = ml
  80. return nil
  81. }
  82. // Set method logger for "service/*".
  83. //
  84. // New methodLogger with same service overrides the old one.
  85. func (l *logger) setServiceMethodLogger(service string, ml *methodLoggerConfig) error {
  86. if _, ok := l.services[service]; ok {
  87. return fmt.Errorf("conflicting rules for service %v found", service)
  88. }
  89. if l.services == nil {
  90. l.services = make(map[string]*methodLoggerConfig)
  91. }
  92. l.services[service] = ml
  93. return nil
  94. }
  95. // Set method logger for "service/method".
  96. //
  97. // New methodLogger with same method overrides the old one.
  98. func (l *logger) setMethodMethodLogger(method string, ml *methodLoggerConfig) error {
  99. if _, ok := l.blacklist[method]; ok {
  100. return fmt.Errorf("conflicting rules for method %v found", method)
  101. }
  102. if _, ok := l.methods[method]; ok {
  103. return fmt.Errorf("conflicting rules for method %v found", method)
  104. }
  105. if l.methods == nil {
  106. l.methods = make(map[string]*methodLoggerConfig)
  107. }
  108. l.methods[method] = ml
  109. return nil
  110. }
  111. // Set blacklist method for "-service/method".
  112. func (l *logger) setBlacklist(method string) error {
  113. if _, ok := l.blacklist[method]; ok {
  114. return fmt.Errorf("conflicting rules for method %v found", method)
  115. }
  116. if _, ok := l.methods[method]; ok {
  117. return fmt.Errorf("conflicting rules for method %v found", method)
  118. }
  119. if l.blacklist == nil {
  120. l.blacklist = make(map[string]struct{})
  121. }
  122. l.blacklist[method] = struct{}{}
  123. return nil
  124. }
  125. // getMethodLogger returns the methodLogger for the given methodName.
  126. //
  127. // methodName should be in the format of "/service/method".
  128. //
  129. // Each methodLogger returned by this method is a new instance. This is to
  130. // generate sequence id within the call.
  131. func (l *logger) getMethodLogger(methodName string) *MethodLogger {
  132. s, m, err := parseMethodName(methodName)
  133. if err != nil {
  134. grpclog.Infof("binarylogging: failed to parse %q: %v", methodName, err)
  135. return nil
  136. }
  137. if ml, ok := l.methods[s+"/"+m]; ok {
  138. return newMethodLogger(ml.hdr, ml.msg)
  139. }
  140. if _, ok := l.blacklist[s+"/"+m]; ok {
  141. return nil
  142. }
  143. if ml, ok := l.services[s]; ok {
  144. return newMethodLogger(ml.hdr, ml.msg)
  145. }
  146. if l.all == nil {
  147. return nil
  148. }
  149. return newMethodLogger(l.all.hdr, l.all.msg)
  150. }