{"id":"featherfall-org/quill-logger","name":"quill-logger","scope":"featherfall-org","platform":"roblox","description":"A tiny, context aware logger for Quill","version":"0.1.0-alpha.2","latest":"0.1.0-alpha.2","versions":["0.1.0-alpha.1","0.1.0-alpha.2"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"d5b1193cf786bbb01eef2572248cefa2dd61a5b7798a26771c034488c7f07c1d","likes":0,"downloads":0,"install":"forest install featherfall-org/quill-logger","url":"https://forest.dev/p/roblox/featherfall-org/quill-logger","files":"https://api.forest.dev/ai/package/roblox/featherfall-org/quill-logger/files","readme":"# Logger\r\n\r\nA simple, yet powerful logger.<br>\r\nThe logger isn't a Quill module, but rather a helper crate, and so it isn't added to Quill and can be used outside of Quill.\r\n\r\n## Usage\r\n\r\nA logger has an identifier, a subscriber and an optional, supplementary context.\r\n```luau\r\ntype LoggerConstructor = (identifier: Identifier, subscriber: Subscriber, context: Context) -> Logger\r\n```\r\n\r\nAn identifier doesn't have to be unique, and can simply be considered as a name for the logger.\r\n```luau\r\ntype Identifier = string\r\n```\r\n\r\nA subscriber is called for each logger event, as long as the global log level is at least the level of the event.\r\n```luau\r\ntype Subscriber = (Event) -> ()\r\n```\r\n\r\nContext is arbitrary user-defined data that can be used to give subscribers more context about an event.<br>\r\nFor example, in a Datastore API wrapper, you could put the player's user id and data in it.<br>\r\nEvents receive both logger & log context merged into one.\r\n```luau\r\ntype Context = { [string]: any }\r\n```\r\n\r\nLoggers can be extended with additional context and a new identifier.<br>\r\nGiven a base logger `my_logger` with context `{ foo = \"bar\" }`\r\n```luau\r\nlocal my_logger = logger.new(\"my_logger\", my_subscriber, { foo = \"bar\" })\r\n```\r\nyou can extend it with additional context `{ hello = \"world\" }`\r\n```luau\r\nlocal my_new_logger = logger.new(\"my_new_logger\", { hello = \"world\" })\r\n```\r\nresulting in logger `my_new_logger` with context `{ foo = \"bar\", hello = \"world\" }`.\r\n\r\nEvents are a table containing the timestamp of the event, its level, message, logger name and context.\r\n```luau\r\nexport type Event = {\r\n    timestamp: number,\r\n    level: Level,\r\n    message: string,\r\n    logger: string,\r\n    context: { [string]: any }?,\r\n}\r\n```\r\n\r\nEvents can be created manually via `logger:event`:\r\n```luau\r\nevent: (\r\n    self: Logger,\r\n    level: Level,\r\n    message: string,\r\n    context: { [string]: any }?\r\n) -> (),\r\n```\r\nalbeit each logger also exposes a bunch of wrapper functions for each log level:\r\n```luau\r\nlogger:trace(\"This is a trace message!\", my_additional_ctx)\r\nlogger:debug(\"This is a debug message!\", my_additional_ctx)\r\n-- and so on...\r\n```\r\n\r\nThe crate exposes three subscribers by default:\r\n- `console_subscriber`, which outputs all events to the console in the format of:\r\n  ```\r\n  {event.logger} - {event.level} @ {event.timestamp}:\r\n  {event.message}\r\n  ```\r\n  while also erroring for any fatal events\r\n- `traceback_subscriber`, which has the same behaviour as `console_subscriber`, while additionally outputting stack traces\r\n- `context_subscriber`, which has the same behaviour as `traceback_subscriber`, while additionally outputting event context\r\n\r\nYou may set a global log level for each logger with `.set_log_level()`, as mentioned earlier, which stops subscribers from listening to any events which aren't at least of that log level.<br>\r\nFor example, to only output warn events and above, you'd do:\r\n```luau\r\nlogger.set_log_level(\"warn\")\r\n```\r\n","readmeTruncated":false}