A structured TypeScript logging library built for multi-adapter workflows. Wire up Sentry, SignOz, Firebase, or your own adapter — all through a single unified interface. Adapter errors never crash your app.
- Multiple Logging Levels: Trace, Debug, Info, Warn, Error with configurable minimum levels per adapter
- Extensible Adapter System: Plug in any logging backend — Sentry, SignOz, Firebase, or your own
- Built-in Console Logging: Configurable console output with level filtering
- Predefined Events: Common analytics scenarios like Login, Share, AppOpen, Search
- Exception Handling: Automatic stack trace capture and error logging
- Metadata Support: Rich context via
extraData,response, andsignozPayload - Log Sanitization: Newlines, tabs, and non-printable characters are stripped before sending to adapters to prevent log injection
- Resilient Adapters: Adapter errors are silently absorbed — a broken integration won't crash your app
- TypeScript Support: Full type definitions and type safety
- Installation
- Quick Start
- Configuration
- Logging Levels
- Predefined Events
- Adapters
- Custom Adapter
- Development
- Contributing
- License
npm install @akadenia/loggerimport { Logger, Severity } from "@akadenia/logger"
const logger = new Logger({
consoleEnabled: true,
consoleMinimumLogLevel: Severity.Info,
})
// Basic logging
logger.info("Application started")
logger.warn("High memory usage", { extraData: { memoryMB: 512 } })
logger.error("Payment failed", { extraData: { orderId: "ORD-123" } })
// With API response context
logger.error("Failed to fetch data", {
extraData: {
userId: "1234",
response: {
status: 500,
statusText: "Internal Server Error",
message: "Server error",
data: { errorCode: "ERR_500" },
},
},
})
// Exception logging
try {
// ...
} catch (error) {
logger.exception("Failed to process request", error as Error, {
extraData: { userId: "u42" }
})
}type Config = {
consoleEnabled?: boolean // Enable/disable console logging
consoleMinimumLogLevel?: Severity // Minimum level for console output
}Severity levels in ascending order:
| Level | Value | Usage |
|---|---|---|
Severity.Trace |
1 | Fine-grained diagnostic info |
Severity.Debug |
2 | Development debugging |
Severity.Info |
3 | Operational events |
Severity.Warn |
4 | Unexpected but recoverable situations |
Severity.Error |
5 | Failures that need attention |
Each adapter has its own minimumLogLevel — messages below the threshold are silently skipped.
All log methods accept an optional Options object:
type Options = {
extraData?: any // Structured metadata attached to the log
response?: AkadeniaApiResponse // API response (trimmed before sending to adapters)
exception?: Error // Error object for exception/fatal captures
forceConsole?: boolean // Override consoleEnabled for this call
signozPayload?: any // SignOz-specific OTLP fields (trace_id, span_id, resources, attributes, etc.)
}For analytics-style events:
enum PredefinedLogEvents {
Login = "LOGIN",
Share = "SHARE",
AppOpen = "APP_OPEN",
Search = "SEARCH",
}logger.predefinedEvent({ type: PredefinedLogEvents.Login })
logger.predefinedEvent({
type: PredefinedLogEvents.Share,
extraData: { contentType: "article", itemId: "post-1", method: "link" },
})
logger.predefinedEvent({
type: PredefinedLogEvents.Search,
extraData: { searchTerm: "typescript logging" },
})
logger.predefinedEvent({ type: PredefinedLogEvents.AppOpen })Predefined events are routed to adapters that implement
predefinedEvent()(e.g. FirebaseAdapter). Other adapters ignore them gracefully.
Add one or more adapters to fan out logs to external services:
logger.addLogger(adapter)import * as Sentry from "@sentry/node"
import { SentryAdapter, Severity } from "@akadenia/logger"
Sentry.init({ dsn: "https://..." })
const sentryAdapter = new SentryAdapter(Sentry, Severity.Warn)
logger.addLogger(sentryAdapter)The Sentry adapter automatically handles Sentry's 16KB payload limit — it truncates
response.datafirst, then the full payload if needed. Sensitive keys (auth,token,password,secret, etc.) are masked before sending.
import { SignozAdapter, Severity } from "@akadenia/logger"
const signozAdapter = new SignozAdapter("https://ingest.signoz.io/logs", Severity.Info)
logger.addLogger(signozAdapter)
// With trace context
logger.info("Request processed", {
extraData: { userId: "u42" },
signozPayload: {
trace_id: "abc123",
span_id: "def456",
resources: { service: "api-server", env: "production" },
attributes: { "http.method": "GET", "http.route": "/users" },
},
})import { FirebaseAdapter, Severity } from "@akadenia/logger"
import crashlytics from "@react-native-firebase/crashlytics"
import analytics from "@react-native-firebase/analytics"
const firebaseAdapter = new FirebaseAdapter(crashlytics, analytics, Severity.Info, true)
logger.addLogger(firebaseAdapter)Implement the ILogger interface to build your own:
import { ILogger, Severity, Options } from "@akadenia/logger"
class MyAdapter implements ILogger {
name = "my-adapter"
minimumLogLevel = Severity.Info
trace(message: string, options?: Options) {}
debug(message: string, options?: Options) {}
info(message: string, options?: Options) { console.log("[INFO]", message) }
warn(message: string, options?: Options) { console.warn("[WARN]", message) }
error(message: string, options?: Options) { console.error("[ERROR]", message) }
exception(message: string, exception: Error, options?: Options) {
console.error("[EXCEPTION]", message, exception)
}
}
logger.addLogger(new MyAdapter())npm run buildnpm testnpm run formatnpm run lintWe welcome contributions! Please feel free to submit a Pull Request.
git clone https://github.com/akadenia/AkadeniaLogger.git
cd AkadeniaLogger
npm install
npm run build
npm testWe follow Conventional Commits. Scope is required.
type(scope): description
Common scopes: logger · adapters · events · docs · deps · test · build · ci
Types: feat · fix · docs · style · refactor · test · chore
- Node.js >= 22 (runtime)
- Node.js >= 20 (consumer)
For support, please open an issue on GitHub.