SDK برای Node.js
ردیابی خطای سمت سرور برای برنامههای Node.js با middleware برای Express، breadcrumb، context محدود به یک بلوک و پشتیبانی از TypeScript.
پایش کامل خطاها در برنامههای Node.js
exceptionهای مدیریتنشده و promiseهای rejectشدهی بیپاسخ را میگیرد
middleware داخلی برای مدیریت درخواستها و خطاها در Express.js
رویدادهای پیش از خطا را برای درک بهتر شرایط ثبت میکند
با withScope برای یک بلوک کد بهطور موقت context تعیین کنید
خطاها را به اطلاعات کاربر مرتبط کنید
با beforeSend، ignoredExceptions و ignoredPaths رویدادها را فیلتر یا اصلاح کنید
تعریفهای کامل TypeScript همراه بسته است
نصب#
بستهها از Abrova Center نصب میشوند. دو مرحله دارد:
۱. رجیستری ابرووا را اضافه کنید به فایل .npmrc در ریشهی پروژه (npm، yarn و pnpm همگی آن را میخوانند):
# .npmrc @abrova-trace:registry=https://center.abrova.ir/api/packages/abrova/npm/
۲. بسته را نصب کنید:
npm install @abrova-trace/nodejs-sdk # or yarn add @abrova-trace/nodejs-sdk # or pnpm add @abrova-trace/nodejs-sdk
شروع سریع#
const AbrovaTrace = require('@abrova-trace/nodejs-sdk');
// Initialize AbrovaTrace
AbrovaTrace.init({
apiKey: 'ab_live_your_api_key', // project API key
serverSecret: process.env.ABROVA_SERVER_SECRET, // ab_srv_... (required)
environment: 'production',
release: '1.0.0'
});
// Capture exceptions
try {
throw new Error('Something went wrong!');
} catch (error) {
AbrovaTrace.captureException(error);
}
// Capture messages
AbrovaTrace.captureMessage('User completed checkout');ثبت خطاها#
ثبت exceptionها
AbrovaTrace.captureException(error, {
extra: {
userId: 123,
feature: 'checkout'
}
});ثبت پیامها
AbrovaTrace.captureMessage('Something happened', {
level: 'warning', // 'debug' | 'info' (default) | 'warning' | 'error'
extra: { context: 'additional info' },
tags: { feature: 'checkout' }
});پیامها در کنسول، در بخش ابرووا تریس › پیامها همراه با سطح، پلتفرم، دادههای اضافه و breadcrumbها نمایش داده میشوند. پیام هیچوقت مشکل (issue) نمیسازد. سطح 'warn' بهصورت warning، سطح 'fatal' بهصورت error و سطح 'trace' بهصورت debug فرستاده میشود؛ هر مقدار دیگری info میشود. پیام را برای چیزهایی به کار ببرید که برنامه عمداً گزارش میدهد («checkout شروع شد»، «همگامسازی تمام شد»)؛ برای عیبیابی پرحجم از Logs استفاده کنید.
Breadcrumbها#
Breadcrumbها رویدادهای پیش از خطا را ثبت میکنند تا بفهمید قبل از وقوع خطا چه اتفاقی افتاده است.
Breadcrumb دستی
AbrovaTrace.addBreadcrumb({
message: 'User clicked checkout',
category: 'user-action',
level: 'info',
data: { cartTotal: 99.99 }
});توابع کمکی Breadcrumb
const { Breadcrumb } = require('@abrova-trace/nodejs-sdk');
// HTTP request breadcrumb
AbrovaTrace.addBreadcrumb(Breadcrumb.http('POST', '/api/order', 200, 150));
// Database query breadcrumb
AbrovaTrace.addBreadcrumb(Breadcrumb.database('SELECT * FROM users', 25));
// User action breadcrumb
AbrovaTrace.addBreadcrumb(Breadcrumb.user('clicked_button', { buttonId: 'submit' }));اطلاعات کاربر#
AbrovaTrace.setUser({
id: 123,
email: 'user@example.com',
username: 'john_doe'
});Context محدود به یک بلوک#
با context محدود میتوانید کاربر و مقادیر اضافه را فقط برای یک بلوک کد همگام (synchronous) تعیین کنید. وقتی callback برمیگردد، کاربر و مقادیر اضافه به حالت قبل برمیگردند؛ breadcrumbهایی که داخل بلوک اضافه شدهاند باقی میمانند.
AbrovaTrace.withScope((scope) => {
scope.setUser({ id: 456 });
scope.setExtra('operation', 'bulk_import');
scope.addBreadcrumb({ message: 'Starting import' });
// Errors captured here include this context
AbrovaTrace.captureException(new Error('Import failed'));
});
// Context is restored after the blockیکپارچگی با Express.js#
middleware داخلی برای ردیابی خودکار درخواستها و مدیریت خطا در برنامههای Express.js.
const express = require('express');
const AbrovaTrace = require('@abrova-trace/nodejs-sdk');
const app = express();
// Initialize
AbrovaTrace.init({
apiKey: 'ab_live_your_api_key',
serverSecret: process.env.ABROVA_SERVER_SECRET,
environment: process.env.NODE_ENV
});
// Add middleware
const middleware = AbrovaTrace.expressMiddleware();
app.use(middleware.requestHandler());
// Your routes
app.get('/api/users/:id', async (req, res) => {
// Your route logic
});
// Error handler (must be last)
app.use(middleware.errorHandler());
app.listen(3000);middleware مدیریت خطا باید بعد از همهی routeها اضافه شود. Express لازم میداند که middlewareهای مدیریت خطا آخر از همه تعریف شوند. پیش از AbrovaTrace.expressMiddleware() تابع AbrovaTrace.init() را صدا بزنید: middlewareی که پیش از init() ساخته شود هیچ کاری نمیکند.
خطاهایی که errorHandler() گزارش میدهد شامل متد درخواست، URL، path، route منطبق (مثلاً /api/users/:id)، پارامترهای query و route، user agent، آدرس IP و وضعیت پاسخ هستند (اگر err.status / err.statusCode در محدودهی 4xx یا 5xx باشد همان، وگرنه 500). headerها و body درخواست هرگز فرستاده نمیشوند. پارامترهای query و route که نامشان حساس به نظر برسد (password، token، secret، auth، API key، session، cookie، signature، OTP، code) بهصورت [REDACTED] فرستاده میشوند. همین قاعده برای آدرس درخواستی که همراه خطاها و breadcrumbها فرستاده میشود هم برقرار است: مقدار پارامترهای query حساس در آن با [REDACTED] جایگزین میشود (مثلاً /reset?token=[REDACTED]&page=2)، اما نام پارامترها و بقیهی مقادیر حفظ میشوند (از نسخهی 0.2.3).
ردیابی کوئریهای پایگاه داده#
const AbrovaTrace = require('@abrova-trace/nodejs-sdk');
async function executeQuery(sql, params) {
const startTime = Date.now();
try {
AbrovaTrace.addBreadcrumb({
message: 'Executing query',
category: 'database',
data: { sql: sql.substring(0, 100) }
});
const results = await db.query(sql, params);
AbrovaTrace.addBreadcrumb({
message: 'Query completed',
category: 'database',
data: { duration_ms: Date.now() - startTime }
});
return results;
} catch (error) {
AbrovaTrace.captureException(error, {
extra: { sql, duration_ms: Date.now() - startTime }
});
throw error;
}
}فیلتر کردن خطاها#
با hook به نام beforeSend میتوانید رویدادها را پیش از ارسال به ابرووا تریس فیلتر یا اصلاح کنید. این hook برای exceptionها و رویدادهای captureMessage() اجرا میشود؛ برای حذف یک رویداد null برگردانید. برای نادیده گرفتن کامل یک کلاس exception یا یک path درخواست، بهجای آن از گزینههای ignoredExceptions و ignoredPaths استفاده کنید.
AbrovaTrace.init({
apiKey: 'ab_live_your_api_key',
serverSecret: process.env.ABROVA_SERVER_SECRET,
beforeSend(event) {
// Don't send network errors
if (event.message.includes('ECONNREFUSED')) {
return null;
}
// Add custom data (errors are AbrovaTraceError objects; messages from
// captureMessage() arrive as plain objects without setExtra)
if (typeof event.setExtra === 'function') {
event.setExtra('server_id', process.env.SERVER_ID);
}
return event;
}
});خاموش شدن تمیز#
خطاها، پیامها، لاگها و spanهای عملکرد در پسزمینه فرستاده میشوند. تابع flush() هر چیزی را که هنوز در صف است میفرستد؛ پس پیش از پایان پروسه صدایش بزنید: قبل از process.exit()، در پایان handler یک تابع serverless و در handlerهای خاموش شدن.
process.on('SIGTERM', async () => {
console.log('Shutting down...');
const sent = await AbrovaTrace.flush(2000); // false if 2 seconds pass before everything is sent
await AbrovaTrace.close(); // Sends buffered logs and performance spans, then resets the SDK
process.exit(0);
});تابع flush(timeout) یک timeout بر حسب میلیثانیه میگیرد (پیشفرض: 5000) و یک Promise<boolean> برمیگرداند: اگر ارسال در مهلت تمام شود true و اگر مهلت زودتر تمام شود false. این Promise هیچوقت reject نمیشود. close() هم یک Promise برمیگرداند؛ لاگها و spanهای عملکردِ در بافر را میفرستد، اما منتظر خطاها و پیامهایی که هنوز در حال ارسالاند نمیماند؛ پس اول flush() را صدا بزنید. بعد از close()، پیش از استفادهی دوباره از SDK باید init() را دوباره صدا بزنید.
در یک تابع serverless، پیش از برگشتن handler عمل flush را انجام دهید:
exports.handler = async (event) => {
try {
return await processEvent(event);
} catch (error) {
AbrovaTrace.captureException(error);
throw error;
} finally {
await AbrovaTrace.flush();
}
};Source mapها#
اگر از TypeScript، bundlerها (webpack، esbuild) یا Babel استفاده میکنید، برای stack trace دقیق source mapها را فعال کنید:
node --enable-source-maps app.js
یا از داخل کد برنامه:
process.setSourceMapsEnabled(true);
لاگگیری#
لاگ ساختاریافتهی سمت سرور، بهصورت دستهای و با backoff نمایی و بدون هیچ وابستگی. لاگها به ابرووا تریس › Logs میروند و از captureMessage() (بخش پیامها) جدا هستند. بعد از init()، یک بار لاگگیری را فعال کنید و از هر جای برنامه لاگ بنویسید:
AbrovaTrace.enableLogging({ sourceId: 'api-server' });
AbrovaTrace.info('Server started on port 3000');
AbrovaTrace.warn('Database connection slow', { latency: 2500 });
AbrovaTrace.logError('Failed to process payment', { orderId: '12345' });برای جزئیات کامل این مسیر — سطحهای لاگ، یکپارچگی با Express، ارسال دستهای و خاموش شدن تمیز — صفحهی لاگگیری در SDK برای Node.js را ببینید.
گزینههای پیکربندی#
AbrovaTrace.init({
apiKey: 'ab_live_your_api_key', // Required
serverSecret: 'ab_srv_your_secret', // Required
environment: 'production', // Default: NODE_ENV or 'development'
release: '1.0.0', // Default: npm_package_version or '1.0.0'
enabled: true, // Default: true
debug: false, // Default: false
timeout: 5000, // Default: 5000ms
captureUncaughtExceptions: true, // Default: true
captureUnhandledRejections: true, // Default: true
maxBreadcrumbs: 50, // Default: 50 (max 100)
sampleRate: 1.0, // Default: 1.0 (captureException and captureMessage)
ignoredExceptions: ['ValidationError'], // Error class, error.name, or RegExp
ignoredPaths: ['/health*'], // Express paths not reported
beforeSend: (event) => event, // Filter/modify events
});| گزینه | نوع | اجباری | توضیح |
|---|---|---|---|
| apiKey | string | بله | کلید API پروژه (ab_live_xxx) |
| serverSecret | string | بله | کلید سرور (ab_srv_xxx)؛ فقط روی سرور نگهش دارید |
| environment | string | خیر | نام محیط (پیشفرض: NODE_ENV یا "development") |
| release | string | خیر | نسخهی برنامه (پیشفرض: npm_package_version یا "1.0.0") |
| enabled | boolean | خیر | روشن/خاموش کردن ردیابی (پیشفرض: true) |
| debug | boolean | خیر | فعال کردن لاگ عیبیابی (پیشفرض: false) |
| timeout | number | خیر | مهلت HTTP بر حسب میلیثانیه، 1000 تا 30000 (پیشفرض: 5000) |
| captureUncaughtExceptions | boolean | خیر | ثبت خودکار exceptionهای مدیریتنشده (پیشفرض: true) |
| captureUnhandledRejections | boolean | خیر | ثبت خودکار rejectionهای مدیریتنشده (پیشفرض: true) |
| maxBreadcrumbs | number | خیر | حداکثر تعداد breadcrumbهای نگهداشتهشده، تا ۱۰۰ (پیشفرض: 50). ۱۰ مورد آخر همراه هر رویداد فرستاده میشوند |
| sampleRate | number | خیر | سهم رویدادهای captureException() و captureMessage() که فرستاده میشوند، 0.0 تا 1.0 (پیشفرض: 1.0) |
| ignoredExceptions | array | خیر | exceptionهایی که captureException() و error handler مربوط به Express گزارش نمیکنند: یک کلاس خطا (با instanceof مقایسه میشود)، رشتهای برابر با error.name، یا یک RegExp که روی error.name آزموده میشود. exceptionهای مدیریتنشده و rejectionهای مدیریتنشده همیشه گزارش میشوند |
| ignoredPaths | array | خیر | pathهای درخواستی که middleware مربوط به Express از آنها میگذرد: glob، path دقیق یا RegExp |
| beforeSend | function | خیر | hook برای فیلتر یا اصلاح خطاها و پیامها پیش از ارسال؛ برای حذف، null برگردانید |
آمار SDK#
const stats = AbrovaTrace.getStats();
console.log(stats);
// {
// isEnabled: true,
// breadcrumbCount: 5,
// rateLimiter: { totalErrorsInWindow: 3, uniqueErrorsInWindow: 2, totalLimit: 100, errorLimit: 10, windowMs: 60000 },
// config: { environment: 'production', release: '1.0.0', apiKey: 'ab_live_abc1234...' }
// }پشتیبانی از TypeScript#
SDK تعریفهای کامل TypeScript را همراه دارد. هر typeی را که لازم دارید import کنید:
import AbrovaTrace, {
AbrovaTraceInitOptions,
AbrovaTraceError,
Breadcrumb,
BreadcrumbOptions,
UserContext
} from '@abrova-trace/nodejs-sdk';پیشنیازها#
- Node.js — >= 14.0.0
- Express (اختیاری) — >= 4.0.0
مرجع API#
AbrovaTrace
init(config)— راهاندازی SDKcaptureException(error, options?)— ثبت یک خطاcaptureMessage(message, options?)— ارسال پیام به ابرووا تریس › پیامها (options:level،extra،tags)addBreadcrumb(breadcrumb)— افزودن یک breadcrumbsetUser(user)— تعیین اطلاعات کاربرsetRequestContext(context)— تعیین context درخواست که به رویدادهای ثبتشده پیوست میشودwithScope(callback)— اجرای کد با scope جداگانهexpressMiddleware()— گرفتن middleware برای Express.jsflush(timeout?)— ارسال خطاها، پیامها، لاگها و spanهای عملکرد در صف؛timeoutبر حسب میلیثانیه (پیشفرض: 5000). خروجیPromise<boolean>است: اگر مهلت زودتر تمام شودfalseclose()— ارسال لاگها و spanهای عملکرد و سپس پاکسازی (یک Promise برمیگرداند)getStats()— گرفتن آمار SDKenableLogging(options?)،log()،trace()،logDebug()،info()،warn()،logError()،fatal()،flushLogs()— لاگگیری (صفحهی لاگگیری در SDK برای Node.js را ببینید)trackOperation(name, fn, options?)،reportPerformanceSpan(span)،reportPerformanceSpanBatch(spans)،flushPerformance()— spanهای عملکرد
توابع کمکی Breadcrumb
Breadcrumb.http(method, url, status?, duration?)— breadcrumb برای درخواست HTTPBreadcrumb.database(query, duration, error?)— breadcrumb برای کوئری پایگاه دادهBreadcrumb.user(action, data?)— breadcrumb برای کار کاربرBreadcrumb.console(level, message, ...args)— breadcrumb برای خروجی consoleBreadcrumb.navigation(from, to, method?)— breadcrumb برای جابهجایی بین صفحههاBreadcrumb.custom(message, category, data?)— breadcrumb با دستهبندی دلخواه
Middleware برای Express
requestHandler()— middleware ردیابی درخواست را برمیگرداندerrorHandler()— middleware مدیریت خطا را برمیگرداندuserMiddleware()— اطلاعات کاربر را ازreq.user(id، email، username) تعیین میکندtransactionMiddleware(name)— برای یک route نامدار، breadcrumbهای شروع و پایان (مدت و وضعیت) اضافه میکند
نمونهی کامل#
const express = require('express');
const AbrovaTrace = require('@abrova-trace/nodejs-sdk');
const { Breadcrumb } = require('@abrova-trace/nodejs-sdk');
// Initialize AbrovaTrace
AbrovaTrace.init({
apiKey: 'ab_live_your_api_key',
serverSecret: process.env.ABROVA_SERVER_SECRET,
environment: process.env.NODE_ENV || 'development',
release: '1.0.0',
captureUncaughtExceptions: true,
captureUnhandledRejections: true,
maxBreadcrumbs: 50,
debug: process.env.NODE_ENV === 'development',
});
const app = express();
// Add AbrovaTrace middleware
const middleware = AbrovaTrace.expressMiddleware();
app.use(middleware.requestHandler());
app.use(express.json());
// Set user context from auth
app.use((req, res, next) => {
if (req.user) {
AbrovaTrace.setUser({
id: req.user.id,
email: req.user.email,
});
}
next();
});
app.get('/api/users/:id', async (req, res) => {
AbrovaTrace.addBreadcrumb(Breadcrumb.user('view_user', {
userId: req.params.id,
}));
try {
const user = await db.query('SELECT * FROM users WHERE id = ?', [req.params.id]);
AbrovaTrace.addBreadcrumb(Breadcrumb.database('SELECT * FROM users', 15));
res.json(user);
} catch (error) {
AbrovaTrace.captureException(error, {
extra: { userId: req.params.id },
});
res.status(500).json({ error: 'Internal Server Error' });
}
});
// Error handler (must be last)
app.use(middleware.errorHandler());
// Graceful shutdown
process.on('SIGTERM', async () => {
await AbrovaTrace.flush(2000);
await AbrovaTrace.close();
process.exit(0);
});
app.listen(3000, () => console.log('Server running on port 3000'));توصیهها#
ابرووا تریس را در ابتدای نقطهی ورود برنامه راهاندازی کنید تا همهی خطاها ثبت شوند
برای ردیابی کامل در Express.js، request handler را اول و error handler را آخر اضافه کنید
خطاها را به اطلاعات کاربر مرتبط کنید تا عیبیابی آسانتر شود
با withScope برای یک بلوک همگام context موقت تعیین کنید؛ context در SDK برای کل پروسه مشترک است، برای همین وقتی callback برمیگردد به حالت قبل برمیگردد
کارهای مهم (کوئریهای پایگاه داده، درخواستهای HTTP، کارهای کاربر) را بهصورت breadcrumb ثبت کنید
در SIGTERM/SIGINT منتظر flush() و close() بمانید تا خطاها، لاگها و spanهای در صف فرستاده شوند
برای stack trace دقیق در برنامههای TypeScript یا bundleشده از --enable-source-maps استفاده کنید
خطاهای پرسروصدا را فیلتر کنید و دادهی خطا را با context دلخواه غنی کنید