log.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package hclog
  2. import (
  3. "io"
  4. "log"
  5. "os"
  6. "strings"
  7. "sync"
  8. )
  9. var (
  10. DefaultOutput = os.Stderr
  11. DefaultLevel = Info
  12. )
  13. type Level int
  14. const (
  15. // This is a special level used to indicate that no level has been
  16. // set and allow for a default to be used.
  17. NoLevel Level = 0
  18. // The most verbose level. Intended to be used for the tracing of actions
  19. // in code, such as function enters/exits, etc.
  20. Trace Level = 1
  21. // For programmer lowlevel analysis.
  22. Debug Level = 2
  23. // For information about steady state operations.
  24. Info Level = 3
  25. // For information about rare but handled events.
  26. Warn Level = 4
  27. // For information about unrecoverable events.
  28. Error Level = 5
  29. )
  30. // When processing a value of this type, the logger automatically treats the first
  31. // argument as a Printf formatting string and passes the rest as the values to be
  32. // formatted. For example: L.Info(Fmt{"%d beans/day", beans}). This is a simple
  33. // convience type for when formatting is required.
  34. type Format []interface{}
  35. // Fmt returns a Format type. This is a convience function for creating a Format
  36. // type.
  37. func Fmt(str string, args ...interface{}) Format {
  38. return append(Format{str}, args...)
  39. }
  40. // LevelFromString returns a Level type for the named log level, or "NoLevel" if
  41. // the level string is invalid. This facilitates setting the log level via
  42. // config or environment variable by name in a predictable way.
  43. func LevelFromString(levelStr string) Level {
  44. // We don't care about case. Accept "INFO" or "info"
  45. levelStr = strings.ToLower(strings.TrimSpace(levelStr))
  46. switch levelStr {
  47. case "trace":
  48. return Trace
  49. case "debug":
  50. return Debug
  51. case "info":
  52. return Info
  53. case "warn":
  54. return Warn
  55. case "error":
  56. return Error
  57. default:
  58. return NoLevel
  59. }
  60. }
  61. // The main Logger interface. All code should code against this interface only.
  62. type Logger interface {
  63. // Args are alternating key, val pairs
  64. // keys must be strings
  65. // vals can be any type, but display is implementation specific
  66. // Emit a message and key/value pairs at the TRACE level
  67. Trace(msg string, args ...interface{})
  68. // Emit a message and key/value pairs at the DEBUG level
  69. Debug(msg string, args ...interface{})
  70. // Emit a message and key/value pairs at the INFO level
  71. Info(msg string, args ...interface{})
  72. // Emit a message and key/value pairs at the WARN level
  73. Warn(msg string, args ...interface{})
  74. // Emit a message and key/value pairs at the ERROR level
  75. Error(msg string, args ...interface{})
  76. // Indicate if TRACE logs would be emitted. This and the other Is* guards
  77. // are used to elide expensive logging code based on the current level.
  78. IsTrace() bool
  79. // Indicate if DEBUG logs would be emitted. This and the other Is* guards
  80. IsDebug() bool
  81. // Indicate if INFO logs would be emitted. This and the other Is* guards
  82. IsInfo() bool
  83. // Indicate if WARN logs would be emitted. This and the other Is* guards
  84. IsWarn() bool
  85. // Indicate if ERROR logs would be emitted. This and the other Is* guards
  86. IsError() bool
  87. // Creates a sublogger that will always have the given key/value pairs
  88. With(args ...interface{}) Logger
  89. // Create a logger that will prepend the name string on the front of all messages.
  90. // If the logger already has a name, the new value will be appended to the current
  91. // name. That way, a major subsystem can use this to decorate all it's own logs
  92. // without losing context.
  93. Named(name string) Logger
  94. // Create a logger that will prepend the name string on the front of all messages.
  95. // This sets the name of the logger to the value directly, unlike Named which honor
  96. // the current name as well.
  97. ResetNamed(name string) Logger
  98. // Return a value that conforms to the stdlib log.Logger interface
  99. StandardLogger(opts *StandardLoggerOptions) *log.Logger
  100. }
  101. type StandardLoggerOptions struct {
  102. // Indicate that some minimal parsing should be done on strings to try
  103. // and detect their level and re-emit them.
  104. // This supports the strings like [ERROR], [ERR] [TRACE], [WARN], [INFO],
  105. // [DEBUG] and strip it off before reapplying it.
  106. InferLevels bool
  107. }
  108. type LoggerOptions struct {
  109. // Name of the subsystem to prefix logs with
  110. Name string
  111. // The threshold for the logger. Anything less severe is supressed
  112. Level Level
  113. // Where to write the logs to. Defaults to os.Stdout if nil
  114. Output io.Writer
  115. // An optional mutex pointer in case Output is shared
  116. Mutex *sync.Mutex
  117. // Control if the output should be in JSON.
  118. JSONFormat bool
  119. // Include file and line information in each log line
  120. IncludeLocation bool
  121. // The time format to use instead of the default
  122. TimeFormat string
  123. }