Skip to content
This repository was archived by the owner on Jun 18, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a582ea9
Initial drop of nodereport project for nodejs repo
rnchamberlain Aug 25, 2016
410958e
Fix for RUSAGE_THREAD not supported on OSX
rnchamberlain Sep 5, 2016
3af9796
Fix compiler warnings for timeval tv_usec on OSX
rnchamberlain Sep 5, 2016
fd87c96
Fix whitespace and CRLF line endings
rnchamberlain Sep 6, 2016
3f0ad28
Fix formatting/style issues in binding and package files
rnchamberlain Sep 6, 2016
e7a5266
Remove hard-coded filename and path lengths
rnchamberlain Sep 6, 2016
2d9d7bc
Add error handling for uv calls, remove duplicate code
rnchamberlain Sep 8, 2016
01fc6b0
Remove unnecessary ToString call for Nan parameters
rnchamberlain Sep 9, 2016
069fa32
Remove redundant passing of signal nr via callbacks
rnchamberlain Sep 9, 2016
26b25c1
Fix FreeBSD issues, and use secure_getenv()
rnchamberlain Sep 9, 2016
9d330b3
Fix for secure_getenv() not available on OSX
rnchamberlain Sep 9, 2016
2e64d34
Wrap code in nodereport namespace
rnchamberlain Sep 12, 2016
c6ecd33
Replace strcpy calls with safer snprintf
rnchamberlain Sep 13, 2016
dccc0e5
Move snprintf and arraysize definitions to header file
rnchamberlain Sep 13, 2016
f7b8a3c
Minor changes, indents, comments, casts, variable names
rnchamberlain Sep 13, 2016
af73614
Separate functions for report sections, plus fix minor nits
rnchamberlain Oct 3, 2016
bd8b06b
Fix missing mutex initialization (OSX aborts on signal)
rnchamberlain Oct 3, 2016
0f2093b
Fix .js files to use 2 space indentation
rnchamberlain Oct 5, 2016
56e9ee1
Fix API to allow live changes to trigger signal
rnchamberlain Oct 10, 2016
efb729e
Trigger events other than API are off by default
rnchamberlain Oct 12, 2016
2b5e0a0
Missing ifdef, no signal support on Windows
rnchamberlain Oct 12, 2016
4365862
Improve signal functions, fix K&Risms, whitespace etc
rnchamberlain Oct 14, 2016
a46a004
Fix for __func__ not available on VS 2013
rnchamberlain Oct 14, 2016
7cd3f76
Add local secure_getenv() and fix sizeof call
rnchamberlain Oct 17, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app
*.node

# Project files
*.project
*.cproject

# Build directories
/build/
/node_modules/
59 changes: 57 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,65 @@
# nodereport

nodereport is an add-on for Node.js, delivered as an NPM module,
nodereport is an add-on for Node.js, delivered as an NPM native module,
which provides a human-readable diagnostic summary report, written
to file. The report is intended for development, test and production
use, to capture and preserve information for problem determination.
It includes Javascript and native stack traces, heap statistics,
platform information and resource usage etc. With the report enabled,
reports are triggered on unhandled exceptions, fatal errors, signals
reports can be triggered on unhandled exceptions, fatal errors, signals
and calls to a Javascript API.

Usage:

npm install nodejs/nodereport

var nodereport = require('nodereport');

By default, this will allow a NodeReport to be triggered via an API
call from a JavaScript application. The filename of the NodeReport is
returned. The default filename includes the date, time, PID and a
sequence number. Alternatively a filename can be specified on the API call.

nodereport.triggerReport();

var filename = nodereport.triggerReport();

nodereport.triggerReport("myReportName");

Content of the NodeReport in the initial implementation consists of a
header section containing the event type, date, time, PID and Node version,
sections containing Javascript and native stack traces, a section containing
V8 heap information, a section containing libuv handle information and an OS
platform information section showing CPU and memory usage and system limits.
The following messages are issued to stderr when a NodeReport is triggered:

Writing Node.js error report to file: NodeReport.201605113.145311.26249.001.txt
Node.js error report completed

A NodeReport can also be triggered on unhandled exception and fatal error
events, and/or signals (Linux/OSX only). These and other options can be
enabled or disabled using the following APIs:

nodereport.setEvents("exception+fatalerror+signal+apicall");
nodereport.setSignal("SIGUSR2|SIGQUIT");
nodereport.setFileName("stdout|stderr|<filename>");
nodereport.setDirectory("<full path>");
nodereport.setCoreDump("yes|no");
nodereport.setVerbose("yes|no");

Configuration on module initialisation is also available via environment variables:

export NODEREPORT_EVENTS=exception+fatalerror+signal+apicall
export NODEREPORT_SIGNAL=SIGUSR2|SIGQUIT
export NODEREPORT_FILENAME=stdout|stderr|<filename>
export NODEREPORT_DIRECTORY=<full path>
export NODEREPORT_COREDUMP=yes|no
export NODEREPORT_VERBOSE=yes|no

Sample programs for triggering NodeReports are provided in the
node_modules/nodereport/demo directory:

api.js - NodeReport triggered by Javascript API call
exception.js - NodeReport triggered by unhandled exception
fatalerror.js - NodeReport triggered by fatal error on Javascript heap out of memory
loop.js - looping application, NodeReport triggered using kill -USR2 <pid>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is some trailing whitespace in this file.

30 changes: 30 additions & 0 deletions binding.gyp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"targets": [
{
"target_name": "nodereport",
"sources": [ "src/node_report.cc", "src/module.cc" ],
"include_dirs": [ '<!(node -e "require(\'nan\')")' ],
"conditions": [
["OS=='linux'", {
"defines": [ "_GNU_SOURCE" ],
"cflags": [ "-g", "-O2", "-std=c++11", ],
}],
["OS=='win'", {
"libraries": [ "dbghelp.lib" ],
"dll_files": [ "dbghelp.dll" ],
}],
],
},
{
"target_name": "install",
"type":"none",
"dependencies" : [ "nodereport" ],
"copies": [
{
"destination": "<(module_root_dir)",
"files": ["<(module_root_dir)/build/Release/nodereport.node"]
}]
},
],
}

@bnoordhuis bnoordhuis Sep 1, 2016 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent use of single and double quotes in this file.

EDIT: Not just in this file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^-- comment not addressed. js uses 4 SPC indents, c++ uses 2? I suggest pulling the eslint config from nodejs to keep some consistency of code, and make it easier for people to contribute consistent code to the project.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to using the ESLint config from core.

35 changes: 35 additions & 0 deletions demo/api_call.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Example - generation of NodeReport via API call
var nodereport = require('nodereport');
var http = require("http");

var count = 0;

function my_listener(request, response) {
switch(count++) {
case 0:
response.writeHead(200,{"Content-Type": "text/plain"});
response.write("\nRunning NodeReport API demo... refresh page to trigger NodeReport");
response.end();
break;
case 1:
response.writeHead(200,{"Content-Type": "text/plain"});
// Call the nodereport module to trigger a NodeReport
var filename = nodereport.triggerReport();
response.write("\n" + filename + " written - refresh page to close");
response.end();
break;
default:
process.exit(0);
}
}

var http_server = http.createServer(my_listener);
http_server.listen(8080);

console.log('api_call.js: Node running');
console.log('api_call.js: Go to http://<machine>:8080/ or http://localhost:8080/');

setTimeout(function(){
console.log('api_call.js: test timeout expired, exiting.');
process.exit(0);
}, 60000);
33 changes: 33 additions & 0 deletions demo/exception.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Example - generation of NodeReport on uncaught exception
require('nodereport').setEvents("exception");
var http = require("http");

var count = 0;

function my_listener(request, response) {
switch(count++) {
case 0:
response.writeHead(200,{"Content-Type": "text/plain"});
response.write("\nRunning NodeReport exception demo... refresh page to cause exception (application will terminate)");
response.end();
break;
default:
throw new UserException('*** exception.js: exception thrown from my_listener()');
}
}

function UserException(message) {
this.message = message;
this.name = "UserException";
}

var http_server = http.createServer(my_listener);
http_server.listen(8080);

console.log('exception.js: Node running');
console.log('exception.js: Go to http://<machine>:8080/ or http://localhost:8080/');

setTimeout(function() {
console.log('exception.js: test timeout expired, exiting.');
process.exit(0);
}, 60000);
41 changes: 41 additions & 0 deletions demo/fatalerror.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Example - generation of Nodereport on fatal error (Javascript heap OOM)
require('nodereport').setEvents("fatalerror");
var http = require('http');

var count = 0;

function my_listener(request, response) {
switch(count++) {
case 0:
response.writeHead(200,{"Content-Type": "text/plain"});
response.write("\nRunning NodeReport fatal error demo... refresh page to trigger excessive memory usage (application will terminate)");
response.end();
break;
case 1:
console.log('heap_oom.js: allocating excessive Javascript heap memory....');
var list = [];
while (true) {
list.push(new MyRecord());
}
response.end();
break;
}
}

function MyRecord() {
this.name = 'foo';
this.id = 128;
this.account = 98454324;
}

var http_server = http.createServer(my_listener);
http_server.listen(8080);

console.log('fatalerror.js: Node running');
console.log('fatalerror.js: Note: heap default is 1.4Gb, use --max-old-space-size=<size in Mb> to change');
console.log('fatalerror.js: Go to http://<machine>:8080/ or http://localhost:8080/');

setTimeout(function(){
console.log('fatalerror.js: timeout expired, exiting.');
process.exit(0);
}, 60000);
53 changes: 53 additions & 0 deletions demo/loop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Example - geneation of Nodereport via signal for a looping application
require('nodereport').setEvents("signal");
var http = require("http");

var count = 0;

function my_listener(request, response) {
switch(count++) {
case 0:
response.writeHead(200,{"Content-Type": "text/plain"});
response.write("\nRunning NodeReport looping application demo. Node process ID = " + process.pid);
response.write("\n\nRefresh page to enter loop, then use 'kill -USR2 " + process.pid + "' to trigger NodeReport");
response.end();
break;
case 1:
console.log("loop.js: going to loop now, use 'kill -USR2 " + process.pid + "' to trigger NodeReport");
var list = [];
for (var i=0; i<10000000000; i++) {
for (var j=0; i<1000; i++) {
list.push(new MyRecord());
}
for (var j=0; i<1000; i++) {
list[j].id += 1;
list[j].account += 2;
}
for (var j=0; i<1000; i++) {
list.pop();
}
}
response.writeHead(200,{"Content-Type": "text/plain"});
response.write("\nNodeReport demo.... finished looping");
response.end();
break;
default:
}
}

function MyRecord() {
this.name = 'foo';
this.id = 128;
this.account = 98454324;
}

var http_server = http.createServer(my_listener);
http_server.listen(8080);

console.log('loop.js: Node running');
console.log('loop.js: Go to http://<machine>:8080/ or http://localhost:8080/');

setTimeout(function() {
console.log('loop.js: timeout expired, exiting.');
process.exit(0);
}, 60000);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

21 changes: 21 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "nodereport",
"main": "build/Release/nodereport.node",
"version": "0.1.0",
"description": "Diagnostic NodeReport",
"homepage": "https://github.com/nodejs/nodereport",
"repository": {
"type": "git",
"url": "https://github.com/nodejs/nodereport.git"
},
"engines": {
"node": ">=4.0.0"
},
"dependencies": {
"nan": "^2.3.5"
},
"license": "MIT",
"scripts": {
"test": "node test/autorun.js"
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add the scripts entry so that the tests are run when you type
npm test

Loading