diff --git a/.env.development b/.env.development index 70091e74..44a2ffdf 100644 --- a/.env.development +++ b/.env.development @@ -1,10 +1,14 @@ - # Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. +# Logging Configuration - Development environment gets maximum visibility +VITE_LOG_LEVEL=debug + # iOS doesn't like spaces in the app title. TIME_SAFARI_APP_TITLE="TimeSafari_Dev" VITE_APP_SERVER=http://localhost:8080 -# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production). +# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not + production). + VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 # Using shared server by default to ease setup, which works for shared test users. diff --git a/.env.production b/.env.production index bbf73a08..aef4d6a4 100644 --- a/.env.production +++ b/.env.production @@ -1,6 +1,7 @@ # Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. - +# Logging Configuration - Production environment gets minimal logging for performance +VITE_LOG_LEVEL=warn VITE_APP_SERVER=https://timesafari.app # This is the claim ID for actions in the BVC project. diff --git a/.env.test b/.env.test index a01c323c..5776e66c 100644 --- a/.env.test +++ b/.env.test @@ -1,9 +1,14 @@ # Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. +# Logging Configuration - Test environment gets balanced logging for debugging +VITE_LOG_LEVEL=info + # iOS doesn't like spaces in the app title. TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.app -# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production). +# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not + production). + VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch diff --git a/README.md b/README.md index 6d987467..ba8bf89b 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,35 @@ See [BUILDING.md](BUILDING.md) for comprehensive build instructions for all plat TimeSafari provides a simple script-based approach to clear the database for development purposes. +## Logging Configuration + +TimeSafari supports configurable logging levels via the `VITE_LOG_LEVEL` environment variable. This allows developers to control console output verbosity without modifying code. + +### Quick Usage + +```bash +# Show only errors +VITE_LOG_LEVEL=error npm run dev + +# Show warnings and errors +VITE_LOG_LEVEL=warn npm run dev + +# Show info, warnings, and errors (default) +VITE_LOG_LEVEL=info npm run dev + +# Show all log levels including debug +VITE_LOG_LEVEL=debug npm run dev +``` + +### Available Levels + +- **`error`**: Critical errors only +- **`warn`**: Warnings and errors (default for production web) +- **`info`**: Info, warnings, and errors (default for development/capacitor) +- **`debug`**: All log levels including verbose debugging + +See [Logging Configuration Guide](doc/logging-configuration.md) for complete details. + ### Quick Usage ```bash # Run the database clearing script diff --git a/doc/logging-configuration.md b/doc/logging-configuration.md new file mode 100644 index 00000000..2ef2a6d2 --- /dev/null +++ b/doc/logging-configuration.md @@ -0,0 +1,117 @@ +# Logging Configuration Guide + +## Overview + +TimeSafari now supports configurable logging levels via the `VITE_LOG_LEVEL` environment variable. This allows developers to control the verbosity of console output without modifying code. + +## Available Log Levels + +| Level | Value | Description | Console Output | +|-------|-------|-------------|----------------| +| `error` | 0 | Errors only | Critical errors only | +| `warn` | 1 | Warnings and errors | Warnings and errors | +| `info` | 2 | Info, warnings, and errors | General information, warnings, and errors | +| `debug` | 3 | All log levels | Verbose debugging information | + +## Environment Variable + +Set the `VITE_LOG_LEVEL` environment variable to control logging: + +```bash +# Show only errors +VITE_LOG_LEVEL=error + +# Show warnings and errors (default for production web) +VITE_LOG_LEVEL=warn + +# Show info, warnings, and errors (default for development/capacitor) +VITE_LOG_LEVEL=info + +# Show all log levels including debug +VITE_LOG_LEVEL=debug +``` + +## Default Behavior by Platform + +The logger automatically selects appropriate default log levels based on your platform and environment: + +- **Production Web**: `warn` (warnings and errors only) +- **Electron**: `error` (errors only - very quiet) +- **Development/Capacitor**: `info` (info and above) + +## Usage Examples + +### Setting Log Level in Development + +```bash +# In your terminal before running the app +export VITE_LOG_LEVEL=debug +npm run dev + +# Or inline +VITE_LOG_LEVEL=debug npm run dev +``` + +### Setting Log Level in Production + +```bash +# For verbose production logging +VITE_LOG_LEVEL=info npm run build:web + +# For minimal production logging +VITE_LOG_LEVEL=warn npm run build:web +``` + +### Programmatic Access + +The logger provides methods to check current configuration: + +```typescript +import { logger } from '@/utils/logger'; + +// Get current log level +const currentLevel = logger.getCurrentLevel(); // 'info' + +// Check if a level is enabled +const debugEnabled = logger.isLevelEnabled('debug'); // false if level < debug + +// Get available levels +const levels = logger.getAvailableLevels(); // ['error', 'warn', 'info', 'debug'] +``` + +## Database Logging + +Database logging continues to work regardless of console log level settings. All log messages are still stored in the database for debugging and audit purposes. + +## Migration Notes + +- **Existing code**: No changes required - logging behavior remains the same +- **New feature**: Use `VITE_LOG_LEVEL` to override default behavior +- **Backward compatible**: All existing logging calls work as before + +## Best Practices + +1. **Development**: Use `VITE_LOG_LEVEL=debug` for maximum visibility +2. **Testing**: Use `VITE_LOG_LEVEL=info` for balanced output +3. **Production**: Use `VITE_LOG_LEVEL=warn` for minimal noise +4. **Debugging**: Temporarily set `VITE_LOG_LEVEL=debug` to troubleshoot issues + +## Troubleshooting + +### No Logs Appearing + +Check your `VITE_LOG_LEVEL` setting: +```bash +echo $VITE_LOG_LEVEL +``` + +### Too Many Logs + +Reduce verbosity by setting a lower log level: +```bash +VITE_LOG_LEVEL=warn +``` + +### Platform-Specific Issues + +Remember that Electron is very quiet by default. Use `VITE_LOG_LEVEL=info` to see more output in Electron builds. diff --git a/src/components/DataExportSection.vue b/src/components/DataExportSection.vue index ce8ee2fc..a21be7b2 100644 --- a/src/components/DataExportSection.vue +++ b/src/components/DataExportSection.vue @@ -187,9 +187,10 @@ export default class DataExportSection extends Vue { const exContact: Contact = R.omit(["contactMethods"], contact); // now add contactMethods as a true array of ContactMethod objects exContact.contactMethods = contact.contactMethods - ? (typeof contact.contactMethods === 'string' && contact.contactMethods.trim() !== '' - ? JSON.parse(contact.contactMethods) - : []) + ? typeof contact.contactMethods === "string" && + contact.contactMethods.trim() !== "" + ? JSON.parse(contact.contactMethods) + : [] : []; return exContact; }); diff --git a/src/components/OfferDialog.vue b/src/components/OfferDialog.vue index b8b8093f..81664088 100644 --- a/src/components/OfferDialog.vue +++ b/src/components/OfferDialog.vue @@ -18,7 +18,7 @@ Raymer */
@@ -152,8 +152,6 @@ export default class OfferDialog extends Vue { }; } - - // ================================================= // COMPONENT METHODS // ================================================= @@ -199,8 +197,6 @@ export default class OfferDialog extends Vue { this.visible = false; } - - /** * Handle amount updates from AmountInput component * @param value - New amount value diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 4b78ed3a..52ae5daa 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -2,9 +2,10 @@ * Enhanced logger with self-contained database logging * * Provides comprehensive logging with console and database output. + * Supports configurable log levels via VITE_LOG_LEVEL environment variable. * * @author Matthew Raymer - * @version 2.0.0 + * @version 2.1.0 * @since 2025-01-25 */ @@ -46,6 +47,42 @@ export function safeStringify(obj: unknown) { const isElectron = process.env.VITE_PLATFORM === "electron"; const isProduction = process.env.NODE_ENV === "production"; +// Log level configuration via environment variable +const LOG_LEVELS = { + error: 0, + warn: 1, + info: 2, + debug: 3, +} as const; + +type LogLevel = keyof typeof LOG_LEVELS; + +// Parse VITE_LOG_LEVEL environment variable +const getLogLevel = (): LogLevel => { + const envLogLevel = process.env.VITE_LOG_LEVEL?.toLowerCase(); + + if (envLogLevel && envLogLevel in LOG_LEVELS) { + return envLogLevel as LogLevel; + } + + // Default log levels based on environment + if (isProduction && !isElectron) { + return "warn"; // Production web: warnings and errors only + } else if (isElectron) { + return "error"; // Electron: errors only + } else { + return "info"; // Development/Capacitor: info and above + } +}; + +const currentLogLevel = getLogLevel(); +const currentLevelValue = LOG_LEVELS[currentLogLevel]; + +// Helper function to check if a log level should be displayed +const shouldLog = (level: LogLevel): boolean => { + return LOG_LEVELS[level] <= currentLevelValue; +}; + // Track initialization state to prevent circular dependencies let isInitializing = true; @@ -105,11 +142,11 @@ async function logToDatabase( } } -// Enhanced logger with self-contained database methods +// Enhanced logger with self-contained database methods and log level control 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 only show if VITE_LOG_LEVEL allows it + if (shouldLog("debug")) { // eslint-disable-next-line no-console console.debug(message, ...args); } @@ -117,11 +154,8 @@ export const logger = { }, log: (message: string, ...args: unknown[]) => { - // Regular logs - show in development or for capacitor, but quiet for Electron - if ( - (!isProduction && !isElectron) || - process.env.VITE_PLATFORM === "capacitor" - ) { + // Regular logs - show if VITE_LOG_LEVEL allows info level + if (shouldLog("info")) { // eslint-disable-next-line no-console console.log(message, ...args); } @@ -132,11 +166,7 @@ export const logger = { }, info: (message: string, ...args: unknown[]) => { - if ( - process.env.NODE_ENV !== "production" || - process.env.VITE_PLATFORM === "capacitor" || - process.env.VITE_PLATFORM === "electron" - ) { + if (shouldLog("info")) { // eslint-disable-next-line no-console console.info(message, ...args); } @@ -147,8 +177,7 @@ export const logger = { }, warn: (message: string, ...args: unknown[]) => { - // Always show warnings, but for Electron, suppress routine database warnings - if (!isElectron || !message.includes("[CapacitorPlatformService]")) { + if (shouldLog("warn")) { // eslint-disable-next-line no-console console.warn(message, ...args); } @@ -159,9 +188,10 @@ export const logger = { }, error: (message: string, ...args: unknown[]) => { - // Errors will always be logged to console - // eslint-disable-next-line no-console - console.error(message, ...args); + if (shouldLog("error")) { + // eslint-disable-next-line no-console + console.error(message, ...args); + } // Database logging const messageString = safeStringify(message); @@ -175,11 +205,11 @@ export const logger = { }, toConsoleAndDb: async (message: string, isError = false): Promise => { - // Console output - if (isError) { + // Console output based on log level + if (isError && shouldLog("error")) { // eslint-disable-next-line no-console console.error(message); - } else { + } else if (!isError && shouldLog("info")) { // eslint-disable-next-line no-console console.log(message); } @@ -194,6 +224,12 @@ export const logger = { error: (message: string) => logToDatabase(`[${componentName}] ${message}`, "error"), }), + + // Log level information methods + getCurrentLevel: (): LogLevel => currentLogLevel, + getCurrentLevelValue: (): number => currentLevelValue, + isLevelEnabled: (level: LogLevel): boolean => shouldLog(level), + getAvailableLevels: (): LogLevel[] => Object.keys(LOG_LEVELS) as LogLevel[], }; // Function to manually mark initialization as complete