diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index ca2d097d..94991cd1 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -15,7 +15,7 @@ on: jobs: code-gen: - name: Code Generation + name: Verify code generation runs-on: ubuntu-latest steps: - name: Checkout @@ -39,7 +39,7 @@ jobs: fi golangci: - name: GolangCI + name: Run golangci-lint runs-on: ubuntu-latest steps: - name: Checkout @@ -49,9 +49,9 @@ jobs: with: go-version: "1.24.x" - name: Run golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v8 with: - version: v1.64.6 + version: v2.4.0 test: name: Test diff --git a/.golangci.yml b/.golangci.yml index ee0b7bab..7ad37dd0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,36 +1,69 @@ -run: - timeout: 5m +version: "2" linters: - disable-all: true + default: none enable: - - gofmt - - unused - - gosimple - - copyloopvar + - errcheck - gocritic - gosec - - errcheck - - goimports + - govet + - ineffassign - revive - staticcheck - - govet - - stylecheck - unconvert - - ineffassign - -linters-settings: - goimports: - local-prefixes: github.com/tbe-team/raybot - staticcheck: - checks: - - all - - "-ST1003" - - "-SA4006" - - "-SA1029" - stylecheck: - checks: - - all - - "-ST1003" - - "-SA4006" - - "-ST1016" - - "-ST1005" + - unused + - sloglint + settings: + staticcheck: + checks: + - -SA1029 + - -SA4006 + - -ST1003 + - -ST1005 + - -ST1016 + - all + sloglint: + no-mixed-args: true + attr-only: true + context: scope + static-msg: true + msg-style: lowercased + key-naming-case: snake + args-on-sep-lines: true + no-global: all + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - path: (.+)\.go$ + text: by other packages, and that stutters; consider calling this + - path: (.+)\.go$ + text: "var-naming:" + - path: (.+)\.go$ + text: "receiver-naming:" + - path: (.+)\.go$ + text: "unexported-return:" + - path: (.+)\.go$ + text: "unused-parameter: parameter" + - path: (.+)\.go$ + text: "context-keys-type: should not use basic type string" + - path: (.+)\.go$ + text: error strings should not be capitalized + - linters: + - staticcheck + text: "ST1003:" + paths: + - '(.+)_test\.go' +formatters: + enable: + - gofmt + - goimports + settings: + goimports: + local-prefixes: + - github.com/tbe-team/raybot + exclusions: + generated: disable diff --git a/Makefile b/Makefile index 125547ef..432ee7ab 100644 --- a/Makefile +++ b/Makefile @@ -139,4 +139,4 @@ test-cov: ######################## .PHONY: lint-go lint-go: - golangci-lint run ./... --config .golangci.yml + go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.4.0 run ./... --config .golangci.yml diff --git a/go.mod b/go.mod index 8e0cd130..9bf03e07 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 github.com/jhump/grpctunnel v0.3.0 github.com/karalabe/hid v1.0.0 + github.com/lmittmann/tint v1.1.2 github.com/mattn/go-sqlite3 v1.14.28 github.com/oapi-codegen/runtime v1.1.2 github.com/pressly/goose/v3 v3.24.3 diff --git a/go.sum b/go.sum index f3e5fb9c..baaccc84 100644 --- a/go.sum +++ b/go.sum @@ -107,6 +107,8 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhR github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= +github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= diff --git a/internal/handlers/cloud/service.go b/internal/handlers/cloud/service.go index f668efef..122edfe4 100644 --- a/internal/handlers/cloud/service.go +++ b/internal/handlers/cloud/service.go @@ -99,7 +99,7 @@ func New( return &Service{ opts: opts, cfg: cfg, - log: log.With("service", "cloud"), + log: log.With(slog.String("service", "cloud")), publisher: publisher, subscriber: subscriber, commandService: commandService, @@ -177,7 +177,7 @@ func (s *Service) runReverseTunnel(ctx context.Context, reverseTunnelServer *grp started, err := reverseTunnelServer.Serve(ctx) if !started || err != nil { serveErrChan <- struct{}{} - s.log.Error("serving reverse tunnel failed, retrying", + s.log.ErrorContext(ctx, "serving reverse tunnel failed, retrying", slog.Bool("started", started), slog.Int("attempts", attempts), slog.Duration("retry_delay", retryDelay), diff --git a/internal/handlers/espserial/service.go b/internal/handlers/espserial/service.go index d2056273..3d6b46e0 100644 --- a/internal/handlers/espserial/service.go +++ b/internal/handlers/espserial/service.go @@ -39,7 +39,7 @@ func New( cfg: cfg, publisher: publisher, client: client, - log: log.With("service", "espserial"), + log: log.With(slog.String("service", "espserial")), cargoService: cargoService, } @@ -72,7 +72,7 @@ func (s *Service) readLoop(ctx context.Context) { default: msg, err := s.client.Read(ctx) if err != nil { - s.log.Error("failed to read from serial client", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to read from serial client", slog.Any("error", err)) if errors.Is(err, espserial.ErrESPSerialNotConnected) { s.publisher.Publish( events.ESPSerialDisconnectedTopic, @@ -89,12 +89,16 @@ func (s *Service) readLoop(ctx context.Context) { } func (s *Service) routeMessage(ctx context.Context, msg []byte) { - s.log.Debug("routing message", slog.Any("message", msg)) + s.log.DebugContext(ctx, "routing message", slog.Any("message", msg)) var temp struct { Type messageType `json:"type"` } if err := json.Unmarshal(msg, &temp); err != nil { - s.log.Error("failed to unmarshal message type", slog.Any("error", err), slog.Any("message", msg)) + s.log.ErrorContext(ctx, + "failed to unmarshal message type", + slog.Any("message", msg), + slog.Any("error", err), + ) return } @@ -102,22 +106,38 @@ func (s *Service) routeMessage(ctx context.Context, msg []byte) { case messageTypeSyncState: var syncStateMsg syncStateMessage if err := json.Unmarshal(msg, &syncStateMsg); err != nil { - s.log.Error("failed to unmarshal sync state message", slog.Any("error", err), slog.Any("message", msg)) + s.log.ErrorContext(ctx, + "failed to unmarshal sync state message", + slog.Any("message", msg), + slog.Any("error", err), + ) return } if err := s.HandleSyncState(ctx, syncStateMsg); err != nil { - s.log.Error("failed to handle sync state message", slog.Any("error", err), slog.Any("message", msg)) + s.log.ErrorContext(ctx, + "failed to handle sync state message", + slog.Any("message", msg), + slog.Any("error", err), + ) } case messageTypeACK: var ackMsg ackMessage if err := json.Unmarshal(msg, &ackMsg); err != nil { - s.log.Error("failed to unmarshal ack message", slog.Any("error", err), slog.Any("message", msg)) + s.log.ErrorContext(ctx, + "failed to unmarshal ack message", + slog.Any("message", msg), + slog.Any("error", err), + ) return } if err := s.HandleACK(ackMsg); err != nil { - s.log.Error("failed to handle ack message", slog.Any("error", err), slog.Any("message", msg)) + s.log.ErrorContext(ctx, + "failed to handle ack message", + slog.Any("message", msg), + slog.Any("error", err), + ) } } } diff --git a/internal/handlers/event/cloud_event_handler.go b/internal/handlers/event/cloud_event_handler.go index b897c8db..ccdd9802 100644 --- a/internal/handlers/event/cloud_event_handler.go +++ b/internal/handlers/event/cloud_event_handler.go @@ -20,7 +20,7 @@ func (s *Service) HandleCloudConnectedEvent(ctx context.Context, _ events.CloudC LastConnectedAt: ptr.New(time.Now()), SetLastConnectedAt: true, }); err != nil { - s.log.Error("failed to update cloud connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update cloud connection", slog.Any("error", err)) } } @@ -61,6 +61,6 @@ func (s *Service) HandleCloudDisconnectedEvent(ctx context.Context, event events }) if err := g.Wait(); err != nil { - s.log.Error("failed to update cloud connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update cloud connection", slog.Any("error", err)) } } diff --git a/internal/handlers/event/esp_event_handler.go b/internal/handlers/event/esp_event_handler.go index 9f150c7f..a535e773 100644 --- a/internal/handlers/event/esp_event_handler.go +++ b/internal/handlers/event/esp_event_handler.go @@ -17,7 +17,7 @@ func (s *Service) HandleESPSerialConnectedEvent(ctx context.Context, _ events.ES LastConnectedAt: ptr.New(time.Now()), SetLastConnectedAt: true, }); err != nil { - s.log.Error("failed to update ESP serial connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update ESP serial connection", slog.Any("error", err)) } } @@ -28,6 +28,6 @@ func (s *Service) HandleESPSerialDisconnectedEvent(ctx context.Context, event ev Error: ptr.New(event.Error.Error()), SetError: true, }); err != nil { - s.log.Error("failed to update ESP serial connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update ESP serial connection", slog.Any("error", err)) } } diff --git a/internal/handlers/event/pic_event_handler.go b/internal/handlers/event/pic_event_handler.go index 13ff08b2..58e190b7 100644 --- a/internal/handlers/event/pic_event_handler.go +++ b/internal/handlers/event/pic_event_handler.go @@ -20,7 +20,7 @@ func (s *Service) HandlePICSerialConnectedEvent(ctx context.Context, _ events.PI LastConnectedAt: ptr.New(time.Now()), SetLastConnectedAt: true, }); err != nil { - s.log.Error("failed to update PIC serial connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update PIC serial connection", slog.Any("error", err)) } } @@ -53,6 +53,6 @@ func (s *Service) HandlePICSerialDisconnectedEvent(ctx context.Context, event ev }) if err := g.Wait(); err != nil { - s.log.Error("failed to update cloud connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update cloud connection", slog.Any("error", err)) } } diff --git a/internal/handlers/event/rfid_usb_event_handler.go b/internal/handlers/event/rfid_usb_event_handler.go index 4f4ec6c3..11be1ff1 100644 --- a/internal/handlers/event/rfid_usb_event_handler.go +++ b/internal/handlers/event/rfid_usb_event_handler.go @@ -20,7 +20,7 @@ func (s *Service) HandleRFIDUSBConnectedEvent(ctx context.Context, _ events.RFID LastConnectedAt: ptr.New(time.Now()), SetLastConnectedAt: true, }); err != nil { - s.log.Error("failed to update RFID USB connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update RFID USB connection", slog.Any("error", err)) } } @@ -53,6 +53,6 @@ func (s *Service) HandleRFIDUSBDisconnectedEvent(ctx context.Context, event even }) if err := g.Wait(); err != nil { - s.log.Error("failed to update cloud connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update cloud connection", slog.Any("error", err)) } } diff --git a/internal/handlers/event/service.go b/internal/handlers/event/service.go index 219e9865..e77c2b58 100644 --- a/internal/handlers/event/service.go +++ b/internal/handlers/event/service.go @@ -31,7 +31,7 @@ func New( systemService system.Service, ) *Service { return &Service{ - log: log.With("service", "event"), + log: log.With(slog.String("service", "event")), subscriber: subscriber, appStateService: appStateService, commandService: commandService, @@ -58,7 +58,7 @@ func (s *Service) registerHandlers(ctx context.Context) { func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.CloudConnectedEvent) if !ok { - s.log.Error("received invalid event", slog.Any("event", msg.Payload)) + s.log.ErrorContext(ctx, "received invalid event", slog.Any("event", msg.Payload)) return } @@ -72,7 +72,7 @@ func (s *Service) registerHandlers(ctx context.Context) { func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.CloudDisconnectedEvent) if !ok { - s.log.Error("received invalid event", slog.Any("event", msg.Payload)) + s.log.ErrorContext(ctx, "received invalid event", slog.Any("event", msg.Payload)) return } @@ -86,7 +86,7 @@ func (s *Service) registerHandlers(ctx context.Context) { func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.ESPSerialConnectedEvent) if !ok { - s.log.Error("received invalid event", slog.Any("event", msg.Payload)) + s.log.ErrorContext(ctx, "received invalid event", slog.Any("event", msg.Payload)) return } @@ -100,7 +100,7 @@ func (s *Service) registerHandlers(ctx context.Context) { func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.ESPSerialDisconnectedEvent) if !ok { - s.log.Error("received invalid event", slog.Any("event", msg.Payload)) + s.log.ErrorContext(ctx, "received invalid event", slog.Any("event", msg.Payload)) return } @@ -114,7 +114,7 @@ func (s *Service) registerHandlers(ctx context.Context) { func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.PICSerialConnectedEvent) if !ok { - s.log.Error("received invalid event", slog.Any("event", msg.Payload)) + s.log.ErrorContext(ctx, "received invalid event", slog.Any("event", msg.Payload)) return } @@ -128,7 +128,7 @@ func (s *Service) registerHandlers(ctx context.Context) { func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.PICSerialDisconnectedEvent) if !ok { - s.log.Error("received invalid event", slog.Any("event", msg.Payload)) + s.log.ErrorContext(ctx, "received invalid event", slog.Any("event", msg.Payload)) return } @@ -142,7 +142,7 @@ func (s *Service) registerHandlers(ctx context.Context) { func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.RFIDUSBConnectedEvent) if !ok { - s.log.Error("received invalid event", slog.Any("event", msg.Payload)) + s.log.ErrorContext(ctx, "received invalid event", slog.Any("event", msg.Payload)) return } @@ -156,7 +156,7 @@ func (s *Service) registerHandlers(ctx context.Context) { func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.RFIDUSBDisconnectedEvent) if !ok { - s.log.Error("received invalid event", slog.Any("event", msg.Payload)) + s.log.ErrorContext(ctx, "received invalid event", slog.Any("event", msg.Payload)) return } diff --git a/internal/handlers/http/middleware/recoverer.go b/internal/handlers/http/middleware/recoverer.go index d8b6d3df..1e8ded48 100644 --- a/internal/handlers/http/middleware/recoverer.go +++ b/internal/handlers/http/middleware/recoverer.go @@ -37,7 +37,7 @@ func Recoverer(log *slog.Logger) func(http.Handler) http.Handler { panic(rvr) } - log.Error("panic", slog.Any("recover", rvr), + log.ErrorContext(r.Context(), "http panic", slog.Any("recover", rvr), slog.String("stack", string(debug.Stack()))) if r.Header.Get("Connection") != "Upgrade" { diff --git a/internal/handlers/http/service.go b/internal/handlers/http/service.go index 7cb57a1b..737aab0a 100644 --- a/internal/handlers/http/service.go +++ b/internal/handlers/http/service.go @@ -53,7 +53,7 @@ func New( ) *Service { return &Service{ cfg: cfg, - log: log.With("service", "http"), + log: log.With(slog.String("service", "http")), configService: configService, systemService: systemService, dashboardDataService: dashboardDataService, diff --git a/internal/handlers/jobs/delete_deactivated_alarms_handler.go b/internal/handlers/jobs/delete_deactivated_alarms_handler.go index 16bacd8d..b1b3a49a 100644 --- a/internal/handlers/jobs/delete_deactivated_alarms_handler.go +++ b/internal/handlers/jobs/delete_deactivated_alarms_handler.go @@ -54,7 +54,7 @@ func (h *deleteDeactivatedAlarmsHandler) run(ctx context.Context, stoppedCh chan Threshold: time.Now().Add(-deleteDeactivatedAlarmsThreshold), }, ); err != nil { - h.log.Error("failed to delete deactivated alarms", slog.Any("error", err)) + h.log.ErrorContext(ctx, "failed to delete deactivated alarms", slog.Any("error", err)) } } } diff --git a/internal/handlers/jobs/delete_old_command_handler.go b/internal/handlers/jobs/delete_old_command_handler.go index cb0af6c6..163e7d77 100644 --- a/internal/handlers/jobs/delete_old_command_handler.go +++ b/internal/handlers/jobs/delete_old_command_handler.go @@ -50,7 +50,7 @@ func (h *deleteOldCommandHandler) run(ctx context.Context, stoppedCh chan struct case <-time.After(h.deleteOldCommandCfg.ScheduleDuration()): if err := h.commandService.DeleteOldCommands(ctx); err != nil { - h.log.Error("failed to delete old commands", slog.Any("error", err)) + h.log.ErrorContext(ctx, "failed to delete old commands", slog.Any("error", err)) } } } diff --git a/internal/handlers/jobs/execute_command_handler.go b/internal/handlers/jobs/execute_command_handler.go index 9b07a463..f4addff7 100644 --- a/internal/handlers/jobs/execute_command_handler.go +++ b/internal/handlers/jobs/execute_command_handler.go @@ -29,7 +29,7 @@ func newExecuteCommandHandler( subscriber eventbus.Subscriber, ) *executeCommandHandler { return &executeCommandHandler{ - log: log.With("service", "execute_command_handler"), + log: log.With(slog.String("service", "execute_command_handler")), commandService: commandService, subscriber: subscriber, } @@ -81,6 +81,6 @@ func (h *executeCommandHandler) handle(ctx context.Context) { defer h.running.Store(false) if err := h.commandService.RunNextExecutableCommand(ctx); err != nil { - h.log.Error("failed to find next executable command and run", slog.Any("error", err)) + h.log.ErrorContext(ctx, "failed to find next executable command and run", slog.Any("error", err)) } } diff --git a/internal/handlers/jobs/service.go b/internal/handlers/jobs/service.go index 49554c83..f762508b 100644 --- a/internal/handlers/jobs/service.go +++ b/internal/handlers/jobs/service.go @@ -31,7 +31,7 @@ func New( ) *Service { return &Service{ cronCfg: cronCfg, - log: log.With("service", "jobs"), + log: log.With(slog.String("service", "jobs")), subscriber: subscriber, commandService: commandService, alarmService: alarmService, diff --git a/internal/handlers/picserial/service.go b/internal/handlers/picserial/service.go index 761ad86b..2d816b23 100644 --- a/internal/handlers/picserial/service.go +++ b/internal/handlers/picserial/service.go @@ -56,7 +56,7 @@ func New( cfg: cfg, client: client, publisher: publisher, - log: log.With("service", "picserial"), + log: log.With(slog.String("service", "picserial")), batteryService: batteryService, distanceSensorService: distanceSensorService, liftMotorService: liftMotorService, @@ -94,7 +94,7 @@ func (s *Service) readLoop(ctx context.Context) { default: msg, err := s.client.Read(ctx) if err != nil { - s.log.Error("failed to read from serial client", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to read from serial client", slog.Any("error", err)) if errors.Is(err, picserial.ErrPICSerialNotConnected) { s.publisher.Publish( events.PICSerialDisconnectedTopic, @@ -115,7 +115,11 @@ func (s *Service) routeMessage(ctx context.Context, msg []byte) { Type messageType `json:"type"` } if err := json.Unmarshal(msg, &temp); err != nil { - s.log.Error("failed to unmarshal message", slog.Any("error", err), slog.Any("message", msg)) + s.log.ErrorContext(ctx, + "failed to unmarshal message", + slog.Any("error", err), + slog.Any("message", msg), + ) return } @@ -124,25 +128,41 @@ func (s *Service) routeMessage(ctx context.Context, msg []byte) { case messageTypeSyncState: var syncStateMsg syncStateMessage if err := json.Unmarshal(msg, &syncStateMsg); err != nil { - s.log.Error("failed to unmarshal sync state message", slog.Any("error", err), slog.Any("message", msg)) + s.log.ErrorContext(ctx, + "failed to unmarshal sync state message", + slog.Any("error", err), + slog.Any("message", msg), + ) return } if err := s.HandleSyncState(ctx, syncStateMsg); err != nil { - s.log.Error("failed to handle sync state message", slog.Any("error", err), slog.Any("message", msg)) + s.log.ErrorContext(ctx, + "failed to handle sync state message", + slog.Any("error", err), + slog.Any("message", msg), + ) } case messageTypeACK: var ackMsg ackMessage if err := json.Unmarshal(msg, &ackMsg); err != nil { - s.log.Error("failed to unmarshal ack message", slog.Any("error", err), slog.Any("message", msg)) + s.log.ErrorContext(ctx, + "failed to unmarshal ack message", + slog.Any("error", err), + slog.Any("message", msg), + ) return } if err := s.HandleACK(ackMsg); err != nil { - s.log.Error("failed to handle ack message", slog.Any("error", err), slog.Any("message", msg)) + s.log.ErrorContext(ctx, + "failed to handle ack message", + slog.Any("error", err), + slog.Any("message", msg), + ) } default: - s.log.Error("unknown message type", slog.Any("type", temp.Type)) + s.log.ErrorContext(ctx, "unknown message type", slog.Any("type", temp.Type)) } } diff --git a/internal/handlers/rfidusb/rfid_tag_handler.go b/internal/handlers/rfidusb/rfid_tag_handler.go index d4ea78dc..f4ec1b81 100644 --- a/internal/handlers/rfidusb/rfid_tag_handler.go +++ b/internal/handlers/rfidusb/rfid_tag_handler.go @@ -8,10 +8,10 @@ import ( ) func (s *Service) HandleRFIDTag(ctx context.Context, tag string) { - s.log.Debug("RFID tag detected", slog.String("tag", tag)) + s.log.DebugContext(ctx, "RFID tag detected", slog.String("tag", tag)) if err := s.locationService.UpdateLocation(ctx, location.UpdateLocationParams{ CurrentLocation: tag, }); err != nil { - s.log.Error("failed to update location", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update location", slog.Any("error", err)) } } diff --git a/internal/handlers/rfidusb/service.go b/internal/handlers/rfidusb/service.go index 40cddf7c..d4d5316e 100644 --- a/internal/handlers/rfidusb/service.go +++ b/internal/handlers/rfidusb/service.go @@ -25,7 +25,7 @@ func New( locationService location.Service, ) *Service { return &Service{ - log: log.With("service", "rfidusb"), + log: log.With(slog.String("service", "rfidusb")), publisher: publisher, client: newClient(), locationService: locationService, @@ -35,7 +35,7 @@ func New( func (s *Service) Run(ctx context.Context) (CleanupFunc, error) { if err := s.client.Open(); err != nil { // We don't want to fail the service if the serial client fails to open - s.log.Error("failed to open RFID reader", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to open RFID reader", slog.Any("error", err)) s.publisher.Publish( events.RFIDUSBDisconnectedTopic, eventbus.NewMessage(events.RFIDUSBDisconnectedEvent{ @@ -70,7 +70,7 @@ func (s *Service) readLoop(ctx context.Context) { default: tag, err := s.client.Read() if err != nil { - s.log.Error("failed to read rfid tag", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to read rfid tag", slog.Any("error", err)) s.publisher.Publish( events.RFIDUSBDisconnectedTopic, eventbus.NewMessage(events.RFIDUSBDisconnectedEvent{ diff --git a/internal/hardware/controller/controller.go b/internal/hardware/controller/controller.go index 368c1337..8d14a7f9 100644 --- a/internal/hardware/controller/controller.go +++ b/internal/hardware/controller/controller.go @@ -108,21 +108,21 @@ func (c *controller) writePICCommandWithACK(ctx context.Context, cmd picCommand) func (c *controller) trackingPICCommandACK(ctx context.Context, id string) error { log := c.log.With(slog.String("id", id)) - log.Info("start tracking PIC command ack") + log.InfoContext(ctx, "start tracking PIC command ack") doneCh := make(chan struct{}) c.subscriber.Subscribe(ctx, events.PICCmdAckTopic, func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.PICCmdAckEvent) if !ok { - log.Error("invalid event", slog.Any("event", msg.Payload)) + log.ErrorContext(ctx, "invalid event", slog.Any("event", msg.Payload)) return } if ev.ID == id { if ev.Success { - log.Info("PIC command ack success") + log.InfoContext(ctx, "PIC command ack success") } else { - log.Error("PIC command ack failed") + log.ErrorContext(ctx, "PIC command ack failed") } close(doneCh) } @@ -130,11 +130,11 @@ func (c *controller) trackingPICCommandACK(ctx context.Context, id string) error select { case <-doneCh: - log.Info("stop tracking PIC command ack") + log.InfoContext(ctx, "stop tracking PIC command ack") return nil case <-time.After(c.cfg.PIC.CommandACKTimeout): - log.Error("PIC command ack timeout") + log.ErrorContext(ctx, "PIC command ack timeout") return ErrCommandACKTimeout case <-ctx.Done(): @@ -190,21 +190,21 @@ func (c *controller) writeESPCommandWithACK(ctx context.Context, cmd espCommand) func (c *controller) trackingESPCommandACK(ctx context.Context, id string) error { log := c.log.With(slog.String("id", id)) - log.Info("start tracking ESP command ack") + log.InfoContext(ctx, "start tracking ESP command ack") doneCh := make(chan struct{}) c.subscriber.Subscribe(ctx, events.ESPCmdAckTopic, func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.ESPCmdAckEvent) if !ok { - log.Error("invalid event", slog.Any("event", msg.Payload)) + log.ErrorContext(ctx, "invalid event", slog.Any("event", msg.Payload)) return } if ev.ID == id { if ev.Success { - log.Info("ESP command ack success") + log.InfoContext(ctx, "ESP command ack success") } else { - log.Error("ESP command ack failed") + log.ErrorContext(ctx, "ESP command ack failed") } close(doneCh) } @@ -212,11 +212,11 @@ func (c *controller) trackingESPCommandACK(ctx context.Context, id string) error select { case <-doneCh: - log.Info("stop tracking ESP command ack") + log.InfoContext(ctx, "stop tracking ESP command ack") return nil case <-time.After(c.cfg.ESP.CommandACKTimeout): - log.Error("ESP command ack timeout") + log.ErrorContext(ctx, "ESP command ack timeout") return ErrCommandACKTimeout case <-ctx.Done(): diff --git a/internal/logging/logging.go b/internal/logging/logging.go index a0cbc6fd..475106c3 100644 --- a/internal/logging/logging.go +++ b/internal/logging/logging.go @@ -4,7 +4,9 @@ import ( "fmt" "log/slog" "os" + "time" + "github.com/lmittmann/tint" "gopkg.in/natefinch/lumberjack.v2" "github.com/tbe-team/raybot/internal/config" @@ -57,8 +59,17 @@ func newConsoleHandler(cfg config.LogConsoleHandler) slog.Handler { }) } - return slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{ - Level: cfg.Level, + return tint.NewHandler(os.Stdout, &tint.Options{ + Level: cfg.Level, + TimeFormat: time.RFC3339, + ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr { + if a.Value.Kind() == slog.KindAny { + if _, ok := a.Value.Any().(error); ok { + return tint.Attr(9, a) + } + } + return a + }, }) } diff --git a/internal/services/alarm/alarmimpl/service.go b/internal/services/alarm/alarmimpl/service.go index 47ec8d58..b34412cf 100644 --- a/internal/services/alarm/alarmimpl/service.go +++ b/internal/services/alarm/alarmimpl/service.go @@ -74,7 +74,7 @@ func (s Service) DeleteDeactivatedAlarmsByThreshold(ctx context.Context, params func (s Service) deactivateAllActivatedAlarms(ctx context.Context) { if err := s.alarmRepo.DeactivateAllAlarms(ctx); err != nil { - s.log.Error("failed to deactivate all activated alarms", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to deactivate all activated alarms", slog.Any("error", err)) } } @@ -101,7 +101,7 @@ func (s Service) DeactivateAlarm(ctx context.Context, params alarm.DeactivateAla g.Go(func() error { if err := s.ledService.SetAlertLedOff(ctx); err != nil { if errors.Is(err, led.ErrLedNotConnected) { - s.log.Warn("alert led is not connected, skipping") + s.log.WarnContext(ctx, "alert led is not connected, skipping") return nil } return fmt.Errorf("failed to set alert led off: %w", err) diff --git a/internal/services/command/commandimpl/service.go b/internal/services/command/commandimpl/service.go index 2db7be47..bd4d7377 100644 --- a/internal/services/command/commandimpl/service.go +++ b/internal/services/command/commandimpl/service.go @@ -42,7 +42,7 @@ func NewService( ) command.Service { s := &Service{ deleteOldCmdCfg: deleteOldCmdCfg, - log: log.With("service", "command"), + log: log.With(slog.String("service", "command")), validator: validator, publisher: publisher, runningCmdRepository: runningCmdRepository, @@ -197,7 +197,7 @@ func (s *Service) DeleteOldCommands(ctx context.Context) error { func (s *Service) cancelQueuedAndProcessingCommands(ctx context.Context) { if err := s.commandRepository.CancelPendingCommands(ctx); err != nil { - s.log.Error("failed to cancel queued and processing commands on startup", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to cancel queued and processing commands on startup", slog.Any("error", err)) } } @@ -210,7 +210,7 @@ func (s *Service) runNextExecutableCommand(ctx context.Context) error { return fmt.Errorf("get next executable command: %w", err) } - s.log.Info("found executable command, executing", + s.log.InfoContext(ctx, "found executable command, executing", slog.Int64("command_id", cmd.ID), slog.String("command_type", cmd.Type.String()), slog.Any("command_inputs", cmd.Inputs), diff --git a/internal/services/command/executor/cargo_check_qr_executor.go b/internal/services/command/executor/cargo_check_qr_executor.go index 4ac28fa9..71d8a542 100644 --- a/internal/services/command/executor/cargo_check_qr_executor.go +++ b/internal/services/command/executor/cargo_check_qr_executor.go @@ -47,21 +47,21 @@ func (e cargoCheckQRExecutor) OnCancel(_ context.Context) error { func (e cargoCheckQRExecutor) trackingCargoQRCodeUntilMatched(ctx context.Context, qrCode string) { ctx, cancel := context.WithCancel(ctx) defer func() { - e.log.Info("stop tracking cargo qr code") + e.log.InfoContext(ctx, "stop tracking cargo qr code") cancel() }() doneCh := make(chan struct{}) - e.log.Info("start tracking cargo qr code", slog.Any("qr_code", qrCode)) + e.log.InfoContext(ctx, "start tracking cargo qr code", slog.Any("qr_code", qrCode)) e.subscriber.Subscribe(ctx, events.CargoQRCodeUpdatedTopic, func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.CargoQRCodeUpdatedEvent) if !ok { - e.log.Error("invalid event", slog.Any("event", msg.Payload)) + e.log.ErrorContext(ctx, "invalid event", slog.Any("event", msg.Payload)) return } if ev.QRCode == qrCode { - e.log.Info("cargo qr code matched", slog.Any("qrcode", ev.QRCode)) + e.log.InfoContext(ctx, "cargo qr code matched", slog.Any("qrcode", ev.QRCode)) close(doneCh) } }) diff --git a/internal/services/command/executor/cargo_close_executor.go b/internal/services/command/executor/cargo_close_executor.go index c67d5e4c..880aa551 100644 --- a/internal/services/command/executor/cargo_close_executor.go +++ b/internal/services/command/executor/cargo_close_executor.go @@ -67,21 +67,21 @@ func (e cargoCloseExecutor) OnCancel(_ context.Context) error { func (e cargoCloseExecutor) trackingCargoDoorUntilClosed(ctx context.Context) { ctx, cancel := context.WithCancel(ctx) defer func() { - e.log.Info("stop tracking cargo door") + e.log.InfoContext(ctx, "stop tracking cargo door") cancel() }() doneCh := make(chan struct{}) - e.log.Info("start tracking cargo door") + e.log.InfoContext(ctx, "start tracking cargo door") e.subscriber.Subscribe(ctx, events.CargoDoorUpdatedTopic, func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.CargoDoorUpdatedEvent) if !ok { - e.log.Error("invalid event", slog.Any("event", msg.Payload)) + e.log.ErrorContext(ctx, "invalid event", slog.Any("event", msg.Payload)) return } if !ev.IsOpen { - e.log.Info("cargo door closed") + e.log.InfoContext(ctx, "cargo door closed") close(doneCh) } }) diff --git a/internal/services/command/executor/cargo_lift_executor.go b/internal/services/command/executor/cargo_lift_executor.go index 18040e0d..c5499ae7 100644 --- a/internal/services/command/executor/cargo_lift_executor.go +++ b/internal/services/command/executor/cargo_lift_executor.go @@ -93,7 +93,7 @@ func (e cargoLiftExecutor) trackingLiftPositionUntilReached(ctx context.Context, requiredStableReadCount := e.getRequiredStableReadCount(ctx) stableReadCount := 0 - e.log.Info("start tracking lift position", + e.log.InfoContext(ctx, "start tracking lift position", slog.Int64("target_position", int64(liftPosition)), slog.Int("required_stable_read_count", requiredStableReadCount)) @@ -101,13 +101,13 @@ func (e cargoLiftExecutor) trackingLiftPositionUntilReached(ctx context.Context, e.subscriber.Subscribe(ctx, events.DistanceSensorUpdatedTopic, func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.UpdateDistanceSensorEvent) if !ok { - e.log.Error("invalid event", slog.Any("event", msg.Payload)) + e.log.ErrorContext(ctx, "invalid event", slog.Any("event", msg.Payload)) return } if e.isLiftPositionReached(ev.DownDistance, liftPosition) { stableReadCount++ - e.log.Info("lift position reached", + e.log.InfoContext(ctx, "lift position reached", slog.Int("stable_read_count", stableReadCount), slog.Int("required_stable_read_count", requiredStableReadCount), slog.Int64("down_distance", int64(ev.DownDistance)), @@ -122,7 +122,7 @@ func (e cargoLiftExecutor) trackingLiftPositionUntilReached(ctx context.Context, return } - e.log.Warn("reset stable read count", + e.log.WarnContext(ctx, "reset stable read count", slog.Int64("down_distance", int64(ev.DownDistance))) stableReadCount = 0 }) @@ -143,7 +143,7 @@ func (cargoLiftExecutor) isLiftPositionReached(current, target uint16) bool { func (e cargoLiftExecutor) getRequiredStableReadCount(ctx context.Context) int { commandCfg, err := e.configService.GetCommandConfig(ctx) if err != nil { - e.log.Error("failed to get command config", slog.Any("error", err)) + e.log.ErrorContext(ctx, "failed to get command config", slog.Any("error", err)) return 1 } return int(commandCfg.CargoLift.StableReadCount) diff --git a/internal/services/command/executor/cargo_lower_executor.go b/internal/services/command/executor/cargo_lower_executor.go index 74b87a0f..984db1f3 100644 --- a/internal/services/command/executor/cargo_lower_executor.go +++ b/internal/services/command/executor/cargo_lower_executor.go @@ -94,7 +94,7 @@ func (e cargoLowerExecutor) trackingLowerPositionUntilReached(ctx context.Contex requiredStableReadCount := e.getRequiredStableReadCount(ctx) stableReadCount := 0 - e.log.Info("start tracking lower position", + e.log.InfoContext(ctx, "start tracking lower position", slog.Int64("lower_position", int64(lowerPosition)), slog.Int("required_stable_read_count", requiredStableReadCount)) @@ -150,30 +150,30 @@ func (e cargoLowerExecutor) trackingLowerPositionUntilReached(ctx context.Contex func (e cargoLowerExecutor) trackingBottomObstacle(ctx context.Context, inputs command.CargoLowerInputs) { ctx, cancel := context.WithCancel(ctx) defer func() { - e.log.Info("stop tracking bottom obstacle") + e.log.InfoContext(ctx, "stop tracking bottom obstacle") cancel() }() obstacleTracking, err := e.getObstacleTracking(ctx) if err != nil { - e.log.Error("failed to get obstacle tracking", slog.Any("error", err)) + e.log.ErrorContext(ctx, "failed to get obstacle tracking", slog.Any("error", err)) return } bottomDistanceCh := make(chan uint16, 1) - e.log.Info("start tracking bottom obstacle") + e.log.InfoContext(ctx, "start tracking bottom obstacle") e.subscriber.Subscribe(ctx, events.CargoBottomDistanceUpdatedTopic, func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.CargoBottomDistanceUpdatedEvent) if !ok { - e.log.Error("invalid event", slog.Any("event", msg.Payload)) + e.log.ErrorContext(ctx, "invalid event", slog.Any("event", msg.Payload)) return } select { case bottomDistanceCh <- ev.BottomDistance: default: - e.log.Error("dropped message from bottom distance channel", + e.log.ErrorContext(ctx, "dropped message from bottom distance channel", slog.Uint64("bottom_distance", uint64(ev.BottomDistance))) } }) @@ -188,9 +188,9 @@ func (e cargoLowerExecutor) trackingBottomObstacle(ctx context.Context, inputs c case bottomDistance := <-bottomDistanceCh: // If the bottom distance is less than the enter distance, we stop the motor if bottomDistance <= obstacleTracking.EnterDistance && isMotorRunning { - e.log.Info("obstacle detected, stopping motor", slog.Uint64("bottom_distance", uint64(bottomDistance))) + e.log.InfoContext(ctx, "obstacle detected, stopping motor", slog.Uint64("bottom_distance", uint64(bottomDistance))) if err := e.liftMotorService.Stop(ctx); err != nil { - e.log.Error("failed to stop lift motor", slog.Any("error", err)) + e.log.ErrorContext(ctx, "failed to stop lift motor", slog.Any("error", err)) } isMotorRunning = false @@ -199,12 +199,12 @@ func (e cargoLowerExecutor) trackingBottomObstacle(ctx context.Context, inputs c // If the bottom distance is greater than the exit distance, we run motor again if bottomDistance >= obstacleTracking.ExitDistance && !isMotorRunning { - e.log.Info("obstacle cleared, running motor again", slog.Uint64("bottom_distance", uint64(bottomDistance))) + e.log.InfoContext(ctx, "obstacle cleared, running motor again", slog.Uint64("bottom_distance", uint64(bottomDistance))) if err := e.liftMotorService.SetCargoPosition(ctx, liftmotor.SetCargoPositionParams{ MotorSpeed: inputs.MotorSpeed, Position: inputs.Position, }); err != nil { - e.log.Error("failed to set cargo position", slog.Any("error", err)) + e.log.ErrorContext(ctx, "failed to set cargo position", slog.Any("error", err)) } isMotorRunning = true @@ -221,7 +221,7 @@ func (e cargoLowerExecutor) isLowerPositionReached(current, target uint16) bool func (e cargoLowerExecutor) getRequiredStableReadCount(ctx context.Context) int { commandCfg, err := e.configService.GetCommandConfig(ctx) if err != nil { - e.log.Error("failed to get command config", slog.Any("error", err)) + e.log.ErrorContext(ctx, "failed to get command config", slog.Any("error", err)) return 1 } return int(commandCfg.CargoLower.StableReadCount) @@ -230,7 +230,7 @@ func (e cargoLowerExecutor) getRequiredStableReadCount(ctx context.Context) int func (e cargoLowerExecutor) getObstacleTracking(ctx context.Context) (config.ObstacleTracking, error) { commandCfg, err := e.configService.GetCommandConfig(ctx) if err != nil { - e.log.Error("failed to get command config", slog.Any("error", err)) + e.log.ErrorContext(ctx, "failed to get command config", slog.Any("error", err)) return config.ObstacleTracking{ EnterDistance: 10, ExitDistance: 20, diff --git a/internal/services/command/executor/cargo_open_executor.go b/internal/services/command/executor/cargo_open_executor.go index eb08c5f5..af737913 100644 --- a/internal/services/command/executor/cargo_open_executor.go +++ b/internal/services/command/executor/cargo_open_executor.go @@ -67,21 +67,21 @@ func (e cargoOpenExecutor) OnCancel(_ context.Context) error { func (e cargoOpenExecutor) trackingCargoDoorUntilOpen(ctx context.Context) { ctx, cancel := context.WithCancel(ctx) defer func() { - e.log.Info("stop tracking cargo door open") + e.log.InfoContext(ctx, "stop tracking cargo door open") cancel() }() doneCh := make(chan struct{}) - e.log.Info("start tracking cargo door open") + e.log.InfoContext(ctx, "start tracking cargo door open") e.subscriber.Subscribe(ctx, events.CargoDoorUpdatedTopic, func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.CargoDoorUpdatedEvent) if !ok { - e.log.Error("invalid event", slog.Any("event", msg.Payload)) + e.log.ErrorContext(ctx, "invalid event", slog.Any("event", msg.Payload)) return } if ev.IsOpen { - e.log.Info("cargo door open completed") + e.log.InfoContext(ctx, "cargo door open completed") close(doneCh) } }) diff --git a/internal/services/command/executor/move_to_executor.go b/internal/services/command/executor/move_to_executor.go index a63b3a78..3ee8db0b 100644 --- a/internal/services/command/executor/move_to_executor.go +++ b/internal/services/command/executor/move_to_executor.go @@ -77,21 +77,21 @@ func (e moveToExecutor) OnCancel(ctx context.Context) error { func (e moveToExecutor) trackingLocationUntilReached(ctx context.Context, location string) { ctx, cancel := context.WithCancel(ctx) defer func() { - e.log.Info("stop tracking location", slog.String("location", location)) + e.log.InfoContext(ctx, "stop tracking location", slog.String("location", location)) cancel() }() doneCh := make(chan struct{}) - e.log.Info("start tracking location", slog.String("target_location", location)) + e.log.InfoContext(ctx, "start tracking location", slog.String("target_location", location)) e.subscriber.Subscribe(ctx, events.LocationUpdatedTopic, func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.LocationUpdatedEvent) if !ok { - e.log.Error("invalid event", slog.Any("event", msg.Payload)) + e.log.ErrorContext(ctx, "invalid event", slog.Any("event", msg.Payload)) return } if ev.Location == location { - e.log.Info("location reached", slog.String("location", ev.Location)) + e.log.InfoContext(ctx, "location reached", slog.String("location", ev.Location)) close(doneCh) } }) diff --git a/internal/services/command/executor/scan_location_executor.go b/internal/services/command/executor/scan_location_executor.go index 0214c62c..f772dde5 100644 --- a/internal/services/command/executor/scan_location_executor.go +++ b/internal/services/command/executor/scan_location_executor.go @@ -69,18 +69,18 @@ func (e scanLocationExecutor) OnCancel(ctx context.Context) error { func (e scanLocationExecutor) recordLocationsUntilLoopedBack(ctx context.Context) []command.Location { ctx, cancel := context.WithCancel(ctx) defer func() { - e.log.Info("stop recording location") + e.log.InfoContext(ctx, "stop recording location") cancel() }() locs := []command.Location{} doneCh := make(chan struct{}) - e.log.Info("start recording location") + e.log.InfoContext(ctx, "start recording location") e.subscriber.Subscribe(ctx, events.LocationUpdatedTopic, func(msg *eventbus.Message) { ev, ok := msg.Payload.(events.LocationUpdatedEvent) if !ok { - e.log.Error("invalid event", slog.Any("event", msg.Payload)) + e.log.ErrorContext(ctx, "invalid event", slog.Any("event", msg.Payload)) return } @@ -90,7 +90,7 @@ func (e scanLocationExecutor) recordLocationsUntilLoopedBack(ctx context.Context return } - e.log.Info("record location", slog.String("location", ev.Location)) + e.log.InfoContext(ctx, "record location", slog.String("location", ev.Location)) locs = append(locs, command.Location{ Location: ev.Location, ScannedAt: time.Now(), diff --git a/internal/services/command/executor/service.go b/internal/services/command/executor/service.go index 73a8d475..83d3878a 100644 --- a/internal/services/command/executor/service.go +++ b/internal/services/command/executor/service.go @@ -150,7 +150,7 @@ func (s *service) execute(ctx context.Context, cmd command.Command) (command.Out runningCmd := command.NewCancelableCommand(ctx, cmd) defer func() { if err := s.runningCommandRepository.Remove(ctx); err != nil { - s.log.Error("failed to remove running command", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to remove running command", slog.Any("error", err)) } }() @@ -177,7 +177,7 @@ func (s *service) execute(ctx context.Context, cmd command.Command) (command.Out func (s *service) runCancelHook(ctx context.Context, cmd command.Command) error { c, ok := s.cancelableMap[cmd.Type] if !ok { - s.log.Error("cancelable executor not found", slog.Any("command_type", cmd.Type)) + s.log.ErrorContext(ctx, "cancelable executor not found", slog.Any("command_type", cmd.Type)) return nil } if err := c.OnCancel(ctx); err != nil { @@ -188,8 +188,11 @@ func (s *service) runCancelHook(ctx context.Context, cmd command.Command) error } func (s *service) handleSuccess(ctx context.Context, id int64, outputs command.Outputs) error { - log := s.log.With(slog.Int64("command_id", id), slog.Any("outputs", outputs)) - log.Info("command executed successfully") + log := s.log.With( + slog.Int64("command_id", id), + slog.Any("outputs", outputs), + ) + log.InfoContext(ctx, "command executed successfully") now := time.Now() _, err := s.commandRepository.UpdateCommand(ctx, command.UpdateCommandParams{ @@ -212,7 +215,7 @@ func (s *service) handleSuccess(ctx context.Context, id int64, outputs command.O func (s *service) handleCancel(ctx context.Context, id int64, outputs command.Outputs) error { log := s.log.With(slog.Int64("command_id", id)) - log.Info("command cancelled") + log.InfoContext(ctx, "command cancelled") now := time.Now() _, err := s.commandRepository.UpdateCommand(ctx, command.UpdateCommandParams{ @@ -233,8 +236,11 @@ func (s *service) handleCancel(ctx context.Context, id int64, outputs command.Ou } func (s *service) handleFailure(ctx context.Context, id int64, execErr error) error { - log := s.log.With(slog.Int64("command_id", id), slog.Any("exec_error", execErr)) - log.Error("command execution failed") + log := s.log.With( + slog.Int64("command_id", id), + slog.Any("exec_error", execErr), + ) + log.ErrorContext(ctx, "command execution failed") now := time.Now() _, err := s.commandRepository.UpdateCommand(ctx, command.UpdateCommandParams{ diff --git a/internal/services/led/ledimpl/service.go b/internal/services/led/ledimpl/service.go index d5e9ca12..34d5a659 100644 --- a/internal/services/led/ledimpl/service.go +++ b/internal/services/led/ledimpl/service.go @@ -40,12 +40,12 @@ func NewService( func (s *Service) Start(ctx context.Context) { systemLed, err := ledh.New(s.cfg.System.Pin) if err != nil { - s.log.Error("failed to create system led", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to create system led", slog.Any("error", err)) if err := s.repository.UpdateSystemLedConnection(ctx, led.Connection{ Connected: false, Error: ptr.New(err.Error()), }); err != nil { - s.log.Error("failed to update system led connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update system led connection", slog.Any("error", err)) } } else { s.systemLed = systemLed @@ -53,18 +53,18 @@ func (s *Service) Start(ctx context.Context) { Connected: true, LastConnectedAt: ptr.New(time.Now()), }); err != nil { - s.log.Error("failed to update system led connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update system led connection", slog.Any("error", err)) } } alertLed, err := ledh.New(s.cfg.Alert.Pin) if err != nil { - s.log.Error("failed to create alert led", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to create alert led", slog.Any("error", err)) if err := s.repository.UpdateAlertLedConnection(ctx, led.Connection{ Connected: false, Error: ptr.New(err.Error()), }); err != nil { - s.log.Error("failed to update alert led connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update alert led connection", slog.Any("error", err)) } } else { s.alertLed = alertLed @@ -72,16 +72,16 @@ func (s *Service) Start(ctx context.Context) { Connected: true, LastConnectedAt: ptr.New(time.Now()), }); err != nil { - s.log.Error("failed to update alert led connection", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update alert led connection", slog.Any("error", err)) } } if err := s.SetSystemLedOn(ctx); err != nil { - s.log.Error("failed to set system led on", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to set system led on", slog.Any("error", err)) } if err = s.SetAlertLedOff(ctx); err != nil { - s.log.Error("failed to set alert led on", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to set alert led on", slog.Any("error", err)) } } @@ -142,7 +142,7 @@ func (s *Service) BlinkSystemLed(ctx context.Context, params led.BlinkSystemLedP Mode: led.ModeOff, UpdatedAt: time.Now(), }); err != nil { - s.log.Error("failed to update system led state", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update system led state", slog.Any("error", err)) } }() @@ -211,7 +211,7 @@ func (s *Service) BlinkAlertLed(ctx context.Context, params led.BlinkAlertLedPar Mode: led.ModeOff, UpdatedAt: time.Now(), }); err != nil { - s.log.Error("failed to update alert led state", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to update alert led state", slog.Any("error", err)) } }() diff --git a/internal/services/limitswitch/limitswitchimpl/service.go b/internal/services/limitswitch/limitswitchimpl/service.go index afef669f..0dceb9e0 100644 --- a/internal/services/limitswitch/limitswitchimpl/service.go +++ b/internal/services/limitswitch/limitswitchimpl/service.go @@ -26,7 +26,7 @@ func NewService( repo limitswitch.Repository, ) limitswitch.Service { return &Service{ - log: log.With("service", "limitswitch"), + log: log.With(slog.String("service", "limitswitch")), validator: validator, publisher: publisher, repo: repo, @@ -71,7 +71,7 @@ func (s Service) UpdateLimitSwitchByID(ctx context.Context, params limitswitch.U return nil } -func (s Service) publishLimitSwitchPressedEvent(_ context.Context, id limitswitch.LimitSwitchID, pressedAt time.Time) { +func (s Service) publishLimitSwitchPressedEvent(ctx context.Context, id limitswitch.LimitSwitchID, pressedAt time.Time) { switch id { case limitswitch.LimitSwitchID1: s.publisher.Publish(events.LimitSwitch1PressedTopic, &eventbus.Message{ @@ -81,6 +81,6 @@ func (s Service) publishLimitSwitchPressedEvent(_ context.Context, id limitswitc }) default: - s.log.Error("invalid limit switch id", slog.Any("id", id)) + s.log.ErrorContext(ctx, "invalid limit switch id", slog.Any("id", id)) } } diff --git a/internal/services/monitoring/monitoringimpl/service.go b/internal/services/monitoring/monitoringimpl/service.go index 96aa7f73..551ab1c8 100644 --- a/internal/services/monitoring/monitoringimpl/service.go +++ b/internal/services/monitoring/monitoringimpl/service.go @@ -82,7 +82,7 @@ func (s *Service) startMonitorBattery(ctx context.Context) error { pollingFunc := func() { state, err := s.batteryRepo.GetBatteryState(ctx) if err != nil { - s.log.Error("failed to get battery state", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to get battery state", slog.Any("error", err)) return } @@ -92,7 +92,7 @@ func (s *Service) startMonitorBattery(ctx context.Context) error { cfg, err := s.configService.GetBatteryMonitoringConfig(ctx) if err != nil { - s.log.Error("failed to get battery monitoring config", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to get battery monitoring config", slog.Any("error", err)) return } @@ -290,14 +290,14 @@ func (s *Service) handleBatteryAlarm(ctx context.Context, data alarm.BatteryData ActivatedAt: time.Now(), }) if err != nil { - s.log.Error("failed to create battery alarm", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to create battery alarm", slog.Any("error", err)) } if err := s.systemService.SetStatusError(ctx); err != nil { - s.log.Error("failed to set system status error due to alarm", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to set system status error due to alarm", slog.Any("error", err)) } if err := s.batteryService.DisableCharge(ctx); err != nil { - s.log.Error("failed to disable charge due to alarm", slog.Any("error", err)) + s.log.ErrorContext(ctx, "failed to disable charge due to alarm", slog.Any("error", err)) } } diff --git a/internal/services/wifi/wifiimpl/service.go b/internal/services/wifi/wifiimpl/service.go index 8a646976..683b4b1f 100644 --- a/internal/services/wifi/wifiimpl/service.go +++ b/internal/services/wifi/wifiimpl/service.go @@ -24,7 +24,7 @@ type service struct { func NewService(cfg config.Wifi, log *slog.Logger) wifi.Service { return &service{ cfg: cfg, - log: log.With("service", "wifi"), + log: log.With(slog.String("service", "wifi")), } } diff --git a/internal/storage/db/db.go b/internal/storage/db/db.go index 2321f1ac..23a59457 100644 --- a/internal/storage/db/db.go +++ b/internal/storage/db/db.go @@ -43,7 +43,7 @@ func NewSQLiteDB(path string) (*SQLiteDB, error) { } func (p *SQLiteDB) WithTX(ctx context.Context, fn func(DB) error) (err error) { - tx, err := p.DB.BeginTx(ctx, nil) + tx, err := p.BeginTx(ctx, nil) if err != nil { return fmt.Errorf("begin tx: %w", err) } diff --git a/pkg/eventbus/inproc.go b/pkg/eventbus/inproc.go index 102fdc63..a75b2419 100644 --- a/pkg/eventbus/inproc.go +++ b/pkg/eventbus/inproc.go @@ -17,7 +17,7 @@ type InProcEventBus struct { func NewInProcEventBus(log *slog.Logger) *InProcEventBus { return &InProcEventBus{ - log: log.With("component", "inproc_event_bus"), + log: log.With(slog.String("component", "inproc_event_bus")), subscribers: make(map[string][]*subscriber), } } @@ -46,7 +46,7 @@ func (e *InProcEventBus) Publish(topic string, message *Message) { go func(sub *subscriber) { defer func() { if r := recover(); r != nil { - e.log.Error("recovered panic in subscriber", slog.Any("error", r)) + e.log.ErrorContext(context.TODO(), "recovered panic in subscriber", slog.Any("error", r)) } }()