Function Compute currently 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 calls in the Node.js runtime environments.

Print logs

Function logs printed 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 Logs.

Run the following command to obtain function logs:

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

The output logs are as follows:

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 to be printed. 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 print 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 output logs are as follows:

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 is as follows:

callback(Error error, Object result);           
where:
  • error: Optional. This parameter is used to return error information 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 call type of the function. The returned value of a synchronous call is serialized to a byte stream, which is then returned to the caller. The returned value of an asynchronous call is discarded, in which case you must log important information.
  • The function execution ends after the callback is called.

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

    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 called.

    If no callback is called, 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 calling the following function:

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

    The call result is as follows:

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

Handle errors

You may receive the following types of errors after calling 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 call the callback:

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

    The response is as follows:

    {
      "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 is as follows:

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

For more information, see Error handling.

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 Version Description Reference
co 4.6.0 Control flow https://github.com/tj/co
gm 1.23.0 Image processing library https://github.com/aheckmann/gm
ali-oss 4.10.1 Object Storage Service (OSS) SDK https://github.com/ali-sdk/ali-oss
ali-mns 2.6.5 Message Service (MNS) SDK https://github.com/InCar/ali-mns
tablestore 4.2.0 Tablestore (OTS) SDK https://github.com/aliyun/aliyun-tablestore-nodejs-sdk
aliyun-sdk 1.10.12 Alibaba Cloud SDK https://github.com/aliyun-UED/aliyun-sdk-js
@alicloud/fc2 2.1.0 Function Compute SDK https://github.com/aliyun/fc-nodejs-sdk
opencv 6.0.0 Visual algorithm library https://github.com/peterbraden/node-opencv
body 5.1.0 HTTP body parsing library https://github.com/Raynos/body
raw-body 2.3.2 HTTP body parsing library https://github.com/stream-utils/raw-body

The following shows the sample code 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:

  • Method 1: Manage dependencies by using the node package manager (NPM).

    The following example illustrates 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 the 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 located 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 call the zip command, specify all the files in the desired code directories as source files to generate a deployment code package. For example, you can use zip code.zip /home/code/*.

      After packaging is completed, 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 applications, you can run the fun install command to install dependencies. For more information, see Use fun install to install third-party dependencies. The following example illustrates 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
        python2.7
        python3
        java8
        php7.2
       (Move up and down to reveal more choices)
    2. Use 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 file named template.yml. 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, sets Handler to index.handler, Initializer to index.initializer, and the runtime of the function to nodejs8, and specifies CodeUri as 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, see Serverless Application Model.

    4. Run the fun install command in the root directory of the function to install dependencies.
      $ fun install
      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           

      You can view the related log after the function is executed.

      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.

Call 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 environment of Function Compute. The Node.js runtime environment for Function Compute is as follows:
  • Linux kernel: Linux 4.4.24-2.al7.x86_64
  • Docker base image: docker pull node:6.10