From 151828f5695ca6d9b3eb12ddc94affd4850e4715 Mon Sep 17 00:00:00 2001 From: walker Date: Fri, 22 Dec 2023 15:06:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=97=A5=E5=BF=97=E7=BA=AA?= =?UTF-8?q?=E5=BD=95=E5=8F=8A=E6=9F=A5=E8=AF=A2=E8=AF=B7=E6=B1=82=E5=AE=8C?= =?UTF-8?q?=E5=96=84=20-=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E4=B8=BA?= =?UTF-8?q?=E5=86=85=E5=AD=98=E8=AE=B0=E5=BD=95=EF=BC=8C=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=B8=8A=E9=99=90=E5=AE=9A=E4=B8=BA1000=E6=9D=A1=20-=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E8=AF=B7=E6=B1=82=E6=9F=A5=E6=9C=80=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E6=9D=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/subsys_use/main.go | 28 ++++++++++++ log/log.go | 87 ++++++++++++++++++++++++++++++++++++++ log/log_test.go | 14 ++++++ main.go | 8 ++-- server/iot_log.go | 4 +- server/server.go | 2 + 6 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 log/log.go create mode 100644 log/log_test.go diff --git a/example/subsys_use/main.go b/example/subsys_use/main.go index 809b8ed..be45903 100644 --- a/example/subsys_use/main.go +++ b/example/subsys_use/main.go @@ -29,6 +29,12 @@ func main() { time.Sleep(3 * time.Second) // 等待应用mqtt连接 for i := 0; i < 4; i++ { ac.startIotQcService() // 启动IOT驱采服务 + resp, err := ac.iotLogReq(&dto.IotServiceLogReq{Count: 10}) + if err != nil { + slog.Error("应用请求日志错误", "err", err) + } else { + slog.Info("应用请求日志成功", "resp", resp) + } time.Sleep(10 * time.Second) ac.stopIotQcService() // 停止IOT驱采服务 time.Sleep(5 * time.Second) @@ -189,6 +195,28 @@ func (app *AppClient) iotStopReq(req *dto.IotQcServiceStopReq) (*dto.IotQcServic return result, nil } +func (app *AppClient) iotLogReq(req *dto.IotServiceLogReq) (*dto.IotServiceLogResp, error) { + h, err := app.newRpcHandler("%s/iotlogresp") + if err != nil { + return nil, err + } + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + b, err := proto.Marshal(req) + if err != nil { + return nil, errors.Join(fmt.Errorf("序列化IOT服务日志请求消息失败"), err) + } + resp, err := h.Request(ctx, &paho.Publish{ + Topic: mqtt.GetLogReqTopic(), + Payload: b, + }) + if err != nil { + return nil, errors.Join(fmt.Errorf("发送IOT服务日志请求错误"), err) + } + result := &dto.IotServiceLogResp{} + proto.Unmarshal(resp.Payload, result) + return result, nil +} func (app *AppClient) RegIotCjDataHandler(h func(*dto.IotCj)) { app.cfg.Router.RegisterHandler(mqtt.GetCjTopic(), func(p *paho.Publish) { cj := &dto.IotCj{} diff --git a/log/log.go b/log/log.go new file mode 100644 index 0000000..6dee84e --- /dev/null +++ b/log/log.go @@ -0,0 +1,87 @@ +package log + +import ( + "io" + "log/slog" + "os" + "sync" +) + +var historyList *logHistoryList + +func GetTailsOf(num int) []string { + if historyList == nil { + return nil + } + return historyList.GetTailsOf(num) +} + +// 初始化IOT日志配置和历史纪录 +func InitLog() { + level := slog.LevelInfo + historyList = newLogHistoryList(1000) // 最多保存1000条(根据情况调整) + w := newIotLogWriter(historyList) + slog.SetDefault(slog.New(slog.NewJSONHandler(w, &slog.HandlerOptions{ + Level: level, + AddSource: false, + }))) +} + +type iotLogWriter struct { + io.Writer + logs *logHistoryList +} + +// 输出到Stdout +func newIotLogWriter(logs *logHistoryList) *iotLogWriter { + return &iotLogWriter{Writer: os.Stdout, logs: logs} +} + +func (w *iotLogWriter) Write(p []byte) (n int, err error) { + w.logs.Add(string(p)) + return w.Writer.Write(p) +} + +type logHistoryList struct { + logs []string + capacity int + mutex sync.Mutex +} + +func newLogHistoryList(capacity int) *logHistoryList { + return &logHistoryList{ + logs: make([]string, capacity), + capacity: capacity, + } +} + +func (cl *logHistoryList) Add(item string) { + cl.mutex.Lock() + defer cl.mutex.Unlock() + + if len(cl.logs) >= cl.capacity { + // 如果容量已满,删除最早的元素 + cl.logs = cl.logs[1:] + } + cl.logs = append(cl.logs, item) +} + +func (cl *logHistoryList) Len() int { + cl.mutex.Lock() + defer cl.mutex.Unlock() + + return len(cl.logs) +} + +// 获取最新的num条记录 +func (cl *logHistoryList) GetTailsOf(num int) []string { + cl.mutex.Lock() + defer cl.mutex.Unlock() + + end := len(cl.logs) + start := end - num + if start < 0 { + start = 0 + } + return cl.logs[start:end] +} diff --git a/log/log_test.go b/log/log_test.go new file mode 100644 index 0000000..0933931 --- /dev/null +++ b/log/log_test.go @@ -0,0 +1,14 @@ +package log + +import ( + "strconv" + "testing" +) + +func TestGetLogHistory(t *testing.T) { + list := newLogHistoryList(10) + for i := 0; i < 10; i++ { + list.Add("test" + strconv.Itoa(i)) + } + t.Log(list.GetTailsOf(20)) +} diff --git a/main.go b/main.go index 8cb3966..776bb19 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,9 @@ package main -import "joylink.club/iot/server" +import ( + "joylink.club/iot/server" +) func main() { - // slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ - // Level: slog.LevelDebug, - // AddSource: false, - // }))) server.StartIotQcServer() } diff --git a/server/iot_log.go b/server/iot_log.go index d5d2da8..5dcfe16 100644 --- a/server/iot_log.go +++ b/server/iot_log.go @@ -2,9 +2,11 @@ package server import ( "joylink.club/iot/dto" + "joylink.club/iot/log" ) // 获取IOT日志请求响应 func GetIotLog(req *dto.IotServiceLogReq) *dto.IotServiceLogResp { - return &dto.IotServiceLogResp{} + tails := log.GetTailsOf(int(req.Count)) + return &dto.IotServiceLogResp{Logs: tails} } diff --git a/server/server.go b/server/server.go index 9b072ff..03fe329 100644 --- a/server/server.go +++ b/server/server.go @@ -8,6 +8,7 @@ import ( "joylink.club/iot/config" "joylink.club/iot/dto" + "joylink.club/iot/log" "joylink.club/iot/mqtt" "joylink.club/iot/service" ) @@ -130,6 +131,7 @@ func (s *IotQcServer) stopIotQcMappingService(req *dto.IotQcServiceStopReq) *dto } func StartIotQcServer() { + log.InitLog() iqcs = &IotQcServer{ tasks: []service.IScheduledTask{}, state: &dto.IotServiceState{