Эта статья была впервые опубликована в моем личном блогеБлог Сая
Пожалуйста, укажите источникalipot.top/blog/5 нет 45 нет 9…
Проблема: используется в проектеlog4js
Журнал можно нормально записать в файл, а потом использоватьpm2
После запуска обнаруживается, что запись в файл невозможна. Я долго искал в Интернете и не мог найти причину, поэтому я подумал о методе просмотра исходного кода, чтобы узнать, что пошло не так.
#Сначала посмотрите на соответствующую конфигурацию
log4js
Конфигурация:
{
"type": "dateFile",
"filename": "logfile/",
"pattern": "flow-yyyy-MM-dd-hh.log",
"alwaysIncludePattern": true,
"layout": { "type": "messagePassThrough" }
}
pm2
Конфигурация:
{
"apps": [
{
"name": "project_name",
"script": "index.js",
"exec_mode": "cluster",
"instances": 4,
"instance_var": "INSTANCE_ID",
"max_memory_restart": "1G",
"autorestart": true,
"node_args": [],
"watch": ["config", "data", "lib","public", "index.js"],
"watch_options": {
"usePolling": true
},
"args": [],
"env": {},
"env_dev": {
...
},
"env_production": {
...
}
}
]
}
# log4js
Файл, соответствующий формату времени, не может быть сгенерирован автоматически
Обычный прямой запуск создаст журнал в каталоге журнала конфигурации.flow-yyyy-MM-dd-hh.log
форматировать файл, но сpm2
Он не генерируется при запуске.
Метод вызова log4js:require('log4js').getLogger()
, так что вы можете найти его прямо в исходном кодеgetLogger
:
1. Пройтиpackage.json
серединаmain
Мы определили, что его основной входной файл./lib/log4js
;
2. найтиgetLogger
метод
/**
* Get a logger instance.
* @static
* @param loggerCategoryName
* @return {Logger} instance of logger for the category
*/
function getLogger(category) {
const cat = category || 'default'
debug(`creating logger as ${isMaster() ? 'master' : 'worker'}`)
return new Logger(isMaster() ? sendLogEventToAppender : workerDispatch, cat)
}
один из нихisMaster()
метод, чтобы определить, является ли это основным процессом
function isPM2Master() {
return config.pm2 && process.env[config.pm2InstanceVar] === '0'
}
function isMaster() {
return config.disableClustering || cluster.isMaster || isPM2Master()
}
можно увидетьisPM2Master
через конфигpm2
параметры иpm2InstanceVar
чтобы быть уверенным. Поэтому нам нужноlog4js
Добавьте эти две конфигурации в файл configuration.
{
pm2: true,
pm2InstanceVar: "INSTANCE_ID" // 与pm2的配置对应
}
pm2 в конкретной переменной среды NODE_APP_INSTANCEМожет использоваться для определения процесса master-slave
Перезагрузитесь в это времяpm2
после (обязательноpm2 delete
В противном случае конфигурационный файл pm2 не вступит в силу), вы уже видите сгенерированный файл, но лог все равно не записывается. Затем посмотрите исходный код:
# workerDispatch
метод
function workerDispatch(logEvent) {
debug(`sending message to master from worker ${process.pid}`)
process.send({ topic: 'log4js:message', data: serialise(logEvent) })
}
Этот метод получает событие журнала для рабочего процесса и отправляет сообщение. Должно быть место для его получения. Найдите этот метод, просмотрев код:
function configure(configurationFileOrObject) {
// ...
if (config.disableClustering) {
debug('Not listening for cluster messages, because clustering disabled.');
} else {
// PM2 cluster support
// PM2 runs everything as workers - install pm2-intercom for this to work.
// we only want one of the app instances to write logs
if (isPM2Master()) {
debug('listening for PM2 broadcast messages');
process.removeListener('message', receiver);
process.on('message', receiver);
} else if (cluster.isMaster) {
debug('listening for cluster messages');
cluster.removeListener('message', receiver);
cluster.on('message', receiver);
} else {
debug('not listening for messages, because we are not a master process');
}
}
мы можем видеть вif
В условии есть операция мониторинга, но следующая функция мониторинга не выполняется, и тут я заметил три строчки комментариев внутри, которые нужно установитьpm2-intercom
; после выполненияpm2 install pm2-intercom
После этого, конечно же, журнал был успешно записан в файл.