main.go 4.67 KB
package gologger

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"sync"
	"time"
)

type Option uint8

const (
	Events Option = 0x01
	Errors Option = 0x02
)

const (
	MaxLogSize5MB   int64 = 5 * 1024 * 1024
	MaxLogSize1MB   int64 = 1 * 1024 * 1024
	MaxLogSize500KB int64 = 500 * 1024
	MaxLogSize100KB int64 = 100 * 1024
	MaxLogSize512B  int64 = 512
)

const errDirName = "error-logs"
const evtDirName = "event-logs"

type Logger struct {
	muEv   *sync.Mutex
	eventf *os.File

	eventFileName string

	muEr   *sync.Mutex
	errorf *os.File

	errorFileName string

	splitSize int64
}

func New(name string, flags Option, splitSize int64) (logger *Logger, err error) {
	logger = &Logger{}

	logger.splitSize = splitSize

	timestamp := "_" + time.Now().Format(time.RFC3339)

	// event file/dir
	if flags&Events > 0 {
		err = os.Mkdir(evtDirName, os.ModePerm)
		if err != nil {
			if !os.IsExist(err) {
				fmt.Printf("logger: mkdir: couldn't create event log directory\n")
				return nil, err
			}
		}

		logger.eventFileName = name + "-events"
		path := filepath.Join(evtDirName, logger.eventFileName+timestamp+".txt")
		logger.eventf, err = os.Create(path)
		if err != nil {
			fmt.Printf("logger: new: couldn't create event log file\n")
			return nil, err
		}

		logger.muEv = &sync.Mutex{}
	}

	// error file/dir
	if flags&Errors > 0 {
		err = os.Mkdir(errDirName, os.ModePerm)
		if err != nil {
			if !os.IsExist(err) {
				fmt.Printf("logger: new: couldn't create error log directory\n")
				return nil, err
			}
		}

		logger.errorFileName = name + "-errors"
		path := filepath.Join(errDirName, logger.errorFileName+timestamp+".txt")
		logger.errorf, err = os.Create(path)
		if err != nil {
			fmt.Printf("logger: new: couldn't create error log file\n")
			return nil, err
		}

		logger.muEr = &sync.Mutex{}
	}

	return logger, nil
}

func (logger *Logger) Print(s string) {
	fmt.Printf(time.Now().Format(time.RFC3339) + ": " + s + "\n")
}

func (logger *Logger) LogEvent(event string) {
	if logger.eventf != nil {
		logger.muEv.Lock()
		defer logger.muEv.Unlock()
		logger.eventf.WriteString(time.Now().Format(time.RFC3339) + ": " + event + "\n")
		logger.splitEventLog()
	}
}

func (logger *Logger) LogError(comment string, err error) {
	if logger.errorf != nil {
		logger.muEr.Lock()
		defer logger.muEr.Unlock()
		logger.errorf.WriteString(time.Now().Format(time.RFC3339) + ": " + comment + ": " + err.Error() + "\n")
		logger.splitErrorLog()
	}
}

func (logger *Logger) TraceEvent(event string) {
	if logger.eventf != nil {
		logger.muEv.Lock()
		defer logger.muEv.Unlock()
		_, file, line, ok := runtime.Caller(1)
		var s string
		if ok {
			s = fmt.Sprintf("%s: %s %d: %s\n", time.Now().Format(time.RFC3339), file, line, event)
		} else {
			s = fmt.Sprintf(time.Now().Format(time.RFC3339) + ": [can't retreive stack details]:" + event + "\n")
		}
		logger.eventf.WriteString(s)
		logger.splitEventLog()
	}
}

func (logger *Logger) TraceError(err error) {
	if logger.errorf != nil {
		logger.muEr.Lock()
		defer logger.muEr.Unlock()
		_, file, line, ok := runtime.Caller(1)
		var s string
		if ok {
			s = fmt.Sprintf("%s %s %d: %s\n", time.Now().Format(time.RFC3339), file, line, err.Error())
		} else {
			s = fmt.Sprintf(time.Now().Format(time.RFC3339) + ": [can't retreive stack details]:" + err.Error() + "\n")
		}
		logger.errorf.WriteString(s)
		logger.splitErrorLog()
	}
}

func (logger *Logger) Close() {
	if logger.eventf != nil {
		err := logger.eventf.Close()
		if err != nil {
			fmt.Printf("logger: on exit: couldn't close event log file\n")
		}
	}

	if logger.errorf != nil {
		err := logger.errorf.Close()
		if err != nil {
			fmt.Printf("logger: on exit: couldn't close error log file\n")
		}
	}
}

func (l *Logger) splitEventLog() {
	timestamp := "_" + time.Now().Format(time.RFC3339)

	evfstats, _ := l.eventf.Stat()
	if evfstats.Size() >= l.splitSize {
		// close old file
		err := l.eventf.Close()
		if err != nil {
			fmt.Printf("logger: split: couldn't close event file\n")
			return
		}
		// open new file
		var errnew error
		path := filepath.Join(evtDirName, l.eventFileName+timestamp)
		l.eventf, errnew = os.Create(path)

		if errnew != nil {
			fmt.Printf("logger: split: couldn't create event log file\n")
		}
	}
}

func (l *Logger) splitErrorLog() {
	timestamp := "_" + time.Now().Format(time.RFC3339)

	erfstats, _ := l.errorf.Stat()
	if erfstats.Size() >= l.splitSize {
		// close old file
		err := l.errorf.Close()
		if err != nil {
			fmt.Printf("logger: split: couldn't close error file\n")
			return
		}
		// open new file
		var errnew error
		path := filepath.Join(errDirName, l.errorFileName+timestamp)
		l.errorf, errnew = os.Create(path)

		if errnew != nil {
			fmt.Printf("logger: split: couldn't create error log file\n")
		}
	}
}