logr.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. Copyright 2019 The logr Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. // Package logr defines abstract interfaces for logging. Packages can depend on
  14. // these interfaces and callers can implement logging in whatever way is
  15. // appropriate.
  16. //
  17. // This design derives from Dave Cheney's blog:
  18. // http://dave.cheney.net/2015/11/05/lets-talk-about-logging
  19. //
  20. // This is a BETA grade API. Until there is a significant 2nd implementation,
  21. // I don't really know how it will change.
  22. //
  23. // The logging specifically makes it non-trivial to use format strings, to encourage
  24. // attaching structured information instead of unstructured format strings.
  25. //
  26. // Usage
  27. //
  28. // Logging is done using a Logger. Loggers can have name prefixes and named
  29. // values attached, so that all log messages logged with that Logger have some
  30. // base context associated.
  31. //
  32. // The term "key" is used to refer to the name associated with a particular
  33. // value, to disambiguate it from the general Logger name.
  34. //
  35. // For instance, suppose we're trying to reconcile the state of an object, and
  36. // we want to log that we've made some decision.
  37. //
  38. // With the traditional log package, we might write:
  39. // log.Printf(
  40. // "decided to set field foo to value %q for object %s/%s",
  41. // targetValue, object.Namespace, object.Name)
  42. //
  43. // With logr's structured logging, we'd write:
  44. // // elsewhere in the file, set up the logger to log with the prefix of "reconcilers",
  45. // // and the named value target-type=Foo, for extra context.
  46. // log := mainLogger.WithName("reconcilers").WithValues("target-type", "Foo")
  47. //
  48. // // later on...
  49. // log.Info("setting field foo on object", "value", targetValue, "object", object)
  50. //
  51. // Depending on our logging implementation, we could then make logging decisions
  52. // based on field values (like only logging such events for objects in a certain
  53. // namespace), or copy the structured information into a structured log store.
  54. //
  55. // For logging errors, Logger has a method called Error. Suppose we wanted to
  56. // log an error while reconciling. With the traditional log package, we might
  57. // write:
  58. // log.Errorf("unable to reconcile object %s/%s: %v", object.Namespace, object.Name, err)
  59. //
  60. // With logr, we'd instead write:
  61. // // assuming the above setup for log
  62. // log.Error(err, "unable to reconcile object", "object", object)
  63. //
  64. // This functions similarly to:
  65. // log.Info("unable to reconcile object", "error", err, "object", object)
  66. //
  67. // However, it ensures that a standard key for the error value ("error") is used
  68. // across all error logging. Furthermore, certain implementations may choose to
  69. // attach additional information (such as stack traces) on calls to Error, so
  70. // it's preferred to use Error to log errors.
  71. //
  72. // Parts of a log line
  73. //
  74. // Each log message from a Logger has four types of context:
  75. // logger name, log verbosity, log message, and the named values.
  76. //
  77. // The Logger name constists of a series of name "segments" added by successive
  78. // calls to WithName. These name segments will be joined in some way by the
  79. // underlying implementation. It is strongly reccomended that name segements
  80. // contain simple identifiers (letters, digits, and hyphen), and do not contain
  81. // characters that could muddle the log output or confuse the joining operation
  82. // (e.g. whitespace, commas, periods, slashes, brackets, quotes, etc).
  83. //
  84. // Log verbosity represents how little a log matters. Level zero, the default,
  85. // matters most. Increasing levels matter less and less. Try to avoid lots of
  86. // different verbosity levels, and instead provide useful keys, logger names,
  87. // and log messages for users to filter on. It's illegal to pass a log level
  88. // below zero.
  89. //
  90. // The log message consists of a constant message attached to the the log line.
  91. // This should generally be a simple description of what's occuring, and should
  92. // never be a format string.
  93. //
  94. // Variable information can then be attached using named values (key/value
  95. // pairs). Keys are arbitrary strings, while values may be any Go value.
  96. //
  97. // Key Naming Conventions
  98. //
  99. // Keys are not strictly required to conform to any specification or regex, but
  100. // it is recommended that they:
  101. // * be human-readable and meaningful (not auto-generated or simple ordinals)
  102. // * be constant (not dependent on input data)
  103. // * contain only printable characters
  104. // * not contain whitespace or punctuation
  105. //
  106. // These guidelines help ensure that log data is processed properly regardless
  107. // of the log implementation. For example, log implementations will try to
  108. // output JSON data or will store data for later database (e.g. SQL) queries.
  109. //
  110. // While users are generally free to use key names of their choice, it's
  111. // generally best to avoid using the following keys, as they're frequently used
  112. // by implementations:
  113. //
  114. // - `"caller"`: the calling information (file/line) of a particular log line.
  115. // - `"error"`: the underlying error value in the `Error` method.
  116. // - `"level"`: the log level.
  117. // - `"logger"`: the name of the associated logger.
  118. // - `"msg"`: the log message.
  119. // - `"stacktrace"`: the stack trace associated with a particular log line or
  120. // error (often from the `Error` message).
  121. // - `"ts"`: the timestamp for a log line.
  122. //
  123. // Implementations are encouraged to make use of these keys to represent the
  124. // above concepts, when neccessary (for example, in a pure-JSON output form, it
  125. // would be necessary to represent at least message and timestamp as ordinary
  126. // named values).
  127. package logr
  128. // TODO: consider adding back in format strings if they're really needed
  129. // TODO: consider other bits of zap/zapcore functionality like ObjectMarshaller (for arbitrary objects)
  130. // TODO: consider other bits of glog functionality like Flush, InfoDepth, OutputStats
  131. // Logger represents the ability to log messages, both errors and not.
  132. type Logger interface {
  133. // Enabled tests whether this Logger is enabled. For example, commandline
  134. // flags might be used to set the logging verbosity and disable some info
  135. // logs.
  136. Enabled() bool
  137. // Info logs a non-error message with the given key/value pairs as context.
  138. //
  139. // The msg argument should be used to add some constant description to
  140. // the log line. The key/value pairs can then be used to add additional
  141. // variable information. The key/value pairs should alternate string
  142. // keys and arbitrary values.
  143. Info(msg string, keysAndValues ...interface{})
  144. // Error logs an error, with the given message and key/value pairs as context.
  145. // It functions similarly to calling Info with the "error" named value, but may
  146. // have unique behavior, and should be preferred for logging errors (see the
  147. // package documentations for more information).
  148. //
  149. // The msg field should be used to add context to any underlying error,
  150. // while the err field should be used to attach the actual error that
  151. // triggered this log line, if present.
  152. Error(err error, msg string, keysAndValues ...interface{})
  153. // V returns an Logger value for a specific verbosity level, relative to
  154. // this Logger. In other words, V values are additive. V higher verbosity
  155. // level means a log message is less important. It's illegal to pass a log
  156. // level less than zero.
  157. V(level int) Logger
  158. // WithValues adds some key-value pairs of context to a logger.
  159. // See Info for documentation on how key/value pairs work.
  160. WithValues(keysAndValues ...interface{}) Logger
  161. // WithName adds a new element to the logger's name.
  162. // Successive calls with WithName continue to append
  163. // suffixes to the logger's name. It's strongly reccomended
  164. // that name segments contain only letters, digits, and hyphens
  165. // (see the package documentation for more information).
  166. WithName(name string) Logger
  167. }