{"id":16544679,"url":"https://github.com/mahajanankur/motifer","last_synced_at":"2025-03-16T19:32:29.847Z","repository":{"id":46861951,"uuid":"291666776","full_name":"mahajanankur/motifer","owner":"mahajanankur","description":"Generic logs pattern builder for express, built on top of Winston.","archived":false,"fork":false,"pushed_at":"2024-10-08T12:04:11.000Z","size":417,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-19T11:50:22.832Z","etag":null,"topics":["apm","express-request-identifier","javascript-logger","logger","loggerfactory","logging","nodejs","winston"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mahajanankur.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-31T09:05:04.000Z","updated_at":"2024-10-08T12:04:15.000Z","dependencies_parsed_at":"2024-10-20T20:32:49.994Z","dependency_job_id":null,"html_url":"https://github.com/mahajanankur/motifer","commit_stats":{"total_commits":88,"total_committers":5,"mean_commits":17.6,"dds":0.125,"last_synced_commit":"1aa5b32c7231e63ea6937eb101c0076920c136d0"},"previous_names":["mahajanankur/motif"],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mahajanankur%2Fmotifer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mahajanankur%2Fmotifer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mahajanankur%2Fmotifer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mahajanankur%2Fmotifer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mahajanankur","download_url":"https://codeload.github.com/mahajanankur/motifer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221395466,"owners_count":16812207,"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":["apm","express-request-identifier","javascript-logger","logger","loggerfactory","logging","nodejs","winston"],"created_at":"2024-10-11T19:04:10.603Z","updated_at":"2024-10-27T11:10:53.272Z","avatar_url":"https://github.com/mahajanankur.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Motifer\n\n[![Version npm](https://img.shields.io/npm/v/motifer.svg?style=flat-square)](https://www.npmjs.com/package/motifer)\n[![HitCount](https://hits.dwyl.com/mahajanankur/motifer.svg?style=flat-square)](http://hits.dwyl.com/mahajanankur/motifer)\n\n[![NPM](https://nodei.co/npm/motifer.png?downloads=true\u0026downloadRank=true)](https://nodei.co/npm/motifer/)\n\nMotifer is a generic logs pattern builder on top of Winston. It covers multiple usecases as follows.\n\n  - Log pattern validation.\n  - Consistent log pattern across the application.\n  - Logstash and Cloudtrail support.\n  - Request and response logging with a **unique request id** for a request flow.\n\n### Overview\n\nMotifer uses a number of open source projects to work properly:\n\n* [Winston](https://github.com/winstonjs/winston)\n* [Morgan](https://github.com/expressjs/morgan)\n\nAnd of course Motifer itself is open source with a public [repository](https://github.com/mahajanankur/motifer) on GitHub.\n\n### Installation\n\nMotifer requires [Node.js](https://nodejs.org/) to run.\n\nInstall the dependencies and devDependencies and start the server.\n\n```sh\n$ npm i motifer\n```\n## Usage\nThe recommended way to use `motifer` is to create a logger. The simplest way to do this is using `LoggerFactory` or `ExpressLoggerFactory`.\n### LoggerFactory\nInitialize the `LoggerFactory` object once and use it in different js files.\n``` js\nconst { LoggerFactory } = require('motifer');\n\nlet options = [{\n    \"rotate\": true,\n    \"filename\": \"logfile-%DATE%.log\",\n    \"frequency\": \"5m\",\n    \"datePattern\": \"YYYY-MM-DD-HHmm\",\n    \"archived\": true,\n    \"maxSize\": \"20m\",\n    \"maxFiles\": \"14d\",\n    \"dirname\": \"/home/ankur/motifer/examples\",\n    \"level\": \"debug\"\n}];\nexports.Logger = new LoggerFactory(\"app_name\", \"log_level\", options);\n```\nSupported log levels are **info, debug, warn and error**.\n\n``` js\nconst { Logger } = require('./index');\nlet logger = Logger.getLogger(__filename);\n\nconst printLogs = args =\u003e {\n        logger.info(`The message to print ${args.subargs}`);\n}\n```\n``` log\n2020-08-31T09:45:53.717Z [APP_NAME] [INFO] [filename.js] The sample info message.\n2020-08-31T09:45:53.720Z [APP_NAME] [DEBUG] [filename.js] The sample debug message. The arguments are {\"key1\":\"value1\",\"key2\":\"value2\"}.\n2020-08-31T09:45:53.721Z [APP_NAME] [WARN] [filename.js] The sample warn message.\n2020-08-31T09:45:53.722Z [APP_NAME] [ERROR] [filename.js] Error: Sample Error Message with arguments {\"key1\":\"value1\"}\n    at getTerminatedEmployees (/motifer/examples/service.js:10:20)\n    at Object.\u003canonymous\u003e (motifer/examples/service.js:23:1)\n    at Module._compile (internal/modules/cjs/loader.js:778:30)\n    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)\n    at Module.load (internal/modules/cjs/loader.js:653:32)\n    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)\n    at Function.Module._load (internal/modules/cjs/loader.js:585:3)\n    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)\n    at startup (internal/bootstrap/node.js:283:19)\n    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)\n2020-08-31T09:45:53.723Z [APP_NAME] [ERROR] [filename.js] Error: Sample Error Message\n    at getTerminatedEmployees (/motifer/examples/service.js:10:20)\n    at Object.\u003canonymous\u003e (motifer/examples/service.js:23:1)\n    at Module._compile (internal/modules/cjs/loader.js:778:30)\n    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)\n    at Module.load (internal/modules/cjs/loader.js:653:32)\n    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)\n    at Function.Module._load (internal/modules/cjs/loader.js:585:3)\n    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)\n    at startup (internal/bootstrap/node.js:283:19)\n    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)\n```\n---\n### ExpressLoggerFactory\nInitialize the `ExpressLoggerFactory` object once with express server object and use it in different routes. **Make sure you initialize the body parser middleware before motifer initialization to log the request body.**\n##### index.js / app.js\n``` js\nconst express = require(\"express\");\nconst bodyParser = require(\"body-parser\");\nconst { ExpressLoggerFactory } = require(\"motifer\");\n// Change this Object according to your route.\nconst route = require(\"./src/controllers/route\");\nconst port = 8080;\n\n//Configure the server\nconst server = express();\n\n//Configure the JSON body parser for request.\nserver.use(bodyParser.json());\n\n// Motifer - This is a mandatory initialization to send the express object to \n// the motifer scope. If this configuration not set, it will not print the requestId.\n\nlet options = [{\n    \"rotate\": true,\n    \"filename\": \"logfile-%DATE%.log\",\n    \"frequency\": \"5m\",\n    \"datePattern\": \"YYYY-MM-DD-HHmm\",\n    \"archived\": true,\n    \"maxSize\": \"20m\",\n    \"maxFiles\": \"14d\",\n    \"dirname\": \"/home/ankur/motifer/examples\",\n    \"level\": \"debug\"\n}];\nconst Logger = new ExpressLoggerFactory(\"app\", \"debug\", server, options);\nconst logger = Logger.getLogger(__filename);\n\n//Server port configuration.\nserver.listen(port, () =\u003e {\n    logger.info(`Motifer node server is running on port:`, port);\n});\n\n//Register the controllers as routers.\nserver.use(\"/api\", route);\n```\n\n##### routes.js / service.js / repository.js\n``` js\nconst express = require(\"express\");\nconst { Logger } = require(\"motifer\");\n//ExpressLoggerFactory should be initialized before using this in index.js.\nconst logger = Logger.getLogger(__filename);\n//Get router from express\nconst router = express.Router();\n\n//Resources\nrouter.get(\"/status\", async (req, res, next) =\u003e {\n    logger.info(\"Service status request.\");\n    logger.debug(\"Service is up, sample debug log.\", req.query);\n    logger.warn(\"Warning the parameter is null, sample warn log.\");\n    logger.error(\"Exception is thrown, sample error log.\");\n    return res.json({message: \"Service is running!!\"});\n});\n\nmodule.exports = router;\n```\n\u003e Request id is of `UUID V4` type.\n\n#### Log Patterns\n##### Request Logs\n``` log\nTIMESTAMP_ISO [request] [REQUEST_ID] [APP_NAME] [LOG_LEVEL] [REQUEST_METHOD] [REQUEST_IP] [API_PATH] [BODY]\n```\n##### Service Logs\n``` log\nTIMESTAMP_ISO [service] [REQUEST_ID] [APP_NAME] [LOG_LEVEL] [FILENAME] MULTI_OR_SINGLE_LINE_MESSAGE\n```\n##### Response Logs\n``` log\nTIMESTAMP_ISO [response] [REQUEST_ID] [APP_NAME] [LOG_LEVEL] [REQUEST_METHOD] [REQUEST_IP] [API_PATH] [RESPONSE_STATUS] [CONTENT_LENGTH] [RESPONSE_TIME] [USER_AGENT] \n```\n\n``` log\n2020-09-13T15:39:26.320Z [request] [47de6d41-6dbd-44fc-9732-e28823755b58] [APP_NAME] [INFO] [GET] [::1] [/api/status/10?service=myservice\u0026cc=IND] [{}]\n2020-09-13T15:39:26.325Z [service] [47de6d41-6dbd-44fc-9732-e28823755b58] [APP_NAME] [INFO] [status.js] Some sample messages to print.\n2020-09-13T15:39:26.325Z [service] [47de6d41-6dbd-44fc-9732-e28823755b58] [APP_NAME] [DEBUG] [status.service.js] Publishing data to channel with topic: sampleTopic.\n2020-09-13T15:39:26.326Z [service] [47de6d41-6dbd-44fc-9732-e28823755b58] [APP_NAME] [ERROR] [status.service.js] Error: Runtime Exception\n    at exports.checkStatus (/motifer/rest/src/services/status.service.js:8:18)\n    at router.get (/motifer/rest/src/controllers/status.js:15:5)\n    at Layer.handle [as handle_request] (/motifer/rest/node_modules/express/lib/router/layer.js:95:5)\n    at next (/motifer/rest/node_modules/express/lib/router/route.js:137:13)\n    at Route.dispatch (/motifer/rest/node_modules/express/lib/router/route.js:112:3)\n    at Layer.handle [as handle_request] (/motifer/rest/node_modules/express/lib/router/layer.js:95:5)\n    at /motifer/rest/node_modules/express/lib/router/index.js:281:22\n    at param (/motifer/rest/node_modules/express/lib/router/index.js:354:14)\n    at param (/motifer/rest/node_modules/express/lib/router/index.js:365:14)\n    at Function.process_params (/motifer/rest/node_modules/express/lib/router/index.js:410:3)\n2020-09-13T15:39:26.326Z [service] [47de6d41-6dbd-44fc-9732-e28823755b58] [APP_NAME] [WARN] [status.js] Service status request.\n2020-09-13T15:39:26.331Z [response] [47de6d41-6dbd-44fc-9732-e28823755b58] [APP_NAME] [INFO] [GET] [::1] [/api/status/10?service=search\u0026cc=IND] [304] [10] [6.018 ms] [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36]\n2020-09-13T15:39:26.815Z [request] [bcf6d2e2-f8c9-49ee-9efa-65fb15d8b11e] [APP_NAME] [INFO] [GET] [::1] [/favicon.ico] [{}]\n2020-09-13T15:39:26.817Z [response] [bcf6d2e2-f8c9-49ee-9efa-65fb15d8b11e] [APP_NAME] [INFO] [GET] [::1] [/favicon.ico] [404] [150] [1.880 ms] [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36]\n```\n---\n### LoggerFactory\n\nThe **object** has three parameter.\n\n| Param | Description |Mandatory |Default |Comments|\n| ------ | ------ | ------ | ------ | ------ |\n| service | Application or service name. | Yes | NA| This is a mandatory param.|\n| level | Log level for the application. | No | info| Info is default log level.|\n| options | Array of objects for file appender and rotation. | No | null| If not supplied file appender will not be attached.|\n\n### ExpressLoggerFactory\n\nThe **object** has four parameter.\n\n| Param | Description |Mandatory |Default |Comments|\n| ------ | ------ | ------ | ------ | ------ |\n| service | Application or service name. | Yes | NA| This is a mandatory param.|\n| level | Log level for the application. | Yes | NA| This is a mandatory param.|\n| express | Express object | Yes | NA| This is a mandatory param.|\n| options | Array of objects for file appender and rotation. | No | null| If not supplied file appender will not be attached.|\n\n---\n## Options\nYou can rotate files by minute, hour, day, month, year or weekday. The object contains following options:\n\n- **rotate:** A boolean to define whether or not to rotate log files. **(default: 'false')**\n- **frequency:** A string representing the frequency of rotation. This is useful if you want to have timed rotations, as opposed to rotations that happen at specific moments in time. Valid values are '#m' (minites) or '#h' (hours) (e.g., '5m' or '3h'). You also need to mention the`datePattern` for the rotation times. **(default: null)**\n- **datePattern:** A string representing the [moment.js date format](http://momentjs.com/docs/#/displaying/format/) to be used for rotating. The meta characters used in this string will dictate the frequency of the file rotation. For example, if your datePattern is simply 'HH' you will end up with 24 log files that are picked up and appended to every day. **Make sure to define this along with the `frequency` for specific pattern rotation.** Example patterns for day: 'YYYY-MM-DD', hours: 'YYYY-MM-DD-HH' and minutes: 'YYYY-MM-DD-HHmm'. **(default: 'YYYY-MM-DD')**\n- **filename:** Filename to be used to log to. This filename can include the `%DATE%` placeholder which will include the formatted `datePattern` at that point in the filename. **(default: 'motifer-%DATE%.log')**\n- **dirname:** The directory name to save log files to. **(default: '.')**\n- **maxSize:** Maximum size of the file after which it will rotate. This can be a number of bytes, or units of `kb, mb, and gb`. If using the units, add 'k', 'm', or 'g' as the suffix. The units need to directly follow the number. **(default: '20m')**\n- **maxFiles:** Maximum number of logs to keep. If not set, no logs will be removed. This can be a number of files or number of days. If using days, add 'd' as the suffix. **(default: '14d')**\n- **archived:** A boolean to define whether or not to archived log files. **(default: 'true')**\n- **level:** Log level for the file appender. **(default: 'info')**\n---\n## Examples\n\n### Logger without file appenders.\n``` js\n//Initialize the express server.\nconst server = express();\nconst Logger = new ExpressLoggerFactory(\"app\", \"debug\", server);\n```\n\n### Logger with file appenders but without file rotation.\n``` js\n//Initialize the express server.\nconst server = express();\n\nlet options = [{\n    \"filename\": \"logfile.log\",\n    \"dirname\": \"/home/ankur/motifer/examples\"\n}];\nconst Logger = new ExpressLoggerFactory(\"app\", \"debug\", server, options);\n```\n\n### Logger with log file rotation.\n``` js\n//Initialize the express server.\nconst server = express();\n\nlet options = [{\n    \"rotate\": true,\n    \"filename\": \"logfile-%DATE%.log\",\n    \"frequency\": \"2d\",\n    \"datePattern\": \"YYYY-MM-DD-HH\",\n    \"archived\": true,\n    \"maxSize\": \"20m\",\n    \"maxFiles\": \"14d\",\n    \"dirname\": \"/home/ankur/motifer/examples\"\n}];\nconst Logger = new ExpressLoggerFactory(\"app\", \"debug\", server, options);\n```\n### Logger with multiple file appenders.\n``` js\n//Initialize the express server.\nconst server = express();\n\nlet options = [\n{\n    \"level\": \"error\",\n    \"filename\": \"error.log\",\n    \"dirname\": \"/home/ankur/motifer/examples\"\n},\n{\n    \"level\": \"warn\",\n    \"filename\": \"warn.log\"\n},\n{\n    \"rotate\": true,\n    \"filename\": \"logfile-%DATE%.log\",\n    \"frequency\": \"2d\",\n    \"datePattern\": \"YYYY-MM-DD-HH\",\n    \"archived\": true,\n    \"maxSize\": \"20m\",\n    \"maxFiles\": \"14d\",\n    \"dirname\": \"/home/ankur/motifer/examples\"\n}];\nconst Logger = new ExpressLoggerFactory(\"app\", \"debug\", server, options);\n```\nLicense\n----\n\n**Apache 2.0**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmahajanankur%2Fmotifer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmahajanankur%2Fmotifer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmahajanankur%2Fmotifer/lists"}