{"id":45278192,"url":"https://github.com/ersinkoc/log","last_synced_at":"2026-02-21T02:04:11.801Z","repository":{"id":332988606,"uuid":"1135838587","full_name":"ersinkoc/Log","owner":"ersinkoc","description":"Blazing fast, plugin-based logging for Node.js and browsers with micro-kernel architecture.","archived":false,"fork":false,"pushed_at":"2026-01-16T17:45:09.000Z","size":215,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-17T05:43:08.330Z","etag":null,"topics":["log","logging"],"latest_commit_sha":null,"homepage":"http://log.oxog.dev/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ersinkoc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-16T17:01:46.000Z","updated_at":"2026-01-16T17:45:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ersinkoc/Log","commit_stats":null,"previous_names":["ersinkoc/log"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/ersinkoc/Log","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersinkoc%2FLog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersinkoc%2FLog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersinkoc%2FLog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersinkoc%2FLog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ersinkoc","download_url":"https://codeload.github.com/ersinkoc/Log/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersinkoc%2FLog/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29671513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T00:11:43.526Z","status":"online","status_checked_at":"2026-02-21T02:00:07.432Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["log","logging"],"created_at":"2026-02-21T02:03:58.765Z","updated_at":"2026-02-21T02:04:11.788Z","avatar_url":"https://github.com/ersinkoc.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @oxog/log\n\n[![npm version](https://img.shields.io/npm/v/@oxog/log.svg)](https://www.npmjs.com/package/@oxog/log)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)\n[![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org/)\n\nBlazing fast, plugin-based logging for Node.js and browsers with micro-kernel architecture.\n\nPart of the [@oxog ecosystem](https://github.com/ersinkoc).\n\n## Features\n\n- **Six Log Levels**: trace, debug, info, warn, error, fatal\n- **Structured Logging**: Attach metadata objects to log entries\n- **Child Loggers**: Create scoped loggers with bound context\n- **Correlation ID**: Track requests across async operations\n- **Source Location**: Capture file and line number\n- **Performance Timing**: Built-in time/timeEnd utilities\n- **Redaction**: Mask sensitive fields from output\n- **Multiple Formats**: JSON, Pretty, Auto (based on environment)\n- **Multiple Transports**: Console, Stream, File, HTTP, localStorage\n- **Hybrid Sync/Async**: Level-based synchronization with buffering\n- **Browser Support**: Native DevTools integration\n- **Zero Config**: Works out of the box with sensible defaults\n- **TypeScript First**: Full type safety and IntelliSense support\n\n## Installation\n\n```bash\nnpm install @oxog/log\n```\n\n## Quick Start\n\n```typescript\nimport { createLogger } from '@oxog/log';\n\nconst log = createLogger({ name: 'my-app' });\n\n// Simple logging\nlog.info('Server started');\n\n// Structured logging with data\nlog.info({ port: 3000, env: 'production' }, 'Listening');\n\n// Child loggers with context\nconst dbLog = log.child({ module: 'database' });\ndbLog.info('Connected to database');\n```\n\n## Log Levels\n\n```typescript\nlog.trace('Detailed debugging');   // 10\nlog.debug('Debug information');    // 20\nlog.info('Informational');         // 30\nlog.warn('Warning');               // 40\nlog.error('Error occurred');       // 50\nlog.fatal('Fatal error');          // 60\n```\n\n## Examples\n\n### Child Loggers\n\n```typescript\nconst dbLog = log.child({ module: 'database' });\ndbLog.info('Connected');\n\nconst queryLog = dbLog.child({ operation: 'select' });\nqueryLog.debug('Executing query');\n```\n\n### Correlation ID\n\n```typescript\nconst reqLog = log.withCorrelation('req-abc-123');\nreqLog.info('Request received');\nreqLog.info('Processing');\nreqLog.info('Response sent');\n```\n\n### Performance Timing\n\n```typescript\nlog.time('db-query');\nawait database.query('SELECT * FROM users');\nlog.timeEnd('db-query');\n\n// Or use startTimer for more control\nconst end = log.startTimer('api-call');\nawait fetch('/api/data');\nend();\n```\n\n### Redaction\n\n```typescript\nconst log = createLogger({\n  redact: ['password', 'token', 'creditCard']\n});\n\nlog.info({ user: 'john', password: 'secret123' });\n// Output: {\"user\":\"john\",\"password\":\"[REDACTED]\"}\n```\n\n### Multiple Transports\n\n```typescript\nimport { createLogger, consoleTransport, fileTransport } from '@oxog/log';\n\nconst log = createLogger({\n  transports: [\n    consoleTransport({ colors: true }),\n    fileTransport({\n      path: './logs/app.log',\n      rotate: '1d',\n      maxFiles: 7\n    })\n  ]\n});\n```\n\n### Output Formats\n\n```typescript\n// Structured JSON (production)\nconst jsonLog = createLogger({ format: 'json' });\n\n// Human-readable (development)\nconst prettyLog = createLogger({ format: 'pretty' });\n\n// Auto-detect based on environment\nconst autoLog = createLogger({ format: 'auto' });\n```\n\n### Error Handling\n\n```typescript\ntry {\n  const data = await fetchData();\n} catch (error) {\n  log.error(error, 'Failed to fetch data');\n}\n\nlog.fatal(new Error('Cannot start'), 'Server error');\n```\n\n### Level Filtering\n\n```typescript\nconst log = createLogger({ level: 'warn' });\n\nlog.info('This will NOT appear');  // Below minimum level\nlog.warn('This WILL appear');\n\n// Dynamic level change\nlog.setLevel('debug');\nlog.info('Now this appears');\n```\n\n### Source Location\n\n```typescript\nconst log = createLogger({ source: true });\n\nlog.info('Debug me');\n// Output: {\"level\":30,\"file\":\"server.ts\",\"line\":42,\"msg\":\"Debug me\"}\n```\n\n## Plugin System\n\n```typescript\nimport { createLogger, redactPlugin, sourcePlugin } from '@oxog/log';\n\nconst log = createLogger({\n  plugins: [\n    redactPlugin(['apiKey', 'secret']),\n    sourcePlugin()\n  ]\n});\n```\n\n### Custom Plugin\n\n```typescript\nimport type { Plugin } from '@oxog/types';\n\nconst myPlugin: Plugin = {\n  name: 'myPlugin',\n  version: '1.0.0',\n  install(kernel) {\n    // Custom logic\n  }\n};\n\nlog.use(myPlugin);\n```\n\n## Browser Usage\n\n```typescript\nimport { createLogger } from '@oxog/log';\n\nconst log = createLogger();\n\nlog.info('Hello from browser!');\nlog.warn('Careful!');\nlog.error('Something went wrong');\n\n// Child loggers use console.group\nconst child = log.child({ component: 'Auth' });\nchild.info('Checking token');\n```\n\n## Transport Error Handling\n\n```typescript\n// Listen for transport failures\nlog.on('error', ({ transport, error, entry }) =\u003e {\n  console.error(`Transport ${transport} failed:`, error.message);\n  // Optionally alert ops team or use fallback\n});\n```\n\n## Sync vs Async Logging\n\n```typescript\nconst log = createLogger({\n  // fatal and error are sync by default (written before process exit)\n  sync: {\n    fatal: true,  // default\n    error: true,  // default\n    warn: false,\n    info: false,\n    debug: false,\n    trace: false,\n  }\n});\n\n// Fatal logs are written synchronously - safe before process.exit()\nprocess.on('uncaughtException', (err) =\u003e {\n  log.fatal(err, 'Uncaught exception');\n  process.exit(1); // Log is guaranteed to be written\n});\n```\n\n## Efficient Redaction\n\n```typescript\nimport { stringifyWithRedaction } from '@oxog/log';\n\n// More efficient than redactFields + JSON.stringify for large objects\nconst json = stringifyWithRedaction(\n  largeObject,\n  ['password', 'token', 'headers.authorization']\n);\n```\n\n## Graceful Shutdown\n\n```typescript\n// Flush buffered logs before shutdown\nawait log.flush();\n\n// Cleanup and destroy (also flushes buffer)\nawait log.close();\n```\n\n## API Reference\n\n### createLogger(options?)\n\nCreates a new logger instance.\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `name` | `string` | `'app'` | Logger name |\n| `level` | `LogLevelName` | `'info'` | Minimum log level |\n| `format` | `'json' \\| 'pretty' \\| 'auto'` | `'auto'` | Output format |\n| `transports` | `Transport[]` | `[consoleTransport()]` | Output destinations |\n| `redact` | `string[]` | `[]` | Fields to redact |\n| `source` | `boolean` | `false` | Include source location |\n| `timestamp` | `boolean` | `true` | Include timestamp |\n| `context` | `object` | `{}` | Static context |\n| `plugins` | `Plugin[]` | `[]` | Plugins to load |\n\n### Logger Methods\n\n#### Logging\n- `trace(msg)` / `trace(obj, msg)` - Trace level\n- `debug(msg)` / `debug(obj, msg)` - Debug level\n- `info(msg)` / `info(obj, msg)` - Info level\n- `warn(msg)` / `warn(obj, msg)` - Warn level\n- `error(msg)` / `error(obj, msg)` / `error(err, msg)` - Error level\n- `fatal(msg)` / `fatal(obj, msg)` / `fatal(err, msg)` - Fatal level\n\n#### Context\n- `child(context)` - Create child logger with additional context\n- `withCorrelation(id)` - Create logger with correlation ID\n\n#### Timing\n- `time(label)` - Start a timer\n- `timeEnd(label)` - End timer and log duration\n- `startTimer(label)` - Returns stop function\n\n#### Plugin Management\n- `use(plugin)` - Register plugin\n- `unregister(name)` - Unregister plugin\n- `hasPlugin(name)` - Check if plugin exists\n- `listPlugins()` - List all plugins\n\n#### Lifecycle\n- `flush()` - Flush buffered logs\n- `close()` - Cleanup and close transports\n\n#### Level Management\n- `setLevel(level)` - Set minimum level\n- `getLevel()` - Get current level\n- `isLevelEnabled(level)` - Check if level is enabled\n\n## Documentation\n\nFor detailed documentation, see the [docs](./docs) folder:\n\n- [Specification](./docs/SPECIFICATION.md) - Full API specification\n- [Implementation](./docs/IMPLEMENTATION.md) - Implementation details\n- [Tasks](./docs/TASKS.md) - Development tasks\n\n## Contributing\n\nContributions are welcome! Please read our contributing guidelines before submitting a PR.\n\n## License\n\nMIT - see [LICENSE](./LICENSE) for details.\n\n## Author\n\nErsin Koc - [@ersinkoc](https://github.com/ersinkoc)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fersinkoc%2Flog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fersinkoc%2Flog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fersinkoc%2Flog/lists"}