Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slim down README.md #75

Merged
merged 1 commit into from
May 23, 2024
Merged
Changes from all commits
Commits
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
205 changes: 15 additions & 190 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,198 +1,23 @@
# Pyroscope nodejs package

Enhance your Node.js application’s performance with our Node.js Profiler. Seamlessly integrated with Pyroscope, it provides real-time insights into your application’s operation, helping you identify and resolve performance bottlenecks. This integration is key for Node.js developers aiming to boost efficiency, reduce latency, and maintain optimal application performance.
This is the nodejs profiling package for Grafana Pyroscope. It is based on the
work of [@datadog/pprof](https://github.com/DataDog/pprof-nodejs) and [v8's
sample based profiler][v8-prof]. And it adds:

For more detailed information, please refer to our [documentation page](https://grafana.com/docs/pyroscope/latest/configure-client/language-sdks/nodejs) on using the Node.js language SDK
- Wall and CPU profiles with support for dynamic tags
- Pull mode using express middleware
- Ability to Export to Grafana Pyroscope

## Configuration
## Downloads

| env var | default | description |
| ----------------------------- | ----------------------- | -------------------------------------------------------------------- |
| `PYROSCOPE_SAMPLING_INTERVAL` | `10` | The interval in milliseconds between samples. |
| `PYROSCOPE_SAMPLING_DURATION` | `10000` (10s) | The duration in milliseconds for which you want to collect a sample. |
| `PYROSCOPE_SERVER_ADDRESS` | `http://localhost:4040` | The address of the Pyroscope server. |
| `PYROSCOPE_APPLICATION_NAME` | `""` | The application name used when uploading profiling data. |
| `PYROSCOPE_AUTH_TOKEN` | N/A | The authorization token used to upload profiling data. |
Visit the [npm package][releases] to find the latest version of this package.

## Modes
## Usage

Pyroscope supports two main operation modes:
* Push mode
* Pull mode

Push mode means the package itself uploads profile data to a pyroscope server, while pull mode means you provide pyroscope server with an endpoint(s) to scrape profile data

NodeJS Pyroscope module supports collecting cpu, wall-time, and heap. More details you may find [here](https://cloud.google.com/profiler/docs/concepts-profiling)

## Push mode

Usage differs, first you need to import and init pyroscope module.
Module is available for both CommonJS and ESM variants, so you can use it the way it fits your project.

### Javascript

```javascript
const Pyroscope = require('@pyroscope/nodejs');

Pyroscope.init({serverAddress: 'http://pyroscope:4040', appName: 'nodejs'});
Pyroscope.start();
```

### Typescript:
```typescript
import Pyroscope from '@pyroscope/nodejs';

Pyroscope.init({serverAddress: 'http://pyroscope:4040', appName: 'nodejs'});
Pyroscope.start();
```

Both params `appName` and `serverAddress` are mandatory. Once you `init` you may `startCpuProfiling()`, `startWallProfiling()` and/or `startHeapProfiling()`. `start()` starts both memory and CPU profiling

### Dynamic tags

You may assign certain labels to certain parts of your code by using wrapper function `tagWrapper(tags: Record<string, string | number | undefined>, fn: Function)`. Please note that this is only available for cpu profiling.


```typescript
...

app.get('/scooter', function scooterSearchHandler(req, res) {
Pyroscope.tagWrapper({'vehicle':'scooter'}, () =>
genericSearchHandler(0.1)(req, res)
);
});

```

## Pull Mode

In order to enable pull mode you need to implement the following endpoints:
* `/debug/pprof/profile` -- for wall-time profiling
* `/debug/pprof/heap` -- for heap profiling

You may implement your own enpoints with Pyroscope API, like in the example:

```javascript
Pyroscope.init()

app.get('/debug/pprof/profile', async function handler(req, res) {
console.log('Collecting Cpu for', req.query.seconds);
try {
const p = await Pyroscope.collectCpu(req.query.seconds);
res.send(p);
} catch (e) {
console.error('Error collecting cpu', e);
res.sendStatus(500);
}
});
```

Parameter `appName` is mandatory in pull mode.

## Pull Mode

In order to enable pull mode you need to implement the following endpoints:
* `/debug/pprof/profile` -- for wall-time profiling
* `/debug/pprof/heap` -- for heap profiling

You may implement your own enpoints with Pyroscope API, like in the example:

```javascript
app.get('/debug/pprof/profile', async function handler(req, res) {
console.log('Collecting Cpu for', req.query.seconds);
try {
const p = await Pyroscope.collectCpu(req.query.seconds);
res.send(p);
} catch (e) {
console.error('Error collecting cpu', e);
res.sendStatus(500);
}
});
```

or you may use express middleware.

```javascript
import Pyroscope from '@pyroscope/nodejs'

Pyroscope.init()
const app = express()
app.use(Pyroscope.expressMiddleware());
```

then you also need to configure your pyroscope server by providing config file

```yaml
---
log-level: debug
scrape-configs:
- job-name: testing # any name
enabled-profiles: [cpu, mem] # cpu and mem for cpu and heap
static-configs:
- application: rideshare
spy-name: nodespy # make pyroscope know it's node profiles
targets:
- localhost:3000 # address of your scrape target
labels:
env: dev # labels

```
### Debugging

Use `DEBUG` env var set to `pyroscope` to enable debugging messages. Otherwise, all messages will be suppressed.

`DEBUG=pyroscope node index.js`
## API
### Configuration

```
init(c : PyroscopeConfig)

```

Configuration options
```typescript
interface PyroscopeConfig {
serverAddress?: string; // Server address for push mode
appName?: string; // Application name
tags?: Record<string, any>; // Static tags
sourceMapper?: SourceMapper; // Source maps
basicAuthUser?: string; // Grafana Cloud Authentification
basicAuthPassword?: string; // Grafana Cloud Authentification
}
```

Both `serverAddress` and `appName` are mandatory for push mode.

### CPU Profiling
```javascript
// Start collecting for 10s and push to server
Pyroscope.startCpuProfiling()
Pyroscope.stopCpuProfiling()

// Or do it manually
Pyroscope.collectCpu(seconds?:number);
```

### Wall Profiling
```javascript
// Start collecting for 10s and push to server
Pyroscope.startWallProfiling()
Pyroscope.stopWallProfiling()

// Or do it manually
Pyroscope.collectWall(seconds?:number);
```

### Heap Profiling
```javascript
// Start heap profiling and upload to server
Pyroscope.startHeapProfiling()
Pyroscope.stopHeapProfiling()

// Or do it manually
Pyroscope.startHeapCollecting()
Pyroscope.collectHeap();
Pyroscope.stopHeapCollecting()
```
Visit [docs](https://pyroscope.io/docs/java/) page for usage and configuration documentation.

[Grafana Pyroscope]:https://grafana.com/oss/pyroscope/
[@datadog/pprof]:https://github.com/DataDog/pprof-nodejs
[v8-prof]:https://v8.dev/docs/profile
[docs]:https://grafana.com/docs/pyroscope/latest/configure-client/language-sdks/nodejs
[releases]:https://www.npmjs.com/package/@pyroscope/nodejs