Application Performance Monitoring (APM) agent for Node.js applications with transaction tracing, error tracking, custom metrics, and distributed tracing capabilities.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Generate Real User Monitoring (RUM) scripts for correlating server-side performance with client-side metrics.
Generate the browser monitoring script tag for injection into HTML pages.
/**
* Generate browser monitoring script for Real User Monitoring injection.
* Must be called for each page request - do not reuse between users or requests.
* @param {object} [options] - Configuration options
* @param {string} [options.nonce] - CSP nonce for script tag
* @param {boolean} [options.hasToRemoveScriptWrapper] - Return script content without <script> tags
* @param {boolean} [options.allowTransactionlessInjection] - Allow injection without active transaction
* @returns {string} HTML script tag or script content, empty string or HTML comment on error
*/
function getBrowserTimingHeader(options);Usage Examples:
const newrelic = require('newrelic');
// Basic usage in Express templates
app.get('/', (req, res) => {
const browserScript = newrelic.getBrowserTimingHeader();
res.render('index', { browserScript });
});
// Template usage (EJS example)
// In your HTML head section:
// <%- browserScript %>
// With CSP nonce
app.get('/secure-page', (req, res) => {
const nonce = generateNonce();
const browserScript = newrelic.getBrowserTimingHeader({ nonce });
res.set('Content-Security-Policy', `script-src 'nonce-${nonce}' 'self'`);
res.render('secure-page', { browserScript });
});
// For React/SPA applications (script content only)
app.get('/api/browser-script', (req, res) => {
const scriptContent = newrelic.getBrowserTimingHeader({
hasToRemoveScriptWrapper: true
});
res.json({ scriptContent });
});
// Allow injection without active transaction
app.get('/static-page', (req, res) => {
const browserScript = newrelic.getBrowserTimingHeader({
allowTransactionlessInjection: true
});
res.render('static-page', { browserScript });
});interface BrowserTimingOptions {
/** CSP nonce to inject into the script tag for security */
nonce?: string;
/** Return script content without <script> wrapper tags */
hasToRemoveScriptWrapper?: boolean;
/** Allow browser agent injection when no active transaction exists */
allowTransactionlessInjection?: boolean;
}<script type='text/javascript'>
window.NREUM||(NREUM={});NREUM.info = {"beacon":"bam.nr-data.net","errorBeacon":"bam.nr-data.net","licenseKey":"abc123","applicationID":"12345","transactionName":"xyz","queueTime":0,"applicationTime":123,"ttGuid":"def456","agent":"js-agent.newrelic.com/nr-spa-1234.min.js"};
// ... agent loader script
</script><script type='text/javascript' nonce="abc123xyz">
// ... same content as above
</script>window.NREUM||(NREUM={});NREUM.info = {"beacon":"bam.nr-data.net",...};
// ... agent loader script (content only)The function returns HTML comments with error codes when browser monitoring cannot be generated:
<!-- NREUM: (0) --> - Browser monitoring disabled in configuration<!-- NREUM: (1) --> - No active transaction or transaction ignored<!-- NREUM: (2) --> - Browser monitoring configuration missing<!-- NREUM: (3) --> - Transaction name missing<!-- NREUM: (4) --> - Application ID missing (agent not connected)<!-- NREUM: (5) --> - Browser key missing (server disabled monitoring)<!-- NREUM: (6) --> - Agent loader script missing<!-- NREUM: (7) --> - Browser monitoring disabled by serverBrowser monitoring requires:
browser_monitoring.enable: true in configurationallowTransactionlessInjection: true)// EJS template
app.get('/', (req, res) => {
res.render('index', {
title: 'My App',
browserScript: newrelic.getBrowserTimingHeader()
});
});
// In views/index.ejs:
// <!DOCTYPE html>
// <html>
// <head>
// <title><%= title %></title>
// <%- browserScript %>
// </head>
// <body>...</body>
// </html>// API route to get browser script
app.get('/api/newrelic-browser', (req, res) => {
const scriptContent = newrelic.getBrowserTimingHeader({
hasToRemoveScriptWrapper: true
});
res.json({
success: scriptContent.length > 0,
script: scriptContent
});
});
// In React component:
useEffect(() => {
fetch('/api/newrelic-browser')
.then(res => res.json())
.then(data => {
if (data.success && data.script) {
const script = document.createElement('script');
script.innerHTML = data.script;
document.head.appendChild(script);
}
});
}, []);// Middleware to automatically add browser script to all HTML responses
app.use((req, res, next) => {
const originalRender = res.render;
res.render = function(view, options = {}) {
// Add browser script to all template renders
options.browserScript = newrelic.getBrowserTimingHeader();
return originalRender.call(this, view, options);
};
next();
});// Generate nonce for each request
function generateNonce() {
return require('crypto').randomBytes(16).toString('base64');
}
app.use((req, res, next) => {
// Generate nonce for this request
const nonce = generateNonce();
res.locals.nonce = nonce;
// Set CSP header
res.set('Content-Security-Policy',
`script-src 'nonce-${nonce}' 'self' js-agent.newrelic.com bam.nr-data.net`
);
next();
});
app.get('/', (req, res) => {
const browserScript = newrelic.getBrowserTimingHeader({
nonce: res.locals.nonce
});
res.render('index', { browserScript });
});function getSafeBrowserScript(options = {}) {
try {
const script = newrelic.getBrowserTimingHeader(options);
// Check if script generation failed (returns HTML comment)
if (script.startsWith('<!-- NREUM:')) {
console.warn('Browser monitoring script generation failed:', script);
return ''; // Return empty string for failed generation
}
return script;
} catch (error) {
console.error('Error generating browser monitoring script:', error);
return ''; // Fail gracefully
}
}
// Usage with fallback
app.get('/', (req, res) => {
const browserScript = getSafeBrowserScript();
res.render('index', { browserScript });
});// For SPAs, you might want to inject the script only on initial page load
app.get('/', (req, res) => {
const browserScript = newrelic.getBrowserTimingHeader();
res.render('spa-shell', { browserScript });
});
// API routes don't need browser monitoring
app.get('/api/*', (req, res, next) => {
// Skip browser monitoring for API calls
next();
});// Only inject in production environment
function getBrowserScriptForEnvironment(options = {}) {
if (process.env.NODE_ENV !== 'production') {
return ''; // No browser monitoring in development
}
return newrelic.getBrowserTimingHeader(options);
}
app.get('/', (req, res) => {
const browserScript = getBrowserScriptForEnvironment();
res.render('index', { browserScript });
});<head> section, after any X-UA-Compatible meta tags