/
utils.go
117 lines (103 loc) · 2.89 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package common
import (
"bufio"
"encoding/json"
"os"
"strings"
"time"
"github.com/BitTraceProject/BitTrace-Types/pkg/constants"
"github.com/BitTraceProject/BitTrace-Types/pkg/errorx"
)
func ExecuteFunctionByRetry(f func() error) error {
var err error
for i := 0; i < constants.DEFAULT_RETRY_COUNT; i++ {
err = f()
if err == nil {
return nil
}
}
return err
}
// ScanFileLines 从 startN 处开始,scan 数据到达文件结尾,返回数据数组,eof 和 error,
// eof 判断是按照自定义的一行来判断的,注意这里潜在的问题是 logger 与 exporter 读写竞争可能导致日志输出到错误的 day,
// 所以在 resolver 处理时,只依赖数据本身,不依赖 logger 的信息,logger 和 exporter 只需要保证不丢数据就行
func ScanFileLines(filePath string, startN int64) ([][]byte, bool, error) {
f, err := os.OpenFile(filePath, os.O_RDWR, 0644)
if err != nil {
return nil, false, err
}
defer f.Close()
r := bufio.NewReader(f)
//s := bufio.NewScanner(f)
for i := int64(0); i < startN; i++ {
line, err := r.ReadBytes('\n')
if err != nil {
return nil, false, nil
}
// 当前 n 处还没有数据,但是已经 eof 了
if strings.Contains(string(line[:len(line)-1]), constants.LOGGER_EOF_DAY) {
return nil, true, nil
}
}
var lines = make([][]byte, 0)
for {
line, err := r.ReadBytes('\n')
if err != nil {
break
}
if strings.Contains(string(line[:len(line)-1]), constants.LOGGER_EOF_DAY) {
return lines, true, nil
}
lines = append(lines, line[:len(line)-1])
}
return lines, false, nil
}
func IsFileExisted(filePath string) bool {
info, err := os.Stat(filePath)
return (err == nil || os.IsExist(err)) && !info.IsDir()
}
func IsDirExisted(dirPath string) bool {
info, err := os.Stat(dirPath)
return (err == nil || os.IsExist(err)) && info.IsDir()
}
func DirFileCount(dirPath string) int {
files, _ := os.ReadDir(dirPath)
return len(files)
}
func DayTime(dayStr string) time.Time {
day, _ := time.Parse(constants.TIME_LAYOUT_DAY, dayStr)
return day
}
func CurrentDay(day time.Time) string {
return day.Format(constants.TIME_LAYOUT_DAY)
}
// LookupEnvPairs 根据所有 key 查找环境变量,并通过 map 保存,如果中途有 error 不会直接中断,而是继续
func LookupEnvPairs(envPairs *map[string]string) {
for envKey := range *envPairs {
env, ok := os.LookupEnv(envKey)
if !ok {
(*envPairs)[envKey] = ""
continue
}
(*envPairs)[envKey] = env
}
return
}
// LookupEnv 根据所有 key 查找环境变量,并通过 map 保存,如果中途有 error 不会直接中断,而是继续
func LookupEnv(envKey string) (string, error) {
env, ok := os.LookupEnv(envKey)
if !ok {
return "", errorx.ErrEnvLookupFailed
}
return env, nil
}
func StructToJsonStr(s any) string {
if s == nil {
return "{}"
}
res, err := json.Marshal(s)
if err != nil {
return "{}"
}
return string(res)
}