【问题标题】:Replay a log file with NodeJS as if it were happening in real-time使用 NodeJS 重播日志文件,就好像它是实时发生的一样
【发布时间】:2018-07-20 10:11:19
【问题描述】:

我有一个日志文件,其中包含从一个名为 Flarm 的系统捕获的大约 14.000 个飞机位置数据点,它看起来像这样:

{"addr":"A","time":1531919658.578100,"dist":902.98,"alt":385,"vs":-8}
{"addr":"A","time":1531919658.987861,"dist":914.47,"alt":384,"vs":-7}
{"addr":"A","time":1531919660.217471,"dist":925.26,"alt":383,"vs":-7}
{"addr":"A","time":1531919660.623466,"dist":925.26,"alt":383,"vs":-7}

我需要做的是找到一种方法来实时“播放”这个文件(就好像它现在正在发生一样,即使它是预先录制的),并在日志条目“发生”时发出一个事件'。该文件没有被添加,它是预先录制的,播放将在稍后阶段进行。

这样做的原因是我在开发时无法访问接收设备。

我能想到的唯一方法是为每个日志条目设置超时,但这似乎不是正确的方法。此外,这个过程必须扩展到更长的录音(这个只有一个小时)。

还有其他方法吗?

【问题讨论】:

    标签: node.js real-time


    【解决方案1】:

    如果你想用实际的时差“回放”它们,setTimeout 几乎是你必须要做的。

    const processEntry = (entry, index) => {
      index++;
      const nextEntry = getEntry(index);
      if (nextEntry == null) return;
    
      const timeDiff = nextEntry.time - entry.time;
      emitEntryEvent(entry);
      setTimeout(processEntry, timeDiff, nextEntry, index);
    };
    
    processEntry(getEntry(0), 0);
    

    这会发出当前条目,然后根据差异设置超时,直到下一个条目。 getEntry 可以从预填充的数组中获取行,也可以根据索引单独获取行。在后一种情况下,只有两行数据只能同时在内存中。

    【讨论】:

      【解决方案2】:

      假设你想可视化飞行日志,你可以使用fs watch 如下,观察日志文件的变化:

      fs.watch('somefile', function (event, filename) {
          console.log('event is: ' + event);
          if (filename) {
              console.log('filename provided: ' + filename);
          } else {
              console.log('filename not provided');
          }
      });
      

      代码摘录来自here。有关fs.watch() 的更多信息,请查看here

      然后,为了在前端进行无缝更新,您可以在服务器上设置Websocket,您可以在其中查看日志文件并通过该套接字将新添加的行发送到前端。

      在前端获取数据后,您可以在那里对其进行可视化。虽然我之前没有做过任何飞行可视化项目,但我曾多次使用D3js 来可视化其他内容(声音、数值数据、度量分析等),并且每次都能完成。

      【讨论】:

      • 我应该澄清一下:我不想像使用 tail -F 那样添加行,日志文件已完全写入,所有行都在其中。这是实时发生的事情的记录。我需要做的是回放录制就像它正在现场发生,从而模拟我在开发时无法访问的系统。感谢您提供 D3js 的链接!我肯定会在接下来的步骤中使用它:)
      • 哦,明白了。然后解析日志文件,分成块(可能是逐行),将这些块发送到浏览器,中间有delay = t_nextLine - t_lastLineSent,最后使用D3js进行可视化。我发现了这个 repo,也许它对可视化有用:github.com/koutst/flight-visualization。您可以通过浏览器对每一行进行长轮询,但这不会给出实时的“感觉”,或者您可以通过 websocket 推送这些块 - 这将给出适当的实时感。 ;)
      【解决方案3】:

      最后搞定了! setTimeout 原来是答案,并结合 Lucas S 的输入。这就是我最终的结果:

      const EventEmitter = require('events');
      const fs = require('fs');
      
      const readable = fs.createReadStream("./data/2018-07-18_1509log.json", {
        encoding: 'utf8',
        fd: null
      });
      
      function read_next_line() {
        var chunk;
        var line = '';
        // While this is a thing we can do, assign chunk
        while ((chunk = readable.read(1)) !== null) {
          // If chunk is a newline character, return the line
          if (chunk === '\n'){
            return JSON.parse(line);
          } else {
            line += chunk;
          }
        }
        return false;
      }
      
      var lines = [];
      var nextline;
      
      const processEntry = () => {
        // If lines is empty, read a line
        if (lines.length === 0) lines.push(read_next_line());
      
        // Quit here if we've reached the last line
        if ((nextline = read_next_line()) == false) return true;
      
        // Else push the just read line into our array
        lines.push(nextline);
      
        // Get the time difference in milliseconds
        var delay = Number(lines[1].time - lines[0].time) * 1000;
      
        // Remove the first line
        lines.shift();
      
        module.exports.emit('data', lines[0]);
      
        // Repeat after the calculated delay
        setTimeout(processEntry, delay);
      }
      
      var ready_to_start = false;
      
      // When the stream becomes readable, allow starting
      readable.on('readable', function() {
        ready_to_start = true;
      });
      
      
      module.exports = new EventEmitter;
      module.exports.start = function() {
        if (ready_to_start) processEntry();
        if (!ready_to_start) return false;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-14
        • 1970-01-01
        • 1970-01-01
        • 2016-03-16
        • 2018-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多