{"id":22753585,"url":"https://github.com/starryinternet/jobi","last_synced_at":"2025-06-17T04:39:22.603Z","repository":{"id":45443577,"uuid":"237221720","full_name":"StarryInternet/jobi","owner":"StarryInternet","description":null,"archived":false,"fork":false,"pushed_at":"2021-12-13T19:38:26.000Z","size":203,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-31T14:10:22.049Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/StarryInternet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-01-30T13:44:01.000Z","updated_at":"2021-12-13T19:38:25.000Z","dependencies_parsed_at":"2022-09-10T02:21:14.993Z","dependency_job_id":null,"html_url":"https://github.com/StarryInternet/jobi","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/StarryInternet/jobi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StarryInternet%2Fjobi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StarryInternet%2Fjobi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StarryInternet%2Fjobi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StarryInternet%2Fjobi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StarryInternet","download_url":"https://codeload.github.com/StarryInternet/jobi/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StarryInternet%2Fjobi/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260294181,"owners_count":22987600,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-12-11T06:11:46.820Z","updated_at":"2025-06-17T04:39:22.549Z","avatar_url":"https://github.com/StarryInternet.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jobi\n\nTiny logging utility with events, streams, and sane defaults.\n\n```js\nconst logger = require('@starryinternet/jobi');\nlogger.warn(`Soon we'll be jobiing our logs 🤯`);\n```\n\n## Lore\n\nJobi is a fictional tree from Thomas the Tank Engine that is _logged_. That's all folks.\n\n![Jumping Jobi Wood](./assets/JumpingJobiWood.jpg)\n\n## Features\n\n- Pretty (default), JSON, and custom formats\n- Configurable `stdout` and `stderr` streams\n- Singleton by default\n- Shared or local format and level\n- `Error` stack serialization\n\n## Levels\n\n**stdout**\n- `trace`\n- `debug`\n- `info`\n\n**stderr**\n- `warn`\n- `error`\n- `critical`\n\nEach value implicitly includes all levels above itself – so, for example, when\nyour app is run with `NODE_DEBUG=warn node app.js`, all `warn`, `error`, and\n`critical` logs will be sent to `stdout`/`stderr`. In the same example,\n`logger.info()` and `logger.debug()` would effectively be no-ops.\n\n## API\n\n#### `logger.log(level, message, [...interpolationValues])`\n- `level` (string): one of the levels defined above\n- `message` (string): an optional message. If the message is a format string, it will use the `interpolationValues` as the format parameters.\n- `[...interpolationValues]` (...any): optional values to use to format the `message` using `util.format()`. Otherwise, these values will be appended to the `message`.\n\n#### `logger.\u003clevel\u003e(message, [interpolationValues])`\n\nThe same as `logger.log`, but without the need to pass the `level` as a parameter. Prefer using these to `logger.log`.\n\n#### `logger.format` (Log =\u003e string)\n\nGet the current log format **OR** set the current log format for this `Jobi` instance. By default, a `Jobi` instance will use the shared log format. Set `logger.format = null` to resume using the shared log format.\n\n`Log`:\n- `timestamp` (string)\n- `level` (string)\n- `message` (string | undefined) *prefix is prepended to `message`*\n\n#### `logger.prefix` (string)\n\nGet the current log prefix of a Jobi instance. Prefixes can only be set in the\nconstructor.\n\n#### `Jobi.level` (string)\n\nGet the shared log level **OR** set the shared log level.\n\n#### `Jobi.format` (Log =\u003e string)\n\nGet the shared log format **OR** set the shared log format.\n\n#### `new Jobi(opts)`\n\n##### `opts`\n- `[format]` (string | (Log =\u003e string))\n- `[prefix]` (string)\n- `[stdout]` (stream.Writable)\n- `[stderr]` (stream.Writable)\n\n##### Example\n```js\nlogger.log('info', 'This is an info log');\n\n// Preferred\nlogger.info('This is another info log');\n```\n\n**NOTE**: `logger.log` has the same argument signature as `console.log`.\n\n### Configuration\n\n#### Log Level\n\n`jobi` will read the initial log level from the `NODE_DEBUG` environment variable.\n\nThe `NODE_DEBUG` environment variable can actually contain *multiple* flags,\nbut the one with the **lowest** priority level will win. For example,\n`NODE_DEBUG=debug,info,critical node app.js` will use `debug` as the log level,\nsince it automatically includes the other levels.\n\n**NOTE**: If the log level is not set, `jobi` will not write any logs.\n\n#### Log Format\n\n`jobi` will read the initial log format from the `JOBI_FORMAT` environment variable.\n\nPossible formats:\n- `pretty`\n- `json`\n\n#### Log Prefix\n\nA log prefix that will be prepended to the `message` property of a log object\nand can be set by passing the `prefix` prop to the Jobi constructor. Prefixes\nare added to all logs of Jobi instance. For different prefixes create separate\ninstances.\n\n### Events\n\nEach log level will emit an event of the same name _if the log level is high enough_. For example, `logger.critical('foo');` will emit a `'critical'` event whose\ncallback argument will be of type `Log`. This way, applications can hook in to the logging system and respond however they want (post to Slack, send to a logging service, etc.).\n\nIn addition, emit a `log` event when any log is received *if there is a listener to the event*. This event will be passed with args `level`, `formattedLog`, and `rawLog`. Code can hook into these events to forward logs or ensure that logs are being added even if it is not being written to `stdout`/`stderr`.\n\n### Streaming\n\nBy default, logs are written to either `process.stdout` or `process.stderr`.\n\nApps can optionally overwrite `logger.stdout` and `logger.stderr` with other\ninstances of `stream.Writable` in order to stream logs to the filesystem,\nvia HTTP, to a database, etc.\n\n### Node.js Compatibility\n\n`jobi` requires \u003e= Node.js 8.3.\n\n### Examples\n\n##### Logging\n\n```js\nconst logger = require('@starryinternet/jobi');\n\nlogger.critical( 'this is a %s with some %s', 'log', 'formatting' );\n```\n\n##### Event binding\n\n```js\nconst logger = require('@starryinternet/jobi');\n\nlogger.on( 'critical', msg =\u003e slack.notify( msg ) );\nlogger.on( 'error', (msg, log) =\u003e {\n  slack.notify(msg);\n  console.error(log.stack);\n});\n```\n\n##### Streaming\n\n```js\nconst logger = require('@starryinternet/jobi');\nconst fs     = require('fs');\n\nconst file = fs.createWriteStream('./log.txt');\nlogger.stdout = file;\nlogger.stderr = file;\n\nlogger.info('blah blah blah');\n```\n\n##### Custom Log Format\n\n```js\nconst { Jobi } = require('@starryinternet/jobi');\nconst format = log =\u003e '\u003e\u003e ' + log.message || 'No message';\n\nconst logger = new Jobi({ format });\nlogger.info('Hello world'); // \"\u003e\u003e Hello world\"\nlogger.info(); // \"\u003e\u003e No message\"\n```\n\n##### Custom Log Prefix\n```js\nconst { Jobi } = require('@starryinternet/jobi');\nconst prefix = 'logger: ';\n\nconst logger = new Jobi({ prefix });\nlogger.info('Hello world'); // \"[2021-11-29T15:35:59.859Z] INFO: logger: log message\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstarryinternet%2Fjobi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstarryinternet%2Fjobi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstarryinternet%2Fjobi/lists"}