The official Treblle SDK for JavaScript frameworks including Hono. Seamlessly integrate Treblle to manage communication with your dashboard, send errors, and secure sensitive data.
Treblle with Hono
To integrate Treblle with Hono, we provide an official unified SDK for JavaScript frameworks - treblle.
Requirements
- Node.js:
>=18.0.0(relies on the built-in globalfetch) - Hono:
4.x
Hono is multi-runtime, and the Treblle SDK works across Node.js, Bun, and Deno.
Installation
Install the Treblle JavaScript SDK via NPM :
npm install treblle@^3.0.0Load the required module in your app:
import { honoTreblle } from "treblle";Note
New in v3: per-framework subpath imports let bundlers include only the adapter you use. For Hono you can import from treblle/hono:
import { honoTreblle } from "treblle/hono";Setting up credentials
Create a free account on treblle.com to get your credentials:
sdkToken(SDK Token)apiKey(API Key)
Add these to your .env file:
TREBLLE_SDK_TOKEN=your_sdk_token
TREBLLE_API_KEY=your_api_keyBasic Setup
Initialize Treblle in your app by registering the honoTreblle middleware on all routes:
import { Hono } from "hono";
import { honoTreblle } from "treblle";
const app = new Hono();
// Add Treblle middleware to all routes
app.use(
"*",
honoTreblle({
sdkToken: process.env.TREBLLE_SDK_TOKEN,
apiKey: process.env.TREBLLE_API_KEY,
})
);
// Add your routes
app.get("/api/users", (c) => c.json({ users: [] }));
app.post("/api/users", async (c) => {
const body = await c.req.json();
return c.json({ success: true, user: body });
});
export default app;That’s it! Your API requests and responses are now being sent to your Treblle Dashboard. You’ll get features like auto-documentation, real-time request/response monitoring, and error tracking.
Configuration Options
You can pass additional configuration options:
app.use(
"*",
honoTreblle({
sdkToken: process.env.TREBLLE_SDK_TOKEN,
apiKey: process.env.TREBLLE_API_KEY,
maskedKeywords: ["customSecret", "internalId"], // Optional: Mask additional fields
blockedPaths: ["admin", "health"], // Optional: Skip logging certain paths
debug: true, // Optional: Show Treblle errors in console (default: false)
ingressEndpoint: "https://ingress-eu.treblle.com", // Optional: Custom ingress endpoint
})
);Available options
Option
Description
sdkToken (required)
Your Treblle SDK token
apiKey (required)
Your Treblle API key
maskedKeywords (optional)
Keywords to mask in request/response bodies and headers. Replaces the default keywords - spread DEFAULT_MASKED_KEYWORDS to extend them. Pass [] to turn masking off.
blockedPaths (optional)
Array of path prefixes or RegExp to exclude from logging
debug (optional)
Boolean to show Treblle-related errors in console (default: false)
ingressEndpoint (optional)
Custom Treblle ingress endpoint URL to send data to (default: https://ingress.treblle.com)
Selective route monitoring
Hono’s routing lets you scope the Treblle middleware to only the routes you care about:
// Monitor only API routes
app.use(
"/api/*",
honoTreblle({
sdkToken: process.env.TREBLLE_SDK_TOKEN,
apiKey: process.env.TREBLLE_API_KEY,
})
);
// Or exclude specific paths
app.use(
"*",
honoTreblle({
sdkToken: process.env.TREBLLE_SDK_TOKEN,
apiKey: process.env.TREBLLE_API_KEY,
blockedPaths: /^\/(health|metrics|admin)/, // Using RegExp for complex patterns
})
);Choosing where data is sent (data region)
By default the SDK sends all data to https://ingress.treblle.com. If you need your data processed in a specific region, set the ingressEndpoint option to the appropriate Treblle ingress URL:
app.use(
"*",
honoTreblle({
sdkToken: process.env.TREBLLE_SDK_TOKEN,
apiKey: process.env.TREBLLE_API_KEY,
ingressEndpoint: "https://ingress-eu.treblle.com", // send data to the EU ingress
})
);When ingressEndpoint is omitted (or empty), the SDK falls back to the default https://ingress.treblle.com.
Masking sensitive data
Treblle masks sensitive values in request/response bodies and headers before anything leaves your server. Matching is case-insensitive and applies to values of any type. Masking is driven entirely by the maskedKeywords option:
maskedKeywords
Behavior
not set (default)
The built-in default keywords are masked
your own array
Exactly the keywords you list are masked - this replaces the defaults
[] (empty array)
Masking is turned off entirely - bodies and headers are sent as-is
Default masked keywords
When you don’t set maskedKeywords, the following keywords are masked by default:
password, pwd, secret, password_confirmation, passwordConfirmation, cc, card_number, cardNumber, ccv, ssn, credit_score, creditScore, authorization, cookie, set-cookie, x-api-key, api_key, apikey, token, access_token, accessToken, refresh_token, refreshToken, bearer, x-auth-token
Adding to the defaults
Because your array replaces the defaults, extend them by spreading the exported DEFAULT_MASKED_KEYWORDS list rather than listing every default by hand:
import { honoTreblle, DEFAULT_MASKED_KEYWORDS } from "treblle";
app.use(
"*",
honoTreblle({
sdkToken: process.env.TREBLLE_SDK_TOKEN,
apiKey: process.env.TREBLLE_API_KEY,
maskedKeywords: [...DEFAULT_MASKED_KEYWORDS, "customSecret", "internalId"],
})
);Turning masking off
Pass an empty array to disable masking completely:
app.use(
"*",
honoTreblle({
sdkToken: process.env.TREBLLE_SDK_TOKEN,
apiKey: process.env.TREBLLE_API_KEY,
maskedKeywords: [], // masking disabled
})
);Caution
With masking off, sensitive request/response body fields and headers - including Authorization, Cookie, API keys and tokens - are sent to Treblle in plaintext. Only disable masking when you are certain no sensitive data flows through the monitored endpoints.
Path blocking examples
Block specific paths or patterns from being logged:
// Block specific paths (string array)
blockedPaths: ["admin", "health", "metrics"];
// Block using RegExp for complex patterns
blockedPaths: /^\/(admin|health|metrics)/;
// Mixed array with strings and RegExp
blockedPaths: ["admin", /^\/api\/v1\/internal/];Tracking database queries
Treblle can show the SQL queries executed during each request (with their execution time) in the data.queries array of the payload. Node has no framework-wide “a query ran” event, so query tracking is opt-in: you wire your database layer’s query event to Treblle’s trackQuery helper once, and every query made during a request is captured automatically. Until you do this, data.queries is simply an empty array.
trackQuery(sql, time) records a query against the request currently in flight (it uses AsyncLocalStorage under the hood, so you don’t need access to c). It is a no-op when called outside of a request.
Caution
Only pass the parameterized SQL string (e.g. SELECT * FROM users WHERE id = $1) - never the parameter bindings. As a safety net, trackQuery also scrubs any inline string/number literals it finds (replacing them with ?).
import { trackQuery } from "treblle";Prisma - enable the query event log and forward each event:
const prisma = new PrismaClient({
log: [{ level: "query", emit: "event" }],
});
prisma.$on("query", (e) => trackQuery(e.query, e.duration));Note
Prisma emits query events on an internal async channel, which can lose the request’s context in some setups. If queries don’t appear, prefer a per-request Prisma extension/middleware that calls trackQuery.
Knex - subscribe to its (synchronous, reliable) query events:
const timers = new Map();
knex.on("query", (q) => timers.set(q.__knexQueryUid, process.hrtime.bigint()));
knex.on("query-response", (_res, q) => {
const start = timers.get(q.__knexQueryUid);
const ms = start ? Number(process.hrtime.bigint() - start) / 1e6 : 0;
timers.delete(q.__knexQueryUid);
trackQuery(q.sql, ms);
});Sequelize - turn on benchmark and forward from the logging callback:
const sequelize = new Sequelize(connectionString, {
benchmark: true, // provides the execution time (ms) as the 2nd arg
logging: (sql, ms) => trackQuery(sql, ms),
});Adding custom metadata
Attach your own key/value properties to each request - for example user-id, plan, or region - so you can search and filter on them in Treblle. The pairs are sent in the payload as a data.metadata object.
setMetadata works the same way in every framework with no extra setup. Like trackQuery, it uses AsyncLocalStorage under the hood, so you can call it from anywhere during a request without access to c - and it is a no-op when called outside of one. It accepts either a single key/value or an object of pairs:
import { setMetadata } from "treblle";
app.get("/orders", (c) => {
setMetadata("user-id", c.get("userId"));
setMetadata({ plan: "premium", region: "eu" });
return c.json({ ok: true });
});To keep the payload small and search-friendly, metadata is limited:
- Max 20 keys per request (extra new keys are dropped).
- Keys up to 64 characters (longer keys are truncated).
- Values must be a string, number, or boolean; strings up to 128 characters (longer values are truncated, unsupported types are dropped).
Caution
Metadata is not masked - values are sent verbatim. Never put secrets, tokens, or sensitive personal data in metadata.
Production-only Setup
Run Treblle only in production:
const app = new Hono();
if (process.env.NODE_ENV === "production") {
app.use(
"*",
honoTreblle({
sdkToken: process.env.TREBLLE_SDK_TOKEN,
apiKey: process.env.TREBLLE_API_KEY,
})
);
}Debugging
Enable debug mode to see Treblle errors in your console:
app.use(
"*",
honoTreblle({
sdkToken: process.env.TREBLLE_SDK_TOKEN,
apiKey: process.env.TREBLLE_API_KEY,
debug: true,
})
);Tip
For production environments, consider using environment-based configuration to automatically enable or disable debug mode without code changes.
Migrating from v2 to v3
Several configuration options were renamed for clarity and consistency in v3. sdkToken and apiKey keep their names. Update your config:
v2 option
v3 replacement
additionalFieldsToMask
maskedKeywords - same behavior; replaces the defaults, [] turns masking off
blocklistPaths
blockedPaths - same behavior
endpoint
ingressEndpoint - same behavior
ignoreDefaultBlockedPaths
removed - the default blocked paths are now always applied and cannot be disabled
Note
Masking now on by default: in v2, honoTreblle accidentally disabled masking when maskedKeywords was omitted. v3 fixes this - the default keywords are always masked unless you explicitly pass maskedKeywords: [].
Cloudflare Workers support removed: the moduleWorkerTreblle and serviceWorkerTreblle exports have been removed. If you use Treblle in Cloudflare Workers, stay on treblle@2.x for now - a dedicated web-standards edge SDK is coming as a separate package.
Node.js >=18 required: v3 dropped the node-fetch fallback and relies on the built-in global fetch.