{"_id":"@8pattern/jlogger","_rev":"2-5b860bfed8cd1f809e9f9cb2f9340b61","name":"@8pattern/jlogger","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@8pattern/jlogger","version":"0.1.0","description":"a tiny log library for JS","scripts":{"dev":"webpack --mode=development","build":"webpack --mode=production","test":"jest"},"keywords":["log"],"author":{"name":"8th-pattern"},"license":"MIT","main":"./dist/jLogger.js","devDependencies":{"@babel/plugin-proposal-class-properties":"^7.5.5","@babel/plugin-proposal-object-rest-spread":"^7.5.5","@babel/preset-typescript":"^7.6.0","@types/jest":"^24.0.18","babel-loader":"^8.0.6","clean-webpack-plugin":"^3.0.0","jest":"^24.9.0","jest-cli":"^24.9.0","terser-webpack-plugin":"^2.1.0","ts-jest":"^24.1.0","typescript":"^3.6.3","webpack":"^4.40.2","webpack-cli":"^3.3.9"},"repository":{"type":"git","url":"git+https://github.com/8th-pattern/jLogger.git"},"bugs":{"url":"https://github.com/8th-pattern/jLogger/issues"},"homepage":"https://github.com/8th-pattern/jLogger#readme","_id":"@8pattern/jlogger@0.1.0","_nodeVersion":"10.16.2","_npmVersion":"6.7.0","dist":{"integrity":"sha512-+6N9ZXwawxd5dSyNFSd7JZNBXYUb7DChtyZxUQwAhIUgjzHYSD2lamNQOalsAjJNd30tXkSjX/jzEVaCbwSCvA==","shasum":"9eea151b70d1b682afdc237c575a434c54d54d22","tarball":"https://registry.npmjs.org/@8pattern/jlogger/-/jlogger-0.1.0.tgz","fileCount":20,"unpackedSize":38482,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdpS0ECRA9TVsSAnZWagAAZUoQAIf3A9yLG9LRqhhKMrza\nFrRQPm0kqBwKzmwKv7YLj+VUTtWRvrjRoeXef+jk2Ud3F/MNRUpJa5xqvU5P\n9Yi3DecFohbQhdHqv2v3ZqXZiGefx+cl6MQ475+GBrm4cAYiA3AIPj5G9MEk\nO5G6GoEpsUf4Ukx/BPBEIJQK4d6XyxMbCrWg3mUF1MZ9rmU/1GUcHkygb9n3\nieD7bY2FlRktXHCRLZMZ30bUmuI2mv1hyKjPz/bvpJVC25hzZdohEMxUrxZL\n64yli4GSpBfy1FFtkq+Ye9hfzHkF9DMiVWR5+Fj2EboHj3JbhZDQZcIdZnWp\nCN2bMn4UDl+O6vT+GkWU6gg2Fw+WWezlKyz7N11/f1olhFwUDqP7qpaZraTc\ntTQA+ZkibOAtLh6f/OF4GOkM43fEH4VqEYncKfKBlQQCNx0rwiv4pXGGNNLC\nHrUZ7rYRgWsH1IUiGrB9wCmkXJajhzJb37/LZvDVXpkdhxGZBQmPFdEDxZQF\n/5g4jWmIbEc3ib+pOe1PIKv5Rp3KnuHN/yYDQindqt9a3wSaqNUzRfhLb0i8\nsUq5Hv1JWrTGDeOMfz6y0HqtoZJk3C5eBVZBG2EbZQ1sHKjUKStBHkX4GSiI\nTPzKMgcCjkmHlV1hXMjzH6LZxk0ybI1Qr0Zdet5SzvYWYWqJesvZNh3Azk8D\nMiAJ\r\n=g5DK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICG0btQZB/E+Gupb6XQBY9SO9plxMR4PBuM2g9YgSH2DAiEA8QbSghdA1hcSYwgk5v3nbfsh6rZxlTwC9hMNk6YSRGc="}]},"maintainers":[{"name":"8pattern","email":"eighth.principle@gmail.com"}],"_npmUser":{"name":"8pattern","email":"eighth.principle@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/jlogger_0.1.0_1571106052291_0.8243124268160762"},"_hasShrinkwrap":false},"0.1.1":{"name":"@8pattern/jlogger","version":"0.1.1","description":"a tiny & flexible logger for JS","scripts":{"dev":"rollup -c -w --environment NODE_ENV:development","build":"rollup -c --environment NODE_ENV:production","test":"jest"},"keywords":["log"],"author":{"name":"8th-pattern"},"license":"MIT","main":"./dist/jLogger.js","types":"./src","devDependencies":{"@babel/plugin-proposal-class-properties":"^7.5.5","@babel/plugin-proposal-object-rest-spread":"^7.5.5","@babel/preset-typescript":"^7.6.0","@types/jest":"^24.0.18","babel-loader":"^8.0.6","jest":"^24.9.0","jest-cli":"^24.9.0","ts-jest":"^24.1.0","rollup":"^1.26.3","rollup-plugin-babel":"^4.3.3","rollup-plugin-terser":"^5.1.2","rollup-plugin-typescript2":"^0.24.3","typescript":"^3.6.3"},"repository":{"type":"git","url":"git+https://github.com/8th-pattern/jLogger.git"},"bugs":{"url":"https://github.com/8th-pattern/jLogger/issues"},"homepage":"https://github.com/8th-pattern/jLogger#readme","gitHead":"2ab28c340790115e4f50ce9ffabe605064acd597","_id":"@8pattern/jlogger@0.1.1","_nodeVersion":"12.13.0","_npmVersion":"6.12.1","dist":{"integrity":"sha512-GlHRIEPPh0++7xGqxGG0L6tqLHOoZAhW8smJLj92wGJbzC71W3I6aDsO/SHaGtX5Wa1jZ4lrKp2/m/inWI8arQ==","shasum":"2a96a9fc330030cb3e23cdb4cb5cf8f60b2d4b83","tarball":"https://registry.npmjs.org/@8pattern/jlogger/-/jlogger-0.1.1.tgz","fileCount":22,"unpackedSize":58749,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdxRmVCRA9TVsSAnZWagAA014P/1DNGnf1WBuFqUh/HnKJ\n/bwS/I3jI+2rXFSsEB55oxtVjsCh0YBaK0Ya0J5eTOIyczxVC1+cQ6ynA1mW\nuGYZQc7qzmjkJlwAUNXPEICwERiS/y9ChxABkxxdaa+jU6/Yz+TbAroSLmz7\nsZ/jZYSCIDbf4aI1vjjWYMiP0rX4ezd6faBGvybPnXwC/ibsIrUzqPGQOnLP\nUOhtE8LwL0IHIwkUx5iX/jsL8uLNbdrEiYBTrO0rEBNHOrq2m4Xm3f7hE/Ha\n8AXN0q7Zo+B/qqX8q4uWCixYGMwJ+OngmEJi6zlUAX4YAhlOCa2W/TyRqSaq\nPwc6ueTh9da3wu49NomdAfFb84+buSajgpOI4/FXmOYPbUPPSoroRXogF6Bl\nARq2DQTDQUFUVHYJCBdDNeGGW+zEWEhMtc61KRQX5VSOfuiyt27362GtOEnb\nChT3HovPwjkOweWsrs3kkPvW5TBLBNyLDJuJT7RZT+LexLhhq5klpWdwb/w6\nscaF+5IdTS3ankXGfehWz85T1L/9BgwSNNjDwnxk8SzsLlgBDIZT0Q6biHTo\nrrIcSH/W/bgTvyRNJKbe/7xpGh/a6vtfPG6svSZnXz5Q2KYX+uUUBAe18RP0\n+ObeVgl09UWagRIHU0L16mEgbjHYaAALN87X/o+bBygkEc+9HvXdTQGzEbC0\nkXZn\r\n=B+vN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDadvQC/b/mpITeTKlvLA1jsinuN7FO2FxK0KJD87Qy0QIgbiAk2UQPOUG8YrgjH45pGramT9qTfeSsJ2ZmSxEx7M0="}]},"maintainers":[{"name":"8pattern","email":"eighth.principle@gmail.com"}],"_npmUser":{"name":"8pattern","email":"eighth.principle@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/jlogger_0.1.1_1573198228643_0.5977981025463526"},"_hasShrinkwrap":false}},"time":{"created":"2019-10-15T02:20:52.031Z","0.1.0":"2019-10-15T02:20:52.423Z","modified":"2022-04-04T10:50:08.010Z","0.1.1":"2019-11-08T07:30:28.730Z"},"maintainers":[{"name":"8pattern","email":"eighth.principle@gmail.com"}],"description":"a tiny & flexible logger for JS","homepage":"https://github.com/8th-pattern/jLogger#readme","keywords":["log"],"repository":{"type":"git","url":"git+https://github.com/8th-pattern/jLogger.git"},"author":{"name":"8th-pattern"},"bugs":{"url":"https://github.com/8th-pattern/jLogger/issues"},"license":"MIT","readme":"# jLogger\r\nA tiny & flexible logger for JS\r\n\r\n[toc]\r\n\r\n\r\n\r\n## Install\r\n\r\n```javascript\r\nnpm install -S @8pattern/jlogger\r\n```\r\n\r\n\r\n\r\n## Usage\r\n\r\n### Demo with default appenders\r\n\r\n```javascript\r\nimport JLogger from '@8pattern/jlogger'\r\nconst logger = new JLogger()\r\nlogger.info('hello, world')\r\n```\r\n\r\nif you execute the previous codes, you will find the console prints a JSON like *{\"level\":\"INFO\", ... ,\"count\":1,\"content\":\"hello, world\"}* automatically. \r\n\r\n### Demo with appenders\r\n\r\n```javascript\r\nimport JLogger, { appender } from '@8pattern/jlogger'\r\nconst logger = new JLogger()\r\nlogger.Appender.register(new appender.FileAppender())\r\nlogger.info('hello, world')\r\n```\r\n\r\nExecute the previous codes, not only the console will print a JSON like *{\"level\":\"INFO\", ... ,\"count\":1,\"content\":\"hello, world\"}*, but also a log file (yyyy-mm-dd.log) can be found in same dir with the same JSON (in Node environment). \r\n\r\n### Procedure\r\n\r\n#### Preparation\r\n\r\nBefore print logs by jLogger, a instance should be generated. It allows users to bind some arguments and configurations on the instance. The construction function can receive two arguments.\r\n\r\n```javascript\r\nconst logArguments = {}, logConfig = {}\r\nconst logger = new JLogger(logArguments, logConfig)\r\n```\r\n\r\n1. logArguments &lt;object&gt;: receive some default arguments within this instance scope, i.e., each log will receive these arguments.\r\n\r\n   In Node environment, the default value is:\r\n\r\n   + **pid**: same as process.pid\r\n\r\n   In browser, the default value are:\r\n\r\n   + **wid**: a random number less than 100,000\r\n   + **url**: the current route path, i.e., the href without protocol, host and port\r\n\r\n   **You CAN assign some custom arguments**, such as: filePath, author and etc.\r\n\r\n   ```javascript\r\n   const logArguments = { hello: 'world' }\r\n   const logger = new JLogger(logArguments)\r\n   logger.info('') // { ..., hello: 'world', ... }\r\n   ```\r\n\r\n2. logConfig &lt;object&gt;: some configurations to change the logger behavior.\r\n\r\n   Only the following configurations is valid.\r\n\r\n   + **category**  &lt;JSON&gt;\r\n\r\n     Default value: \r\n\r\n     ```json\r\n     {\r\n         notice: 'NOTICE',\r\n         action: 'ACTION',\r\n         function: 'FUNCTION',\r\n     }\r\n     ```\r\n\r\n   > **NOTE**: you can change these category values or add some new categories. **Deletion is useless** (Because we use them inside).\r\n\r\n   \r\n\r\n   + **level** &lt;JSON&gt;\r\n   \r\n     Default value: \r\n   \r\n     ```javascript\r\n     {\r\n         error: 'ERROR',\r\n         warn: 'WARN',\r\n         info: 'INFO',\r\n         debug: 'DEBUG',\r\n     }\r\n     ```\r\n   \r\n   > **NOTE**: Same as category, change values and add new levels works but **Deletion is useless**.\r\n\r\n   + format &lt;function&gt;\r\n   \r\n     + argument: logArguments &lt;JSON&gt;\r\n     + return: logString &lt;string&gt;\r\n   \r\n     Default value: \r\n   \r\n     ```javascript\r\n     (logArgs) => JSON.stringify(logArgs)\r\n     ```\r\n   \r\n   > 1. The content of logArguments will be presented at the following section.\r\n   > 2. If some log arguments don't wanted to be printed, such as some levels or categories, you can modify this format implementation.\r\n   \r\n   + printLevel &lt;array&gt;\r\n   \r\n     Default value: \r\n     \r\n     ```javascript\r\n     ['debug', 'info', 'warn', 'error']\r\n     ```\r\n   \r\n   > The elements must be the keys rather than values in *logConfig.level*\r\n\r\n#### Control appenders\r\n\r\n##### Pre-given appenders\r\n\r\nAppenders illustrates the print methods of  every logs. You can find some pre-given appenders from *appender* of the jLogger.\r\n\r\n```javascript\r\nimport { appender } from '@8pattern/jlogger'\r\nconst { Appender, ConsoleAppender, FileAppender } = appender\r\n```\r\n\r\n+ **Appender**\r\n\r\n  Abstract class for every specific appender. Only a abstract method *print* is binded on it. When you design a custom appender, you **MUST** extend from this parent class (presented later).\r\n\r\n+ **ConsoleAppender**\r\n\r\n  Print the logs into the console. It's also the default appenders, so you won't do anything but work.\r\n\r\n+ **FileAppender**\r\n\r\n  Print the logs into the file (only works in Node).\r\n\r\n  ```javascript\r\n  import JLogger, { appender } from '@8pattern/jlogger'\r\n  const logger = new JLogger()\r\n  logger.Appender.set([new appender.FileAppender()])\r\n  ```\r\n\r\n  It can be instantiated with some configurations as well.\r\n\r\n  ```javascript\r\n  const fileAppender = new FileAppender({\r\n      filePath: './',\r\n      fileName: `${dateformat(Date.now(), 'yyyy-mm-dd')}`,\r\n      fileExtension: 'log',\r\n  })\r\n  ```\r\n\r\n  + filePath &lt;string&gt;: the revelant path of the log file. \r\n\r\n    Default value: *'./'*\r\n\r\n  + fileName &lt;string&gt;: the name of the log file. \r\n\r\n    Default value: `${dateformat(Date.now(), 'yyyy-mm-dd')}`\r\n\r\n  + fileExtension &lt;string&gt;: the extension of the log file. \r\n\r\n    Default value: `log`\r\n\r\n##### Update appenders\r\n\r\nTo activate an appender, you need process the *logger.Appender*, and it provides some methods to control registered appenders.\r\n\r\n+ appenders &lt;array&gt;: store the registered appenders.\r\n\r\n  ```javascript\r\n  const logger = new JLogger()\r\n  console.log(logger.Appenders.appenders.length)\r\n  // 1, there is a instance of ConsoleAppender by default\r\n  ```\r\n\r\n+ set &lt;function&gt;\r\n\r\n  + argument: appenders &lt;array&gt;\r\n\r\n  + return: currentRegisteredAppendersNumber &lt;number&gt;\r\n\r\n  ```javascript\r\n  logger.Appenders.set([new ConsoleAppender(), new FileAppender()])\r\n  ```\r\n  > NOTE:\r\n  >\r\n  > 1. This method will replace all appenders.\r\n  > 2. Any appenders which not extended from the abstract class Appender will be filtered. \r\n\r\n+ get &lt;function&gt;\r\n\r\n  + argument: null\r\n\r\n  + return: appenders&lt;array&gt;\r\n\r\n  ```javascript\r\n  logger.Appender.get() // === logger.Appender.appenders\r\n  ```\r\n\r\n+ register &lt;function&gt;\r\n\r\n  + argument: appender\r\n  + return: null\r\n\r\n    ```javascript\r\n  logger.Appender.register(new FileAppender()) // logger.Appender.appenders.length === 2\r\n    ```\r\n\r\n  > NOTE:\r\n  >\r\n  > 1. Compare to set method, it only add a new appender RATHER THAN replace all of them.\r\n  > 2. ONLY instance of abstract class Appender will make effect as well.\r\n  > 3. If the appender has been registered, it won't add a new one.\r\n\r\n  ```javascript\r\n  logger.set([new ConsoleAppender()])\r\n  // logger.Appenders.appenders.length === 1\r\n  \r\n  const fileAppender = new FileAppender()\r\n  \r\n  logger.Appender.register(fileAppender)\r\n  // logger.Appenders.appenders.length === 2, register a new FileAppender instance\r\n  \r\n  logger.Appender.register(fileAppender)\r\n  // logger.Appenders.appenders.length === 2, because it has been registered before\r\n  \r\n  logger.Appender.register(new FileAppender())\r\n  // logger.Appenders.appenders.length === 3, a new FileAppender registered\r\n  \r\n  logger.Appender.register({})\r\n  // throw a error, because the provided appender is illegal.\r\n  ```\r\n\r\n  \r\n\r\n+ delete &lt;function&gt;\r\n\r\n  + argument: appender\r\n\r\n  + return: isSuccess &lt;boolean&gt;\r\n\r\n  ```javascript\r\n  const fileAppender = new FileAppender()\r\n  \r\n  logger.Appender.set([fileAppender])\r\n  // logger.Appenders.appenders.length === 1\r\n  \r\n  logger.Appender.delete(new FileAppender())\r\n  // === false, logger.Appenders.appenders.length === 1, the given appender doesen't exist\r\n  \r\n  const fileAppender = new FileAppender()\r\n  \r\n  logger.Appender.delete(fileAppender)\r\n  // === true, logger.Appenders.appenders.length === 0\r\n  ```\r\n\r\n##### Design a custom appender\r\n\r\nIf you want to customize a appender, you only need to extend your class from Appender and implement the print method.\r\n\r\n```javascript\r\nimport { appender } from '@8pattern/jlogger'\r\n\r\nclass CustomAppender extends appender.Appender {\r\n    print(logArgs) {\r\n        console.log(logArgs)\r\n    }\r\n}\r\n\r\njlogger.Appender.register(new CustomAppender())\r\n```\r\n\r\n\r\n\r\n#### Call to log\r\n\r\n##### logArgument\r\n\r\nThe logArgument contains all fields of a log, and it may be used to format the logger or print in the appender. It must contains the following values.\r\n\r\n+ **level**: the log level. Default value: *logger.config.level.info*.\r\n+ **timeStamp**: current time stamp (without formation). Value: *Date.now()*.\r\n+ **count**: the number of log called. Value: automatically increased from 0.\r\n+ **content**: the log content.\r\n\r\nBesides, some custom arguments can be added from construction or log call function. And the arguments from call function has higher priority than the construction. But, **\"*timeStamp*\" and \"*count*\" have the higher priority and can't be overridden.**\r\n\r\n```javascript\r\nconst logger = new Logger({a: 1, b: 2})\r\nlogger.info('', { b: 3, c: 4 })\r\n// { ..., a: 1, b: 3, c: 4, ... }\r\n```\r\n\r\n\r\n\r\n> If you want change the time or count in final logs, add another arguments and change the format function.\r\n\r\n##### Ordinary log method\r\n\r\n+ **log**\r\n\r\n  + argument: content &lt;string&gt;, logArgs &lt;JSON&gt;\r\n  + return: finalLogArgs &lt;JSON&gt;\r\n\r\n  ```javascript\r\n  logger.log('hello world', { a: 1 })\r\n  // { a: 1, ... content: 'hello world', ... }\r\n  ```\r\n\r\n+ **debug** / **info** / **warn**\r\n\r\n  + argument: content &lt;string&gt;, logArgs &lt;JSON&gt;\r\n  + return: finalLogArgs &lt;JSON&gt;\r\n\r\n  They are all sugar of log with levels.\r\n\r\n  ```javascript\r\n  logger.debug('') // { ..., level: 'DEBUG', ... }\r\n  logger.info('') // { ..., level: 'INFO', ... }\r\n  logger.warn('') // { ..., level: 'WARN', ... }\r\n  ```\r\n\r\n+ **error**\r\n\r\n  + argument: content &lt;string&gt; | &lt;Error&gt;, logArgs &lt;JSON&gt;\r\n  + return: finalLogArgs &lt;JSON&gt;\r\n\r\n  It is also the sugar of log with error level, but it can receive Error as content. If called with an Error, \"*errType*\" and \"*errDesc*\" will be added into finalLogArgs, and the stack of Error will be regarded as the content\r\n\r\n  ```javascript\r\n  logger.error('')\r\n  // { ..., content: '', ..., level: 'ERROR', ... }\r\n  \r\n  const err = new Error('Some errors')\r\n  logger.error(err)\r\n  // { ..., content: 'Error: Some errors at ...', ..., errDesc: 'Some errors', errType: 'Error', ... }\r\n  ```\r\n\r\n+ other level defined in config\r\n\r\n  If some other levels defined in config, it provides these sugars as well.\r\n\r\n  ```javascript\r\n  const level = {\r\n      fatal: 'FATAL',\r\n  }\r\n  const logger = new JLogger({}, { level })\r\n  logger.fatal('')\r\n  // { ..., level: 'FATAL', ... }\r\n  ```\r\n\r\n##### Function log\r\n\r\nSince function logs are so important but their same structures bored the coder, we provide two methods for function logs particularly.\r\n\r\n+ logWrap\r\n\r\n  + argument: wrapped &lt;Function&gt;, logArgs &lt;JSON&gt;\r\n  + return: &lt;Function&gt;\r\n\r\n  This method will print logs of the wrapped function input and output. If the function throws an error, it will print a error log automatically.\r\n\r\n  ```javascript\r\n  const fun(a) {\r\n      return a + 1;\r\n  }\r\n  \r\n  const wrappedFun = jLogger.logWrap(fun, { t: 1 })\r\n  \r\n  wrappedFun(1)\r\n  // { ..., content: 'INPUT: [1]',category: 'FUNCTION', funName: 'fun', t: 1, ...}\r\n  // { ..., content: 'OUTPUT: 2',category: 'FUNCTION', funName: 'fun', t: 1, ...}\r\n  ```\r\n  \r\n    ```javascript\r\n  const fun() {\r\n      throw new Error('some errors')\r\n  }\r\n  \r\n  const wrappedFun = jLogger.logWrap(fun)\r\n  \r\n  wrappedFun('hello')\r\n  // { ..., content: 'INPUT: ['hello']', category: 'FUNCTION', funName: 'fun', ...}\r\n  // { ..., category: 'FUNCTION', funName: 'fun', level: 'ERROR', ...}\r\n    ```\r\n\r\n+ logDecorator\r\n\r\n  + argument: logArgs &lt;JSON&gt;\r\n  + return: &lt;Function&gt;\r\n\r\n  There is a proposal for decorator for class method，and we also provide a logDecorator which is based on logWrap.\r\n\r\n  ```javascript\r\n  const log = logger.logDecorator({ test: 1 })\r\n  \r\n  class T {\r\n      @log\r\n      test1(a) {\r\n          return a + 1\r\n      }\r\n      \r\n      @logger.logDecorator({ test: 2 })\r\n      test2() {\r\n          throw new Error('some errors')\r\n      }\r\n  }\r\n  \r\n  const t = T()\r\n  \r\n  t.test1(1)\r\n  // { ..., content: 'INPUT: [1]', category: 'FUNCTION', className: 'T', funName: 'test1', t: 1, ...}\r\n  // { ..., content: 'OUTPUT: 2',category: 'FUNCTION', className: 'T', funName: 'test1', t: 1, ...}\r\n  \r\n  t.test(2)\r\n  // { ..., content: 'INPUT: [2]', category: 'FUNCTION', className: 'T', funName: 'test2', t: 2, ...}\r\n  // { ..., category: 'FUNCTION', level: 'ERROR', className: 'T', funName: 'test2', t: 2, ...}\r\n  ```\r\n\r\n  \r\n\r\n### Util\r\n\r\nWe provide some useful tools relevant to logs, which can be found from *jLogger.util* \r\n\r\n```javascript\r\nimport { util } from '@8pattern/jlogger'\r\nconst { dateformat, contentLengthFormat, logTag } = util\r\n```\r\n\r\n#### dateformat\r\n\r\n+ argument:\r\n  + date &lt;Date&gt; | &lt;number&gt;. Default value: *new Date()*\r\n  + formatStr &lt;string&gt;. Default value: 'yyyy-mm-dd HH:MM:ss.l'\r\n+ return: &lt;string&gt;\r\n\r\nThis method is a tiny function to format date. The usage is similar with the other mature library， i.e.,\r\n\r\n```javascript\r\ny -> year\r\nm -> month\r\nd -> day\r\nH -> hour\r\nM -> minute\r\ns -> second\r\nl -> millisecond\r\n```\r\n\r\nFor example:\r\n\r\n```javascript\r\ndateformat(0, 'yyyy-mm-dd') // 1970-01-01\r\ndateformat(new Date(0), 'yy-m-d') // 70-1-1\r\ndateformat(0, 'HH:MM:ss') // 00:00:00\r\ndateformat(0, 'H:M:s.l') // 0:0:0.0000\r\n```\r\n\r\n#### contentLengthFormat\r\n\r\n+ argument:\r\n  + content &lt;string&gt;.\r\n  + lengthLimit &lt;number&gt; | &lt;null&gt;. Default value: null\r\n  + replaceString &lt;string&gt;. Default value: ' <<<... $IGNORED_STRING_LENGTH chars are ignored ...>>> '\r\n+ return: &lt;string&gt;\r\n\r\n```javascript\r\ncontentLengthFormat('123456789')\r\n// 123456789, because lengthLimit === null\r\n\r\ncontentLengthFormat('123456789', 4)\r\n// 12 <<<... 5 chars are ignored ...>>> 89\r\n\r\ncontentLengthFormat('123456789', 4, '...igonred...')\r\n// 12...ignored...89\r\n```\r\n\r\n#### logTag\r\n\r\nThe tag for the template string for a log content. It will transform Function, Array and Object into more readable formation.\r\n\r\n```javascript\r\nfunction fun(a) { return a + 1; }\r\n`${fun}` // \"function fun(a) { return a + 1; }\"\r\nlogTag`${fun}` // \"-Function[fun]-\"\r\n```\r\n\r\n```javascript\r\nconst arr = [1,2,3,4,5]\r\n`${arr}` // \"1,2,3,4,5\"\r\nlogTag`${fun}` // \"[1,2,3,4,5]\"\r\n```\r\n\r\n```javascript\r\nconst dict = { a: 1 }\r\n`${dict}` // \"[object Object]\"\r\nlogTag`${dict}` // \"{ a: 1 }\"\r\n```\r\n\r\n```javascript\r\nclass CustomClass {}\r\nconst t = new CustomClass()\r\n`${t}` // \"[object Object]\"\r\nlogTag`${t}` // \"-CustomClass-\"\r\n```\r\n\r\nA complete example:\r\n\r\n```javascript\r\nconst obj = {\r\n    arr: [1, 2, function() {}],\r\n    fun() {},\r\n}\r\n\r\n`content is ${obj}` // \"content is [object Object]\"\r\nlogTag`content is ${obj}` // \"content is {arr:[1,2,-Function-], fun:-Function[fun]-}\"\r\n```\r\n\r\n","readmeFilename":"README.md"}