Compare commits
1 Commits
platformse
...
logging-up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a622d20b8 |
178
docs/development/debug-logging.md
Normal file
178
docs/development/debug-logging.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# Debug Logging Control
|
||||
|
||||
## Overview
|
||||
|
||||
Debug logging in TimeSafari can be controlled via environment variables to reduce console noise during development and production.
|
||||
|
||||
## Current Behavior
|
||||
|
||||
By default, debug logging is **disabled** to reduce console noise. Debug logs are very verbose and include detailed information about:
|
||||
|
||||
- Camera operations (ImageMethodDialog, PhotoDialog)
|
||||
- Database operations (CapacitorPlatformService)
|
||||
- QR Scanner operations
|
||||
- Platform service operations
|
||||
- Component lifecycle events
|
||||
|
||||
## How to Enable Debug Logging
|
||||
|
||||
### Option 1: Environment Variable (Recommended)
|
||||
|
||||
Set the `VITE_DEBUG_LOGGING` environment variable to `true`:
|
||||
|
||||
```bash
|
||||
# For development
|
||||
VITE_DEBUG_LOGGING=true npm run dev
|
||||
|
||||
# For web builds
|
||||
VITE_DEBUG_LOGGING=true npm run build:web:dev
|
||||
|
||||
# For Electron builds
|
||||
VITE_DEBUG_LOGGING=true npm run build:electron:dev
|
||||
```
|
||||
|
||||
### Option 2: .env File
|
||||
|
||||
Create or modify `.env.local` file:
|
||||
|
||||
```bash
|
||||
# Enable debug logging
|
||||
VITE_DEBUG_LOGGING=true
|
||||
```
|
||||
|
||||
### Option 3: Package.json Scripts
|
||||
|
||||
Add debug variants to your package.json scripts:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"dev:debug": "VITE_DEBUG_LOGGING=true npm run dev",
|
||||
"build:web:debug": "VITE_DEBUG_LOGGING=true npm run build:web:dev",
|
||||
"build:electron:debug": "VITE_DEBUG_LOGGING=true npm run build:electron:dev"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Debug Logging Rules
|
||||
|
||||
Debug logging follows these rules:
|
||||
|
||||
1. **Only shows in development mode** (not production)
|
||||
2. **Only shows for web platform** (not Electron)
|
||||
3. **Must be explicitly enabled** via `VITE_DEBUG_LOGGING=true`
|
||||
4. **Never logged to database** (to reduce noise)
|
||||
5. **Very verbose** - includes detailed component state and operations
|
||||
|
||||
## Components with Debug Logging
|
||||
|
||||
The following components include debug logging:
|
||||
|
||||
- **ImageMethodDialog.vue** - Camera operations, preview state
|
||||
- **PhotoDialog.vue** - Camera operations, video setup
|
||||
- **AmountInput.vue** - Input validation, increment/decrement
|
||||
- **GiftedDialog.vue** - Amount updates, form state
|
||||
- **CapacitorPlatformService.ts** - Database operations, migrations
|
||||
- **QRScanner services** - Camera permissions, scanner state
|
||||
- **PlatformServiceMixin.ts** - Service initialization
|
||||
|
||||
## Example Debug Output
|
||||
|
||||
When enabled, you'll see output like:
|
||||
|
||||
```
|
||||
[ImageMethodDialog] open called
|
||||
[ImageMethodDialog] Camera facing mode: user
|
||||
[ImageMethodDialog] Should mirror video: true
|
||||
[ImageMethodDialog] Platform capabilities: {isMobile: false, hasCamera: true}
|
||||
[ImageMethodDialog] Starting camera preview from open()
|
||||
[ImageMethodDialog] startCameraPreview called
|
||||
[ImageMethodDialog] Current showCameraPreview state: true
|
||||
[ImageMethodDialog] MediaDevices available: true
|
||||
[ImageMethodDialog] getUserMedia constraints: {video: {facingMode: "user"}}
|
||||
[ImageMethodDialog] Setting video element srcObject
|
||||
[ImageMethodDialog] Video metadata loaded, starting playback
|
||||
[ImageMethodDialog] Video element started playing successfully
|
||||
```
|
||||
|
||||
## Disabling Debug Logging
|
||||
|
||||
To disable debug logging:
|
||||
|
||||
1. **Remove the environment variable:**
|
||||
```bash
|
||||
unset VITE_DEBUG_LOGGING
|
||||
```
|
||||
|
||||
2. **Or set it to false:**
|
||||
```bash
|
||||
VITE_DEBUG_LOGGING=false npm run dev
|
||||
```
|
||||
|
||||
3. **Or remove from .env file:**
|
||||
```bash
|
||||
# Comment out or remove this line
|
||||
# VITE_DEBUG_LOGGING=true
|
||||
```
|
||||
|
||||
## Production Behavior
|
||||
|
||||
In production builds, debug logging is **always disabled** regardless of the environment variable setting. This ensures:
|
||||
|
||||
- No debug output in production
|
||||
- No performance impact from debug logging
|
||||
- Clean console output for end users
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Debug Logging Not Working
|
||||
|
||||
1. **Check environment variable:**
|
||||
```bash
|
||||
echo $VITE_DEBUG_LOGGING
|
||||
```
|
||||
|
||||
2. **Verify it's set to "true":**
|
||||
```bash
|
||||
VITE_DEBUG_LOGGING=true npm run dev
|
||||
```
|
||||
|
||||
3. **Check if you're in development mode:**
|
||||
- Debug logging only works in development (`NODE_ENV !== "production"`)
|
||||
- Production builds always disable debug logging
|
||||
|
||||
### Too Much Debug Output
|
||||
|
||||
If debug logging is too verbose:
|
||||
|
||||
1. **Disable it completely:**
|
||||
```bash
|
||||
unset VITE_DEBUG_LOGGING
|
||||
```
|
||||
|
||||
2. **Or modify specific components** to use `logger.log` instead of `logger.debug`
|
||||
|
||||
3. **Or add conditional logging** in components:
|
||||
```typescript
|
||||
if (process.env.VITE_DEBUG_LOGGING === "true") {
|
||||
logger.debug("Detailed debug info");
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use debug logging sparingly** - only for troubleshooting
|
||||
2. **Disable in production** - debug logging is automatically disabled
|
||||
3. **Use specific component prefixes** - makes it easier to filter output
|
||||
4. **Consider log levels** - use `logger.log` for important info, `logger.debug` for verbose details
|
||||
5. **Test without debug logging** - ensure your app works without debug output
|
||||
|
||||
## Future Improvements
|
||||
|
||||
Potential enhancements to the debug logging system:
|
||||
|
||||
1. **Component-specific debug flags** - enable debug for specific components only
|
||||
2. **Log level filtering** - show only certain types of debug messages
|
||||
3. **Debug UI panel** - in-app debug information display
|
||||
4. **Structured logging** - JSON format for better parsing
|
||||
5. **Performance monitoring** - track impact of debug logging
|
||||
@@ -14,7 +14,10 @@ import { ElectronCapacitorApp, setupContentSecurityPolicy, setupReloadWatcher }
|
||||
const gotTheLock = app.requestSingleInstanceLock();
|
||||
|
||||
if (!gotTheLock) {
|
||||
console.log('[Electron] Another instance is already running. Exiting immediately...');
|
||||
// Debug logging - only show when VITE_DEBUG_LOGGING is enabled
|
||||
if (process.env.VITE_DEBUG_LOGGING === 'true') {
|
||||
console.log('[Electron] Another instance is already running. Exiting immediately...');
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -90,7 +93,10 @@ if (electronIsDev) {
|
||||
|
||||
// Handle second instance launch (focus existing window and show dialog)
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
console.log('[Electron] Second instance attempted to launch');
|
||||
// Debug logging - only show when VITE_DEBUG_LOGGING is enabled
|
||||
if (process.env.VITE_DEBUG_LOGGING === 'true') {
|
||||
console.log('[Electron] Second instance attempted to launch');
|
||||
}
|
||||
|
||||
// Someone tried to run a second instance, we should focus our window instead
|
||||
const mainWindow = myCapacitorApp.getMainWindow();
|
||||
@@ -163,7 +169,10 @@ ipcMain.handle('export-data-to-downloads', async (_event, fileName: string, data
|
||||
// Write the file to the Downloads directory
|
||||
await fs.writeFile(filePath, data, 'utf-8');
|
||||
|
||||
console.log(`[Electron Main] File exported successfully: ${filePath}`);
|
||||
// Debug logging - only show when VITE_DEBUG_LOGGING is enabled
|
||||
if (process.env.VITE_DEBUG_LOGGING === 'true') {
|
||||
console.log(`[Electron Main] File exported successfully: ${filePath}`);
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
||||
@@ -3,7 +3,10 @@ import { contextBridge, ipcRenderer } from 'electron';
|
||||
require('./rt/electron-rt');
|
||||
//////////////////////////////
|
||||
// User Defined Preload scripts below
|
||||
console.log('User Preload!');
|
||||
// Debug logging - only show when VITE_DEBUG_LOGGING is enabled
|
||||
if (process.env.VITE_DEBUG_LOGGING === 'true') {
|
||||
console.log('User Preload!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose secure IPC APIs to the renderer process.
|
||||
|
||||
@@ -167,7 +167,7 @@ export default class ContactInputForm extends Vue {
|
||||
*/
|
||||
@Emit("qr-scan")
|
||||
private handleQRScan(): void {
|
||||
console.log("[ContactInputForm] QR scan button clicked");
|
||||
// QR scan button clicked - event emitted to parent
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -162,8 +162,6 @@
|
||||
/* TODO: Human Testing Required - PlatformServiceMixin Migration */
|
||||
// Priority: High | Migrated: 2025-07-06 | Author: Matthew Raymer
|
||||
//
|
||||
// TESTING NEEDED: Component migrated from legacy logConsoleAndDb to PlatformServiceMixin
|
||||
// but requires human validation due to meeting component accessibility limitations.
|
||||
//
|
||||
// Test Scenarios Required:
|
||||
// 1. Load members list with valid meeting password
|
||||
@@ -174,7 +172,6 @@
|
||||
// 6. Cross-platform testing: web, mobile, desktop
|
||||
//
|
||||
// Reference: docs/migration-testing/migration-checklist-MembersList.md
|
||||
// Migration Details: Replaced 3 logConsoleAndDb() calls with this.$logAndConsole()
|
||||
// Validation: Passes lint checks and TypeScript compilation
|
||||
// Navigation: Contacts → Chair Icon → Start/Join Meeting → Members List
|
||||
|
||||
|
||||
@@ -273,8 +273,8 @@ export async function logToDb(
|
||||
// Prevent infinite logging loops - if we're already trying to log to database,
|
||||
// just log to console instead to break circular dependency
|
||||
if (isLoggingToDatabase) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`[DB-PREVENTED-${level.toUpperCase()}] ${message}`);
|
||||
// Use logger.debug for controlled debug output instead of direct console.log
|
||||
logger.debug(`[DB-PREVENTED-${level.toUpperCase()}] ${message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -502,15 +502,7 @@ export function findAllVisibleToDids(
|
||||
import * as R from 'ramda';
|
||||
//import { findAllVisibleToDids } from './src/libs/util'; // doesn't work because other dependencies fail so gotta copy-and-paste function
|
||||
|
||||
console.log(R.equals(findAllVisibleToDids(null), {}));
|
||||
console.log(R.equals(findAllVisibleToDids(9), {}));
|
||||
console.log(R.equals(findAllVisibleToDids([]), {}));
|
||||
console.log(R.equals(findAllVisibleToDids({}), {}));
|
||||
console.log(R.equals(findAllVisibleToDids({ issuer: "abc" }), {}));
|
||||
console.log(R.equals(findAllVisibleToDids({ issuerVisibleToDids: ["abc"] }), { ".issuer": ["abc"] }));
|
||||
console.log(R.equals(findAllVisibleToDids([{ issuerVisibleToDids: ["abc"] }]), { "[0].issuer": ["abc"] }));
|
||||
console.log(R.equals(findAllVisibleToDids(["xyz", { fluff: { issuerVisibleToDids: ["abc"] } }]), { "[1].fluff.issuer": ["abc"] }));
|
||||
console.log(R.equals(findAllVisibleToDids(["xyz", { fluff: { issuerVisibleToDids: ["abc"] }, stuff: [ { did: "HIDDEN", agentDidVisibleToDids: ["def", "ghi"] } ] }]), { "[1].fluff.issuer": ["abc"], "[1].stuff[0].agentDid": ["def", "ghi"] }));
|
||||
// Test/debug console.log statements removed - use logger.debug() if needed
|
||||
|
||||
*
|
||||
**/
|
||||
|
||||
@@ -250,6 +250,12 @@ onerror = function (error) {
|
||||
* Auto-initialize on worker startup (removed to prevent circular dependency)
|
||||
* Initialization now happens on first database operation
|
||||
*/
|
||||
// Use console for critical startup message to avoid circular dependency
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("[SQLWorker] Worker loaded, ready to receive messages");
|
||||
// Use logger.debug for controlled debug output instead of direct console.log
|
||||
// Note: This is a worker context, so we use a simple debug message
|
||||
if (typeof self !== "undefined" && self.name) {
|
||||
// Worker context - use simple debug output
|
||||
self.postMessage({
|
||||
type: "debug",
|
||||
message: "[SQLWorker] Worker loaded, ready to receive messages",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,9 +42,8 @@ export class PlatformServiceFactory {
|
||||
const platform = process.env.VITE_PLATFORM || "web";
|
||||
|
||||
if (!PlatformServiceFactory.creationLogged) {
|
||||
// Use console for critical startup message to avoid circular dependency
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
// Use logger.debug for controlled debug output instead of direct console.log
|
||||
logger.debug(
|
||||
`[PlatformServiceFactory] Creating singleton instance for platform: ${platform}`,
|
||||
);
|
||||
PlatformServiceFactory.creationLogged = true;
|
||||
|
||||
@@ -174,7 +174,7 @@ export class DeepLinkHandler {
|
||||
const validRoute = routeSchema.parse(path) as DeepLinkRoute;
|
||||
routeName = ROUTE_MAP[validRoute].name;
|
||||
} catch (error) {
|
||||
console.error(`[DeepLink] Invalid route path: ${path}`);
|
||||
logger.error(`[DeepLink] Invalid route path: ${path}`);
|
||||
|
||||
// Redirect to error page with information about the invalid link
|
||||
await this.router.replace({
|
||||
@@ -201,7 +201,7 @@ export class DeepLinkHandler {
|
||||
validatedQuery = await schema.parseAsync(query);
|
||||
} catch (error) {
|
||||
// For parameter validation errors, provide specific error feedback
|
||||
console.error(
|
||||
logger.error(
|
||||
`[DeepLink] Invalid parameters for route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with params: ${JSON.stringify(params)} ... and query: ${JSON.stringify(query)}`,
|
||||
);
|
||||
await this.router.replace({
|
||||
@@ -226,7 +226,7 @@ export class DeepLinkHandler {
|
||||
query: validatedQuery,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(
|
||||
logger.error(
|
||||
`[DeepLink] Error routing to route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with validated params: ${JSON.stringify(validatedParams)} ... and validated query: ${JSON.stringify(validatedQuery)}`,
|
||||
);
|
||||
// For parameter validation errors, provide specific error feedback
|
||||
@@ -260,7 +260,7 @@ export class DeepLinkHandler {
|
||||
await this.validateAndRoute(path, sanitizedParams, query);
|
||||
} catch (error) {
|
||||
const deepLinkError = error as DeepLinkError;
|
||||
console.error(
|
||||
logger.error(
|
||||
`[DeepLink] Error (${deepLinkError.code}): ${deepLinkError.details}`,
|
||||
);
|
||||
|
||||
|
||||
@@ -97,9 +97,8 @@ export class WebPlatformService implements PlatformService {
|
||||
}
|
||||
} else {
|
||||
// We're in a worker context - skip initBackend call
|
||||
// Use console for critical startup message to avoid circular dependency
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
// Use logger.debug for controlled debug output instead of direct console.log
|
||||
logger.debug(
|
||||
"[WebPlatformService] Skipping initBackend call in worker context",
|
||||
);
|
||||
}
|
||||
@@ -693,11 +692,7 @@ export class WebPlatformService implements PlatformService {
|
||||
const setClause = keys.map((key) => `${key} = ?`).join(", ");
|
||||
const sql = `UPDATE settings SET ${setClause} WHERE accountDid = ?`;
|
||||
const params = [...keys.map((key) => settings[key]), did];
|
||||
console.log(
|
||||
"[WebPlatformService] updateDidSpecificSettings",
|
||||
sql,
|
||||
JSON.stringify(params, null, 2),
|
||||
);
|
||||
// Debug logging removed - use logger.debug() if needed
|
||||
await this.dbExec(sql, params);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||
import { logger } from "@/utils/logger";
|
||||
|
||||
@Component({
|
||||
mixins: [PlatformServiceMixin],
|
||||
@@ -267,7 +268,7 @@ This tests the complete save → retrieve cycle with actual database interaction
|
||||
this.result = `User #0 settings test completed. isRegistered: ${accountSettings.isRegistered}`;
|
||||
} catch (error) {
|
||||
this.result = `Error testing User #0 settings: ${error}`;
|
||||
console.error("Error testing User #0 settings:", error);
|
||||
logger.error("Error testing User #0 settings:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,10 +757,7 @@ export const PlatformServiceMixin = {
|
||||
// Merge with any provided defaults (these take highest precedence)
|
||||
const finalSettings = { ...mergedSettings, ...defaults };
|
||||
|
||||
console.log(
|
||||
"[PlatformServiceMixin] $accountSettings",
|
||||
JSON.stringify(finalSettings, null, 2),
|
||||
);
|
||||
// Debug logging removed - use logger.debug() if needed
|
||||
return finalSettings;
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
|
||||
@@ -45,6 +45,7 @@ export function safeStringify(obj: unknown) {
|
||||
// Determine if we should suppress verbose logging (for Electron)
|
||||
const isElectron = process.env.VITE_PLATFORM === "electron";
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
const isDebugEnabled = process.env.VITE_DEBUG_LOGGING === "true";
|
||||
|
||||
// Track initialization state to prevent circular dependencies
|
||||
let isInitializing = true;
|
||||
@@ -108,8 +109,8 @@ async function logToDatabase(
|
||||
// Enhanced logger with self-contained database methods
|
||||
export const logger = {
|
||||
debug: (message: string, ...args: unknown[]) => {
|
||||
// Debug logs are very verbose - only show in development mode for web
|
||||
if (!isProduction && !isElectron) {
|
||||
// Debug logs are very verbose - only show when explicitly enabled
|
||||
if (isDebugEnabled && !isProduction && !isElectron) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(message, ...args);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ import {
|
||||
VALID_DEEP_LINK_ROUTES,
|
||||
deepLinkSchemas,
|
||||
} from "../interfaces/deepLinks";
|
||||
import { logConsoleAndDb } from "../db/databaseUtil";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
const route = useRoute();
|
||||
@@ -106,9 +105,8 @@ const reportIssue = () => {
|
||||
|
||||
// Log the error for analytics
|
||||
onMounted(() => {
|
||||
logConsoleAndDb(
|
||||
logger.error(
|
||||
`[DeepLinkError] Error page displayed for path: ${originalPath.value}, code: ${errorCode.value}, params: ${JSON.stringify(route.params)}, query: ${JSON.stringify(route.query)}`,
|
||||
true,
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user