v0.83.0: observability pass — always-DEBUG capture ring + GET /debug/logs + heartbeat log-pull + gap-fill sweep
Capture layer: applog.New returns (logger, Ring) — slog fan-out, stderr at the configured level, ~1000-entry ring fixed at LevelDebug (remote diagnostics without a config flip). GET /debug/logs (token-authed, ?raw=1) + request-level DEBUG middleware. Heartbeat log-pull mirrors the report logtail pattern: envelope log_tail_requested -> next heartbeat carries log_tail (128KB cap, consume-once, failed-push retry proven). Gap-fill sweep over netverify/ netstorage/netmount/signedjobs/selfupdate/disks/controller-swap/desired/loop. Red-proofs: ring-at-emit-level FAILs capture test; drain removed FAILs consume-once; dropped phase line FAILs the S7 log-sequence smoke. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -127,12 +127,15 @@ func (s *Server) handleNetStorageAdd(w http.ResponseWriter, r *http.Request, vmi
|
||||
if !s.netReachable(spec.Protocol, spec.Server) {
|
||||
s.releaseNetVerify(job)
|
||||
s.logger.Warn("local-api: network mount refused — endpoint not reachable",
|
||||
"name", spec.Name, "server", spec.Server, "proto", spec.Protocol)
|
||||
"name", spec.Name, "server", spec.Server, "proto", spec.Protocol,
|
||||
"code", storage.NetVerifyUnreachable)
|
||||
writeStatus(w, http.StatusBadGateway, false,
|
||||
map[string]any{"code": storage.NetVerifyUnreachable},
|
||||
"NAS endpoint not reachable")
|
||||
return
|
||||
}
|
||||
s.logger.Debug("local-api: NAS endpoint pre-probe passed",
|
||||
"name", spec.Name, "server", spec.Server, "proto", spec.Protocol)
|
||||
|
||||
// SMB: stage the credentials out-of-band (0600). NFS needs none (server squash).
|
||||
if spec.Protocol == storage.ProtocolSMB {
|
||||
@@ -144,6 +147,7 @@ func (s *Server) handleNetStorageAdd(w http.ResponseWriter, r *http.Request, vmi
|
||||
return
|
||||
}
|
||||
spec.CredsRef = credsPath
|
||||
s.logger.Debug("local-api: SMB credentials staged", "name", spec.Name, "path", credsPath) // path only, never content
|
||||
}
|
||||
|
||||
if err := s.netStorage.EnsureNetworkMount(r.Context(), spec); err != nil {
|
||||
@@ -251,7 +255,9 @@ func (s *Server) writeSMBCreds(name, username, password string) (string, error)
|
||||
|
||||
// removeSMBCreds deletes a share's creds file (best-effort; absent is fine).
|
||||
func (s *Server) removeSMBCreds(name string) {
|
||||
_ = os.Remove(s.smbCredsPath(name))
|
||||
if err := os.Remove(s.smbCredsPath(name)); err == nil {
|
||||
s.logger.Debug("local-api: SMB credentials file removed", "name", name, "path", s.smbCredsPath(name))
|
||||
}
|
||||
}
|
||||
|
||||
// smbCredsPath computes a share's creds file path (pure — used by validation BEFORE the file exists).
|
||||
|
||||
Reference in New Issue
Block a user