feat(logging): enhance debug logging across app
Improves application logging and error tracking: - Add structured logging in main.common.ts for app initialization - Enhance API error handling with detailed context in services - Add deep link debugging in Capacitor platform - Improve plan service logging with retry information - Update endorser server logs for better cache debugging Technical changes: - Replace console.error with info for non-critical cache misses - Add component context to global error handler - Add detailed logging for plan loading and retries - Improve deep link route matching logs - Add mount state logging for Capacitor This improves debugging capabilities across web and mobile platforms.
This commit is contained in:
@@ -649,19 +649,19 @@ export async function getPlanFromCache(
|
||||
cred = resp.data.data[0];
|
||||
planCache.set(handleId, cred);
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to load plan with handle",
|
||||
console.info(
|
||||
"[EndorserServer] Plan cache is empty for handle",
|
||||
handleId,
|
||||
" Got data:",
|
||||
resp.data,
|
||||
JSON.stringify(resp.data),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"Failed to load plan with handle",
|
||||
"[EndorserServer] Failed to load plan with handle",
|
||||
handleId,
|
||||
" Got error:",
|
||||
error,
|
||||
JSON.stringify(error),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ import { handleApiError } from "./services/api";
|
||||
import { loadPlanWithRetry } from "./services/plan";
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
|
||||
console.log("[Capacitor] Starting initialization");
|
||||
console.log("[Capacitor] Platform:", process.env.VITE_PLATFORM);
|
||||
|
||||
const app = initializeApp();
|
||||
|
||||
// Store initial deep link if app is not ready
|
||||
@@ -20,44 +23,32 @@ window.addEventListener('unhandledrejection', (event) => {
|
||||
// Create reusable handler function
|
||||
const handleDeepLink = async (data: { url: string }) => {
|
||||
try {
|
||||
if (Capacitor.isNativePlatform()) {
|
||||
console.log("[Capacitor Deep Link] START Handler");
|
||||
console.log("[Capacitor Deep Link] Received URL:", data.url);
|
||||
console.log("[Capacitor Deep Link] START Handler");
|
||||
console.log("[Capacitor Deep Link] Received URL:", data.url);
|
||||
|
||||
// Wait for router to be ready
|
||||
await router.isReady();
|
||||
|
||||
// Parse the custom URL scheme
|
||||
const parts = data.url.split('://');
|
||||
if (parts.length !== 2) {
|
||||
throw new Error('Invalid URL format');
|
||||
}
|
||||
|
||||
// Wait for app to be mounted
|
||||
if (!app._container) {
|
||||
console.log("[Capacitor Deep Link] Waiting for app mount");
|
||||
await new Promise<void>((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
if (app._container) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
const url = new URL(data.url);
|
||||
const path = url.pathname.substring(1);
|
||||
|
||||
if (Capacitor.isNativePlatform()) {
|
||||
console.log("[Capacitor Deep Link] Parsed path:", path);
|
||||
}
|
||||
const path = parts[1]; // This will be "claim/01JMAAFZRNSRTQ0EBSD70A8E1H"
|
||||
console.log("[Capacitor Deep Link] Parsed path:", path);
|
||||
|
||||
// Map parameterized routes
|
||||
const paramRoutes = {
|
||||
'claim': /^claim\/(.+)$/,
|
||||
'claim': /^claim\/(.+)$/, // Updated pattern without leading slash
|
||||
};
|
||||
|
||||
// Check if path matches any parameterized route
|
||||
for (const [routeName, pattern] of Object.entries(paramRoutes)) {
|
||||
const match = path.match(pattern);
|
||||
if (match) {
|
||||
if (Capacitor.isNativePlatform()) {
|
||||
console.log(`[Capacitor Deep Link] Matched route: ${routeName}, param: ${match[1]}`);
|
||||
}
|
||||
await router.push({
|
||||
console.log(`[Capacitor Deep Link] Matched route: ${routeName}, param: ${match[1]}`);
|
||||
await router.replace({
|
||||
name: routeName,
|
||||
params: { id: match[1] }
|
||||
});
|
||||
@@ -65,7 +56,7 @@ const handleDeepLink = async (data: { url: string }) => {
|
||||
}
|
||||
}
|
||||
|
||||
await router.push('/' + path);
|
||||
await router.replace('/' + path);
|
||||
} catch (error) {
|
||||
console.error("[Capacitor Deep Link] Error:", error);
|
||||
handleApiError(error, 'deep-link');
|
||||
@@ -75,5 +66,6 @@ const handleDeepLink = async (data: { url: string }) => {
|
||||
// Register listener
|
||||
App.addListener("appUrlOpen", handleDeepLink);
|
||||
|
||||
// Mount app
|
||||
console.log("[Capacitor] Mounting app");
|
||||
app.mount("#app");
|
||||
console.log("[Capacitor] App mounted");
|
||||
@@ -11,12 +11,17 @@ import Camera from "simple-vue-camera";
|
||||
|
||||
// Global Error Handler
|
||||
function setupGlobalErrorHandler(app: VueApp) {
|
||||
console.log("[App Init] Setting up global error handler");
|
||||
app.config.errorHandler = (
|
||||
err: unknown,
|
||||
instance: ComponentPublicInstance | null,
|
||||
info: string
|
||||
) => {
|
||||
console.error("Ouch! Global Error Handler.", err, info, instance);
|
||||
console.error("[App Error] Global Error Handler:", {
|
||||
error: err,
|
||||
info,
|
||||
component: instance?.$options.name || 'unknown'
|
||||
});
|
||||
alert(
|
||||
(err instanceof Error ? err.message : "Something bad happened") +
|
||||
" - Try reloading or restarting the app."
|
||||
@@ -26,15 +31,31 @@ function setupGlobalErrorHandler(app: VueApp) {
|
||||
|
||||
// Function to initialize the app
|
||||
export function initializeApp() {
|
||||
const app = createApp(App)
|
||||
.component("fa", FontAwesomeIcon)
|
||||
.component("camera", Camera)
|
||||
.use(createPinia())
|
||||
.use(VueAxios, axios)
|
||||
.use(router)
|
||||
.use(Notifications);
|
||||
console.log("[App Init] Starting app initialization");
|
||||
console.log("[App Init] Platform:", process.env.VITE_PLATFORM);
|
||||
|
||||
const app = createApp(App);
|
||||
console.log("[App Init] Vue app created");
|
||||
|
||||
app.component("fa", FontAwesomeIcon)
|
||||
.component("camera", Camera);
|
||||
console.log("[App Init] Components registered");
|
||||
|
||||
const pinia = createPinia();
|
||||
app.use(pinia);
|
||||
console.log("[App Init] Pinia store initialized");
|
||||
|
||||
app.use(VueAxios, axios);
|
||||
console.log("[App Init] Axios initialized");
|
||||
|
||||
app.use(router);
|
||||
console.log("[App Init] Router initialized");
|
||||
|
||||
app.use(Notifications);
|
||||
console.log("[App Init] Notifications initialized");
|
||||
|
||||
setupGlobalErrorHandler(app);
|
||||
console.log("[App Init] App initialization complete");
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
export const handleApiError = (error: any, endpoint: string) => {
|
||||
if (process.env.VITE_PLATFORM === 'capacitor') {
|
||||
console.error(`[Capacitor API Error] ${endpoint}:`, error);
|
||||
console.error(`[Capacitor API Error] ${endpoint}:`, {
|
||||
message: error.message,
|
||||
status: error.response?.status,
|
||||
data: error.response?.data,
|
||||
config: {
|
||||
url: error.config?.url,
|
||||
method: error.config?.method,
|
||||
headers: error.config?.headers
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Specific handling for rate limits
|
||||
|
||||
@@ -1,19 +1,71 @@
|
||||
export const loadPlanWithRetry = async (handle: string, retries = 3) => {
|
||||
for (let i = 0; i < retries; i++) {
|
||||
try {
|
||||
const plan = await loadPlan(handle);
|
||||
if (plan) return plan;
|
||||
} catch (err) {
|
||||
console.warn(`[Plan Load] Attempt ${i + 1} failed for ${handle}`);
|
||||
if (i === retries - 1) throw err;
|
||||
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
|
||||
import axios from 'axios';
|
||||
|
||||
interface PlanResponse {
|
||||
data?: any;
|
||||
status?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export const loadPlanWithRetry = async (handle: string, retries = 3): Promise<PlanResponse> => {
|
||||
try {
|
||||
console.log(`[Plan Service] Loading plan ${handle}, attempt 1/${retries}`);
|
||||
console.log(`[Plan Service] Context: Deep link handle=${handle}, isClaimFlow=${handle.includes('claim')}`);
|
||||
|
||||
// Different endpoint if this is a claim flow
|
||||
const response = await loadPlan(handle);
|
||||
console.log(`[Plan Service] Plan ${handle} loaded successfully:`, {
|
||||
status: response?.status,
|
||||
headers: response?.headers,
|
||||
data: response?.data
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
console.error(`[Plan Service] Error loading plan ${handle}:`, {
|
||||
message: error.message,
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
data: error.response?.data,
|
||||
headers: error.response?.headers,
|
||||
config: {
|
||||
url: error.config?.url,
|
||||
method: error.config?.method,
|
||||
baseURL: error.config?.baseURL,
|
||||
headers: error.config?.headers
|
||||
}
|
||||
});
|
||||
|
||||
if (retries > 1) {
|
||||
console.log(`[Plan Service] Retrying plan ${handle}, ${retries-1} attempts remaining`);
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
return loadPlanWithRetry(handle, retries - 1);
|
||||
}
|
||||
|
||||
return {
|
||||
error: `Failed to load plan ${handle} after ${4-retries} attempts: ${error.message}`,
|
||||
status: error.response?.status
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const loadPlan = async (handle: string) => {
|
||||
// Implement your plan loading logic here
|
||||
// This is a placeholder - replace with actual implementation
|
||||
const response = await fetch(`/api/plans/${handle}`);
|
||||
return response.json();
|
||||
export const loadPlan = async (handle: string): Promise<PlanResponse> => {
|
||||
console.log(`[Plan Service] Making API request for plan ${handle}`);
|
||||
|
||||
const endpoint = handle.includes('claim')
|
||||
? `/api/claims/${handle}`
|
||||
: `/api/plans/${handle}`;
|
||||
|
||||
console.log(`[Plan Service] Using endpoint: ${endpoint}`);
|
||||
|
||||
try {
|
||||
const response = await axios.get(endpoint);
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
console.error(`[Plan Service] API request failed for ${handle}:`, {
|
||||
endpoint,
|
||||
error: error.message,
|
||||
response: error.response?.data
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -585,6 +585,7 @@ export default class ClaimView extends Vue {
|
||||
}
|
||||
|
||||
async created() {
|
||||
console.log("ClaimView created");
|
||||
const settings = await retrieveSettingsForActiveAccount();
|
||||
this.activeDid = settings.activeDid || "";
|
||||
this.apiServer = settings.apiServer || "";
|
||||
@@ -659,6 +660,7 @@ export default class ClaimView extends Vue {
|
||||
}
|
||||
|
||||
async loadClaim(claimId: string, userDid: string) {
|
||||
console.log("[ClaimView] loadClaim called with claimId:", claimId);
|
||||
const urlPath = libsUtil.isGlobalUri(claimId)
|
||||
? "/api/claim/byHandle/"
|
||||
: "/api/claim/";
|
||||
@@ -666,6 +668,7 @@ export default class ClaimView extends Vue {
|
||||
const headers = await serverUtil.getHeaders(userDid);
|
||||
|
||||
try {
|
||||
console.log("[ClaimView] Making API request to:", url);
|
||||
const resp = await this.axios.get(url, { headers });
|
||||
if (resp.status === 200) {
|
||||
this.veriClaim = resp.data;
|
||||
|
||||
@@ -17,6 +17,9 @@ export async function createBuildConfig(mode: string) {
|
||||
const isCapacitor = mode === "capacitor";
|
||||
const isPyWebView = mode === "pywebview";
|
||||
|
||||
// Explicitly set platform
|
||||
process.env.VITE_PLATFORM = mode;
|
||||
|
||||
if (isElectron || isPyWebView || isCapacitor) {
|
||||
process.env.VITE_PWA_ENABLED = 'false';
|
||||
}
|
||||
@@ -35,6 +38,7 @@ export async function createBuildConfig(mode: string) {
|
||||
},
|
||||
define: {
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
||||
'process.env.VITE_PLATFORM': JSON.stringify(mode),
|
||||
'process.env.VITE_PWA_ENABLED': JSON.stringify(!(isElectron || isPyWebView || isCapacitor)),
|
||||
__dirname: isElectron ? JSON.stringify(process.cwd()) : '""',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user