UNPKG

4.66 kBJavaScriptView Raw
1'use strict'
2
3/* eslint no-prototype-builtins: 0 */
4
5const { EventEmitter } = require('events')
6const SonicBoom = require('sonic-boom')
7const flatstr = require('flatstr')
8const {
9 lsCacheSym,
10 levelValSym,
11 setLevelSym,
12 getLevelSym,
13 chindingsSym,
14 mixinSym,
15 asJsonSym,
16 writeSym,
17 timeSym,
18 timeSliceIndexSym,
19 streamSym,
20 serializersSym,
21 formattersSym,
22 useOnlyCustomLevelsSym,
23 needsMetadataGsym
24} = require('./symbols')
25const {
26 getLevel,
27 setLevel,
28 isLevelEnabled,
29 mappings,
30 initialLsCache,
31 genLsCache,
32 assertNoLevelCollisions
33} = require('./levels')
34const {
35 asChindings,
36 asJson,
37 buildFormatters
38} = require('./tools')
39const {
40 version
41} = require('./meta')
42
43// note: use of class is satirical
44// https://github.com/pinojs/pino/pull/433#pullrequestreview-127703127
45const constructor = class Pino {}
46const prototype = {
47 constructor,
48 child,
49 bindings,
50 setBindings,
51 flush,
52 isLevelEnabled,
53 version,
54 get level () { return this[getLevelSym]() },
55 set level (lvl) { return this[setLevelSym](lvl) },
56 get levelVal () { return this[levelValSym] },
57 set levelVal (n) { throw Error('levelVal is read-only') },
58 [lsCacheSym]: initialLsCache,
59 [writeSym]: write,
60 [asJsonSym]: asJson,
61 [getLevelSym]: getLevel,
62 [setLevelSym]: setLevel
63}
64
65Object.setPrototypeOf(prototype, EventEmitter.prototype)
66
67module.exports = prototype
68
69const resetChildingsFormatter = bindings => bindings
70function child (bindings) {
71 if (!bindings) {
72 throw Error('missing bindings for child Pino')
73 }
74 const serializers = this[serializersSym]
75 const formatters = this[formattersSym]
76 const instance = Object.create(this)
77 if (bindings.hasOwnProperty('serializers') === true) {
78 instance[serializersSym] = Object.create(null)
79
80 for (var k in serializers) {
81 instance[serializersSym][k] = serializers[k]
82 }
83 const parentSymbols = Object.getOwnPropertySymbols(serializers)
84 for (var i = 0; i < parentSymbols.length; i++) {
85 const ks = parentSymbols[i]
86 instance[serializersSym][ks] = serializers[ks]
87 }
88
89 for (var bk in bindings.serializers) {
90 instance[serializersSym][bk] = bindings.serializers[bk]
91 }
92 const bindingsSymbols = Object.getOwnPropertySymbols(bindings.serializers)
93 for (var bi = 0; bi < bindingsSymbols.length; bi++) {
94 const bks = bindingsSymbols[bi]
95 instance[serializersSym][bks] = bindings.serializers[bks]
96 }
97 } else instance[serializersSym] = serializers
98 if (bindings.hasOwnProperty('formatters')) {
99 const { level, bindings: chindings, log } = bindings.formatters
100 instance[formattersSym] = buildFormatters(
101 level || formatters.level,
102 chindings || resetChildingsFormatter,
103 log || formatters.log
104 )
105 } else {
106 instance[formattersSym] = buildFormatters(
107 formatters.level,
108 resetChildingsFormatter,
109 formatters.log
110 )
111 }
112 if (bindings.hasOwnProperty('customLevels') === true) {
113 assertNoLevelCollisions(this.levels, bindings.customLevels)
114 instance.levels = mappings(bindings.customLevels, instance[useOnlyCustomLevelsSym])
115 genLsCache(instance)
116 }
117 instance[chindingsSym] = asChindings(instance, bindings)
118 const childLevel = bindings.level || this.level
119 instance[setLevelSym](childLevel)
120
121 return instance
122}
123
124function bindings () {
125 const chindings = this[chindingsSym]
126 var chindingsJson = `{${chindings.substr(1)}}` // at least contains ,"pid":7068,"hostname":"myMac"
127 var bindingsFromJson = JSON.parse(chindingsJson)
128 delete bindingsFromJson.pid
129 delete bindingsFromJson.hostname
130 return bindingsFromJson
131}
132
133function setBindings (newBindings) {
134 const chindings = asChindings(this, newBindings)
135 this[chindingsSym] = chindings
136}
137
138function write (_obj, msg, num) {
139 const t = this[timeSym]()
140 const mixin = this[mixinSym]
141 const objError = _obj instanceof Error
142 var obj
143
144 if (_obj === undefined || _obj === null) {
145 obj = mixin ? mixin() : {}
146 } else {
147 obj = Object.assign(mixin ? mixin() : {}, _obj)
148 if (!msg && objError) {
149 msg = _obj.message
150 }
151
152 if (objError) {
153 obj.stack = _obj.stack
154 if (!obj.type) {
155 obj.type = 'Error'
156 }
157 }
158 }
159
160 const s = this[asJsonSym](obj, msg, num, t)
161
162 const stream = this[streamSym]
163 if (stream[needsMetadataGsym] === true) {
164 stream.lastLevel = num
165 stream.lastObj = obj
166 stream.lastTime = t.slice(this[timeSliceIndexSym])
167 stream.lastLogger = this // for child loggers
168 }
169 if (stream instanceof SonicBoom) stream.write(s)
170 else stream.write(flatstr(s))
171}
172
173function flush () {
174 const stream = this[streamSym]
175 if ('flush' in stream) stream.flush()
176}