diff --git a/README.md b/README.md index b3094d6..9d851e8 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,8 @@ Usage of /tmp/go-build847101717/b001/exe/log-processor: Задержка чтения входного файла. Разрешены обозначения 'ns', 'us' ('µs'), 'ms', 's', 'm','h') (default "5ms") -tz-offset string Сдвиг по времени от UTC (default "+03:00") + -worklog-out string + Направление вывода журнала работы программы (console, file) (default "file") -write-out-file Запись обработанных данных в файл ``` diff --git a/log-processor.go b/log-processor.go index e2eab69..c75092f 100644 --- a/log-processor.go +++ b/log-processor.go @@ -3,8 +3,7 @@ // Версия: 1.0.0 // Автор: Сергей Калинин svk@nuk-svk.ru https://git.nuk-svk.ru/svk/ // ---------------------------------------------------------------------- -// Лицензия: GPL(v3) -//------------------------- ------------------------------------------------ + package main import ( @@ -16,11 +15,11 @@ import ( "time" "io" // "runtime" - "path/filepath" + "path/filepath" "regexp" "strings" "strconv" - "encoding/json" + "encoding/json" // "github.com/hpcloud/tail" "net" "sort" @@ -66,6 +65,8 @@ var ( TailSleep time.Duration RunAsWinService bool ExcludeEvent []string + InFile string + WorkLogOut string ) type Config struct { @@ -332,6 +333,7 @@ func getNewFilesFromDir(filesList []string, dir string) []string { // from the input buffered reader. // An error is returned iff there is an error with the // buffered reader. + func Readln(r *bufio.Reader) (string, error) { var (isPrefix bool = true err error = nil @@ -344,6 +346,13 @@ func Readln(r *bufio.Reader) (string, error) { return string(ln),err } +// func Readln(r *bufio.Reader) (string, error){ + // result, err := r.ReadString('\n') + // // log.Println(result) + // ln := result + // return ln, err +// } + func hex2int(hexStr string) int { // base 16 for hexadecimal result, err := strconv.ParseInt(hexStr, 16, 64) @@ -698,9 +707,9 @@ func parseString (outLine string, logOffset int64) map[string]string { regexpLogRecord := regexp.MustCompile(`(?P\d{14}),(?P\w{1}),\{(?P\w+),(?P\w+)\},(?P\d+),(?P\d+),(?P\d+),(?P\d+),(?P\d+),(?P\w{1}),\"(?P.*)\",(?P\d+),\{(?P.+)\},\"(?P.*)\",(?P\d+),(?P\d+),(?P\d+),(?P\d+),(?P\d{1}),\{(\d|,)+\}$`) // Полную строку прогоняем через регексп и распихиваем сразу по полям matchedOut := regexpLogRecord.MatchString(outLine) - if Debug { - log.Println(outLine) - } + // if Debug { + // log.Println(outLine) + // } if matchedOut { findedData := regexpLogRecord.FindStringSubmatch(outLine) if findedData != nil { @@ -811,12 +820,18 @@ func implContains(sl []string, name string) bool { // Запуск чтения файлов func runOperations () { + var client *opensearch.Client + + if InFile != "" { + tail(client, InFile, os.Stdout) + return + } + // получаем список файлов на момент запуска filesList := getDirectoryContents(DirIn) // получаем последний модифицированный файл lastModifyFiles := getLastModifyFile(DirIn) - var client *opensearch.Client log.Println("Список новых файлов:", lastModifyFiles, len(lastModifyFiles)) // запускаем процесс обработки if len(lastModifyFiles) == 0 { @@ -876,6 +891,7 @@ func tail(client *opensearch.Client, fileName string, out io.Writer) { // bulkCount int // arrRecords []map[string]string fOut *os.File + // matchedEnd bool ) // bulkCount = 0 @@ -924,9 +940,11 @@ func tail(client *opensearch.Client, fileName string, out io.Writer) { } oldSize := info.Size() + + // Регулярные выражения для определения начала и конца записи regexpBeginRecord := regexp.MustCompile(`^\{\d{14},\w{1},$`) regexpEndRecord := regexp.MustCompile(`^\},$`) - // var ( + // var (й // isPrefix bool = true // // err error = nil // line []byte @@ -947,18 +965,20 @@ func tail(client *opensearch.Client, fileName string, out io.Writer) { matchedBegin := regexpBeginRecord.MatchString(l) if matchedBegin { recBegin = true + outLine = "" } if recBegin { outLine = outLine + l - // outLine = outLine + strings.TrimSpace(l) } // Находим конец записи matchedEnd := regexpEndRecord.MatchString(l) - // fmt.Println(recBegin, matchedEnd) - // fmt.Println(outLine) + if matchedEnd { recBegin = false outLine = strings.TrimSuffix(strings.TrimLeft(outLine, "{,"), "},") + if Debug { + log.Println(outLine) + } // Парсим подготовленную строку result := parseString(outLine, logOffset) if Debug { @@ -1012,6 +1032,12 @@ func tail(client *opensearch.Client, fileName string, out io.Writer) { log.Println("Ошибка определения позиции 'pos, err := f.Seek(0, io.SeekCurrent)' в файле", fileName, "error:", err) // panic(err) } + // Если задан файл с коммандной строки то выходим + if InFile != "" { + return + } + + // Запускаем чтение каталога и получепние списка с новыми файлами for { time.Sleep(time.Second) newinfo, err := f.Stat() @@ -1302,11 +1328,11 @@ func main() { flag.StringVar(&DirCfg, "dir-config", ".config", "Каталог для файлов настройки (DIR_CFG)") flag.StringVar(&FileCfg, "config", "config.ini", "Файл настроек") flag.BoolVar(&CreateFileCfg, "create-config", false, "Создать файл настроек") - flag.BoolVar(&Debug, "debug", false, "Выводить данные в консоль") + flag.BoolVar(&Debug, "debug", false, "Выводить отладочную информацию") flag.StringVar(&DirIn, "dir-in", "in", "Каталог для исходных файлов (DIR_IN)") flag.StringVar(&DirOut, "dir-out", "out", "Каталог для обработанных файлов (DIR_OUT)") flag.StringVar(&DirTemp, "dir-temp", "tmp", "Каталог для временных файлов (TEMP)") - flag.StringVar(&DirLog, "dir-log", "log", "Каталог для лога работы (DIR_LOG)") + flag.StringVar(&DirLog, "dir-worklog", "log", "Каталог для лога работы (DIR_LOG)") flag.StringVar(&DictFile, "dict-file", "1Cv8.lgf", "Файл со словарём (DICT_FILE)") flag.BoolVar(&SendToEs, "es-send", false, "Отправлять данные в ElasticSearch") flag.StringVar(&EsUrl, "es-url", "", "Адрес узла Elastic Search (ELASTICSEARCH_URL)") @@ -1323,7 +1349,8 @@ func main() { flag.StringVar(&ObjectTypes, "object-types", "1,2,3,4,5,6,7,8", "Список типов объектов словаря для выборки, разделённый запятой (OBJECT_TYPES)") flag.StringVar(&TimeZoneOffset, "tz-offset", "+03:00", "Сдвиг по времени от UTC") flag.StringVar(&Duration, "tail-sleep", "5ms", "Задержка чтения входного файла. Разрешены обозначения 'ns', 'us' ('µs'), 'ms', 's', 'm','h')") - // flag.StringVar(&ExcludeEvent, "exclude-event", "", "Список событий исключенных из выдачи разделенных ';'") + flag.StringVar(&InFile, "file", "", "Имя файла для обработки. Если требуется обработать один файл") + flag.StringVar(&WorkLogOut, "worklog-out", "file", "Направление вывода журнала работы программы (console, file)") flag.Parse() @@ -1407,17 +1434,26 @@ func main() { createWorkDir() - // Установка и открытие лога для порграммы - fLog, err := os.OpenFile(filepath.Join(DirLog, "1c-log-processor.log"), os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) - if err != nil { - fmt.Printf("error opening log file: %v", err) - } - defer fLog.Close() - if Debug { - log.SetOutput(os.Stdout) - } else { - log.SetOutput(fLog) + // Определим куда выводим лог работы + switch WorkLogOut { + case "file": + // Установка и открытие лога для программы + fLog, err := os.OpenFile(filepath.Join(DirLog, "1c-log-processor.log"), os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) + if err != nil { + fmt.Printf("error opening log file: %v", err) + } + defer fLog.Close() + log.SetOutput(fLog) + case "console": + log.SetOutput(os.Stdout) } + // if Debug { + // log.SetOutput(os.Stdout) + // } else { + // log.SetOutput(fLog) + // } + // log.SetOutput(fLog) + // readDictFile(dictFile) DictObjects = readDictFile(DictFile)