├── .github
└── workflows
│ ├── ci.yml
│ └── scripts
│ ├── postinstall.js
│ └── write-package-json.js
├── .gitignore
├── HISTORY.md
├── README.md
├── devbox.json
├── devbox.lock
├── dune-project
├── dune-workspace
├── example.png
├── examples
├── package.json
├── rescript.json
└── src
│ └── ReScript.res
├── lib
├── package.json
├── rescript.json
└── src
│ ├── Interface.res
│ ├── Location.res
│ └── loggers
│ ├── Browser.res
│ ├── Browser.resi
│ ├── Edge.res
│ ├── Edge.resi
│ ├── Node.res
│ ├── Node.resi
│ ├── Universal.res
│ └── Universal.resi
├── package.json
├── ppx
├── bin
│ ├── Bin.ml
│ └── dune
└── lib
│ ├── Lib.ml
│ └── dune
├── rescript-logger-ppx.opam
├── windows.patch
└── yarn.lock
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | push:
8 | tags:
9 | - 'v*'
10 |
11 | jobs:
12 | validate:
13 | name: Validate
14 | runs-on: ubuntu-latest
15 | strategy:
16 | matrix:
17 | os: [ubuntu-latest]
18 | ocaml-version: [4.14.1]
19 | node-version: [16.x]
20 |
21 | steps:
22 | - name: Checkout repo
23 | uses: actions/checkout@v4
24 |
25 | - name: Setup Node ${{ matrix.node-version }}
26 | uses: actions/setup-node@v4
27 | with:
28 | node-version: ${{ matrix.node-version }}
29 |
30 | - name: Print Yarn cache
31 | id: print-yarn-cache
32 | run: echo "yarn-cache=$(yarn cache dir)" >> $GITHUB_OUTPUT
33 |
34 | - name: Restore Yarn cache
35 | id: yarn-cache
36 | uses: actions/cache@v4
37 | with:
38 | path: ${{ steps.print-yarn-cache.outputs.yarn-cache }}
39 | key: ${{ matrix.os }}-yarn-${{ hashFiles('yarn.lock', '*/yarn.lock') }}
40 |
41 | - name: Install Yarn deps
42 | run: yarn install
43 |
44 | - name: Setup OCaml ${{ matrix.ocaml-version }}
45 | uses: ocaml/setup-ocaml@v2
46 | with:
47 | ocaml-compiler: ${{ matrix.ocaml-version }}
48 |
49 | - name: Install Opam deps
50 | run: opam install . --deps-only --with-test
51 |
52 | - name: Build PPX
53 | run: opam exec -- dune build
54 |
55 | - name: Build ReScript lib
56 | run: |
57 | cd lib
58 | yarn run build
59 |
60 | - name: Build ReScript examples
61 | run: |
62 | cd examples
63 | yarn run build
64 |
65 | build_macos:
66 | name: Build on ${{ matrix.os }}
67 | runs-on: ${{ matrix.os }}
68 | if: startsWith(github.ref, 'refs/tags/v')
69 | needs:
70 | - validate
71 | strategy:
72 | matrix:
73 | os: [macos-13, macos-14]
74 | ocaml-version: [4.14.1]
75 | node-version: [16.x]
76 |
77 | steps:
78 | - name: Checkout repo
79 | uses: actions/checkout@v4
80 |
81 | - name: Setup Node ${{ matrix.node-version }}
82 | uses: actions/setup-node@v4
83 | with:
84 | node-version: ${{ matrix.node-version }}
85 |
86 | - name: Print Yarn cache
87 | id: print-yarn-cache
88 | run: echo "yarn-cache=$(yarn cache dir)" >> $GITHUB_OUTPUT
89 |
90 | - name: Restore Yarn cache
91 | id: yarn-cache
92 | uses: actions/cache@v4
93 | with:
94 | path: ${{ steps.print-yarn-cache.outputs.yarn-cache }}
95 | key: ${{ matrix.os }}-yarn-${{ hashFiles('yarn.lock', '*/yarn.lock') }}
96 |
97 | - name: Install Yarn deps
98 | run: yarn install
99 |
100 | - name: Setup OCaml ${{ matrix.ocaml-version }}
101 | uses: ocaml/setup-ocaml@v2
102 | with:
103 | ocaml-compiler: ${{ matrix.ocaml-version }}
104 |
105 | - name: Install Opam deps
106 | run: opam install . --deps-only --with-test
107 |
108 | - name: Build PPX
109 | run: opam exec -- dune build
110 |
111 | - name: Build ReScript lib
112 | run: |
113 | cd lib
114 | yarn run build
115 |
116 | - name: Build ReScript examples
117 | run: |
118 | cd examples
119 | yarn run build
120 |
121 | - name: Upload artifacts
122 | uses: actions/upload-artifact@v4
123 | with:
124 | name: ${{ matrix.os }}
125 | path: _build/default/ppx/bin/bin.exe
126 |
127 | build_linux:
128 | name: Build on ${{ matrix.container-os }}
129 | runs-on: ${{ matrix.host-os }}
130 | if: startsWith(github.ref, 'refs/tags/v')
131 | needs:
132 | - validate
133 | strategy:
134 | matrix:
135 | host-os: [ubuntu-latest]
136 | container-os: [linux-alpine-3]
137 | ocaml-version: [4.14.1]
138 | node-version: [16.x]
139 | container:
140 | image: alex35mil/alpine-ocaml-opam-node-yarn:alpine-3.19-ocaml-4.14-node-16.20-yarn-1.22-o5gm
141 |
142 | steps:
143 | - name: Checkout repo
144 | uses: actions/checkout@v4
145 |
146 | - name: Print Yarn cache
147 | id: print-yarn-cache
148 | run: echo "yarn-cache=$(yarn cache dir)" >> $GITHUB_OUTPUT
149 |
150 | - name: Restore Yarn cache
151 | id: yarn-cache
152 | uses: actions/cache@v4
153 | with:
154 | path: ${{ steps.print-yarn-cache.outputs.yarn-cache }}
155 | key: ${{ matrix.container-os }}-yarn-${{ hashFiles('yarn.lock', '*/yarn.lock') }}
156 |
157 | - name: Install Yarn deps
158 | run: yarn install
159 |
160 | - name: Setup OCaml ${{ matrix.ocaml-version }}
161 | run: opam init -a --disable-sandboxing --compiler=${{ matrix.ocaml-version }}
162 |
163 | - name: Install Opam deps
164 | run: opam install . --deps-only --with-test
165 |
166 | - name: Build PPX
167 | run: opam exec -- dune build --profile static
168 |
169 | - name: Build ReScript lib
170 | run: |
171 | cd lib
172 | yarn run build
173 |
174 | - name: Build ReScript examples
175 | run: |
176 | cd examples
177 | yarn run build
178 |
179 | - name: Upload artifacts
180 | uses: actions/upload-artifact@v4
181 | with:
182 | name: ${{ matrix.container-os }}
183 | path: _build/default/ppx/bin/bin.exe
184 |
185 | build_windows:
186 | name: Build on ${{ matrix.os }}
187 | runs-on: ${{ matrix.os }}
188 | if: startsWith(github.ref, 'refs/tags/v')
189 | needs:
190 | - validate
191 | strategy:
192 | matrix:
193 | os: [windows-latest]
194 | ocaml-version: [4.14.1]
195 | node-version: [16.x]
196 |
197 | steps:
198 | - name: Checkout repo
199 | uses: actions/checkout@v4
200 |
201 | - name: Setup Node ${{ matrix.node-version }}
202 | uses: actions/setup-node@v4
203 | with:
204 | node-version: ${{ matrix.node-version }}
205 |
206 | - name: Print Yarn cache
207 | id: print-yarn-cache
208 | run: echo "::set-output name=yarn-cache::$(yarn cache dir)" # Using the old way as the new way doesn't work on windows
209 |
210 | - name: Restore Yarn cache
211 | id: yarn-cache
212 | uses: actions/cache@v4
213 | with:
214 | path: ${{ steps.print-yarn-cache.outputs.yarn-cache }}
215 | key: ${{ matrix.os }}-yarn-${{ hashFiles('yarn.lock', '*/yarn.lock') }}
216 |
217 | - name: Install Yarn deps
218 | run: yarn install
219 |
220 | - name: Apply Opam deps patch
221 | run: |
222 | $lastCommitterName = git log -1 --pretty=format:'%an'
223 | $lastCommitterEmail = git log -1 --pretty=format:'%ae'
224 | git config user.name "$lastCommitterName"
225 | git config user.email "$lastCommitterEmail"
226 | git apply windows.patch
227 | git add .
228 | git commit -m "Patch opam deps"
229 |
230 | - name: Setup OCaml ${{ matrix.ocaml-version }}
231 | uses: ocaml/setup-ocaml@v2
232 | with:
233 | ocaml-compiler: ${{ matrix.ocaml-version }}
234 |
235 | - name: Pin Opam deps
236 | run: |
237 | opam pin add dune https://github.com/ocaml/dune.git#7cbb0e7 # 3.11.1
238 | opam pin add ppxlib https://github.com/ocaml-ppx/ppxlib.git#f0496c9 # 0.30.0
239 |
240 | - name: Install Opam deps
241 | run: opam install . --deps-only --with-test
242 |
243 | - name: Build PPX
244 | run: opam exec -- dune build
245 |
246 | - name: Build ReScript lib
247 | run: |
248 | cd lib
249 | yarn run build
250 |
251 | - name: Build ReScript examples
252 | run: |
253 | cd examples
254 | yarn run build
255 |
256 | - name: Upload artifacts
257 | uses: actions/upload-artifact@v4
258 | with:
259 | name: ${{ matrix.os }}
260 | path: _build/default/ppx/bin/bin.exe
261 |
262 | release:
263 | needs:
264 | - build_macos
265 | - build_linux
266 | - build_windows
267 | name: Release
268 | runs-on: ubuntu-latest
269 | if: startsWith(github.ref, 'refs/tags/v')
270 |
271 | steps:
272 | - name: Checkout repo
273 | uses: actions/checkout@v4
274 |
275 | - name: Setup Node ${{ matrix.node-version }}
276 | uses: actions/setup-node@v4
277 | with:
278 | node-version: 16.x
279 | registry-url: "https://registry.npmjs.org"
280 |
281 | - name: Download macOS x86 artifacts
282 | uses: actions/download-artifact@v4
283 | with:
284 | name: macos-13
285 | path: _bin/darwin/intel
286 |
287 | - name: Download macOS ARM artifacts
288 | uses: actions/download-artifact@v4
289 | with:
290 | name: macos-14
291 | path: _bin/darwin/arm
292 |
293 | - name: Download Linux artifacts
294 | uses: actions/download-artifact@v4
295 | with:
296 | name: linux-alpine-3
297 | path: _bin/linux
298 |
299 | - name: Download Windows artifacts
300 | uses: actions/download-artifact@v4
301 | with:
302 | name: windows-latest
303 | path: _bin/windows
304 |
305 | - name: Move artifacts
306 | run: |
307 | mkdir -p _release/bin
308 | mv _bin/darwin/intel/bin.exe _release/bin/rescript-logger-ppx-darwin-x64.exe
309 | mv _bin/darwin/arm/bin.exe _release/bin/rescript-logger-ppx-darwin-arm64.exe
310 | mv _bin/linux/bin.exe _release/bin/rescript-logger-ppx-linux-x64.exe
311 | mv _bin/windows/bin.exe _release/bin/rescript-logger-ppx-win-x64.exe
312 | rm -rf _bin
313 |
314 | - name: Move lib files
315 | run: |
316 | mkdir -p _release/src
317 | cp README.md _release/README.md
318 | cp lib/rescript.json _release/rescript.json
319 | cp -a lib/src/. _release/src/
320 | cp .github/workflows/scripts/postinstall.js _release/postinstall.js
321 | node .github/workflows/scripts/write-package-json.js
322 |
323 | - name: Upload release
324 | uses: actions/upload-artifact@v4
325 | with:
326 | name: release
327 | path: _release
328 |
329 | - name: Publish
330 | if: success()
331 | run: |
332 | cd _release
333 | npm publish
334 | env:
335 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
336 |
--------------------------------------------------------------------------------
/.github/workflows/scripts/postinstall.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const fs = require("fs");
4 |
5 | const PPX = "rescript-logger-ppx";
6 |
7 | let arch = process.arch;
8 | let platform = process.platform;
9 |
10 | if (arch === "ia32") {
11 | arch = "x86";
12 | }
13 |
14 | if (platform === "win32") {
15 | platform = "win";
16 | }
17 |
18 | const filename = `bin/${PPX}-${platform}-${arch}.exe`;
19 |
20 | const supported = fs.existsSync(filename);
21 |
22 | if (!supported) {
23 | console.error(`${PPX} does not support this platform :(`);
24 | console.error("");
25 | console.error(`${PPX} comes prepacked as built binaries to avoid large`);
26 | console.error("dependencies at build-time.");
27 | console.error("");
28 | console.error(`If you want ${PPX} to support this platform natively,`);
29 | console.error("please open an issue at our repository, linked above. Please");
30 | console.error(`specify that you are on the ${platform} platform,`);
31 | console.error(`on the ${arch} architecture.`);
32 |
33 | }
34 |
35 | if (!fs.existsSync("ppx.exe")) {
36 | copyFileSync(filename, "ppx.exe");
37 | fs.chmodSync("ppx.exe", 0755);
38 | }
39 |
40 | if (!fs.existsSync("ppx")) {
41 | copyFileSync(filename, "ppx");
42 | fs.chmodSync("ppx", 0755);
43 | }
44 |
45 | function copyFileSync(source, dest) {
46 | if (typeof fs.copyFileSync === "function") {
47 | fs.copyFileSync(source, dest);
48 | } else {
49 | fs.writeFileSync(dest, fs.readFileSync(source));
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/.github/workflows/scripts/write-package-json.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 |
4 | const {
5 | name,
6 | version,
7 | description,
8 | author,
9 | license,
10 | repository,
11 | files,
12 | peerDependencies,
13 | keywords
14 | } = require("../../../package.json");
15 |
16 | const packageJson = JSON.stringify(
17 | {
18 | name,
19 | version,
20 | description,
21 | author,
22 | license,
23 | repository,
24 | files,
25 | peerDependencies,
26 | keywords,
27 | scripts: {
28 | postinstall: "node ./postinstall.js"
29 | }
30 | },
31 | null,
32 | 2
33 | );
34 |
35 | fs.writeFileSync(
36 | path.join(__dirname, "..", "..", "..", "_release", "package.json"),
37 | packageJson,
38 | { encoding: "utf8" }
39 | );
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .direnv/
3 | .devbox/
4 | .vscode/
5 | .envrc
6 | .cache
7 | .merlin
8 | .bsb.lock
9 | *.res.js
10 | .DS_Store
11 | /_build
12 | /_release
13 | /lib/lib/
14 | /examples/lib/
15 | rescript-logger-ppx.install
16 |
--------------------------------------------------------------------------------
/HISTORY.md:
--------------------------------------------------------------------------------
1 | # History
2 | ## UNRELEASED
3 |
4 | ## 4.0.0
5 | - Update to ReScript 11.
6 | - Add `Edge` logger.
7 | - **[BREAKING]** Remove Linux `arm64` binary.
8 |
9 | ## 3.1.0
10 | - Add Linux `arm64` binary.
11 |
12 | ## 3.0.0
13 | - **[BREAKING]** Remove `filePath` from `Location.t`.
14 | - Upgrade to `rescript@10`.
15 |
16 | ## 2.2.0
17 | - Add universal logger (`ReScriptLogger.Universal`). Useful for apps with SSR.
18 |
19 | ## 2.1.0
20 | - Add native `arm64` support.
21 |
22 | ## 2.0.2
23 | - Remove `bs-platform` peer dependency.
24 |
25 | ## 2.0.1
26 | - Add support for M1 Macs through Rosetta [#28](https://github.com/shakacode/rescript-logger/pull/28).
27 |
28 | ## 2.0.0
29 | - Package renamed to `rescript-logger` and converted to `ReScript` syntax.
30 | - Default loggers namespaced and renamed:
31 | - `BrowserLogger` -> `ReScriptLogger.Browser`
32 | - `NodeLogger` -> `ReScriptLogger.Node`
33 | - Environment variables renamed:
34 | - `BS_LOG` -> `RES_LOG`
35 | - `BS_LOGGER` -> `RES_LOGGER`
36 | - Added environment variable `RES_LOG_ONLY`. It allows logging only from specific locations in code.
37 | E.g. `RES_LOG_ONLY=Module.Submodule.fn bsb ...`
38 | See [`Verbosity customization > Code location`](./README.md#code-location).
39 | - Each log entry produced by default loggers is prefixed with full location from where it's been called.
40 | E.g. `[Module.Submodule.fn] ...`
41 | - Logger interface changed (pay attention if you have custom loggers in your codebase):
42 | - Logger function `WithData` renamed to `1`
43 | - Logger function `WithData` renamed to ``
44 | - Each logger function receives `Location.t` record instead of a `__MODULE__` string. See [`Custom loggers`](./README.md#custom-loggers).
45 |
46 | ## 1.3.0
47 | - Add `Trace` level.
48 | - Ensure PPX binary is available on all platforms.
49 |
50 | ## 1.2.0
51 | - Make logging event polymorphic in `BrowserLogger` and `NodeLogger`.
52 |
53 | ## 1.1.0
54 | - Logging in libraries.
55 |
56 | ## 1.0.0
57 | - BuckleScript v7 support.
58 | - Make `warn` default log level for situations when `BS_LOG` env var doesn't exist.
59 | - Fix postinstall script for Windows.
60 |
61 | ## 0.1.1
62 | - Fix Windows build.
63 |
64 | ## 0.1.0
65 | - Prefix all log entries with value of a `__MODULE__` variable.
66 | - Update PPX setup.
67 |
68 | ## 0.0.9
69 | - Default logger renamed from `Console` to `BrowserLogger`.
70 | - Added `NodeLogger`.
71 |
72 | ## 0.0.8
73 | - Make `[@log]` annotation generic: it can be placed in front of any `switch` expression with constructors.
74 | - `[@log]` can accept optional namespace: `[@log "MyNamespace"]`.
75 |
76 | ## 0.0.7
77 | - Allow log statements inside annotated reducers.
78 |
79 | ## 0.0.6
80 | - Use default logger when `BS_LOGGER` is empty string.
81 |
82 | ## 0.0.5
83 | - Add `BS_LOGGER` environment variable.
84 | - Rename default logger from `Log` to `Console`.
85 |
86 | ## 0.0.4
87 | React logger.
88 |
89 | ## 0.0.3
90 | Lots of changes, hope nobody used it yet.
91 |
92 | ## 0.0.2
93 | Package renamed to `bs-log`.
94 |
95 | ## 0.0.1
96 | Initial release.
97 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rescript-logger
2 |
3 | [](https://www.npmjs.com/package/rescript-logger)
4 | [](https://www.npmjs.com/package/rescript-logger)
5 |
6 | Logging implementation for [ReScript](https://rescript-lang.org).
7 |
8 | 
9 |
10 | ## Features
11 | - Zero runtime in production builds.
12 | - Multiple logging levels.
13 | - Customizable verbosity.
14 | - `[@log]` helper.
15 | - [`@rescript/react`](https://github.com/rescript-lang/rescript-react) integration.
16 | - Custom loggers.
17 | - Logging in libraries.
18 |
19 | > ### ShakaCode
20 | > 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.
21 | >
22 | > If you are a developer interested in working on ReScript / TypeScript / Rust / Ruby on Rails projects, [we're hiring](https://www.shakacode.com/career/)!
23 |
24 | ## Installation
25 | Get the package:
26 |
27 | ```shell
28 | # yarn
29 | yarn add rescript-logger
30 | # or npm
31 | npm install --save rescript-logger
32 | ```
33 |
34 | Then add it to `bsconfig.json`:
35 |
36 | ```json
37 | "bs-dependencies": [
38 | "rescript-logger"
39 | ],
40 | "ppx-flags": ["rescript-logger/ppx"]
41 | ```
42 |
43 | ## Usage
44 | There are 5 log levels:
45 | - `trace`
46 | - `debug`
47 | - `info`
48 | - `warn`
49 | - `error`
50 |
51 | You can log message of specific level using appropriate macros:
52 |
53 | ```reason
54 | // ReScript
55 | %log.info("Info message")
56 | %log.error("Error message")
57 |
58 | // Reason
59 | [%log.info "Info message"];
60 | [%log.error "Error message"];
61 | ```
62 |
63 | ### Additional data
64 | You can add data to log entry like this:
65 |
66 | ```reason
67 | // ReScript
68 | %log.info(
69 | "Info message"
70 | ("Foo", 42)
71 | )
72 | %log.info(
73 | "Info message"
74 | ("Foo", {x: 42})
75 | ("Bar", [1, 2, 3])
76 | )
77 |
78 | // Reason
79 | [%log.info "Info message"; ("Foo", 42)];
80 | [%log.info
81 | "Info message";
82 | ("Foo", {x: 42});
83 | ("Bar", [1, 2, 3]);
84 | ];
85 | ```
86 |
87 | Currently, logger can accept up to 7 additional entries.
88 |
89 | ### Verbosity customization
90 | Output verbosity can be customized by providing specific **log level** and/or **code locations**.
91 |
92 | #### Log level
93 | You can set maximum log level via environment variable `RES_LOG`.
94 |
95 | Let's say you want to log only warnings and errors. To make it happen, run your build like this:
96 |
97 | ```shell
98 | RES_LOG=warn rescript build
99 | ```
100 |
101 | Available `RES_LOG` values:
102 | - `*`: log everything
103 | - `trace`: basically, the same as `*`
104 | - `debug`: log everything except `trace` level messages
105 | - `info`: log everything except `trace` & `debug` level messages
106 | - `warn`: log `warn` & `error` messages only
107 | - `error`: log `error` messages only
108 | - `off`: don't log anything
109 |
110 | If `RES_LOG` is set to `off`, nothing will be logged and none of the log entries will appear in your JS assets.
111 |
112 | In case if `RES_LOG` environment variable is not set, log level `warn` will be used.
113 |
114 | Also, see [Usage in libraries](#usage-in-libraries).
115 |
116 | #### Code location
117 | If you want to focus on logging from specific part(s) of your code, you can use `RES_LOG_ONLY` environment variable.
118 |
119 | For example, if you want to see logs only from module `Test`, run the build as following:
120 |
121 | ```shell
122 | RES_LOG_ONLY=Test rescript build
123 | ```
124 |
125 | You can pass submodules and functions to it as well. If you want to log from multiple locations, separate them by `,`.
126 |
127 | Consider the following source:
128 |
129 | ```reason
130 | // Test.res
131 | %log.warn("Top level message")
132 |
133 | module Submodule1 = {
134 | %log.warn("Message from Submodule1")
135 | }
136 |
137 | module Submodule2 = {
138 | %log.warn("Message from Submodule2")
139 |
140 | let fn = () => %log.warn("Message from function within Submodule2")
141 | fn()
142 | }
143 | ```
144 |
145 | Here is what will be logged with different build configurations:
146 |
147 | ```
148 | # build
149 | RES_LOG_ONLY=Test rescript build
150 |
151 | # output
152 | WARNING [Test] Top level message
153 | WARNING [Test.Submodule1] Message from Submodule1
154 | WARNING [Test.Submodule2] Message from Submodule2
155 | WARNING [Test.Submodule2.fn] Message from function within Submodule2
156 |
157 | # build
158 | RES_LOG_ONLY=Test.Submodule2 rescript build
159 |
160 | # output
161 | WARNING [Test.Submodule2] Message from Submodule2
162 | WARNING [Test.Submodule2.fn] Message from function within Submodule2
163 |
164 | # build
165 | RES_LOG_ONLY=Test.Submodule1,Test.Submodule2.fn rescript build
166 |
167 | # output
168 | WARNING [Test.Submodule1] Message from Submodule1
169 | WARNING [Test.Submodule2.fn] Message from function within Submodule2
170 | ```
171 |
172 | ### `[@log]` helper
173 | This helper can be placed in front of any `switch` expression with constructor patterns and it will inject debug expressions into each branch.
174 |
175 | ```reason
176 | // ReScript
177 | let _ =
178 | x =>
179 | @log
180 | switch x {
181 | | A => "A"
182 | | B(b) => b
183 | }
184 |
185 | // Reason
186 | let _ =
187 | x =>
188 | [@log]
189 | switch (x) {
190 | | A => "A"
191 | | B(b) => b
192 | }
193 | ```
194 |
195 | Without a `@log` helper, an equivalent would be:
196 |
197 | ```reason
198 | // ReScript
199 | let _ =
200 | x =>
201 | switch (x) {
202 | | A =>
203 | %log.debug("A")
204 | "A"
205 | | B(b) =>
206 | %log.debug("B with payload" ("b", b))
207 | b
208 | }
209 |
210 | // Reason
211 | let _ =
212 | x =>
213 | switch (x) {
214 | | A =>
215 | [%log.debug "A"];
216 | "A";
217 | | B(b) =>
218 | [%log.debug "B with payload"; ("b", b)];
219 | b;
220 | }
221 | ```
222 |
223 | You can pass optional custom namespace to helper like this: `@log("MyNamespace")`.
224 |
225 | `[@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.
226 |
227 | ### `@rescript/react` integration
228 | Using `@log` helper, you can log dispatched actions in your components.
229 |
230 | Annotate `reducer` function like this:
231 |
232 | ```reason
233 | // ReScript
234 | let reducer =
235 | (state, action) =>
236 | @log
237 | switch action {
238 | ...
239 | }
240 |
241 | // Reason
242 | let reducer =
243 | (state, action) =>
244 | [@log]
245 | switch (action) {
246 | ...
247 | }
248 | ```
249 |
250 | These entries are logged on the `debug` level so none of it will appear in your production builds.
251 |
252 | ### Custom loggers
253 | `rescript-logger` ships with 4 loggers:
254 | - `ReScriptLogger.Browser` (default)
255 | - `ReScriptLogger.Node`
256 | - `ReScriptLogger.Edge` (to use in edge environment, such as Cloudflare Workers)
257 | - `ReScriptLogger.Universal` (picks either `Browser` or `Node` logger at runtime depending on an environment, useful for apps with SSR)
258 |
259 | And you can easily plug your own.
260 |
261 | 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.
262 |
263 | To implement your own logger, you need to create a module (e.g. `BugTracker.re`) and set the following environment variables for production build.
264 |
265 | ```
266 | RES_LOG=error
267 | RES_LOGGER=BugTracker
268 | ```
269 |
270 | Considering that you want to log only `error` level messages, you need to create functions only for errors logging.
271 |
272 | ```reason
273 | // BugTracker.res
274 |
275 | let error = (loc, msg) => BugTrackerSDK.notify(`${msg} in ${loc.rootModule}`)
276 |
277 | let error1 =
278 | (
279 | loc,
280 | msg,
281 | (label, payload),
282 | ) =>
283 | BugTrackerSDK.notify(
284 | `${msg} in ${loc.rootModule}`,
285 | [|(label, payload)|],
286 | );
287 |
288 | let error2 =
289 | (
290 | loc,
291 | msg,
292 | (label1, payload1),
293 | (label2, payload2),
294 | ) =>
295 | BugTrackerSDK.notify(
296 | `${msg} in ${loc.rootModule}`,
297 | [|
298 | (label1, payload1),
299 | (label2, payload2),
300 | |],
301 | );
302 |
303 | // Up to 7
304 | ```
305 |
306 | The first argument `loc` is a `ReScriptLogger.Location.t` record. It's passed by PPX and contains the location data.
307 |
308 | ```reason
309 | type t = {
310 | rootModule: string,
311 | subModulePath: list,
312 | value: option,
313 | fullPath: string,
314 | filePath: string,
315 | }
316 | ```
317 |
318 | If `Test.Submodule.fn` gets called, logger would receive the following location:
319 |
320 | ```reason
321 | // Test.res
322 | module Submodule = {
323 | let fn = () => %log.warn("Warn!")
324 | }
325 |
326 | // Location
327 | {
328 | rootModule: "Test",
329 | subModulePath: list{"Submodule"},
330 | value: Some("fn"),
331 | fullPath: "Test.Submodule.fn",
332 | filePath: "/absolute/path/to/project/src/Test.res",
333 | }
334 | ```
335 |
336 | ---
337 | 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.
338 |
339 | ### Usage in libraries
340 | 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.
341 |
342 | `rescript-logger/ppx` accepts `--lib` flag:
343 |
344 | ```json
345 | "ppx-flags": [
346 | ["rescript-logger/ppx", "--lib=my-lib"]
347 | ]
348 | ```
349 |
350 | Once this flag is passed, you need to provide special value of `RES_LOG` to log your entries:
351 |
352 | ```shell
353 | RES_LOG=my-lib=* rescript build
354 | ```
355 |
356 | 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:
357 |
358 | ```shell
359 | RES_LOG=*,my-lib=error rescript build
360 | ```
361 |
362 | Few more examples to illustrate how it works:
363 |
364 | ```shell
365 | # log everything from application code only
366 | RES_LOG=* rescript build
367 |
368 | # log everything from application code
369 | # log errors from `my-lib`
370 | RES_LOG=*,my-lib=error rescript build
371 |
372 | # log everything from application code
373 | # log errors from `my-lib-1`
374 | # log warnings and errors from `my-lib-2`
375 | RES_LOG=*,my-lib-1=error,my-lib-2=warn rescript build
376 | ```
377 |
378 | ## Caveats
379 | **Logging is disabled after file save**
380 | 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:
381 |
382 | ```shell
383 | RES_LOG=info atom .
384 | ```
385 |
386 | If your editor is telling you, variables used in ppx are unused, you can either:
387 | 1. prefix such variables with `_`
388 | 2. or open editor with `RES_LOG` variable set to appropriate level.
389 |
390 | **Changing value of `RES_LOG`/`RES_LOGGER`/`RES_LOG_ONLY` doesn't make any effect**
391 | When you change a value of environment variable, `rescript clean` before the next build.
392 |
393 | ## Developing
394 | Repo consists of 2 parts:
395 | - ReScript lib: dependencies are managed by `yarn`
396 | - OCaml PPX: dependencies are managed either by `nix` (in development) or `esy` (in development and/or on CI)
397 |
398 | ### Nix flow
399 | Clone repo and either enter the Nix shell:
400 |
401 | ```
402 | nix-shell
403 | ```
404 |
405 | Or use [`direnv`](https://direnv.net/) and create `.envrc` file in the root directory of the project with the folowing content:
406 |
407 | ```
408 | use nix
409 | ```
410 |
411 | Then install deps:
412 |
413 | ```shell
414 | yarn install
415 | ```
416 |
417 | Build loggers and ppx:
418 |
419 | ```shell
420 | dune build
421 | cd lib && yarn run build
422 | cd ../examples && yarn run build
423 | ```
424 |
425 | ### Devbox flow
426 | Clone repo and either enter the Devbox shell:
427 |
428 | ```
429 | devbox shell
430 | ```
431 |
432 | Or use [`direnv`](https://direnv.net/) and create `.envrc` file in the root directory of the project by running:
433 |
434 | ```
435 | devbox generate direnv --print-envrc
436 | ```
437 |
438 | Then install deps:
439 |
440 | ```shell
441 | yarn install
442 | ```
443 |
444 | Build loggers and ppx:
445 |
446 | ```shell
447 | devbox run build
448 | cd lib && yarn run build
449 | cd ../examples && yarn run build
450 | ```
451 |
452 | ### Esy flow
453 | Clone repo and install deps:
454 |
455 | ```shell
456 | esy install
457 | yarn install
458 | ```
459 |
460 | Build loggers and ppx:
461 |
462 | ```shell
463 | esy build
464 | cd lib && yarn run build
465 | cd ../examples && yarn run build
466 | ```
467 |
468 | ### Auto-formatting
469 | 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.
470 |
471 | ## Supporters
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 | The following companies support our open source projects, and ShakaCode uses their products!
502 |
--------------------------------------------------------------------------------
/devbox.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "ocamlPackages.ocaml",
4 | "ocamlPackages.dune_3",
5 | "ocamlPackages.findlib",
6 | "ocamlPackages.ppxlib",
7 | "ocamlPackages.alcotest",
8 | "ocamlPackages.ocaml-lsp",
9 | "nodejs",
10 | "yarn"
11 | ],
12 | "shell": {
13 | "init_hook": [
14 | "export PATH=$PATH:node_modules/.bin"
15 | ],
16 | "scripts": {
17 | "build": "dune build",
18 | "test": "dune exec test.exe"
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/devbox.lock:
--------------------------------------------------------------------------------
1 | {
2 | "lockfile_version": "1",
3 | "packages": {
4 | "nodejs": {
5 | "resolved": "github:NixOS/nixpkgs/f80ac848e3d6f0c12c52758c0f25c10c97ca3b62#nodejs",
6 | "source": "nixpkg"
7 | },
8 | "ocamlPackages.alcotest": {
9 | "resolved": "github:NixOS/nixpkgs/75a52265bda7fd25e06e3a67dee3f0354e73243c#ocamlPackages.alcotest",
10 | "source": "nixpkg"
11 | },
12 | "ocamlPackages.dune_3": {
13 | "resolved": "github:NixOS/nixpkgs/75a52265bda7fd25e06e3a67dee3f0354e73243c#ocamlPackages.dune_3",
14 | "source": "nixpkg"
15 | },
16 | "ocamlPackages.findlib": {
17 | "resolved": "github:NixOS/nixpkgs/75a52265bda7fd25e06e3a67dee3f0354e73243c#ocamlPackages.findlib",
18 | "source": "nixpkg"
19 | },
20 | "ocamlPackages.ocaml": {
21 | "resolved": "github:NixOS/nixpkgs/75a52265bda7fd25e06e3a67dee3f0354e73243c#ocamlPackages.ocaml",
22 | "source": "nixpkg"
23 | },
24 | "ocamlPackages.ocaml-lsp": {
25 | "resolved": "github:NixOS/nixpkgs/75a52265bda7fd25e06e3a67dee3f0354e73243c#ocamlPackages.ocaml-lsp",
26 | "source": "nixpkg"
27 | },
28 | "ocamlPackages.ppxlib": {
29 | "resolved": "github:NixOS/nixpkgs/75a52265bda7fd25e06e3a67dee3f0354e73243c#ocamlPackages.ppxlib",
30 | "source": "nixpkg"
31 | },
32 | "yarn": {
33 | "resolved": "github:NixOS/nixpkgs/f80ac848e3d6f0c12c52758c0f25c10c97ca3b62#yarn",
34 | "source": "nixpkg"
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/dune-project:
--------------------------------------------------------------------------------
1 | (lang dune 2.6)
2 | (name rescript-logger-ppx)
3 |
--------------------------------------------------------------------------------
/dune-workspace:
--------------------------------------------------------------------------------
1 | (lang dune 2.6)
2 |
--------------------------------------------------------------------------------
/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakacode/rescript-logger/ec688eadb1513991aa084380cf4013f7500d14b4/example.png
--------------------------------------------------------------------------------
/examples/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rescript-logger-examples",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "build": "rescript build"
7 | },
8 | "devDependencies": {
9 | "rescript": "11.0.1",
10 | "rescript-logger": "*"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/examples/rescript.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rescript-logger-examples",
3 | "sources": [
4 | {
5 | "dir": "src",
6 | "subdirs": true
7 | }
8 | ],
9 | "bs-dependencies": [
10 | "rescript-logger"
11 | ],
12 | "package-specs": {
13 | "module": "es6",
14 | "in-source": true
15 | },
16 | "ppx-flags": [
17 | [
18 | "../_build/default/ppx/bin/bin.exe"
19 | ]
20 | ],
21 | "suffix": ".res.js"
22 | }
23 |
--------------------------------------------------------------------------------
/examples/src/ReScript.res:
--------------------------------------------------------------------------------
1 | let something = Some("thing")
2 |
3 | %log.trace("Trace message")
4 | %log.trace(
5 | "Trace message"
6 | ("1", 42)
7 | )
8 | %log.trace(
9 | "Trace message"
10 | ("1", 42)
11 | ("2", {"x": 42})
12 | )
13 | %log.trace(
14 | "Trace message"
15 | ("1", 42)
16 | ("2", {"x": 42})
17 | ("3", something)
18 | )
19 | %log.trace(
20 | "Trace message"
21 | ("1", 42)
22 | ("2", {"x": 42})
23 | ("3", something)
24 | ("4", list{1, 2, 4})
25 | )
26 | %log.trace(
27 | "Trace message"
28 | ("1", 42)
29 | ("2", {"x": 42})
30 | ("3", something)
31 | ("4", list{1, 2, 4})
32 | ("5", [1, 2, 4])
33 | )
34 | %log.trace(
35 | "Trace message"
36 | ("1", 42)
37 | ("2", {"x": 42})
38 | ("3", something)
39 | ("4", list{1, 2, 4})
40 | ("5", [1, 2, 4])
41 | ("6", true)
42 | )
43 | %log.trace(
44 | "Trace message"
45 | ("1", 42)
46 | ("2", {"x": 42})
47 | ("3", something)
48 | ("4", list{1, 2, 4})
49 | ("5", [1, 2, 4])
50 | ("6", true)
51 | ("7", #x)
52 | )
53 |
54 | %log.debug("Debug message")
55 | %log.debug(
56 | "Debug message"
57 | ("1", 42)
58 | )
59 | %log.debug(
60 | "Debug message"
61 | ("1", 42)
62 | ("2", {"x": 42})
63 | )
64 | %log.debug(
65 | "Debug message"
66 | ("1", 42)
67 | ("2", {"x": 42})
68 | ("3", something)
69 | )
70 | %log.debug(
71 | "Debug message"
72 | ("1", 42)
73 | ("2", {"x": 42})
74 | ("3", something)
75 | ("4", list{1, 2, 4})
76 | )
77 | %log.debug(
78 | "Debug message"
79 | ("1", 42)
80 | ("2", {"x": 42})
81 | ("3", something)
82 | ("4", list{1, 2, 4})
83 | ("5", [1, 2, 4])
84 | )
85 | %log.debug(
86 | "Debug message"
87 | ("1", 42)
88 | ("2", {"x": 42})
89 | ("3", something)
90 | ("4", list{1, 2, 4})
91 | ("5", [1, 2, 4])
92 | ("6", true)
93 | )
94 | %log.debug(
95 | "Debug message"
96 | ("1", 42)
97 | ("2", {"x": 42})
98 | ("3", something)
99 | ("4", list{1, 2, 4})
100 | ("5", [1, 2, 4])
101 | ("6", true)
102 | ("7", #x)
103 | )
104 |
105 | %log.info("Info message")
106 | %log.info(
107 | "Info message"
108 | ("1", 42)
109 | )
110 | %log.info(
111 | "Info message"
112 | ("1", 42)
113 | ("2", {"x": 42})
114 | )
115 | %log.info(
116 | "Info message"
117 | ("1", 42)
118 | ("2", {"x": 42})
119 | ("3", something)
120 | )
121 | %log.info(
122 | "Info message"
123 | ("1", 42)
124 | ("2", {"x": 42})
125 | ("3", something)
126 | ("4", list{1, 2, 4})
127 | )
128 | %log.info(
129 | "Info message"
130 | ("1", 42)
131 | ("2", {"x": 42})
132 | ("3", something)
133 | ("4", list{1, 2, 4})
134 | ("5", [1, 2, 4])
135 | )
136 | %log.info(
137 | "Info message"
138 | ("1", 42)
139 | ("2", {"x": 42})
140 | ("3", something)
141 | ("4", list{1, 2, 4})
142 | ("5", [1, 2, 4])
143 | ("6", true)
144 | )
145 | %log.info(
146 | "Info message"
147 | ("1", 42)
148 | ("2", {"x": 42})
149 | ("3", something)
150 | ("4", list{1, 2, 4})
151 | ("5", [1, 2, 4])
152 | ("6", true)
153 | ("7", #x)
154 | )
155 |
156 | %log.warn("Warn message")
157 | %log.warn(
158 | "Warn message"
159 | ("1", 42)
160 | )
161 | %log.warn(
162 | "Warn message"
163 | ("1", 42)
164 | ("2", {"x": 42})
165 | )
166 | %log.warn(
167 | "Warn message"
168 | ("1", 42)
169 | ("2", {"x": 42})
170 | ("3", something)
171 | )
172 | %log.warn(
173 | "Warn message"
174 | ("1", 42)
175 | ("2", {"x": 42})
176 | ("3", something)
177 | ("4", list{1, 2, 4})
178 | )
179 | %log.warn(
180 | "Warn message"
181 | ("1", 42)
182 | ("2", {"x": 42})
183 | ("3", something)
184 | ("4", list{1, 2, 4})
185 | ("5", [1, 2, 4])
186 | )
187 | %log.warn(
188 | "Warn message"
189 | ("1", 42)
190 | ("2", {"x": 42})
191 | ("3", something)
192 | ("4", list{1, 2, 4})
193 | ("5", [1, 2, 4])
194 | ("6", true)
195 | )
196 | %log.warn(
197 | "Warn message"
198 | ("1", 42)
199 | ("2", {"x": 42})
200 | ("3", something)
201 | ("4", list{1, 2, 4})
202 | ("5", [1, 2, 4])
203 | ("6", true)
204 | ("7", #x)
205 | )
206 |
207 | %log.error("Error message")
208 | %log.error(
209 | "Error message"
210 | ("1", 42)
211 | )
212 | %log.error(
213 | "Error message"
214 | ("1", 42)
215 | ("2", {"x": 42})
216 | )
217 | %log.error(
218 | "Error message"
219 | ("1", 42)
220 | ("2", {"x": 42})
221 | ("3", something)
222 | )
223 | %log.error(
224 | "Error message"
225 | ("1", 42)
226 | ("2", {"x": 42})
227 | ("3", something)
228 | ("4", list{1, 2, 4})
229 | )
230 | %log.error(
231 | "Error message"
232 | ("1", 42)
233 | ("2", {"x": 42})
234 | ("3", something)
235 | ("4", list{1, 2, 4})
236 | ("5", [1, 2, 4])
237 | )
238 | %log.error(
239 | "Error message"
240 | ("1", 42)
241 | ("2", {"x": 42})
242 | ("3", something)
243 | ("4", list{1, 2, 4})
244 | ("5", [1, 2, 4])
245 | ("6", true)
246 | )
247 | %log.error(
248 | "Error message"
249 | ("1", 42)
250 | ("2", {"x": 42})
251 | ("3", something)
252 | ("4", list{1, 2, 4})
253 | ("5", [1, 2, 4])
254 | ("6", true)
255 | ("7", #x)
256 | )
257 |
258 | module Inner = {
259 | %log.error("Error message in module")
260 |
261 | let fn = x => {
262 | %log.error(
263 | "Error message in module within a function"
264 | ("X", x)
265 | )
266 | x
267 | }
268 | }
269 |
270 | module Very = {
271 | module Deep = {
272 | module Module = {
273 | %log.info("Info message from the Very.Deep.Module")
274 | }
275 | }
276 | }
277 |
278 | type state
279 | type action =
280 | | A
281 | | B(string)
282 | | C(string, string)
283 | | D(string, string, string)
284 | | E(string, string, string, string)
285 | | F(string, string, string, string, string)
286 | | G(string, string, string, string, string, string)
287 | | H(string, string, string, string, string, string, string)
288 | type component = {reducer: (action, state) => string}
289 | let make = {
290 | reducer: (action, _state) =>
291 | @log
292 | switch action {
293 | | A => "a"
294 | | B(x) =>
295 | %log.trace(
296 | "Ext"
297 | ("within", "@log")
298 | )
299 | x
300 | | C(_x1, x2) => x2
301 | | D(_x1, _x2, x3) => x3
302 | | E(_x1, _x2, _x3, x4) => x4
303 | | F(_x1, _x2, _x3, _x4, x5) => x5
304 | | G(_x1, _x2, _x3, _x4, _x5, x6) => x6
305 | | H(_x1, _x2, _x3, _x4, _x5, _x6, x7) => x7
306 | },
307 | }
308 |
309 | type ns =
310 | | A
311 | | B(string)
312 | | C(int)
313 | let ns = x =>
314 | @log("Namespace")
315 | switch x {
316 | | A => "A"
317 | | B(x) => x
318 | | C(_) => "C"
319 | }
320 | let s: string = ns(B("b"))
321 |
322 | let noop = x =>
323 | @log
324 | switch x {
325 | | "" => "a"
326 | | _ => "b"
327 | }
328 |
--------------------------------------------------------------------------------
/lib/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rescript-logger",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "rescript build -w",
7 | "build": "rescript build"
8 | },
9 | "devDependencies": {
10 | "rescript": "11.0.1"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/rescript.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rescript-logger",
3 | "namespace": "ReScriptLogger",
4 | "sources": [
5 | {
6 | "dir": "src",
7 | "subdirs": true
8 | }
9 | ],
10 | "package-specs": {
11 | "module": "es6",
12 | "in-source": true
13 | },
14 | "suffix": ".res.js"
15 | }
16 |
--------------------------------------------------------------------------------
/lib/src/Interface.res:
--------------------------------------------------------------------------------
1 | module type Logger = {
2 | let trace: (Location.t, 'x) => unit
3 | let trace1: (Location.t, 'x, (string, 'x1)) => unit
4 | let trace2: (Location.t, 'x, (string, 'x1), (string, 'x2)) => unit
5 | let trace3: (Location.t, 'x, (string, 'x1), (string, 'x2), (string, 'x3)) => unit
6 | let trace4: (Location.t, 'x, (string, 'x1), (string, 'x2), (string, 'x3), (string, 'x4)) => unit
7 | let trace5: (
8 | Location.t,
9 | 'x,
10 | (string, 'x1),
11 | (string, 'x2),
12 | (string, 'x3),
13 | (string, 'x4),
14 | (string, 'x5),
15 | ) => unit
16 | let trace6: (
17 | Location.t,
18 | 'x,
19 | (string, 'x1),
20 | (string, 'x2),
21 | (string, 'x3),
22 | (string, 'x4),
23 | (string, 'x5),
24 | (string, 'x6),
25 | ) => unit
26 | let trace7: (
27 | Location.t,
28 | 'x,
29 | (string, 'x1),
30 | (string, 'x2),
31 | (string, 'x3),
32 | (string, 'x4),
33 | (string, 'x5),
34 | (string, 'x6),
35 | (string, 'x7),
36 | ) => unit
37 |
38 | let debug: (Location.t, 'x) => unit
39 | let debug1: (Location.t, 'x, (string, 'x1)) => unit
40 | let debug2: (Location.t, 'x, (string, 'x1), (string, 'x2)) => unit
41 | let debug3: (Location.t, 'x, (string, 'x1), (string, 'x2), (string, 'x3)) => unit
42 | let debug4: (Location.t, 'x, (string, 'x1), (string, 'x2), (string, 'x3), (string, 'x4)) => unit
43 | let debug5: (
44 | Location.t,
45 | 'x,
46 | (string, 'x1),
47 | (string, 'x2),
48 | (string, 'x3),
49 | (string, 'x4),
50 | (string, 'x5),
51 | ) => unit
52 | let debug6: (
53 | Location.t,
54 | 'x,
55 | (string, 'x1),
56 | (string, 'x2),
57 | (string, 'x3),
58 | (string, 'x4),
59 | (string, 'x5),
60 | (string, 'x6),
61 | ) => unit
62 | let debug7: (
63 | Location.t,
64 | 'x,
65 | (string, 'x1),
66 | (string, 'x2),
67 | (string, 'x3),
68 | (string, 'x4),
69 | (string, 'x5),
70 | (string, 'x6),
71 | (string, 'x7),
72 | ) => unit
73 |
74 | let info: (Location.t, 'x) => unit
75 | let info1: (Location.t, 'x, (string, 'x1)) => unit
76 | let info2: (Location.t, 'x, (string, 'x1), (string, 'x2)) => unit
77 | let info3: (Location.t, 'x, (string, 'x1), (string, 'x2), (string, 'x3)) => unit
78 | let info4: (Location.t, 'x, (string, 'x1), (string, 'x2), (string, 'x3), (string, 'x4)) => unit
79 | let info5: (
80 | Location.t,
81 | 'x,
82 | (string, 'x1),
83 | (string, 'x2),
84 | (string, 'x3),
85 | (string, 'x4),
86 | (string, 'x5),
87 | ) => unit
88 | let info6: (
89 | Location.t,
90 | 'x,
91 | (string, 'x1),
92 | (string, 'x2),
93 | (string, 'x3),
94 | (string, 'x4),
95 | (string, 'x5),
96 | (string, 'x6),
97 | ) => unit
98 | let info7: (
99 | Location.t,
100 | 'x,
101 | (string, 'x1),
102 | (string, 'x2),
103 | (string, 'x3),
104 | (string, 'x4),
105 | (string, 'x5),
106 | (string, 'x6),
107 | (string, 'x7),
108 | ) => unit
109 |
110 | let warn: (Location.t, 'x) => unit
111 | let warn1: (Location.t, 'x, (string, 'x1)) => unit
112 | let warn2: (Location.t, 'x, (string, 'x1), (string, 'x2)) => unit
113 | let warn3: (Location.t, 'x, (string, 'x1), (string, 'x2), (string, 'x3)) => unit
114 | let warn4: (Location.t, 'x, (string, 'x1), (string, 'x2), (string, 'x3), (string, 'x4)) => unit
115 | let warn5: (
116 | Location.t,
117 | 'x,
118 | (string, 'x1),
119 | (string, 'x2),
120 | (string, 'x3),
121 | (string, 'x4),
122 | (string, 'x5),
123 | ) => unit
124 | let warn6: (
125 | Location.t,
126 | 'x,
127 | (string, 'x1),
128 | (string, 'x2),
129 | (string, 'x3),
130 | (string, 'x4),
131 | (string, 'x5),
132 | (string, 'x6),
133 | ) => unit
134 | let warn7: (
135 | Location.t,
136 | 'x,
137 | (string, 'x1),
138 | (string, 'x2),
139 | (string, 'x3),
140 | (string, 'x4),
141 | (string, 'x5),
142 | (string, 'x6),
143 | (string, 'x7),
144 | ) => unit
145 |
146 | let error: (Location.t, 'x) => unit
147 | let error1: (Location.t, 'x, (string, 'x1)) => unit
148 | let error2: (Location.t, 'x, (string, 'x1), (string, 'x2)) => unit
149 | let error3: (Location.t, 'x, (string, 'x1), (string, 'x2), (string, 'x3)) => unit
150 | let error4: (Location.t, 'x, (string, 'x1), (string, 'x2), (string, 'x3), (string, 'x4)) => unit
151 | let error5: (
152 | Location.t,
153 | 'x,
154 | (string, 'x1),
155 | (string, 'x2),
156 | (string, 'x3),
157 | (string, 'x4),
158 | (string, 'x5),
159 | ) => unit
160 | let error6: (
161 | Location.t,
162 | 'x,
163 | (string, 'x1),
164 | (string, 'x2),
165 | (string, 'x3),
166 | (string, 'x4),
167 | (string, 'x5),
168 | (string, 'x6),
169 | ) => unit
170 | let error7: (
171 | Location.t,
172 | 'x,
173 | (string, 'x1),
174 | (string, 'x2),
175 | (string, 'x3),
176 | (string, 'x4),
177 | (string, 'x5),
178 | (string, 'x6),
179 | (string, 'x7),
180 | ) => unit
181 | }
182 |
--------------------------------------------------------------------------------
/lib/src/Location.res:
--------------------------------------------------------------------------------
1 | type t = {
2 | rootModule: string,
3 | subModulePath: list,
4 | value: option,
5 | fullPath: string,
6 | }
7 |
8 | let format = x => `[${x.fullPath}]`
9 |
--------------------------------------------------------------------------------
/lib/src/loggers/Browser.res:
--------------------------------------------------------------------------------
1 | @val @scope("console") external log: ('a, 'b) => unit = "log"
2 | @val @scope("console") external groupEnd: unit => unit = "groupEnd"
3 |
4 | // Level: Trace
5 | @val @scope("console")
6 | external traceGroup: (
7 | @as("%c TRACE ") _,
8 | @as("background: #636363; color: #fff;") _,
9 | 'a,
10 | 'b,
11 | ) => unit = "group"
12 |
13 | @val @scope("console")
14 | external traceGroupCollapsed: (
15 | @as("%c TRACE ") _,
16 | @as("background: #636363; color: #fff;") _,
17 | 'a,
18 | 'b,
19 | ) => unit = "groupCollapsed"
20 |
21 | let trace = (loc: Location.t, x: 'x) => {
22 | loc->Location.format->traceGroupCollapsed(x)
23 | groupEnd()
24 | }
25 |
26 | let trace1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
27 | loc->Location.format->traceGroup(x)
28 | log(l1 ++ ":", x1)
29 | groupEnd()
30 | }
31 |
32 | let trace2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
33 | loc->Location.format->traceGroup(x)
34 | log(l1 ++ ":", x1)
35 | log(l2 ++ ":", x2)
36 | groupEnd()
37 | }
38 |
39 | let trace3 = (
40 | loc: Location.t,
41 | x: 'x,
42 | (l1, x1): (string, 'x1),
43 | (l2, x2): (string, 'x2),
44 | (l3, x3): (string, 'x3),
45 | ) => {
46 | loc->Location.format->traceGroup(x)
47 | log(l1 ++ ":", x1)
48 | log(l2 ++ ":", x2)
49 | log(l3 ++ ":", x3)
50 | groupEnd()
51 | }
52 |
53 | let trace4 = (
54 | loc: Location.t,
55 | x: 'x,
56 | (l1, x1): (string, 'x1),
57 | (l2, x2): (string, 'x2),
58 | (l3, x3): (string, 'x3),
59 | (l4, x4): (string, 'x4),
60 | ) => {
61 | loc->Location.format->traceGroup(x)
62 | log(l1 ++ ":", x1)
63 | log(l2 ++ ":", x2)
64 | log(l3 ++ ":", x3)
65 | log(l4 ++ ":", x4)
66 | groupEnd()
67 | }
68 |
69 | let trace5 = (
70 | loc: Location.t,
71 | x: 'x,
72 | (l1, x1): (string, 'x1),
73 | (l2, x2): (string, 'x2),
74 | (l3, x3): (string, 'x3),
75 | (l4, x4): (string, 'x4),
76 | (l5, x5): (string, 'x5),
77 | ) => {
78 | loc->Location.format->traceGroup(x)
79 | log(l1 ++ ":", x1)
80 | log(l2 ++ ":", x2)
81 | log(l3 ++ ":", x3)
82 | log(l4 ++ ":", x4)
83 | log(l5 ++ ":", x5)
84 | groupEnd()
85 | }
86 |
87 | let trace6 = (
88 | loc: Location.t,
89 | x: 'x,
90 | (l1, x1): (string, 'x1),
91 | (l2, x2): (string, 'x2),
92 | (l3, x3): (string, 'x3),
93 | (l4, x4): (string, 'x4),
94 | (l5, x5): (string, 'x5),
95 | (l6, x6): (string, 'x6),
96 | ) => {
97 | loc->Location.format->traceGroup(x)
98 | log(l1 ++ ":", x1)
99 | log(l2 ++ ":", x2)
100 | log(l3 ++ ":", x3)
101 | log(l4 ++ ":", x4)
102 | log(l5 ++ ":", x5)
103 | log(l6 ++ ":", x6)
104 | groupEnd()
105 | }
106 |
107 | let trace7 = (
108 | loc: Location.t,
109 | x: 'x,
110 | (l1, x1): (string, 'x1),
111 | (l2, x2): (string, 'x2),
112 | (l3, x3): (string, 'x3),
113 | (l4, x4): (string, 'x4),
114 | (l5, x5): (string, 'x5),
115 | (l6, x6): (string, 'x6),
116 | (l7, x7): (string, 'x7),
117 | ) => {
118 | loc->Location.format->traceGroup(x)
119 | log(l1 ++ ":", x1)
120 | log(l2 ++ ":", x2)
121 | log(l3 ++ ":", x3)
122 | log(l4 ++ ":", x4)
123 | log(l5 ++ ":", x5)
124 | log(l6 ++ ":", x6)
125 | log(l7 ++ ":", x7)
126 | groupEnd()
127 | }
128 |
129 | // Level: Debug
130 | @val @scope("console")
131 | external debugGroup: (
132 | @as("%c DEBUG ") _,
133 | @as("background: #82658c; color: #fff;") _,
134 | 'a,
135 | 'b,
136 | ) => unit = "group"
137 |
138 | @val @scope("console")
139 | external debugGroupCollapsed: (
140 | @as("%c DEBUG ") _,
141 | @as("background: #82658c; color: #fff;") _,
142 | 'a,
143 | 'b,
144 | ) => unit = "groupCollapsed"
145 |
146 | let debug = (loc: Location.t, x: 'x) => {
147 | loc->Location.format->debugGroupCollapsed(x)
148 | groupEnd()
149 | }
150 |
151 | let debug1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
152 | loc->Location.format->debugGroup(x)
153 | log(l1 ++ ":", x1)
154 | groupEnd()
155 | }
156 |
157 | let debug2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
158 | loc->Location.format->debugGroup(x)
159 | log(l1 ++ ":", x1)
160 | log(l2 ++ ":", x2)
161 | groupEnd()
162 | }
163 |
164 | let debug3 = (
165 | loc: Location.t,
166 | x: 'x,
167 | (l1, x1): (string, 'x1),
168 | (l2, x2): (string, 'x2),
169 | (l3, x3): (string, 'x3),
170 | ) => {
171 | loc->Location.format->debugGroup(x)
172 | log(l1 ++ ":", x1)
173 | log(l2 ++ ":", x2)
174 | log(l3 ++ ":", x3)
175 | groupEnd()
176 | }
177 |
178 | let debug4 = (
179 | loc: Location.t,
180 | x: 'x,
181 | (l1, x1): (string, 'x1),
182 | (l2, x2): (string, 'x2),
183 | (l3, x3): (string, 'x3),
184 | (l4, x4): (string, 'x4),
185 | ) => {
186 | loc->Location.format->debugGroup(x)
187 | log(l1 ++ ":", x1)
188 | log(l2 ++ ":", x2)
189 | log(l3 ++ ":", x3)
190 | log(l4 ++ ":", x4)
191 | groupEnd()
192 | }
193 |
194 | let debug5 = (
195 | loc: Location.t,
196 | x: 'x,
197 | (l1, x1): (string, 'x1),
198 | (l2, x2): (string, 'x2),
199 | (l3, x3): (string, 'x3),
200 | (l4, x4): (string, 'x4),
201 | (l5, x5): (string, 'x5),
202 | ) => {
203 | loc->Location.format->debugGroup(x)
204 | log(l1 ++ ":", x1)
205 | log(l2 ++ ":", x2)
206 | log(l3 ++ ":", x3)
207 | log(l4 ++ ":", x4)
208 | log(l5 ++ ":", x5)
209 | groupEnd()
210 | }
211 |
212 | let debug6 = (
213 | loc: Location.t,
214 | x: 'x,
215 | (l1, x1): (string, 'x1),
216 | (l2, x2): (string, 'x2),
217 | (l3, x3): (string, 'x3),
218 | (l4, x4): (string, 'x4),
219 | (l5, x5): (string, 'x5),
220 | (l6, x6): (string, 'x6),
221 | ) => {
222 | loc->Location.format->debugGroup(x)
223 | log(l1 ++ ":", x1)
224 | log(l2 ++ ":", x2)
225 | log(l3 ++ ":", x3)
226 | log(l4 ++ ":", x4)
227 | log(l5 ++ ":", x5)
228 | log(l6 ++ ":", x6)
229 | groupEnd()
230 | }
231 |
232 | let debug7 = (
233 | loc: Location.t,
234 | x: 'x,
235 | (l1, x1): (string, 'x1),
236 | (l2, x2): (string, 'x2),
237 | (l3, x3): (string, 'x3),
238 | (l4, x4): (string, 'x4),
239 | (l5, x5): (string, 'x5),
240 | (l6, x6): (string, 'x6),
241 | (l7, x7): (string, 'x7),
242 | ) => {
243 | loc->Location.format->debugGroup(x)
244 | log(l1 ++ ":", x1)
245 | log(l2 ++ ":", x2)
246 | log(l3 ++ ":", x3)
247 | log(l4 ++ ":", x4)
248 | log(l5 ++ ":", x5)
249 | log(l6 ++ ":", x6)
250 | log(l7 ++ ":", x7)
251 | groupEnd()
252 | }
253 |
254 | // Level: Info
255 | @val @scope("console")
256 | external infoGroup: (@as("%c INFO ") _, @as("background: #29d; color: #fff;") _, 'a, 'b) => unit =
257 | "group"
258 |
259 | @val @scope("console")
260 | external infoGroupCollapsed: (
261 | @as("%c INFO ") _,
262 | @as("background: #29d; color: #fff;") _,
263 | 'a,
264 | 'b,
265 | ) => unit = "groupCollapsed"
266 |
267 | let info = (loc: Location.t, x: 'x) => {
268 | loc->Location.format->infoGroupCollapsed(x)
269 | groupEnd()
270 | }
271 |
272 | let info1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
273 | loc->Location.format->infoGroup(x)
274 | log(l1 ++ ":", x1)
275 | groupEnd()
276 | }
277 |
278 | let info2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
279 | loc->Location.format->infoGroup(x)
280 | log(l1 ++ ":", x1)
281 | log(l2 ++ ":", x2)
282 | groupEnd()
283 | }
284 |
285 | let info3 = (
286 | loc: Location.t,
287 | x: 'x,
288 | (l1, x1): (string, 'x1),
289 | (l2, x2): (string, 'x2),
290 | (l3, x3): (string, 'x3),
291 | ) => {
292 | loc->Location.format->infoGroup(x)
293 | log(l1 ++ ":", x1)
294 | log(l2 ++ ":", x2)
295 | log(l3 ++ ":", x3)
296 | groupEnd()
297 | }
298 |
299 | let info4 = (
300 | loc: Location.t,
301 | x: 'x,
302 | (l1, x1): (string, 'x1),
303 | (l2, x2): (string, 'x2),
304 | (l3, x3): (string, 'x3),
305 | (l4, x4): (string, 'x4),
306 | ) => {
307 | loc->Location.format->infoGroup(x)
308 | log(l1 ++ ":", x1)
309 | log(l2 ++ ":", x2)
310 | log(l3 ++ ":", x3)
311 | log(l4 ++ ":", x4)
312 | groupEnd()
313 | }
314 |
315 | let info5 = (
316 | loc: Location.t,
317 | x: 'x,
318 | (l1, x1): (string, 'x1),
319 | (l2, x2): (string, 'x2),
320 | (l3, x3): (string, 'x3),
321 | (l4, x4): (string, 'x4),
322 | (l5, x5): (string, 'x5),
323 | ) => {
324 | loc->Location.format->infoGroup(x)
325 | log(l1 ++ ":", x1)
326 | log(l2 ++ ":", x2)
327 | log(l3 ++ ":", x3)
328 | log(l4 ++ ":", x4)
329 | log(l5 ++ ":", x5)
330 | groupEnd()
331 | }
332 |
333 | let info6 = (
334 | loc: Location.t,
335 | x: 'x,
336 | (l1, x1): (string, 'x1),
337 | (l2, x2): (string, 'x2),
338 | (l3, x3): (string, 'x3),
339 | (l4, x4): (string, 'x4),
340 | (l5, x5): (string, 'x5),
341 | (l6, x6): (string, 'x6),
342 | ) => {
343 | loc->Location.format->infoGroup(x)
344 | log(l1 ++ ":", x1)
345 | log(l2 ++ ":", x2)
346 | log(l3 ++ ":", x3)
347 | log(l4 ++ ":", x4)
348 | log(l5 ++ ":", x5)
349 | log(l6 ++ ":", x6)
350 | groupEnd()
351 | }
352 |
353 | let info7 = (
354 | loc: Location.t,
355 | x: 'x,
356 | (l1, x1): (string, 'x1),
357 | (l2, x2): (string, 'x2),
358 | (l3, x3): (string, 'x3),
359 | (l4, x4): (string, 'x4),
360 | (l5, x5): (string, 'x5),
361 | (l6, x6): (string, 'x6),
362 | (l7, x7): (string, 'x7),
363 | ) => {
364 | loc->Location.format->infoGroup(x)
365 | log(l1 ++ ":", x1)
366 | log(l2 ++ ":", x2)
367 | log(l3 ++ ":", x3)
368 | log(l4 ++ ":", x4)
369 | log(l5 ++ ":", x5)
370 | log(l6 ++ ":", x6)
371 | log(l7 ++ ":", x7)
372 | groupEnd()
373 | }
374 |
375 | // Level: Warn
376 | @val @scope("console")
377 | external warnGroup: (
378 | @as("%c WARNING ") _,
379 | @as("background: #fce473; color: #573a08;") _,
380 | 'a,
381 | 'b,
382 | ) => unit = "group"
383 |
384 | @val @scope("console")
385 | external warnGroupCollapsed: (
386 | @as("%c WARNING ") _,
387 | @as("background: #fce473; color: #573a08;") _,
388 | 'a,
389 | 'b,
390 | ) => unit = "groupCollapsed"
391 |
392 | let warn = (loc: Location.t, x: 'x) => {
393 | loc->Location.format->warnGroupCollapsed(x)
394 | groupEnd()
395 | }
396 |
397 | let warn1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
398 | loc->Location.format->warnGroup(x)
399 | log(l1 ++ ":", x1)
400 | groupEnd()
401 | }
402 |
403 | let warn2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
404 | loc->Location.format->warnGroup(x)
405 | log(l1 ++ ":", x1)
406 | log(l2 ++ ":", x2)
407 | groupEnd()
408 | }
409 |
410 | let warn3 = (
411 | loc: Location.t,
412 | x: 'x,
413 | (l1, x1): (string, 'x1),
414 | (l2, x2): (string, 'x2),
415 | (l3, x3): (string, 'x3),
416 | ) => {
417 | loc->Location.format->warnGroup(x)
418 | log(l1 ++ ":", x1)
419 | log(l2 ++ ":", x2)
420 | log(l3 ++ ":", x3)
421 | groupEnd()
422 | }
423 |
424 | let warn4 = (
425 | loc: Location.t,
426 | x: 'x,
427 | (l1, x1): (string, 'x1),
428 | (l2, x2): (string, 'x2),
429 | (l3, x3): (string, 'x3),
430 | (l4, x4): (string, 'x4),
431 | ) => {
432 | loc->Location.format->warnGroup(x)
433 | log(l1 ++ ":", x1)
434 | log(l2 ++ ":", x2)
435 | log(l3 ++ ":", x3)
436 | log(l4 ++ ":", x4)
437 | groupEnd()
438 | }
439 |
440 | let warn5 = (
441 | loc: Location.t,
442 | x: 'x,
443 | (l1, x1): (string, 'x1),
444 | (l2, x2): (string, 'x2),
445 | (l3, x3): (string, 'x3),
446 | (l4, x4): (string, 'x5),
447 | (l5, x5): (string, 'x6),
448 | ) => {
449 | loc->Location.format->warnGroup(x)
450 | log(l1 ++ ":", x1)
451 | log(l2 ++ ":", x2)
452 | log(l3 ++ ":", x3)
453 | log(l4 ++ ":", x4)
454 | log(l5 ++ ":", x5)
455 | groupEnd()
456 | }
457 |
458 | let warn6 = (
459 | loc: Location.t,
460 | x: 'x,
461 | (l1, x1): (string, 'x1),
462 | (l2, x2): (string, 'x2),
463 | (l3, x3): (string, 'x3),
464 | (l4, x4): (string, 'x4),
465 | (l5, x5): (string, 'x5),
466 | (l6, x6): (string, 'x6),
467 | ) => {
468 | loc->Location.format->warnGroup(x)
469 | log(l1 ++ ":", x1)
470 | log(l2 ++ ":", x2)
471 | log(l3 ++ ":", x3)
472 | log(l4 ++ ":", x4)
473 | log(l5 ++ ":", x5)
474 | log(l6 ++ ":", x6)
475 | groupEnd()
476 | }
477 |
478 | let warn7 = (
479 | loc: Location.t,
480 | x: 'x,
481 | (l1, x1): (string, 'x1),
482 | (l2, x2): (string, 'x2),
483 | (l3, x3): (string, 'x3),
484 | (l4, x4): (string, 'x4),
485 | (l5, x5): (string, 'x5),
486 | (l6, x6): (string, 'x6),
487 | (l7, x7): (string, 'x7),
488 | ) => {
489 | loc->Location.format->warnGroup(x)
490 | log(l1 ++ ":", x1)
491 | log(l2 ++ ":", x2)
492 | log(l3 ++ ":", x3)
493 | log(l4 ++ ":", x4)
494 | log(l5 ++ ":", x5)
495 | log(l6 ++ ":", x6)
496 | log(l7 ++ ":", x7)
497 | groupEnd()
498 | }
499 |
500 | // Level: Error
501 | @val @scope("console")
502 | external errorGroup: (
503 | @as("%c ERROR ") _,
504 | @as("background: #d11a1a; color: #fff;") _,
505 | 'a,
506 | 'b,
507 | ) => unit = "group"
508 |
509 | @val @scope("console")
510 | external errorGroupCollapsed: (
511 | @as("%c ERROR ") _,
512 | @as("background: #d11a1a; color: #fff;") _,
513 | 'a,
514 | 'b,
515 | ) => unit = "groupCollapsed"
516 |
517 | let error = (loc: Location.t, x: 'x) => {
518 | loc->Location.format->errorGroupCollapsed(x)
519 | groupEnd()
520 | }
521 |
522 | let error1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
523 | loc->Location.format->errorGroup(x)
524 | log(l1 ++ ":", x1)
525 | groupEnd()
526 | }
527 |
528 | let error2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
529 | loc->Location.format->errorGroup(x)
530 | log(l1 ++ ":", x1)
531 | log(l2 ++ ":", x2)
532 | groupEnd()
533 | }
534 |
535 | let error3 = (
536 | loc: Location.t,
537 | x: 'x,
538 | (l1, x1): (string, 'x1),
539 | (l2, x2): (string, 'x2),
540 | (l3, x3): (string, 'x3),
541 | ) => {
542 | loc->Location.format->errorGroup(x)
543 | log(l1 ++ ":", x1)
544 | log(l2 ++ ":", x2)
545 | log(l3 ++ ":", x3)
546 | groupEnd()
547 | }
548 |
549 | let error4 = (
550 | loc: Location.t,
551 | x: 'x,
552 | (l1, x1): (string, 'x1),
553 | (l2, x2): (string, 'x2),
554 | (l3, x3): (string, 'x3),
555 | (l4, x4): (string, 'x4),
556 | ) => {
557 | loc->Location.format->errorGroup(x)
558 | log(l1 ++ ":", x1)
559 | log(l2 ++ ":", x2)
560 | log(l3 ++ ":", x3)
561 | log(l4 ++ ":", x4)
562 | groupEnd()
563 | }
564 |
565 | let error5 = (
566 | loc: Location.t,
567 | x: 'x,
568 | (l1, x1): (string, 'x1),
569 | (l2, x2): (string, 'x2),
570 | (l3, x3): (string, 'x3),
571 | (l4, x4): (string, 'x4),
572 | (l5, x5): (string, 'x5),
573 | ) => {
574 | loc->Location.format->errorGroup(x)
575 | log(l1 ++ ":", x1)
576 | log(l2 ++ ":", x2)
577 | log(l3 ++ ":", x3)
578 | log(l4 ++ ":", x4)
579 | log(l5 ++ ":", x5)
580 | groupEnd()
581 | }
582 |
583 | let error6 = (
584 | loc: Location.t,
585 | x: 'x,
586 | (l1, x1): (string, 'x1),
587 | (l2, x2): (string, 'x2),
588 | (l3, x3): (string, 'x3),
589 | (l4, x4): (string, 'x4),
590 | (l5, x5): (string, 'x5),
591 | (l6, x6): (string, 'x6),
592 | ) => {
593 | loc->Location.format->errorGroup(x)
594 | log(l1 ++ ":", x1)
595 | log(l2 ++ ":", x2)
596 | log(l3 ++ ":", x3)
597 | log(l4 ++ ":", x4)
598 | log(l5 ++ ":", x5)
599 | log(l6 ++ ":", x6)
600 | groupEnd()
601 | }
602 |
603 | let error7 = (
604 | loc: Location.t,
605 | x: 'x,
606 | (l1, x1): (string, 'x1),
607 | (l2, x2): (string, 'x2),
608 | (l3, x3): (string, 'x3),
609 | (l4, x4): (string, 'x4),
610 | (l5, x5): (string, 'x5),
611 | (l6, x6): (string, 'x6),
612 | (l7, x7): (string, 'x7),
613 | ) => {
614 | loc->Location.format->errorGroup(x)
615 | log(l1 ++ ":", x1)
616 | log(l2 ++ ":", x2)
617 | log(l3 ++ ":", x3)
618 | log(l4 ++ ":", x4)
619 | log(l5 ++ ":", x5)
620 | log(l6 ++ ":", x6)
621 | log(l7 ++ ":", x7)
622 | groupEnd()
623 | }
624 |
--------------------------------------------------------------------------------
/lib/src/loggers/Browser.resi:
--------------------------------------------------------------------------------
1 | include Interface.Logger
2 |
--------------------------------------------------------------------------------
/lib/src/loggers/Edge.res:
--------------------------------------------------------------------------------
1 | @val @scope("console") external log: ('a, 'b) => unit = "log"
2 | @val @scope("console") external group: ('a, 'b, 'c) => unit = "log"
3 | @val @scope("console") external groupCollapsed: ('a, 'b, 'c) => unit = "log"
4 |
5 | // Level: Trace
6 | let traceLabel = `\u001B[48;2;99;99;99m\u001B[38;2;255;255;255m TRACE \u001B[39m\u001B[49m`
7 |
8 | let trace = (loc: Location.t, x: 'x) => {
9 | traceLabel->groupCollapsed(loc->Location.format, x)
10 | }
11 |
12 | let trace1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
13 | traceLabel->group(loc->Location.format, x)
14 | log(l1 ++ ":", x1)
15 | }
16 |
17 | let trace2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
18 | traceLabel->group(loc->Location.format, x)
19 | log(l1 ++ ":", x1)
20 | log(l2 ++ ":", x2)
21 | }
22 |
23 | let trace3 = (
24 | loc: Location.t,
25 | x: 'x,
26 | (l1, x1): (string, 'x1),
27 | (l2, x2): (string, 'x2),
28 | (l3, x3): (string, 'x3),
29 | ) => {
30 | traceLabel->group(loc->Location.format, x)
31 | log(l1 ++ ":", x1)
32 | log(l2 ++ ":", x2)
33 | log(l3 ++ ":", x3)
34 | }
35 |
36 | let trace4 = (
37 | loc: Location.t,
38 | x: 'x,
39 | (l1, x1): (string, 'x1),
40 | (l2, x2): (string, 'x2),
41 | (l3, x3): (string, 'x3),
42 | (l4, x4): (string, 'x4),
43 | ) => {
44 | traceLabel->group(loc->Location.format, x)
45 | log(l1 ++ ":", x1)
46 | log(l2 ++ ":", x2)
47 | log(l3 ++ ":", x3)
48 | log(l4 ++ ":", x4)
49 | }
50 |
51 | let trace5 = (
52 | loc: Location.t,
53 | x: 'x,
54 | (l1, x1): (string, 'x1),
55 | (l2, x2): (string, 'x2),
56 | (l3, x3): (string, 'x3),
57 | (l4, x4): (string, 'x4),
58 | (l5, x5): (string, 'x5),
59 | ) => {
60 | traceLabel->group(loc->Location.format, x)
61 | log(l1 ++ ":", x1)
62 | log(l2 ++ ":", x2)
63 | log(l3 ++ ":", x3)
64 | log(l4 ++ ":", x4)
65 | log(l5 ++ ":", x5)
66 | }
67 |
68 | let trace6 = (
69 | loc: Location.t,
70 | x: 'x,
71 | (l1, x1): (string, 'x1),
72 | (l2, x2): (string, 'x2),
73 | (l3, x3): (string, 'x3),
74 | (l4, x4): (string, 'x4),
75 | (l5, x5): (string, 'x5),
76 | (l6, x6): (string, 'x6),
77 | ) => {
78 | traceLabel->group(loc->Location.format, x)
79 | log(l1 ++ ":", x1)
80 | log(l2 ++ ":", x2)
81 | log(l3 ++ ":", x3)
82 | log(l4 ++ ":", x4)
83 | log(l5 ++ ":", x5)
84 | log(l6 ++ ":", x6)
85 | }
86 |
87 | let trace7 = (
88 | loc: Location.t,
89 | x: 'x,
90 | (l1, x1): (string, 'x1),
91 | (l2, x2): (string, 'x2),
92 | (l3, x3): (string, 'x3),
93 | (l4, x4): (string, 'x4),
94 | (l5, x5): (string, 'x5),
95 | (l6, x6): (string, 'x6),
96 | (l7, x7): (string, 'x7),
97 | ) => {
98 | traceLabel->group(loc->Location.format, x)
99 | log(l1 ++ ":", x1)
100 | log(l2 ++ ":", x2)
101 | log(l3 ++ ":", x3)
102 | log(l4 ++ ":", x4)
103 | log(l5 ++ ":", x5)
104 | log(l6 ++ ":", x6)
105 | log(l7 ++ ":", x7)
106 | }
107 |
108 | // Level: Debug
109 | let debugLabel = `\u001B[48;2;130;101;140m\u001B[38;2;255;255;255m DEBUG \u001B[39m\u001B[49m`
110 |
111 | let debug = (loc: Location.t, x: 'x) => {
112 | debugLabel->groupCollapsed(loc->Location.format, x)
113 | }
114 |
115 | let debug1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
116 | debugLabel->group(loc->Location.format, x)
117 | log(l1 ++ ":", x1)
118 | }
119 |
120 | let debug2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
121 | debugLabel->group(loc->Location.format, x)
122 | log(l1 ++ ":", x1)
123 | log(l2 ++ ":", x2)
124 | }
125 |
126 | let debug3 = (
127 | loc: Location.t,
128 | x: 'x,
129 | (l1, x1): (string, 'x1),
130 | (l2, x2): (string, 'x2),
131 | (l3, x3): (string, 'x3),
132 | ) => {
133 | debugLabel->group(loc->Location.format, x)
134 | log(l1 ++ ":", x1)
135 | log(l2 ++ ":", x2)
136 | log(l3 ++ ":", x3)
137 | }
138 |
139 | let debug4 = (
140 | loc: Location.t,
141 | x: 'x,
142 | (l1, x1): (string, 'x1),
143 | (l2, x2): (string, 'x2),
144 | (l3, x3): (string, 'x3),
145 | (l4, x4): (string, 'x4),
146 | ) => {
147 | debugLabel->group(loc->Location.format, x)
148 | log(l1 ++ ":", x1)
149 | log(l2 ++ ":", x2)
150 | log(l3 ++ ":", x3)
151 | log(l4 ++ ":", x4)
152 | }
153 |
154 | let debug5 = (
155 | loc: Location.t,
156 | x: 'x,
157 | (l1, x1): (string, 'x1),
158 | (l2, x2): (string, 'x2),
159 | (l3, x3): (string, 'x3),
160 | (l4, x4): (string, 'x4),
161 | (l5, x5): (string, 'x5),
162 | ) => {
163 | debugLabel->group(loc->Location.format, x)
164 | log(l1 ++ ":", x1)
165 | log(l2 ++ ":", x2)
166 | log(l3 ++ ":", x3)
167 | log(l4 ++ ":", x4)
168 | log(l5 ++ ":", x5)
169 | }
170 |
171 | let debug6 = (
172 | loc: Location.t,
173 | x: 'x,
174 | (l1, x1): (string, 'x1),
175 | (l2, x2): (string, 'x2),
176 | (l3, x3): (string, 'x3),
177 | (l4, x4): (string, 'x4),
178 | (l5, x5): (string, 'x5),
179 | (l6, x6): (string, 'x6),
180 | ) => {
181 | debugLabel->group(loc->Location.format, x)
182 | log(l1 ++ ":", x1)
183 | log(l2 ++ ":", x2)
184 | log(l3 ++ ":", x3)
185 | log(l4 ++ ":", x4)
186 | log(l5 ++ ":", x5)
187 | log(l6 ++ ":", x6)
188 | }
189 |
190 | let debug7 = (
191 | loc: Location.t,
192 | x: 'x,
193 | (l1, x1): (string, 'x1),
194 | (l2, x2): (string, 'x2),
195 | (l3, x3): (string, 'x3),
196 | (l4, x4): (string, 'x4),
197 | (l5, x5): (string, 'x5),
198 | (l6, x6): (string, 'x6),
199 | (l7, x7): (string, 'x7),
200 | ) => {
201 | debugLabel->group(loc->Location.format, x)
202 | log(l1 ++ ":", x1)
203 | log(l2 ++ ":", x2)
204 | log(l3 ++ ":", x3)
205 | log(l4 ++ ":", x4)
206 | log(l5 ++ ":", x5)
207 | log(l6 ++ ":", x6)
208 | log(l7 ++ ":", x7)
209 | }
210 |
211 | // Level: Info
212 | let infoLabel = `\u001B[48;2;34;153;221m\u001B[38;2;255;255;255m INFO \u001B[39m\u001B[49m`
213 |
214 | let info = (loc: Location.t, x: 'x) => {
215 | infoLabel->groupCollapsed(loc->Location.format, x)
216 | }
217 |
218 | let info1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
219 | infoLabel->group(loc->Location.format, x)
220 | log(l1 ++ ":", x1)
221 | }
222 |
223 | let info2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
224 | infoLabel->group(loc->Location.format, x)
225 | log(l1 ++ ":", x1)
226 | log(l2 ++ ":", x2)
227 | }
228 |
229 | let info3 = (
230 | loc: Location.t,
231 | x: 'x,
232 | (l1, x1): (string, 'x1),
233 | (l2, x2): (string, 'x2),
234 | (l3, x3): (string, 'x3),
235 | ) => {
236 | infoLabel->group(loc->Location.format, x)
237 | log(l1 ++ ":", x1)
238 | log(l2 ++ ":", x2)
239 | log(l3 ++ ":", x3)
240 | }
241 |
242 | let info4 = (
243 | loc: Location.t,
244 | x: 'x,
245 | (l1, x1): (string, 'x1),
246 | (l2, x2): (string, 'x2),
247 | (l3, x3): (string, 'x3),
248 | (l4, x4): (string, 'x4),
249 | ) => {
250 | infoLabel->group(loc->Location.format, x)
251 | log(l1 ++ ":", x1)
252 | log(l2 ++ ":", x2)
253 | log(l3 ++ ":", x3)
254 | log(l4 ++ ":", x4)
255 | }
256 |
257 | let info5 = (
258 | loc: Location.t,
259 | x: 'x,
260 | (l1, x1): (string, 'x1),
261 | (l2, x2): (string, 'x2),
262 | (l3, x3): (string, 'x3),
263 | (l4, x4): (string, 'x4),
264 | (l5, x5): (string, 'x5),
265 | ) => {
266 | infoLabel->group(loc->Location.format, x)
267 | log(l1 ++ ":", x1)
268 | log(l2 ++ ":", x2)
269 | log(l3 ++ ":", x3)
270 | log(l4 ++ ":", x4)
271 | log(l5 ++ ":", x5)
272 | }
273 |
274 | let info6 = (
275 | loc: Location.t,
276 | x: 'x,
277 | (l1, x1): (string, 'x1),
278 | (l2, x2): (string, 'x2),
279 | (l3, x3): (string, 'x3),
280 | (l4, x4): (string, 'x4),
281 | (l5, x5): (string, 'x5),
282 | (l6, x6): (string, 'x6),
283 | ) => {
284 | infoLabel->group(loc->Location.format, x)
285 | log(l1 ++ ":", x1)
286 | log(l2 ++ ":", x2)
287 | log(l3 ++ ":", x3)
288 | log(l4 ++ ":", x4)
289 | log(l5 ++ ":", x5)
290 | log(l6 ++ ":", x6)
291 | }
292 |
293 | let info7 = (
294 | loc: Location.t,
295 | x: 'x,
296 | (l1, x1): (string, 'x1),
297 | (l2, x2): (string, 'x2),
298 | (l3, x3): (string, 'x3),
299 | (l4, x4): (string, 'x4),
300 | (l5, x5): (string, 'x5),
301 | (l6, x6): (string, 'x6),
302 | (l7, x7): (string, 'x7),
303 | ) => {
304 | infoLabel->group(loc->Location.format, x)
305 | log(l1 ++ ":", x1)
306 | log(l2 ++ ":", x2)
307 | log(l3 ++ ":", x3)
308 | log(l4 ++ ":", x4)
309 | log(l5 ++ ":", x5)
310 | log(l6 ++ ":", x6)
311 | log(l7 ++ ":", x7)
312 | }
313 |
314 | // Level: Warn
315 | let warnLabel = `\u001B[48;2;252;228;115m\u001B[38;2;87;58;8m WARNING \u001B[39m\u001B[49m`
316 |
317 | let warn = (loc: Location.t, x: 'x) => {
318 | warnLabel->groupCollapsed(loc->Location.format, x)
319 | }
320 |
321 | let warn1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
322 | warnLabel->group(loc->Location.format, x)
323 | log(l1 ++ ":", x1)
324 | }
325 |
326 | let warn2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
327 | warnLabel->group(loc->Location.format, x)
328 | log(l1 ++ ":", x1)
329 | log(l2 ++ ":", x2)
330 | }
331 |
332 | let warn3 = (
333 | loc: Location.t,
334 | x: 'x,
335 | (l1, x1): (string, 'x1),
336 | (l2, x2): (string, 'x2),
337 | (l3, x3): (string, 'x3),
338 | ) => {
339 | warnLabel->group(loc->Location.format, x)
340 | log(l1 ++ ":", x1)
341 | log(l2 ++ ":", x2)
342 | log(l3 ++ ":", x3)
343 | }
344 |
345 | let warn4 = (
346 | loc: Location.t,
347 | x: 'x,
348 | (l1, x1): (string, 'x1),
349 | (l2, x2): (string, 'x2),
350 | (l3, x3): (string, 'x3),
351 | (l4, x4): (string, 'x4),
352 | ) => {
353 | warnLabel->group(loc->Location.format, x)
354 | log(l1 ++ ":", x1)
355 | log(l2 ++ ":", x2)
356 | log(l3 ++ ":", x3)
357 | log(l4 ++ ":", x4)
358 | }
359 |
360 | let warn5 = (
361 | loc: Location.t,
362 | x: 'x,
363 | (l1, x1): (string, 'x1),
364 | (l2, x2): (string, 'x2),
365 | (l3, x3): (string, 'x3),
366 | (l4, x4): (string, 'x5),
367 | (l5, x5): (string, 'x6),
368 | ) => {
369 | warnLabel->group(loc->Location.format, x)
370 | log(l1 ++ ":", x1)
371 | log(l2 ++ ":", x2)
372 | log(l3 ++ ":", x3)
373 | log(l4 ++ ":", x4)
374 | log(l5 ++ ":", x5)
375 | }
376 |
377 | let warn6 = (
378 | loc: Location.t,
379 | x: 'x,
380 | (l1, x1): (string, 'x1),
381 | (l2, x2): (string, 'x2),
382 | (l3, x3): (string, 'x3),
383 | (l4, x4): (string, 'x4),
384 | (l5, x5): (string, 'x5),
385 | (l6, x6): (string, 'x6),
386 | ) => {
387 | warnLabel->group(loc->Location.format, x)
388 | log(l1 ++ ":", x1)
389 | log(l2 ++ ":", x2)
390 | log(l3 ++ ":", x3)
391 | log(l4 ++ ":", x4)
392 | log(l5 ++ ":", x5)
393 | log(l6 ++ ":", x6)
394 | }
395 |
396 | let warn7 = (
397 | loc: Location.t,
398 | x: 'x,
399 | (l1, x1): (string, 'x1),
400 | (l2, x2): (string, 'x2),
401 | (l3, x3): (string, 'x3),
402 | (l4, x4): (string, 'x4),
403 | (l5, x5): (string, 'x5),
404 | (l6, x6): (string, 'x6),
405 | (l7, x7): (string, 'x7),
406 | ) => {
407 | warnLabel->group(loc->Location.format, x)
408 | log(l1 ++ ":", x1)
409 | log(l2 ++ ":", x2)
410 | log(l3 ++ ":", x3)
411 | log(l4 ++ ":", x4)
412 | log(l5 ++ ":", x5)
413 | log(l6 ++ ":", x6)
414 | log(l7 ++ ":", x7)
415 | }
416 |
417 | // Level: Error
418 | let errorLabel = `\u001B[48;2;209;26;26m\u001B[38;2;255;255;255m ERROR \u001B[39m\u001B[49m`
419 |
420 | let error = (loc: Location.t, x: 'x) => {
421 | errorLabel->groupCollapsed(loc->Location.format, x)
422 | }
423 |
424 | let error1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
425 | errorLabel->group(loc->Location.format, x)
426 | log(l1 ++ ":", x1)
427 | }
428 |
429 | let error2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
430 | errorLabel->group(loc->Location.format, x)
431 | log(l1 ++ ":", x1)
432 | log(l2 ++ ":", x2)
433 | }
434 |
435 | let error3 = (
436 | loc: Location.t,
437 | x: 'x,
438 | (l1, x1): (string, 'x1),
439 | (l2, x2): (string, 'x2),
440 | (l3, x3): (string, 'x3),
441 | ) => {
442 | errorLabel->group(loc->Location.format, x)
443 | log(l1 ++ ":", x1)
444 | log(l2 ++ ":", x2)
445 | log(l3 ++ ":", x3)
446 | }
447 |
448 | let error4 = (
449 | loc: Location.t,
450 | x: 'x,
451 | (l1, x1): (string, 'x1),
452 | (l2, x2): (string, 'x2),
453 | (l3, x3): (string, 'x3),
454 | (l4, x4): (string, 'x4),
455 | ) => {
456 | errorLabel->group(loc->Location.format, x)
457 | log(l1 ++ ":", x1)
458 | log(l2 ++ ":", x2)
459 | log(l3 ++ ":", x3)
460 | log(l4 ++ ":", x4)
461 | }
462 |
463 | let error5 = (
464 | loc: Location.t,
465 | x: 'x,
466 | (l1, x1): (string, 'x1),
467 | (l2, x2): (string, 'x2),
468 | (l3, x3): (string, 'x3),
469 | (l4, x4): (string, 'x4),
470 | (l5, x5): (string, 'x5),
471 | ) => {
472 | errorLabel->group(loc->Location.format, x)
473 | log(l1 ++ ":", x1)
474 | log(l2 ++ ":", x2)
475 | log(l3 ++ ":", x3)
476 | log(l4 ++ ":", x4)
477 | log(l5 ++ ":", x5)
478 | }
479 |
480 | let error6 = (
481 | loc: Location.t,
482 | x: 'x,
483 | (l1, x1): (string, 'x1),
484 | (l2, x2): (string, 'x2),
485 | (l3, x3): (string, 'x3),
486 | (l4, x4): (string, 'x4),
487 | (l5, x5): (string, 'x5),
488 | (l6, x6): (string, 'x6),
489 | ) => {
490 | errorLabel->group(loc->Location.format, x)
491 | log(l1 ++ ":", x1)
492 | log(l2 ++ ":", x2)
493 | log(l3 ++ ":", x3)
494 | log(l4 ++ ":", x4)
495 | log(l5 ++ ":", x5)
496 | log(l6 ++ ":", x6)
497 | }
498 |
499 | let error7 = (
500 | loc: Location.t,
501 | x: 'x,
502 | (l1, x1): (string, 'x1),
503 | (l2, x2): (string, 'x2),
504 | (l3, x3): (string, 'x3),
505 | (l4, x4): (string, 'x4),
506 | (l5, x5): (string, 'x5),
507 | (l6, x6): (string, 'x6),
508 | (l7, x7): (string, 'x7),
509 | ) => {
510 | errorLabel->group(loc->Location.format, x)
511 | log(l1 ++ ":", x1)
512 | log(l2 ++ ":", x2)
513 | log(l3 ++ ":", x3)
514 | log(l4 ++ ":", x4)
515 | log(l5 ++ ":", x5)
516 | log(l6 ++ ":", x6)
517 | log(l7 ++ ":", x7)
518 | }
519 |
--------------------------------------------------------------------------------
/lib/src/loggers/Edge.resi:
--------------------------------------------------------------------------------
1 | include Interface.Logger
2 |
--------------------------------------------------------------------------------
/lib/src/loggers/Node.res:
--------------------------------------------------------------------------------
1 | @val @scope("console") external log: ('a, 'b) => unit = "log"
2 | @val @scope("console") external group: ('a, 'b, 'c) => unit = "group"
3 | @val @scope("console") external groupCollapsed: ('a, 'b, 'c) => unit = "groupCollapsed"
4 | @val @scope("console") external groupEnd: unit => unit = "groupEnd"
5 |
6 | // Level: Trace
7 | let traceLabel = `\u001B[48;2;99;99;99m\u001B[38;2;255;255;255m TRACE \u001B[39m\u001B[49m`
8 |
9 | let trace = (loc: Location.t, x: 'x) => {
10 | traceLabel->groupCollapsed(loc->Location.format, x)
11 | groupEnd()
12 | }
13 |
14 | let trace1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
15 | traceLabel->group(loc->Location.format, x)
16 | log(l1 ++ ":", x1)
17 | groupEnd()
18 | }
19 |
20 | let trace2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
21 | traceLabel->group(loc->Location.format, x)
22 | log(l1 ++ ":", x1)
23 | log(l2 ++ ":", x2)
24 | groupEnd()
25 | }
26 |
27 | let trace3 = (
28 | loc: Location.t,
29 | x: 'x,
30 | (l1, x1): (string, 'x1),
31 | (l2, x2): (string, 'x2),
32 | (l3, x3): (string, 'x3),
33 | ) => {
34 | traceLabel->group(loc->Location.format, x)
35 | log(l1 ++ ":", x1)
36 | log(l2 ++ ":", x2)
37 | log(l3 ++ ":", x3)
38 | groupEnd()
39 | }
40 |
41 | let trace4 = (
42 | loc: Location.t,
43 | x: 'x,
44 | (l1, x1): (string, 'x1),
45 | (l2, x2): (string, 'x2),
46 | (l3, x3): (string, 'x3),
47 | (l4, x4): (string, 'x4),
48 | ) => {
49 | traceLabel->group(loc->Location.format, x)
50 | log(l1 ++ ":", x1)
51 | log(l2 ++ ":", x2)
52 | log(l3 ++ ":", x3)
53 | log(l4 ++ ":", x4)
54 | groupEnd()
55 | }
56 |
57 | let trace5 = (
58 | loc: Location.t,
59 | x: 'x,
60 | (l1, x1): (string, 'x1),
61 | (l2, x2): (string, 'x2),
62 | (l3, x3): (string, 'x3),
63 | (l4, x4): (string, 'x4),
64 | (l5, x5): (string, 'x5),
65 | ) => {
66 | traceLabel->group(loc->Location.format, x)
67 | log(l1 ++ ":", x1)
68 | log(l2 ++ ":", x2)
69 | log(l3 ++ ":", x3)
70 | log(l4 ++ ":", x4)
71 | log(l5 ++ ":", x5)
72 | groupEnd()
73 | }
74 |
75 | let trace6 = (
76 | loc: Location.t,
77 | x: 'x,
78 | (l1, x1): (string, 'x1),
79 | (l2, x2): (string, 'x2),
80 | (l3, x3): (string, 'x3),
81 | (l4, x4): (string, 'x4),
82 | (l5, x5): (string, 'x5),
83 | (l6, x6): (string, 'x6),
84 | ) => {
85 | traceLabel->group(loc->Location.format, x)
86 | log(l1 ++ ":", x1)
87 | log(l2 ++ ":", x2)
88 | log(l3 ++ ":", x3)
89 | log(l4 ++ ":", x4)
90 | log(l5 ++ ":", x5)
91 | log(l6 ++ ":", x6)
92 | groupEnd()
93 | }
94 |
95 | let trace7 = (
96 | loc: Location.t,
97 | x: 'x,
98 | (l1, x1): (string, 'x1),
99 | (l2, x2): (string, 'x2),
100 | (l3, x3): (string, 'x3),
101 | (l4, x4): (string, 'x4),
102 | (l5, x5): (string, 'x5),
103 | (l6, x6): (string, 'x6),
104 | (l7, x7): (string, 'x7),
105 | ) => {
106 | traceLabel->group(loc->Location.format, x)
107 | log(l1 ++ ":", x1)
108 | log(l2 ++ ":", x2)
109 | log(l3 ++ ":", x3)
110 | log(l4 ++ ":", x4)
111 | log(l5 ++ ":", x5)
112 | log(l6 ++ ":", x6)
113 | log(l7 ++ ":", x7)
114 | groupEnd()
115 | }
116 |
117 | // Level: Debug
118 | let debugLabel = `\u001B[48;2;130;101;140m\u001B[38;2;255;255;255m DEBUG \u001B[39m\u001B[49m`
119 |
120 | let debug = (loc: Location.t, x: 'x) => {
121 | debugLabel->groupCollapsed(loc->Location.format, x)
122 | groupEnd()
123 | }
124 |
125 | let debug1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
126 | debugLabel->group(loc->Location.format, x)
127 | log(l1 ++ ":", x1)
128 | groupEnd()
129 | }
130 |
131 | let debug2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
132 | debugLabel->group(loc->Location.format, x)
133 | log(l1 ++ ":", x1)
134 | log(l2 ++ ":", x2)
135 | groupEnd()
136 | }
137 |
138 | let debug3 = (
139 | loc: Location.t,
140 | x: 'x,
141 | (l1, x1): (string, 'x1),
142 | (l2, x2): (string, 'x2),
143 | (l3, x3): (string, 'x3),
144 | ) => {
145 | debugLabel->group(loc->Location.format, x)
146 | log(l1 ++ ":", x1)
147 | log(l2 ++ ":", x2)
148 | log(l3 ++ ":", x3)
149 | groupEnd()
150 | }
151 |
152 | let debug4 = (
153 | loc: Location.t,
154 | x: 'x,
155 | (l1, x1): (string, 'x1),
156 | (l2, x2): (string, 'x2),
157 | (l3, x3): (string, 'x3),
158 | (l4, x4): (string, 'x4),
159 | ) => {
160 | debugLabel->group(loc->Location.format, x)
161 | log(l1 ++ ":", x1)
162 | log(l2 ++ ":", x2)
163 | log(l3 ++ ":", x3)
164 | log(l4 ++ ":", x4)
165 | groupEnd()
166 | }
167 |
168 | let debug5 = (
169 | loc: Location.t,
170 | x: 'x,
171 | (l1, x1): (string, 'x1),
172 | (l2, x2): (string, 'x2),
173 | (l3, x3): (string, 'x3),
174 | (l4, x4): (string, 'x4),
175 | (l5, x5): (string, 'x5),
176 | ) => {
177 | debugLabel->group(loc->Location.format, x)
178 | log(l1 ++ ":", x1)
179 | log(l2 ++ ":", x2)
180 | log(l3 ++ ":", x3)
181 | log(l4 ++ ":", x4)
182 | log(l5 ++ ":", x5)
183 | groupEnd()
184 | }
185 |
186 | let debug6 = (
187 | loc: Location.t,
188 | x: 'x,
189 | (l1, x1): (string, 'x1),
190 | (l2, x2): (string, 'x2),
191 | (l3, x3): (string, 'x3),
192 | (l4, x4): (string, 'x4),
193 | (l5, x5): (string, 'x5),
194 | (l6, x6): (string, 'x6),
195 | ) => {
196 | debugLabel->group(loc->Location.format, x)
197 | log(l1 ++ ":", x1)
198 | log(l2 ++ ":", x2)
199 | log(l3 ++ ":", x3)
200 | log(l4 ++ ":", x4)
201 | log(l5 ++ ":", x5)
202 | log(l6 ++ ":", x6)
203 | groupEnd()
204 | }
205 |
206 | let debug7 = (
207 | loc: Location.t,
208 | x: 'x,
209 | (l1, x1): (string, 'x1),
210 | (l2, x2): (string, 'x2),
211 | (l3, x3): (string, 'x3),
212 | (l4, x4): (string, 'x4),
213 | (l5, x5): (string, 'x5),
214 | (l6, x6): (string, 'x6),
215 | (l7, x7): (string, 'x7),
216 | ) => {
217 | debugLabel->group(loc->Location.format, x)
218 | log(l1 ++ ":", x1)
219 | log(l2 ++ ":", x2)
220 | log(l3 ++ ":", x3)
221 | log(l4 ++ ":", x4)
222 | log(l5 ++ ":", x5)
223 | log(l6 ++ ":", x6)
224 | log(l7 ++ ":", x7)
225 | groupEnd()
226 | }
227 |
228 | // Level: Info
229 | let infoLabel = `\u001B[48;2;34;153;221m\u001B[38;2;255;255;255m INFO \u001B[39m\u001B[49m`
230 |
231 | let info = (loc: Location.t, x: 'x) => {
232 | infoLabel->groupCollapsed(loc->Location.format, x)
233 | groupEnd()
234 | }
235 |
236 | let info1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
237 | infoLabel->group(loc->Location.format, x)
238 | log(l1 ++ ":", x1)
239 | groupEnd()
240 | }
241 |
242 | let info2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
243 | infoLabel->group(loc->Location.format, x)
244 | log(l1 ++ ":", x1)
245 | log(l2 ++ ":", x2)
246 | groupEnd()
247 | }
248 |
249 | let info3 = (
250 | loc: Location.t,
251 | x: 'x,
252 | (l1, x1): (string, 'x1),
253 | (l2, x2): (string, 'x2),
254 | (l3, x3): (string, 'x3),
255 | ) => {
256 | infoLabel->group(loc->Location.format, x)
257 | log(l1 ++ ":", x1)
258 | log(l2 ++ ":", x2)
259 | log(l3 ++ ":", x3)
260 | groupEnd()
261 | }
262 |
263 | let info4 = (
264 | loc: Location.t,
265 | x: 'x,
266 | (l1, x1): (string, 'x1),
267 | (l2, x2): (string, 'x2),
268 | (l3, x3): (string, 'x3),
269 | (l4, x4): (string, 'x4),
270 | ) => {
271 | infoLabel->group(loc->Location.format, x)
272 | log(l1 ++ ":", x1)
273 | log(l2 ++ ":", x2)
274 | log(l3 ++ ":", x3)
275 | log(l4 ++ ":", x4)
276 | groupEnd()
277 | }
278 |
279 | let info5 = (
280 | loc: Location.t,
281 | x: 'x,
282 | (l1, x1): (string, 'x1),
283 | (l2, x2): (string, 'x2),
284 | (l3, x3): (string, 'x3),
285 | (l4, x4): (string, 'x4),
286 | (l5, x5): (string, 'x5),
287 | ) => {
288 | infoLabel->group(loc->Location.format, x)
289 | log(l1 ++ ":", x1)
290 | log(l2 ++ ":", x2)
291 | log(l3 ++ ":", x3)
292 | log(l4 ++ ":", x4)
293 | log(l5 ++ ":", x5)
294 | groupEnd()
295 | }
296 |
297 | let info6 = (
298 | loc: Location.t,
299 | x: 'x,
300 | (l1, x1): (string, 'x1),
301 | (l2, x2): (string, 'x2),
302 | (l3, x3): (string, 'x3),
303 | (l4, x4): (string, 'x4),
304 | (l5, x5): (string, 'x5),
305 | (l6, x6): (string, 'x6),
306 | ) => {
307 | infoLabel->group(loc->Location.format, x)
308 | log(l1 ++ ":", x1)
309 | log(l2 ++ ":", x2)
310 | log(l3 ++ ":", x3)
311 | log(l4 ++ ":", x4)
312 | log(l5 ++ ":", x5)
313 | log(l6 ++ ":", x6)
314 | groupEnd()
315 | }
316 |
317 | let info7 = (
318 | loc: Location.t,
319 | x: 'x,
320 | (l1, x1): (string, 'x1),
321 | (l2, x2): (string, 'x2),
322 | (l3, x3): (string, 'x3),
323 | (l4, x4): (string, 'x4),
324 | (l5, x5): (string, 'x5),
325 | (l6, x6): (string, 'x6),
326 | (l7, x7): (string, 'x7),
327 | ) => {
328 | infoLabel->group(loc->Location.format, x)
329 | log(l1 ++ ":", x1)
330 | log(l2 ++ ":", x2)
331 | log(l3 ++ ":", x3)
332 | log(l4 ++ ":", x4)
333 | log(l5 ++ ":", x5)
334 | log(l6 ++ ":", x6)
335 | log(l7 ++ ":", x7)
336 | groupEnd()
337 | }
338 |
339 | // Level: Warn
340 | let warnLabel = `\u001B[48;2;252;228;115m\u001B[38;2;87;58;8m WARNING \u001B[39m\u001B[49m`
341 |
342 | let warn = (loc: Location.t, x: 'x) => {
343 | warnLabel->groupCollapsed(loc->Location.format, x)
344 | groupEnd()
345 | }
346 |
347 | let warn1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
348 | warnLabel->group(loc->Location.format, x)
349 | log(l1 ++ ":", x1)
350 | groupEnd()
351 | }
352 |
353 | let warn2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
354 | warnLabel->group(loc->Location.format, x)
355 | log(l1 ++ ":", x1)
356 | log(l2 ++ ":", x2)
357 | groupEnd()
358 | }
359 |
360 | let warn3 = (
361 | loc: Location.t,
362 | x: 'x,
363 | (l1, x1): (string, 'x1),
364 | (l2, x2): (string, 'x2),
365 | (l3, x3): (string, 'x3),
366 | ) => {
367 | warnLabel->group(loc->Location.format, x)
368 | log(l1 ++ ":", x1)
369 | log(l2 ++ ":", x2)
370 | log(l3 ++ ":", x3)
371 | groupEnd()
372 | }
373 |
374 | let warn4 = (
375 | loc: Location.t,
376 | x: 'x,
377 | (l1, x1): (string, 'x1),
378 | (l2, x2): (string, 'x2),
379 | (l3, x3): (string, 'x3),
380 | (l4, x4): (string, 'x4),
381 | ) => {
382 | warnLabel->group(loc->Location.format, x)
383 | log(l1 ++ ":", x1)
384 | log(l2 ++ ":", x2)
385 | log(l3 ++ ":", x3)
386 | log(l4 ++ ":", x4)
387 | groupEnd()
388 | }
389 |
390 | let warn5 = (
391 | loc: Location.t,
392 | x: 'x,
393 | (l1, x1): (string, 'x1),
394 | (l2, x2): (string, 'x2),
395 | (l3, x3): (string, 'x3),
396 | (l4, x4): (string, 'x5),
397 | (l5, x5): (string, 'x6),
398 | ) => {
399 | warnLabel->group(loc->Location.format, x)
400 | log(l1 ++ ":", x1)
401 | log(l2 ++ ":", x2)
402 | log(l3 ++ ":", x3)
403 | log(l4 ++ ":", x4)
404 | log(l5 ++ ":", x5)
405 | groupEnd()
406 | }
407 |
408 | let warn6 = (
409 | loc: Location.t,
410 | x: 'x,
411 | (l1, x1): (string, 'x1),
412 | (l2, x2): (string, 'x2),
413 | (l3, x3): (string, 'x3),
414 | (l4, x4): (string, 'x4),
415 | (l5, x5): (string, 'x5),
416 | (l6, x6): (string, 'x6),
417 | ) => {
418 | warnLabel->group(loc->Location.format, x)
419 | log(l1 ++ ":", x1)
420 | log(l2 ++ ":", x2)
421 | log(l3 ++ ":", x3)
422 | log(l4 ++ ":", x4)
423 | log(l5 ++ ":", x5)
424 | log(l6 ++ ":", x6)
425 | groupEnd()
426 | }
427 |
428 | let warn7 = (
429 | loc: Location.t,
430 | x: 'x,
431 | (l1, x1): (string, 'x1),
432 | (l2, x2): (string, 'x2),
433 | (l3, x3): (string, 'x3),
434 | (l4, x4): (string, 'x4),
435 | (l5, x5): (string, 'x5),
436 | (l6, x6): (string, 'x6),
437 | (l7, x7): (string, 'x7),
438 | ) => {
439 | warnLabel->group(loc->Location.format, x)
440 | log(l1 ++ ":", x1)
441 | log(l2 ++ ":", x2)
442 | log(l3 ++ ":", x3)
443 | log(l4 ++ ":", x4)
444 | log(l5 ++ ":", x5)
445 | log(l6 ++ ":", x6)
446 | log(l7 ++ ":", x7)
447 | groupEnd()
448 | }
449 |
450 | // Level: Error
451 | let errorLabel = `\u001B[48;2;209;26;26m\u001B[38;2;255;255;255m ERROR \u001B[39m\u001B[49m`
452 |
453 | let error = (loc: Location.t, x: 'x) => {
454 | errorLabel->groupCollapsed(loc->Location.format, x)
455 | groupEnd()
456 | }
457 |
458 | let error1 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1)) => {
459 | errorLabel->group(loc->Location.format, x)
460 | log(l1 ++ ":", x1)
461 | groupEnd()
462 | }
463 |
464 | let error2 = (loc: Location.t, x: 'x, (l1, x1): (string, 'x1), (l2, x2): (string, 'x2)) => {
465 | errorLabel->group(loc->Location.format, x)
466 | log(l1 ++ ":", x1)
467 | log(l2 ++ ":", x2)
468 | groupEnd()
469 | }
470 |
471 | let error3 = (
472 | loc: Location.t,
473 | x: 'x,
474 | (l1, x1): (string, 'x1),
475 | (l2, x2): (string, 'x2),
476 | (l3, x3): (string, 'x3),
477 | ) => {
478 | errorLabel->group(loc->Location.format, x)
479 | log(l1 ++ ":", x1)
480 | log(l2 ++ ":", x2)
481 | log(l3 ++ ":", x3)
482 | groupEnd()
483 | }
484 |
485 | let error4 = (
486 | loc: Location.t,
487 | x: 'x,
488 | (l1, x1): (string, 'x1),
489 | (l2, x2): (string, 'x2),
490 | (l3, x3): (string, 'x3),
491 | (l4, x4): (string, 'x4),
492 | ) => {
493 | errorLabel->group(loc->Location.format, x)
494 | log(l1 ++ ":", x1)
495 | log(l2 ++ ":", x2)
496 | log(l3 ++ ":", x3)
497 | log(l4 ++ ":", x4)
498 | groupEnd()
499 | }
500 |
501 | let error5 = (
502 | loc: Location.t,
503 | x: 'x,
504 | (l1, x1): (string, 'x1),
505 | (l2, x2): (string, 'x2),
506 | (l3, x3): (string, 'x3),
507 | (l4, x4): (string, 'x4),
508 | (l5, x5): (string, 'x5),
509 | ) => {
510 | errorLabel->group(loc->Location.format, x)
511 | log(l1 ++ ":", x1)
512 | log(l2 ++ ":", x2)
513 | log(l3 ++ ":", x3)
514 | log(l4 ++ ":", x4)
515 | log(l5 ++ ":", x5)
516 | groupEnd()
517 | }
518 |
519 | let error6 = (
520 | loc: Location.t,
521 | x: 'x,
522 | (l1, x1): (string, 'x1),
523 | (l2, x2): (string, 'x2),
524 | (l3, x3): (string, 'x3),
525 | (l4, x4): (string, 'x4),
526 | (l5, x5): (string, 'x5),
527 | (l6, x6): (string, 'x6),
528 | ) => {
529 | errorLabel->group(loc->Location.format, x)
530 | log(l1 ++ ":", x1)
531 | log(l2 ++ ":", x2)
532 | log(l3 ++ ":", x3)
533 | log(l4 ++ ":", x4)
534 | log(l5 ++ ":", x5)
535 | log(l6 ++ ":", x6)
536 | groupEnd()
537 | }
538 |
539 | let error7 = (
540 | loc: Location.t,
541 | x: 'x,
542 | (l1, x1): (string, 'x1),
543 | (l2, x2): (string, 'x2),
544 | (l3, x3): (string, 'x3),
545 | (l4, x4): (string, 'x4),
546 | (l5, x5): (string, 'x5),
547 | (l6, x6): (string, 'x6),
548 | (l7, x7): (string, 'x7),
549 | ) => {
550 | errorLabel->group(loc->Location.format, x)
551 | log(l1 ++ ":", x1)
552 | log(l2 ++ ":", x2)
553 | log(l3 ++ ":", x3)
554 | log(l4 ++ ":", x4)
555 | log(l5 ++ ":", x5)
556 | log(l6 ++ ":", x6)
557 | log(l7 ++ ":", x7)
558 | groupEnd()
559 | }
560 |
--------------------------------------------------------------------------------
/lib/src/loggers/Node.resi:
--------------------------------------------------------------------------------
1 | include Interface.Logger
2 |
--------------------------------------------------------------------------------
/lib/src/loggers/Universal.res:
--------------------------------------------------------------------------------
1 | @val external window: Dom.window = "window"
2 |
3 | // NOTE: Unfortunately, it pulls in currying.
4 | // Not sure if it's possible to uncurry without changing the interface, which would be a breaking change.
5 | include unpack(
6 | window->Js.typeof == "undefined"
7 | ? module(Node: Interface.Logger)
8 | : module(Browser: Interface.Logger)
9 | )
10 |
--------------------------------------------------------------------------------
/lib/src/loggers/Universal.resi:
--------------------------------------------------------------------------------
1 | include Interface.Logger
2 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rescript-logger",
3 | "version": "4.0.0",
4 | "description": "Logging implementation for ReScript",
5 | "author": "Alex Fedoseev ",
6 | "license": "MIT",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/shakacode/rescript-logger.git"
10 | },
11 | "private": true,
12 | "workspaces": [
13 | "lib",
14 | "examples"
15 | ],
16 | "files": [
17 | "src",
18 | "bin",
19 | "rescript.json",
20 | "postinstall.js"
21 | ],
22 | "keywords": [
23 | "log",
24 | "logger",
25 | "logging",
26 | "rescript",
27 | "reason",
28 | "reasonml",
29 | "ocaml",
30 | "bucklescript"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/ppx/bin/Bin.ml:
--------------------------------------------------------------------------------
1 | Ppxlib.Driver.run_as_ppx_rewriter ()
2 |
--------------------------------------------------------------------------------
/ppx/bin/dune:
--------------------------------------------------------------------------------
1 | (env
2 | (static
3 | (flags
4 | (:standard -ccopt -static))))
5 |
6 | (executable
7 | (package rescript-logger-ppx)
8 | (name bin)
9 | (public_name rescript-logger-ppx)
10 | (libraries rescript-logger-ppx.lib))
11 |
--------------------------------------------------------------------------------
/ppx/lib/Lib.ml:
--------------------------------------------------------------------------------
1 | open Ppxlib
2 | open Ast_helper
3 |
4 | module Env = struct
5 | let level = "RES_LOG"
6 | let logger = "RES_LOGGER"
7 | let only = "RES_LOG_ONLY"
8 | end
9 |
10 | module Delimiter = struct
11 | let key_val = '='
12 | let entries = ','
13 | end
14 |
15 | module Level = struct
16 | type t =
17 | | Trace
18 | | Debug
19 | | Info
20 | | Warn
21 | | Error
22 |
23 | let from_string =
24 | function
25 | | "*"
26 | | "trace" -> Some(Trace)
27 | | "debug" -> Some(Debug)
28 | | "info" -> Some(Info)
29 | | "warn"
30 | | "warning" -> Some(Warn)
31 | | "error" -> Some(Error)
32 | | "off" -> None
33 | | _ as x -> failwith ("Invalid log level: " ^ x);
34 | end
35 |
36 | module Fn = struct
37 | type t =
38 | | Trace
39 | | Trace1
40 | | Trace2
41 | | Trace3
42 | | Trace4
43 | | Trace5
44 | | Trace6
45 | | Trace7
46 | | Debug
47 | | Debug1
48 | | Debug2
49 | | Debug3
50 | | Debug4
51 | | Debug5
52 | | Debug6
53 | | Debug7
54 | | Info
55 | | Info1
56 | | Info2
57 | | Info3
58 | | Info4
59 | | Info5
60 | | Info6
61 | | Info7
62 | | Warn
63 | | Warn1
64 | | Warn2
65 | | Warn3
66 | | Warn4
67 | | Warn5
68 | | Warn6
69 | | Warn7
70 | | Error
71 | | Error1
72 | | Error2
73 | | Error3
74 | | Error4
75 | | Error5
76 | | Error6
77 | | Error7
78 |
79 | let to_string =
80 | function
81 | | Trace -> "trace"
82 | | Trace1 -> "trace1"
83 | | Trace2 -> "trace2"
84 | | Trace3 -> "trace3"
85 | | Trace4 -> "trace4"
86 | | Trace5 -> "trace5"
87 | | Trace6 -> "trace6"
88 | | Trace7 -> "trace7"
89 | | Debug -> "debug"
90 | | Debug1 -> "debug1"
91 | | Debug2 -> "debug2"
92 | | Debug3 -> "debug3"
93 | | Debug4 -> "debug4"
94 | | Debug5 -> "debug5"
95 | | Debug6 -> "debug6"
96 | | Debug7 -> "debug7"
97 | | Info -> "info"
98 | | Info1 -> "info1"
99 | | Info2 -> "info2"
100 | | Info3 -> "info3"
101 | | Info4 -> "info4"
102 | | Info5 -> "info5"
103 | | Info6 -> "info6"
104 | | Info7 -> "info7"
105 | | Warn -> "warn"
106 | | Warn1 -> "warn1"
107 | | Warn2 -> "warn2"
108 | | Warn3 -> "warn3"
109 | | Warn4 -> "warn4"
110 | | Warn5 -> "warn5"
111 | | Warn6 -> "warn6"
112 | | Warn7 -> "warn7"
113 | | Error -> "error"
114 | | Error1 -> "error1"
115 | | Error2 -> "error2"
116 | | Error3 -> "error3"
117 | | Error4 -> "error4"
118 | | Error5 -> "error5"
119 | | Error6 -> "error6"
120 | | Error7 -> "error7"
121 | end
122 |
123 | module LibArg = struct
124 | let box: string option ref = ref None
125 |
126 | let set x = box := Some x
127 | let reset () = box := None
128 |
129 | let key = "--lib"
130 | let spec = Arg.String set
131 | let doc = " Library name"
132 | end
133 |
134 | module Lib = struct
135 | let from_args () =
136 | if Sys.argv |> Array.length > 1
137 | then
138 | match Sys.argv.(1) |> String.split_on_char Delimiter.key_val with
139 | | "--lib"::lib::[] -> Some lib
140 | | _ -> None
141 | else
142 | None
143 | end
144 |
145 | let level =
146 | let default = Level.Warn in
147 | let lib = Lib.from_args () in
148 |
149 | match Env.level |> Sys.getenv with
150 | | exception Not_found ->
151 | (
152 | match lib with
153 | | Some _ -> None
154 | | None -> Some default
155 | )
156 | | _ as raw_env_entries ->
157 | let entries = raw_env_entries |> String.split_on_char Delimiter.entries in
158 | match (entries, lib) with
159 | | ([], _) -> failwith ("Empty value of environment variable " ^ Env.level)
160 | | ((level::[] | level::_), None) -> level |> Level.from_string
161 | | (entries, Some lib) ->
162 | entries |>
163 | (
164 | List.fold_left
165 | (
166 | fun res entry ->
167 | match res with
168 | | Some res -> Some res
169 | | None ->
170 | match entry |> String.split_on_char Delimiter.key_val with
171 | | lib'::level::[] when lib' = lib -> level |> Level.from_string
172 | | _ -> None
173 | )
174 | None
175 | )
176 |
177 | let logger =
178 | let default = "ReScriptLogger.Browser" in
179 |
180 | let rec build ?lid xs =
181 | match (lid, xs) with
182 | | (None, x::xs) -> xs |> build ~lid: (Lident x)
183 | | (Some lid, x::xs) -> xs |> build ~lid: (Ldot (lid, x))
184 | | (Some lid, []) -> lid
185 | | (None, []) -> failwith "Empty logger" in
186 |
187 | let parse x = x |> String.split_on_char '.' |> build in
188 |
189 | match Env.logger |> Sys.getenv with
190 | | "" -> default |> parse
191 | | exception Not_found -> default |> parse
192 | | _ as x -> x |> parse
193 |
194 | let only: string list list option =
195 | match Env.only |> Sys.getenv with
196 | | "" -> None
197 | | exception Not_found -> None
198 | | _ as x ->
199 | Some (
200 | x
201 | |> String.split_on_char ','
202 | |> List.map (String.split_on_char '.')
203 | )
204 |
205 | let rec should_log path only =
206 | match (path, only) with
207 | | (_, []) -> true
208 | | ([], _::_) -> false
209 | | (p::path, o::only) ->
210 | if o <> p
211 | then false
212 | else should_log path only
213 |
214 | let should_log ~only path =
215 | let path =
216 | path
217 | |> Code_path.fully_qualified_path
218 | |> String.split_on_char '.' in
219 | let finder = path |> should_log in
220 | match only |> List.find_opt finder with
221 | | Some _ -> true
222 | | None -> false
223 |
224 | module Ast = struct
225 | let rec list ?expr xs =
226 | match (expr, xs) with
227 | | (None, []) ->
228 | Exp.construct
229 | {txt = Lident "[]"; loc = !default_loc}
230 | None
231 | | (Some expr, []) ->
232 | Exp.construct
233 | {txt = Lident "::"; loc = !default_loc}
234 | (Some expr)
235 | | (None, x::xs) ->
236 | xs |> (
237 | list
238 | ~expr:
239 | (Exp.tuple [
240 | Exp.constant (Const.string x);
241 | Exp.construct
242 | {txt = Lident "[]"; loc = !default_loc}
243 | None
244 | ])
245 | )
246 | | (Some expr, x::xs) ->
247 | xs |> (
248 | list
249 | ~expr:
250 | (Exp.tuple [
251 | Exp.constant (Const.string x);
252 | Exp.construct
253 | {txt = Lident "::"; loc = !default_loc}
254 | (Some expr)
255 | ])
256 | )
257 |
258 | let module_arg cp =
259 | Exp.record
260 | [
261 | (
262 | {txt = Lident "rootModule"; loc = !default_loc},
263 | Exp.constant (Const.string (cp |> Code_path.main_module_name))
264 | );
265 | (
266 | {txt = Lident "subModulePath"; loc = !default_loc},
267 | cp |> Code_path.submodule_path |> List.rev |> list
268 | );
269 | (
270 | {txt = Lident "value"; loc = !default_loc},
271 | match cp |> Code_path.value with
272 | | Some value ->
273 | Exp.construct
274 | {txt = Lident "Some"; loc = !default_loc}
275 | (Some (Exp.constant (Const.string value)))
276 | | None ->
277 | Exp.construct
278 | {txt = Lident "None"; loc = !default_loc}
279 | None
280 | );
281 | (
282 | {txt = Lident "fullPath"; loc = !default_loc},
283 | Exp.constant (Const.string (cp |> Code_path.fully_qualified_path))
284 | );
285 | ]
286 | None
287 |
288 | let logger fn =
289 | Exp.ident {txt = Ldot (logger, fn |> Fn.to_string); loc = !default_loc}
290 |
291 | let log fn cp x =
292 | Exp.apply
293 | (fn |> logger)
294 | [
295 | (Nolabel, cp |> module_arg);
296 | (Nolabel, x);
297 | ]
298 |
299 | let log1 fn cp x1 x =
300 | Exp.apply
301 | (fn |> logger)
302 | [
303 | (Nolabel, cp |> module_arg);
304 | (Nolabel, x);
305 | (Nolabel, x1);
306 | ]
307 |
308 | let log2 fn cp x1 x2 x =
309 | Exp.apply
310 | (fn |> logger)
311 | [
312 | (Nolabel, cp |> module_arg);
313 | (Nolabel, x);
314 | (Nolabel, x1);
315 | (Nolabel, x2);
316 | ]
317 |
318 | let log3 fn cp x1 x2 x3 x =
319 | Exp.apply
320 | (fn |> logger)
321 | [
322 | (Nolabel, cp |> module_arg);
323 | (Nolabel, x);
324 | (Nolabel, x1);
325 | (Nolabel, x2);
326 | (Nolabel, x3);
327 | ]
328 |
329 | let log4 fn cp x1 x2 x3 x4 x =
330 | Exp.apply
331 | (fn |> logger)
332 | [
333 | (Nolabel, cp |> module_arg);
334 | (Nolabel, x);
335 | (Nolabel, x1);
336 | (Nolabel, x2);
337 | (Nolabel, x3);
338 | (Nolabel, x4);
339 | ]
340 |
341 | let log5 fn cp x1 x2 x3 x4 x5 x =
342 | Exp.apply
343 | (fn |> logger)
344 | [
345 | (Nolabel, cp |> module_arg);
346 | (Nolabel, x);
347 | (Nolabel, x1);
348 | (Nolabel, x2);
349 | (Nolabel, x3);
350 | (Nolabel, x4);
351 | (Nolabel, x5);
352 | ]
353 |
354 | let log6 fn cp x1 x2 x3 x4 x5 x6 x =
355 | Exp.apply
356 | (fn |> logger)
357 | [
358 | (Nolabel, cp |> module_arg);
359 | (Nolabel, x);
360 | (Nolabel, x1);
361 | (Nolabel, x2);
362 | (Nolabel, x3);
363 | (Nolabel, x4);
364 | (Nolabel, x5);
365 | (Nolabel, x6);
366 | ]
367 |
368 | let log7 fn cp x1 x2 x3 x4 x5 x6 x7 x =
369 | Exp.apply
370 | (fn |> logger)
371 | [
372 | (Nolabel, cp |> module_arg);
373 | (Nolabel, x);
374 | (Nolabel, x1);
375 | (Nolabel, x2);
376 | (Nolabel, x3);
377 | (Nolabel, x4);
378 | (Nolabel, x5);
379 | (Nolabel, x6);
380 | (Nolabel, x7);
381 | ]
382 |
383 | let nothing =
384 | Exp.construct
385 | {txt = Lident "()"; loc = !default_loc}
386 | None
387 | end
388 |
389 | module LogExt = struct
390 | open Ast
391 |
392 | let transform
393 | ~ext_level: (ext_level: Level.t)
394 | ~env_level: (env_level: Level.t option)
395 | ~context: (context: Expansion_context.Extension.t)
396 | (payload: payload)
397 | =
398 | let cp = context |> Expansion_context.Extension.code_path in
399 | match only with
400 | | Some only when not (cp |> should_log ~only) -> nothing
401 | | Some _
402 | | None ->
403 | match payload with
404 | | PStr({pstr_desc = Pstr_eval (x, _)}::[]) ->
405 | (
406 | match (ext_level, env_level) with
407 | | (Trace, Some (Trace)) -> x |> log Trace cp
408 | | (Debug, Some (Trace | Debug)) -> x |> log Debug cp
409 | | (Info, Some (Trace | Debug | Info)) -> x |> log Info cp
410 | | (Warn, Some (Trace | Debug | Info | Warn)) -> x |> log Warn cp
411 | | (Error, Some (Trace | Debug | Info | Warn | Error)) -> x |> log Error cp
412 | | ((Trace | Debug | Info | Warn | Error), _) -> nothing
413 | )
414 |
415 | | PStr(
416 | {pstr_desc = Pstr_eval (x, _)}::
417 | {pstr_desc = Pstr_eval (x1, _)}::[]) ->
418 | (
419 | match (ext_level, env_level) with
420 | | (Trace, Some (Trace)) -> x |> log1 Trace1 cp x1
421 | | (Debug, Some (Trace | Debug)) -> x |> log1 Debug1 cp x1
422 | | (Info, Some (Trace | Debug | Info)) -> x |> log1 Info1 cp x1
423 | | (Warn, Some (Trace | Debug | Info | Warn)) -> x |> log1 Warn1 cp x1
424 | | (Error, Some (Trace | Debug | Info | Warn | Error)) -> x |> log1 Error1 cp x1
425 | | ((Trace | Debug | Info | Warn | Error), _) -> nothing
426 | )
427 |
428 | | PStr(
429 | {pstr_desc = Pstr_eval (x, _)}::
430 | {pstr_desc = Pstr_eval (x1, _)}::
431 | {pstr_desc = Pstr_eval (x2, _)}::[]) ->
432 | (
433 | match (ext_level, env_level) with
434 | | (Trace, Some (Trace)) -> x |> log2 Trace2 cp x1 x2
435 | | (Debug, Some (Trace | Debug)) -> x |> log2 Debug2 cp x1 x2
436 | | (Info, Some (Trace | Debug | Info)) -> x |> log2 Info2 cp x1 x2
437 | | (Warn, Some (Trace | Debug | Info | Warn)) -> x |> log2 Warn2 cp x1 x2
438 | | (Error, Some (Trace | Debug | Info | Warn | Error)) -> x |> log2 Error2 cp x1 x2
439 | | ((Trace | Debug | Info | Warn | Error), _) -> nothing
440 | )
441 |
442 | | PStr(
443 | {pstr_desc = Pstr_eval (x, _)}::
444 | {pstr_desc = Pstr_eval (x1, _)}::
445 | {pstr_desc = Pstr_eval (x2, _)}::
446 | {pstr_desc = Pstr_eval (x3, _)}::[]) ->
447 | (
448 | match (ext_level, env_level) with
449 | | (Trace, Some (Trace)) -> x |> log3 Trace3 cp x1 x2 x3
450 | | (Debug, Some (Trace | Debug)) -> x |> log3 Debug3 cp x1 x2 x3
451 | | (Info, Some (Trace | Debug | Info)) -> x |> log3 Info3 cp x1 x2 x3
452 | | (Warn, Some (Trace | Debug | Info | Warn)) -> x |> log3 Warn3 cp x1 x2 x3
453 | | (Error, Some (Trace | Debug | Info | Warn | Error)) -> x |> log3 Error3 cp x1 x2 x3
454 | | ((Trace | Debug | Info | Warn | Error), _) -> nothing
455 | )
456 |
457 | | PStr(
458 | {pstr_desc = Pstr_eval (x, _)}::
459 | {pstr_desc = Pstr_eval (x1, _)}::
460 | {pstr_desc = Pstr_eval (x2, _)}::
461 | {pstr_desc = Pstr_eval (x3, _)}::
462 | {pstr_desc = Pstr_eval (x4, _)}::[]) ->
463 | (
464 | match (ext_level, env_level) with
465 | | (Trace, Some (Trace)) -> x |> log4 Trace4 cp x1 x2 x3 x4
466 | | (Debug, Some (Trace | Debug)) -> x |> log4 Debug4 cp x1 x2 x3 x4
467 | | (Info, Some (Trace | Debug | Info)) -> x |> log4 Info4 cp x1 x2 x3 x4
468 | | (Warn, Some (Trace | Debug | Info | Warn)) -> x |> log4 Warn4 cp x1 x2 x3 x4
469 | | (Error, Some (Trace | Debug | Info | Warn | Error)) -> x |> log4 Error4 cp x1 x2 x3 x4
470 | | ((Trace | Debug | Info | Warn | Error), _) -> nothing
471 | )
472 |
473 | | PStr(
474 | {pstr_desc = Pstr_eval (x, _)}::
475 | {pstr_desc = Pstr_eval (x1, _)}::
476 | {pstr_desc = Pstr_eval (x2, _)}::
477 | {pstr_desc = Pstr_eval (x3, _)}::
478 | {pstr_desc = Pstr_eval (x4, _)}::
479 | {pstr_desc = Pstr_eval (x5, _)}::[]) ->
480 | (
481 | match (ext_level, env_level) with
482 | | (Trace, Some (Trace)) -> x |> log5 Trace5 cp x1 x2 x3 x4 x5
483 | | (Debug, Some (Trace | Debug)) -> x |> log5 Debug5 cp x1 x2 x3 x4 x5
484 | | (Info, Some (Trace | Debug | Info)) -> x |> log5 Info5 cp x1 x2 x3 x4 x5
485 | | (Warn, Some (Trace | Debug | Info | Warn)) -> x |> log5 Warn5 cp x1 x2 x3 x4 x5
486 | | (Error, Some (Trace | Debug | Info | Warn | Error)) -> x |> log5 Error5 cp x1 x2 x3 x4 x5
487 | | ((Trace | Debug | Info | Warn | Error), _) -> nothing
488 | )
489 |
490 | | PStr(
491 | {pstr_desc = Pstr_eval (x, _)}::
492 | {pstr_desc = Pstr_eval (x1, _)}::
493 | {pstr_desc = Pstr_eval (x2, _)}::
494 | {pstr_desc = Pstr_eval (x3, _)}::
495 | {pstr_desc = Pstr_eval (x4, _)}::
496 | {pstr_desc = Pstr_eval (x5, _)}::
497 | {pstr_desc = Pstr_eval (x6, _)}::[]) ->
498 | (
499 | match (ext_level, env_level) with
500 | | (Trace, Some (Trace)) -> x |> log6 Trace6 cp x1 x2 x3 x4 x5 x6
501 | | (Debug, Some (Trace | Debug)) -> x |> log6 Debug6 cp x1 x2 x3 x4 x5 x6
502 | | (Info, Some (Trace | Debug | Info)) -> x |> log6 Info6 cp x1 x2 x3 x4 x5 x6
503 | | (Warn, Some (Trace | Debug | Info | Warn)) -> x |> log6 Warn6 cp x1 x2 x3 x4 x5 x6
504 | | (Error, Some (Trace | Debug | Info | Warn | Error)) -> x |> log6 Error6 cp x1 x2 x3 x4 x5 x6
505 | | ((Trace | Debug | Info | Warn | Error), _) -> nothing
506 | )
507 |
508 | | PStr(
509 | {pstr_desc = Pstr_eval (x, _)}::
510 | {pstr_desc = Pstr_eval (x1, _)}::
511 | {pstr_desc = Pstr_eval (x2, _)}::
512 | {pstr_desc = Pstr_eval (x3, _)}::
513 | {pstr_desc = Pstr_eval (x4, _)}::
514 | {pstr_desc = Pstr_eval (x5, _)}::
515 | {pstr_desc = Pstr_eval (x6, _)}::
516 | {pstr_desc = Pstr_eval (x7, _)}::[]) ->
517 | (
518 | match (ext_level, env_level) with
519 | | (Trace, Some (Trace)) -> x |> log7 Trace7 cp x1 x2 x3 x4 x5 x6 x7
520 | | (Debug, Some (Trace | Debug)) -> x |> log7 Debug7 cp x1 x2 x3 x4 x5 x6 x7
521 | | (Info, Some (Trace | Debug | Info)) -> x |> log7 Info7 cp x1 x2 x3 x4 x5 x6 x7
522 | | (Warn, Some (Trace | Debug | Info | Warn)) -> x |> log7 Warn7 cp x1 x2 x3 x4 x5 x6 x7
523 | | (Error, Some (Trace | Debug | Info | Warn | Error)) -> x |> log7 Error7 cp x1 x2 x3 x4 x5 x6 x7
524 | | ((Trace | Debug | Info | Warn | Error), _) -> nothing
525 | )
526 |
527 | | _ ->
528 | Location.raise_errorf
529 | ~loc: (context |> Expansion_context.Extension.extension_point_loc)
530 | "Too many arguments"
531 |
532 | let trace =
533 | Context_free.Rule.extension
534 | (
535 | Extension.V3.declare
536 | "log.trace"
537 | Extension.Context.expression
538 | Ast_pattern.__
539 | (
540 | fun ~ctxt ->
541 | transform
542 | ~ext_level: Trace
543 | ~env_level: level
544 | ~context: ctxt
545 | )
546 | )
547 |
548 | let debug =
549 | Context_free.Rule.extension
550 | (
551 | Extension.V3.declare
552 | "log.debug"
553 | Extension.Context.expression
554 | Ast_pattern.__
555 | (
556 | fun ~ctxt ->
557 | transform
558 | ~ext_level: Debug
559 | ~env_level: level
560 | ~context: ctxt
561 | )
562 | )
563 |
564 | let info =
565 | Context_free.Rule.extension
566 | (
567 | Extension.V3.declare
568 | "log.info"
569 | Extension.Context.expression
570 | Ast_pattern.__
571 | (
572 | fun ~ctxt ->
573 | transform
574 | ~ext_level: Info
575 | ~env_level: level
576 | ~context: ctxt
577 | )
578 | )
579 |
580 | let warn =
581 | Context_free.Rule.extension
582 | (
583 | Extension.V3.declare
584 | "log.warn"
585 | Extension.Context.expression
586 | Ast_pattern.__
587 | (
588 | fun ~ctxt ->
589 | transform
590 | ~ext_level: Warn
591 | ~env_level: level
592 | ~context: ctxt
593 | )
594 | )
595 |
596 | let error =
597 | Context_free.Rule.extension
598 | (
599 | Extension.V3.declare
600 | "log.error"
601 | Extension.Context.expression
602 | Ast_pattern.__
603 | (
604 | fun ~ctxt ->
605 | transform
606 | ~ext_level: Error
607 | ~env_level: level
608 | ~context: ctxt
609 | )
610 | )
611 | end
612 |
613 | module LogAttr = struct
614 | open Ast
615 |
616 | let attr =
617 | Attribute.declare
618 | "log"
619 | Attribute.Context.expression
620 | (
621 | T
622 | (
623 | fun ctx loc x k ->
624 | match x with
625 | | PStr [] ->
626 | ctx.matched <- ctx.matched + 1;
627 | None |> k
628 | | PStr(
629 | {
630 | pstr_desc =
631 | Pstr_eval(
632 | {pexp_desc = Pexp_constant (Pconst_string (x, _loc, _))},
633 | _
634 | )
635 | }::[]) ->
636 | ctx.matched <- ctx.matched + 1;
637 | Some x |> k
638 | | _ -> Location.raise_errorf ~loc "Expected string"
639 | )
640 | )
641 | (fun x -> x)
642 |
643 | let format ns ctx tag =
644 | match ns with
645 | | None ->
646 | (
647 | match ctx with
648 | | `WithoutPayload -> Exp.constant (Pconst_string (tag, !default_loc, None))
649 | | `WithPayload -> Exp.constant (Pconst_string (tag ^ " with payload", !default_loc, None))
650 | | `WithNotLoggedPayload -> Exp.constant (Pconst_string (tag ^ " with payload (not logged)", !default_loc, None))
651 | )
652 | | Some ns ->
653 | let __ = "::" in
654 | match ctx with
655 | | `WithoutPayload -> Exp.constant (Pconst_string (ns ^ __ ^ tag, !default_loc, None))
656 | | `WithPayload -> Exp.constant (Pconst_string (ns ^ __ ^ tag ^ " with payload", !default_loc, None))
657 | | `WithNotLoggedPayload -> Exp.constant (Pconst_string (ns ^ __ ^ tag ^ " with payload (not logged)", !default_loc, None))
658 |
659 | let payload x =
660 | Exp.tuple
661 | [
662 | Exp.constant (Pconst_string (x, !default_loc, None));
663 | Exp.ident {txt = Lident x; loc = !default_loc};
664 | ]
665 |
666 | let transform
667 | ~env_level: (env_level: Level.t option)
668 | ~namespace: (namespace: string option)
669 | ~context: (context: Expansion_context.Base.t)
670 | (expr: expression)
671 | =
672 | (* TODO: Use Base getters once ppxlib is updated *)
673 | let context =
674 | Expansion_context.Extension.make
675 | ~extension_point_loc: expr.pexp_loc
676 | ~base: context
677 | () in
678 | let cp = context |> Expansion_context.Extension.code_path in
679 |
680 | match only with
681 | | Some only when not (cp |> should_log ~only) -> expr
682 | | Some _
683 | | None ->
684 | match (expr, env_level) with
685 | |
686 | (
687 | {pexp_desc = Pexp_match (_, _)} as expr,
688 | (Some (Info | Warn | Error) | None)
689 | ) -> expr
690 | |
691 | (
692 | {pexp_desc = Pexp_match (match_, cases); pexp_loc; pexp_attributes},
693 | Some(Trace | Debug)
694 | ) ->
695 | Exp.match_
696 | ~loc: pexp_loc
697 | ~attrs: pexp_attributes
698 | match_
699 | (
700 | cases
701 | |> List.map
702 | (
703 | function
704 | |
705 | {
706 | pc_lhs = {ppat_desc = Ppat_construct ({txt = Lident tag}, None)} as pattern;
707 | pc_rhs = branch;
708 | } ->
709 | Exp.case
710 | pattern
711 | (
712 | Exp.sequence
713 | (tag |> format namespace `WithoutPayload |> log Debug cp)
714 | branch
715 | )
716 | |
717 | {
718 | pc_lhs =
719 | {
720 | ppat_desc =
721 | Ppat_construct (
722 | {txt = Lident tag},
723 | Some(
724 | _,
725 | {
726 | ppat_desc =
727 | (
728 | (Ppat_tuple ({ppat_desc = Ppat_var {txt = x1}}::[]))(* Reason *)
729 | | (Ppat_var {txt = x1}) (* ReScript *)
730 | )
731 | }
732 | )
733 | )
734 | } as pattern;
735 | pc_rhs = branch;
736 | } ->
737 | Exp.case
738 | pattern
739 | (
740 | Exp.sequence
741 | (
742 | tag
743 | |> format namespace `WithPayload
744 | |> log1 Debug1 cp (x1 |> payload)
745 | )
746 | branch
747 | )
748 | |
749 | {
750 | pc_lhs =
751 | {
752 | ppat_desc =
753 | Ppat_construct (
754 | {txt = Lident tag},
755 | Some(
756 | _,
757 | {
758 | ppat_desc =
759 | Ppat_tuple (
760 | {ppat_desc = Ppat_var {txt = x1}}::
761 | {ppat_desc = Ppat_var {txt = x2}}::[]
762 | )
763 | }
764 | )
765 | )
766 | } as pattern;
767 | pc_rhs = branch;
768 | } ->
769 | Exp.case
770 | pattern
771 | (
772 | Exp.sequence
773 | (
774 | tag
775 | |> format namespace `WithPayload
776 | |> log2 Debug2 cp (x1 |> payload) (x2 |> payload)
777 | )
778 | branch
779 | )
780 | |
781 | {
782 | pc_lhs =
783 | {
784 | ppat_desc =
785 | Ppat_construct (
786 | {txt = Lident tag},
787 | Some(
788 | _,
789 | {
790 | ppat_desc =
791 | Ppat_tuple (
792 | {ppat_desc = Ppat_var {txt = x1}}::
793 | {ppat_desc = Ppat_var {txt = x2}}::
794 | {ppat_desc = Ppat_var {txt = x3}}::[]
795 | )
796 | }
797 | )
798 | )
799 | } as pattern;
800 | pc_rhs = branch;
801 | } ->
802 | Exp.case
803 | pattern
804 | (
805 | Exp.sequence
806 | (
807 | tag
808 | |> format namespace `WithPayload
809 | |>
810 | log3
811 | Debug3
812 | cp
813 | (x1 |> payload)
814 | (x2 |> payload)
815 | (x3 |> payload)
816 | )
817 | branch
818 | )
819 | |
820 | {
821 | pc_lhs =
822 | {
823 | ppat_desc =
824 | Ppat_construct (
825 | {txt = Lident tag},
826 | Some(
827 | _,
828 | {
829 | ppat_desc =
830 | Ppat_tuple (
831 | {ppat_desc = Ppat_var {txt = x1}}::
832 | {ppat_desc = Ppat_var {txt = x2}}::
833 | {ppat_desc = Ppat_var {txt = x3}}::
834 | {ppat_desc = Ppat_var {txt = x4}}::[]
835 | )
836 | }
837 | )
838 | )
839 | } as pattern;
840 | pc_rhs = branch;
841 | } ->
842 | Exp.case
843 | pattern
844 | (
845 | Exp.sequence
846 | (
847 | tag
848 | |> format namespace `WithPayload
849 | |>
850 | log4
851 | Debug4
852 | cp
853 | (x1 |> payload)
854 | (x2 |> payload)
855 | (x3 |> payload)
856 | (x4 |> payload)
857 | )
858 | branch
859 | )
860 | |
861 | {
862 | pc_lhs =
863 | {
864 | ppat_desc =
865 | Ppat_construct (
866 | {txt = Lident tag},
867 | Some(
868 | _,
869 | {
870 | ppat_desc =
871 | Ppat_tuple (
872 | {ppat_desc = Ppat_var {txt = x1}}::
873 | {ppat_desc = Ppat_var {txt = x2}}::
874 | {ppat_desc = Ppat_var {txt = x3}}::
875 | {ppat_desc = Ppat_var {txt = x4}}::
876 | {ppat_desc = Ppat_var {txt = x5}}::[]
877 | )
878 | }
879 | )
880 | )
881 | } as pattern;
882 | pc_rhs = branch;
883 | } ->
884 | Exp.case
885 | pattern
886 | (
887 | Exp.sequence
888 | (
889 | tag
890 | |> format namespace `WithPayload
891 | |>
892 | log5
893 | Debug5
894 | cp
895 | (x1 |> payload)
896 | (x2 |> payload)
897 | (x3 |> payload)
898 | (x4 |> payload)
899 | (x5 |> payload)
900 | )
901 | branch
902 | )
903 | |
904 | {
905 | pc_lhs =
906 | {
907 | ppat_desc =
908 | Ppat_construct (
909 | {txt = Lident tag},
910 | Some(
911 | _,
912 | {
913 | ppat_desc =
914 | Ppat_tuple (
915 | {ppat_desc = Ppat_var {txt = x1}}::
916 | {ppat_desc = Ppat_var {txt = x2}}::
917 | {ppat_desc = Ppat_var {txt = x3}}::
918 | {ppat_desc = Ppat_var {txt = x4}}::
919 | {ppat_desc = Ppat_var {txt = x5}}::
920 | {ppat_desc = Ppat_var {txt = x6}}::[]
921 | )
922 | }
923 | )
924 | )
925 | } as pattern;
926 | pc_rhs = branch;
927 | } ->
928 | Exp.case
929 | pattern
930 | (
931 | Exp.sequence
932 | (
933 | tag
934 | |> format namespace `WithPayload
935 | |>
936 | log6
937 | Debug6
938 | cp
939 | (x1 |> payload)
940 | (x2 |> payload)
941 | (x3 |> payload)
942 | (x4 |> payload)
943 | (x5 |> payload)
944 | (x6 |> payload)
945 | )
946 | branch
947 | )
948 | |
949 | {
950 | pc_lhs =
951 | {
952 | ppat_desc =
953 | Ppat_construct (
954 | {txt = Lident tag},
955 | Some(
956 | _,
957 | {
958 | ppat_desc =
959 | Ppat_tuple (
960 | {ppat_desc = Ppat_var {txt = x1}}::
961 | {ppat_desc = Ppat_var {txt = x2}}::
962 | {ppat_desc = Ppat_var {txt = x3}}::
963 | {ppat_desc = Ppat_var {txt = x4}}::
964 | {ppat_desc = Ppat_var {txt = x5}}::
965 | {ppat_desc = Ppat_var {txt = x6}}::
966 | {ppat_desc = Ppat_var {txt = x7}}::[]
967 | )
968 | }
969 | )
970 | )
971 | } as pattern;
972 | pc_rhs = branch;
973 | } ->
974 | Exp.case
975 | pattern
976 | (
977 | Exp.sequence
978 | (
979 | tag
980 | |> format namespace `WithPayload
981 | |>
982 | log7
983 | Debug7
984 | cp
985 | (x1 |> payload)
986 | (x2 |> payload)
987 | (x3 |> payload)
988 | (x4 |> payload)
989 | (x5 |> payload)
990 | (x6 |> payload)
991 | (x7 |> payload)
992 | )
993 | branch
994 | )
995 | |
996 | {
997 | pc_lhs = {ppat_desc = Ppat_construct({txt = Lident tag}, Some _)} as pattern;
998 | pc_rhs = branch;
999 | } ->
1000 | Exp.case
1001 | pattern
1002 | (
1003 | Exp.sequence
1004 | (
1005 | tag
1006 | |> format namespace `WithNotLoggedPayload
1007 | |> log Debug cp
1008 | )
1009 | branch
1010 | )
1011 | | {pc_lhs = pattern; pc_rhs = branch} -> Exp.case pattern branch
1012 | )
1013 | )
1014 |
1015 | | ({pexp_loc}, _) -> Location.raise_errorf ~loc: pexp_loc "Expected pattern matching"
1016 |
1017 | let impl =
1018 | (
1019 | object (_self)
1020 | inherit Ast_traverse.map_with_expansion_context_and_errors as super
1021 |
1022 | method! expression ctx expr =
1023 | let expr, errors = super#expression ctx expr in
1024 | match expr |> Attribute.get attr with
1025 | | None -> (expr, errors)
1026 | | Some namespace ->
1027 | let expr = expr |> transform ~env_level:level ~namespace ~context:ctx in
1028 | (expr, errors)
1029 |
1030 | method! structure ctx str =
1031 | let str, errors = super#structure ctx str in
1032 | Attribute.check_all_seen ();
1033 | (str, errors)
1034 | end
1035 | )#structure
1036 | end
1037 |
1038 | module File_path = struct
1039 | let chop_prefix ~prefix x =
1040 | let prefix_len = String.length prefix in
1041 | let x_len = String.length x in
1042 | if x_len >= prefix_len && String.sub x 0 prefix_len = prefix then
1043 | Some (String.sub x prefix_len (x_len - prefix_len))
1044 | else
1045 | None
1046 |
1047 | let get_default_path (loc : Location.t) =
1048 | let fname = loc.loc_start.pos_fname in
1049 | match chop_prefix ~prefix:"./" fname with
1050 | | Some fname -> fname
1051 | | None -> fname
1052 |
1053 | let get_default_path_str : structure -> string = function
1054 | | [] -> ""
1055 | | { pstr_loc = loc; _ } :: _ -> get_default_path loc
1056 |
1057 | let get_default_path_sig : signature -> string = function
1058 | | [] -> ""
1059 | | { psig_loc = loc; _ } :: _ -> get_default_path loc
1060 | end
1061 |
1062 | let _ =
1063 | "rescript-logger-ppx"
1064 | |>
1065 | Driver.register_transformation
1066 | ~rules: (let open LogExt in [trace; debug; info; warn; error])
1067 | ~impl: (
1068 | fun str ->
1069 | let path = str |> File_path.get_default_path_str in
1070 | let ctx =
1071 | Expansion_context.Base.top_level
1072 | ~tool_name: (Ocaml_common.Ast_mapper.tool_name ())
1073 | ~file_path: path
1074 | ~input_name: (
1075 | (* I'm not sure if it's what meant by `input_name` *)
1076 | match path |> Filename.basename |> Filename.chop_extension with
1077 | | x -> x
1078 | | exception _ -> ""
1079 | )
1080 | in
1081 | let str, _ = str |> LogAttr.impl ctx in
1082 | str
1083 | )
1084 |
1085 | let _ = Driver.add_arg LibArg.key LibArg.spec ~doc:LibArg.doc
1086 |
--------------------------------------------------------------------------------
/ppx/lib/dune:
--------------------------------------------------------------------------------
1 | (library
2 | (name lib)
3 | (public_name rescript-logger-ppx.lib)
4 | (kind ppx_rewriter)
5 | (libraries ppxlib)
6 | (flags (:standard -w -30-9))
7 | (preprocess (pps ppxlib.metaquot)))
8 |
--------------------------------------------------------------------------------
/rescript-logger-ppx.opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | name: "rescript-logger-ppx"
3 | version: "4.0.0"
4 | synopsis: "Logging implementation for ReScript"
5 | description: """
6 | Logging implementation for ReScript
7 | """
8 | maintainer: "Alex Fedoseev "
9 | authors: "Alex Fedoseev "
10 | license: "MIT"
11 | homepage: "https://github.com/shakacode/rescript-logger.git"
12 | bug-reports: "https://github.com/shakacode/rescript-logger/issues"
13 | dev-repo: "git+https://github.com/shakacode/rescript-logger.git"
14 | depends: [
15 | "ocaml" { = "4.14.1" }
16 | "dune" { = "3.11.1" }
17 | "ppxlib" { = "0.30.0" }
18 | ]
19 | build: [
20 | ["dune" "build" "-p" name "-j" jobs]
21 | ]
22 |
--------------------------------------------------------------------------------
/windows.patch:
--------------------------------------------------------------------------------
1 | diff --git a/rescript-logger-ppx.opam b/rescript-logger-ppx.opam
2 | index f270f4d..1cd834e 100644
3 | --- a/rescript-logger-ppx.opam
4 | +++ b/rescript-logger-ppx.opam
5 | @@ -13,8 +13,8 @@ bug-reports: "https://github.com/shakacode/rescript-logger/issues"
6 | dev-repo: "git+https://github.com/shakacode/rescript-logger.git"
7 | depends: [
8 | "ocaml" { = "4.14.1" }
9 | - "dune" { = "3.11.1" }
10 | - "ppxlib" { = "0.30.0" }
11 | + "dune" { = "3.5.0" }
12 | + "ppxlib" { = "0.28.0" }
13 | ]
14 | build: [
15 | ["dune" "build" "-p" name "-j" jobs]
16 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | rescript@11.0.1:
6 | version "11.0.1"
7 | resolved "https://registry.yarnpkg.com/rescript/-/rescript-11.0.1.tgz#c74af134dc8a16d152169b2456d0720324835f54"
8 | integrity sha512-7T4PRp/d0+CBNnY6PYKffFqo9tGZlvnZpboF/n+8SKS+JZ6VvXJO7W538VPZXf3EYx1COGAWWvkF9e/HgSAqHg==
9 |
--------------------------------------------------------------------------------