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

segments-timing.mddocs/

Segments & Timing

Create custom timing segments for specific operations and code blocks within transactions.

Capabilities

Start Segment

Wrap a function in a segment to track its execution time and optionally record it as a metric.

/**
 * Wraps a function in a segment for custom timing. Must be called within an active transaction.
 * @param {string} name - The name for the segment and optional metric
 * @param {boolean} record - Whether to record the segment as a metric
 * @param {Function} handler - The function to track as a segment
 * @param {Function} [callback] - Optional callback for async operations
 * @returns {*} The return value of the handler function
 */
function startSegment(name, record, handler, callback);

Usage Examples:

const newrelic = require('newrelic');

// Simple synchronous segment
function processData(data) {
  return newrelic.startSegment('DataProcessing', true, () => {
    // This work will be timed and recorded as a metric
    return performExpensiveCalculation(data);
  });
}

// Asynchronous segment with callback
function fetchUserData(userId, callback) {
  newrelic.startSegment('FetchUser', true, (cb) => {
    database.getUser(userId, cb);
  }, callback);
}

// Asynchronous segment with promises
async function processOrder(orderId) {
  return newrelic.startSegment('OrderProcessing', true, async () => {
    const order = await database.getOrder(orderId);
    const processed = await processPayment(order);
    await updateInventory(order.items);
    return processed;
  });
}

// Segment without metric recording (for tracing only)
function validateInput(input) {
  return newrelic.startSegment('InputValidation', false, () => {
    return validator.validate(input);
  });
}

Segment Behavior

Recording vs. Non-Recording Segments

  • Recording segments (record: true): Create metrics that appear in transaction breakdown and server breakdown graphs
  • Non-recording segments (record: false): Only appear in transaction traces for detailed timing information

Automatic Timing

Segments automatically:

  • Start timing when the handler function begins execution
  • End timing when the handler function completes
  • Handle both synchronous and asynchronous operations
  • Preserve return values and thrown exceptions

Context Requirements

  • Must be called within an active transaction
  • If called outside a transaction, the handler executes normally but no segment is created
  • Warning is logged when called outside transaction context

Common Usage Patterns

Database Operation Timing

async function getUserWithProfile(userId) {
  const user = await newrelic.startSegment('Database/GetUser', true, async () => {
    return await database.users.findById(userId);
  });
  
  const profile = await newrelic.startSegment('Database/GetProfile', true, async () => {
    return await database.profiles.findByUserId(userId);
  });
  
  return { user, profile };
}

External Service Calls

async function callPaymentService(paymentData) {
  return newrelic.startSegment('External/PaymentService', true, async () => {
    const response = await httpClient.post('/api/payments', paymentData);
    return response.data;
  });
}

async function callMultipleServices(data) {
  const [userService, orderService, notificationService] = await Promise.all([
    newrelic.startSegment('External/UserService', true, () => 
      userServiceClient.updateUser(data.user)
    ),
    newrelic.startSegment('External/OrderService', true, () => 
      orderServiceClient.createOrder(data.order)
    ),
    newrelic.startSegment('External/NotificationService', true, () => 
      notificationClient.sendEmail(data.notification)
    )
  ]);
  
  return { userService, orderService, notificationService };
}

Complex Business Logic Timing

async function processComplexWorkflow(workflowData) {
  // Validate input (trace only, no metric)
  const validatedData = newrelic.startSegment('Workflow/Validation', false, () => {
    return validateWorkflowData(workflowData);
  });
  
  // Initialize workflow (recorded as metric)
  const workflow = await newrelic.startSegment('Workflow/Initialize', true, async () => {
    return await initializeWorkflow(validatedData);
  });
  
  // Execute each step with timing
  const results = [];
  for (let i = 0; i < workflow.steps.length; i++) {
    const step = workflow.steps[i];
    const result = await newrelic.startSegment(`Workflow/Step${i + 1}`, true, async () => {
      return await executeWorkflowStep(step, results);
    });
    results.push(result);
  }
  
  // Finalize workflow
  return newrelic.startSegment('Workflow/Finalize', true, async () => {
    return await finalizeWorkflow(workflow, results);
  });
}

Cache Operations

async function getCachedData(key) {
  // Check cache (trace timing but don't record as metric)
  let data = newrelic.startSegment('Cache/Get', false, () => {
    return cache.get(key);
  });
  
  if (!data) {
    // Cache miss - fetch from database (record as metric)
    data = await newrelic.startSegment('Database/FetchForCache', true, async () => {
      return await database.getData(key);
    });
    
    // Store in cache (trace only)
    newrelic.startSegment('Cache/Set', false, () => {
      cache.set(key, data, 3600); // 1 hour TTL
    });
  }
  
  return data;
}

File System Operations

const fs = require('fs').promises;

async function processFile(filePath) {
  // Read file with timing
  const content = await newrelic.startSegment('FileSystem/Read', true, async () => {
    return await fs.readFile(filePath, 'utf8');
  });
  
  // Process content
  const processed = newrelic.startSegment('FileProcessing/Parse', true, () => {
    return parseFileContent(content);
  });
  
  // Transform data
  const transformed = newrelic.startSegment('FileProcessing/Transform', true, () => {
    return transformData(processed);
  });
  
  // Write result
  await newrelic.startSegment('FileSystem/Write', true, async () => {
    const outputPath = filePath.replace('.input', '.output');
    return await fs.writeFile(outputPath, JSON.stringify(transformed));
  });
  
  return transformed;
}

CPU-Intensive Operations

function performAnalytics(dataset) {
  // Data preparation
  const prepared = newrelic.startSegment('Analytics/DataPrep', true, () => {
    return dataset.map(item => normalizeData(item));
  });
  
  // Statistical calculations
  const stats = newrelic.startSegment('Analytics/Statistics', true, () => {
    return {
      mean: calculateMean(prepared),
      median: calculateMedian(prepared),
      standardDeviation: calculateStdDev(prepared)
    };
  });
  
  // Generate report
  const report = newrelic.startSegment('Analytics/ReportGeneration', true, () => {
    return generateAnalyticsReport(prepared, stats);
  });
  
  return report;
}

Error Handling in Segments

async function robustOperation(data) {
  try {
    return await newrelic.startSegment('RobustOperation/Execute', true, async () => {
      const validated = validateData(data);
      const processed = await processData(validated);
      return processed;
    });
  } catch (error) {
    // Errors are automatically captured by the segment
    // Add additional context if needed
    newrelic.addCustomAttribute('operationFailed', true);
    newrelic.noticeError(error, {
      operation: 'RobustOperation',
      dataSize: data?.length || 0
    });
    throw error;
  }
}

Nested Segments

async function nestedOperations(data) {
  return newrelic.startSegment('MainOperation', true, async () => {
    
    // Level 1 nested segment
    const prepared = await newrelic.startSegment('MainOperation/Preparation', true, async () => {
      
      // Level 2 nested segments
      const cleaned = newrelic.startSegment('Preparation/DataCleaning', false, () => {
        return cleanData(data);
      });
      
      const validated = newrelic.startSegment('Preparation/Validation', false, () => {
        return validateData(cleaned);
      });
      
      return { cleaned, validated };
    });
    
    // Another level 1 segment
    const result = await newrelic.startSegment('MainOperation/Processing', true, async () => {
      return await processData(prepared.validated);
    });
    
    return result;
  });
}

Conditional Segment Recording

function adaptiveSegmentRecording(data, options = {}) {
  const shouldRecord = options.recordMetrics !== false;
  const segmentName = options.segmentName || 'AdaptiveOperation';
  
  return newrelic.startSegment(segmentName, shouldRecord, () => {
    if (data.length > 1000) {
      // For large datasets, add sub-segments
      return newrelic.startSegment(`${segmentName}/LargeDataset`, shouldRecord, () => {
        return processLargeDataset(data);
      });
    } else {
      return processSmallDataset(data);
    }
  });
}

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