logger.go 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. Critical(...interface{})
  19. Criticalf(string, ...interface{})
  20. }
  21. // DefaultLogger is the default logger used by a pipeline, and wraps the standard
  22. // log library.
  23. type DefaultLogger struct {
  24. I *log.Logger
  25. W *log.Logger
  26. E *log.Logger
  27. }
  28. // NewLogger returns a configured default logger.
  29. func NewLogger() *DefaultLogger {
  30. return &DefaultLogger{
  31. I: log.New(os.Stderr, "[INFO] ", log.LstdFlags),
  32. W: log.New(os.Stderr, "[WARN] ", log.LstdFlags),
  33. E: log.New(os.Stderr, "[ERROR] ", log.LstdFlags),
  34. }
  35. }
  36. // Info writes to "info" logger.
  37. func (d *DefaultLogger) Info(v ...interface{}) { d.I.Println(v...) }
  38. // Infof writes to "info" logger with printf-style formatting.
  39. func (d *DefaultLogger) Infof(f string, v ...interface{}) { d.I.Printf(f, v...) }
  40. // Warn writes to the "warning" logger.
  41. func (d *DefaultLogger) Warn(v ...interface{}) { d.W.Println(v...) }
  42. // Warnf writes to the "warning" logger with printf-style formatting.
  43. func (d *DefaultLogger) Warnf(f string, v ...interface{}) { d.W.Printf(f, v...) }
  44. // Error writes to the "error" logger.
  45. func (d *DefaultLogger) Error(v ...interface{}) { d.E.Println(v...) }
  46. // Errorf writes to the "error" logger with printf-style formatting.
  47. func (d *DefaultLogger) Errorf(f string, v ...interface{}) { d.E.Printf(f, v...) }
  48. // Critical writes to the "error" logger and logs the current stacktrace.
  49. func (d *DefaultLogger) Critical(v ...interface{}) {
  50. d.E.Println(v...)
  51. d.logStacktraceToErr()
  52. }
  53. // Criticalf writes to the "error" logger with printf-style formatting and logs the
  54. // current stacktrace.
  55. func (d *DefaultLogger) Criticalf(f string, v ...interface{}) {
  56. d.E.Printf(f, v...)
  57. d.logStacktraceToErr()
  58. }
  59. // logStacktraceToErr prints a stacktrace to the logger's error output.
  60. // It skips 4 levels that aren't meaningful to a logged stacktrace:
  61. // * debug.Stack()
  62. // * core.captureStacktrace()
  63. // * DefaultLogger::logStacktraceToErr()
  64. // * DefaultLogger::Error() or DefaultLogger::Errorf()
  65. func (d *DefaultLogger) logStacktraceToErr() {
  66. d.E.Println("stacktrace:\n" + strings.Join(captureStacktrace(4), "\n"))
  67. }
  68. func captureStacktrace(skip int) []string {
  69. stack := string(debug.Stack())
  70. lines := strings.Split(stack, "\n")
  71. linesToSkip := 2*skip + 1
  72. if linesToSkip > len(lines) {
  73. return lines
  74. }
  75. return lines[linesToSkip:]
  76. }