Function Compute supports Node.js 6.10 with Node.js 6 runtime, Node.js 8.9.0 with Node.js 8 runtime, Node.js 10.15.3 with Node.js 10 runtime, and Node.js 12.16.1 with Node.js 12 runtime. This topic describes the logs, functions, errors, modules, and external command invocations in Node.js runtime environments.

Display logs

Function logs displayed by using console.log are collected into the Logstore that you specify when you create the service to which the functions belong. For more information about function logs, see Configure Log Service resources and view function execution logs.

Run the following command to obtain function logs:

exports.handler = function (event, context, callback) {
    console.info('hello world');
    callback(null, 'hello world');
};            

The similar output log is displayed:

message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [INFO] hello world           
In addition, you can call the setLogLevel operation to specify the level of logs you want to display. The following table lists the log levels in descending order.
Log level Interface
Error console.error
Warn console.warn
Info console.info
Verbose console.log
Debug console.debug

Execute the following code to display warn and error logs.

'use strict';
exports.handler = function(evt, ctx, cb) {
    console.setLogLevel("error");
    console.error("console error 1");
    console.info("console info 1");
    console.warn("console warn 1");
    console.log("console log 1");

    console.setLogLevel("warn");
    console.error("console error 2");
    console.info("console info 2");
    console.warn("console warn 2");
    console.log("console log 2");

    console.setLogLevel("info");
    cb(null, evt);
};            

The similar output logs are displayed:

message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [ERROR] console error 1
message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [ERROR] console error 2
message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [WARN] console warn 2          

Return data

Node.js is based on the asynchronous programming model. To return data, you must add the callback function as an input parameter to your functions. The syntax of the callback function:

callback(Error error, Object result);           
The parameters in the function:
  • error: optional. This parameter is used to return the error message if the function fails internally. The value is null if the function is executed.
  • result: optional. This parameter is used to return the result that indicates the function is executed. The value of result can be of any type. Function Compute serializes the value into a byte stream, adds the byte stream to the body of the response, and returns the response to the caller.
Note The method for processing the returned value varies depending on the invocation type of the function. The returned value of a synchronous invocation is serialized to a byte stream, which is then returned to the caller. The returned value of an asynchronous invocation is discarded, in which case you must log important information.
  • The function execution ends after the callback is invoked.

    After the callback is invoked, the execution of the function ends. If callback is invoked multiple times, only the result of the first callback takes effect. Ensure that all tasks are complete before the callback is invoked. Otherwise, some tasks may not be run. For example, the following function returns hello world but message will not be displayed.

    exports.handler = function(event, context, callback) {
      callback(null, 'hello world');
      callback(null, 'done');
      setTimeout(function() {
        console.log('message');
      }, 1000);
    };          
  • The function times out if the callback is not invoked.

    If no callback is invoked, the system considers that the function is still in process, and then waits for the result of the function until the function times out. For example, you will receive a timeout error after invoking the following function:

    exports.handler = function(event, context, callback) {
      console.log('hello world');
    };            

    The invocation result:

    {"errorMessage":"Function timed out after 3 seconds"}           

Troubleshooting

You may receive the following types of errors after invoking a function in the Node.js runtime environment. The error type is indicated by X-Fc-Error-Type in the returned HTTP Header field.

  • HandledInvocationError: errors returned by the first parameter of the callback.

    Example:

    Run the following command to invoke the callback:

    exports.handler = function(event, context, callback) {
      callback(new Error('oops'));
    };

    The response:

    {
      "errorMessage": "oops",
      "errorType": "Error",
      "stackTrace": [
        "at exports.handler (/code/index.js:2:12)"
      ]
    }
  • UnhandledInvocationError: other errors, including uncaptured exceptions, timeout errors, and out-of-memory (OOM) errors.

    If no error is captured based on the function logic, Function Compute attempts to capture errors and returns specific information. The system returns generic error information if the system cannot capture any error, for example, because your running function suddenly fails and exits.

    exports.handler = function(event, context, callback) {
      throw new Error('oops');
    };

    The response:

    {"errorMessage":"Process exited unexpectedly before completing request"}

For more information, see Handle errors.

Use built-in modules

In addition to standard Node.js modules, the Node.js runtime environment for Function Compute provides the following common modules that you can directly reference.

Module Supported version Description
co 4.6.0 Control flow
gm 1.23.0 Image processing library
ali-oss 4.10.1 OSS SDK
ali-mns 2.6.5 MNS SDK
tablestore 4.2.0 OTS SDK
aliyun-sdk 1.10.12 Aliyun SDK
@alicloud/fc2 2.1.0 Function Compute SDK
opencv 6.0.0 Visual algorithm library
body 5.1.0 HTTP body parsing library
raw-body 2.3.2 HTTP body parsing library

The following code is for accessing OSS:

var gm = require('gm').subClass({ imageMagick: true });
exports.handler = function (event, context, callback) {
    gm(event)
        .flip()
        .toBuffer('PNG', function (err, buffer) {
            if (err) return callback(err);
            callback(null, buffer); 
       });
};
Note The preceding function directly uses the binary data of the image in the event parameter and directly returns the binary data for the generated image.

Use custom modules

To use a custom module, you must package the custom module and the code together and upload the package. You can manage dependencies by using the following methods:

Notice If you package custom modules locally, you must upload node_modules.
  • Method 1: Manage dependencies by using the node package manager (NPM).

    The following example demonstrates how to add a MySQL module.

    1. Run the following command to create a directory to store the code and dependent module.
      mkdir /tmp/code
    2. Run the following command to install dependencies in the /tmp/code directory.
      cd /tmp/code
      npm install mysql
    3. Create a code file, such as /tmp/code/index.js, and use the MySQL module in the code.
      var mysql = require('mysql');
      var connection;
      // exports.initializer: initializer function
      exports.initializer = function (context, callback) {
        connection = mysql.createConnection({
          host: 'localhost',
          user: '***',
          password: '*******',
          database: 'my_db'
        });
        connection.connect();
      }
      
      exports.handler = function (event, context, callback) {
        connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
          if (error) return callback(error);
          console.log('The solution is: ', results[0].solution);
          callback(null, results[0].solution);
        });
        connection.end();
      };
    4. Package and upload the code and dependencies.

      You must package the desired files instead of all code folders. After you package the files, ensure that the files of the handler function are placed in the root directory of the package.

      • In the Windows operating system, you can select all the files in the desired code directories of the function, right-click these files, and compress the files into a code package in ZIP format.
      • In the Linux operating system, when you invoke the zip command, specify all the files in the desired code directory as source files to generate a deployment code package. For example, you can use zip code.zip /home/code/*.

      After packaging is complete, click the function name in the Function Compute console. On the page that appears, click the Code tab. You can select Import from OSS or Upload Zip File to upload the code package.

  • Method 2: Install dependencies by running the fun install command.

    If you use FunCraft to deploy an application, you can run the fun install command to install dependencies. For more information, see Run the fun install command to install third-party dependencies. The following example demonstrates how to add a MySQL module.

    1. Run the following command to initialize the Funfile file in the root directory of the function.
      fun install init
      ? Select a runtime
        nodejs6 
      ❯ nodejs8
        nodejs10
        nodejs12
        python2.7
        python3
        java8
        php7.2
       (Move up and down to reveal more choices)
    2. Use the Node.js 8 runtime, generate a file named Funfile in the current directory, and edit the content of the file.
      RUNTIME nodejs8
      RUN npm install mysql
    3. Create a template.yml file. For more information, see template.yml. For example, create /tmp/code/template.yml.
      ROSTemplateFormatVersion: '2015-09-01'
      Transform: 'Aliyun::Serverless-2018-04-03'
      Resources:
        FunDemo: 
          Type: 'Aliyun::Serverless::Service'
          nodejsdemo: 
            Type: 'Aliyun::Serverless::Function'
            Properties:
              Handler: index.handler
              Runtime: nodejs8
              Initializer: index.initializer
              CodeUri: './'           

      The template.yml file declares the FunDemo service and the nodejsdemo function for the FunDemo service. The file sets Handler to index.handler, Initializer to index.initializer, the runtime of the function to nodejs8, and CodeUri to the current directory. For more information, see CodeUri. During application deployment, Funcraft packages and uploads the specified folders or files under the CodeUri directory.

      For more configuration rules, visit Serverless Application Model.

    4. Run the fun install command in the root directory of the function to install dependencies.
      fun install

      The following result is returned:

      using template: template.yml
      start installing function dependencies without docker
      
      building FunDemo/nodejsdemo
      Funfile exist, Fun will use container to build forcely
      Step 1/2 : FROM registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-nodejs8:build-1.9.4
      ---> 8c6c75614064
      Step 2/2 : RUN npm install mysql
      ---> Using cache
      ---> 715f4427faf9
      sha256:715f4427faf9b66238328e44736078f2ac4bbc0d403e441a6c460b6cc2f405ae
      Successfully built 715f4427faf9
      Successfully tagged fun-cache-58fa61db-dd07-416b-aa47-a6ee752ec6d7:latest
      copying function artifact to /Users/txd123/Desktop/express
      
      Install Success
      
      
      Tips for next step
      ======================
      * Invoke Event Function: fun local invoke
      * Invoke Http Function: fun local start
      * Build Http Function: fun build
      * Deploy Resources: fun deploy
                                  
    5. Use Funcraft to deploy the application.
      fun deploy           

      The following result is returned:

      using region: cn-hangzhou
      using accountId: ***********3557
      using accessKeyId: ***********r3Ra
      using timeout: 300
      
      Waiting for service FunDemo to be deployed...
          Waiting for function nodejsdemo to be deployed...
              Waiting for packaging function nodejs code...
              package function nodejs code done
          function nodejsdemo deploy success
      service FunDemo deploy success
                                  

    Log on to the Function Compute console. You can see that the related services and functions are created. If you click Invoke in the Code tab, the correct results are returned.

Run external commands

Your functions may use some tools that are not written in Node.js, such as executable files that are compiled in Shell, C++, or Go. You can package these tools and the code together and use them by running external commands in the functions. The following code shows how to run a Shell script.

var exec = require('child_process');

exports.handler = function(event, context, callback) {
  var scriptPath = process.env['FC_FUNC_CODE_PATH'] + '/script.sh';
  exec.exec('bash '+scriptPath, {}, function(err, stdout, stderr) {
    if (err) return callback(err);
    console.log(stdout, stderr);
    callback(null, stdout);
  });
};
            
Note The executable files compiled in C, C++, and Go must be compatible with the runtime environments of Function Compute. The Node.js runtime environments in Function Compute:
  • Linux kernel: Linux 4.4.24-2.al7.x86_64
  • Docker base image: docker pull node:6.10