winston-prisma 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +1236 -0
  3. package/dist/winston.js +157 -0
  4. package/dist/winston_prisma/common.js +45 -0
  5. package/dist/winston_prisma/config/index.js +37 -0
  6. package/dist/winston_prisma/config/prisma-config.js +32 -0
  7. package/dist/winston_prisma/container.js +114 -0
  8. package/dist/winston_prisma/create-logger.js +104 -0
  9. package/dist/winston_prisma/exception-handler.js +228 -0
  10. package/dist/winston_prisma/exception-stream.js +56 -0
  11. package/dist/winston_prisma/logger.js +608 -0
  12. package/dist/winston_prisma/profiler.js +52 -0
  13. package/dist/winston_prisma/rejection-handler.js +228 -0
  14. package/dist/winston_prisma/tail-file.js +115 -0
  15. package/dist/winston_prisma/transports/console.js +110 -0
  16. package/dist/winston_prisma/transports/file.js +670 -0
  17. package/dist/winston_prisma/transports/http.js +238 -0
  18. package/dist/winston_prisma/transports/index.js +56 -0
  19. package/dist/winston_prisma/transports/stream.js +63 -0
  20. package/index.d.ts +220 -0
  21. package/lib/winston.js +180 -0
  22. package/lib/winston_prisma/common.js +46 -0
  23. package/lib/winston_prisma/config/index.d.ts +99 -0
  24. package/lib/winston_prisma/config/index.js +35 -0
  25. package/lib/winston_prisma/config/prisma-config.js +32 -0
  26. package/lib/winston_prisma/container.js +118 -0
  27. package/lib/winston_prisma/create-logger.js +104 -0
  28. package/lib/winston_prisma/exception-handler.js +245 -0
  29. package/lib/winston_prisma/exception-stream.js +54 -0
  30. package/lib/winston_prisma/logger.js +676 -0
  31. package/lib/winston_prisma/profiler.js +53 -0
  32. package/lib/winston_prisma/rejection-handler.js +251 -0
  33. package/lib/winston_prisma/tail-file.js +124 -0
  34. package/lib/winston_prisma/transports/console.js +117 -0
  35. package/lib/winston_prisma/transports/file.js +732 -0
  36. package/lib/winston_prisma/transports/http.js +258 -0
  37. package/lib/winston_prisma/transports/index.d.ts +106 -0
  38. package/lib/winston_prisma/transports/index.js +56 -0
  39. package/lib/winston_prisma/transports/stream.js +63 -0
  40. package/package.json +74 -0
package/README.md ADDED
@@ -0,0 +1,1236 @@
1
+ # winston-prisma
2
+
3
+ A logger for just about everything + prisma log.
4
+ [![Version npm](https://img.shields.io/npm/v/winston.svg?style=flat-square)](https://www.npmjs.com/package/winston)
5
+ [![npm Downloads](https://img.shields.io/npm/dm/winston.svg?style=flat-square)](https://npmcharts.com/compare/winston?minimal=true)
6
+ [![build status](https://github.com/winstonjs/winston/actions/workflows/ci.yml/badge.svg)](https://github.com/winstonjs/winston/actions/workflows/ci.yml)
7
+ [![coverage status](https://coveralls.io/repos/github/winstonjs/winston/badge.svg?branch=master)](https://coveralls.io/github/winstonjs/winston?branch=master)
8
+
9
+ [![NPM](https://nodei.co/npm/winston.png?downloads=true&downloadRank=true)](https://nodei.co/npm/winston/)
10
+
11
+ ## winston-prisma
12
+
13
+ See the [Upgrade Guide](UPGRADE-3.0.md) for more information. Bug reports and
14
+ PRs welcome!
15
+
16
+ ## Looking for `winston@2.x` documentation?
17
+
18
+ Please note that the documentation below is for `winston-prisma`.
19
+ [Read the `winston@2.x` documentation].
20
+
21
+ ## Motivation
22
+
23
+ `winston` is designed to be a simple and universal logging library with
24
+ support for multiple transports. A transport is essentially a storage device
25
+ for your logs. Each `winston` logger can have multiple transports (see:
26
+ [Transports]) configured at different levels (see: [Logging levels]). For
27
+ example, one may want error logs to be stored in a persistent remote location
28
+ (like a database), but all logs output to the console or a local file.
29
+
30
+ `winston` aims to decouple parts of the logging process to make it more
31
+ flexible and extensible. Attention is given to supporting flexibility in log
32
+ formatting (see: [Formats]) & levels (see: [Using custom logging levels]), and
33
+ ensuring those APIs decoupled from the implementation of transport logging
34
+ (i.e. how the logs are stored / indexed, see: [Adding Custom Transports]) to
35
+ the API that they exposed to the programmer.
36
+
37
+ ## Quick Start
38
+
39
+ TL;DR? Check out the [quick start example][quick-example] in `./examples/`.
40
+ There are a number of other examples in [`./examples/*.js`][examples].
41
+ Don't see an example you think should be there? Submit a pull request
42
+ to add it!
43
+
44
+ ## Usage
45
+
46
+ The recommended way to use `winston` is to create your own logger. The
47
+ simplest way to do this is using `winston.createLogger`:
48
+
49
+ ``` js
50
+ const winston = require('winston');
51
+ const prismalog = winston.prismalog();
52
+
53
+ const logger = winston.createLogger({
54
+ level: 'info',
55
+ format: winston.format.json(),
56
+ defaultMeta: { service: 'user-service' },
57
+ transports: [
58
+ //
59
+ // - Write all logs with importance level of `error` or less to `error.log`
60
+ // - Write all logs with importance level of `info` or less to `combined.log`
61
+ //
62
+ new winston.transports.File({ filename: 'error.log', level: 'error' }),
63
+ new winston.transports.File({ filename: 'combined.log' }),
64
+ ],
65
+ });
66
+
67
+ //
68
+ // If we're not in production then log to the `console` with the format:
69
+ // `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
70
+ //
71
+ if (process.env.NODE_ENV !== 'production') {
72
+ logger.add(new winston.transports.Console({
73
+ format: winston.format.simple(),
74
+ }));
75
+ }
76
+ ```
77
+
78
+ You may also log directly via the default logger exposed by
79
+ `require('winston')`, but this merely intended to be a convenient shared
80
+ logger to use throughout your application if you so choose.
81
+ Note that the default logger doesn't have any transports by default.
82
+ You need add transports by yourself, and leaving the default logger without any
83
+ transports may produce a high memory usage issue.
84
+
85
+ ## Table of contents
86
+
87
+ * [Motivation](#motivation)
88
+ * [Quick Start](#quick-start)
89
+ * [Usage](#usage)
90
+ * [Table of Contents](#table-of-contents)
91
+ * [Logging](#logging)
92
+ * [Creating your logger](#creating-your-own-logger)
93
+ * [Streams, `objectMode`, and `info` objects](#streams-objectmode-and-info-objects)
94
+ * [Formats]
95
+ * [Combining formats](#combining-formats)
96
+ * [String interpolation](#string-interpolation)
97
+ * [Filtering `info` Objects](#filtering-info-objects)
98
+ * [Creating custom formats](#creating-custom-formats)
99
+ * [Logging levels]
100
+ * [Using logging levels](#using-logging-levels)
101
+ * [Using custom logging levels](#using-custom-logging-levels)
102
+ * [Transports]
103
+ * [Multiple transports of the same type](#multiple-transports-of-the-same-type)
104
+ * [Adding Custom Transports](#adding-custom-transports)
105
+ * [Common Transport options](#common-transport-options)
106
+ * [Exceptions](#exceptions)
107
+ * [Handling Uncaught Exceptions with winston](#handling-uncaught-exceptions-with-winston)
108
+ * [To Exit or Not to Exit](#to-exit-or-not-to-exit)
109
+ * [Rejections](#rejections)
110
+ * [Handling Uncaught Promise Rejections with winston](#handling-uncaught-promise-rejections-with-winston)
111
+ * [Profiling](#profiling)
112
+ * [Streaming Logs](#streaming-logs)
113
+ * [Querying Logs](#querying-logs)
114
+ * [Further Reading](#further-reading)
115
+ * [Using the default logger](#using-the-default-logger)
116
+ * [Awaiting logs to be written in `winston`](#awaiting-logs-to-be-written-in-winston)
117
+ * [Working with multiple Loggers in `winston`](#working-with-multiple-loggers-in-winston)
118
+ * [Installation](#installation)
119
+ * [Run Tests](#run-tests)
120
+
121
+ ## Logging
122
+
123
+ Logging levels in `winston` conform to the severity ordering specified by
124
+ [RFC5424]: _severity of all levels is assumed to be numerically **ascending**
125
+ from most important to least important._
126
+
127
+ ``` js
128
+ const levels = {
129
+ error: 0,
130
+ warn: 1,
131
+ info: 2,
132
+ http: 3,
133
+ verbose: 4,
134
+ debug: 5,
135
+ silly: 6
136
+ };
137
+ ```
138
+
139
+ ### Creating your own Logger
140
+ You get started by creating a logger using `winston.createLogger`:
141
+
142
+ ``` js
143
+ const logger = winston.createLogger({
144
+ transports: [
145
+ new winston.transports.Console(),
146
+ new winston.transports.File({ filename: 'combined.log' })
147
+ ]
148
+ });
149
+ ```
150
+
151
+ A logger accepts the following parameters:
152
+
153
+ | Name | Default | Description |
154
+ | ------------- | --------------------------- | --------------- |
155
+ | `level` | `'info'` | Log only if [`info.level`](#streams-objectmode-and-info-objects) is less than or equal to this level |
156
+ | `levels` | `winston.config.npm.levels` | Levels (and colors) representing log priorities |
157
+ | `format` | `winston.format.json` | Formatting for `info` messages (see: [Formats]) |
158
+ | `transports` | `[]` _(No transports)_ | Set of logging targets for `info` messages |
159
+ | `exitOnError` | `true` | If false, handled exceptions will not cause `process.exit` |
160
+ | `silent` | `false` | If true, all logs are suppressed |
161
+
162
+ The levels provided to `createLogger` will be defined as convenience methods
163
+ on the `logger` returned.
164
+
165
+ ``` js
166
+ //
167
+ // Logging
168
+ //
169
+ logger.log({
170
+ level: 'info',
171
+ message: 'Hello distributed log files!'
172
+ });
173
+
174
+ logger.info('Hello again distributed logs');
175
+ ```
176
+
177
+ You can add or remove transports from the `logger` once it has been provided
178
+ to you from `winston.createLogger`:
179
+
180
+ ``` js
181
+ const files = new winston.transports.File({ filename: 'combined.log' });
182
+ const console = new winston.transports.Console();
183
+
184
+ logger
185
+ .clear() // Remove all transports
186
+ .add(console) // Add console transport
187
+ .add(files) // Add file transport
188
+ .remove(console); // Remove console transport
189
+ ```
190
+
191
+ You can also wholesale reconfigure a `winston.Logger` instance using the
192
+ `configure` method:
193
+
194
+ ``` js
195
+ const logger = winston.createLogger({
196
+ level: 'info',
197
+ transports: [
198
+ new winston.transports.Console(),
199
+ new winston.transports.File({ filename: 'combined.log' })
200
+ ]
201
+ });
202
+
203
+ //
204
+ // Replaces the previous transports with those in the
205
+ // new configuration wholesale.
206
+ //
207
+ const DailyRotateFile = require('winston-daily-rotate-file');
208
+ logger.configure({
209
+ level: 'verbose',
210
+ transports: [
211
+ new DailyRotateFile(opts)
212
+ ]
213
+ });
214
+ ```
215
+
216
+ ### Creating child loggers
217
+
218
+ You can create child loggers from existing loggers to pass metadata overrides:
219
+
220
+ ``` js
221
+ const logger = winston.createLogger({
222
+ transports: [
223
+ new winston.transports.Console(),
224
+ ]
225
+ });
226
+
227
+ const childLogger = logger.child({ requestId: '451' });
228
+ ```
229
+ > `.child` is likely to be bugged if you're also extending the `Logger` class, due to some implementation details that make `this` keyword to point to unexpected things. Use with caution.
230
+
231
+ ### Streams, `objectMode`, and `info` objects
232
+
233
+ In `winston`, both `Logger` and `Transport` instances are treated as
234
+ [`objectMode`](https://nodejs.org/api/stream.html#stream_object_mode)
235
+ streams that accept an `info` object.
236
+
237
+ The `info` parameter provided to a given format represents a single log
238
+ message. The object itself is mutable. Every `info` must have at least the
239
+ `level` and `message` properties:
240
+
241
+ ``` js
242
+ const info = {
243
+ level: 'info', // Level of the logging message
244
+ message: 'Hey! Log something?' // Descriptive message being logged.
245
+ };
246
+ ```
247
+
248
+ Properties **besides level and message** are considered as "`meta`". i.e.:
249
+
250
+ ``` js
251
+ const { level, message, ...meta } = info;
252
+ ```
253
+
254
+ Several of the formats in `logform` itself add additional properties:
255
+
256
+ | Property | Format added by | Description |
257
+ | ----------- | --------------- | ----------- |
258
+ | `splat` | `splat()` | String interpolation splat for `%d %s`-style messages. |
259
+ | `timestamp` | `timestamp()` | timestamp the message was received. |
260
+ | `label` | `label()` | Custom label associated with each message. |
261
+ | `ms` | `ms()` | Number of milliseconds since the previous log message. |
262
+
263
+ As a consumer you may add whatever properties you wish – _internal state is
264
+ maintained by `Symbol` properties:_
265
+
266
+ - `Symbol.for('level')` _**(READ-ONLY)**:_ equal to `level` property.
267
+ **Is treated as immutable by all code.**
268
+ - `Symbol.for('message'):` complete string message set by "finalizing formats":
269
+ - `json`
270
+ - `logstash`
271
+ - `printf`
272
+ - `prettyPrint`
273
+ - `simple`
274
+ - `Symbol.for('splat')`: additional string interpolation arguments. _Used
275
+ exclusively by `splat()` format._
276
+
277
+ These Symbols are stored in another package: `triple-beam` so that all
278
+ consumers of `logform` can have the same Symbol reference. i.e.:
279
+
280
+ ``` js
281
+ const { LEVEL, MESSAGE, SPLAT } = require('triple-beam');
282
+
283
+ console.log(LEVEL === Symbol.for('level'));
284
+ // true
285
+
286
+ console.log(MESSAGE === Symbol.for('message'));
287
+ // true
288
+
289
+ console.log(SPLAT === Symbol.for('splat'));
290
+ // true
291
+ ```
292
+
293
+ > **NOTE:** any `{ message }` property in a `meta` object provided will
294
+ > automatically be concatenated to any `msg` already provided: For
295
+ > example the below will concatenate 'world' onto 'hello':
296
+ >
297
+ > ``` js
298
+ > logger.log('error', 'hello', { message: 'world' });
299
+ > logger.info('hello', { message: 'world' });
300
+ > ```
301
+
302
+ ## Formats
303
+
304
+ Formats in `winston` can be accessed from `winston.format`. They are
305
+ implemented in [`logform`](https://github.com/winstonjs/logform), a separate
306
+ module from `winston`. This allows flexibility when writing your own transports
307
+ in case you wish to include a default format with your transport.
308
+
309
+ In modern versions of `node` template strings are very performant and are the
310
+ recommended way for doing most end-user formatting. If you want to bespoke
311
+ format your logs, `winston.format.printf` is for you:
312
+
313
+ ``` js
314
+ const { createLogger, format, transports } = require('winston');
315
+ const { combine, timestamp, label, printf } = format;
316
+
317
+ const myFormat = printf(({ level, message, label, timestamp }) => {
318
+ return `${timestamp} [${label}] ${level}: ${message}`;
319
+ });
320
+
321
+ const logger = createLogger({
322
+ format: combine(
323
+ label({ label: 'right meow!' }),
324
+ timestamp(),
325
+ myFormat
326
+ ),
327
+ transports: [new transports.Console()]
328
+ });
329
+ ```
330
+
331
+ To see what built-in formats are available and learn more about creating your
332
+ own custom logging formats, see [`logform`][logform].
333
+
334
+ ### Combining formats
335
+
336
+ Any number of formats may be combined into a single format using
337
+ `format.combine`. Since `format.combine` takes no `opts`, as a convenience it
338
+ returns pre-created instance of the combined format.
339
+
340
+ ``` js
341
+ const { createLogger, format, transports } = require('winston');
342
+ const { combine, timestamp, label, prettyPrint } = format;
343
+
344
+ const logger = createLogger({
345
+ format: combine(
346
+ label({ label: 'right meow!' }),
347
+ timestamp(),
348
+ prettyPrint()
349
+ ),
350
+ transports: [new transports.Console()]
351
+ })
352
+
353
+ logger.log({
354
+ level: 'info',
355
+ message: 'What time is the testing at?'
356
+ });
357
+ // Outputs:
358
+ // { level: 'info',
359
+ // message: 'What time is the testing at?',
360
+ // label: 'right meow!',
361
+ // timestamp: '2017-09-30T03:57:26.875Z' }
362
+ ```
363
+
364
+ ### String interpolation
365
+
366
+ The `log` method provides the string interpolation using [util.format]. **It
367
+ must be enabled using `format.splat()`.**
368
+
369
+ Below is an example that defines a format with string interpolation of
370
+ messages using `format.splat` and then serializes the entire `info` message
371
+ using `format.simple`.
372
+
373
+ ``` js
374
+ const { createLogger, format, transports } = require('winston');
375
+ const logger = createLogger({
376
+ format: format.combine(
377
+ format.splat(),
378
+ format.simple()
379
+ ),
380
+ transports: [new transports.Console()]
381
+ });
382
+
383
+ // info: test message my string {}
384
+ logger.log('info', 'test message %s', 'my string');
385
+
386
+ // info: test message 123 {}
387
+ logger.log('info', 'test message %d', 123);
388
+
389
+ // info: test message first second {number: 123}
390
+ logger.log('info', 'test message %s, %s', 'first', 'second', { number: 123 });
391
+ ```
392
+
393
+ ### Filtering `info` Objects
394
+
395
+ If you wish to filter out a given `info` Object completely when logging then
396
+ simply return a falsey value.
397
+
398
+ ``` js
399
+ const { createLogger, format, transports } = require('winston');
400
+
401
+ // Ignore log messages if they have { private: true }
402
+ const ignorePrivate = format((info, opts) => {
403
+ if (info.private) { return false; }
404
+ return info;
405
+ });
406
+
407
+ const logger = createLogger({
408
+ format: format.combine(
409
+ ignorePrivate(),
410
+ format.json()
411
+ ),
412
+ transports: [new transports.Console()]
413
+ });
414
+
415
+ // Outputs: {"level":"error","message":"Public error to share"}
416
+ logger.log({
417
+ level: 'error',
418
+ message: 'Public error to share'
419
+ });
420
+
421
+ // Messages with { private: true } will not be written when logged.
422
+ logger.log({
423
+ private: true,
424
+ level: 'error',
425
+ message: 'This is super secret - hide it.'
426
+ });
427
+ ```
428
+
429
+ Use of `format.combine` will respect any falsey values return and stop
430
+ evaluation of later formats in the series. For example:
431
+
432
+ ``` js
433
+ const { format } = require('winston');
434
+ const { combine, timestamp, label } = format;
435
+
436
+ const willNeverThrow = format.combine(
437
+ format(info => { return false })(), // Ignores everything
438
+ format(info => { throw new Error('Never reached') })()
439
+ );
440
+ ```
441
+
442
+ ### Creating custom formats
443
+
444
+ Formats are prototypal objects (i.e. class instances) that define a single
445
+ method: `transform(info, opts)` and return the mutated `info`:
446
+
447
+ - `info`: an object representing the log message.
448
+ - `opts`: setting specific to the current instance of the format.
449
+
450
+ They are expected to return one of two things:
451
+
452
+ - **An `info` Object** representing the modified `info` argument. Object
453
+ references need not be preserved if immutability is preferred. All current
454
+ built-in formats consider `info` mutable, but [immutablejs] is being
455
+ considered for future releases.
456
+ - **A falsey value** indicating that the `info` argument should be ignored by the
457
+ caller. (See: [Filtering `info` Objects](#filtering-info-objects)) below.
458
+
459
+ `winston.format` is designed to be as simple as possible. To define a new
460
+ format, simply pass it a `transform(info, opts)` function to get a new
461
+ `Format`.
462
+
463
+ The named `Format` returned can be used to create as many copies of the given
464
+ `Format` as desired:
465
+
466
+ ``` js
467
+ const { format } = require('winston');
468
+
469
+ const volume = format((info, opts) => {
470
+ if (opts.yell) {
471
+ info.message = info.message.toUpperCase();
472
+ } else if (opts.whisper) {
473
+ info.message = info.message.toLowerCase();
474
+ }
475
+
476
+ return info;
477
+ });
478
+
479
+ // `volume` is now a function that returns instances of the format.
480
+ const scream = volume({ yell: true });
481
+ console.dir(scream.transform({
482
+ level: 'info',
483
+ message: `sorry for making you YELL in your head!`
484
+ }, scream.options));
485
+ // {
486
+ // level: 'info'
487
+ // message: 'SORRY FOR MAKING YOU YELL IN YOUR HEAD!'
488
+ // }
489
+
490
+ // `volume` can be used multiple times to create different formats.
491
+ const whisper = volume({ whisper: true });
492
+ console.dir(whisper.transform({
493
+ level: 'info',
494
+ message: `WHY ARE THEY MAKING US YELL SO MUCH!`
495
+ }, whisper.options));
496
+ // {
497
+ // level: 'info'
498
+ // message: 'why are they making us yell so much!'
499
+ // }
500
+ ```
501
+
502
+ ## Logging Levels
503
+
504
+ Logging levels in `winston` conform to the severity ordering specified by
505
+ [RFC5424]: _severity of all levels is assumed to be numerically **ascending**
506
+ from most important to least important._
507
+
508
+ Each `level` is given a specific integer priority. The higher the priority the
509
+ more important the message is considered to be, and the lower the
510
+ corresponding integer priority. For example, as specified exactly in RFC5424
511
+ the `syslog` levels are prioritized from 0 to 7 (highest to lowest).
512
+
513
+ ```js
514
+ {
515
+ emerg: 0,
516
+ alert: 1,
517
+ crit: 2,
518
+ error: 3,
519
+ warning: 4,
520
+ notice: 5,
521
+ info: 6,
522
+ debug: 7
523
+ }
524
+ ```
525
+
526
+ Similarly, `npm` logging levels are prioritized from 0 to 6 (highest to
527
+ lowest):
528
+
529
+ ``` js
530
+ {
531
+ error: 0,
532
+ warn: 1,
533
+ info: 2,
534
+ http: 3,
535
+ verbose: 4,
536
+ debug: 5,
537
+ silly: 6
538
+ }
539
+ ```
540
+
541
+ If you do not explicitly define the levels that `winston` should use, the
542
+ `npm` levels above will be used.
543
+
544
+ ### Using Logging Levels
545
+
546
+ Setting the level for your logging message can be accomplished in one of two
547
+ ways. You can pass a string representing the logging level to the log() method
548
+ or use the level specified methods defined on every winston Logger.
549
+
550
+ ``` js
551
+ //
552
+ // Any logger instance
553
+ //
554
+ logger.log('silly', "127.0.0.1 - there's no place like home");
555
+ logger.log('debug', "127.0.0.1 - there's no place like home");
556
+ logger.log('verbose', "127.0.0.1 - there's no place like home");
557
+ logger.log('info', "127.0.0.1 - there's no place like home");
558
+ logger.log('warn', "127.0.0.1 - there's no place like home");
559
+ logger.log('error', "127.0.0.1 - there's no place like home");
560
+ logger.info("127.0.0.1 - there's no place like home");
561
+ logger.warn("127.0.0.1 - there's no place like home");
562
+ logger.error("127.0.0.1 - there's no place like home");
563
+
564
+ //
565
+ // Default logger
566
+ //
567
+ winston.log('info', "127.0.0.1 - there's no place like home");
568
+ winston.info("127.0.0.1 - there's no place like home");
569
+ ```
570
+
571
+ `winston` allows you to define a `level` property on each transport which
572
+ specifies the **maximum** level of messages that a transport should log. For
573
+ example, using the `syslog` levels you could log only `error` messages to the
574
+ console and everything `info` and below to a file (which includes `error`
575
+ messages):
576
+
577
+ ``` js
578
+ const logger = winston.createLogger({
579
+ levels: winston.config.syslog.levels,
580
+ transports: [
581
+ new winston.transports.Console({ level: 'error' }),
582
+ new winston.transports.File({
583
+ filename: 'combined.log',
584
+ level: 'info'
585
+ })
586
+ ]
587
+ });
588
+ ```
589
+
590
+ You may also dynamically change the log level of a transport:
591
+
592
+ ``` js
593
+ const transports = {
594
+ console: new winston.transports.Console({ level: 'warn' }),
595
+ file: new winston.transports.File({ filename: 'combined.log', level: 'error' })
596
+ };
597
+
598
+ const logger = winston.createLogger({
599
+ transports: [
600
+ transports.console,
601
+ transports.file
602
+ ]
603
+ });
604
+
605
+ logger.info('Will not be logged in either transport!');
606
+ transports.console.level = 'info';
607
+ transports.file.level = 'info';
608
+ logger.info('Will be logged in both transports!');
609
+ ```
610
+
611
+ `winston` supports customizable logging levels, defaulting to npm style
612
+ logging levels. Levels must be specified at the time of creating your logger.
613
+
614
+ ### Using Custom Logging Levels
615
+
616
+ In addition to the predefined `npm`, `syslog`, and `cli` levels available in
617
+ `winston`, you can also choose to define your own:
618
+
619
+ ``` js
620
+ const myCustomLevels = {
621
+ levels: {
622
+ foo: 0,
623
+ bar: 1,
624
+ baz: 2,
625
+ foobar: 3
626
+ },
627
+ colors: {
628
+ foo: 'blue',
629
+ bar: 'green',
630
+ baz: 'yellow',
631
+ foobar: 'red'
632
+ }
633
+ };
634
+
635
+ const customLevelLogger = winston.createLogger({
636
+ levels: myCustomLevels.levels
637
+ });
638
+
639
+ customLevelLogger.foobar('some foobar level-ed message');
640
+ ```
641
+
642
+ Although there is slight repetition in this data structure, it enables simple
643
+ encapsulation if you do not want to have colors. If you do wish to have
644
+ colors, in addition to passing the levels to the Logger itself, you must make
645
+ winston aware of them:
646
+
647
+ ``` js
648
+ winston.addColors(myCustomLevels.colors);
649
+ ```
650
+
651
+ This enables loggers using the `colorize` formatter to appropriately color and style
652
+ the output of custom levels.
653
+
654
+ Additionally, you can also change background color and font style.
655
+ For example,
656
+ ``` js
657
+ baz: 'italic yellow',
658
+ foobar: 'bold red cyanBG'
659
+ ```
660
+
661
+ Possible options are below.
662
+
663
+ * Font styles: `bold`, `dim`, `italic`, `underline`, `inverse`, `hidden`,
664
+ `strikethrough`.
665
+
666
+ * Font foreground colors: `black`, `red`, `green`, `yellow`, `blue`, `magenta`,
667
+ `cyan`, `white`, `gray`, `grey`.
668
+
669
+ * Background colors: `blackBG`, `redBG`, `greenBG`, `yellowBG`, `blueBG`
670
+ `magentaBG`, `cyanBG`, `whiteBG`
671
+
672
+ ### Colorizing Standard logging levels
673
+
674
+ To colorize the standard logging level add
675
+ ```js
676
+ winston.format.combine(
677
+ winston.format.colorize(),
678
+ winston.format.json()
679
+ );
680
+ ```
681
+ where `winston.format.json()` is whatever other formatter you want to use. The `colorize` formatter must come before any formatters adding text you wish to color.
682
+
683
+ ## Transports
684
+
685
+ There are several [core transports] included in `winston`, which leverage the
686
+ built-in networking and file I/O offered by Node.js core. In addition, there
687
+ are [additional transports] written by members of the community.
688
+
689
+ ## Multiple transports of the same type
690
+
691
+ It is possible to use multiple transports of the same type e.g.
692
+ `winston.transports.File` when you construct the transport.
693
+
694
+ ``` js
695
+ const logger = winston.createLogger({
696
+ transports: [
697
+ new winston.transports.File({
698
+ filename: 'combined.log',
699
+ level: 'info'
700
+ }),
701
+ new winston.transports.File({
702
+ filename: 'errors.log',
703
+ level: 'error'
704
+ })
705
+ ]
706
+ });
707
+ ```
708
+
709
+ If you later want to remove one of these transports you can do so by using the
710
+ transport itself. e.g.:
711
+
712
+ ``` js
713
+ const combinedLogs = logger.transports.find(transport => {
714
+ return transport.filename === 'combined.log'
715
+ });
716
+
717
+ logger.remove(combinedLogs);
718
+ ```
719
+
720
+ ## Adding Custom Transports
721
+
722
+ Adding a custom transport is easy. All you need to do is accept any options
723
+ you need, implement a log() method, and consume it with `winston`.
724
+
725
+ ``` js
726
+ const Transport = require('winston-transport');
727
+ const util = require('util');
728
+
729
+ //
730
+ // Inherit from `winston-transport` so you can take advantage
731
+ // of the base functionality and `.exceptions.handle()`.
732
+ //
733
+ module.exports = class YourCustomTransport extends Transport {
734
+ constructor(opts) {
735
+ super(opts);
736
+ //
737
+ // Consume any custom options here. e.g.:
738
+ // - Connection information for databases
739
+ // - Authentication information for APIs (e.g. loggly, papertrail,
740
+ // logentries, etc.).
741
+ //
742
+ }
743
+
744
+ log(info, callback) {
745
+ setImmediate(() => {
746
+ this.emit('logged', info);
747
+ });
748
+
749
+ // Perform the writing to the remote service
750
+ callback();
751
+ }
752
+ };
753
+ ```
754
+
755
+ ## Common Transport options
756
+
757
+ As every transport inherits from [winston-transport], it's possible to set
758
+ a custom format and a custom log level on each transport separately:
759
+
760
+ ``` js
761
+ const logger = winston.createLogger({
762
+ transports: [
763
+ new winston.transports.File({
764
+ filename: 'error.log',
765
+ level: 'error',
766
+ format: winston.format.json()
767
+ }),
768
+ new winston.transports.Http({
769
+ level: 'warn',
770
+ format: winston.format.json()
771
+ }),
772
+ new winston.transports.Console({
773
+ level: 'info',
774
+ format: winston.format.combine(
775
+ winston.format.colorize(),
776
+ winston.format.simple()
777
+ )
778
+ })
779
+ ]
780
+ });
781
+ ```
782
+
783
+ ## Exceptions
784
+
785
+ ### Handling Uncaught Exceptions with winston
786
+
787
+ With `winston`, it is possible to catch and log `uncaughtException` events
788
+ from your process. With your own logger instance you can enable this behavior
789
+ when it's created or later on in your applications lifecycle:
790
+
791
+ ``` js
792
+ const { createLogger, transports } = require('winston');
793
+
794
+ // Enable exception handling when you create your logger.
795
+ const logger = createLogger({
796
+ transports: [
797
+ new transports.File({ filename: 'combined.log' })
798
+ ],
799
+ exceptionHandlers: [
800
+ new transports.File({ filename: 'exceptions.log' })
801
+ ]
802
+ });
803
+
804
+ // Or enable it later on by adding a transport or using `.exceptions.handle`
805
+ const logger = createLogger({
806
+ transports: [
807
+ new transports.File({ filename: 'combined.log' })
808
+ ]
809
+ });
810
+
811
+ // Call exceptions.handle with a transport to handle exceptions
812
+ logger.exceptions.handle(
813
+ new transports.File({ filename: 'exceptions.log' })
814
+ );
815
+ ```
816
+
817
+ If you want to use this feature with the default logger, simply call
818
+ `.exceptions.handle()` with a transport instance.
819
+
820
+ ``` js
821
+ //
822
+ // You can add a separate exception logger by passing it to `.exceptions.handle`
823
+ //
824
+ winston.exceptions.handle(
825
+ new winston.transports.File({ filename: 'path/to/exceptions.log' })
826
+ );
827
+
828
+ //
829
+ // Alternatively you can set `handleExceptions` to true when adding transports
830
+ // to winston.
831
+ //
832
+ winston.add(new winston.transports.File({
833
+ filename: 'path/to/combined.log',
834
+ handleExceptions: true
835
+ }));
836
+ ```
837
+
838
+ ### To Exit or Not to Exit
839
+
840
+ By default, winston will exit after logging an uncaughtException. If this is
841
+ not the behavior you want, set `exitOnError = false`
842
+
843
+ ``` js
844
+ const logger = winston.createLogger({ exitOnError: false });
845
+
846
+ //
847
+ // or, like this:
848
+ //
849
+ logger.exitOnError = false;
850
+ ```
851
+
852
+ When working with custom logger instances, you can pass in separate transports
853
+ to the `exceptionHandlers` property or set `handleExceptions` on any
854
+ transport.
855
+
856
+ ##### Example 1
857
+
858
+ ``` js
859
+ const logger = winston.createLogger({
860
+ transports: [
861
+ new winston.transports.File({ filename: 'path/to/combined.log' })
862
+ ],
863
+ exceptionHandlers: [
864
+ new winston.transports.File({ filename: 'path/to/exceptions.log' })
865
+ ]
866
+ });
867
+ ```
868
+
869
+ ##### Example 2
870
+
871
+ ``` js
872
+ const logger = winston.createLogger({
873
+ transports: [
874
+ new winston.transports.Console({
875
+ handleExceptions: true
876
+ })
877
+ ],
878
+ exitOnError: false
879
+ });
880
+ ```
881
+
882
+ The `exitOnError` option can also be a function to prevent exit on only
883
+ certain types of errors:
884
+
885
+ ``` js
886
+ function ignoreEpipe(err) {
887
+ return err.code !== 'EPIPE';
888
+ }
889
+
890
+ const logger = winston.createLogger({ exitOnError: ignoreEpipe });
891
+
892
+ //
893
+ // or, like this:
894
+ //
895
+ logger.exitOnError = ignoreEpipe;
896
+ ```
897
+
898
+ ## Rejections
899
+
900
+ ### Handling Uncaught Promise Rejections with winston
901
+
902
+ With `winston`, it is possible to catch and log `uncaughtRejection` events
903
+ from your process. With your own logger instance you can enable this behavior
904
+ when it's created or later on in your applications lifecycle:
905
+
906
+ ``` js
907
+ const { createLogger, transports } = require('winston');
908
+
909
+ // Enable rejection handling when you create your logger.
910
+ const logger = createLogger({
911
+ transports: [
912
+ new transports.File({ filename: 'combined.log' })
913
+ ],
914
+ rejectionHandlers: [
915
+ new transports.File({ filename: 'rejections.log' })
916
+ ]
917
+ });
918
+
919
+ // Or enable it later on by adding a transport or using `.rejections.handle`
920
+ const logger = createLogger({
921
+ transports: [
922
+ new transports.File({ filename: 'combined.log' })
923
+ ]
924
+ });
925
+
926
+ // Call rejections.handle with a transport to handle rejections
927
+ logger.rejections.handle(
928
+ new transports.File({ filename: 'rejections.log' })
929
+ );
930
+ ```
931
+
932
+ If you want to use this feature with the default logger, simply call
933
+ `.rejections.handle()` with a transport instance.
934
+
935
+ ``` js
936
+ //
937
+ // You can add a separate rejection logger by passing it to `.rejections.handle`
938
+ //
939
+ winston.rejections.handle(
940
+ new winston.transports.File({ filename: 'path/to/rejections.log' })
941
+ );
942
+
943
+ //
944
+ // Alternatively you can set `handleRejections` to true when adding transports
945
+ // to winston.
946
+ //
947
+ winston.add(new winston.transports.File({
948
+ filename: 'path/to/combined.log',
949
+ handleRejections: true
950
+ }));
951
+ ```
952
+
953
+ ## Profiling
954
+
955
+ In addition to logging messages and metadata, `winston` also has a simple
956
+ profiling mechanism implemented for any logger:
957
+
958
+ ``` js
959
+ //
960
+ // Start profile of 'test'
961
+ //
962
+ logger.profile('test');
963
+
964
+ setTimeout(function () {
965
+ //
966
+ // Stop profile of 'test'. Logging will now take place:
967
+ // '17 Jan 21:00:00 - info: test duration=1000ms'
968
+ //
969
+ logger.profile('test');
970
+ }, 1000);
971
+ ```
972
+
973
+ Also you can start a timer and keep a reference that you can call `.done()`
974
+ on:
975
+
976
+ ``` js
977
+ // Returns an object corresponding to a specific timing. When done
978
+ // is called the timer will finish and log the duration. e.g.:
979
+ //
980
+ const profiler = logger.startTimer();
981
+ setTimeout(function () {
982
+ profiler.done({ message: 'Logging message' });
983
+ }, 1000);
984
+ ```
985
+
986
+ All profile messages are set to 'info' level by default, and both message and
987
+ metadata are optional. For individual profile messages, you can override the default log level by supplying a metadata object with a `level` property:
988
+
989
+ ```js
990
+ logger.profile('test', { level: 'debug' });
991
+ ```
992
+
993
+ ## Querying Logs
994
+
995
+ `winston` supports querying of logs with Loggly-like options. [See Loggly
996
+ Search API](https://www.loggly.com/docs/api-retrieving-data/). Specifically:
997
+ `File`, `Couchdb`, `Redis`, `Loggly`, `Nssocket`, and `Http`.
998
+
999
+ ``` js
1000
+ const options = {
1001
+ from: new Date() - (24 * 60 * 60 * 1000),
1002
+ until: new Date(),
1003
+ limit: 10,
1004
+ start: 0,
1005
+ order: 'desc',
1006
+ fields: ['message']
1007
+ };
1008
+
1009
+ //
1010
+ // Find items logged between today and yesterday.
1011
+ //
1012
+ logger.query(options, function (err, results) {
1013
+ if (err) {
1014
+ /* TODO: handle me */
1015
+ throw err;
1016
+ }
1017
+
1018
+ console.log(results);
1019
+ });
1020
+ ```
1021
+
1022
+ ## Streaming Logs
1023
+ Streaming allows you to stream your logs back from your chosen transport.
1024
+
1025
+ ``` js
1026
+ //
1027
+ // Start at the end.
1028
+ //
1029
+ winston.stream({ start: -1 }).on('log', function(log) {
1030
+ console.log(log);
1031
+ });
1032
+ ```
1033
+
1034
+ ## Further Reading
1035
+
1036
+ ### Using the Default Logger
1037
+
1038
+ The default logger is accessible through the `winston` module directly. Any
1039
+ method that you could call on an instance of a logger is available on the
1040
+ default logger:
1041
+
1042
+ ``` js
1043
+ const winston = require('winston');
1044
+
1045
+ winston.log('info', 'Hello distributed log files!');
1046
+ winston.info('Hello again distributed logs');
1047
+
1048
+ winston.level = 'debug';
1049
+ winston.log('debug', 'Now my debug messages are written to console!');
1050
+ ```
1051
+
1052
+ By default, no transports are set on the default logger. You must
1053
+ add or remove transports via the `add()` and `remove()` methods:
1054
+
1055
+ ``` js
1056
+ const files = new winston.transports.File({ filename: 'combined.log' });
1057
+ const console = new winston.transports.Console();
1058
+
1059
+ winston.add(console);
1060
+ winston.add(files);
1061
+ winston.remove(console);
1062
+ ```
1063
+
1064
+ Or do it with one call to configure():
1065
+
1066
+ ``` js
1067
+ winston.configure({
1068
+ transports: [
1069
+ new winston.transports.File({ filename: 'somefile.log' })
1070
+ ]
1071
+ });
1072
+ ```
1073
+
1074
+ For more documentation about working with each individual transport supported
1075
+ by `winston` see the [`winston` Transports](docs/transports.md) document.
1076
+
1077
+ ### Awaiting logs to be written in `winston`
1078
+
1079
+ Often it is useful to wait for your logs to be written before exiting the
1080
+ process. Each instance of `winston.Logger` is also a [Node.js stream]. A
1081
+ `finish` event will be raised when all logs have flushed to all transports
1082
+ after the stream has been ended.
1083
+
1084
+ ``` js
1085
+ const transport = new winston.transports.Console();
1086
+ const logger = winston.createLogger({
1087
+ transports: [transport]
1088
+ });
1089
+
1090
+ logger.on('finish', function (info) {
1091
+ // All `info` log messages has now been logged
1092
+ });
1093
+
1094
+ logger.info('CHILL WINSTON!', { seriously: true });
1095
+ logger.end();
1096
+ ```
1097
+
1098
+ It is also worth mentioning that the logger also emits an 'error' event
1099
+ if an error occurs within the logger itself which
1100
+ you should handle or suppress if you don't want unhandled exceptions:
1101
+
1102
+ ``` js
1103
+ //
1104
+ // Handle errors originating in the logger itself
1105
+ //
1106
+ logger.on('error', function (err) { /* Do Something */ });
1107
+ ```
1108
+
1109
+ ### Working with multiple Loggers in winston
1110
+
1111
+ Often in larger, more complex, applications it is necessary to have multiple
1112
+ logger instances with different settings. Each logger is responsible for a
1113
+ different feature area (or category). This is exposed in `winston` in two
1114
+ ways: through `winston.loggers` and instances of `winston.Container`. In fact,
1115
+ `winston.loggers` is just a predefined instance of `winston.Container`:
1116
+
1117
+ ``` js
1118
+ const winston = require('winston');
1119
+ const { format } = winston;
1120
+ const { combine, label, json } = format;
1121
+
1122
+ //
1123
+ // Configure the logger for `category1`
1124
+ //
1125
+ winston.loggers.add('category1', {
1126
+ format: combine(
1127
+ label({ label: 'category one' }),
1128
+ json()
1129
+ ),
1130
+ transports: [
1131
+ new winston.transports.Console({ level: 'silly' }),
1132
+ new winston.transports.File({ filename: 'somefile.log' })
1133
+ ]
1134
+ });
1135
+
1136
+ //
1137
+ // Configure the logger for `category2`
1138
+ //
1139
+ winston.loggers.add('category2', {
1140
+ format: combine(
1141
+ label({ label: 'category two' }),
1142
+ json()
1143
+ ),
1144
+ transports: [
1145
+ new winston.transports.Http({ host: 'localhost', port:8080 })
1146
+ ]
1147
+ });
1148
+ ```
1149
+
1150
+ Now that your loggers are setup, you can require winston _in any file in your
1151
+ application_ and access these pre-configured loggers:
1152
+
1153
+ ``` js
1154
+ const winston = require('winston');
1155
+
1156
+ //
1157
+ // Grab your preconfigured loggers
1158
+ //
1159
+ const category1 = winston.loggers.get('category1');
1160
+ const category2 = winston.loggers.get('category2');
1161
+
1162
+ category1.info('logging to file and console transports');
1163
+ category2.info('logging to http transport');
1164
+ ```
1165
+
1166
+ If you prefer to manage the `Container` yourself, you can simply instantiate one:
1167
+
1168
+ ``` js
1169
+ const winston = require('winston');
1170
+ const { format } = winston;
1171
+ const { combine, label, json } = format;
1172
+
1173
+ const container = new winston.Container();
1174
+
1175
+ container.add('category1', {
1176
+ format: combine(
1177
+ label({ label: 'category one' }),
1178
+ json()
1179
+ ),
1180
+ transports: [
1181
+ new winston.transports.Console({ level: 'silly' }),
1182
+ new winston.transports.File({ filename: 'somefile.log' })
1183
+ ]
1184
+ });
1185
+
1186
+ const category1 = container.get('category1');
1187
+ category1.info('logging to file and console transports');
1188
+ ```
1189
+
1190
+ ## Installation
1191
+
1192
+ ``` bash
1193
+ npm install winston
1194
+ ```
1195
+
1196
+ ``` bash
1197
+ yarn add winston
1198
+ ```
1199
+
1200
+ ## Run Tests
1201
+
1202
+ All of the winston tests are written with [`mocha`][mocha], [`nyc`][nyc], and
1203
+ [`assume`][assume]. They can be run with `npm`.
1204
+
1205
+ ``` bash
1206
+ npm test
1207
+ ```
1208
+
1209
+ #### Author: [Charlie Robbins]
1210
+ #### Contributors: [Jarrett Cruger], [David Hyde], [Chris Alderson]
1211
+
1212
+ [Transports]: #transports
1213
+ [Logging levels]: #logging-levels
1214
+ [Formats]: #formats
1215
+ [Using custom logging levels]: #using-custom-logging-levels
1216
+ [Adding Custom Transports]: #adding-custom-transports
1217
+ [core transports]: docs/transports.md#winston-core
1218
+ [additional transports]: docs/transports.md#additional-transports
1219
+
1220
+ [RFC5424]: https://tools.ietf.org/html/rfc5424
1221
+ [util.format]: https://nodejs.org/dist/latest/docs/api/util.html#util_util_format_format_args
1222
+ [mocha]: https://mochajs.org
1223
+ [nyc]: https://github.com/istanbuljs/nyc
1224
+ [assume]: https://github.com/bigpipe/assume
1225
+ [logform]: https://github.com/winstonjs/logform#readme
1226
+ [winston-transport]: https://github.com/winstonjs/winston-transport
1227
+
1228
+ [Read the `winston@2.x` documentation]: https://github.com/winstonjs/winston/tree/2.x
1229
+
1230
+ [quick-example]: https://github.com/winstonjs/winston/blob/master/examples/quick-start.js
1231
+ [examples]: https://github.com/winstonjs/winston/tree/master/examples
1232
+
1233
+ [Charlie Robbins]: http://github.com/indexzero
1234
+ [Jarrett Cruger]: https://github.com/jcrugzz
1235
+ [David Hyde]: https://github.com/dabh
1236
+ [Chris Alderson]: https://github.com/chrisalderson