logger.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package cron
  2. import (
  3. "io"
  4. "log"
  5. "os"
  6. "strings"
  7. "time"
  8. )
  9. // DefaultLogger is used by Cron if none is specified.
  10. var DefaultLogger = PrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))
  11. // DiscardLogger can be used by callers to discard all log messages.
  12. var DiscardLogger = PrintfLogger(log.New(io.Discard, "", 0))
  13. // Logger is the interface used in this package for logging, so that any backend
  14. // can be plugged in. It is a subset of the github.com/go-logr/logr interface.
  15. type Logger interface {
  16. // Info logs routine messages about cron's operation.
  17. Info(msg string, keysAndValues ...interface{})
  18. // Error logs an error condition.
  19. Error(err error, msg string, keysAndValues ...interface{})
  20. }
  21. // PrintfLogger wraps a Printf-based logger (such as the standard library "log")
  22. // into an implementation of the Logger interface which logs errors only.
  23. func PrintfLogger(l interface{ Printf(string, ...interface{}) }) Logger {
  24. return printfLogger{l, false}
  25. }
  26. // VerbosePrintfLogger wraps a Printf-based logger (such as the standard library
  27. // "log") into an implementation of the Logger interface which logs everything.
  28. func VerbosePrintfLogger(l interface{ Printf(string, ...interface{}) }) Logger {
  29. return printfLogger{l, true}
  30. }
  31. type printfLogger struct {
  32. logger interface{ Printf(string, ...interface{}) }
  33. logInfo bool
  34. }
  35. func (pl printfLogger) Info(msg string, keysAndValues ...interface{}) {
  36. if pl.logInfo {
  37. keysAndValues = formatTimes(keysAndValues)
  38. pl.logger.Printf(
  39. formatString(len(keysAndValues)),
  40. append([]interface{}{msg}, keysAndValues...)...)
  41. }
  42. }
  43. func (pl printfLogger) Error(err error, msg string, keysAndValues ...interface{}) {
  44. keysAndValues = formatTimes(keysAndValues)
  45. pl.logger.Printf(
  46. formatString(len(keysAndValues)+2),
  47. append([]interface{}{msg, "error", err}, keysAndValues...)...)
  48. }
  49. // formatString returns a logfmt-like format string for the number of
  50. // key/values.
  51. func formatString(numKeysAndValues int) string {
  52. var sb strings.Builder
  53. sb.WriteString("%s")
  54. if numKeysAndValues > 0 {
  55. sb.WriteString(", ")
  56. }
  57. for i := 0; i < numKeysAndValues/2; i++ {
  58. if i > 0 {
  59. sb.WriteString(", ")
  60. }
  61. sb.WriteString("%v=%v")
  62. }
  63. return sb.String()
  64. }
  65. // formatTimes formats any time.Time values as RFC3339.
  66. func formatTimes(keysAndValues []interface{}) []interface{} {
  67. var formattedArgs []interface{}
  68. for _, arg := range keysAndValues {
  69. if t, ok := arg.(time.Time); ok {
  70. arg = t.Format(time.RFC3339)
  71. }
  72. formattedArgs = append(formattedArgs, arg)
  73. }
  74. return formattedArgs
  75. }