Skip to content

Commit 7408ba2

Browse files
committed
public version
0 parents  commit 7408ba2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+4053
-0
lines changed

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.DS_Store
2+
._
3+
._.*
4+
build
5+
node_modules
6+
npm-debug.log

.npmignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*.log
2+
node_modules
3+
test
4+
.gitignore
5+
.npmignore

Gruntfile.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
3+
module.exports = function(grunt) {
4+
grunt.initConfig({
5+
pkg: grunt.file.readJSON('package.json'),
6+
jshint: {
7+
files: ['Gruntfile.js', 'lib/**/*.js'],
8+
options: {
9+
node: true,
10+
esversion: 6,
11+
globalstrict: true,
12+
'-W069': true
13+
}
14+
}
15+
});
16+
17+
grunt.loadNpmTasks('grunt-contrib-jshint');
18+
19+
grunt.registerTask('default', [
20+
'jshint'
21+
]);
22+
};
23+

LICENSE

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Copyright (c) 2017, StackImpact GmbH. All rights reserved.
2+
3+
Redistribution and use in source and binary forms, with or without
4+
modification, are permitted provided that the following conditions are met:
5+
* Redistributions of source code must retain the above copyright
6+
notice, this list of conditions and the following disclaimer.
7+
* Redistributions in binary form must reproduce the above copyright
8+
notice, this list of conditions and the following disclaimer in the
9+
documentation and/or other materials provided with the distribution.
10+
* Neither the name of the StackImpact GmbH nor the
11+
names of its contributors may be used to endorse or promote products
12+
derived from this software without specific prior written permission.
13+
14+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17+
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
18+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24+
25+

README.md

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# StackImpact Node.js Agent
2+
3+
## Overview
4+
5+
StackImpact is a performance profiler for production applications. It gives developers continuous and historical view of application performance with line-of-code precision, which includes CPU, memory allocation and blocking call hot spots as well as execution bottlenecks, errors and runtime metrics. Learn more at [stackimpact.com](https://stackimpact.com/).
6+
7+
![dashboard](https://stackimpact.com/wp-content/uploads/2017/09/hotspots-cpu-1.4-nodejs.png)
8+
9+
10+
#### Features
11+
12+
* Continuous hot spot profiling for CPU, memory allocations, blocking calls
13+
* Continuous bottleneck tracing for HTTP handlers and other libraries
14+
* Exception monitoring
15+
* Health monitoring including CPU, memory, garbage collection and other runtime metrics
16+
* Anomaly alerts on most important metrics
17+
* Multiple account users for team collaboration
18+
19+
Learn more on the [features](https://stackimpact.com/features/) page (with screenshots).
20+
21+
22+
#### Documentation
23+
24+
See full [documentation](https://stackimpact.com/docs/) for reference.
25+
26+
27+
28+
## Supported environment
29+
30+
* Linux, OS X or Windows. Node.js v4.0.0 or higher.
31+
* **CPU profiler is disabled by default for Node.js v7.0.0 and higher due to memory leak in underlying V8’s CPU profiler. To enable, add `cpuProfilerDisabled: false` to startup options.**
32+
* Allocation profiler supports Node.js v6.0.0 and higher. **The allocation profiler is disabled by default, since V8’s heap sampling is still experimental and is seen to result in segmentation faults. To enable, add `allocationProfilerDisabled: false` to startup options.**
33+
* Async profiler supports Node.js v8.1.0 and higher.
34+
35+
36+
## Getting started
37+
38+
39+
#### Create StackImpact account
40+
41+
[Sign up](https://dashboard.stackimpact.com/#/signup) for a free account (also with GitHub login).
42+
43+
44+
#### Installing the agent
45+
46+
Install the Node.js agent by running
47+
48+
```
49+
npm install stackimpact
50+
```
51+
52+
And import the package in your application
53+
54+
```javascript
55+
const stackimpact = require('stackimpact');
56+
```
57+
58+
59+
#### Configuring the agent
60+
61+
Start the agent in the main thread by specifying the agent key and application name. The agent key can be found in your account's Configuration section.
62+
63+
```javascript
64+
let agent = stackimpact.start({
65+
agentKey: 'agent key here',
66+
appName = 'MyNodejsApp'
67+
});
68+
```
69+
70+
All initialization options:
71+
72+
* `agentKey` (Required) The API key for communication with the StackImpact servers.
73+
* `appName` (Required) A name to identify and group application data. Typically, a single codebase, deployable unit or executable module corresponds to one application.
74+
* `appVersion` (Optional) Sets application version, which can be used to associate profiling information with the source code release.
75+
* `appEnvironment` (Optional) Used to differentiate applications in different environments.
76+
* `hostName` (Optional) By default, host name will be the OS hostname.
77+
* `debug` (Optional) Enables debug logging.
78+
* `cpuProfilerDisabled`, `allocationProfilerDisabled`, `asyncProfilerDisabled`, `errorProfilerDisabled` (Optional) Disables respective profiler when `true`.
79+
* `includeAgentFrames` (Optional) Set to `true` to not exclude agent stack frames from profiles.
80+
81+
82+
#### Shutting down the agent
83+
84+
Use `agent.destroy()` to stop the agent if necessary, e.g. to allow application to exit.
85+
86+
87+
#### Analyzing performance data in the Dashboard
88+
89+
Once your application is restarted, you can start observing continuous CPU, memory, I/O, and other hot spot profiles, execution bottlenecks as well as process metrics in the [Dashboard](https://dashboard.stackimpact.com/).
90+
91+
92+
#### Troubleshooting
93+
94+
To enable debug logging, add `debug: true` to startup options. If the debug log doesn't give you any hints on how to fix a problem, please report it to our support team in your account's Support section.
95+
96+
97+
## Overhead
98+
99+
The agent overhead is measured to be less than 1% for applications under high load.

binding.gyp

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"targets": [
3+
{
4+
"target_name": "stackimpact-addon",
5+
"sources": [
6+
"src/stackimpact_addon.cc",
7+
"src/heap_stats.cc",
8+
"src/gc_stats.cc",
9+
"src/event_loop_stats.cc",
10+
"src/cpu_profiler.cc",
11+
"src/allocation_sampler.cc"
12+
],
13+
"include_dirs": ["<!(node -e \"require('nan')\")"]
14+
}
15+
]
16+
}

examples/app.js

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
const fs = require('fs');
2+
const http = require('http');
3+
const stackimpact = require('..');
4+
5+
6+
// StackImpact agent initialization
7+
let agent = stackimpact.start({
8+
dashboardAddress: process.env.DASHBOARD_ADDRESS,
9+
agentKey: process.env.AGENT_KEY,
10+
appName: 'ExampleNodejsApp',
11+
appVersion: '1.0.0',
12+
cpuProfilerDisabled: false,
13+
allocationProfilerDisabled: false,
14+
debug: true
15+
});
16+
17+
18+
19+
process.on('uncaughtException', (err) => {
20+
// overwrites default exit behaviour
21+
//console.log(err);
22+
});
23+
24+
process.on('unhandledRejection', (err) => {
25+
// overwrites default exit behaviour
26+
//console.log(err);
27+
});
28+
29+
30+
function cpuWork(usage, duration) {
31+
let usageTimer = setInterval(() => {
32+
for(let i = 0; i < usage * 300000; i++) {
33+
Math.random();
34+
}
35+
}, 1000);
36+
37+
if(duration) {
38+
setTimeout(() => {
39+
clearInterval(usageTimer);
40+
}, duration * 1000);
41+
}
42+
}
43+
44+
45+
function simulateCpu() {
46+
cpuWork(15);
47+
48+
setInterval(() => {
49+
cpuWork(50, 240);
50+
}, 1200 * 1000);
51+
}
52+
53+
54+
function simulateMemLeak() {
55+
let mem1 = [];
56+
var n = 0;
57+
58+
// 30 min
59+
setInterval(() => {
60+
if(n++ > 1800) {
61+
mem1 = [];
62+
n = 0;
63+
}
64+
65+
for(let i = 0; i < 10000; i++) {
66+
obj1 = {'v': Math.random()};
67+
mem1.push(obj1);
68+
}
69+
}, 1000);
70+
71+
// 5 sec
72+
setInterval(() => {
73+
let mem2 = [];
74+
for(let i = 0; i < 1000; i++) {
75+
obj2 = {'v': Math.random()};
76+
mem2.push(obj2);
77+
}
78+
}, 5000);
79+
}
80+
81+
82+
function simulateHttp() {
83+
setInterval(() => {
84+
85+
var options = {
86+
host: '127.0.0.1',
87+
port: 5005
88+
};
89+
90+
var req = http.get(options, (res) => {
91+
});
92+
93+
req.on('error', function(err) {
94+
console.log(err.message);
95+
});
96+
}, 1000);
97+
}
98+
99+
100+
function simulateExceptions() {
101+
setInterval(() => {
102+
if(Math.random() > 0.2) {
103+
setTimeout(() => {
104+
throw new Error('some error ' + Math.round(Math.random() * 10));
105+
}, 1);
106+
}
107+
}, 5 * 1000);
108+
}
109+
110+
111+
function simulateRejections() {
112+
setInterval(() => {
113+
if(Math.random() > 0.2) {
114+
setTimeout(() => {
115+
Promise.reject(new Error('some rejection'));
116+
}, 1);
117+
}
118+
}, 5 * 1000);
119+
}
120+
121+
122+
const server = http.createServer((req, res) => {
123+
fs.readFile('/tmp', () => {
124+
setTimeout(() => {
125+
cpuWork(10, 2);
126+
127+
res.statusCode = 200;
128+
res.setHeader('Content-Type', 'text/plain');
129+
res.end('Hello World\n');
130+
}, 500);
131+
});
132+
});
133+
134+
server.listen(5005, '127.0.0.1', () => {
135+
console.log('App running');
136+
137+
simulateCpu();
138+
simulateMemLeak();
139+
simulateHttp();
140+
simulateExceptions();
141+
simulateRejections();
142+
});

index.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
let Agent = require('./lib/agent').Agent;
2+
3+
4+
let agent = null;
5+
6+
exports.start = function(opts) {
7+
if(!agent) {
8+
agent = new Agent();
9+
}
10+
11+
agent.start(opts);
12+
return agent;
13+
};

0 commit comments

Comments
 (0)