@napp/logger
v5.0.3
Published
low level log archigture. minimum resources, user friendly, powerfull logger library. supported browser & nodejs
Readme
@napp/logger
Lightweight, dependency-free logger core for Node.js and modern browsers.
Node.js болон browser орчинд ажиллах, хамаарал багатай хөнгөн logger library.
- Zero runtime dependencies — Runtime хамаарал байхгүй
- Tree-based hierarchical log level config — Tree бүтэцтэй шаталсан log level тохиргоо
onWriteevent stream — app controls where logs go — Гаралтыг апп өөрөө удирданаbaseAttrinheritance across parent → child loggers — Parent → child хооронд metadata дамжина- Full + short methods:
trace/debug/info/warn/error/fatalandt/d/i/w/e/f - ESM + CJS dual build, TypeScript types included — ESM + CJS хоёуланд ажиллана
Install
npm install @napp/loggerQuick Start
import { LogContext, LogLevel, getLogger } from '@napp/logger';
// One-time setup at app startup
// Апп эхлэхэд нэг удаа тохируулна
LogContext.defaultContext.config.set(['app'], LogLevel.Info);
LogContext.defaultContext.onWrite.subscribe(log => {
console.log(`[${log.level}] ${log.logpath.join('.')} — ${log.message}`, log.attr);
});
// Use anywhere in the app — аппын хаана ч дуудаж болно
const log = getLogger('app.route');
log.info('server started', { port: 3000 });
log.debug('skipped — below Info'); // Info-с доош тул гарахгүйCore Concepts / Үндсэн ойлголтууд
Log Level
Log levels control which events are emitted.
Log level нь ямар event гарахыг шийдэнэ.
| Level | Value | Description |
|-------|-------|-------------|
| Off | 0 | Logging disabled / Унтраасан |
| Trace | 1 | Most verbose / Хамгийн дэлгэрэнгүй |
| Debug | 5 | Debug info / Debug мэдээлэл |
| Info | 9 | General info / Ерөнхий мэдээлэл |
| Warn | 13 | Warnings / Анхааруулга |
| Error | 17 | Errors / Алдаа |
| Fatal | 21 | Critical failures / Хэрэглэх боломжгүй алдаа |
Parse a level from string or number:
String эсвэл тоогоор level авах:
import { parseLogLevel, LogLevel } from '@napp/logger';
parseLogLevel('warn', LogLevel.Info) // → LogLevel.Warn
parseLogLevel(11, LogLevel.Off) // → LogLevel.Info (nearest band / ойр түвшин)
parseLogLevel('unknown', LogLevel.Info) // → LogLevel.Info (default)Log Name — Prefix Tree Config
Log нэр — Prefix Tree тохиргоо
Log names use . as a separator and form a tree. Config inherits down the tree.
Log нэр нь .-ээр тусгаарлагдаж tree бүтэц үүсгэнэ. Тохиргоо дээрээс доош өвлөгдөнө.
const ctx = new LogContext();
ctx.config.set(['app'], LogLevel.Info);
ctx.config.set(['app', 'db'], LogLevel.Error);
// app.route → Info (inherits from 'app' / 'app'-аас өвлөнө)
// app.db → Error (exact match / яг тохирсон)
// app.db.pool → Error (inherits from 'app.db')
// other → Off (no config → silent / тохиргоо байхгүй → гарахгүй)Root config-г хоосон path буюу []-ээр тохируулна. Энэ нь бүх log name-д үйлчлэх global default level болно.
Root config uses an empty path []. It becomes the global default level for every log name.
ctx.config.set([], LogLevel.Info);
ctx.config.set(['app', 'db'], LogLevel.Error);
// app.route → Info (inherits from root / root-оос өвлөнө)
// app.db → Error (branch override / салбарын override)
// other → Info (inherits from root / root-оос өвлөнө)LogLevel.Off means no logs are emitted for that branch.LogLevel.Off бол тухайн салбарт log бичигдэхгүй.
onWrite — App Handles Output / Апп гаралтыг хэрэгжүүлнэ
The library only decides whether to emit. The app subscribes to onWrite and writes wherever it needs.
Library нь зөвхөн emit хийх эсэхийг шийднэ. Бичих үйлдлийг апп onWrite-д subscribe хийж өөрөө хэрэгжүүлнэ.
ctx.onWrite.subscribe(log => {
console.log(log); // stdout
fs.appendFileSync('app.log', JSON.stringify(log)) // disk / файл
fetch('/logs', { body: JSON.stringify(log) }) // remote / сервер
});baseAttr — Structured Metadata / Бүтэцтэй metadata
Attach shared metadata to a logger. Every log event from that logger automatically includes it.
Logger-т нэг удаа metadata оноовол тухайн logger-ийн бүх event-д автоматаар дагалдана.
const log = ctx.getLogger('app.route', { service: 'api', env: 'prod' });
log.info('request received', { requestId: 'abc' });
// attr → { service: 'api', env: 'prod', requestId: 'abc' }Merge order / Merge дараалал: ctx.baseAttr → logger.baseAttr → event attr
Later values override earlier ones for the same key.
Ижил нэртэй талбарт сүүлийн утга өмнөхийг дарна.
child() — Scoped Child Logger / Дэд logger
const appLog = ctx.getLogger('app');
const dbLog = appLog.child('db'); // logpath: ['app', 'db']
const sqlLog = appLog.child('db.query'); // logpath: ['app', 'db', 'query']Child inherits parent baseAttr and can add or override fields.
Child нь parent-ийн baseAttr-ийг өвлөж, нэмэх эсвэл дарж болно.
const parent = ctx.getLogger('app', { service: 'api' });
const child = parent.child('route', { module: 'user' });
// child baseAttr → { service: 'api', module: 'user' }LogContext
LogContext holds the config tree and onWrite stream for the entire app.LogContext нь апп дахь config tree болон onWrite stream-ийг нэгтгэн хадгална.
import { LogContext, LogLevel } from '@napp/logger';
const ctx = new LogContext({ env: 'prod' }); // optional baseAttr
ctx.config.set(['app'], LogLevel.Info);
ctx.onWrite.subscribe(log => console.log(log));
const log = ctx.getLogger('app.route');
log.warn('slow response', { ms: 420 });Default Context (Singleton) / Үндсэн context
LogContext.defaultContext is a pre-created singleton. getLogger() without a ctx argument uses it automatically.LogContext.defaultContext нь урьдчилан үүссэн singleton. ctx заахгүй бол getLogger() үүнийг автоматаар ашиглана.
// Setup once at startup — эхлэхэд нэг удаа
LogContext.defaultContext.config.set(['app'], LogLevel.Debug);
LogContext.defaultContext.onWrite.subscribe(log => console.log(log));
// Use anywhere — хаана ч ctx заахгүйгээр
const log = getLogger('app.worker');
log.info('ready');Custom Context (Testing / Isolation) / Тусгай context
Useful for tests or isolated modules where you don't want to share the default context.
Test болон тусгаарлагдсан модульд default context-ийг хуваалцахгүйгээр ашиглах боломж.
const testCtx = new LogContext();
testCtx.config.set(['app'], LogLevel.Trace);
const captured: ILogItem[] = [];
testCtx.onWrite.subscribe(log => captured.push(log));
const log = getLogger('app', undefined, testCtx);
log.info('test event');Attr Serialization — toJSON / Attr-ийн JSON хөрвүүлэлт
The library passes attr values as-is. It does not serialize Error objects or any other type automatically.
Library нь attr-ийн утгыг шууд дамжуулна. Error болон бусад object-ийг автоматаар боловсруулахгүй.
Serialization is the app's responsibility — controlled via toJSON().
JSON болгох үйлдэл нь хэрэглэгчийн хариуцлага — toJSON() тусламжтайгаар удирдана.
// ❌ Without toJSON — toJSON байхгүй бол
log.error('failed', { error: new Error('timeout') });
// attr.error → {} ← Error object JSON-д хоосон болно
// ✅ With toJSON — toJSON нэмсэн бол
class AppError extends Error {
toJSON() {
return { name: this.name, message: this.message, stack: this.stack };
}
}
log.error('failed', { error: new AppError('timeout') });
// attr.error → { name: 'AppError', message: 'timeout', stack: '...' }Same applies to any custom object — toJSON() gives you full control over what gets logged.
Ямар ч custom object-д toJSON() нэмж, ямар мэдээлэл log-д орохыг өөрөө тодорхойлно.
class User {
constructor(public id: number, public name: string, private password: string) {}
toJSON() {
return { id: this.id, name: this.name }; // password орохгүй / password excluded
}
}
log.info('login', { user: new User(1, 'bat', 's3cr3t') });
// attr.user → { id: 1, name: 'bat' }Safe JSON + Redaction / Аюулгүй JSON ба нууцлал
@napp/logger нь attr дээр mask, hide, redact автоматаар хийхгүй. Энэ нь app талын policy байна.@napp/logger does not automatically mask, hide, or redact attr. This is an app-side policy.
Writer руу дамжуулахын өмнө app нь log event-ийг safe plain JSON object болгон хувиргаж, sensitive талбаруудыг нуух эсвэл маск хийх ёстой.
Before passing a log event to a writer, the app should convert it to a safe plain JSON object and hide or mask sensitive fields.
ctx.onWrite.subscribe(log => {
const safeLog = toSafeJsonLog(log, {
hide: ['password', 'token', 'headers.authorization'],
mask: ['user.email', 'user.phone'],
});
writer.write(safeLog);
});Recommended flow / Зөвлөмж болгож буй урсгал:
logger → raw structured event → app serializer/redactor → writerMessage string-д secret утга шууд оруулахгүй. Sensitive мэдээллийг attr дээр бүтэцтэй өгч, app serializer/redactor дээр policy хэрэгжүүлнэ.
Do not put secrets directly into the message string. Pass sensitive values as structured attr fields and apply policy in the app serializer/redactor.
API Reference / Дэлгэрэнгүй лавлах
For full interface details, method signatures, and type definitions, see:
Бүх interface, method, type-ийн дэлгэрэнгүй тайлбарыг доорх файлаас үзнэ үү:
Notes / Тэмдэглэл
- Dual build: ESM (
dist/index.js) + CJS (dist/index.cjs) — хоёуланд ажиллана - TypeScript types:
dist/index.d.ts - Target runtime: Node.js ≥ 22, modern browsers
- No runtime dependencies — runtime хамаарал байхгүй
License
MIT
