main.go 3.99 KB
package gologger

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

var muEv = &sync.Mutex{}
var muEr = &sync.Mutex{}

const MaxLogFileSize5MB int64 = 5 * 1024 * 1024
const MaxLogFileSize1MB int64 = 1 * 1024 * 1024
const MaxLogFileSize500KB int64 = 500 * 1024
const MaxLogFileSize100KB int64 = 100 * 1024
const MaxLogFileSize512B int64 = 512

const ErrDirName = "error-logs"
const EvtDirName = "event-logs"

type Logger struct {
	eventf        *os.File
	eventFileName string
	errorf        *os.File
	errorFileName string
}

var logger Logger

func Init(eventFileName, errorFileName string) error {
	timestamp := "_" + time.Now().Format(time.RFC3339)

	// create directories to keep log files
	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
		}
	}

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

	// create files
	logger.eventFileName = eventFileName
	logger.errorFileName = errorFileName

	path := filepath.Join(EvtDirName, eventFileName+timestamp)
	logger.eventf, err = os.Create(path)

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

	path = filepath.Join(ErrDirName, errorFileName+timestamp)
	logger.errorf, err = os.Create(path)

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

	return nil
}

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

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

func LogDetailedEvent(event string) {
	muEv.Lock()
	defer 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 LogDetailedError(err error) {
	muEr.Lock()
	defer 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() {
	// close files
	err := logger.eventf.Close()
	if err != nil {
		fmt.Printf("logger: on exit: couldn't close event log file\n")
	}

	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() >= MaxLogFileSize100KB {
		// 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() >= MaxLogFileSize100KB {
		// 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")
		}
	}
}