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  }