{"id":13583284,"url":"https://github.com/xpl/ololog","last_synced_at":"2025-04-05T11:11:23.582Z","repository":{"id":53346828,"uuid":"89606711","full_name":"xpl/ololog","owner":"xpl","description":"A better console.log for the log-driven debugging junkies","archived":false,"fork":false,"pushed_at":"2021-03-29T18:16:33.000Z","size":5501,"stargazers_count":214,"open_issues_count":14,"forks_count":8,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-29T10:06:39.484Z","etag":null,"topics":["ansi","ansi-colors","chrome-devtools","console-log","debug","debugging-tool","debugging-tools","log","logging","pretty-print","printer","stack-traces","stacktrace","terminal-colors","tty"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/ololog","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xpl.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}},"created_at":"2017-04-27T14:29:53.000Z","updated_at":"2025-03-22T20:04:15.000Z","dependencies_parsed_at":"2022-09-05T01:00:34.270Z","dependency_job_id":null,"html_url":"https://github.com/xpl/ololog","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/xpl%2Fololog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xpl%2Fololog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xpl%2Fololog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xpl%2Fololog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xpl","download_url":"https://codeload.github.com/xpl/ololog/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247325693,"owners_count":20920714,"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":["ansi","ansi-colors","chrome-devtools","console-log","debug","debugging-tool","debugging-tools","log","logging","pretty-print","printer","stack-traces","stacktrace","terminal-colors","tty"],"created_at":"2024-08-01T15:03:22.714Z","updated_at":"2025-04-05T11:11:23.558Z","avatar_url":"https://github.com/xpl.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Ololog!\n\n[![Build Status](https://travis-ci.org/xpl/ololog.svg?branch=master)](https://travis-ci.org/xpl/ololog) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/toprqa1obtcawp1m?svg=true)](https://ci.appveyor.com/project/xpl/ololog)\n [![NPM](https://img.shields.io/npm/v/ololog.svg)](http://npmjs.com/package/ololog)\n\n- [x] A better `console.log` for the log-driven debugging junkies\n- [x] [Colors / styles](https://github.com/xpl/ololog#ansi-styling) for terminals and Chrome DevTools (try [online demo](https://xpl.github.io/ololog/))\n- [x] [Displays call locations](https://github.com/xpl/ololog#displaying-call-location)\n- [x] [Returns its argument](https://github.com/xpl/ololog#debugging-of-functional-expressions) (for easy debugging of functional expressions)\n- [x] [Smart indentation / newline handling](https://github.com/xpl/ololog/#smart-indentation--newline-handling)\n- [x] [Powerful object printer](https://github.com/xpl/ololog#smart-object-printing)\n- [x] Formats `Error` instances as [pretty stacktraces with source lines](https://github.com/xpl/ololog#pretty-printing-error-instances)\n- [x] Full sourcemap support (via [`get-source`](https://github.com/xpl/get-source))\n- [x] [Pluggable pipeline architecture](https://github.com/xpl/pipez#pipezbeta)\n- [x] [Can replace the default unhandled error printer in Node](https://github.com/xpl/ololog#using-as-the-default-exception-printer-in-node)\n- [x] [Integrates with Mocha](https://github.com/xpl/ololog#using-with-mocha) (experimental)\n\n\n# Examples _(NEW!)_\n\nThese examples demonstrate some non-trivial complex behaviors that could be achieved with Ololog by [plugging](#overriding-the-default-behaivor) into it's rendering pipeline. For simpler examples read further docs!\n\n1. [Logging to a file and on screen at the same time (with different log levels)](https://github.com/xpl/ololog/blob/master/examples/logging-to-file.js)\n2. [Collapsing repeated messages (with an incrementing counter)](https://github.com/xpl/ololog/blob/master/examples/collapsing-repeated-messages.js)\n\n     \u003cimg width=\"422\" alt=\"screen shot 2018-05-11 at 19 32 48\" src=\"https://user-images.githubusercontent.com/1707/39935701-8cc52cfe-5552-11e8-934b-43f1f8da0518.png\"\u003e\n\n3. [Displaying log levels and custom tags](https://github.com/xpl/ololog/blob/master/examples/custom-tags.js)\n\n     \u003cimg width=\"458\" alt=\"screen shot 2019-01-22 at 22 46 59\" src=\"https://user-images.githubusercontent.com/1707/51561304-ec029d00-1e97-11e9-9fcc-6d6edd0401fb.png\"\u003e\n\n\n# TODO\n\n- [ ] HTML/DOM rendering\n- [ ] Improve [tests](https://github.com/xpl/ololog/blob/master/test.js) coverage\n\n# Importing\n\nFor use with Node or with module bundlers (Browserify / WebPack / Rollup):\n\n```bash\nnpm install ololog\n```\n```javascript\nconst log = require ('ololog')\n```\n\n# Using With [Mocha](https://mochajs.org/)\n\n\u003cimg src=\"https://user-images.githubusercontent.com/1707/30816536-e504a9d6-a21e-11e7-976c-778a95d32219.png\"\u003e\n\n```bash\nmocha --reporter ololog/reporter\n```\n\n- [x] Aligns log messages nicely\n- [x] Supresses log output for nonfailed tests (disable with `.only` or `this.verbose=true` for a suite/test)\n- [x] Automatically manages empty lines / whitespace for better legibility\n- [x] Prints unhandled exceptions and promise rejections as nice stacktraces\n- [x] [Animated execution progress](https://user-images.githubusercontent.com/1707/30836580-c80ab106-a267-11e7-87d1-04513d36995b.gif)\n\n**NOTE:** It is highly experimental yet, and things may not work as expected...\n\n# Browser Bundle\n\n...for those who still uses `\u003cscript\u003e` tag for module importing ;) Exposes the global `ololog` and [`ansicolor`](https://github.com/xpl/ansicolor) objects. Installs [String extensions for ANSI styles](https://github.com/xpl/ansicolor#nice-mode-by-request). Not compressed.\n\n```html\n\u003cscript src=\"https://unpkg.com/ololog\"\u003e\u003c/script\u003e \u003c!-- from unpkg.com CDN --\u003e\n\u003cscript\u003e\n    log = ololog\n    log ('something'.red)\n\u003c/script\u003e\n```\n\n# Basic Usage\n\nAt first, it's similar to `console.log`:\n\n```javascript\nlog ('foo', 'bar', 'baz') // foo bar baz\n```\n\n# Configuration\n\nIt exposes a method called `.configure`, which produces a new `log` instance with the new settings applied (not mutating the original one), which can be saved and re-used subsequently:\n\n```javascript\nconst log = require ('ololog').configure ({ concat: { separator: '' }})\n```\n```javascript\nlog ('foo', 'bar', 'baz') // foobarbaz\n```\n\n...or you can apply the configuration method _ad-hoc_:\n\n```javascript\nlog.configure ({ concat: { separator: '' }}) ('foo', 'bar', 'baz') // foobarbaz\n```\n\nAnd you can chain the configuration calls, applying them subsequently:\n\n```javascript\nlog1 = log.configure ({ locate: false }) // removes the code location tag\nlog1 ('foo')\n\nlog2 = log1.configure ({ time: true }) // preserves previous settings + enables timestamps\nlog2 ('bar')\n```\n\nThe variety of possible options will be covered just below — there is a plenty of them!\n\nConfiguration engine is implemented as a separate external library, for everyone's use — you can [read more about it here](https://github.com/xpl/pipez#pipez). Contributions are welcome.\n\n# Debugging Of Functional Expressions\n\nOlolog returns its first argument (a feature that `console.log` doesn't have), and it greatly simplifies debugging of functional expressions, as you can simply wrap part of an expression to `log`:\n\n```javascript\narray.map (x =\u003e log (x) + 1)\n```\n\nIt is far less ugly than with `console.log`:\n\n```javascript\narray.map (x =\u003e { console.log (x); return x + 1 })\n```\n\nAlso, if you don't like that behavior, you can override it. For example, returning the _last argument_ instead of first:\n\n```javascript\nlog = log.configure ({\n\n    returnValue: (text, { initialArguments }) =\u003e initialArguments[initialArguments.length - 1]\n})\n```\n\n# ANSI Styling\n\nBacked by the [ansicolor](https://github.com/xpl/ansicolor) library, colored output is supported for the terminal environment and for the Chrome DevTools console. On other platforms, ANSI codes are safely stripped from the output, so they don't mess up anything.\n\nApply styling by calling the [`ansicolor`](https://github.com/xpl/ansicolor) methods on arbitrary strings:\n\n```javascript\nrequire ('ansicolor').nice // importing in .nice mode extends the String prototype, but there's a safe functional mode as well (see the docs...)\n\nlog (('foo'.dim.red + 'bar'.bgLightCyan).underline)\n```\n\n...or by using the built-in shorthand methods (no need to import `ansicolor`, but we lose the ability to colorize just a part of a string):\n\n```javascript\nlog.red ('red text')\nlog.bright.red.underline ('multiple styles combined')\n```\n\n[See all the supported styling options here](https://github.com/xpl/ansicolor#supported-styles).\n\n# Smart Indentation / Newline Handling\n\nTo add indentation to a multiline text or complex objects, you can simply provide the indentation symbols as a first argument:\n\n```javascript\nlog ('    ', 'foo\\nbar\\nbar')\n```\n```\n    foo\n    bar\n    bar\n```\n\nThe remarkable thing is that you can provide *any text* that would be used to offset what's coming after it. This is especially useful with printing long objects that span across many lines:\n\n```javascript\nlog ('This is my object:', { foo: 10, bar: 20, qux: 30 })\n```\n```\nThis is my object: { foo: 10,\n                     bar: 20,\n                     qux: 30  }\n```\n\nCompare it to the crappy `console.log` output, which doesn't care about readability:\n\n```\nThis is my object: { foo: 10,\n bar: 20,\n qux: 30  }\n```\n\nOlolog also handles the ANSI escape codes correctly while computing the proper the indentation width:\n\n```javascript\nconst { bright } = require ('ansicolor')\n\nlog.magenta (bright.green ('This is my object:'), { foo: 10, bar: 20, qux: 30 })\n```\n\n\u003cimg width=\"261\" alt=\"Screen Shot 2019-06-27 at 13 39 08\" src=\"https://user-images.githubusercontent.com/1707/60259909-fe6a8200-98e0-11e9-8aff-7563afd77230.png\"\u003e\n\n## Using The `indent` Option\n\nThe other way is to use the `indent` config option:\n\n```javascript\nlog.configure ({ indent: { level: 3 } }) ('foo\\nbar\\nbaz\\n')\n```\n\nShorthand method:\n\n```javascript\nlog.indent (2) ('foo\\n', 'bar\\n', 'baz')\n```\n\nYou can also set the indentation pattern should be used:\n\n```javascript\nlog = log.configure ({ indent: { pattern: '\\t' } })\n```\n\n# Smart Object Printing\n\nAll magic is provided by the external [String.ify](https://github.com/xpl/string.ify) library. Read the docs to see all the available configuration options. There are plenty of them! Contributions are welcome.\n\n![GIF Animation](https://user-images.githubusercontent.com/1707/39936518-6163e2dc-5555-11e8-9c40-3abe57371ab4.gif)\n\nDefault output:\n\n```javascript\nlog (obj) // prints example object\n```\n```\n{ asks: [ { price: \"1000\", amt: 10 },\n          { price: \"2000\", amt: 10 }  ],\n  bids: [ { price: \"500\", amt: 10 },\n          { price: \"100\", amt: 10 }  ]   }\n```\n\nLonger strings:\n\n```javascript\nlog.maxLength (70) (obj)\n```\n```\n{ asks: [{ price: \"1000\", amt: 10 }, { price: \"2000\", amt: 10 }],\n  bids: [{ price: \"500\", amt: 10 }, { price: \"100\", amt: 10 }]    }\n```\n\nShorter strings:\n\n```javascript\nlog.maxLength (20) (obj)\n```\n```\n{ asks: [ {  price: \"1000\",\n               amt:  10     },\n          {  price: \"2000\",\n               amt:  10     }  ],\n  bids: [ {  price: \"500\",\n               amt:  10    },\n          {  price: \"100\",\n               amt:  10    }  ]   }\n```\n\nDisabling right keys alignment:\n\n```javascript\nlog.noRightAlignKeys (anotherObj)\n```\n```\n{ obj: [ { someLongPropertyName: 1,\n           propertyName: 2,\n           anotherProp: 4,\n           moreProps: 5             },\n         { propertyName: { someVeryLongPropertyName: true,\n                           qux: 6,\n                           zap: \"lol\"                      } } ] }\n```\n\nDisabling fancy nesting:\n\n```javascript\nlog.noFancy (anotherObj)\n```\n```\n{\n    obj: [\n        {\n            someLongPropertyName: 1,\n            propertyName: 2,\n            anotherProp: 4,\n            moreProps: 5\n        },\n        {\n            propertyName: {\n                someVeryLongPropertyName: true,\n                qux: 6,\n                zap: \"lol\"\n            }\n        }\n    ]\n}\n```\n\nNo fancy nesting + setting indentation width to 2 spaces:\n\n```javascript\nlog.configure ({ stringify: { fancy: false, indentation: '  ' } }) (yetAnotherObj)\n```\n```\n{\n  obj: [\n    {\n      propertyName: 2,\n      moreProps: 5\n    }\n  ]\n}\n```\n\nSingle line mode:\n\n```javascript\nlog.noPretty (obj)\n```\n```\n{ asks: [{ price: \"1000\", amount: 10 }, { price: \"2000\", amount: 10 }], bids: [{ price: \"500\", amount: 10 }, { price: \"100\", amount: 10 }] }\n```\n\nChanging max print depth / max array length:\n\n```javascript\nlog.maxDepth (1).maxArrayLength (100) (obj) // or log.configure ({ stringify: { maxDepth: 1, maxArrayLength: 100 } })\n```\n```javascript\nlog.unlimited (obj) // disables limiting\n```\n\nSetting floating-point output precision:\n\n```javascript\nlog.precision (2) ({ foo: 123.456789 })\n```\n```javascript\n{ foo: 123.45 }\n```\n\nPassing other configuration options to [`string.ify`](https://github.com/xpl/string.ify) (read the its docs for more info):\n\n```javascript\nlog.configure ({\n\n    stringify: {\n        pure:            false,\n        json:            false,\n        maxDepth:        5,\n        maxLength:       50,\n        maxArrayLength:  60,\n        maxObjectLength: 200,\n        maxStringLength: 60,\n        precision:       undefined,\n        formatter:       undefined,\n        pretty:         'auto',\n        rightAlignKeys:  true,\n        fancy:           true,\n        indentation:    '    '\n    }\n    \n}) (obj)\n```\n\n### Avoid Too Long Call Chains\n\nPlease not that in case of multiple configuration options it is preferable to do that:\n\n```javascript\nlog.configure ({ stringify: { precision: 2, maxLength: 20, noFancy: true, maxDepth: 8 }})\n```\n\n...instead of:\n\n```javascript\nlog.precision (2).maxLength (20).noFancy.maxDepth (8)\n```\n\n...because the latter generates too deep callstack which could disrupt the displaying of the [call location tag](https://github.com/xpl/ololog#displaying-call-location) along with the message! The problem is yet to be solved in future [`pipez`](https://github.com/xpl/pipez) versions.\n\n# Using With Custom Stringifier\n\nReplacing the default printer with [q-i](https://github.com/sapegin/q-i) (as an example):\n\n```javascript\nconst log = require ('ololog').configure ({ stringify: { print: require ('q-i').stringify } })\n```\n```javascript\nlog ({ foo: true, bar: 42 })\n```\n\n![pic](https://user-images.githubusercontent.com/1707/30799941-222a66a8-a1e7-11e7-89b5-4bed706c7840.png)\n\nYou can also override the arguments stringification stage completely (see more on [overriding default behavior](https://github.com/xpl/ololog#overriding-the-default-behavior)):\n\n```javascript\nlog = require ('ololog').configure ({ stringify (args, cfg) { return args.map (x =\u003e myCustomStringifier (x, cfg)) } })\n\n// ...providing additional configuration somewhere later...\nlog = log.configure ({ stringify: { /* this object will be passed down as `cfg` to myCustomStringifier */ }})\n```\n\n# Pretty Printing `Error` Instances\n\nThis feature is implemented in the [StackTracey](https://github.com/xpl/stacktracey#pretty-printing) library. See it's docs for more (you can configure the path shortening / library calls skipping).\n\n```javascript\nlog.bright.red (e) // where `e` is an instance of Error\n```\n\nor (if you want the output go to _stderr_ and supress the grey location badge):\n\n```javascript\nlog.bright.red.error.noLocate (e)\n```\n\n\u003cimg width=\"1091\" alt=\"Screen Shot 2019-04-06 at 00 56 17\" src=\"https://user-images.githubusercontent.com/1707/55658599-d8b06e00-5806-11e9-935c-32a11d689c92.png\"\u003e\n\n# Using As The Default Exception Printer In Node\n\n```javascript\nprocess.on ('uncaughtException',  e =\u003e { log.bright.red.error.noLocate (e); process.exit (1) })\nprocess.on ('unhandledRejection', e =\u003e { log.bright.red.error.noLocate (e); process.exit (1) })\n```\n\nOr you can simply call the `handleNodeErrors` helper when importing Ololog:\n\n```javascript\nconst log = require ('ololog').handleNodeErrors ()\n```\n\n### See Also: [`panic-overlay`](https://github.com/xpl/panic-overlay/#panic-overlay-)\n\nYou can improve the error reporting not only in Node projects, but also in browsers. See the [`panic-overlay`](https://github.com/xpl/panic-overlay/#panic-overlay-) library which shares the same codebase with Ololog:\n\n\u003cimg width=\"400\" src=\"https://user-images.githubusercontent.com/1707/54091547-44332700-4392-11e9-81a8-8593c48980b1.png\"\u003e\n\n# Displaying Call Location\n\nHave you ever encountered a situation where you need to quickly find in the code the place where the logging is called, but it's not so easy to do? With call location tags it's really easy. And it's enabled by default.\n\n![log message](https://cdn.jpg.wtf/futurico/d6/dd/1493351933-d6dd0c2e633fbb2f886c25c0d8e6f6ad.png)\n\n![call](https://cdn.jpg.wtf/futurico/d6/0c/1493352126-d60cebe41bab9c3d111364ecfc9d2c65.png)\n\nDisabling:\n\n```javascript\nlog.configure ({ locate: false }) (...)\n```\n\n...or:\n\n```javascript\nlog.noLocate (...)\n````\n\nCustom printer:\n\n```javascript\nlog.configure ({ locate: { print: ({ calleeShort, fileName, line }) =\u003e ... } }) (...)\n```\n\nDisplaying outer call location (upwards the stack), can be useful when implementing library code / wrappers:\n\n```javascript\nlog.configure ({ locate: { shift: 1 }}) (...)\n```\n\nManually setting call location (see the [StackTracey](https://github.com/xpl/stacktracey) library, which serves the purpose):\n\n```javascript\nlog.configure ({ locate: { where: new StackTracey ().at (2) } }) (...)\n```\n\n# Timestamping\n\nDisabled by default. To enable (with default options):\n\n```javascript\nlog = log.configure ({ time: true })\n```\n\n\u003cimg width=\"965\" src=\"https://user-images.githubusercontent.com/1707/39397314-f5df5ffe-4b05-11e8-8b7c-fda493d40749.png\"\u003e\n\nConfigure formatting:\n\n```javascript\nlog = log.configure ({ time: { yes: true, format: 'iso' } })\n```\n\nHere is the correspondence between the `format` option value and the related `Date` method used for rendering:\n\n| `format` value       | `Date` method\n| -------------------- | --------------------- |\n| `\"locale\"` (default) | `.toLocaleString ()`  |\n| `\"iso\"`              | `.toISOString ()`     |\n| `\"utc\"`              | `.toUTCString ()`     |\n| `null`               | `.toString ()`        |\n\nProviding [locale and timezone options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString) (available when `format` is set to `locale`):\n\n```javascript\nlog.configure ({\n    time: {\n        yes: true,\n        format: 'locale',\n        locale: 'en-US',\n        options: { timeZone: 'America/Denver' }\n    }\n})\n```\n\nProviding a custom printer:\n\n```javascript\nlog.configure ({ time: { yes: true, print: x =\u003e (String (x) + ' | ').bright.cyan }}) ('Lorem ipsum dolor sit amet\\nconsectetur adipiscing elit..')\n```\n\n![pic](https://cdn.jpg.wtf/futurico/93/45/1493357501-9345b20f7edd289e0336bc322f1e68c3.png)\n\nBackdating:\n\n```javascript\nlog.configure ({ time: { yes: true, when: new Date ('2017-02-27T12:45:19.951Z') }}) (...)\n```\n\n# Specifying Additional Semantics (errors / warnings / info messages)\n\nYou can add the `.error` call modifier, which tells Ololog to render with the `console.error` instead of the `console.log`: \n\n```javascript\nlog.error ('this goes to stderr')\n```\n```javascript\nlog.bright.red.error ('bright red error!')\n```\n\nOther `console` methods are supported as well:\n\n```javascript\nlog.info ('calls console.info')\n```\n```javascript\nlog.warn ('calls console.warn')\n```\n```javascript\nlog.debug ('calls console.debug')\n```\n\n\n# Displaying The `INFO` / `WARN` / `ERROR` / `DEBUG` Tags\n\nThere is a `tag` stage (disabled by default) that displays the log level:\n\n```javascript\nconst log = require ('ololog').configure ({ tag: true })\n\nlog       ('a regular message')\nlog.info  ('an info message')\nlog.warn  ('a warning')\nlog.error ('an error')\nlog.debug ('a debug message')\n```\n\n\u003cimg width=\"203\" alt=\"screen shot 2019-01-22 at 22 22 44\" src=\"https://user-images.githubusercontent.com/1707/51559915-426ddc80-1e94-11e9-967e-4780437d6818.png\"\u003e\n\n# Customized Tag Printer\n\nYou can completely override the `tag` stage, introducing new parameters and behavior (a `clusterId` in this example):\n\n```javascript\nconst bullet = require ('string.bullet') // NB: these packages are part of Ololog, no need to install them separately\nconst { cyan, yellow, red, dim } = require ('ansicolor')\n\nconst log = require ('ololog').configure ({\n\n    locate: false,\n    time: true,\n    tag: (lines, {\n            level = '',\n            levelColor = { 'info': cyan, 'warn': yellow, 'error': red.bright.inverse, 'debug': blue},\n            clusterId\n          }) =\u003e {\n        \n        const clusterStr = clusterId ? ('CLUSTER[' + (clusterId + '').padStart (2, '0') + ']') : ''\n        const levelStr = level \u0026\u0026 (levelColor[level] || (s =\u003e s)) (level.toUpperCase ())\n\n        return bullet (dim (clusterStr.padStart (10)) + '\\t' + levelStr.padStart (6) + '\\t', lines)\n    }\n})\n```\n\n```javascript\nlog.configure ({ tag: { clusterId: 1  } })       ('foo')\nlog.configure ({ tag: { clusterId: 3  } }).info  ('bar')\nlog.configure ({ tag: { clusterId: 27 } }).error ('a multiline\\nerror\\nmessage')\n```\n\nThe output:\n\n\u003cimg width=\"458\" alt=\"screen shot 2019-01-22 at 22 46 59\" src=\"https://user-images.githubusercontent.com/1707/51561304-ec029d00-1e97-11e9-9fcc-6d6edd0401fb.png\"\u003e\n\nYou can also use [*Custom Methods*](https://github.com/xpl/ololog#adding-custom-helper-methods) feature to make it even more concise:\n\n```javascript\nlog = log.methods ({\n\n    // adds `clusterId` helper\n    clusterId (n) { return this.configure ({ tag: { clusterId: n } }) }\n})\n\nlog.clusterId (1)        ('foo')\nlog.clusterId (3) .info  ('bar')\nlog.clusterId (27).error ('a multiline\\nerror\\nmessage')\n```\n\n# Limiting Max Argument Length\n\n```javascript\nlog.configure ({ trim: { max: 5 } }) ('1234567890', 'abcdefgh') // 1234… abcd…\n```\n\n# Getting The Rendered Text\n\nThe following will execute all stages before the 'render' (screen output) stage, returning its argument:\n\n```javascript\nlog.before ('render') ({ foo: 42 }) // '{ foo: 42 }'\n```\n\nThe other way of getting the text (for example, if you want to intercept it and output to your custom renderer, like Blessed) is to override the default `render` step, see below...\n\n# Overriding The Default Behavior\n\nYou can provide a custom implementation for certain steps in the Ololog's pipeline. For example, you can replace the `render` step to output the rendered text to somewhere else other than `console.log`:\n\n```javascript\nlog = log.configure ({\n\n    render (text, { consoleMethod = '' /* can be also debug/info/error/warn */ }) {\n\n        // receives '{ foo: 42 }' and outputs it to the Blessed library\n        box.pushLine (text)\n        box.scroll (1)\n        screen.render ()\n    }\n})\n\nlog ({ foo: 42 })\n```\n\nYou can look up all the default steps you could replace here:\n\nhttps://github.com/xpl/ololog/blob/master/ololog.js#L67\n\n# Injecting Custom Code Before/After Steps\n\nYou can also bind new code to the existing methods in an _aspect-oriented programming_ style, executing it _before_, _after_ or _instead_ – and thus overriding the default behavior. See the [pipez](https://github.com/xpl/pipez#pipez) library, which provides all the fun — with its help you could build incredibly configurable things similar to Ololog easily.\n\nFor example, if you want to write `.error` calls not just on screen, but to a separate file, you can do following (by injecting a custom hook after the `render` call):\n\n```javascript\nconst ololog = require ('ololog')\n    , ansi   = require ('ansicolor')\n    , fs     = require ('fs')\n    \nconst log = require ('ololog').configure ({\n\n    'render+' (text, { consoleMethod = '' }) { // adds this method after `render`\n        if (consoleMethod === 'error') {\n            fs.appendToFile ('error.log', '\\n' + ansi.strip (text)) // strip ANSI styling codes from output\n        }\n        return text\n    }\n})\n```\n\nHere's a complete example on how to set up a file logging that supports different log levels:\n\n- [`examples/logging-to-file.js`](https://github.com/xpl/ololog/blob/master/examples/logging-to-file.js)\n\nHere's another trick that you could do by injecting a handler _before_ the `render` step (that would be `+render` instead of `render+`):\n\n- [Collapsing repeated messages (with an incrementing counter)](https://github.com/xpl/ololog/blob/master/examples/collapsing-repeated-messages.js)\n\n     \u003cimg width=\"422\" alt=\"screen shot 2018-05-11 at 19 32 48\" src=\"https://user-images.githubusercontent.com/1707/39935701-8cc52cfe-5552-11e8-934b-43f1f8da0518.png\"\u003e\n\n# Adding Custom Helper Methods\n\nYou can add your own shorthand methods/properties (will add new properties globally for any instance of the `ololog`, but this may change in future). An example, demonstrating how the actual `indent` and `red` chain-style helpers were implemented:\n\n```javascript\nlog.methods ({\n\n    indent (level) { return this.configure ({ indent: { level: level }}) }\n    get red ()     { return this.configure ({ 'concat+': lines =\u003e lines.map (ansicolor.red) }) } // executes it after the 'concat'\n})\n```\n\n# No-op Device\n\nUse `.noop` to obtain a reduced instance that does nothing apart from returning its first argument:\n\n```javascript\nconst doesNothing = log.noop\n```\n```javascript\ndoesNothing.bright.red ('this never shows') // simply returns 'this never shows'\n```\n\n# Powered By\n\n- [String.ify](https://github.com/xpl/string.ify)\n- [StackTracey](https://github.com/xpl/stacktracey)\n- [pipez](https://github.com/xpl/pipez)\n- [ansicolor](https://github.com/xpl/ansicolor)\n- [printable-characters](https://github.com/xpl/printable-characters)\n\n# Projects That Use Ololog\n\n- [CCXT](https://github.com/ccxt-dev/ccxt) – a cryptocurrency trading library with 100+ exchanges.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxpl%2Fololog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxpl%2Fololog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxpl%2Fololog/lists"}