loveckiy.ivan
6 months ago
11 changed files with 430 additions and 711 deletions
@ -1,321 +0,0 @@ |
|||
// обертка для логирования, которая дополняем аттрибутами логируемого процесса logrus
|
|||
// дополняем значениями, идентифицирующими запущенный сервис UID,Name,Service
|
|||
|
|||
package logger |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
"io" |
|||
"os" |
|||
"strings" |
|||
"sync" |
|||
"time" |
|||
|
|||
"git.lowcodeplatform.net/fabric/lib" |
|||
"github.com/sirupsen/logrus" |
|||
) |
|||
|
|||
var logrusB = logrus.New() |
|||
|
|||
|
|||
type log struct { |
|||
|
|||
// куда логируем? stdout/;*os.File на файл, в который будем писать логи
|
|||
Output io.Writer `json:"output"` |
|||
//Debug:
|
|||
// сообщения отладки, профилирования.
|
|||
// В production системе обычно сообщения этого уровня включаются при первоначальном
|
|||
// запуске системы или для поиска узких мест (bottleneck-ов).
|
|||
|
|||
//Info: - логировать процесс выполнения
|
|||
// обычные сообщения, информирующие о действиях системы.
|
|||
// Реагировать на такие сообщения вообще не надо, но они могут помочь, например,
|
|||
// при поиске багов, расследовании интересных ситуаций итд.
|
|||
|
|||
//Warning: - логировать странные операции
|
|||
// записывая такое сообщение, система пытается привлечь внимание обслуживающего персонала.
|
|||
// Произошло что-то странное. Возможно, это новый тип ситуации, ещё не известный системе.
|
|||
// Следует разобраться в том, что произошло, что это означает, и отнести ситуацию либо к
|
|||
// инфо-сообщению, либо к ошибке. Соответственно, придётся доработать код обработки таких ситуаций.
|
|||
|
|||
//Error: - логировать ошибки
|
|||
// ошибка в работе системы, требующая вмешательства. Что-то не сохранилось, что-то отвалилось.
|
|||
// Необходимо принимать меры довольно быстро! Ошибки этого уровня и выше требуют немедленной записи в лог,
|
|||
// чтобы ускорить реакцию на них. Нужно понимать, что ошибка пользователя – это не ошибка системы.
|
|||
// Если пользователь ввёл в поле -1, где это не предполагалось – не надо писать об этом в лог ошибок.
|
|||
|
|||
//Panic: - логировать критические ошибки
|
|||
// это особый класс ошибок. Такие ошибки приводят к неработоспособности системы в целом, или
|
|||
// неработоспособности одной из подсистем. Чаще всего случаются фатальные ошибки из-за неверной конфигурации
|
|||
// или отказов оборудования. Требуют срочной, немедленной реакции. Возможно, следует предусмотреть уведомление о таких ошибках по SMS.
|
|||
// указываем уровни логирования Error/Warning/Debug/Info/Panic
|
|||
|
|||
//Trace: - логировать обработки запросов
|
|||
|
|||
// можно указывать через | разные уровени логирования, например Error|Warning
|
|||
// можно указать All - логирование всех уровней
|
|||
Levels string `json:"levels"` |
|||
// uid процесса (сервиса), который логируется (случайная величина)
|
|||
UID string `json:"uid"` |
|||
// имя процесса (сервиса), который логируется
|
|||
Name string `json:"name"` |
|||
// название сервиса (app/gui...)
|
|||
Service string `json:"service"` |
|||
// директория сохранения логов
|
|||
Dir string `json:"dir"` |
|||
// uid-конфигурации с которой был запущен процесс
|
|||
Config string `json:"config"` |
|||
// интервал между проверками актуального файла логирования (для текущего дня)
|
|||
IntervalReload time.Duration `json:"delay_reload"` |
|||
// интервал проверками на наличие файлов на удаление
|
|||
IntervalClearFiles time.Duration `json:"interval_clear_files"` |
|||
// период хранения файлов лет-месяцев-дней (например: 0-1-0 - хранить 1 месяц)
|
|||
PeriodSaveFiles string `json:"period_save_files"` |
|||
|
|||
// путь к сервису отправки логов в хранилище (Logbox)
|
|||
LogboxURL string |
|||
// интервал отправки (в промежутках сохраняем в буфер)
|
|||
LogboxSendInterval time.Duration |
|||
|
|||
File *os.File |
|||
|
|||
mux *sync.Mutex |
|||
} |
|||
|
|||
// ConfigLogger общий конфигуратор логирования
|
|||
type ConfigLogger struct { |
|||
Level, Uid, Name, Srv, Config string |
|||
|
|||
File ConfigFileLogger |
|||
Vfs ConfigVfsLogger |
|||
//Logbox ConfigLogboxLogger
|
|||
Priority []string |
|||
} |
|||
|
|||
type Log interface { |
|||
Trace(args ...interface{}) |
|||
Debug(args ...interface{}) |
|||
Info(args ...interface{}) |
|||
Warning(args ...interface{}) |
|||
Error(err error, args ...interface{}) |
|||
Panic(err error, args ...interface{}) |
|||
Exit(err error, args ...interface{}) |
|||
|
|||
Close() |
|||
} |
|||
|
|||
func (l *log) Trace(args ...interface{}) { |
|||
if strings.Contains(l.Levels, "Trace") { |
|||
logrusB.SetOutput(l.Output) |
|||
logrusB.SetFormatter(&logrus.JSONFormatter{}) |
|||
logrusB.SetLevel(logrus.TraceLevel) |
|||
|
|||
logrusB.WithFields(logrus.Fields{ |
|||
"name": l.Name, |
|||
"uid": l.UID, |
|||
"srv": l.Service, |
|||
"config": l.Config, |
|||
}).Trace(args...) |
|||
if strings.Contains(l.Levels, "Stdout") { |
|||
fmt.Printf("Trace: %+v\n", args) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (l *log) Debug(args ...interface{}) { |
|||
if strings.Contains(l.Levels, "Debug") { |
|||
logrusB.SetOutput(l.Output) |
|||
logrusB.SetFormatter(&logrus.JSONFormatter{}) |
|||
|
|||
// Only log the warning severity or above.
|
|||
logrusB.SetLevel(logrus.DebugLevel) |
|||
|
|||
logrusB.WithFields(logrus.Fields{ |
|||
"name": l.Name, |
|||
"uid": l.UID, |
|||
"srv": l.Service, |
|||
"config": l.Config, |
|||
}).Debug(args...) |
|||
if strings.Contains(l.Levels, "Stdout") { |
|||
fmt.Printf("Debug: %+v\n", args) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (l *log) Info(args ...interface{}) { |
|||
if strings.Contains(l.Levels, "Info") { |
|||
logrusB.SetOutput(l.Output) |
|||
logrusB.SetFormatter(&logrus.JSONFormatter{}) |
|||
|
|||
logrusB.SetLevel(logrus.InfoLevel) |
|||
|
|||
logrusB.WithFields(logrus.Fields{ |
|||
"name": l.Name, |
|||
"uid": l.UID, |
|||
"srv": l.Service, |
|||
"config": l.Config, |
|||
}).Info(args...) |
|||
if strings.Contains(l.Levels, "Stdout") { |
|||
fmt.Printf("Info: %+v\n", args) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (l *log) Warning(args ...interface{}) { |
|||
if strings.Contains(l.Levels, "Warning") { |
|||
logrusB.SetOutput(l.Output) |
|||
logrusB.SetFormatter(&logrus.JSONFormatter{}) |
|||
logrusB.SetLevel(logrus.WarnLevel) |
|||
|
|||
logrusB.WithFields(logrus.Fields{ |
|||
"name": l.Name, |
|||
"uid": l.UID, |
|||
"srv": l.Service, |
|||
"config": l.Config, |
|||
}).Warn(args...) |
|||
if strings.Contains(l.Levels, "Stdout") { |
|||
fmt.Printf("Warn: %+v\n", args) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (l *log) Error(err error, args ...interface{}) { |
|||
if err != nil { |
|||
if args != nil { |
|||
args = append(args, "; error:", err) |
|||
} else { |
|||
args = append(args, "error:", err) |
|||
} |
|||
} |
|||
if strings.Contains(l.Levels, "Error") { |
|||
logrusB.SetOutput(l.Output) |
|||
logrusB.SetFormatter(&logrus.JSONFormatter{}) |
|||
logrusB.SetLevel(logrus.ErrorLevel) |
|||
|
|||
logrusB.WithFields(logrus.Fields{ |
|||
"name": l.Name, |
|||
"uid": l.UID, |
|||
"srv": l.Service, |
|||
"config": l.Config, |
|||
}).Error(args...) |
|||
if strings.Contains(l.Levels, "Stdout") { |
|||
fmt.Printf("Error: %+v\n", args) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (l *log) Panic(err error, args ...interface{}) { |
|||
if err != nil { |
|||
if args != nil { |
|||
args = append(args, "; error:", err) |
|||
} else { |
|||
args = append(args, "error:", err) |
|||
} |
|||
} |
|||
if strings.Contains(l.Levels, "Panic") { |
|||
if strings.Contains(l.Levels, "Stdout") { |
|||
fmt.Printf("Panic: %+v\n", args) |
|||
} |
|||
|
|||
logrusB.SetOutput(l.Output) |
|||
logrusB.SetFormatter(&logrus.JSONFormatter{}) |
|||
logrusB.SetLevel(logrus.PanicLevel) |
|||
logrusB.WithFields(logrus.Fields{ |
|||
"name": l.Name, |
|||
"uid": l.UID, |
|||
"srv": l.Service, |
|||
"config": l.Config, |
|||
}).Panic(args...) |
|||
} |
|||
} |
|||
|
|||
// Exit внутренняя ф-ция логирования и прекращения работы программы
|
|||
func (l *log) Exit(err error, args ...interface{}) { |
|||
if err != nil { |
|||
if args != nil { |
|||
args = append(args, "; error:", err) |
|||
} else { |
|||
args = append(args, "error:", err) |
|||
} |
|||
} |
|||
if strings.Contains(l.Levels, "Fatal") { |
|||
if strings.Contains(l.Levels, "Stdout") { |
|||
fmt.Printf("Exit: %+v\n", args) |
|||
} |
|||
|
|||
logrusB.SetOutput(l.Output) |
|||
logrusB.SetFormatter(&logrus.JSONFormatter{}) |
|||
logrusB.SetLevel(logrus.FatalLevel) |
|||
logrusB.WithFields(logrus.Fields{ |
|||
"name": l.Name, |
|||
"uid": l.UID, |
|||
"srv": l.Service, |
|||
"config": l.Config, |
|||
}).Fatal(args...) |
|||
} |
|||
} |
|||
|
|||
func (l *log) Close() { |
|||
l.File.Close() |
|||
} |
|||
|
|||
func NewLogger(ctx context.Context, cfg ConfigLogger) (logger Log, initType string, err error) { |
|||
var errI error |
|||
err = fmt.Errorf("logger init") |
|||
|
|||
for _, v := range cfg.Priority { |
|||
|
|||
if v == "file" && err != nil { |
|||
// если путь указан относительно / значит задан абсолютный путь, иначе в директории
|
|||
if cfg.File.Dir[:1] != sep { |
|||
rootDir, _ := lib.RootDir() |
|||
cfg.File.Dir = rootDir + sep + "logs" + sep + cfg.File.Dir |
|||
} |
|||
|
|||
// инициализировать лог и его ротацию
|
|||
logger, errI = NewFileLogger(ctx, cfg) |
|||
if errI != nil { |
|||
err = fmt.Errorf("%s %s failed init files-logger, (err: %s)", err, "→", errI) |
|||
fmt.Println(err, cfg) |
|||
} else { |
|||
initType = v |
|||
err = nil |
|||
} |
|||
} |
|||
|
|||
if v == "vfs" && err != nil { |
|||
// инициализировать лог и его ротацию
|
|||
vs := strings.Split(cfg.Vfs.Dir, sep) // берем только последнее значение в пути для vfs-логера
|
|||
vs = vs[len(vs)-1:] |
|||
if len(vs) != 0 { |
|||
cfg.Vfs.Dir = "logs" |
|||
} |
|||
|
|||
// инициализировать лог и его ротацию
|
|||
logger, errI = NewVfsLogger(ctx, cfg) |
|||
fmt.Println(logger, errI) |
|||
if errI != nil { |
|||
err = fmt.Errorf("%s %s failed init files-vfs, (err: %s)", err, "→", errI) |
|||
fmt.Println(err, cfg) |
|||
} else { |
|||
initType = v |
|||
err = nil |
|||
} |
|||
} |
|||
|
|||
//if v == "logbox" && err != nil {
|
|||
// // инициализировать лог и его ротацию
|
|||
// logger, errI = NewLogboxLogger(ctx, cfg)
|
|||
// if errI != nil {
|
|||
// err = fmt.Errorf("%s %s failed init files-logbox, (err: %s)", err, "→", errI)
|
|||
// } else {
|
|||
// initType = v
|
|||
// err = nil
|
|||
// }
|
|||
//}
|
|||
|
|||
} |
|||
|
|||
return logger, initType, err |
|||
} |
@ -1,196 +1,199 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
"io" |
|||
"os" |
|||
"runtime/debug" |
|||
"strconv" |
|||
"strings" |
|||
"sync" |
|||
"time" |
|||
|
|||
"git.lowcodeplatform.net/fabric/lib" |
|||
"github.com/sirupsen/logrus" |
|||
) |
|||
|
|||
type ConfigFileLogger struct { |
|||
Dir string |
|||
IntervalReload, IntervalClearFiles time.Duration |
|||
PeriodSaveFiles string |
|||
} |
|||
|
|||
// вспомогательная фукнция очистки старых файлов для файлового логера
|
|||
func (l *log) fileLoggerClearing(ctx context.Context) { |
|||
|
|||
// попытка очистки старых файлов (каждые пол часа)
|
|||
go func() { |
|||
ticker := time.NewTicker(l.IntervalClearFiles) |
|||
defer ticker.Stop() |
|||
|
|||
// получаем период, через который мы будем удалять файлы
|
|||
period := l.PeriodSaveFiles |
|||
if period == "" { |
|||
l.Error(fmt.Errorf("%s", "Fail perion save log files. (expected format: year-month-day; eg: 0-1-0)")) |
|||
return |
|||
} |
|||
slPeriod := strings.Split(period, "-") |
|||
if len(slPeriod) < 3 { |
|||
l.Error(fmt.Errorf("%s", "Fail perion save log files. (expected format: year-month-day; eg: 0-1-0)")) |
|||
return |
|||
} |
|||
|
|||
// получаем числовые значения года месяца и дня для расчета даты удаления файлов
|
|||
year, err := strconv.Atoi(slPeriod[0]) |
|||
if err != nil { |
|||
l.Error(err, "Fail converted Year from period saved log files. (expected format: year-month-day; eg: 0-1-0)") |
|||
} |
|||
month, err := strconv.Atoi(slPeriod[1]) |
|||
if err != nil { |
|||
l.Error(err, "Fail converted Month from period saved log files. (expected format: year-month-day; eg: 0-1-0)") |
|||
} |
|||
day, err := strconv.Atoi(slPeriod[2]) |
|||
if err != nil { |
|||
l.Error(err, "Fail converted Day from period saved log files. (expected format: year-month-day; eg: 0-1-0)") |
|||
} |
|||
|
|||
for { |
|||
select { |
|||
case <-ctx.Done(): |
|||
return |
|||
case <-ticker.C: |
|||
oneMonthAgo := time.Now().AddDate(-year, -month, -day) // minus 1 месяц
|
|||
fileMonthAgoDate := oneMonthAgo.Format("2006.01.02") |
|||
|
|||
// пробегаем директорию и читаем все файлы, если имя меньше текущее время - месяц = удаляем
|
|||
directory, _ := os.Open(l.Dir) |
|||
objects, err := directory.Readdir(-1) |
|||
if err != nil { |
|||
l.Error(err, "Error read directory: ", directory) |
|||
return |
|||
} |
|||
|
|||
for _, obj := range objects { |
|||
filename := obj.Name() |
|||
filenameMonthAgoDate := fileMonthAgoDate + "_" + l.Service |
|||
|
|||
if filenameMonthAgoDate > filename { |
|||
pathFile := l.Dir + sep + filename |
|||
err = os.Remove(pathFile) |
|||
if err != nil { |
|||
l.Error(err, "Error deleted file: ", pathFile) |
|||
return |
|||
} |
|||
} |
|||
} |
|||
ticker = time.NewTicker(l.IntervalClearFiles) |
|||
} |
|||
} |
|||
}() |
|||
} |
|||
|
|||
// NewFileLogger инициируем логер, которых хранит логи в файлах по указанному пути
|
|||
func NewFileLogger(ctx context.Context, cfg ConfigLogger) (Log, error) { |
|||
var output io.Writer |
|||
var file *os.File |
|||
var err error |
|||
var mode os.FileMode |
|||
m := sync.Mutex{} |
|||
|
|||
l := &log{ |
|||
Output: output, |
|||
Levels: cfg.Level, |
|||
UID: cfg.Uid, |
|||
Name: cfg.Name, |
|||
Service: cfg.Srv, |
|||
Config: cfg.Config, |
|||
Dir: cfg.File.Dir, |
|||
IntervalReload: cfg.File.IntervalReload, |
|||
IntervalClearFiles: cfg.File.IntervalClearFiles, |
|||
PeriodSaveFiles: cfg.File.PeriodSaveFiles, |
|||
mux: &m, |
|||
File: file, |
|||
} |
|||
|
|||
datefile := time.Now().Format("2006.01.02") |
|||
logName := datefile + "_" + cfg.Srv + "_" + cfg.Uid + ".log" |
|||
|
|||
fmt.Println(logName) |
|||
|
|||
// создаем/открываем файл логирования и назначаем его логеру
|
|||
mode = 0711 |
|||
err = lib.CreateDir(cfg.File.Dir, mode) |
|||
if err != nil { |
|||
logrus.Error(err, "Error creating directory") |
|||
return nil, err |
|||
} |
|||
|
|||
pathFile := cfg.File.Dir + "/" + logName |
|||
if !lib.IsExist(pathFile) { |
|||
err = lib.CreateFile(pathFile) |
|||
if err != nil { |
|||
logrus.Error(err, "Error creating file") |
|||
return nil, err |
|||
} |
|||
} |
|||
|
|||
file, err = os.OpenFile(pathFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) |
|||
defer file.Close() |
|||
|
|||
l.File = file |
|||
l.Output = file |
|||
if err != nil { |
|||
logrus.Panic(err, "error opening file") |
|||
return nil, err |
|||
} |
|||
|
|||
defer func() { |
|||
rec := recover() |
|||
if rec != nil { |
|||
b := string(debug.Stack()) |
|||
fmt.Printf("panic in loggier (RotateInit). stack: %+v", b) |
|||
//cancel()
|
|||
//os.Exit(1)
|
|||
} |
|||
}() |
|||
|
|||
// попытка обновить файл (раз в 10 минут)
|
|||
go func() { |
|||
ticker := time.NewTicker(l.IntervalReload) |
|||
defer ticker.Stop() |
|||
|
|||
for { |
|||
select { |
|||
case <-ctx.Done(): |
|||
return |
|||
case <-ticker.C: |
|||
l.File.Close() // закрыл старый файл
|
|||
datefile = time.Now().Format("2006.01.02") |
|||
logName = datefile + "_" + cfg.Srv + "_" + cfg.Uid + ".log" |
|||
pathFile = cfg.File.Dir + "/" + logName |
|||
if !lib.IsExist(pathFile) { |
|||
err := lib.CreateFile(pathFile) |
|||
if err != nil { |
|||
logrus.Error(err, "Error creating file") |
|||
return |
|||
} |
|||
} |
|||
|
|||
file, err = os.OpenFile(pathFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) |
|||
if err != nil { |
|||
logrus.Panic(err, "error opening file") |
|||
return |
|||
} |
|||
|
|||
output = file |
|||
l.Output = output |
|||
l.File = file |
|||
ticker = time.NewTicker(l.IntervalReload) |
|||
} |
|||
} |
|||
}() |
|||
l.fileLoggerClearing(ctx) |
|||
|
|||
return l, err |
|||
} |
|||
//
|
|||
//import (
|
|||
// "context"
|
|||
// "fmt"
|
|||
// "io"
|
|||
// "os"
|
|||
// "runtime/debug"
|
|||
// "strconv"
|
|||
// "strings"
|
|||
// "sync"
|
|||
// "time"
|
|||
//
|
|||
// "git.lowcodeplatform.net/fabric/lib"
|
|||
// "github.com/sirupsen/logrus"
|
|||
//)
|
|||
//
|
|||
//const sep = string(os.PathSeparator)
|
|||
//
|
|||
//type ConfigFileLogger struct {
|
|||
// Dir string
|
|||
// IntervalReload, IntervalClearFiles time.Duration
|
|||
// PeriodSaveFiles string
|
|||
//}
|
|||
//
|
|||
//// вспомогательная фукнция очистки старых файлов для файлового логера
|
|||
//func (l *log) fileLoggerClearing(ctx context.Context) {
|
|||
//
|
|||
// // попытка очистки старых файлов (каждые пол часа)
|
|||
// go func() {
|
|||
// ticker := time.NewTicker(l.IntervalClearFiles)
|
|||
// defer ticker.Stop()
|
|||
//
|
|||
// // получаем период, через который мы будем удалять файлы
|
|||
// period := l.PeriodSaveFiles
|
|||
// if period == "" {
|
|||
// l.Error(fmt.Errorf("%s", "Fail perion save log files. (expected format: year-month-day; eg: 0-1-0)"))
|
|||
// return
|
|||
// }
|
|||
// slPeriod := strings.Split(period, "-")
|
|||
// if len(slPeriod) < 3 {
|
|||
// l.Error(fmt.Errorf("%s", "Fail perion save log files. (expected format: year-month-day; eg: 0-1-0)"))
|
|||
// return
|
|||
// }
|
|||
//
|
|||
// // получаем числовые значения года месяца и дня для расчета даты удаления файлов
|
|||
// year, err := strconv.Atoi(slPeriod[0])
|
|||
// if err != nil {
|
|||
// l.Error(err, "Fail converted Year from period saved log files. (expected format: year-month-day; eg: 0-1-0)")
|
|||
// }
|
|||
// month, err := strconv.Atoi(slPeriod[1])
|
|||
// if err != nil {
|
|||
// l.Error(err, "Fail converted Month from period saved log files. (expected format: year-month-day; eg: 0-1-0)")
|
|||
// }
|
|||
// day, err := strconv.Atoi(slPeriod[2])
|
|||
// if err != nil {
|
|||
// l.Error(err, "Fail converted Day from period saved log files. (expected format: year-month-day; eg: 0-1-0)")
|
|||
// }
|
|||
//
|
|||
// for {
|
|||
// select {
|
|||
// case <-ctx.Done():
|
|||
// return
|
|||
// case <-ticker.C:
|
|||
// oneMonthAgo := time.Now().AddDate(-year, -month, -day) // minus 1 месяц
|
|||
// fileMonthAgoDate := oneMonthAgo.Format("2006.01.02")
|
|||
//
|
|||
// // пробегаем директорию и читаем все файлы, если имя меньше текущее время - месяц = удаляем
|
|||
// directory, _ := os.Open(l.Dir)
|
|||
// objects, err := directory.Readdir(-1)
|
|||
// if err != nil {
|
|||
// l.Error(err, "Error read directory: ", directory)
|
|||
// return
|
|||
// }
|
|||
//
|
|||
// for _, obj := range objects {
|
|||
// filename := obj.Name()
|
|||
// filenameMonthAgoDate := fileMonthAgoDate + "_" + l.Service
|
|||
//
|
|||
// if filenameMonthAgoDate > filename {
|
|||
// pathFile := l.Dir + sep + filename
|
|||
// err = os.Remove(pathFile)
|
|||
// if err != nil {
|
|||
// l.Error(err, "Error deleted file: ", pathFile)
|
|||
// return
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
// ticker = time.NewTicker(l.IntervalClearFiles)
|
|||
// }
|
|||
// }
|
|||
// }()
|
|||
//}
|
|||
//
|
|||
//// NewFileLogger инициируем логер, которых хранит логи в файлах по указанному пути
|
|||
//func NewFileLogger(ctx context.Context, cfg ConfigLogger) (Log, error) {
|
|||
// var output io.Writer
|
|||
// var file *os.File
|
|||
// var err error
|
|||
// var mode os.FileMode
|
|||
// m := sync.Mutex{}
|
|||
//
|
|||
// l := &log{
|
|||
// Output: output,
|
|||
// Levels: cfg.Level,
|
|||
// UID: cfg.Uid,
|
|||
// Name: cfg.Name,
|
|||
// Service: cfg.Srv,
|
|||
// Config: cfg.Config,
|
|||
// Dir: cfg.File.Dir,
|
|||
// IntervalReload: cfg.File.IntervalReload,
|
|||
// IntervalClearFiles: cfg.File.IntervalClearFiles,
|
|||
// PeriodSaveFiles: cfg.File.PeriodSaveFiles,
|
|||
// mux: &m,
|
|||
// File: file,
|
|||
// }
|
|||
//
|
|||
// datefile := time.Now().Format("2006.01.02")
|
|||
// logName := datefile + "_" + cfg.Srv + "_" + cfg.Uid + ".log"
|
|||
//
|
|||
// fmt.Println(logName)
|
|||
//
|
|||
// // создаем/открываем файл логирования и назначаем его логеру
|
|||
// mode = 0711
|
|||
// err = lib.CreateDir(cfg.File.Dir, mode)
|
|||
// if err != nil {
|
|||
// logrus.Error(err, "Error creating directory")
|
|||
// return nil, err
|
|||
// }
|
|||
//
|
|||
// pathFile := cfg.File.Dir + "/" + logName
|
|||
// if !lib.IsExist(pathFile) {
|
|||
// err = lib.CreateFile(pathFile)
|
|||
// if err != nil {
|
|||
// logrus.Error(err, "Error creating file")
|
|||
// return nil, err
|
|||
// }
|
|||
// }
|
|||
//
|
|||
// file, err = os.OpenFile(pathFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
|||
// defer file.Close()
|
|||
//
|
|||
// l.File = file
|
|||
// l.Output = file
|
|||
// if err != nil {
|
|||
// logrus.Panic(err, "error opening file")
|
|||
// return nil, err
|
|||
// }
|
|||
//
|
|||
// defer func() {
|
|||
// rec := recover()
|
|||
// if rec != nil {
|
|||
// b := string(debug.Stack())
|
|||
// fmt.Printf("panic in loggier (RotateInit). stack: %+v", b)
|
|||
// //cancel()
|
|||
// //os.Exit(1)
|
|||
// }
|
|||
// }()
|
|||
//
|
|||
// // попытка обновить файл (раз в 10 минут)
|
|||
// go func() {
|
|||
// ticker := time.NewTicker(l.IntervalReload)
|
|||
// defer ticker.Stop()
|
|||
//
|
|||
// for {
|
|||
// select {
|
|||
// case <-ctx.Done():
|
|||
// return
|
|||
// case <-ticker.C:
|
|||
// l.File.Close() // закрыл старый файл
|
|||
// datefile = time.Now().Format("2006.01.02")
|
|||
// logName = datefile + "_" + cfg.Srv + "_" + cfg.Uid + ".log"
|
|||
// pathFile = cfg.File.Dir + "/" + logName
|
|||
// if !lib.IsExist(pathFile) {
|
|||
// err := lib.CreateFile(pathFile)
|
|||
// if err != nil {
|
|||
// logrus.Error(err, "Error creating file")
|
|||
// return
|
|||
// }
|
|||
// }
|
|||
//
|
|||
// file, err = os.OpenFile(pathFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
|||
// if err != nil {
|
|||
// logrus.Panic(err, "error opening file")
|
|||
// return
|
|||
// }
|
|||
//
|
|||
// output = file
|
|||
// l.Output = output
|
|||
// l.File = file
|
|||
// ticker = time.NewTicker(l.IntervalReload)
|
|||
// }
|
|||
// }
|
|||
// }()
|
|||
// l.fileLoggerClearing(ctx)
|
|||
//
|
|||
// return l, err
|
|||
//}
|
|||
|
@ -0,0 +1,7 @@ |
|||
package logger |
|||
|
|||
//goland:noinspection GoUnusedExportedFunction
|
|||
func SetupDefaultLogger(namespace string, options ...ConfigOption) { |
|||
logger := initLogger(options...) |
|||
defaultLogger = New(logger.Named(namespace)) |
|||
} |
@ -1,98 +1,99 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"bytes" |
|||
"context" |
|||
"io" |
|||
"sync" |
|||
"time" |
|||
|
|||
"git.lowcodeplatform.net/fabric/lib" |
|||
) |
|||
|
|||
type ConfigVfsLogger struct { |
|||
Kind, Endpoint, AccessKeyID, SecretKey, Region, Bucket, Comma, CACert string |
|||
Dir string |
|||
IntervalReload time.Duration |
|||
} |
|||
|
|||
// NewVfsLogger инициализация отправки логов на сервер сбора
|
|||
// ВНИМАНИЕ! крайне неэффективно
|
|||
// при добавлении лога выкачивется весь файл лога, добавляется строка и перезаписывается
|
|||
func NewVfsLogger(ctx context.Context, cfg ConfigLogger) (logger Log, err error) { |
|||
var output io.Writer |
|||
m := sync.Mutex{} |
|||
|
|||
vfs := lib.NewVfs(cfg.Vfs.Kind, cfg.Vfs.Endpoint, cfg.Vfs.AccessKeyID, cfg.Vfs.SecretKey, cfg.Vfs.Region, cfg.Vfs.Bucket, cfg.Vfs.Comma, cfg.Vfs.CACert) |
|||
err = vfs.Connect() |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
sender := newVfsSender(ctx, vfs, cfg.Vfs.Dir, cfg.Srv, cfg.Uid, cfg.Vfs.IntervalReload) |
|||
output = sender |
|||
|
|||
l := &log{ |
|||
Output: output, |
|||
Levels: cfg.Level, |
|||
UID: cfg.Uid, |
|||
Name: cfg.Name, |
|||
Service: cfg.Srv, |
|||
IntervalReload: cfg.Vfs.IntervalReload, |
|||
mux: &m, |
|||
} |
|||
|
|||
return l, nil |
|||
} |
|||
|
|||
type vfsSender struct { |
|||
vfsStorage lib.Vfs |
|||
file string |
|||
} |
|||
|
|||
func (v *vfsSender) Write(p []byte) (n int, err error) { |
|||
dataFile, _, err := v.vfsStorage.Read(v.file) |
|||
concatSlices := [][]byte{ |
|||
dataFile, |
|||
p, |
|||
} |
|||
resultSlice := bytes.Join(concatSlices, []byte("")) |
|||
|
|||
err = v.vfsStorage.Write(v.file, resultSlice) |
|||
if err != nil { |
|||
return 0, err |
|||
} |
|||
return len(p), nil |
|||
} |
|||
|
|||
func newVfsSender(ctx context.Context, vfsStorage lib.Vfs, dir, srv, uid string, intervalReload time.Duration) io.Writer { |
|||
|
|||
sender := &vfsSender{ |
|||
vfsStorage, |
|||
"", |
|||
} |
|||
|
|||
//datefile := time.Now().Format("2006.01.02")
|
|||
datefile := time.Now().Format("2006.01.02") |
|||
sender.file = "/" + dir + "/" + datefile + "_" + srv + "_" + uid + ".log" |
|||
|
|||
// попытка обновить файл (раз в 10 минут)
|
|||
go func() { |
|||
ticker := time.NewTicker(intervalReload) |
|||
defer ticker.Stop() |
|||
|
|||
for { |
|||
select { |
|||
case <-ctx.Done(): |
|||
return |
|||
case <-ticker.C: |
|||
datefile = time.Now().Format("2006.01.02") |
|||
|
|||
sender.file = "/" + dir + "/" + datefile + "_" + srv + "_" + uid + ".log" |
|||
ticker = time.NewTicker(intervalReload) |
|||
} |
|||
} |
|||
}() |
|||
|
|||
return sender |
|||
} |
|||
//
|
|||
//import (
|
|||
// "bytes"
|
|||
// "context"
|
|||
// "io"
|
|||
// "sync"
|
|||
// "time"
|
|||
//
|
|||
// "git.lowcodeplatform.net/fabric/lib"
|
|||
//)
|
|||
//
|
|||
//type ConfigVfsLogger struct {
|
|||
// Kind, Endpoint, AccessKeyID, SecretKey, Region, Bucket, Comma, CACert string
|
|||
// Dir string
|
|||
// IntervalReload time.Duration
|
|||
//}
|
|||
//
|
|||
//// NewVfsLogger инициализация отправки логов на сервер сбора
|
|||
//// ВНИМАНИЕ! крайне неэффективно
|
|||
//// при добавлении лога выкачивется весь файл лога, добавляется строка и перезаписывается
|
|||
//func NewVfsLogger(ctx context.Context, cfg ConfigVfsLogger) (logger Log, err error) {
|
|||
// var output io.Writer
|
|||
// m := sync.Mutex{}
|
|||
//
|
|||
// vfs := lib.NewVfs(cfg.Vfs.Kind, cfg.Vfs.Endpoint, cfg.Vfs.AccessKeyID, cfg.Vfs.SecretKey, cfg.Vfs.Region, cfg.Vfs.Bucket, cfg.Vfs.Comma, cfg.Vfs.CACert)
|
|||
// err = vfs.Connect()
|
|||
// if err != nil {
|
|||
// return nil, err
|
|||
// }
|
|||
//
|
|||
// sender := newVfsSender(ctx, vfs, cfg.Vfs.Dir, cfg.Srv, cfg.Uid, cfg.Vfs.IntervalReload)
|
|||
// output = sender
|
|||
//
|
|||
// l := &log{
|
|||
// Output: output,
|
|||
// Levels: cfg.Level,
|
|||
// UID: cfg.Uid,
|
|||
// Name: cfg.Name,
|
|||
// Service: cfg.Srv,
|
|||
// IntervalReload: cfg.Vfs.IntervalReload,
|
|||
// mux: &m,
|
|||
// }
|
|||
//
|
|||
// return l, nil
|
|||
//}
|
|||
//
|
|||
//type vfsSender struct {
|
|||
// vfsStorage lib.Vfs
|
|||
// file string
|
|||
//}
|
|||
//
|
|||
//func (v *vfsSender) Write(p []byte) (n int, err error) {
|
|||
// dataFile, _, err := v.vfsStorage.Read(v.file)
|
|||
// concatSlices := [][]byte{
|
|||
// dataFile,
|
|||
// p,
|
|||
// }
|
|||
// resultSlice := bytes.Join(concatSlices, []byte(""))
|
|||
//
|
|||
// err = v.vfsStorage.Write(v.file, resultSlice)
|
|||
// if err != nil {
|
|||
// return 0, err
|
|||
// }
|
|||
// return len(p), nil
|
|||
//}
|
|||
//
|
|||
//func newVfsSender(ctx context.Context, vfsStorage lib.Vfs, dir, srv, uid string, intervalReload time.Duration) io.Writer {
|
|||
//
|
|||
// sender := &vfsSender{
|
|||
// vfsStorage,
|
|||
// "",
|
|||
// }
|
|||
//
|
|||
// //datefile := time.Now().Format("2006.01.02")
|
|||
// datefile := time.Now().Format("2006.01.02")
|
|||
// sender.file = "/" + dir + "/" + datefile + "_" + srv + "_" + uid + ".log"
|
|||
//
|
|||
// // попытка обновить файл (раз в 10 минут)
|
|||
// go func() {
|
|||
// ticker := time.NewTicker(intervalReload)
|
|||
// defer ticker.Stop()
|
|||
//
|
|||
// for {
|
|||
// select {
|
|||
// case <-ctx.Done():
|
|||
// return
|
|||
// case <-ticker.C:
|
|||
// datefile = time.Now().Format("2006.01.02")
|
|||
//
|
|||
// sender.file = "/" + dir + "/" + datefile + "_" + srv + "_" + uid + ".log"
|
|||
// ticker = time.NewTicker(intervalReload)
|
|||
// }
|
|||
// }
|
|||
// }()
|
|||
//
|
|||
// return sender
|
|||
//}
|
|||
|
Loading…
Reference in new issue