logger.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package core
  2. import (
  3. "log"
  4. "os"
  5. "runtime/debug"
  6. "strings"
  7. )
  8. // ConfigLogger is the key for the pipeline's logger
  9. const ConfigLogger = "Core.Logger"
  10. // Logger defines the output interface used by Hercules components.
  11. type Logger interface {
  12. Info(...interface{})
  13. Infof(string, ...interface{})
  14. Warn(...interface{})
  15. Warnf(string, ...interface{})
  16. Error(...interface{})
  17. Errorf(string, ...interface{})
  18. }
  19. // DefaultLogger is the default logger used by a pipeline, and wraps the standard
  20. // log library.
  21. type DefaultLogger struct {
  22. I *log.Logger
  23. W *log.Logger
  24. E *log.Logger
  25. }
  26. // NewLogger returns a configured default logger.
  27. func NewLogger() *DefaultLogger {
  28. return &DefaultLogger{
  29. I: log.New(os.Stderr, "[INFO] ", log.LstdFlags),
  30. W: log.New(os.Stderr, "[WARN] ", log.LstdFlags),
  31. E: log.New(os.Stderr, "[ERROR] ", log.LstdFlags),
  32. }
  33. }
  34. // Info writes to "info" logger.
  35. func (d *DefaultLogger) Info(v ...interface{}) { d.I.Println(v...) }
  36. // Infof writes to "info" logger with printf-style formatting.
  37. func (d *DefaultLogger) Infof(f string, v ...interface{}) { d.I.Printf(f, v...) }
  38. // Warn writes to the "warning" logger.
  39. func (d *DefaultLogger) Warn(v ...interface{}) { d.W.Println(v...) }
  40. // Warnf writes to the "warning" logger with printf-style formatting.
  41. func (d *DefaultLogger) Warnf(f string, v ...interface{}) { d.W.Printf(f, v...) }
  42. // Error writes to the "error" logger and logs the current stacktrace.
  43. func (d *DefaultLogger) Error(v ...interface{}) {
  44. d.E.Println(v...)
  45. d.logStacktraceToErr()
  46. }
  47. // Errorf writes to the "error" logger with printf-style formatting and logs the
  48. // current stacktrace.
  49. func (d *DefaultLogger) Errorf(f string, v ...interface{}) {
  50. d.E.Printf(f, v...)
  51. d.logStacktraceToErr()
  52. }
  53. // logStacktraceToErr prints a stacktrace to the logger's error output.
  54. // It skips 4 levels that aren't meaningful to a logged stacktrace:
  55. // * debug.Stack()
  56. // * core.captureStacktrace()
  57. // * DefaultLogger::logStacktraceToErr()
  58. // * DefaultLogger::Error() or DefaultLogger::Errorf()
  59. func (d *DefaultLogger) logStacktraceToErr() {
  60. d.E.Println("stacktrace:\n" + strings.Join(captureStacktrace(0), "\n"))
  61. }
  62. func captureStacktrace(skip int) []string {
  63. stack := string(debug.Stack())
  64. lines := strings.Split(stack, "\n")
  65. linesToSkip := 2*skip + 1
  66. if linesToSkip > len(lines) {
  67. return lines
  68. }
  69. return lines[linesToSkip:]
  70. }