{"id":21446187,"url":"https://github.com/spazmodius/logger","last_synced_at":"2026-05-20T19:11:44.139Z","repository":{"id":143019020,"uuid":"167441613","full_name":"spazmodius/logger","owner":"spazmodius","description":"Ultra-low overhead, unopinionated JSON logging core for Node.js","archived":false,"fork":false,"pushed_at":"2019-01-26T15:54:32.000Z","size":22,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-23T11:23:46.977Z","etag":null,"topics":["module","node"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spazmodius.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2019-01-24T21:36:35.000Z","updated_at":"2019-01-26T15:55:39.000Z","dependencies_parsed_at":"2023-04-22T17:30:53.599Z","dependency_job_id":null,"html_url":"https://github.com/spazmodius/logger","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spazmodius%2Flogger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spazmodius%2Flogger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spazmodius%2Flogger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spazmodius%2Flogger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spazmodius","download_url":"https://codeload.github.com/spazmodius/logger/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243955943,"owners_count":20374410,"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":["module","node"],"created_at":"2024-11-23T02:42:17.199Z","updated_at":"2026-05-20T19:11:39.116Z","avatar_url":"https://github.com/spazmodius.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spaz's Barebones JSON Logger\r\n\r\n***Ultra-low-overhead, unopinionated JSON logging for Node.js***\r\n\r\nThis library provides base functionality for generating JSON logs and writing them to a stream.\r\nIt has very few opinions about what goes into the logs, and can easily be the core of a full-featured logging framework.\r\n\r\n## Install and Usage\r\n`npm install spazmodius/logger`\r\n\r\n```js\r\nconst Logger = require('@spazmodius/logger')\r\nconst log = Logger(process.stdout)\r\nlog({ msg: 'hello world' })\r\nlog({ count: 99 })\r\n```\r\n\r\nwhich outputs newline-delimited JSON:\r\n\r\n```json\r\n{\"msg\":\"hello world\",\"time\":1548369941980}\r\n{\"count\":99,\"time\":1548369941980}\r\n```\r\n\r\n## Concepts\r\n\r\nConcept | Definition\r\n---|---\r\nOutput Stream | A [Writable](https://nodejs.org/api/stream.html#stream_writable_streams) stream, which is the destination for JSON logging.\r\nLogger | A function that logs a line of JSON to it's **output stream**.  Each logger is bound to both a **meta** and a **stringify function**.\r\nChild | A **logger** that derives from another. The child shares its parent's **output stream**, and either extends its **meta** or has a different **stringify function** (and thus a different **signature**), or both.\r\nMeta | A set of fixed fields that will be output with every line of JSON.  Each **logger** is bound to a meta, which is generally a superset of its parent's meta.\r\nStringify Function | A function, usually of your devising, that takes its arguments and returns a string of JSON fields suitable for inclusion in a line of JSON.  Each **logger** is bound to a stringify function, which thereby defines its **signature**.\r\nSignature | The number and types of arguments that a **logger** expects to be sent when it is called.  This will be exactly the same as expected by its **stringify function**.\r\n\r\nThe idea is to generate a \"family\" of loggers, functions that write to the same [Writable](https://nodejs.org/api/stream.html#stream_writable_streams) stream.\r\nThe parent-most logger is very basic, but each child can extend the meta fields, and use a different stringify function to define a bespoke signature that accepts certain values and outputs particular JSON fields.\r\n\r\n## Factory/Constructor\r\n\r\n### [new] Logger( _output_ )\r\n\r\n| Argument | Type | Optional | Description\r\n|---|---|---|---\r\n| `output` | Writable stream | | Stream to which to send lines of JSON\r\n\r\n**Returns** a base logger `log([fields])`\r\n\r\n This factory/constructor method creates a base logger, which writes to the `output` stream.\r\n This is the root of a \"family\" of loggers that all will write to the same output stream.\r\n\r\n This base logger has empty meta (`{}`).\r\n Its signature is an optional object `fields`, whose JSON-serializable properties will be included as fields in the line of JSON.  (Its stringify function is, in fact, [`Logger.stringify.fields`](#loggerstringifyfields-fields-).)\r\n\r\nExample:\r\n```js\r\nconst log = Logger(process.stdout)\r\nlog({ msg: 'hello world' })\r\n```\r\n\r\n## Logger Instance\r\n\r\n### log( _...args_ )\r\n\r\nLogs a line of JSON to the output stream.\r\nThe line of JSON will include:\r\n - fixed meta fields,\r\n - fields from the stringify function and the given `args`\r\n - a `\"time\"` field containing the number of milliseconds since  the UNIX epoch (as returned from `Date.now()`)\r\n\r\nThe signature of this logger depends on its stringify function, specified when it was created (see [`log.child()`](#logchild-meta-stringify-)).\r\nThe same arguments passed to `log()` will be passed along to the stringify function.\r\n\r\n### log.meta\r\n\r\nAn object whose properties represent the fixed fields that are included in the JSON logged by this logger.\r\nThis is purely informational; attempting to modify `log.meta` will not affect the logger.\r\n\r\n### log.signature\r\n\r\nA string representing the arguments accepted by this logger.\r\nThis signature is derived from the this logger's stringify function.\r\nIt is purely informational.\r\n\r\n### log.child( _[meta], [stringify]_ )\r\n\r\n| Argument | Type | Optional | Description\r\n|---|---|---|---\r\n| `meta` | object | \u0026check; | Object whose properties become fixed fields for the child logger. These will extend the `meta` inherited from `log`.\r\n| `stringify` | function | \u0026check; | Function that converts its arguments into JSON fields.\r\n\r\n**Returns** a new logger [`log(...args)`](#log-args-)\r\n\r\nCreates a new logger derived from an existing one.\r\n\r\nThe child logger inherits the parent's meta, extended by the `meta` argument.\r\nNew meta fields can be added, \r\nexisting fields overridden, \r\nor removed by assigning `undefined`.\r\n\r\nThe `stringify` function _must_ return a string: either the empty string, or a comma-delimited list of _JSON fields_.  \r\nA JSON field is a properly quoted and escaped _field name_, followed by a _colon_, followed by a _JSON value_.\r\nThis will be a string that can be enclosed in curly braces to result in a valid JSON object.\r\n\r\n`stringify` will be invoked with the same `args` arguments as the child logger is called with.  \r\n\r\nFor example:\r\n```js\r\n// base logger\r\nconst base = Logger(process.stdout)\r\n\r\n// a logger that includes pid and hostname on every line\r\nconst log = base.child({ pid: process.pid, hostname: os.hostname() })\r\n\r\n// a logger that logs Error objects\r\nconst logError = log.child(\r\n\t{ sev: 'ERROR'}, \r\n\terror =\u003e Logger.stringify.fields.fast({\r\n\t\tmsg: error.message,\r\n\t\terr: { stack: error.stack, ...error }\r\n\t})\r\n)\r\n```\r\n\r\n### log.flush( _[cb]_ )\r\n\r\n| Argument | Type | Optional | Description\r\n|---|---|---|---\r\n| `cb` | function | \u0026check; | Callback function that will be invoked when all current log lines have been flushed to the output stream.\r\n\r\nImmediately (synchronously) writes all queued log lines to the output stream.\r\nOnce the underlying system has accepted all the writes, the callback `cb` will be invoked.\r\nThe `flush()` method is shared by all loggers in the same family.\r\n\r\nThis is useful during process shutdown, to ensure all logs get written.  For example:\r\n```js\r\nprocess.on('uncaughtException', err =\u003e {\r\n\tlogError(err).flush(() =\u003e process.exit(1))\r\n})\r\n```\r\n\r\n## Stringify Utility Functions\r\n\r\nTo assist with constructing fast and effecient stringify functions, there is a small library of utility functions.\r\n\r\n### Logger.stringify.none()\r\n\r\nReturns the empty string, the stringification of no fields.\r\n\r\n### Logger.stringify.fields( _[fields]_ )\r\n\r\n| Argument | Type | Optional | Description\r\n|---|---|---|---\r\n| `fields` | object | \u0026check; | Object whose properties are serialized to JSON fields.\r\n\r\nStringifies many fields at once, as represented by the serializable properties of the `fields` object.\r\n\r\nIf `fields` is a value that cannot be serialized to JSON,\r\nor serializes to a non-object JSON value,\r\nor has no serializable properties,\r\nthen empty string is returned.\r\n\r\n### Logger.stringify.fields.fast( _fields_ )\r\n\r\n| Argument | Type | Optional | Description\r\n|---|---|---|---\r\n| `fields` | object | | Object whose JSON-serializable properties become JSON fields. _Must be a value that serializes to a JSON object._\r\n\r\nA fast, but restrictive, version of [`Logger.stringify.fields`](#loggerstringifyfields-fields-).\r\n\r\n### Logger.stringify.field( _name, value_ )\r\n\r\n| Argument | Type | Optional | Description\r\n|---|---|---|---\r\n| `name` | string | | Name of the field to serialize. Will be coerced into a string.\r\n| `value` | any | | Vaue of the field to serialize.\r\n\r\nStringifies a single field.\r\nIf `value` is not JSON-serializable, then returns empty string.\r\n\r\n### Logger.stringify.field.fast( _name, value_ )\r\n\r\n| Argument | Type | Optional | Description\r\n|---|---|---|---\r\n| `name` | string | | Name of the field to serialize.  _Must be a string that does not require JSON escaping._\r\n| `value` | any | | Vaue of the field to serialize. _Must be a JSON-serializable value._\r\n\r\nA fast, but restrictive, version of [`Logger.stringify.field`](#loggerstringifyfield-name-value-).\r\n\r\n### Logger.stringify.quote( _str_ )\r\n\r\n| Argument | Type | Optional | Description\r\n|---|---|---|---\r\n| `str` | string | | Value to serialize to a JSON string (quoted) value. Will be coerced into a string.\r\n\r\nSerializes a value to a JSON quoted string, escaping characters as necessary.\r\n\r\n### Logger.stringify.quote.fast( _str_ )\r\n\r\n| Argument | Type | Optional | Description\r\n|---|---|---|---\r\n| `str` | string | | String to enclose in quotes. _Must be a string that does not require JSON escaping._\r\n\r\nA fast, but restrictive, version of [`Logger.stringify.quote`](#loggerstringifyquote-str-).\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspazmodius%2Flogger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspazmodius%2Flogger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspazmodius%2Flogger/lists"}