Time out when using chrome on lambda: Any way to see more logs?



  • I am not getting a return from the render function.. my question is can I enable more logging somehow to see where jsreport is getting hung up? details below:

    I am using chrome-aws-lambda to enable running chrome on lambda. I am able to run the example code from this package and it works. Takes about 3 seconds to run.

    sample code here:

     (async () => {
          log.info(`loading chrome `);
          const chromium = require('chrome-aws-lambda');
    
          let executablePath =  await chromium.executablePath;
          log.info(`executable path ... `, executablePath);
    
          let browser = await chromium.puppeteer.launch({
            args: chromium.args,
            defaultViewport: chromium.defaultViewport,
            executablePath: await chromium.executablePath,
            headless: chromium.headless,
          });
        log.info(`executable path ... `, chromium.executablePath);
          log.info(`new page ... `);
          let page = await browser.newPage();
          log.info(`new page ... `, page);
          await page.goto(event.url || 'https://example.com');
    
          let result = await page.title();
          log.info(`result `, result);
        })();
    

    I get back:

    "log": [
            "result ",
            "Example Domain"
        ],
    

    The path for the chromium is /tmp/chromium..

     "log": [
            "executable path ... ",
            "/tmp/chromium"
        ],
    

    I pass this to jsreport:

    const jsreport = require('jsreport-core')({
        tasks: {
            allowedModules: '*',
            strategy: 'in-process'
        },
        loadConfig: false,
        studio: { enabled: false },
        allowLocalFilesAccess: true,
        dataDirectory: path.join(os.tmpdir(), 'jsreport'),
        templatingEngines: { allowedModules: '*' },
        extensions: {
            "chrome-pdf": {
                "launchOptions": {
                    executablePath: "/tmp/chromium",
                    "args": ["--no-sandbox"]
                }
            }
        }
    });
    

    and I guess it loads since it did not error.. but it never returns from render.

    oh.. these are my dependancies. I also pass the flag for pupppeter not to download chrome since it is too large for lambda.. hence using the package

    "dependencies": {
        "chrome-aws-lambda": "^1.17.1",
        "config": "1.21.0",
        "handlebars": "^4.1.0",
        "handlebars-helpers": "0.10.0",
        "handlebars-intl": "1.1.2",
        "jsonwebtoken": "8.2.1",
        "jsreport-chrome-pdf": "^1.4.0",
        "jsreport-core": "^2.4.3",
        "jsreport-handlebars": "^2.0.1",
        "jsreport-html-to-xlsx": "^2.3.0",
        "jsreport-xlsx": "^2.0.10",
        "mongoose": "4.13.17",
        "puppeteer": "1.12.2",
        "regenerator-runtime": "^0.13.2",
        "upgrade": "1.1.0",
        "uuid": "3.1.0"
      },
    

    any thoughts on where jsreport might be getting stuck?



  • oh.. I am doing a very simple foo bar example . template below: Any suggestions would be really appreciated.

            content: "<h1>Hello  {{foo}} </h1>",
            recipe: 'chrome-pdf',
            engine: 'handlebars',
            mimeType: "application/pdf",
            filename: "report.pdf"
        }
    


  • Have you seen our tutorial on how to run jsreport on AWS lambda?

    https://jsreport.net/learn/aws-lambda-serverless



  • ahh.. I did not. We already have js reports running as lambda for a long time.. I was trying to not mess with it and just insert the chrome. Let me look through and try that and see how it works. Thanks for putting that together!



  • @jan_blaha that article was outstanding. Thank you for doing that and putting it together. Very clean solution.
    I did change it all sync calls and I also don't download chrome if it already exists .. I added that bit just fyi.

    Thank you again for documenting that.



  • Thanks for your hints. I'm reading some docs of lambda and I can see that the temp can, but doesn't need to, be shared between multiple instances of the same function.

    This means that downloading and writing chrome to the same location, like I currently do, can break because another instance which is just using it.
    Skipping download if it is already there, can, however, be wrong because the function can assume chrome is fully written to the temp, but the writing can take a little more.
    It sounds to me that the best is to:

    • skip downloading chrome if /tmp/headless-chromium is there
    • download it and write to /tmp/headless-chromium-[random]
    • rename to /tmp/headless-chromium (and continue if error says the file is already there)

    This should be a safe and robust approach because the rename is atomic operation. What do you think?



  • well I use writeFileSync, as well as chmodSync.. so it 'should' wait until written. I have not seen any issues so far in my testing. I have not performance tested.

    So in theory if we run without any of those functions being 'done' the report will error.
    So in theory this is all very tight. I say in theory because only way to really know is to do a performance test.

    I am not sure the suggestion is gonna work because then you are talking about the time between renames and how do you wait on that? (because I think rename can also fail if the chrome is being used.

    Downloading each time is the most robust approach, but until I see where the getObject, writeFileSync and chmodSync re not really sync.. I am ok not to add the additional complexity of renaming.

    My entire jsreport is sync..so I need it to all hold until the report is final.

    I am more than happy to report back here if I see the function I created is not working well for larger number of requests .. for sure..

    thoughts?

    Below is my function.

    const getBucket = promisify(s3.getObject).bind(s3)
    ...
     getBucket(config).then((response) => {
            fs.writeFileSync('/tmp/headless-chromium', response.Body);
            fs.chmodSync('/tmp/headless-chromium', '755');
    ...
    }
    


  • btw.. I spoke to one of my peers.. and he likes your solution to avoid multiple calls all writing the same file. I wonder if there is an atomic writeFileSync that will fail if the file exists already?



  • https://github.com/npm/write-file-atomic
    I found that.. which seems to do the same thing . it downloads and renames (depends on the rename being atomic on the os, Windows it is not).

    so your solution is a good one.. I will move to use this package and change my fs.writeFileSync to use this package (which seems to do your solution under the covers) and will handle this .. good call.


Log in to reply
 

Looks like your connection to jsreport forum was lost, please wait while we try to reconnect.