Diagnostic report

更新时间:
复制 MD 格式

Feature description

Most diagnostic features in Node.js Performance Platform help locate faults by collecting information from a specific perspective. For example, heap snapshots are used for memory issues, and profiling is used for CPU issues. These features collect data over a period to help identify problems.

A diagnostic report captures the instantaneous state of a process from a global perspective. It collects information such as stacks, system resources, and platform details to help locate faults. The JavaScriptStack is especially useful for pinpointing issues caused by long-running regular expressions and infinite loops.

Supported versions for each branch:

  • 2.x: v2.5.2

  • 3.x: v3.11.8

  • 4.x: v4.3.0

Note: This feature requires that the commandx dependency of agenthub/egg-alinode is version 1.5.3 or later. Otherwise, the operation fails.

User guide

On the instance page, click Scrape Performance Data and select Diagnostic Report. On the data trends page, click Diagnostic Report. The current runtime state of the application is then output in json format to help locate faults.

The following list contains some of the most helpful output items for locating problems. Generate a diagnostic report to see the full details.

  • JavaScriptStack: The current JavaScript execution stack.

  • NativeStack: The current C++ execution stack.

  • JsHeapGcInfo: Information about each space on the heap.

  • resource: Process resource information and event loop resource information.

  • libuvHandleSummary: libuv handle information.

  • system: System environment variables, resource limits, and dynamic-link libraries.

  • FileName: The full path of the diagnostic report file.

  • NodeJsVersion: The corresponding Node.js version.

  • alinodeVersion: The runtime version of Node.js Performance Platform.

  • execPath: The path of the runtime binary file.

Online analysis

On the Files page, wait for the diagnostic report to generate. Click Dump to save the application's diagnostic report file to the cloud. Then, click Analyze to perform an online analysis:

The online analysis page displays information from the diagnostic report, such as the JavaScript Stack, Native Stack, Heap Distribution, Libuv Handles, and System Details. The following application example provides more details.

Application example

  • Copy the demo.js code to a server or local machine and save it as demo.js. Make sure agenthub is running, and then run the file.

$ node demo.js

http listen at 8080 pid:  26542
  • In a browser, open http://[your_server_address]:8080.

  • Click Trigger Long Running Regular Expression or Trigger Infinite Loop JS function to trigger a long-running regular expression or an infinite loop.

  • Then, in Node.js Performance Platform, find the process by its PID. Click Diagnostic Report. Go to the Files page, click Dump, and then click Analyze to perform an online analysis.

The most useful information, the JavaScript Stack, is shown first:

js-stack

The process is blocked at the regexpCase() function invocation. At line 18, column 23, the replace operation triggered abnormal regular expression backtracking. This caused the entire process to block.

The remaining information helps pinpoint the problem, as shown in the following figures.

  • Native stack information

native-stack

  • Heap distribution

heap

  • Libuv handle information

libuv

  • System details (includes the current process environment variables, system resource limits, and shared libraries)

Additional information

  • The diagnostic report feature is based on node-report.

  • To automatically generate a diagnostic report when a FatalError or Exception occurs, set the DIAGNOSTIC_EVENTS environment variable to fatalerror, exception, or fatalerror+exception.

demo.js code

'use strict';
const http = require('http');

const regexpCase = function() {
  let str = '<br/>                                             ' +
    '           Enjoy free time after breakfast, then gather at the specified time to check out on your own.';
  str += '<br/>                                      <br/>' +
    '                                        <br/>           ' +
    '                         <br/>';
  str += '                                    <br/>' +
    '                                                        ' +
    '                                                        ' +
    '        <br/>';
  str += '                                                <br/>                                                                                                                <br/>';
  str += '                                                     ' +
    '                                                        ' +
    '       Go to the Siem Reap airport on your own according to the flight schedule to return to China.<br/>';
  str += 'If airport transfer service is needed, an additional 280 will be charged per order.<br/>';

  let r = String(str).replace(/(^(\s*?<br[\s\/]*?>\*?)+|(\s*?<br[\s\/]*?>\s*?)+?$)/igm, '');
};


const findSomething = function(from) {
  // find something from 'from'
  return [];
};

const deadLoopCase = function() {
  let selected = [];
  let curArr = ['item1', 'item2', 'item3'];
  let arr = [];

  while(selected.length < curArr.length) {
    const dp = findSomething(curArr)[0];
    //if (typeof dp === 'undefined') {
    //  break;
    //}
    if (selected.indexOf(dp) === -1) {
      selected.push(dp);
    } else {
      arr = arr.filter(val => {
        return val != dp
      })
    }
  }
};


http.createServer( (req, res) => {
  console.log(req.url);

  switch(req.url) {
    case '/regexp': {
      regexpCase();
      res.end('regexp case');
    } break;
    case '/deadloop': {
      deadLoopCase();
      res.end('deadloop case');
    } break;
    case '/exit': {
      process.exit(0);
    } break;
    default: {
      res.writeHead(200, "OK",{'Content-Type': 'text/html'});
      res.write('<html><head><title>Node.js</title></head><body style="font-family:arial;">');
      res.write('<h2> Regular Expression and Dead Loop Detection Example</h2>');

      res.write('<p>Click on button below to trigger long time running regexp test.');
      res.write('<form enctype="application/x-www-form-urlencoded" action="/regexp" method="post">');
      res.write('<button>Trigger Long Running Regular Expression</button></form>');

      res.write('<p>Click on button below to enter JavaScript dead loop test');
      res.write('<form enctype="application/x-www-form-urlencoded" action="/deadloop" method="post">');
      res.write('<button>Trigger Dead Loop JS function</button></form>');

      res.write('<p>The test can be terminated only before the above cases triggered.');
      res.write('<form enctype="application/x-www-form-urlencoded" action="/exit" method="post">');
      res.write('<button>Exit Test</button></form>');
      res.write('</form></body></html');
      res.end();
    } break;
  }
}).listen(8080);

console.log('\nhttp listen at 8080 pid: ', process.pid);