| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 | package loggerimport (	"fmt"	"os"	"path/filepath"	"runtime"	"sort"	"strings"	"sync"	"time")// TimeFormatDay - format of the day for timestampsconst TimeFormatDay = "2006-01-02"// TimeFormat - total time formatconst TimeFormat = "2006-01-02 15:04:05"// == fields ==var currentLogs = make(map[string]entry)var mu sync.Mutexvar program stringfunc init() {	fullpath, err := os.Executable()	if err != nil {		fullpath = ""	}	program = filepath.Base(fullpath)}// Log - handles adding logsfunc Log(verbosity int, message ...string) {	mu.Lock()	defer mu.Unlock()	var currentTime = time.Now()	var currentMessage = MakeString(" ", message...)	if getVerbose() >= 4 {		pc, file, line, ok := runtime.Caller(1)		if !ok {			file = "?"			line = 0		}		fn := runtime.FuncForPC(pc)		var fnName string		if fn == nil {			fnName = "?()"		} else {			fnName = strings.TrimLeft(filepath.Ext(fn.Name()), ".") + "()"		}		currentMessage = fmt.Sprintf("[%s-%d] %s: %s",			filepath.Base(file), line, fnName, currentMessage)	}	if int32(verbosity) <= getVerbose() && getVerbose() >= 0 {		fmt.Printf("[%s] %s %s \n", program, currentTime.Format(TimeFormat), currentMessage)	}	if program == "netmaker" {		currentLogs[currentMessage] = entry{			Time:  currentTime.Format("2006-01-02 15:04:05.999999999"),			Count: currentLogs[currentMessage].Count + 1,		}	}}// Dump - dumps all logs into a formatted stringfunc Dump() string {	if program != "netmaker" {		return ""	}	mu.Lock()	defer mu.Unlock()	var dumpString = ""	type keyVal struct {		Key   string		Value time.Time		Count int	}	var dumpLogs = make([]keyVal, 0, len(currentLogs))	for key := range currentLogs {		currentEntry := currentLogs[key]		parsedTime, err := time.Parse(TimeFormat, currentEntry.Time)		if err == nil {			dumpLogs = append(dumpLogs, keyVal{				Key:   key,				Value: parsedTime,				Count: currentEntry.Count,			})		}	}	sort.Slice(dumpLogs, func(i, j int) bool {		return dumpLogs[i].Value.Before(dumpLogs[j].Value)	})	for i := range dumpLogs {		var currLog = dumpLogs[i]		dumpString += MakeString(" ", "[netmaker]", currLog.Value.Format(TimeFormat), currLog.Key, fmt.Sprintf("(%d)", currLog.Count), "\n")	}	resetLogs()	return dumpString}// DumpFile - appends log dump log filefunc DumpFile(filePath string) {	if program != "netmaker" {		return	}	f, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)	if err != nil {		fmt.Println(MakeString(" ", "could not open log file", filePath))		return	}	defer f.Close()	if _, err = f.WriteString(Dump()); err != nil {		fmt.Println("could not dump logs")	}}// Retrieve - retrieves logs from given filefunc Retrieve(filePath string) string {	contents, err := os.ReadFile(filePath)	if err != nil {		panic(err)	}	return string(contents)}// FatalLog - exits os after loggingfunc FatalLog(message ...string) {	fmt.Printf("[netmaker] Fatal: %s \n", MakeString(" ", message...))	os.Exit(2)}// == private ==// resetLogs - reallocates logs mapfunc resetLogs() {	currentLogs = make(map[string]entry)}
 |