lazywithclass / winston-cloudwatch

Send logs to Amazon Cloudwatch using Winston.
MIT License
258 stars 104 forks source link

Can we use it inside AWS Lambda? #193

Open cheshu21 opened 2 years ago

cheshu21 commented 2 years ago

I am trying to use Winston Cloudwatch inside my Aws Lambda function but My log stream and Log groups are not created. Could you please help me with this ?

lazywithclass commented 2 years ago

Did you try running one of the examples?

This one has been specifically made fo AWS Lambda usage.

harithzainudin commented 2 years ago

hi @lazywithclass, im really new to winston

I'm really not sure what Ive been doing wrong. I've tried to follow the example that you provided. but I'm still unable to see the error log inside the cloudwatch. Am I missing something?

I really need your advice on this :( cause I don't see the error 1 or bye logging in cloudwatch

the context is coming from the lambda context, and the region is coming from the lambda env variable I import and use winston and winston-cloudwatch inside a file actually, and this is the code looks like. So I just call the info() function in my main file.

image

and this is what my main lambda file looks like

image

and this is what Ive got inside cloudwatch

image

using the example you provided from this one

lazywithclass commented 2 years ago

Hello, it's been years since I've used this module in production, expecially in Lambda: to reproduce the problem you're facing I should just write what's in your screenshots, right?

Thanks!

harithzainudin commented 2 years ago

Hello, it's been years since I've used this module in production, expecially in Lambda: to reproduce the problem you're facing I should just write what's in your screenshots, right?

Thanks!

Hi @lazywithclass , yup sure. thanks for the reply :) to make it easier.. let me copy and paste the code here, instead of you writing it back

and yes, to reproduce, you can just copy and paste the code back oh yes, to add on, I think you need to update the readme to include the correct roles as when I add in the error handler, I've got no enough permission

just need to add in this line of tag (I'm using serverless framework btw)

- Effect: "Allow"
  Action: "logs:DescribeLogStreams"
  Resource: "*"

the main lambda handler (async operation)

require("util").inspect.defaultOptions.depth = null;
const { info } = require("../utils/logger");

module.exports.lambda_handler = async (event, context) => {
  console.log("event", event);
  console.log("context", context);

  console.log("using winston - started");
  info(context);
  console.log("using winston - ended");
};

the info logger file

const util = require("util");
const winston = require("winston");
const WinstonCloudWatch = require("winston-cloudwatch");

function info(context) {
  const self = winston.add(
    new WinstonCloudWatch({
      name: "cloudwatch-testing",
      logGroupName: context.logGroupName,
      logStreamName: context.logStreamName,
      awsRegion: process.env.AWS_REGION,
      awsOptions: {
        awsRegion: process.env.AWS_REGION,
      },
    })
  );

  winston.error("1");
  const transport = self.transports.find(
    (t) => t.name === "cloudwatch-testing"
  );

  transport.kthxbye(function () {
    console.log("bye");
  });
}

from what Ive encounter also, because of lambda async process, the winston logger don't have enough time to finish and exit the process properly, hence it doesn't get call the callback properly. Ive tried to use promisify to promisify the kthxbye but no luck :/

Ive also have try to use const { once } = require("events"); and do await once(logger, "finish") but no luck also hm

do let me know if you need me to try anything or test anything. I'll surely try and help you with what I can and know :)

owaisdrabu commented 1 year ago

@lazywithclass https://github.com/lazywithclass/winston-cloudwatch/issues/73#issuecomment-1247853468

adamleemiller commented 5 months ago

I can confirm that this does not work when deploying via Lambda. Unfortunately I deploy via Docker containers to Lambda therefore I am not able to see if there are any errors unless they are console logged which I have tried to do but have not seen any.

lazywithclass commented 4 months ago

It definitely could be used inside AWS Lambda, at some point I wrote a function to be used inside such a service (see an example https://github.com/lazywithclass/winston-cloudwatch/blob/09f8d4d3bfcef59703608e3cddfba0d6b039fd01/examples/flush-and-exit.js#L5), but I imagine something changed in the years and I don't have anymore time to work on this .

GeorgeCr commented 3 months ago

@cheshu21 After days of crying over my lambda... It's hacky, but it does the job. I've done this trying to build this transport from scratch, inspired by this one. So you can override the lib with this hack or build it yourself and use it.


async log(info: any, callback: any) {
    setImmediate(() => {
      this.emit('logged', info);
    });
    const command3 = new PutLogEventsCommand({
     //config
    });
    console.log('command3', command3);
    try {
      await new Promise((resolve) => setTimeout(resolve, 0));
      const result = await client.send(command);
    } catch (err) {
      console.log('failed');
    }
    callback();
  }

This makes that the process doesn't exit and the logger does not finish the job. Adding a timeout to the event loop makes it so.