From 4f78bfe7440084e73e4ce0cce69655de17bdbc6a Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 26 Aug 2025 09:22:25 +0000 Subject: [PATCH] feat: suppress console spam for expected HTTP errors - Change server switching logs to debug level - Implement structured error logging for profile operations - Handle common HTTP status codes gracefully - Maintain user notifications while cleaning console output --- src/views/AccountViewView.vue | 143 +++++++++++++++++++++++++++++++--- 1 file changed, 133 insertions(+), 10 deletions(-) diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index 3ae1ccee..e68efca2 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -1496,7 +1496,7 @@ export default class AccountViewView extends Vue { const previousApiServer = this.apiServer; const newApiServer = this.apiServerInput; - logger.info("[Server Switching] Claim URL change initiated:", { + logger.debug("[Server Switching] Claim URL change initiated:", { did: this.activeDid, previousServer: previousApiServer, newServer: newApiServer, @@ -1515,7 +1515,7 @@ export default class AccountViewView extends Vue { }); // Log successful server switch - logger.info("[Server Switching] Claim URL change completed:", { + logger.debug("[Server Switching] Claim URL change completed:", { did: this.activeDid, previousServer: previousApiServer, newServer: newApiServer, @@ -1530,7 +1530,7 @@ export default class AccountViewView extends Vue { const previousPartnerServer = this.partnerApiServer; const newPartnerServer = this.partnerApiServerInput; - logger.info("[Server Switching] Partner server change initiated:", { + logger.debug("[Server Switching] Partner server change initiated:", { did: this.activeDid, previousServer: previousPartnerServer, newServer: newPartnerServer, @@ -1548,7 +1548,7 @@ export default class AccountViewView extends Vue { }); // Log successful partner server switch - logger.info("[Server Switching] Partner server change completed:", { + logger.debug("[Server Switching] Partner server change completed:", { did: this.activeDid, previousServer: previousPartnerServer, newServer: newPartnerServer, @@ -1935,18 +1935,54 @@ export default class AccountViewView extends Vue { return null; } catch (error: unknown) { - // Handle specific HTTP status codes + // Handle specific HTTP status codes cleanly to suppress console spam if (error && typeof error === "object" && "response" in error) { const axiosError = error as { response?: { status?: number } }; + if (axiosError.response?.status === 404) { - logger.debug( - "[AccountViewView] Profile not found (404) - this is normal for new users", + logger.info( + "[Profile] No profile found - this is normal for new users", + { + did, + server: this.partnerApiServer, + status: 404, + timestamp: new Date().toISOString(), + }, ); return null; } + + if (axiosError.response?.status === 400) { + logger.warn("[Profile] Bad request - user may not be registered", { + did, + server: this.partnerApiServer, + status: 400, + timestamp: new Date().toISOString(), + }); + return null; + } + + if ( + axiosError.response?.status === 401 || + axiosError.response?.status === 403 + ) { + logger.warn("[Profile] Authentication/authorization issue", { + did, + server: this.partnerApiServer, + status: axiosError.response.status, + timestamp: new Date().toISOString(), + }); + return null; + } } - logger.error("[AccountViewView] Failed to load profile:", error); + // Only log full errors for unexpected issues (5xx, network errors, etc.) + logger.error("[Profile] Unexpected error loading profile:", { + did, + server: this.partnerApiServer, + error: error instanceof Error ? error.message : String(error), + timestamp: new Date().toISOString(), + }); throw new Error("Failed to load profile"); } } @@ -2003,7 +2039,54 @@ export default class AccountViewView extends Vue { return true; } catch (error: unknown) { - logger.error("[AccountViewView] Failed to save profile:", error); + // Handle specific HTTP status codes cleanly to suppress console spam + if (error && typeof error === "object" && "response" in error) { + const axiosError = error as { response?: { status?: number } }; + + if (axiosError.response?.status === 400) { + logger.warn("[Profile] Bad request saving profile", { + did, + server: this.partnerApiServer, + status: 400, + timestamp: new Date().toISOString(), + }); + throw new Error("Invalid profile data"); + } + + if ( + axiosError.response?.status === 401 || + axiosError.response?.status === 403 + ) { + logger.warn( + "[Profile] Authentication/authorization issue saving profile", + { + did, + server: this.partnerApiServer, + status: axiosError.response.status, + timestamp: new Date().toISOString(), + }, + ); + throw new Error("Authentication required"); + } + + if (axiosError.response?.status === 409) { + logger.warn("[Profile] Profile conflict - may already exist", { + did, + server: this.partnerApiServer, + status: 409, + timestamp: new Date().toISOString(), + }); + throw new Error("Profile already exists"); + } + } + + // Only log full errors for unexpected issues + logger.error("[Profile] Unexpected error saving profile:", { + did, + server: this.partnerApiServer, + error: error instanceof Error ? error.message : String(error), + timestamp: new Date().toISOString(), + }); throw new Error("Failed to save profile"); } } @@ -2072,7 +2155,47 @@ export default class AccountViewView extends Vue { return true; } catch (error: unknown) { - logger.error("[AccountViewView] Failed to delete profile:", error); + // Handle specific HTTP status codes cleanly to suppress console spam + if (error && typeof error === "object" && "response" in error) { + const axiosError = error as { response?: { status?: number } }; + + if (axiosError.response?.status === 404) { + logger.info( + "[Profile] Profile not found for deletion - may already be deleted", + { + did, + server: this.partnerApiServer, + status: 404, + timestamp: new Date().toISOString(), + }, + ); + return true; // Consider it successful if already deleted + } + + if ( + axiosError.response?.status === 401 || + axiosError.response?.status === 403 + ) { + logger.warn( + "[Profile] Authentication/authorization issue deleting profile", + { + did, + server: this.partnerApiServer, + status: axiosError.response.status, + timestamp: new Date().toISOString(), + }, + ); + return false; + } + } + + // Only log full errors for unexpected issues + logger.error("[Profile] Unexpected error deleting profile:", { + did, + server: this.partnerApiServer, + error: error instanceof Error ? error.message : String(error), + timestamp: new Date().toISOString(), + }); return false; } }