main.go 4.52 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 goLogger struct {
	muEv   *sync.Mutex
	eventf *os.File

	eventFileName string

	muEr   *sync.Mutex
	errorf *os.File

	errorFileName string

	splitSize int64
}

var logger goLogger

func Init(flags Option, splitSize int64) error {
	timestamp := "_" + time.Now().Format(time.RFC3339)
	var err error

	logger.splitSize = splitSize

	// 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 err
			}
		}

		logger.eventFileName = "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 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 err
			}
		}

		logger.errorFileName = "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 err
		}

		logger.muEr = &sync.Mutex{}
	}

	return nil
}

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

func 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 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 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 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 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 *goLogger) 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 *goLogger) 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")
		}
	}
}