Last batch of error logging

This commit is contained in:
Jonathon Leight
2026-07-05 15:54:07 -04:00
parent 63222ab837
commit d19ff35f50
3 changed files with 27 additions and 9 deletions
+10 -3
View File
@@ -10,6 +10,7 @@ import (
"context"
"crypto/sha256"
"encoding/hex"
"log/slog"
"net"
"net/http"
"strings"
@@ -60,7 +61,9 @@ func (rec *Recorder) Run(ctx context.Context) {
if len(batch) == 0 {
return
}
_ = rec.st.InsertAnalyticsEvents(c, batch)
if err := rec.st.InsertAnalyticsEvents(c, batch); err != nil {
slog.Error("analytics: insert events", "count", len(batch), "err", err)
}
batch = batch[:0]
}
for {
@@ -86,8 +89,12 @@ func (rec *Recorder) Run(ctx context.Context) {
}
func (rec *Recorder) rollup(ctx context.Context) {
_ = rec.st.RollupAnalytics(ctx)
_ = rec.st.PruneAnalytics(ctx, retentionDays)
if err := rec.st.RollupAnalytics(ctx); err != nil {
slog.Error("analytics: rollup", "err", err)
}
if err := rec.st.PruneAnalytics(ctx, retentionDays); err != nil {
slog.Error("analytics: prune", "err", err)
}
}
// Handler wraps a handler, recording each request that isn't filtered out. A nil
+4 -1
View File
@@ -15,6 +15,7 @@ import (
"github.com/meshcore-go/meshcore-go/hardware"
"github.com/jleight/meshtender/internal/mesh"
"github.com/jleight/meshtender/internal/web"
"github.com/jleight/meshtender/internal/wsbridge"
)
@@ -92,7 +93,7 @@ func (s *Handlers) wsConfirm(w http.ResponseWriter, r *http.Request) {
}
repeaterID, err := meshcore.NewIdentityFromHex(rep.PublicKeyHex)
if err != nil {
http.Error(w, "stored repeater key invalid", http.StatusInternalServerError)
s.ServerError(w, r, "stored repeater key invalid", err)
return
}
@@ -203,6 +204,7 @@ func (s *Handlers) wsConfirm(w http.ResponseWriter, r *http.Request) {
}
if err := s.Store.SetRepeaterConfirmed(ctx, id, uid, lr.IsAdmin, int16(lr.Permissions)); err != nil {
web.LogError(r, "confirm: save confirmation", err, "repeater_id", id)
_ = bridge.Status("error", "could not save confirmation: "+err.Error())
return
}
@@ -255,6 +257,7 @@ func (s *Handlers) wsConfirm(w http.ResponseWriter, r *http.Request) {
})
if okLat && okLon {
if err := s.Store.SetRepeaterLocation(ctx, id, lat, lon); err != nil {
web.LogError(r, "confirm: store location", err, "repeater_id", id)
_ = bridge.Status("error", "could not store location: "+err.Error())
} else {
_ = bridge.Status("info", fmt.Sprintf("Stored location: %.5f, %.5f", lat, lon))
+13 -5
View File
@@ -16,6 +16,7 @@ import (
"github.com/jleight/meshtender/internal/mesh"
"github.com/jleight/meshtender/internal/store"
"github.com/jleight/meshtender/internal/web"
"github.com/jleight/meshtender/internal/wsbridge"
)
@@ -148,7 +149,7 @@ func (s *Handlers) pageConsole(w http.ResponseWriter, r *http.Request) {
}
catalog, err := s.Store.ListCommands(r.Context())
if err != nil {
http.Error(w, "could not load commands", http.StatusInternalServerError)
s.ServerError(w, r, "could not load commands", err)
return
}
allowed := s.allowedCommands(r.Context(), rep, uid, catalog)
@@ -174,12 +175,12 @@ func (s *Handlers) wsConsole(w http.ResponseWriter, r *http.Request) {
}
repeaterID, err := meshcore.NewIdentityFromHex(rep.PublicKeyHex)
if err != nil {
http.Error(w, "stored repeater key invalid", http.StatusInternalServerError)
s.ServerError(w, r, "stored repeater key invalid", err)
return
}
catalog, err := s.Store.ListCommands(r.Context())
if err != nil {
http.Error(w, "could not load commands", http.StatusInternalServerError)
s.ServerError(w, r, "could not load commands", err)
return
}
@@ -208,6 +209,7 @@ func (s *Handlers) wsConsole(w http.ResponseWriter, r *http.Request) {
// Group this connection's commands into a session (required for logging).
sessionID, err := s.Store.StartConsoleSession(ctx, id, uid)
if err != nil {
web.LogError(r, "console: start session", err, "repeater_id", id)
_ = bridge.Status("error", "could not start session")
return
}
@@ -311,6 +313,7 @@ func (s *Handlers) wsConsole(w http.ResponseWriter, r *http.Request) {
}
allowed, err := s.Store.CanSendCommand(ctx, uid, id, cmd.ID)
if err != nil {
web.LogError(r, "console: permission check", err, "repeater_id", id, "command_id", cmd.ID)
_ = bridge.Status("error", "permission check failed")
return
}
@@ -319,7 +322,10 @@ func (s *Handlers) wsConsole(w http.ResponseWriter, r *http.Request) {
return
}
logID, _ := s.Store.LogCommand(ctx, id, uid, sessionID, cmd.ID, text)
logID, err := s.Store.LogCommand(ctx, id, uid, sessionID, cmd.ID, text)
if err != nil {
web.LogError(r, "console: log command", err, "repeater_id", id, "command_id", cmd.ID)
}
reply, err := ex.Command(ctx, text, func(attempt, max int) {
if attempt == 1 {
@@ -331,7 +337,9 @@ func (s *Handlers) wsConsole(w http.ResponseWriter, r *http.Request) {
switch {
case err == nil:
if logID != 0 {
_ = s.Store.MarkCommandReply(ctx, logID, reply)
if err := s.Store.MarkCommandReply(ctx, logID, reply); err != nil {
web.LogError(r, "console: mark command reply", err, "log_id", logID)
}
}
_ = bridge.Status("reply", reply)
case errors.Is(err, mesh.ErrNoReply):