@codensity/node
v0.6.0
Published
Official Node.js SDK for Codensity resource usage and sustainability tracking
Maintainers
Readme
@codensity/node
The official Node.js SDK for Codensity. See the estimated energy and carbon behind each feature of your app.
Install
npm install @codensity/nodepnpm add @codensity/nodeyarn add @codensity/nodeQuick start
import { CodensityClient } from "@codensity/node";
const codensity = new CodensityClient({
key: process.env.CODENSITY_KEY!,
environment: "production",
});
const result = await codensity.track("checkout-flow", () =>
processCheckout(data),
);Create an SDK key in your project's dashboard and store it in CODENSITY_KEY.
It looks like cds_live_…@api.getcodensity.com. Use the whole value as shown,
and never commit it to source control. Each key belongs to one environment of
your project, such as production, and every event sent with it is filed there.
The first argument to track is the feature key, such as "checkout-flow".
Use lowercase letters, numbers, dashes and underscores, up to 100 characters;
other keys aren't accepted. A key your project doesn't have yet is created
automatically the first time you send it.
Open your project's dashboard to see each feature's estimated energy and carbon.
Client options
const codensity = new CodensityClient({
key: process.env.CODENSITY_KEY!,
environment: "production",
appVersion: "2.1.0",
flushInterval: 5_000,
maxBatchSize: 50,
maxBufferSize: 1_000,
maxRetries: 2,
onError: (error) => console.error("[codensity]", error),
});| Option | Required | Default | Description |
| --- | --- | --- | --- |
| key | Yes | None | Your SDK key |
| environment | Yes | None | A label for where your app runs, such as "production". Events always go to the environment your key belongs to. |
| appVersion | No | None | Your app's version, sent with your events |
| flushInterval | No | 5000 | How often events are sent, in milliseconds |
| maxBatchSize | No | 50 | Send early once this many events are waiting |
| maxBufferSize | No | 1000 | How many events to hold while Codensity can't be reached. When full, the oldest are dropped first. |
| maxRetries | No | 2 | How many times to retry when Codensity is busy or can't be reached |
| onError | No | None | Called when events can't be sent or are dropped |
Track a function
track runs an async function (one that returns a promise), measures how long
it takes and how much memory it uses, then returns its result unchanged.
const user = await codensity.track("get-user", () =>
db.users.findById(userId),
);If the function throws, it is still measured, and the error is passed on to you.
Record a measurement yourself
codensity.record({
featureKey: "checkout-flow",
executionTimeMs: 145,
memoryBytes: 1024,
metadata: { region: "eu-north-1" },
});Metadata values can be strings, numbers or booleans. Don't put personal data in metadata.
What the SDK sends
Only what you track: the feature key, how long it ran, the memory it used, a timestamp, the SDK and app versions, and any metadata you add. It never reads request bodies, headers or user data.
Send events before exit
Events are sent in the background. Before your process exits, send whatever is still waiting:
await codensity.flush();Do this when shutting down, at the end of a serverless function, or when a script finishes. NestJS apps do this for you, see Shutdown.
Express
Track a route under a feature key:
import { CodensityClient } from "@codensity/node";
import express from "express";
const app = express();
const codensity = new CodensityClient({
key: process.env.CODENSITY_KEY!,
environment: "production",
});
app.post(
"/checkout",
codensity.trackFlow("checkout-flow"),
checkoutHandler,
);NestJS
Set up the module
import { Module } from "@nestjs/common";
import { CodensityModule } from "@codensity/node/nestjs";
@Module({
imports: [
CodensityModule.forRoot({
key: process.env.CODENSITY_KEY!,
environment: "production",
}),
],
})
export class AppModule {}To read the key from ConfigService instead:
import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { CodensityModule } from "@codensity/node/nestjs";
@Module({
imports: [
ConfigModule.forRoot(),
CodensityModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
key: config.getOrThrow<string>("CODENSITY_KEY"),
environment: "production",
}),
}),
],
})
export class AppModule {}Track route handlers
Turn on tracking once in main.ts, after NestFactory.create:
import type { CodensityClient } from "@codensity/node";
import {
CODENSITY_CLIENT,
CodensityInterceptor,
} from "@codensity/node/nestjs";
import { Reflector } from "@nestjs/core";
const client = app.get<CodensityClient>(CODENSITY_CLIENT);
const reflector = app.get(Reflector);
app.useGlobalInterceptors(new CodensityInterceptor(client, reflector));Then mark the handlers you want to track:
import { Track } from "@codensity/node/nestjs";
@Track("checkout-flow")
async checkout() {
return this.checkoutService.process();
}Track anything else
Inject the client and use track:
import type { CodensityClient } from "@codensity/node";
import { CODENSITY_CLIENT } from "@codensity/node/nestjs";
import { Inject, Injectable } from "@nestjs/common";
@Injectable()
export class ReportsService {
constructor(
@Inject(CODENSITY_CLIENT)
private readonly codensity: CodensityClient,
) {}
generate() {
return this.codensity.track("analytics-report", () =>
this.buildReport(),
);
}
}Shutdown
The module sends waiting events when your app shuts down through app.close().
The simplest way to get that is to let Nest handle shutdown signals:
app.enableShutdownHooks();If you handle signals yourself, call app.close() in your handler instead (and
don't also call enableShutdownHooks()):
process.on("SIGTERM", async () => {
await app.close();
process.exit(0);
});If your process can end without app.close(), for example in a serverless
function, call flush() yourself:
import type { CodensityClient } from "@codensity/node";
import { CODENSITY_CLIENT } from "@codensity/node/nestjs";
const codensity = app.get<CodensityClient>(CODENSITY_CLIENT);
await codensity.flush();Learn more
The full guide, including the HTTP API for other languages, is at getcodensity.com/docs.
Requirements
- Node.js 18 or later
- NestJS 9 or later, if you use the NestJS integration
License
MIT
