logger.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package logger
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "runtime"
  7. "sort"
  8. "strings"
  9. "sync"
  10. "time"
  11. )
  12. // TimeFormatDay - format of the day for timestamps
  13. const TimeFormatDay = "2006-01-02"
  14. // TimeFormat - total time format
  15. const TimeFormat = "2006-01-02 15:04:05"
  16. // == fields ==
  17. var currentLogs = make(map[string]entry)
  18. var mu sync.Mutex
  19. var program string
  20. func init() {
  21. fullpath, err := os.Executable()
  22. if err != nil {
  23. fullpath = ""
  24. }
  25. program = filepath.Base(fullpath)
  26. }
  27. // Log - handles adding logs
  28. func Log(verbosity int, message ...string) {
  29. mu.Lock()
  30. defer mu.Unlock()
  31. var currentTime = time.Now()
  32. var currentMessage = MakeString(" ", message...)
  33. if getVerbose() >= 4 {
  34. pc, file, line, ok := runtime.Caller(1)
  35. if !ok {
  36. file = "?"
  37. line = 0
  38. }
  39. fn := runtime.FuncForPC(pc)
  40. var fnName string
  41. if fn == nil {
  42. fnName = "?()"
  43. } else {
  44. fnName = strings.TrimLeft(filepath.Ext(fn.Name()), ".") + "()"
  45. }
  46. currentMessage = fmt.Sprintf("[%s-%d] %s: %s",
  47. filepath.Base(file), line, fnName, currentMessage)
  48. }
  49. if int32(verbosity) <= getVerbose() && getVerbose() >= 0 {
  50. fmt.Printf("[%s] %s %s \n", program, currentTime.Format(TimeFormat), currentMessage)
  51. }
  52. if program == "netmaker" {
  53. currentLogs[currentMessage] = entry{
  54. Time: currentTime.Format("2006-01-02 15:04:05.999999999"),
  55. Count: currentLogs[currentMessage].Count + 1,
  56. }
  57. }
  58. }
  59. // Dump - dumps all logs into a formatted string
  60. func Dump() string {
  61. if program != "netmaker" {
  62. return ""
  63. }
  64. mu.Lock()
  65. defer mu.Unlock()
  66. var dumpString = ""
  67. type keyVal struct {
  68. Key string
  69. Value time.Time
  70. Count int
  71. }
  72. var dumpLogs = make([]keyVal, 0, len(currentLogs))
  73. for key := range currentLogs {
  74. currentEntry := currentLogs[key]
  75. parsedTime, err := time.Parse(TimeFormat, currentEntry.Time)
  76. if err == nil {
  77. dumpLogs = append(dumpLogs, keyVal{
  78. Key: key,
  79. Value: parsedTime,
  80. Count: currentEntry.Count,
  81. })
  82. }
  83. }
  84. sort.Slice(dumpLogs, func(i, j int) bool {
  85. return dumpLogs[i].Value.Before(dumpLogs[j].Value)
  86. })
  87. for i := range dumpLogs {
  88. var currLog = dumpLogs[i]
  89. dumpString += MakeString(" ", "[netmaker]", currLog.Value.Format(TimeFormat), currLog.Key, fmt.Sprintf("(%d)", currLog.Count), "\n")
  90. }
  91. resetLogs()
  92. return dumpString
  93. }
  94. // DumpFile - appends log dump log file
  95. func DumpFile(filePath string) {
  96. if program != "netmaker" {
  97. return
  98. }
  99. f, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
  100. if err != nil {
  101. fmt.Println(MakeString(" ", "could not open log file", filePath))
  102. return
  103. }
  104. defer f.Close()
  105. if _, err = f.WriteString(Dump()); err != nil {
  106. fmt.Println("could not dump logs")
  107. }
  108. }
  109. // Retrieve - retrieves logs from given file
  110. func Retrieve(filePath string) string {
  111. contents, err := os.ReadFile(filePath)
  112. if err != nil {
  113. panic(err)
  114. }
  115. return string(contents)
  116. }
  117. // FatalLog - exits os after logging
  118. func FatalLog(message ...string) {
  119. fmt.Printf("[%s] Fatal: %s \n", program, MakeString(" ", message...))
  120. os.Exit(2)
  121. }
  122. // == private ==
  123. // resetLogs - reallocates logs map
  124. func resetLogs() {
  125. currentLogs = make(map[string]entry)
  126. }