Production Logging Guidelines
8 min read
TL;DR
Only log user-visible events and errors in production console. Never log tokens, credentials, user IDs, PII, or internal implementation details. Use environment-based logging to separate production-safe logs from verbose debug logs. Treat the console like a billboardβonly show what you'd want customers to see.
Production Logging Guidelines
Overview
This guide defines what logging is appropriate for production JavaScript console output to ensure security, privacy, and professionalism.
β ALLOWED in Production Console
1. Application Lifecycle Events
// Good: High-level initialization
console.log('Surmado initialized');
console.log('β
Authentication ready');
console.log('β
Organization loaded');
2. User-Visible Actions (Success)
// Good: Confirmations of user actions
console.log('β
Report submitted successfully');
console.log('β
Brand created:', brandName); // brandName is user-provided, not sensitive
console.log('β
Credits purchased: 12');
3. User-Facing Errors (Non-Sensitive)
// Good: Errors the user can see and act on
console.error('β Failed to load reports. Please refresh the page.');
console.error('β Insufficient credits. Please purchase more to continue.');
console.warn('β οΈ Network error. Retrying...');
4. Feature Flags / Environment Info (Public Only)
// Good: Non-sensitive configuration
console.log('Environment: production');
console.log('API Endpoint: https://api.surmado.com');
console.log('Debug mode: disabled');
5. Branded Messages
// Good: Professional branding
console.log('%cπ Surmado', 'font-size: 20px; font-weight: bold; color: #2C5F5D;');
console.log('Need help? Visit https://surmado.com/support');
β NEVER LOG in Production Console
1. Authentication Tokens / Credentials
// BAD - NEVER DO THIS
console.log('Token:', token); // β Security risk
console.log('API Key:', apiKey); // β Security risk
console.log('Bearer:', authHeader); // β Security risk
console.log('Session:', clerk.session); // β Contains sensitive data
2. User Identifiers / PII
// BAD - Privacy violation
console.log('User ID:', userId); // β PII
console.log('Organization ID:', orgId); // β PII
console.log('Email:', user.email); // β PII
console.log('Clerk User:', clerk.user); // β Contains PII
console.log('Organization:', clerk.organization); // β Contains PII
3. Internal Implementation Details
// BAD - Leaks architecture
console.log('Calling /.netlify/functions/submit-report'); // β Internal paths
console.log('Database query:', query); // β Internal logic
console.log('Python API response:', fullResponse); // β May contain sensitive data
console.debug('Session state:', sessionObject); // β Internal state
4. Detailed Error Stack Traces
// BAD - Exposes code structure
console.error('Error:', error); // β Full stack trace
console.error('Failed:', error.stack); // β Code paths exposed
5. Verbose Debugging Info
// BAD - Too much noise
console.log('Entering function submitReport'); // β Implementation detail
console.log('Variable x:', x, 'Variable y:', y); // β Internal state
console.debug('Loop iteration:', i); // β Verbose
6. Request/Response Payloads with Sensitive Data
// BAD - May contain sensitive info
console.log('Request body:', JSON.stringify(body)); // β May contain tokens/PII
console.log('API response:', response); // β May contain sensitive data
console.log('Headers:', headers); // β May contain auth headers
π― Best Practices
Use Environment-Based Logging
const isDevelopment = window.location.hostname === 'localhost' ||
window.location.hostname.includes('netlify.app');
// Verbose logging only in development
if (isDevelopment) {
console.debug('π Authenticating request...');
console.debug('Session ready:', session);
}
// Always log user-visible events
console.log('β
Report submitted successfully');
Create a Logging Utility
// logger.js
const Logger = {
// Always logs (production-safe)
info: (message) => {
console.log(`βΉοΈ ${message}`);
},
success: (message) => {
console.log(`β
${message}`);
},
error: (message) => {
// Only user-facing error message, no sensitive details
console.error(`β ${message}`);
},
// Only logs in development
debug: (message, data = null) => {
if (isDevelopment) {
console.debug(`π ${message}`, data);
}
}
};
// Usage
Logger.success('Brand created successfully');
Logger.debug('API response', response); // Only in dev
Sanitize Before Logging
// Good: Redact sensitive fields
function sanitizeForLogging(obj) {
const safe = { ...obj };
// Remove sensitive fields
delete safe.token;
delete safe.apiKey;
delete safe.userId;
delete safe.orgId;
delete safe.email;
// Redact values that look like tokens
Object.keys(safe).forEach(key => {
if (typeof safe[key] === 'string' && safe[key].length > 50) {
safe[key] = '[REDACTED]';
}
});
return safe;
}
// Usage
console.log('Config:', sanitizeForLogging(config));
π Production Logging Checklist
Before deploying to production, verify:
- No API tokens, keys, or credentials logged
- No user IDs, org IDs, or email addresses logged
- No full error stack traces (only user-friendly messages)
- No internal API endpoints or implementation details
- No verbose debug logs (or wrapped in isDevelopment check)
- No request/response bodies with sensitive data
- Only user-visible events and errors logged
- Branded/professional console messages
- Error messages are actionable for users
π Audit Your Codebase
Search for these patterns and review each instance:
# Find potentially problematic logging
grep -r "console.log.*token" .
grep -r "console.log.*userId" .
grep -r "console.log.*orgId" .
grep -r "console.log.*email" .
grep -r "console.log.*clerk" .
grep -r "console.debug" .
grep -r "console.error.*error\)" .
π Example: Before & After
β Before (Development/Debug Logging)
console.log('π Authenticating request...');
console.log('User ID:', userId);
console.log('Org ID:', orgId);
console.log('Token:', token.substring(0, 20) + '...');
console.log('Calling API:', apiEndpoint);
console.log('Request headers:', headers);
console.log('Response:', response);
β After (Production-Ready Logging)
// Only log high-level success
console.log('β
Authentication successful');
// Or use conditional logging
if (isDevelopment) {
console.debug('π Auth flow completed');
// Detailed logging only in dev
}
π Implementation Steps
- Create
js/utils/logger.jswith environment-aware logging utility - Replace all
console.log/debug/errorwith Logger utility - Audit existing logs using grep commands above
- Test in production mode locally (disable dev mode)
- Review console for any leaked sensitive data
- Deploy with confidence
π Security Note
Remember: The JavaScript console is public. Anyone can open DevTools and see console output. Treat it like you would a billboard - only show what youβd want customers, competitors, and security researchers to see.
π Questions?
If unsure whether something should be logged, ask:
- Would showing this to a stranger compromise security? β Donβt log
- Does this contain user data or PII? β Donβt log
- Is this only useful for internal debugging? β Dev-only or donβt log
- Would a user find this helpful or confusing? β Log if helpful
When in doubt, donβt log it.
Was this helpful?
Thanks for your feedback!
Have suggestions for improvement?
Tell us moreHelp Us Improve This Article
Know a better way to explain this? Have a real-world example or tip to share?
Contribute and earn credits:
- Submit: Get $25 credit (Signal, Scan, or Solutions)
- If accepted: Get an additional $25 credit ($50 total)
- Plus: Byline credit on this article