Search code examples
debuggingibm-cloudopenwhiskibm-cloud-functions

Debugging IBM Cloud Function


I started looking at IBM Cloud Functions (NodeJS runtime) and I was wondering if anyone had been able to debug a function on his local machine.

Suppose to have a simple NodeJs function which returns a json.

const md5 = require('spark-md5');

function myAction(params) {
    // params contain the "rows" coming from Cloudant including the full documents
    return {
        entries: params.rows.map((row) => { return {
            name: row.doc.name,
            email: row.doc.email,
            comment: row.doc.comment,
            createdAt: row.doc.createdAt,
            icon: (row.doc.email ? `https://secure.gravatar.com/avatar/${md5.hash(row.doc.email.trim().toLowerCase())}?s=64` : null)
        }})
    };
}

exports.main = myAction;

I would like to have breakpoints and step-by-step debug. How can I debug this function before deploying it on the IBM Cloud Functions? I really don't have an idea even on how I can pass inputs and see outputs.I'm used to use Postman for testing my backends but here I'm a bit confused and don't know where to start.


Solution

  • The way I usually solve problems like this is by breaking up my code and exporting it in a way that I can "plug it in" to something I know how to run and debug. You've actually already done that in terms of how you've organized your code. Your cloud function is a function that takes a params argument, returns an object, and you've exported it with exports.main = myAction;.

    To test this locally, including running it in a debugger, I'd create an entry point file which imports the action and calls it. I can run that file without the debugger enabled, relying on console.log to help me debug (which I'd remove before deploying to production), or I can run it with the debugger.

    // main.js
    const action = require('./action').main;
    
    const actionResult = action({
        rows: [
            {
                doc: {
                    name: 'Jane',
                    email: '[email protected]',
                    comment: 'Lovely day, isn\'t it?',
                    createdAt: new Date(),
                },
            },
        ],
    });
    
    console.log('Result:', result);
    

    To run it with the debugger in VS Code, I'd click "Run and Debug" when I have the file open and in focus:

    starting debugger 1

    And I'd choose "Node.js":

    starting debugger 2

    With the debugger running, any break points I set, notably one in the action's file, are hit:

    break point hit

    And I can look at the state as the action executes:

    state of variables during debug

    If I wanted to do a more advanced test, to more closely resemble how my actions would be deployed as web actions, I'd set up an Express.js app and make adapter that use the action as Express.js middleware. Because the signature of a JS action is not compatible with Express.js as middleware, I'd have to write an adapter:

    const express = require('express');
    const action = require('./action').main;
    
    const app = express();
    app.use(express.json());
    
    app.post('/', function (req, res) {
        const actionInput = req.body; // JSON request results in object here
        const actionResult = action(actionInput);
        res.json(actionResult);
    });
    
    app.listen(3000);
    

    express app result

    Just like above, in VS Code, I can debug this with breakpoints and inspect state. Note the ISO8601 string used in the request body in my Insomnia screenshot:

    vs code debugging break point with express