|
1 | 1 | 'use strict';
|
2 | 2 |
|
3 |
| -const util = require('util'); |
4 |
| -const Writable = require('readable-stream/lib/_stream_writable.js'); |
5 |
| -const { LEVEL } = require('triple-beam'); |
6 |
| - |
7 |
| -/** |
8 |
| - * Constructor function for the TransportStream. This is the base prototype |
9 |
| - * that all `winston >= 3` transports should inherit from. |
10 |
| - * @param {Object} options - Options for this TransportStream instance |
11 |
| - * @param {String} options.level - Highest level according to RFC5424. |
12 |
| - * @param {Boolean} options.handleExceptions - If true, info with |
13 |
| - * { exception: true } will be written. |
14 |
| - * @param {Function} options.log - Custom log function for simple Transport |
15 |
| - * creation |
16 |
| - * @param {Function} options.close - Called on "unpipe" from parent. |
17 |
| - */ |
18 |
| -const TransportStream = module.exports = function TransportStream(options = {}) { |
19 |
| - Writable.call(this, { objectMode: true, highWaterMark: options.highWaterMark }); |
20 |
| - |
21 |
| - this.format = options.format; |
22 |
| - this.level = options.level; |
23 |
| - this.handleExceptions = options.handleExceptions; |
24 |
| - this.handleRejections = options.handleRejections; |
25 |
| - this.silent = options.silent; |
26 |
| - |
27 |
| - if (options.log) this.log = options.log; |
28 |
| - if (options.logv) this.logv = options.logv; |
29 |
| - if (options.close) this.close = options.close; |
30 |
| - |
31 |
| - // Get the levels from the source we are piped from. |
32 |
| - this.once('pipe', logger => { |
33 |
| - // Remark (indexzero): this bookkeeping can only support multiple |
34 |
| - // Logger parents with the same `levels`. This comes into play in |
35 |
| - // the `winston.Container` code in which `container.add` takes |
36 |
| - // a fully realized set of options with pre-constructed TransportStreams. |
37 |
| - this.levels = logger.levels; |
38 |
| - this.parent = logger; |
39 |
| - }); |
40 |
| - |
41 |
| - // If and/or when the transport is removed from this instance |
42 |
| - this.once('unpipe', src => { |
43 |
| - // Remark (indexzero): this bookkeeping can only support multiple |
44 |
| - // Logger parents with the same `levels`. This comes into play in |
45 |
| - // the `winston.Container` code in which `container.add` takes |
46 |
| - // a fully realized set of options with pre-constructed TransportStreams. |
47 |
| - if (src === this.parent) { |
48 |
| - this.parent = null; |
49 |
| - if (this.close) { |
50 |
| - this.close(); |
51 |
| - } |
52 |
| - } |
53 |
| - }); |
54 |
| -}; |
55 |
| - |
56 |
| -/* |
57 |
| - * Inherit from Writeable using Node.js built-ins |
58 |
| - */ |
59 |
| -util.inherits(TransportStream, Writable); |
60 |
| - |
61 |
| -/** |
62 |
| - * Writes the info object to our transport instance. |
63 |
| - * @param {mixed} info - TODO: add param description. |
64 |
| - * @param {mixed} enc - TODO: add param description. |
65 |
| - * @param {function} callback - TODO: add param description. |
66 |
| - * @returns {undefined} |
67 |
| - * @private |
68 |
| - */ |
69 |
| -TransportStream.prototype._write = function _write(info, enc, callback) { |
70 |
| - if (this.silent || (info.exception === true && !this.handleExceptions)) { |
71 |
| - return callback(null); |
72 |
| - } |
73 |
| - |
74 |
| - // Remark: This has to be handled in the base transport now because we |
75 |
| - // cannot conditionally write to our pipe targets as stream. We always |
76 |
| - // prefer any explicit level set on the Transport itself falling back to |
77 |
| - // any level set on the parent. |
78 |
| - const level = this.level || (this.parent && this.parent.level); |
79 |
| - |
80 |
| - if (!level || this.levels[level] >= this.levels[info[LEVEL]]) { |
81 |
| - if (info && !this.format) { |
82 |
| - return this.log(info, callback); |
83 |
| - } |
84 |
| - |
85 |
| - let errState; |
86 |
| - let transformed; |
87 |
| - |
88 |
| - // We trap(and re-throw) any errors generated by the user-provided format, but also |
89 |
| - // guarantee that the streams callback is invoked so that we can continue flowing. |
90 |
| - try { |
91 |
| - transformed = this.format.transform(Object.assign({}, info), this.format.options); |
92 |
| - } catch (err) { |
93 |
| - errState = err; |
94 |
| - } |
95 |
| - |
96 |
| - if (errState || !transformed) { |
97 |
| - // eslint-disable-next-line callback-return |
98 |
| - callback(); |
99 |
| - if (errState) throw errState; |
100 |
| - return; |
101 |
| - } |
102 |
| - |
103 |
| - return this.log(transformed, callback); |
104 |
| - } |
105 |
| - this._writableState.sync = false; |
106 |
| - return callback(null); |
107 |
| -}; |
108 |
| - |
109 |
| -/** |
110 |
| - * Writes the batch of info objects (i.e. "object chunks") to our transport |
111 |
| - * instance after performing any necessary filtering. |
112 |
| - * @param {mixed} chunks - TODO: add params description. |
113 |
| - * @param {function} callback - TODO: add params description. |
114 |
| - * @returns {mixed} - TODO: add returns description. |
115 |
| - * @private |
116 |
| - */ |
117 |
| -TransportStream.prototype._writev = function _writev(chunks, callback) { |
118 |
| - if (this.logv) { |
119 |
| - const infos = chunks.filter(this._accept, this); |
120 |
| - if (!infos.length) { |
121 |
| - return callback(null); |
122 |
| - } |
123 |
| - |
124 |
| - // Remark (indexzero): from a performance perspective if Transport |
125 |
| - // implementers do choose to implement logv should we make it their |
126 |
| - // responsibility to invoke their format? |
127 |
| - return this.logv(infos, callback); |
128 |
| - } |
129 |
| - |
130 |
| - for (let i = 0; i < chunks.length; i++) { |
131 |
| - if (!this._accept(chunks[i])) continue; |
132 |
| - |
133 |
| - if (chunks[i].chunk && !this.format) { |
134 |
| - this.log(chunks[i].chunk, chunks[i].callback); |
135 |
| - continue; |
136 |
| - } |
137 |
| - |
138 |
| - let errState; |
139 |
| - let transformed; |
140 |
| - |
141 |
| - // We trap(and re-throw) any errors generated by the user-provided format, but also |
142 |
| - // guarantee that the streams callback is invoked so that we can continue flowing. |
143 |
| - try { |
144 |
| - transformed = this.format.transform( |
145 |
| - Object.assign({}, chunks[i].chunk), |
146 |
| - this.format.options |
147 |
| - ); |
148 |
| - } catch (err) { |
149 |
| - errState = err; |
150 |
| - } |
151 |
| - |
152 |
| - if (errState || !transformed) { |
153 |
| - // eslint-disable-next-line callback-return |
154 |
| - chunks[i].callback(); |
155 |
| - if (errState) { |
156 |
| - // eslint-disable-next-line callback-return |
157 |
| - callback(null); |
158 |
| - throw errState; |
159 |
| - } |
160 |
| - } else { |
161 |
| - this.log(transformed, chunks[i].callback); |
162 |
| - } |
163 |
| - } |
164 |
| - |
165 |
| - return callback(null); |
166 |
| -}; |
167 |
| - |
168 |
| -/** |
169 |
| - * Predicate function that returns true if the specfied `info` on the |
170 |
| - * WriteReq, `write`, should be passed down into the derived |
171 |
| - * TransportStream's I/O via `.log(info, callback)`. |
172 |
| - * @param {WriteReq} write - winston@3 Node.js WriteReq for the `info` object |
173 |
| - * representing the log message. |
174 |
| - * @returns {Boolean} - Value indicating if the `write` should be accepted & |
175 |
| - * logged. |
176 |
| - */ |
177 |
| -TransportStream.prototype._accept = function _accept(write) { |
178 |
| - const info = write.chunk; |
179 |
| - if (this.silent) { |
180 |
| - return false; |
181 |
| - } |
182 |
| - |
183 |
| - // We always prefer any explicit level set on the Transport itself |
184 |
| - // falling back to any level set on the parent. |
185 |
| - const level = this.level || (this.parent && this.parent.level); |
186 |
| - |
187 |
| - // Immediately check the average case: log level filtering. |
188 |
| - if ( |
189 |
| - info.exception === true || |
190 |
| - !level || |
191 |
| - this.levels[level] >= this.levels[info[LEVEL]] |
192 |
| - ) { |
193 |
| - // Ensure the info object is valid based on `{ exception }`: |
194 |
| - // 1. { handleExceptions: true }: all `info` objects are valid |
195 |
| - // 2. { exception: false }: accepted by all transports. |
196 |
| - if (this.handleExceptions || info.exception !== true) { |
197 |
| - return true; |
198 |
| - } |
199 |
| - } |
200 |
| - |
201 |
| - return false; |
202 |
| -}; |
203 |
| - |
204 |
| -/** |
205 |
| - * _nop is short for "No operation" |
206 |
| - * @returns {Boolean} Intentionally false. |
207 |
| - */ |
208 |
| -TransportStream.prototype._nop = function _nop() { |
209 |
| - // eslint-disable-next-line no-undefined |
210 |
| - return void undefined; |
211 |
| -}; |
212 |
| - |
| 3 | +// Expose modern transport directly as the export |
| 4 | +module.exports = require('./modern'); |
213 | 5 |
|
214 | 6 | // Expose legacy stream
|
215 | 7 | module.exports.LegacyTransportStream = require('./legacy');
|
0 commit comments