As a best-selling author, I invite you to explore my books on Amazon. Don't forget to follow me on Medium and show your support. Thank you! Your support means the world!
JavaScript Performance Monitoring: Essential Techniques for Production Applications
Performance monitoring forms the backbone of maintaining robust JavaScript applications in production. Let's explore five critical monitoring techniques that help maintain optimal application performance.
Application Logging
Effective logging provides insights into application behavior and helps troubleshoot issues quickly. I implement structured logging using libraries like Winston or Pino:
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
// Sample logging with context
logger.info('User action completed', {
userId: user.id,
action: 'checkout',
duration: performance.now() - startTime
});
I recommend implementing log sampling for high-volume events to manage storage and processing costs:
function shouldSampleLog(eventName, samplingRate) {
return Math.random() < samplingRate;
}
function logEvent(eventName, data) {
if (shouldSampleLog(eventName, 0.1)) { // 10% sampling rate
logger.info(eventName, data);
}
}
Error Tracking
Capturing and analyzing errors provides crucial insights into application stability. I set up global error handlers to catch unhandled exceptions:
window.onerror = function(message, source, lineno, colno, error) {
const errorData = {
message,
source,
lineno,
colno,
stack: error?.stack,
userAgent: navigator.userAgent,
timestamp: new Date().toISOString()
};
sendErrorToAnalytics(errorData);
return false;
};
// Handle promise rejections
window.addEventListener('unhandledrejection', function(event) {
const errorData = {
message: event.reason?.message || 'Promise rejection',
stack: event.reason?.stack,
timestamp: new Date().toISOString()
};
sendErrorToAnalytics(errorData);
});
Performance Metrics
The Performance API provides powerful tools for measuring critical metrics. I use it to track key performance indicators:
// Monitor First Contentful Paint
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('FCP:', entry.startTime);
sendMetric('FCP', entry.startTime);
}
}).observe({entryTypes: ['paint']});
// Track long tasks
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (entry.duration > 50) {
console.log('Long Task:', entry.duration);
sendMetric('LongTask', entry.duration);
}
}
}).observe({entryTypes: ['longtask']});
// Custom business metrics
function measureBusinessTransaction(transactionName, func) {
const start = performance.now();
const result = func();
const duration = performance.now() - start;
sendMetric(transactionName, duration);
return result;
}
Resource Usage Monitoring
Tracking resource consumption helps prevent performance degradation. I implement memory and CPU monitoring:
// Memory monitoring
function checkMemoryUsage() {
if (performance.memory) {
const usage = {
usedJSHeapSize: performance.memory.usedJSHeapSize,
totalJSHeapSize: performance.memory.totalJSHeapSize,
jsHeapSizeLimit: performance.memory.jsHeapSizeLimit
};
if (usage.usedJSHeapSize > usage.jsHeapSizeLimit * 0.9) {
alertMemoryIssue(usage);
}
sendMetric('memoryUsage', usage);
}
}
// Network request monitoring
const originalFetch = window.fetch;
window.fetch = async function(...args) {
const startTime = performance.now();
try {
const response = await originalFetch.apply(this, args);
const duration = performance.now() - startTime;
sendMetric('networkRequest', {
url: args[0],
duration,
status: response.status
});
return response;
} catch (error) {
sendMetric('networkError', {
url: args[0],
error: error.message
});
throw error;
}
};
User Experience Monitoring
Understanding real user experience is crucial for application success. I implement comprehensive user monitoring:
// Page load timing
window.addEventListener('load', () => {
const timing = performance.timing;
const metrics = {
dnsLookup: timing.domainLookupEnd - timing.domainLookupStart,
tcpConnection: timing.connectEnd - timing.connectStart,
serverResponse: timing.responseEnd - timing.requestStart,
domProcessing: timing.domComplete - timing.domLoading,
totalLoadTime: timing.loadEventEnd - timing.navigationStart
};
sendMetrics('pageLoad', metrics);
});
// User interactions
function trackUserInteraction(element, eventType) {
element.addEventListener(eventType, (event) => {
const startTime = performance.now();
// Wait for next frame to measure response time
requestAnimationFrame(() => {
const duration = performance.now() - startTime;
sendMetric('interaction', {
type: eventType,
element: element.tagName,
duration
});
});
});
}
// Session recording
class SessionRecorder {
constructor() {
this.events = [];
this.isRecording = false;
}
startRecording() {
this.isRecording = true;
this.recordUserActions();
}
recordUserActions() {
document.addEventListener('click', (e) => {
if (this.isRecording) {
this.events.push({
type: 'click',
target: e.target.tagName,
timestamp: Date.now()
});
}
});
// Add more event listeners as needed
}
stopRecording() {
this.isRecording = false;
this.sendRecordingToAnalytics();
}
}
These monitoring techniques provide comprehensive insights into application performance. I recommend implementing them gradually, starting with the most critical aspects for your application. Regular analysis of collected data helps identify optimization opportunities and maintain high performance standards.
Remember to consider privacy implications and obtain necessary user consent when implementing monitoring solutions. Additionally, ensure that monitoring code itself doesn't impact application performance by using techniques like throttling and batching when sending data to analytics servers.
The combination of these monitoring techniques creates a robust system for maintaining and improving JavaScript application performance in production environments. Regular review and adjustment of monitoring strategies ensure continued effectiveness as applications evolve.
101 Books
101 Books is an AI-driven publishing company co-founded by author Aarav Joshi. By leveraging advanced AI technology, we keep our publishing costs incredibly low—some books are priced as low as $4—making quality knowledge accessible to everyone.
Check out our book Golang Clean Code available on Amazon.
Stay tuned for updates and exciting news. When shopping for books, search for Aarav Joshi to find more of our titles. Use the provided link to enjoy special discounts!
Our Creations
Be sure to check out our creations:
Investor Central | Investor Central Spanish | Investor Central German | Smart Living | Epochs & Echoes | Puzzling Mysteries | Hindutva | Elite Dev | JS Schools
We are on Medium
Tech Koala Insights | Epochs & Echoes World | Investor Central Medium | Puzzling Mysteries Medium | Science & Epochs Medium | Modern Hindutva