fluent / fluent-logger-forward-node

A fluent forward protocol implementation for Node.js
https://fluent.github.io/fluent-logger-forward-node/
Apache License 2.0
11 stars 8 forks source link

Node process doesn't exit if the destination is not available #46

Open niyazhussain opened 1 year ago

niyazhussain commented 1 year ago

I stopped the fluentd server and tried the below code with node

const FluentClient = require("@fluent-org/logger").FluentClient;

const flDlogger = new FluentClient("test", {
    eventMode: "Message",
    socket: {
        host: "localhost",
        port: 24224,
        timeout: 3000,
    }
});
flDlogger.emit({}).then(() => { console.log("Sent Message Successfully")}).catch((e) => { console.log(e);})

The node process did not timeout/quit until the server becomes available, is there any flag/way to exit the node process if the destination becomes unavailable, i want to try this in AWS lambda and if the destination is not available then the lambda may run always.

jamiees2 commented 1 year ago

So the problem here is that the client will buffer the event indefinitely if it can't ever connect to a server to send it to. In this case, Node will never resolve the promise returned by emit(), which means that it can't exit.

This is somewhat by design though, since we can't really throw errors for creating the connection as part of sending the message.

I think the best thing to do here is to disable autoconnect behavior, by passing disableAutoconnect, and explicitly connect()-ing and disconnect()-ing the flDlogger. This both gives you access to the errors returned by the socket duringconnect()`, and allows you to shut down the client cleanly.

Alternatively, you could use something like p-timeout to time out the emit(), but I'm not entirely sure that that will work, since the promise is still hanging. Anyway, worth a try :)

niyazhussain21 commented 1 year ago

// If not closed incase of error, then the node process will not exit this.logger.socketOn('error', () => { this.logger.disconnect(); });

ahamid commented 8 months ago

Thanks for this library! I will add, apart from just not exiting (a symptom of an unresolved Promise), it also makes it impossible to wait for message send when connect fails - the emit promise is never returned:


const { FluentClient } = require('@fluent-org/logger');

async function awaitLog() {
  const logger = new FluentClient('testtag', {
    eventMode: 'Message',
    socket: {
      host: 'a-fake-host-well-never-connect-to',
      timeout: 3000,
      reconnect: {
        maxDelay: 3000,
      }
    },
    ack: false
  });
  console.log('before sending log');
  try {
    // below will never resolve, successfully or unsuccessfully    
    await logger.emit({ event: 'test-connect' });
    // instead: just don't wait for send...will Promises leak?
    // logger.emit({ event: 'test-connect' });
  } catch (errorNeverThrown) {
    // connect error is quietly consumed, emit will just hang
  }
  console.log('after sending log');
}

void awaitLog();

I'll add my feeling that it would be useful to return in some form or fashion in this case to support transparent and minimally invasive logging (while also being able to wait for the message to be send (not acknowledged) or fail), to support the case that the endpoint is temporarily down, or maybe not configured at all.

Does connection only occur upon initialization - that is we need to make sure to connect() for every message? Will the retrier also retry connect, or will it just fail for all attempts after disconnection?