рдпрд╣ рдЕрдзрд┐рдХ рдмрд╣реБрдореБрдЦреА рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд╕реНрддреБрдУрдВ (JSON/рд╕рд░рдгреА/рдЕрдиреНрдп) рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдмрдВрдзрди рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рд╕реНрддрд╛рд╡ рд╣реИред
рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдЗрд╕ рдкреНрд░рд╕реНрддрд╛рд╡ рдореЗрдВ рджреЛ рдмрд╛рддреЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред
рд╡рд┐рднрд┐рдиреНрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ (рдЬреИрд╕реЗ #1377, #1381, рд╕реНрд╡рдпрдВ) рдиреЗ рдиреЛрдЯ рдХрд┐рдпрд╛ рд╣реИ рдХрд┐ рд╡рд╕реНрддреБрдУрдВ/рд╕рд░рдгрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдЪрд╛рд░ V3 рдореЗрдВ V2 рд╕реЗ рднрд┐рдиреНрди рд╣реИред V2 рдореЗрдВ рдЗрди рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ options.meta
рдлрд╝реАрд▓реНрдб рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рд╕рдВрджреЗрд╢ рдФрд░ рд╕реНрддрд░ рдФрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рдЕрд▓рдЧ рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
V3 рдореЗрдВ, рдХреЗрд╡рд▓ рдПрдХ рд╣реА рдкрд░рд┐рджреГрд╢реНрдп/рд░реВрдкрд╛рдВрддрд░рдг рд╣реЛрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ options.meta рдХреЛ V2 рдХреА рддрд░рд╣ рд╣реА рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рддрдм рд╣реЛрддрд╛ рд╣реИ рдЬрдм logform.splat рдЯреНрд░рд╛рдВрд╕рдлреЙрд░реНрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЙрдЧ рдореЗрдВ рдЯреЛрдХрди рдореМрдЬреВрдж рд╣реЛрдиреЗ рдкрд░ рд╣реА рд╕реНрдкреНрд▓реИрдЯ рдореЗрдЯрд╛ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдкрд╛рд░реНрд╕ рдХрд░реЗрдЧрд╛ред рдИрдЬреА:
logger.log('info', 'this is a string I want to splat %s', 'together', {an: 'object'})
рдореЗрдВ рдкрд░рд┐рдгрд╛рдо рд╣реЛрдЧрд╛:
info: this is a string I want to splat together {"meta":{"an":"object"}} // with .simple() transform
рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ logform.splat рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ info.meta рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдореЗрдЯрд╛ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рдЬрд╛рдирдХрд╛рд░реА [SPLAT] рдореЗрдВ рдЕрдЫреВрддрд╛ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдПрдХ рд▓реЙрдЧрдлреЙрд░реНрдо рдЬреЛрдбрд╝рдирд╛ рдЬреЛ рд╕рднреА рдЬрд╛рдирдХрд╛рд░реА [SPLAT] рдХреЛ info[meta] рдореЗрдВ рдХреЙрдкреА рдХрд░рддрд╛ рд╣реИ, рджреЛрдиреЛрдВ V2 рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреА рдЕрдкреЗрдХреНрд╖рд╛рдУрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЕрдзрд┐рдХ рд▓рдЪреАрд▓реЗ рд╣реЛрдВрдЧреЗред (рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ, рд╕реАрдзреЗ рд▓реЙрдЧрд░ рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ info[SPLAT] рдЬреЛрдбрд╝рдирд╛ рдФрд░ info[meta] => info[SPLAT] рдкрд░ рдкреНрд░рд▓реЗрдЦрди рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реЛ рд╕рдХрддрд╛ рд╣реИред)
рдПрдХ рдирдпрд╛ рдкрд░рд┐рд╡рд░реНрддрди (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП logform.captureAllMeta рд╕рд┐рд░реНрдл рдирд╛рдордХрд░рдг рдХреЗ рд▓рд┐рдП) рдЗрддрдирд╛ рдЖрд╕рд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ:
// file captureAllMeta.js psuedo-code
module.exports = transform((info, opts) => {
if (info[SPLAT]) {
info.meta = info[SPLAT]
return info;
});
рдХреЗ рдмрд░рд╛рдмрд░
format.combine(
format.splat(),
...
)
рдмрди рдЬрд╛рдПрдЧрд╛
format.combine(
format.splat(),
format.captureAllMeta(),
...
// still need to have a formatter for options.meta. maybe a separate feature request.
)
рдПрдХреНрд╕реНрдЯреНрд░рд╛рд╕реНрдкреНрд▓реИрдЯ рдХреЛрдб рдХреЛ splat() рд╕реЗ рд╣рдЯрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕реЗ рдмрд╛рдж рдХреЗ (рдирдП) рдЯреНрд░рд╛рдВрд╕рдлреЙрд░реНрдо рдореЗрдВ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рд▓рд╛рдн рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ format.splat() рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рд╡реЗ рдЕрднреА рднреА format.captureAllMeta() рдХреЛ рдПрдХ рд╕реНрдЯреИрдВрдбрдЕрд▓реЛрди рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рд░реВрдк рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЕрдм рдпрд╣ рдЬрд╛рдирдХрд░ рдХрд┐ рдЬрд╛рдирдХрд╛рд░реА [рд╕реНрдкреНрд▓реИрдЯ] рдЬрд╛рдирдХрд╛рд░реА [рдореЗрдЯрд╛] рдореЗрдВ рдХреНрдпрд╛ рдЧреБрдо рд╣реИ, рдЗрд╕реЗ рдЬреНрдЮрд╛рди/рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдЕрдВрддрд░ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
V2 рд╕реЗ V3 рд╕рдВрдЧрддрддрд╛ рдмрдврд╝рд╛рддрд╛ рд╣реИред
рд╣рд╛рдВ, рдореИрдВ рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреА рдкреВрд░реА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред
winston
рд╕рдВрд╕реНрдХрд░рдг?_winston@2
winston@3
node -v
рдЖрдЙрдЯрдкреБрдЯ:_ 6.10.0рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд╕рд╛рде V2 рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯ рдХреЛрдб рдХрд╛ рдПрдХ рдирдореВрдирд╛ рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
logger = winston.createLogger({
transports: [
new (winston.transports.Console)({
timestamp: function () {
return dateFormat(Date.now(), "HH:MM:ss.l");
},
formatter: function (options) {
// Return string will be passed to logger.
return options.timestamp() + ' ' + winston.config.colorize(options.level, options.level.toUpperCase()) + ' ' + (undefined !== options.message ? options.message : '') +
(options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta) : '');
},
colorize: true,
level: container.settings.get('logLevel') || 'info',
stderrLevels: [],
handleExceptions: true,
humanReadableUnhandledException: true
})
]
});
// results of Winston<strong i="33">@2</strong>
08:31:30.363 DEBUG Server starting complete.
["Server https started.","Server http started.","Server SSDP started.","Server MDNS started."]
V3 рдореЗрдВ, рдореИрдВрдиреЗ рдЗрд╕реЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХреЗ рд╕рд╛рде рджреЛрд╣рд░рд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рд▓реЗрдХрд┐рди рдкрд░рд┐рдгрд╛рдо рдиреЗ рд╕рд░рдгреА рдкреНрд░рджрд░реНрд╢рд┐рдд рдирд╣реАрдВ рдХреАред
const processObj = logform.format(info => {
console.log('raw: ', raw)
return info
}
)
const myFormat = printf(info => {
info.timestamp = dateFormat(Date.now(), "m/d/yy HH:MM:ss.l")
return `${info.timestamp} ${info.level}: ${info.message}`;
});
logger = createLogger({
level: container.settings.get('logLevel') || 'info',
format: combine(
processObj(),
format.json(),
timestamp({format: () => new Date().toLocaleString()}),
format.colorize(),
format.align(),
format.splat(),
myFormat
),
transports: [new transports.Console()]
});
logger.exceptions.handle()
logger.exitOnError = false;
results = [ 'Not starting https server.', 'Server http started.', 'Server SSDP started.', 'Server MDNS started.']
logger.debug('Server status', results)
// results of winston<strong i="6">@3</strong> -- missing the results array
6/25/18 08:16:30.501 debug: Server starting complete.
рдореИрдВрдиреЗ рдкрд┐рдЫрд▓реА рд░рд╛рдд рдЗрд╕ рдкрд░ рдХрд╛рдо рдХрд┐рдпрд╛ рдФрд░ рдЙрдкрд░реЛрдХреНрдд рд▓рд╛рдЧреВ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреЛрдб рдХреЗ рд╕рд╛рде рдПрдХ рд╢рд╛рдЦрд╛ рдмрдирд╛рдИред рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдЖрдк рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдореИрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рд▓реЙрдЧрдлреЙрд░реНрдо рдореЗрдВ рдкреАрдЖрд░ рдмрдирд╛рдКрдВред
рдпрд╣рд╛рдВ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдлрд╝рд╛рдЗрд▓ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдореИрдВрдиреЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ ...
'use strict';
const winston = require('winston');
const logform = require('logform')
const {SPLAT} = require('triple-beam');
const {createLogger, format, transports} = require('winston');
var logger = createLogger({
format: format.combine(
format.splat()
, format.captureAllMeta()
,
logform.format.printf(info => {
// return `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`;
if ((!info.meta.length)) {
return (`${info.level}: ${info.message}`);
}
else {
return (`${info.level}: ${info.message}\n\t${JSON.stringify(info.meta)}`);
}
})
),
transports: [new transports.Console()]
});
let count = 1
logger.log('info', count + '. this is a string I want to splat %s', 'together', {an: 'object'})
count += 1
console.log('---')
logger.log('info', count + '.this is a string followed by an object and an array', {an: 'object'}, ['an', 'array'])
count += 1
console.log('---')
logger.log('info', count + '.this is a string followed by an object and an array', ['an', 'array'], {an: 'object'})
count += 1
console.log('---')
logger.log('info', count + '. string followed by', 'a string')
console.log('---')
count += 1
logger.log('info', count + '. string followed by 2', 'separate', 'strings')
console.log('---')
count += 1
logger.log('info', count + '. string followed by', {an: 'object'})
console.log('---')
count += 1
logger.log('info', count + '. string followed by 2', {an: 'object'}, ['an', 'array'])
console.log('---')
count += 1
logger.log('info', count + '. string with token followed by string %s', 'string')
console.log('---')
count += 1
logger.log('info', count + '. string with token followed by obj %j', {idunno: 'notsure'})
console.log('---')
count += 1
logger.log('info', count + '. string with token followed by string %s and then objects', 'or here', {an: 'object'}, ['i', 'am', 'missed'])
console.log('---')
count += 1
logger.log('info', count + '. string with two tokens %s %s followed by one ', 'string')
console.log('---')
count += 1
logger.log('info', count + '. string with two tokens %s %j followed by one string and one object', 'string', {an: 'object'}, [1,2,3])
count += 1
console.log('---')
logger.info({message: 'just an object', [SPLAT]: {more:'stuff'}})
count += 1
console.log('---')
logger.info(['an','array'])
count += 1
console.log('---')
logger.info(['an','array',{with:'object'}])
count += 1
console.log('---')
logger.log({
level: 'info',
message: '%d: The answer to life, the universe and everything',
splat: [42]
})
count += 1
console.log('---')
logger.log({
level: 'info',
message: '%d: The answer to life, the universe and everything',
splat: [43],
[Symbol.for('splat')]: [44]
})
count += 1
console.log('---')
logger.log({
level: 'info',
message: '%d: The answer to life, the universe and everything'
})
count += 1
console.log('---')
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд╕рд╛рде ...
info: 1. this is a string I want to splat together
[{"an":"object"}]
---
info: 2.this is a string followed by an object and an array
[{"an":"object"},["an","array"]]
---
info: 3.this is a string followed by an object and an array
[["an","array"],{"an":"object"}]
---
info: 4. string followed by
["a string"]
---
info: 5. string followed by 2
["separate","strings"]
---
info: 6. string followed by
[{"an":"object"}]
---
info: 7. string followed by 2
[{"an":"object"},["an","array"]]
---
info: 8. string with token followed by string string
---
info: 9. string with token followed by obj {"idunno":"notsure"}
---
info: 10. string with token followed by string or here and then objects
[{"an":"object"},["i","am","missed"]]
---
info: 11. string with two tokens string %s followed by one
---
info: 12. string with two tokens string {"an":"object"} followed by one string and one object
[[1,2,3]]
---
info: just an object
[{"more":"stuff"}]
---
info: an,array
---
info: an,array,[object Object] // expected... no %j token
---
info: 42: The answer to life, the universe and everything
---
info: 44: The answer to life, the universe and everything
---
info: %d: The answer to life, the universe and everything
---
рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рдЕрд▓рд╛рд╡рд╛ info.splat рдХреЗ рд▓рд┐рдП рдореЗрд░реЗ рдХреЛрдб рдореЗрдВ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ [SPLAT]ред
рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рдХреА рдЬрд░реВрд░рдд рд╣реИред рдореВрд▓ рд░реВрдк рд╕реЗ, рдпрджрд┐ рдЖрдк рдЕрдкрдиреЗ рдореМрдЬреВрджрд╛ рд▓реЙрдЧ рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдХреЛ рдЫреБрдП рдмрд┐рдирд╛ v3 рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЗрдВрдЯрд░рдкреЛрд▓реЗрд╢рди рдХреЗ рдмрд╛рдж рдореЗрдЯрд╛ рдХреЛ рдПрдХ рдЕрд▓рдЧ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИрдВ, рддреЛ v3 рдЕрдзрд┐рдХрд╛рдВрд╢ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧреИрд░-рд╕реНрдЯрд╛рд░реНрдЯрд░ рд╣реИред рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдХрд┐рд╕реА рдиреЗ рдХреНрдпреЛрдВ рд╕реЛрдЪрд╛ рдХрд┐ рд╕реНрддрд░, рд╕рдВрджреЗрд╢ рдФрд░ рдореЗрдЯрд╛ рдХреЛ рдПрдХ рдмрдбрд╝реА рд╡рд╕реНрддреБ рдореЗрдВ рдорд┐рд▓рд╛рдирд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рдерд╛ред рдпрд╣ рд╕рдВрдШрд░реНрд╖реЛрдВ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдкрдХреНрд╡ рд╣реИред info[Symbol.for('splat)] рднреА рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЗрдВрдЯрд░рдкреЛрд▓реЗрд╢рди рд╡реИрд▓реНрдпреВ рдФрд░ рдореЗрдЯрд╛ рдХреЛ рдПрдХ рд╕рд╛рде рдорд┐рд▓рд╛рдПрдЧрд╛ред рд╣рдо рдореЗрдЯрд╛ SEPARATE рдЪрд╛рд╣рддреЗ рд╣реИрдВред
рддреЛ рдореБрдЭреЗ рдЕрднреА рдПрд╣рд╕рд╛рд╕ рд╣реБрдЖ рдХрд┐ format.splat() рдХрд╛ рдЙрдкрдпреЛрдЧ рдЬрд╛рдирдХрд╛рд░реА рдореЗрдВ рдореЗрдЯрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рддрднреА рдЬрдм рдЖрдк рдЗрдВрдЯрд░рдкреЛрд▓реЗрд╢рди рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк рдкреНрд░рдХреНрд╖реЗрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдореЗрдЯрд╛ рдХреЛ рдХреЗрд╡рд▓ рд╕реВрдЪрдирд╛ рд╡рд╕реНрддреБ рдореЗрдВ рдорд┐рд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдЗрдВрдЯрд░рдкреЛрд▓реЗрд╢рди рдФрд░ рдореЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, format.simple() рдореЗрдЯрд╛ рдХреЛ {рдореЗрдЯрд╛: {METAOBJ}} рдХреЗ рд░реВрдк рдореЗрдВ рдХреЗрд╡рд▓ {METAOBJ} рдЬреИрд╕реЗ v2.
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рддреЛ рдореБрдЭреЗ рдЕрднреА рдПрд╣рд╕рд╛рд╕ рд╣реБрдЖ рдХрд┐ format.splat() рдХрд╛ рдЙрдкрдпреЛрдЧ рдЬрд╛рдирдХрд╛рд░реА рдореЗрдВ рдореЗрдЯрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рддрднреА рдЬрдм рдЖрдк рдЗрдВрдЯрд░рдкреЛрд▓реЗрд╢рди рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк рдкреНрд░рдХреНрд╖реЗрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдореЗрдЯрд╛ рдХреЛ рдХреЗрд╡рд▓ рд╕реВрдЪрдирд╛ рд╡рд╕реНрддреБ рдореЗрдВ рдорд┐рд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдЗрдВрдЯрд░рдкреЛрд▓реЗрд╢рди рдФрд░ рдореЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, format.simple() рдореЗрдЯрд╛ рдХреЛ {рдореЗрдЯрд╛: {METAOBJ}} рдХреЗ рд░реВрдк рдореЗрдВ рдХреЗрд╡рд▓ {METAOBJ} рдЬреИрд╕реЗ v2.