Skip to content

Getting Started with Salesforce Functions

Johannes Fischer edited this page Jul 6, 2023 · 5 revisions

Starting with version 3.1, RFLIB is available as an NPM package for use with Salesforce Functions supporting Javscript and TypeScript for NodeJS.

Installing RFLIB using NPM

In your Salesforce project repository, switch to the functions folder that you want to include RFLIB in, i.e. functions/My_Function. In the function's folder, execute the following commend:

npm install rflib --save

This will install RFLIB as a NodeJS dependency in the node_modules folder and add it to the package.json file. Make sure to commit the change to the package file.

Function Permission Set

As the Salesforce Documentation states: All deployed Functions invoked by an org use the "Functions" permission set in that org when making data requests.

For RFLIB to be able to retrieve the configuration settings and publish Log Events, the following permissions must be added to the Functions Permission Set:

  • Create permission to the Log Event Platform Event object
  • Create permission to the Application Event Occurred Events Platform Event object
  • Access to the Logger Settings Custom Settings

Logger Settings

Make sure to review the Logger Settings related to Salesforce Functions.

Setting What is it for? Default value
Functions Log Size Defines how many messages are cached in the node runtime. 100 messages should be sufficient. Even with larger strings, i.e. full payloads from server requests, I have never found it to impact performance. 100
Functions Compute Log Level Defines what log statements will be forwarded to the Compute Engine logger. These messages can be further processed using the Function's logs. This setting is configured for Production. DEBUG
Functions Server Log Level Defines what log messages will trigger the creation of a Log Event platform event. Please note that this setting ignores the Log Event Reporting Level, which means that even if the client log level is of lower priority, it will still insert the platform event. Reducing this level in production can sometimes be helpful when diagnosing a specific issue. It is not recommended to set this value below WARN, at least not on a global scope. INFO is the lowest level for this setting that will be accepted, any lower levels (DEBUG, TRACE) will be interpreted as INFO. WARN

Using RFLIB in Javascript

In your Functions index.js file, import the module at the top of the file and create a logger instance as outlined in the example below.

// index.js
import rflib from "rflib"; // Imports the module

// Note how the "logger" (Salesforce standard) was renamed to "computeLogger"
export default async function (event, context, computeLogger) { 
  const logger = rflib.createLogger(context, computeLogger, 'my-js-function-name'); // Create an RFLIB logger instance

  logger.info(`Invoked Function with payload ${JSON.stringify(event.data || {})}`);

  const appEventLogger = rflib.createApplicationEventLogger(context, computeLogger); // using NPM module RFLIB v5.0.1
  appEventLogger.logApplicationEvent('my-event-name', null /* relatedRecordId */, null /* additionalInformation */);

  // Business logic here
}

Using RFLIB in TypeScript

Using RFLIB in TypeScript works similarly to Javascript, with some minor differences. Below is an adaption of the example above.

// index.ts
import * as rflib from "rflib";

export default async function execute(
  event: InvocationEvent<any>,
  context: Context,
  computeLogger: Logger
): Promise<OrgInfo> {
  const logger = rflib.createLogger(context, computeLogger, 'my-ts-function-name'); // Create an RFLIB logger instance

  logger.info(`Invoked Function with payload ${JSON.stringify(event.data || {})}`);

  const appEventLogger = rflib.createApplicationEventLogger(context, computeLogger); // using NPM module RFLIB v5.0.1
  appEventLogger.logApplicationEvent('my-event-name', null /* relatedRecordId */, null /* additionalInformation */);

  // Business logic here
}

Understanding the Function Runtime

The module is unique within the Function runtime. This means that the global log messages are shared between multiple functions. Be aware that Log Event will possibly contain statements from multiple functions that are executed at the same time. This is by design since, similar to RFLIB, there could be other modules that have some global state that is share among all functions. This would allow you to debug issues with concurrency. However, future versions might consider options to provide a log message stack for each logger, but I will wait for community feedback before I start working on that.

Depending on how many concurrent Functions requests your compute environment has to handle, it may be beneficial to increase the Functions Log Size to a value higher than 100.