Skip to content

Commit 3c012d0

Browse files
AbhiPrasadchargome
andauthored
feat(pino-transport): Add functionality to send logs to sentry (#16667)
ref #15952 resolves #16622 This PR adds the ability to send logs to sentry via a pino transport. ## Usage ```js import pino from 'pino'; const logger = pino({ transport: { target: '@sentry/pino-transport', options: { // Optional: filter which log levels to send to Sentry logLevels: ['error', 'fatal'], // defaults to all levels }, }, }); // Now your logs will be sent to Sentry logger.info('This is an info message'); logger.error('This is an error message'); ``` ### Options #### `logLevels` **Type:** `Array<'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'>` **Default:** `['trace', 'debug', 'info', 'warn', 'error', 'fatal']` (all levels) Use this option to filter which log levels should be sent to Sentry. ```javascript const transport = pino.transport({ target: '@sentry/pino-transport', options: { logLevels: ['warn', 'error', 'fatal'], // Only send warnings and above }, }); ``` ## Next I need to write some integration tests - this is being tracked by #16624 --------- Co-authored-by: Charly Gomez <[email protected]>
1 parent 63b255f commit 3c012d0

File tree

8 files changed

+1218
-23
lines changed

8 files changed

+1218
-23
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,6 @@ below:
112112
Provides the integration for Session Replay.
113113
- [`@sentry/core`](https://github.com/getsentry/sentry-javascript/tree/master/packages/core): The base for all
114114
JavaScript SDKs with interfaces, type definitions and base classes.
115-
- [`@sentry/pino-transport`](https://github.com/getsentry/sentry-javascript/tree/master/packages/pino-transport): Pino
116-
transport for automatically sending log messages to Sentry.
117115

118116
## Bug Bounty Program
119117

packages/pino-transport/README.md

Lines changed: 251 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,267 @@
1-
# @sentry/pino-transport
1+
<p align="center">
2+
<a href="https://sentry.io/?utm_source=github&utm_medium=logo" target="_blank">
3+
<img src="https://sentry-brand.storage.googleapis.com/sentry-wordmark-dark-280x84.png" alt="Sentry" width="280" height="84">
4+
</a>
5+
</p>
26

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)
7+
# Official Sentry Pino Transport
68

7-
**This package is currently in alpha. Breaking changes may still occur.**
9+
[![npm version](https://img.shields.io/npm/v/@sentry/solid.svg)](https://www.npmjs.com/package/@sentry/solid)
10+
[![npm dm](https://img.shields.io/npm/dm/@sentry/solid.svg)](https://www.npmjs.com/package/@sentry/solid)
11+
[![npm dt](https://img.shields.io/npm/dt/@sentry/solid.svg)](https://www.npmjs.com/package/@sentry/solid)
812

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.
13+
**WARNING**: This transport is in a **pre-release alpha**. The API is unstable and may change at any time.
14+
15+
A Pino transport for sending logs to Sentry using the Sentry JavaScript SDK.
16+
17+
This transport forwards Pino logs to Sentry, allowing you to view and analyze your application logs alongside your errors and performance data in Sentry.
1018

1119
## Installation
1220

1321
```bash
14-
npm install @sentry/node @sentry/pino-transport
22+
npm install @sentry/pino-transport pino
1523
# or
16-
yarn add @sentry/node @sentry/pino-transport
24+
yarn add @sentry/pino-transport pino
25+
# or
26+
pnpm add @sentry/pino-transport pino
1727
```
1828

19-
## Usage
29+
## Requirements
30+
31+
- Node.js 18+
32+
- Pino v8 or v9
33+
- `@sentry/node` SDK with `_experiments.enableLogs: true`
2034

21-
TODO: Add usage instructions
35+
## Setup
2236

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

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

29266
## License
30267

packages/pino-transport/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
"access": "public"
4040
},
4141
"dependencies": {
42-
"@sentry/core": "9.31.0"
42+
"@sentry/node": "9.31.0",
43+
"@sentry/core": "9.31.0",
44+
"pino-abstract-transport": "^2.0.0"
4345
},
4446
"peerDependencies": {
4547
"pino": "^8.0.0 || ^9.0.0"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
declare const __DEBUG_BUILD__: boolean;
2+
3+
/**
4+
* This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.
5+
*
6+
* ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking.
7+
*/
8+
export const DEBUG_BUILD = __DEBUG_BUILD__;

0 commit comments

Comments
 (0)