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",});Express middleware
Section titled “Express middleware”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();});Database queries
Section titled “Database queries”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; }}Sending logs across buckets
Section titled “Sending logs across buckets”// Send 100 logs across 10 buckets, then flush and destroyfor (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 exitingawait gunsole.flush();gunsole.destroy();Graceful shutdown
Section titled “Graceful shutdown”Flush remaining logs before exiting:
process.on("SIGTERM", async () => { await gunsole.flush(); gunsole.destroy(); process.exit(0);});Custom fetch (Node.js < 18)
Section titled “Custom fetch (Node.js < 18)”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,});