logger.go 2.4 KB

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