<commit_before>package gop

import (
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/cocoonlife/timber"
)

type Logger timber.Logger

func (a *App) makeConfigLogger() (timber.ConfigLogger, bool) {
	defaultLogPattern := "[%D %T] [%L] %M"
	filenamesByDefault, _ := a.Cfg.GetBool("gop", "log_filename", false)
	if filenamesByDefault {
		defaultLogPattern = "[%D %T] [%L] %S %M"
	}
	logPattern, _ := a.Cfg.Get("gop", "log_pattern", defaultLogPattern)

	// If set, hack all logging to stdout for dev
	forceStdout, _ := a.Cfg.GetBool("gop", "stdout_only_logging", false)
	configLogger := timber.ConfigLogger{
		LogWriter: new(timber.ConsoleWriter),
		Level:     timber.INFO,
		Formatter: timber.NewPatFormatter(logPattern),
	}

	defaultLogDir, _ := a.Cfg.Get("gop", "log_dir", "/var/log")
	fellbackToCWD := false
	a.logDir = defaultLogDir + "/" + a.ProjectName
	if !forceStdout {
		defaultLogFname := a.logDir + "/" + a.AppName + ".log"
		logFname, _ := a.Cfg.Get("gop", "log_file", defaultLogFname)

		newWriter, err := timber.NewFileWriter(logFname)
		_, dirExistsErr := os.Stat(a.logDir)
		if dirExistsErr != nil && os.IsNotExist(dirExistsErr) {
			// Carry on with stdout logging, but remember to mention it
			fellbackToCWD = true
			a.logDir = "."
		} else {
			if err != nil {
				panic(fmt.Sprintf("Can't open log file: %s", err))
			}
			configLogger.LogWriter = newWriter
		}
	}

	logLevelStr, _ := a.Cfg.Get("gop", "log_level", "INFO")
	logLevelStr = strings.ToUpper(logLevelStr)
	for logLevel, levelStr := range timber.LongLevelStrings {
		if logLevelStr == levelStr {
			configLogger.Level = timber.Level(logLevel)
			break
		}
	}
<commit_msg>add support for package-granularity logging. Requires updated timber to be useful.<commit_after>package gop

import (
	"errors"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/cocoonlife/timber"
)

type Logger timber.Logger

func string2Level(logLevelStr string) (timber.Level, error) {
	logLevelStr = strings.ToUpper(logLevelStr)
	for logLevel, levelStr := range timber.LongLevelStrings {
		if logLevelStr == levelStr {
			return timber.Level(logLevel), nil
		}
	}
	return 0, errors.New("Not found")
}

func (a *App) makeConfigLogger() (timber.ConfigLogger, bool) {
	defaultLogPattern := "[%D %T] [%L] %M"
	filenamesByDefault, _ := a.Cfg.GetBool("gop", "log_filename", false)
	if filenamesByDefault {
		defaultLogPattern = "[%D %T] [%L] %S %M"
	}
	logPattern, _ := a.Cfg.Get("gop", "log_pattern", defaultLogPattern)

	// If set, hack all logging to stdout for dev
	forceStdout, _ := a.Cfg.GetBool("gop", "stdout_only_logging", false)
	configLogger := timber.ConfigLogger{
		LogWriter: new(timber.ConsoleWriter),
		Level:     timber.INFO,
		Formatter: timber.NewPatFormatter(logPattern),
	}

	defaultLogDir, _ := a.Cfg.Get("gop", "log_dir", "/var/log")
	fellbackToCWD := false
	a.logDir = defaultLogDir + "/" + a.ProjectName
	if !forceStdout {
		defaultLogFname := a.logDir + "/" + a.AppName + ".log"
		logFname, _ := a.Cfg.Get("gop", "log_file", defaultLogFname)

		newWriter, err := timber.NewFileWriter(logFname)
		_, dirExistsErr := os.Stat(a.logDir)
		if dirExistsErr != nil && os.IsNotExist(dirExistsErr) {
			// Carry on with stdout logging, but remember to mention it
			fellbackToCWD = true
			a.logDir = "."
		} else {
			if err != nil {
				panic(fmt.Sprintf("Can't open log file: %s", err))
			}
			configLogger.LogWriter = newWriter
		}
	}

	logLevelStr, _ := a.Cfg.Get("gop", "log_level", "INFO")
	logLevel, err := string2Level(logLevelStr)
	if err == nil {
		configLogger.Level = timber.Level(logLevel)
	}

	granularsPrefix, _ := a.Cfg.Get("gop", "log_granulars_prefix", "")
	granularsStrs, _ := a.Cfg.GetList("gop", "log_granulars", nil)
	if granularsStrs != nil {
		configLogger.Granulars = make(map[string]timber.Level)
	GRANULARS:
		for _, granStr := range granularsStrs {
			bits := strings.Split(granStr, ":")
			if len(bits) != 2 {
				continue GRANULARS
			}
			pkgPart := bits[0]
			pkgLevel := bits[1]

			if pkgPart == "" || pkgLevel == "" {
				continue GRANULARS
			}
			pkgName := pkgPart
			if granularsPrefix != "" {
				pkgName = granularsPrefix + "/" + pkgPart
			}
			logLevel, err := string2Level(pkgLevel)
			if err == nil {
				configLogger.Granulars[pkgName] = logLevel
			}
		}
	}

{'fraction_non_alphanumeric': 0.15271966527196654, 'fraction_numerical': 0.0016271501627150163, 'mean_word_length': 3.968822170900693, 'pattern_counts': {'":': 1, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2515023', 'n_tokens_mistral': 1755, 'n_tokens_neox': 1602, 'n_words': 338}