Skip to content

tail

The util/tail module provides a polling-based single-file follower with behavior similar to tail -F. It is designed for caller-managed lifecycle: the caller periodically invokes poll() (typically with setInterval()).

It is available:

  • require('util/tail')

tail.create()

Creates a tailer instance.

Syntax
tail.create(path, options)
Parameters
  • path String: Target file path to follow.
  • options Object:
    • fromStart Boolean (default: false)
      • false: Start following from the current end of file.
      • true: Start reading from the beginning on first poll.
Returned object
Method/FieldTypeDescription
pathStringPath used to create the tailer
poll(callback?)FunctionReads newly appended lines and returns String[]
close()FunctionCloses file handle and ends the tailer

poll(callback?) behavior:

  • Return value: array of newly detected lines (String[])
  • If callback is provided, the same array is passed to the callback
  • Returns an empty array when there are no new lines
  • Reflects truncate/rotation state at poll time

Basic usage example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
const tail = require('util/tail');

const follower = tail.create('/tmp/app.log', { fromStart: false });

const tm = setInterval(function () {
    const lines = follower.poll(function (arr) {
        // arr is String[]
    });

    for (let i = 0; i < lines.length; i++) {
        console.println(lines[i]);
    }
}, 500);

// cleanup example
setTimeout(function () {
    clearInterval(tm);
    follower.close();
}, 10_000);

SSE adapter

util/tail/sse is an adapter that emits tail output as SSE frames.

  • require('util/tail/sse')
  • require('util/tail').sse

tail/sse.create()

Syntax
tailSSE.create(path, options)
Parameters
  • path String: Target file path to follow.
  • options Object:
    • fromStart Boolean (default: false)
    • event String (default: empty string)
    • retryMs Number (optional)
    • write Function (optional)
      • If omitted, output is written to process.stdout.write()
Returned object
MethodDescription
writeHeaders()Writes SSE response headers
poll()Reads new lines, emits SSE event/data frames, returns String[]
send(data, event?)Emits one arbitrary SSE event payload
comment(text)Emits an SSE comment frame (: ...)
close()Closes the internal tailer

cgi-bin SSE example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const tailSSE = require('util/tail/sse');
const process = require('process');

const path = process.env.get('SCRIPT_NAME');
const target = '/work/'+path.substring(0, path.lastIndexOf('/')) + '/app.log';

const intervalMs = Number(process.env.QUERY_INTERVAL_MS || 500);

const adapter = tailSSE.create(target, {
    fromStart: false,
    event: 'log',
    retryMs: 1500,
});

adapter.writeHeaders();

const timer = setInterval(function () {
    try {
        adapter.poll();
    } catch (err) {
        adapter.send(String(err), 'error');
        clearInterval(timer);
        adapter.close();
        process.exit(0);
    }
}, intervalMs);

process.on('SIGINT', function () {
    clearInterval(timer);
    adapter.close();
    process.exit(0);
});

process.on('SIGTERM', function () {
    clearInterval(timer);
    adapter.close();
    process.exit(0);
});

Behavior notes

  • Polling cadence and lifecycle (cleanup/stop) are controlled by the caller.
  • If the file does not exist, poll() returns an empty array; following begins after the file appears.
  • Rotation and truncation are detected and applied at poll time.
Last updated on