0

I have a log file that looks something like

log.txt

{ timestamp: '2019-10-24 04:39:26',
     referer: 'websocket',
     switch:
      { program:
         'elephant',
        preview: 'gopher',
        id: 1571891966523 } } }
{ 'switch-type': 'non-buffered',
     'switch-time': 17,
     'preview-loaded': 477,
     'video-loaded': 345 } }
{ timestamp: '2019-10-24 04:39:35',
     referer: 'websocket',
     switch:
      { program: 'gopher',
        preview: 'camel',
        id: 1571891975677 } } }
{ 'switch-type': 'pre-buffered',
     'switch-time': 15,
     'preview-loaded': 348 } }
{ timestamp: '2019-10-24 04:39:37',
     referer: 'websocket',
     switch:
      { program: 'camel',
        preview:
         'elephant',
        id: 1571891977697 } } }
{ 'switch-type': 'non-buffered',
     'switch-time': 14,
     'preview-loaded': 302,
     'video-loaded': 203 } }
...

That log file was generated by one long-running node.js script that periodically does

// logging script
...
console.dir(data);
...

I want a node.js script to parse through that log file and give me a quick summary. That node.js script is currently something like

// analyze_logs.js
var fs = require('fs');
var obj = JSON.parse(fs.readFileSync('file', 'utf8'));

and I get the error:

JSONDecodeError: Expecting property name enclosed in double quotes

The comments at How can I pretty-print JSON using node.js? make me realize that the above format is not (a series of) strict JSON format.

It's "like JSON, except without quotes for keys".

  1. How do I read data printed from console.dir(), whatever format that may be, from a text file into my node.js script, and parse it back into a normal JavaScript object?

  2. When the text file has a long series of such objects, how do I read through them one at a time? (There seem to be a few JSON streaming libraries that read a series of JSON objects, such as npm stream-json, but they seem to require the logging script to emit strict JSON).

David Cary
  • 5,250
  • 6
  • 53
  • 66

1 Answers1

1

Maybe it's not the best approach, but it could work.

  1. Splitting the log file into chunks that represent single objects: Seeing your log file example above, I think we can assume that lines beginning with no whitespace are starting a new object. So you can go line by line on the file's contents, concatenating the lines into a single string, and if you find a line which starts a new object, you start a new string.

  2. Once you have a string of an object representation like this, you can use eval to interpret it. Because we know that this is valid JS code (actually you have to remove the last }), we just have to transform it to an assignment by adding a dummy variable, then eval will return our object:

const obj = eval(`whatever = { timestamp: '2019-10-24 04:39:26',
     referer: 'websocket',
     switch:
      { program:
         'elephant',
        preview: 'gopher',
        id: 1571891966523 } }`); // here I removed the last }
console.log(obj.switch.program); // prints elephant
juzraai
  • 5,693
  • 8
  • 33
  • 47