Fs.watch () не работает в Node v13 или я делаю что-то не так? - PullRequest
1 голос
/ 25 февраля 2020

Я застрял, пытаясь настроить средство просмотра файлов, которое определяет, когда новые данные добавляются в файл. Общая последовательность: 1.) клиент подключается к серверу. 2.) сервер регистрирует в файл. 3.) fs.watch() обнаруживает, что файл был изменен и запускает функцию, в этом случае простое console.log('New log entry')

Кажется, что все работает, кроме fs.watch(), не обнаруживает, когда новые сообщения добавляются в файл журнала , Однако, если я нажимаю на файл журнала в VScode, он, кажется, вызывает его. Это ошибка в более новых версиях Node или я что-то здесь не так делаю?

Я понимаю, что могу использовать fs.watchFile(), но я надеялся избежать накладных расходов на опрос ...

// src/index.js
const path = require('path');
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
const logger = require('./logger');
const fs = require('fs');

fs.watch('./logs/combined.log', (event) => {
  if (event === 'change') {
    console.log('New log entry');
  }
});

app.use(express.static(path.join(__dirname, '../public')));
app.get('/', function(req, res, next) {
  res.sendFile(path.join(__dirname, '../public', 'index.html'));
});

io.on('connection', function(socket) {
  logger.info('a user connected');
});

const PORT = process.env.PORT || 8888;

server.listen(PORT, () => {
  logger.info(`Listening at http://localhost:${port}`);
});

-

// src/logger.js
const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'logs/combined.log' })
  ]
});

module.exports = logger

-

// public/index.html
<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost:8888');
</script>

-

// simplified test
const logger = require('./logger');
const fs = require('fs');

fs.watch('./logs/combined.log', event => {
  if (event === 'change') {
    console.log('log file has updated');
  }
});

function intervalFunc() {
  logger.info('new log message');
}
setInterval(intervalFunc, 5000);

Ответы [ 2 ]

2 голосов
/ 28 февраля 2020

Обновление:

Так что похоже на то, что Winston поставляется со встроенными слушателями . Эти слушатели действуют подобно наблюдателю файла и позволяют вам подключаться к определенным событиям. Одно из событий, которое вы можете подключить, называется «data» - это позволяет вам прослушивать, когда данные записываются в файл, и запускать функцию обратного вызова.

Это обеспечивает поведение, подобное file.watch.

Они позволяют прослушивать следующие события:

  • close
  • data
  • end
  • error
  • readable

Я проверил это на Windows, и оно отлично работает.

Это тест файл, который я использую:

const winston = require('winston');

const { createLogger, format: { json }, transports: { File } } = winston;

const logger = createLogger({
  level: 'info',
  format: json(),
  transports: [
    new File({ filename: './log.txt' })
  ],  
});

/**
 * Added a built in Winston listener
 */
logger.addListener('data', chunk => {
    console.log('\r\n[winston listener] we have logged some data:\n', chunk)
})

/**
 * Their documentation seems to use the `.on` method.
 * 
 * This appears to provide the same type of behavior that `.addListener` does.
 * 
 * I'm not sure which is best, or recommended, `.addListener` or `.on` - you
 * may want to dig deeper into that.
 */
logger.on('data', chunk => {
    console.log('\r\n[winston on "data"] we have logged some data:\n', chunk);
});

setInterval(() => {
  logger.info('new log message');
}, 5000);

, поэтому я немного подумал над этим, и сначала я подумал, что это происходит, потому что Winston использует потоки записи для обновления файлов ..

Затем я попытался повторить вашу проблему, но я не могу воспроизвести ее.

Каждый раз, когда файл журнала обновляется, на консоль записывается сообщение (то есть fs.watch работает.

Используете ли вы Windows? Какую версию Node вы используете?

Это тестовый файл, который я использую:

const winston = require('winston');
const fs = require('fs');

const { createLogger, format: { json }, transports: { File } } = winston;

const logger = createLogger({
  level: 'info',
  format: json(),
  transports: [
    new File({ filename: './log.txt' })
  ]
});

fs.watch('./log.txt', event => { 
  if (event === 'change') {
    console.log('log file has updated');
  }
});

setInterval(() => {
  logger.info('new log message');
}, 5000);
0 голосов
/ 25 февраля 2020

Документация по узлу для fs.watch имеет целый раздел Caveats , в котором в самом начале указано:

API fs.watch не является На всех платформах согласован на 100% и недоступен в некоторых ситуациях.

Вам следует прочитать этот раздел для получения дополнительной информации, но, возможно, вам придется использовать fs.watchfile , если вы не может заставить fs.watch работать на вас надежно.

[ОБНОВЛЕНИЕ]

Подраздел Аргумент имени файла * раздела Caveats также гласит:

Даже на поддерживаемых платформах filename не всегда гарантируется. Поэтому не предполагайте, что аргумент filename всегда предоставляется в обратном вызове, и имейте некоторые резервные логики c, если он равен null.

, так как вам не нужно использовать filename аргумент (и вы все равно уже знаете имя файла), ваш обратный вызов не должен проверять истинный filename аргумент.

...