github.com/TeaOSLab/EdgeNode@v1.3.8/internal/remotelogs/utils.go (about) 1 package remotelogs 2 3 import ( 4 "encoding/json" 5 "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" 6 "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" 7 teaconst "github.com/TeaOSLab/EdgeNode/internal/const" 8 "github.com/TeaOSLab/EdgeNode/internal/goman" 9 "github.com/TeaOSLab/EdgeNode/internal/rpc" 10 "github.com/TeaOSLab/EdgeNode/internal/trackers" 11 "github.com/cespare/xxhash/v2" 12 "github.com/iwind/TeaGo/Tea" 13 "github.com/iwind/TeaGo/logs" 14 "github.com/iwind/TeaGo/maps" 15 "github.com/iwind/TeaGo/types" 16 "strings" 17 "time" 18 ) 19 20 var logChan = make(chan *pb.NodeLog, 64) // 队列数量不需要太长,因为日志通常仅仅为调试用 21 22 func init() { 23 if !teaconst.IsMain { 24 return 25 } 26 27 // 定期上传日志 28 var ticker = time.NewTicker(60 * time.Second) 29 if Tea.IsTesting() { 30 ticker = time.NewTicker(10 * time.Second) 31 } 32 goman.New(func() { 33 for range ticker.C { 34 var tr = trackers.Begin("UPLOAD_REMOTE_LOGS") 35 err := uploadLogs() 36 tr.End() 37 if err != nil { 38 logs.Println("[LOG]upload logs failed: " + err.Error()) 39 } 40 } 41 }) 42 } 43 44 // Debug 打印调试信息 45 func Debug(tag string, description string) { 46 logs.Println("[" + tag + "]" + description) 47 } 48 49 // Println 打印普通信息 50 func Println(tag string, description string) { 51 logs.Println("[" + tag + "]" + description) 52 53 select { 54 case logChan <- &pb.NodeLog{ 55 Role: teaconst.Role, 56 Tag: tag, 57 Description: description, 58 Level: "info", 59 NodeId: teaconst.NodeId, 60 CreatedAt: time.Now().Unix(), 61 }: 62 default: 63 } 64 } 65 66 // Warn 打印警告信息 67 func Warn(tag string, description string) { 68 logs.Println("[" + tag + "]" + description) 69 70 select { 71 case logChan <- &pb.NodeLog{ 72 Role: teaconst.Role, 73 Tag: tag, 74 Description: description, 75 Level: "warning", 76 NodeId: teaconst.NodeId, 77 CreatedAt: time.Now().Unix(), 78 }: 79 default: 80 } 81 } 82 83 // WarnServer 打印服务相关警告 84 func WarnServer(tag string, description string) { 85 if Tea.IsTesting() { 86 logs.Println("[" + tag + "]" + description) 87 } 88 89 nodeConfig, _ := nodeconfigs.SharedNodeConfig() 90 if nodeConfig != nil && nodeConfig.GlobalServerConfig != nil && !nodeConfig.GlobalServerConfig.Log.RecordServerError { 91 return 92 } 93 94 select { 95 case logChan <- &pb.NodeLog{ 96 Role: teaconst.Role, 97 Tag: tag, 98 Description: description, 99 Level: "warning", 100 NodeId: teaconst.NodeId, 101 CreatedAt: time.Now().Unix(), 102 }: 103 default: 104 105 } 106 } 107 108 // Error 打印错误信息 109 func Error(tag string, description string) { 110 logs.Println("[" + tag + "]" + description) 111 112 // 忽略RPC连接错误 113 var level = "error" 114 if strings.Contains(description, "code = Unavailable desc") { 115 level = "warning" 116 } 117 118 select { 119 case logChan <- &pb.NodeLog{ 120 Role: teaconst.Role, 121 Tag: tag, 122 Description: description, 123 Level: level, 124 NodeId: teaconst.NodeId, 125 CreatedAt: time.Now().Unix(), 126 }: 127 default: 128 129 } 130 } 131 132 // ErrorServer 打印服务相关错误信息 133 func ErrorServer(tag string, description string) { 134 if Tea.IsTesting() { 135 logs.Println("[" + tag + "]" + description) 136 } 137 138 // 忽略RPC连接错误 139 var level = "error" 140 if strings.Contains(description, "code = Unavailable desc") { 141 level = "warning" 142 } 143 144 nodeConfig, _ := nodeconfigs.SharedNodeConfig() 145 if nodeConfig != nil && nodeConfig.GlobalServerConfig != nil && !nodeConfig.GlobalServerConfig.Log.RecordServerError { 146 return 147 } 148 149 select { 150 case logChan <- &pb.NodeLog{ 151 Role: teaconst.Role, 152 Tag: tag, 153 Description: description, 154 Level: level, 155 NodeId: teaconst.NodeId, 156 CreatedAt: time.Now().Unix(), 157 }: 158 default: 159 160 } 161 } 162 163 // ErrorObject 打印错误对象 164 func ErrorObject(tag string, err error) { 165 if err == nil { 166 return 167 } 168 if rpc.IsConnError(err) { 169 Warn(tag, err.Error()) 170 } else { 171 Error(tag, err.Error()) 172 } 173 } 174 175 // ServerError 打印服务相关错误信息 176 func ServerError(serverId int64, tag string, description string, logType nodeconfigs.NodeLogType, params maps.Map) { 177 if Tea.IsTesting() { 178 logs.Println("[" + tag + "]" + description) 179 } 180 181 // 是否记录服务相关错误 182 nodeConfig, _ := nodeconfigs.SharedNodeConfig() 183 if nodeConfig != nil && nodeConfig.GlobalServerConfig != nil && !nodeConfig.GlobalServerConfig.Log.RecordServerError { 184 return 185 } 186 187 // 参数 188 var paramsJSON []byte 189 if len(params) > 0 { 190 p, err := json.Marshal(params) 191 if err != nil { 192 logs.Println("[LOG]ServerError(): json encode failed: " + err.Error()) 193 } else { 194 paramsJSON = p 195 } 196 } 197 198 select { 199 case logChan <- &pb.NodeLog{ 200 Role: teaconst.Role, 201 Tag: tag, 202 Description: description, 203 Level: "error", 204 NodeId: teaconst.NodeId, 205 ServerId: serverId, 206 CreatedAt: time.Now().Unix(), 207 Type: logType, 208 ParamsJSON: paramsJSON, 209 }: 210 default: 211 212 } 213 } 214 215 // ServerSuccess 打印服务相关成功信息 216 func ServerSuccess(serverId int64, tag string, description string, logType nodeconfigs.NodeLogType, params maps.Map) { 217 logs.Println("[" + tag + "]" + description) 218 219 // 参数 220 var paramsJSON []byte 221 if len(params) > 0 { 222 p, err := json.Marshal(params) 223 if err != nil { 224 logs.Println("[LOG]ServerSuccess(): json encode failed: " + err.Error()) 225 } else { 226 paramsJSON = p 227 } 228 } 229 230 select { 231 case logChan <- &pb.NodeLog{ 232 Role: teaconst.Role, 233 Tag: tag, 234 Description: description, 235 Level: "success", 236 NodeId: teaconst.NodeId, 237 ServerId: serverId, 238 CreatedAt: time.Now().Unix(), 239 Type: logType, 240 ParamsJSON: paramsJSON, 241 }: 242 default: 243 244 } 245 } 246 247 // ServerLog 打印服务相关日志信息 248 func ServerLog(serverId int64, tag string, description string, logType nodeconfigs.NodeLogType, params maps.Map) { 249 logs.Println("[" + tag + "]" + description) 250 251 // 参数 252 var paramsJSON []byte 253 if len(params) > 0 { 254 p, err := json.Marshal(params) 255 if err != nil { 256 logs.Println("[LOG]ServerLog(): json encode failed: " + err.Error()) 257 } else { 258 paramsJSON = p 259 } 260 } 261 262 select { 263 case logChan <- &pb.NodeLog{ 264 Role: teaconst.Role, 265 Tag: tag, 266 Description: description, 267 Level: "info", 268 NodeId: teaconst.NodeId, 269 ServerId: serverId, 270 CreatedAt: time.Now().Unix(), 271 Type: logType, 272 ParamsJSON: paramsJSON, 273 }: 274 default: 275 276 } 277 } 278 279 // 上传日志 280 func uploadLogs() error { 281 var logList = []*pb.NodeLog{} 282 283 const hashSize = 5 284 var hashList = []uint64{} 285 286 Loop: 287 for { 288 select { 289 case log := <-logChan: 290 if log.NodeId <= 0 { 291 continue 292 } 293 294 // 是否已存在 295 var hash = xxhash.Sum64String(types.String(log.ServerId) + "_" + log.Description) 296 var found = false 297 for _, h := range hashList { 298 if h == hash { 299 found = true 300 break 301 } 302 } 303 304 // 加入 305 if !found { 306 hashList = append(hashList, hash) 307 if len(hashList) > hashSize { 308 hashList = hashList[1:] 309 } 310 311 logList = append(logList, log) 312 } 313 default: 314 break Loop 315 } 316 } 317 318 if len(logList) == 0 { 319 return nil 320 } 321 322 rpcClient, err := rpc.SharedRPC() 323 if err != nil { 324 return err 325 } 326 327 // 正在退出时不上报错误 328 if teaconst.IsQuiting { 329 return nil 330 } 331 332 _, err = rpcClient.NodeLogRPC.CreateNodeLogs(rpcClient.Context(), &pb.CreateNodeLogsRequest{NodeLogs: logList}) 333 return err 334 }