Skip to content

Node.js Backend

import { createGunsoleClient } from "@gunsole/core";
const gunsole = createGunsoleClient({
projectId: "my-api",
mode: "local",
env: process.env.NODE_ENV,
appName: "api-server",
appVersion: process.env.npm_package_version,
batchSize: 25, // Flush every 25 logs
flushInterval: 2000, // Or every 2 seconds
defaultTags: {
service: "api",
},
});
// Catch unhandled errors (logged as fatal)
gunsole.attachGlobalErrorHandlers();
gunsole.setUser({
id: "user-42",
name: "Admin",
});

Log every request:

import express from "express";
const app = express();
app.use((req, res, next) => {
const start = Date.now();
res.on("finish", () => {
const duration = Date.now() - start;
const level = res.statusCode >= 500 ? "error" : res.statusCode >= 400 ? "warn" : "info";
gunsole[level]({
bucket: "http",
message: `${req.method} ${req.path}${res.statusCode} (${duration}ms)`,
context: {
method: req.method,
path: req.path,
statusCode: res.statusCode,
duration,
userAgent: req.get("user-agent"),
ip: req.ip,
},
tags: {
method: req.method,
route: req.route?.path || req.path,
status: String(res.statusCode),
},
});
});
next();
});
async function query(sql, params) {
const start = Date.now();
try {
const result = await db.query(sql, params);
gunsole.debug({
bucket: "db",
message: `Query OK (${Date.now() - start}ms)`,
context: { sql, params, rowCount: result.rowCount },
tags: { operation: sql.trim().split(" ")[0].toUpperCase() },
});
return result;
} catch (err) {
gunsole.error({
bucket: "db",
message: `Query failed: ${err.message}`,
context: { sql, params, error: err.message },
tags: { operation: sql.trim().split(" ")[0].toUpperCase() },
});
throw err;
}
}
// Send 100 logs across 10 buckets, then flush and destroy
for (const { level, bucket, message, context, tags } of logs) {
const opts = { bucket, message, context, tags };
switch (level) {
case "info": gunsole.info(opts); break;
case "debug": gunsole.debug(opts); break;
case "warn": gunsole.warn(opts); break;
case "error": gunsole.error(opts); break;
case "fatal": gunsole.fatal(opts); break;
}
}
// Always flush before exiting
await gunsole.flush();
gunsole.destroy();

Flush remaining logs before exiting:

process.on("SIGTERM", async () => {
await gunsole.flush();
gunsole.destroy();
process.exit(0);
});

If you’re on Node.js < 18 where fetch isn’t built-in:

import fetch from "node-fetch";
const gunsole = createGunsoleClient({
projectId: "my-api",
mode: "local",
fetch: fetch,
});