CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-newrelic

Application Performance Monitoring (APM) agent for Node.js applications with transaction tracing, error tracking, custom metrics, and distributed tracing capabilities.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

browser-monitoring.mddocs/

Browser Monitoring

Generate Real User Monitoring (RUM) scripts for correlating server-side performance with client-side metrics.

Capabilities

Get Browser Timing Header

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 });
});

Browser Timing Options

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 Output Formats

Default Output (with script tags)

<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>

With CSP Nonce

<script type='text/javascript' nonce="abc123xyz">
// ... same content as above
</script>

Without Script Wrapper

window.NREUM||(NREUM={});NREUM.info = {"beacon":"bam.nr-data.net",...};
// ... agent loader script (content only)

Error Conditions

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 server

Configuration Requirements

Browser monitoring requires:

  1. Agent Connection: Agent must have successfully connected to New Relic servers
  2. Browser Monitoring Enabled: browser_monitoring.enable: true in configuration
  3. Server Configuration: New Relic servers must provide browser monitoring settings
  4. Active Transaction: Usually requires an active transaction (unless allowTransactionlessInjection: true)

Common Integration Patterns

Express with Template Engines

// 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>

React/Next.js Applications

// 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 for Automatic Injection

// 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();
});

CSP-Compliant Implementation

// 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 });
});

Error Handling and Fallbacks

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 });
});

Single Page Application (SPA) Support

// 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();
});

Development vs. Production

// 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 });
});

Best Practices

  1. Placement: Inject the script as high as possible in the <head> section, after any X-UA-Compatible meta tags
  2. Per-Request Generation: Always generate fresh scripts for each request - never cache or reuse
  3. Error Handling: Check for HTML comments indicating failed generation
  4. CSP Compliance: Use nonce parameter when Content Security Policy is enabled
  5. Environment Control: Consider disabling in development environments
  6. Performance: The script is small but generated per-request, consider caching requirements if performance is critical
  7. HTTPS: Browser monitoring works best with HTTPS applications
  8. Correlation: Browser monitoring data correlates with server-side transaction data automatically when properly implemented

docs

aws-lambda.md

browser-monitoring.md

custom-attributes.md

custom-instrumentation.md

distributed-tracing.md

error-handling.md

index.md

llm-monitoring.md

metrics-events.md

segments-timing.md

transaction-management.md

url-naming-rules.md

utilities.md

tile.json