{"id":13495635,"url":"https://github.com/shakacode/rescript-logger","last_synced_at":"2025-04-09T09:07:45.013Z","repository":{"id":40993239,"uuid":"162874673","full_name":"shakacode/rescript-logger","owner":"shakacode","description":"Logging implementation for ReScript","archived":false,"fork":false,"pushed_at":"2024-02-28T15:58:16.000Z","size":402,"stargazers_count":109,"open_issues_count":8,"forks_count":9,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-02T05:08:49.849Z","etag":null,"topics":["ppx","rescript"],"latest_commit_sha":null,"homepage":"","language":"ReScript","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/shakacode.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.md","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":"2018-12-23T08:30:05.000Z","updated_at":"2025-01-15T12:35:15.000Z","dependencies_parsed_at":"2024-06-18T21:11:10.131Z","dependency_job_id":null,"html_url":"https://github.com/shakacode/rescript-logger","commit_stats":{"total_commits":126,"total_committers":9,"mean_commits":14.0,"dds":0.3571428571428571,"last_synced_commit":"ec688eadb1513991aa084380cf4013f7500d14b4"},"previous_names":["minimahq/bs-log","minimahq/res-logger","minimahq/rescript-logger"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakacode%2Frescript-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakacode%2Frescript-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakacode%2Frescript-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakacode%2Frescript-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shakacode","download_url":"https://codeload.github.com/shakacode/rescript-logger/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248008630,"owners_count":21032556,"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":["ppx","rescript"],"created_at":"2024-07-31T19:01:36.619Z","updated_at":"2025-04-09T09:07:44.991Z","avatar_url":"https://github.com/shakacode.png","language":"ReScript","funding_links":[],"categories":["ReScript"],"sub_categories":[],"readme":"# rescript-logger\n\n[![npm version](https://img.shields.io/npm/v/rescript-logger.svg?style=flat-square)](https://www.npmjs.com/package/rescript-logger)\n[![license](https://img.shields.io/npm/l/rescript-logger.svg?style=flat-square)](https://www.npmjs.com/package/rescript-logger)\n\nLogging implementation for [ReScript](https://rescript-lang.org).\n\n![rescript-logger](./example.png)\n\n## Features\n- Zero runtime in production builds.\n- Multiple logging levels.\n- Customizable verbosity.\n- `[@log]` helper.\n- [`@rescript/react`](https://github.com/rescript-lang/rescript-react) integration.\n- Custom loggers.\n- Logging in libraries.\n\n\u003e ### ShakaCode\n\u003e If you are looking for help with the development and optimization of your project, [ShakaCode](https://www.shakacode.com) can help you to take the reliability and performance of your app to the next level.\n\u003e\n\u003e If you are a developer interested in working on ReScript / TypeScript / Rust / Ruby on Rails projects, [we're hiring](https://www.shakacode.com/career/)!\n\n## Installation\nGet the package:\n\n```shell\n# yarn\nyarn add rescript-logger\n# or npm\nnpm install --save rescript-logger\n```\n\nThen add it to `bsconfig.json`:\n\n```json\n\"bs-dependencies\": [\n  \"rescript-logger\"\n],\n\"ppx-flags\": [\"rescript-logger/ppx\"]\n```\n\n## Usage\nThere are 5 log levels:\n- `trace`\n- `debug`\n- `info`\n- `warn`\n- `error`\n\nYou can log message of specific level using appropriate macros:\n\n```reason\n// ReScript\n%log.info(\"Info message\")\n%log.error(\"Error message\")\n\n// Reason\n[%log.info \"Info message\"];\n[%log.error \"Error message\"];\n```\n\n### Additional data\nYou can add data to log entry like this:\n\n```reason\n// ReScript\n%log.info(\n  \"Info message\"\n  (\"Foo\", 42)\n)\n%log.info(\n  \"Info message\"\n  (\"Foo\", {x: 42})\n  (\"Bar\", [1, 2, 3])\n)\n\n// Reason\n[%log.info \"Info message\"; (\"Foo\", 42)];\n[%log.info\n  \"Info message\";\n  (\"Foo\", {x: 42});\n  (\"Bar\", [1, 2, 3]);\n];\n```\n\nCurrently, logger can accept up to 7 additional entries.\n\n### Verbosity customization\nOutput verbosity can be customized by providing specific **log level** and/or **code locations**.\n\n#### Log level\nYou can set maximum log level via environment variable `RES_LOG`.\n\nLet's say you want to log only warnings and errors. To make it happen, run your build like this:\n\n```shell\nRES_LOG=warn rescript build\n```\n\nAvailable `RES_LOG` values:\n- `*`: log everything\n- `trace`: basically, the same as `*`\n- `debug`: log everything except `trace` level messages\n- `info`: log everything except `trace` \u0026 `debug` level messages\n- `warn`: log `warn` \u0026 `error` messages only\n- `error`: log `error` messages only\n- `off`: don't log anything\n\nIf `RES_LOG` is set to `off`, nothing will be logged and none of the log entries will appear in your JS assets.\n\nIn case if `RES_LOG` environment variable is not set, log level `warn` will be used.\n\nAlso, see [Usage in libraries](#usage-in-libraries).\n\n#### Code location\nIf you want to focus on logging from specific part(s) of your code, you can use `RES_LOG_ONLY` environment variable.\n\nFor example, if you want to see logs only from module `Test`, run the build as following:\n\n```shell\nRES_LOG_ONLY=Test rescript build\n```\n\nYou can pass submodules and functions to it as well. If you want to log from multiple locations, separate them by `,`.\n\nConsider the following source:\n\n```reason\n// Test.res\n%log.warn(\"Top level message\")\n\nmodule Submodule1 = {\n  %log.warn(\"Message from Submodule1\")\n}\n\nmodule Submodule2 = {\n  %log.warn(\"Message from Submodule2\")\n\n  let fn = () =\u003e %log.warn(\"Message from function within Submodule2\")\n  fn()\n}\n```\n\nHere is what will be logged with different build configurations:\n\n```\n# build\nRES_LOG_ONLY=Test rescript build\n\n# output\nWARNING  [Test] Top level message\nWARNING  [Test.Submodule1] Message from Submodule1\nWARNING  [Test.Submodule2] Message from Submodule2\nWARNING  [Test.Submodule2.fn] Message from function within Submodule2\n\n# build\nRES_LOG_ONLY=Test.Submodule2 rescript build\n\n# output\nWARNING  [Test.Submodule2] Message from Submodule2\nWARNING  [Test.Submodule2.fn] Message from function within Submodule2\n\n# build\nRES_LOG_ONLY=Test.Submodule1,Test.Submodule2.fn rescript build\n\n# output\nWARNING  [Test.Submodule1] Message from Submodule1\nWARNING  [Test.Submodule2.fn] Message from function within Submodule2\n```\n\n### `[@log]` helper\nThis helper can be placed in front of any `switch` expression with constructor patterns and it will inject debug expressions into each branch.\n\n```reason\n// ReScript\nlet _ =\n  x =\u003e\n    @log\n    switch x {\n    | A =\u003e \"A\"\n    | B(b) =\u003e b\n    }\n\n// Reason\nlet _ =\n  x =\u003e\n    [@log]\n    switch (x) {\n    | A =\u003e \"A\"\n    | B(b) =\u003e b\n    }\n```\n\nWithout a `@log` helper, an equivalent would be:\n\n```reason\n// ReScript\nlet _ =\n  x =\u003e\n    switch (x) {\n    | A =\u003e\n      %log.debug(\"A\")\n      \"A\"\n    | B(b) =\u003e\n      %log.debug(\"B with payload\" (\"b\", b))\n      b\n    }\n\n// Reason\nlet _ =\n  x =\u003e\n    switch (x) {\n    | A =\u003e\n      [%log.debug \"A\"];\n      \"A\";\n    | B(b) =\u003e\n      [%log.debug \"B with payload\"; (\"b\", b)];\n      b;\n    }\n```\n\nYou can pass optional custom namespace to helper like this: `@log(\"MyNamespace\")`.\n\n`[@log]` helper works only for `switch` expressions with constructor patterns, for now. Let us know [in the issues](/issues) if you need to handle more cases.\n\n### `@rescript/react` integration\nUsing `@log` helper, you can log dispatched actions in your components.\n\nAnnotate `reducer` function like this:\n\n```reason\n// ReScript\nlet reducer =\n  (state, action) =\u003e\n    @log\n    switch action {\n      ...\n    }\n\n// Reason\nlet reducer =\n  (state, action) =\u003e\n    [@log]\n    switch (action) {\n      ...\n    }\n```\n\nThese entries are logged on the `debug` level so none of it will appear in your production builds.\n\n### Custom loggers\n`rescript-logger` ships with 4 loggers:\n- `ReScriptLogger.Browser` (default)\n- `ReScriptLogger.Node`\n- `ReScriptLogger.Edge` (to use in edge environment, such as Cloudflare Workers)\n- `ReScriptLogger.Universal` (picks either `Browser` or `Node` logger at runtime depending on an environment, useful for apps with SSR)\n\nAnd you can easily plug your own.\n\nFor example, in development, you want to log everything to console using default logger, but in production, you want to disable console logging and send `error` level events to bug tracker.\n\nTo implement your own logger, you need to create a module (e.g. `BugTracker.re`) and set the following environment variables for production build.\n\n```\nRES_LOG=error\nRES_LOGGER=BugTracker\n```\n\nConsidering that you want to log only `error` level messages, you need to create functions only for errors logging.\n\n```reason\n// BugTracker.res\n\nlet error = (loc, msg) =\u003e BugTrackerSDK.notify(`${msg} in ${loc.rootModule}`)\n\nlet error1 =\n  (\n    loc,\n    msg,\n    (label, payload),\n  ) =\u003e\n    BugTrackerSDK.notify(\n      `${msg} in ${loc.rootModule}`,\n      [|(label, payload)|],\n    );\n\nlet error2 =\n  (\n    loc,\n    msg,\n    (label1, payload1),\n    (label2, payload2),\n  ) =\u003e\n    BugTrackerSDK.notify(\n      `${msg} in ${loc.rootModule}`,\n      [|\n        (label1, payload1),\n        (label2, payload2),\n      |],\n    );\n\n// Up to 7\n```\n\nThe first argument `loc` is a `ReScriptLogger.Location.t` record. It's passed by PPX and contains the location data.\n\n```reason\ntype t = {\n  rootModule: string,\n  subModulePath: list\u003cstring\u003e,\n  value: option\u003cstring\u003e,\n  fullPath: string,\n  filePath: string,\n}\n```\n\nIf `Test.Submodule.fn` gets called, logger would receive the following location:\n\n```reason\n// Test.res\nmodule Submodule = {\n  let fn = () =\u003e %log.warn(\"Warn!\")\n}\n\n// Location\n{\n  rootModule: \"Test\",\n  subModulePath: list{\"Submodule\"},\n  value: Some(\"fn\"),\n  fullPath: \"Test.Submodule.fn\",\n  filePath: \"/absolute/path/to/project/src/Test.res\",\n}\n```\n\n---\nNote, you don't have to re-implement all functions from the default logger, only the ones you actually use. Don't worry to forget to implement something. If later on, you will attempt to use unimplemented method it will be compile time error.\n\n### Usage in libraries\nIf you develop a library and want to use `rescript-logger` during development process, you can do so without spamming output of consumers of your library.\n\n`rescript-logger/ppx` accepts `--lib` flag:\n\n```json\n\"ppx-flags\": [\n  [\"rescript-logger/ppx\", \"--lib=my-lib\"]\n]\n```\n\nOnce this flag is passed, you need to provide special value of `RES_LOG` to log your entries:\n\n```shell\nRES_LOG=my-lib=* rescript build\n```\n\nIf consumers of your lib would like to see log output from your lib, they can do so too by extending a value of `RES_LOG` variable:\n\n```shell\nRES_LOG=*,my-lib=error rescript build\n```\n\nFew more examples to illustrate how it works:\n\n```shell\n# log everything from application code only\nRES_LOG=* rescript build\n\n# log everything from application code\n# log errors from `my-lib`\nRES_LOG=*,my-lib=error rescript build\n\n# log everything from application code\n# log errors from `my-lib-1`\n# log warnings and errors from `my-lib-2`\nRES_LOG=*,my-lib-1=error,my-lib-2=warn rescript build\n```\n\n## Caveats\n**Logging is disabled after file save**\u003cbr /\u003e\nIf you run `bsb` via editor integration, make sure editor picked up `RES_LOG` variable. E.g. if you use Atom run it like this:\n\n```shell\nRES_LOG=info atom .\n```\n\nIf your editor is telling you, variables used in ppx are unused, you can either:\n1. prefix such variables with `_`\n2. or open editor with `RES_LOG` variable set to appropriate level.\n\n**Changing value of `RES_LOG`/`RES_LOGGER`/`RES_LOG_ONLY` doesn't make any effect**\u003cbr /\u003e\nWhen you change a value of environment variable, `rescript clean` before the next build.\n\n## Developing\nRepo consists of 2 parts:\n- ReScript lib: dependencies are managed by `yarn`\n- OCaml PPX: dependencies are managed either by `nix` (in development) or `esy` (in development and/or on CI)\n\n### Nix flow\nClone repo and either enter the Nix shell:\n\n```\nnix-shell\n```\n\nOr use [`direnv`](https://direnv.net/) and create `.envrc` file in the root directory of the project with the folowing content:\n\n```\nuse nix\n```\n\nThen install deps:\n\n```shell\nyarn install\n```\n\nBuild loggers and ppx:\n\n```shell\ndune build\ncd lib \u0026\u0026 yarn run build\ncd ../examples \u0026\u0026 yarn run build\n```\n\n### Devbox flow\nClone repo and either enter the Devbox shell:\n\n```\ndevbox shell\n```\n\nOr use [`direnv`](https://direnv.net/) and create `.envrc` file in the root directory of the project by running:\n\n```\ndevbox generate direnv --print-envrc\n```\n\nThen install deps:\n\n```shell\nyarn install\n```\n\nBuild loggers and ppx:\n\n```shell\ndevbox run build\ncd lib \u0026\u0026 yarn run build\ncd ../examples \u0026\u0026 yarn run build\n```\n\n### Esy flow \nClone repo and install deps:\n\n```shell\nesy install\nyarn install\n```\n\nBuild loggers and ppx:\n\n```shell\nesy build\ncd lib \u0026\u0026 yarn run build\ncd ../examples \u0026\u0026 yarn run build\n```\n\n### Auto-formatting\nNote, this project doesn't use auto-formatting in OCaml files (`*.ml`), so if you're intended to contribute, please, turn off auto-formatting in the editor while editing such files.\n\n## Supporters\n\n\u003ca href=\"https://www.jetbrains.com\"\u003e\n  \u003cimg src=\"https://user-images.githubusercontent.com/4244251/184881139-42e4076b-024b-4b30-8c60-c3cd0e758c0a.png\" alt=\"JetBrains\" height=\"120px\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://scoutapp.com\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://user-images.githubusercontent.com/4244251/184881147-0d077438-3978-40da-ace9-4f650d2efe2e.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://user-images.githubusercontent.com/4244251/184881152-9f2d8fba-88ac-4ba6-873b-22387f8711c5.png\"\u003e\n    \u003cimg alt=\"ScoutAPM\" src=\"https://user-images.githubusercontent.com/4244251/184881152-9f2d8fba-88ac-4ba6-873b-22387f8711c5.png\" height=\"120px\"\u003e\n  \u003c/picture\u003e\n\u003c/a\u003e\n\u003cbr /\u003e\n\u003ca href=\"https://www.browserstack.com\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://user-images.githubusercontent.com/4244251/184881122-407dcc29-df78-4b20-a9ad-f597b56f6cdb.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://user-images.githubusercontent.com/4244251/184881129-e1edf4b7-3ae1-4ea8-9e6d-3595cf01609e.png\"\u003e\n    \u003cimg alt=\"BrowserStack\" src=\"https://user-images.githubusercontent.com/4244251/184881129-e1edf4b7-3ae1-4ea8-9e6d-3595cf01609e.png\" height=\"55px\"\u003e\n  \u003c/picture\u003e\n\u003c/a\u003e\n\u003ca href=\"https://railsautoscale.com\"\u003e\n  \u003cimg src=\"https://user-images.githubusercontent.com/4244251/184881144-95c2c25c-9879-4069-864d-4e67d6ed39d2.png\" alt=\"Rails Autoscale\" height=\"55px\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://www.honeybadger.io\"\u003e\n  \u003cimg src=\"https://user-images.githubusercontent.com/4244251/184881133-79ee9c3c-8165-4852-958e-31687b9536f4.png\" alt=\"Honeybadger\" height=\"55px\"\u003e\n\u003c/a\u003e\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\nThe following companies support our open source projects, and ShakaCode uses their products!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshakacode%2Frescript-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshakacode%2Frescript-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshakacode%2Frescript-logger/lists"}