Skip to content

Commit 4661a26

Browse files
committed
feat(pino-transport): Add functionality to send logs to sentry
1 parent 4bbe610 commit 4661a26

File tree

5 files changed

+1075
-24
lines changed

5 files changed

+1075
-24
lines changed

packages/pino-transport/README.md

Lines changed: 264 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,279 @@
1-
# @sentry/pino-transport
1+
# Sentry Pino Transport
22

3-
[![npm version](https://img.shields.io/npm/v/@sentry/pino-transport.svg)](https://www.npmjs.com/package/@sentry/pino-transport)
4-
[![npm dm](https://img.shields.io/npm/dm/@sentry/pino-transport.svg)](https://www.npmjs.com/package/@sentry/pino-transport)
5-
[![npm dt](https://img.shields.io/npm/dt/@sentry/pino-transport.svg)](https://www.npmjs.com/package/@sentry/pino-transport)
3+
A Pino transport for sending logs to Sentry using the Sentry JavaScript SDK.
64

7-
**This package is currently in alpha. Breaking changes may still occur.**
8-
9-
A Pino transport for integrating [Pino](https://github.com/pinojs/pino) logging with [Sentry](https://sentry.io). This transport automatically captures log messages as Sentry events and breadcrumbs, making it easy to monitor your application's logs in Sentry.
5+
This transport forwards Pino logs to Sentry, allowing you to view and analyze your application logs alongside your errors and performance data in Sentry.
106

117
## Installation
128

139
```bash
14-
npm install @sentry/node @sentry/pino-transport
10+
npm install @sentry/pino-transport pino
1511
# or
16-
yarn add @sentry/node @sentry/pino-transport
12+
yarn add @sentry/pino-transport pino
1713
```
1814

19-
## Usage
15+
## Requirements
2016

21-
TODO: Add usage instructions
17+
- Node.js 18+
18+
- Pino v8 or v9
19+
- `@sentry/node` SDK with `_experiments.enableLogs: true`
2220

23-
## Requirements
21+
## Setup
22+
23+
First, make sure Sentry is initialized with logging enabled:
24+
25+
```javascript
26+
import * as Sentry from '@sentry/node';
27+
28+
Sentry.init({
29+
dsn: 'YOUR_DSN',
30+
_experiments: {
31+
enableLogs: true,
32+
},
33+
});
34+
```
35+
36+
Then create a Pino logger with the Sentry transport:
37+
38+
```javascript
39+
import pino from 'pino';
40+
41+
const logger = pino({
42+
transport: {
43+
target: '@sentry/pino-transport',
44+
options: {
45+
// Optional: filter which log levels to send to Sentry
46+
levels: ['error', 'fatal'], // defaults to all levels
47+
},
48+
},
49+
});
50+
51+
// Now your logs will be sent to Sentry
52+
logger.info('This is an info message');
53+
logger.error('This is an error message');
54+
```
55+
56+
### Programmatic Usage
57+
58+
You can also create the transport programmatically:
59+
60+
```javascript
61+
import pino from 'pino';
62+
import { createSentryPinoTransport } from '@sentry/pino-transport';
63+
64+
const transport = pino.transport({
65+
targets: [
66+
{
67+
target: 'pino-pretty', // Console output
68+
level: 'info',
69+
},
70+
{
71+
target: createSentryPinoTransport,
72+
level: 'error',
73+
options: {
74+
levels: ['error', 'fatal'], // Only send errors and fatal logs to Sentry
75+
},
76+
},
77+
],
78+
});
79+
80+
const logger = pino(transport);
81+
```
82+
83+
## Configuration Options
84+
85+
The transport accepts the following options:
86+
87+
### `levels`
88+
89+
**Type:** `Array<'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'>`
90+
**Default:** `['trace', 'debug', 'info', 'warn', 'error', 'fatal']` (all levels)
91+
92+
Use this option to filter which log levels should be sent to Sentry.
93+
94+
```javascript
95+
const transport = pino.transport({
96+
target: '@sentry/pino-transport',
97+
options: {
98+
levels: ['warn', 'error', 'fatal'], // Only send warnings and above
99+
},
100+
});
101+
```
102+
103+
## Log Level Mapping
104+
105+
Pino log levels are automatically mapped to Sentry log severity levels:
106+
107+
| Pino Level | Pino Numeric | Sentry Level |
108+
| ---------- | ------------ | ------------ |
109+
| trace | 10 | trace |
110+
| debug | 20 | debug |
111+
| info | 30 | info |
112+
| warn | 40 | warn |
113+
| error | 50 | error |
114+
| fatal | 60 | fatal |
115+
116+
### Custom Levels Support
117+
118+
Custom numeric levels are mapped to Sentry levels using ranges, so levels like `11`, `23`, or `42` will map correctly:
119+
120+
- `0-14``trace`
121+
- `15-24``debug`
122+
- `25-34``info`
123+
- `35-44``warn`
124+
- `45-54``error`
125+
- `55+``fatal`
126+
127+
```javascript
128+
import pino from 'pino';
129+
130+
const logger = pino({
131+
customLevels: {
132+
critical: 55, // Maps to 'fatal' (55+ range)
133+
notice: 35, // Maps to 'warn' (35-44 range)
134+
verbose: 11, // Maps to 'trace' (0-14 range)
135+
},
136+
transport: {
137+
target: '@sentry/pino-transport',
138+
},
139+
});
140+
141+
logger.critical('Critical issue occurred'); // → Sent as 'fatal' to Sentry
142+
logger.notice('Important notice'); // → Sent as 'warn' to Sentry
143+
logger.verbose('Detailed information'); // → Sent as 'trace' to Sentry
144+
```
145+
146+
#### Custom Level Attributes
147+
148+
When using custom string levels, the original level name is preserved as `sentry.pino.level` attribute for better traceability:
149+
150+
```javascript
151+
// Log entry in Sentry will include:
152+
// {
153+
// level: 'warn', // Mapped Sentry level
154+
// message: 'Audit event',
155+
// attributes: {
156+
// 'sentry.pino.level': 'audit', // Original custom level name
157+
// 'sentry.origin': 'auto.logging.pino',
158+
// // ... other log attributes
159+
// }
160+
// }
161+
```
162+
163+
### Custom Message Key
164+
165+
The transport respects Pino's `messageKey` configuration:
166+
167+
```javascript
168+
const logger = pino({
169+
messageKey: 'message', // Use 'message' instead of default 'msg'
170+
transport: {
171+
target: '@sentry/pino-transport',
172+
},
173+
});
174+
175+
logger.info({ message: 'Hello world' }); // Works correctly with custom messageKey
176+
```
177+
178+
### Nested Key Support
179+
180+
The transport automatically supports Pino's `nestedKey` configuration, which is used to avoid property conflicts by nesting logged objects under a specific key. When `nestedKey` is configured, the transport flattens these nested properties using dot notation for better searchability in Sentry.
181+
182+
```javascript
183+
const logger = pino({
184+
nestedKey: 'payload', // Nest logged objects under 'payload' key
185+
transport: {
186+
target: '@sentry/pino-transport',
187+
},
188+
});
189+
190+
const conflictingObject = {
191+
level: 'hi', // Conflicts with Pino's level
192+
time: 'never', // Conflicts with Pino's time
193+
foo: 'bar',
194+
userId: 123,
195+
};
196+
197+
logger.info(conflictingObject);
198+
199+
// Without nestedKey, this would cause property conflicts
200+
// With nestedKey, Pino creates: { level: 30, time: 1234567890, payload: conflictingObject }
201+
// The transport flattens it to:
202+
// {
203+
// level: 'info',
204+
// message: undefined,
205+
// attributes: {
206+
// 'payload.level': 'hi', // Flattened nested properties
207+
// 'payload.time': 'never',
208+
// 'payload.foo': 'bar',
209+
// 'payload.userId': 123,
210+
// 'sentry.origin': 'auto.logging.pino',
211+
// }
212+
// }
213+
```
214+
215+
This flattening ensures that no property conflicts occur between logged objects and Pino's internal properties.
216+
217+
## Usage Examples
218+
219+
### Basic Logging
220+
221+
```javascript
222+
import pino from 'pino';
223+
224+
const logger = pino({
225+
transport: {
226+
target: '@sentry/pino-transport',
227+
},
228+
});
229+
230+
logger.trace('Starting application');
231+
logger.debug('Debug information', { userId: 123 });
232+
logger.info('User logged in', { userId: 123, username: 'john_doe' });
233+
logger.warn('Deprecated API used', { endpoint: '/old-api' });
234+
logger.error('Database connection failed', { error: 'Connection timeout' });
235+
logger.fatal('Application crashed', { reason: 'Out of memory' });
236+
```
237+
238+
### Multiple Transports
239+
240+
```javascript
241+
import pino from 'pino';
242+
243+
const logger = pino({
244+
transport: {
245+
targets: [
246+
{
247+
target: 'pino-pretty',
248+
options: { colorize: true },
249+
level: 'debug',
250+
},
251+
{
252+
target: '@sentry/pino-transport',
253+
options: {
254+
logLevels: ['warn', 'error', 'fatal'],
255+
},
256+
level: 'warn',
257+
},
258+
],
259+
},
260+
});
261+
```
262+
263+
## Troubleshooting
264+
265+
### Logs not appearing in Sentry
266+
267+
1. Ensure `_experiments.enableLogs: true` is set in your Sentry configuration.
268+
2. Check that your DSN is correct and the SDK is properly initialized.
269+
3. Verify the log level is included in the `levels` configuration.
270+
4. Check your Sentry organization stats page to see if logs are being received by Sentry.
271+
272+
## Related Documentation
24273

25-
- Node.js 18 or higher
26-
- Pino 8.0.0 or higher
27-
- @sentry/node must be configured in your application
274+
- [Sentry Logs Documentation](https://docs.sentry.io/platforms/javascript/guides/node/logs/)
275+
- [Pino Documentation](https://getpino.io/)
276+
- [Pino Transports](https://getpino.io/#/docs/transports)
28277

29278
## License
30279

packages/pino-transport/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
"access": "public"
4040
},
4141
"dependencies": {
42-
"@sentry/core": "9.30.0"
42+
"@sentry/core": "9.30.0",
43+
"pino-abstract-transport": "^2.0.0"
4344
},
4445
"peerDependencies": {
4546
"pino": "^8.0.0 || ^9.0.0"

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy