If you are looking for help with the development and optimization of your project, ShakaCode can help you to take the reliability and performance of your app to the next level.
If you are a developer interested in working on ReScript / TypeScript / Rust / Ruby on Rails projects, we're hiring!
If you want to focus on logging from specific part(s) of your code, you can use RES_LOG_ONLY environment variable.
For example, if you want to see logs only from module Test, run the build as following:
RES_LOG_ONLY=Test rescript build
You can pass submodules and functions to it as well. If you want to log from multiple locations, separate them by ,.
Consider the following source:
// Test.res
%log.warn("Top level message")
module Submodule1 = {
%log.warn("Message from Submodule1")
}
module Submodule2 = {
%log.warn("Message from Submodule2")
let fn = () => %log.warn("Message from function within Submodule2")
fn()
}
Here is what will be logged with different build configurations:
# build
RES_LOG_ONLY=Test rescript build
# output
WARNING [Test] Top level message
WARNING [Test.Submodule1] Message from Submodule1
WARNING [Test.Submodule2] Message from Submodule2
WARNING [Test.Submodule2.fn] Message from function within Submodule2
# build
RES_LOG_ONLY=Test.Submodule2 rescript build
# output
WARNING [Test.Submodule2] Message from Submodule2
WARNING [Test.Submodule2.fn] Message from function within Submodule2
# build
RES_LOG_ONLY=Test.Submodule1,Test.Submodule2.fn rescript build
# output
WARNING [Test.Submodule1] Message from Submodule1
WARNING [Test.Submodule2.fn] Message from function within Submodule2
[@log] helper
This helper can be placed in front of any switch expression with constructor patterns and it will inject debug expressions into each branch.
// ReScript
let _ =
x =>
@log
switch x {
| A => "A"
| B(b) => b
}
// Reason
let _ =
x =>
[@log]
switch (x) {
| A => "A"
| B(b) => b
}
Without a @log helper, an equivalent would be:
// ReScript
let _ =
x =>
switch (x) {
| A =>
%log.debug("A")
"A"
| B(b) =>
%log.debug("B with payload" ("b", b))
b
}
// Reason
let _ =
x =>
switch (x) {
| A =>
[%log.debug "A"];
"A";
| B(b) =>
[%log.debug "B with payload"; ("b", b)];
b;
}
You can pass optional custom namespace to helper like this: @log("MyNamespace").
[@log] helper works only for switch expressions with constructor patterns, for now. Let us know in the issues if you need to handle more cases.
@rescript/react integration
Using @log helper, you can log dispatched actions in your components.
These entries are logged on the debug level so none of it will appear in your production builds.
Custom loggers
rescript-logger ships with 4 loggers:
ReScriptLogger.Browser (default)
ReScriptLogger.Node
ReScriptLogger.Edge (to use in edge environment, such as Cloudflare Workers)
ReScriptLogger.Universal (picks either Browser or Node logger at runtime depending on an environment, useful for apps with SSR)
And you can easily plug your own.
For 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.
To implement your own logger, you need to create a module (e.g. BugTracker.re) and set the following environment variables for production build.
RES_LOG=error
RES_LOGGER=BugTracker
Considering that you want to log only error level messages, you need to create functions only for errors logging.
// BugTracker.res
let error = (loc, msg) => BugTrackerSDK.notify(`${msg} in ${loc.rootModule}`)
let error1 =
(
loc,
msg,
(label, payload),
) =>
BugTrackerSDK.notify(
`${msg} in ${loc.rootModule}`,
[|(label, payload)|],
);
let error2 =
(
loc,
msg,
(label1, payload1),
(label2, payload2),
) =>
BugTrackerSDK.notify(
`${msg} in ${loc.rootModule}`,
[|
(label1, payload1),
(label2, payload2),
|],
);
// Up to 7
The first argument loc is a ReScriptLogger.Location.t record. It's passed by PPX and contains the location data.
type t = {
rootModule: string,
subModulePath: list<string>,
value: option<string>,
fullPath: string,
filePath: string,
}
If Test.Submodule.fn gets called, logger would receive the following location:
Note, 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.
Usage in libraries
If 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.
Once this flag is passed, you need to provide special value of RES_LOG to log your entries:
RES_LOG=my-lib=* rescript build
If 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:
RES_LOG=*,my-lib=error rescript build
Few more examples to illustrate how it works:
# log everything from application code only
RES_LOG=* rescript build
# log everything from application code# log errors from `my-lib`
RES_LOG=*,my-lib=error rescript build
# log everything from application code# log errors from `my-lib-1`# log warnings and errors from `my-lib-2`
RES_LOG=*,my-lib-1=error,my-lib-2=warn rescript build
Caveats
Logging is disabled after file save
If you run bsb via editor integration, make sure editor picked up RES_LOG variable. E.g. if you use Atom run it like this:
RES_LOG=info atom .
If your editor is telling you, variables used in ppx are unused, you can either:
prefix such variables with _
or open editor with RES_LOG variable set to appropriate level.
Changing value of RES_LOG/RES_LOGGER/RES_LOG_ONLY doesn't make any effect
When you change a value of environment variable, rescript clean before the next build.
Developing
Repo consists of 2 parts:
ReScript lib: dependencies are managed by yarn
OCaml PPX: dependencies are managed either by nix (in development) or esy (in development and/or on CI)
Nix flow
Clone repo and either enter the Nix shell:
nix-shell
Or use direnv and create .envrc file in the root directory of the project with the folowing content:
use nix
Then install deps:
yarn install
Build loggers and ppx:
dune build
cd lib && yarn run build
cd ../examples && yarn run build
Devbox flow
Clone repo and either enter the Devbox shell:
devbox shell
Or use direnv and create .envrc file in the root directory of the project by running:
devbox generate direnv --print-envrc
Then install deps:
yarn install
Build loggers and ppx:
devbox run build
cd lib && yarn run build
cd ../examples && yarn run build
Esy flow
Clone repo and install deps:
esy install
yarn install
Build loggers and ppx:
esy build
cd lib && yarn run build
cd ../examples && yarn run build
Auto-formatting
Note, 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.
Supporters
The following companies support our open source projects, and ShakaCode uses their products!
We found that rescript-logger demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.It has 1 open source maintainer collaborating on the project.
Package last updated on 28 Feb 2024
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Socket is joining TC54 to help develop standards for software supply chain security, contributing to the evolution of SBOMs, CycloneDX, and Package URL specifications.
Malicious npm package postcss-optimizer delivers BeaverTail malware, targeting developer systems; similarities to past campaigns suggest a North Korean connection.
By Kirill Boychenko, Peter van der Zee - Jan 29, 2025