Deploy Lightrun on Node.js Google Cloud Functions🔗
In this tutorial, you will learn how to configure the Lightrun Node.js agent with your Google Cloud Function and deploy it using the gcloud CLI or Cloud Build.
To use Lightrun in your Google Cloud Function, you must deploy Lightrun's agent library with your project. Google Cloud Functions (Gen2) run on Cloud Run and support Node.js runtimes, and functions with dependencies are deployed by packaging them in the source code and deploying via the gcloud CLI or Cloud Build.
Important
Gen1 Cloud Functions have not been tested. Lightrun's Google Cloud wrapper only supports Cloud Functions Gen2. Ensure you deploy with the --gen2 flag when using gcloud functions deploy.
Prerequisites🔗
This tutorial assumes that you have:
- A Lightrun account.
- A Google Cloud account with a project set up.
- gcloud CLI installed and configured on your local machine.
- Node.js installed on your local machine (version 18 or higher).
Configure your Cloud Function source code to work with Lightrun🔗
-
Initialize and wrap your Cloud Function code with the
lightrun/gcpmodule. Thelightrun/gcpmodule ensures that the Lightrun agent is enabled before calling the serverless function, and also properly manages the agent lifecycle for subsequent function invocations.const lightrun = require("lightrun/gcp"); // Initialize Lightrun once at the top level of your file lightrun.init({ lightrunSecret: process.env.LIGHTRUN_SECRET, agentLog: { logsPath: "", level: "debug" }, metadata: { registration: { displayName: "<gcp_function_name>", tags: ['<gcp_function_name>'] } } }); // Wrap your function handler (must be Promise-based) exports.myFunction = lightrun.wrap(async (req, res) => { // Your function code here res.send('Hello from Lightrun!'); });Rules and guidelines
- Change
<gcp-function-name>to your Cloud Function's name.
- Callback-based functions are not supported. Lightrun's Google Cloud wrapper only supports Promise-based (async/await) function handlers. Your function handler must return a Promise or be declared as
async.
-
Debug Google Cloud Functions with the Lightrun Node.js agent.
- The wrapper automatically sets
lightrunWaitForInit: trueto ensure the agent has time to communicate with the Lightrun server before the function execution completes. The wrapper uses a defaultlightrunInitWaitTimeMsof 5000ms (5 seconds), which can be overridden by specifyinglightrunInitWaitTimeMsin thelightrun.init()options if needed.
- Apply metadata tags that include the name of your Cloud Function. This allows you to attach Lightrun actions (breakpoints, logs, etc.) to agents before the function is invoked. Actions bound to metadata tags are automatically attached to all agents that possess those tags.
- The
lightrun.init()call should be made once at the top level of your file, not inside the function handler. The wrapper will reuse the agent instance across warm starts within the same execution environment.
- The wrapper automatically sets
Security best practices
The following examples use environment variables (
process.env.LIGHTRUN_SECRET) for simplicity. For production deployments, use Secret Manager instead. Environment variables are stored in plaintext and can be accessed by anyone with appropriate permissions. Secret Manager provides encryption at rest and in transit, access controls, and auditing.To use Secret Manager, create a secret first:
Then reference it in your deployment command usingecho -n "<your_lightrun_secret>" | gcloud secrets create <secret_name> --data-file=---set-secrets=LIGHTRUN_SECRET=<secret_name>:latestinstead of--set-env-vars=LIGHTRUN_SECRET=<lightrun_secret>. Ensure the Cloud Functions service account has theroles/secretmanager.secretAccessorrole.HelloLightrunHTTP function exampleconst functions = require('@google-cloud/functions-framework'); const lightrun = require('lightrun/gcp'); lightrun.init({ lightrunSecret: process.env.LIGHTRUN_SECRET, metadata: { registration: { displayName: 'helloLightrun' } } }); functions.http('helloHttp', lightrun.wrap(async (req, res) => { res.set('Content-Type', 'text/plain'); res.send('Hello from Lightrun!\n'); }));This example is an HTTP-triggered function. To deploy it, use the HTTP deployment command displayed in the deployment section.
- Change
-
Add Lightrun as a dependency in your
package.jsonfile.{ "name": "gcp_cloud_function", "version": "1.0.0", "description": "GCP Cloud Function with Lightrun", "author": "Lightrun", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "lightrun": ">=1.76.0", "@google-cloud/functions-framework": "^3.0.0" } }
Deploy the Cloud Function🔗
You can deploy your Cloud Function using the gcloud CLI or Cloud Build. The following examples show deployment commands for different trigger types.
Deploy with gcloud CLI🔗
-
Change to your project directory.
cd <your_project_directory> -
Deploy the Cloud Function using
gcloud functions deploy. The following examples show the basic deployment commands for different trigger types.Deployment command placeholders
Placeholder Description <function_name>Your Cloud Function name <region>Your preferred Google Cloud region <entry_point_function_name>The name of your exported function <lightrun_secret>Your Lightrun secret key <bucket_name>Cloud Storage bucket name (for Storage triggers) <topic_name>Pub/Sub topic name (for Pub/Sub triggers) Storage-triggered functions
gcloud functions deploy <function_name> \ --gen2 \ --runtime=nodejs20 \ --region=<region> \ --source=. \ --entry-point=<entry_point_function_name> \ --trigger-bucket=<bucket_name> \ --set-env-vars=LIGHTRUN_SECRET=<lightrun_secret>HTTP-triggered functions
gcloud functions deploy <function_name> \ --gen2 \ --runtime=nodejs20 \ --region=<region> \ --source=. \ --entry-point=<entry_point_function_name> \ --trigger-http \ --set-env-vars=LIGHTRUN_SECRET=<lightrun_secret>Pub/Sub-triggered functions
gcloud functions deploy <function_name> \ --gen2 \ --runtime=nodejs20 \ --region=<region> \ --source=. \ --entry-point=<entry_point_function_name> \ --trigger-topic=<topic_name> \ --set-env-vars=LIGHTRUN_SECRET=<lightrun_secret>Add any additional deployment flags (timeout, memory, scaling, etc.) as needed for your function.
Deploy with Cloud Build🔗
You can also deploy your Cloud Function using Cloud Build by creating a cloudbuild.yaml file.
steps:
# Deploy the Cloud Function
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: 'gcloud'
dir: '${_FUNCTION_DIR}' # Change to function directory before deploying
args:
- 'functions'
- 'deploy'
- '${_FUNCTION_NAME}' # Function name
- '--gen2'
- '--runtime=${_RUNTIME}' # Node.js runtime (e.g., nodejs20)
- '--region=${_REGION}' # Region (e.g., europe-west3)
- '--source=.' # Source is current directory (function dir)
- '--entry-point=${_ENTRY_POINT}' # Function entry point name
- '--trigger-bucket=${_TRIGGER_BUCKET}' # Storage bucket trigger
- '--set-env-vars=${_ENV_VARS}' # Environment variables
# Default substitution variables - ALL can be overridden in Cloud Build trigger settings
substitutions:
_FUNCTION_NAME: 'my-function'
_RUNTIME: 'nodejs20'
_REGION: 'europe-west3'
_FUNCTION_DIR: '.' # Directory containing your function code
_ENTRY_POINT: 'helloHttp' # Entry point function name
_TRIGGER_BUCKET: 'my-bucket' # Storage bucket name
_ENV_VARS: 'LIGHTRUN_SECRET=your-lightrun-secret'
options:
logging: CLOUD_LOGGING_ONLY
Note
For HTTP-triggered functions, replace --trigger-bucket=${_TRIGGER_BUCKET} with --trigger-http. For Pub/Sub-triggered functions, use --trigger-topic=${_TRIGGER_TOPIC} instead.
Verify the deployment🔗
To verify that a Lightrun agent has been added to your Cloud Function correctly:
- Verify that a new agent with your Cloud Function name is created anytime your Cloud Function runs (cold start) and persists across warm starts within the same execution environment.
- Verify that a tag with your Cloud Function name has been added to your Lightrun account.
Agent Lifecycle: Cold start and warm start behavior🔗
Understanding how the Lightrun agent operates during Cloud Function cold starts and warm starts is essential for optimizing performance and managing server communication efficiently.
Cold start vs. warm start🔗
Google Cloud Functions (Gen2) execute in two distinct modes:
- Cold start: Occurs when Google Cloud initializes a new execution environment for your Cloud Function. This happens when the function is invoked for the first time, when Google Cloud scales to handle increased traffic, or when the function has been idle long enough for Google Cloud to terminate the previous execution environment.
- Warm start: Occurs when Google Cloud reuses an existing execution environment from a previous invocation. After a cold start, Cloud Function execution environments may remain active for minutes or hours, depending on Google Cloud's internal resource management policies. During this time, the environment is in a dormant state until the next invocation.
Agent initialization strategy🔗
The Lightrun agent employs an optimized initialization strategy to minimize overhead and reduce unnecessary server communication.
Cold start behavior🔗
During a cold start, the Lightrun agent:
- Initializes and starts up within the new execution environment (via
lightrun.init()called at module load time). - Registers with the Lightrun Server.
- Fetches all active breakpoints from the server.
- Remains resident in memory for subsequent invocations.
This initialization occurs only once per execution environment. Starting a new agent on every function invocation would be computationally expensive and inefficient, so the agent persists across multiple warm starts within the same execution environment.
Warm Start behavior🔗
During a warm start, the agent:
- Reuses the existing agent instance from the previous invocation.
- Fetches breakpoints from the Lightrun Server only if more than the configured timeout (default: client connection timeout) has elapsed since the last fetch.
- Skips server communication entirely for rapid consecutive invocations.
This intelligent caching mechanism ensures that multiple consecutive function calls do not generate redundant requests to the Lightrun Server.
Connection management🔗
The Lightrun agent does not maintain a persistent connection to the Lightrun Server. This design decision reflects the typical characteristics of Cloud Functions:
- Cloud Function invocations are usually short-lived (lasting seconds to minutes).
- Persistent long-polling connections would be inefficient for short execution windows.
- The agent uses a pull-based model to fetch breakpoints on-demand.
Agent expiration configuration🔗
When the Lightrun agent runs inside a Cloud Function, its expiration time on the Lightrun Server is configured to handle the Cloud Function lifecycle appropriately. The agent remains registered and available for warm starts, ensuring that breakpoints can be attached even when the function is not actively executing.