Vercel Functions to GCP Cloud Logging
Log Observability Implementation
Table of contents
No headings in the article.
Well, Vercel Serverless architecture is easy to develop, developer-friendly, and easy to deploy. As and when you start to scale your hobby project into a scale-version, you need to implement several things to keep your systems up and running, error-free. One such system is logging to a log management tool. Vercel offers log-drain options to various services, thanks to their integration partners like Datadog, Logdna, etc. However, Google Cloud Platform's (GCP) Cloud Logging is not an integration provided out of the box. Let's learn to implement the Cloud Logging library and flow our logs into GCP.
โ๐ผ Before we dive deep inside - find if this article works for you
- This implementation will require a GCP service account, specifically the
client_email
,private_key
andproject_id
of the service account to connect. - This implementation is not async and you'll need to await each call due to the serverless architecture limitation. The function may terminate earlier than the log being sent to GCP if not await'ed.
- This implementation will not work on
Edge Functions
like_middleware.ts
since the edge functions runtime runs on browser environment and the logging library's dependencies likefs
won't work.
Get your service account
- Go to your
GCP console
, thenIAM
section, thenService accounts
tab, and then create a new service account. Name it anything you want, give theLogging Admin
permission to the service account. - Once created, select the service account and create a JSON
key
. The downloaded key will containclient_email
,private_key
andproject_id
key-value pairs. This is used to authenticate Google Cloud Logging library which we'll use.
โ๐ผ Note
Vercel environment variables are limited to 4 Kb in total since the underlying AWS Lambda layer supports only unto this limit. This is for each environment.
If you plan to use the service account JSON in the environment variable, plan to add all the permissions your functions may need to a single service account. Creating multiple service accounts for different GCP or Firebase services is not a great approach to follow with Vercel architecture constraints.
Let's create a reusable class for logging
- We've used the service account credentials JSON key file as an environment variable named
GOOGLE_SERVICE_ACCOUNT
. - Install Cloud Logging library
yarn add @google-cloud/logging
. VERCEL_ENV
is either production, staging or development. This is used to log appropriately in a GCP project.
import { Logging } from '@google-cloud/logging';
import { VercelRequest } from "@vercel/node";
export class CloudLogging {
logging = new Logging({
projectId: JSON.parse(process.env.GOOGLE_SERVICE_ACCOUNT).project_id,
credentials: {
client_email: JSON.parse(process.env.GOOGLE_SERVICE_ACCOUNT).client_email,
private_key: JSON.parse(process.env.GOOGLE_SERVICE_ACCOUNT).private_key,
}
});
log = this.logging.log(process.env.VERCEL_ENV, {
removeCircular: true
});
async logData(severity: string, data: string | JSON | any) {
try {
await this.log.write(this.log.entry({
resource: {
type: 'global',
},
labels: {
label: 'exampleLabel'
},
severity: severity,
}, data));
} catch (error) {
console.log(error);
} finally {
return;
}
}
}
Using the CloudLogging class we created
- We import the class we just created called
CloudLogging
. Feel free to tweak the class as per your requirement. - We send logs to GCP Cloud Logging by using the
logData()
method inside the class.
import { CloudLogging } from '@/lib/gcp/logging'; // Refer where you create the class
async function someFunction() {
//...
await cloudLogging.logData('INFO', jsonData || stringData);
//...
}
someClass {
async someMethod() {
//...
await cloudLogging.logData('ERROR', jsonData || stringData);
//...
}
}
Viola, the log service implementation is done and logs will be visible in the GCP console for viewing or data querying.