-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
06c505d
commit 9a7ef6f
Showing
11 changed files
with
458 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
[package] | ||
name = "logging" | ||
version = "0.1.0" | ||
description = "Neon Logging Example" | ||
license = "MIT" | ||
edition = "2018" | ||
exclude = ["index.node"] | ||
|
||
[lib] | ||
crate-type = ["cdylib"] | ||
|
||
[dependencies] | ||
log = "0.4" | ||
|
||
[dependencies.neon] | ||
version = "0.10.0-alpha.3" | ||
default-features = false | ||
features = ["napi-6", "channel-api"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Logging | ||
|
||
The logging example connects the Rust [`log`][log] crate to the Node [`debug`][debug] module. Neon modules can write logs directly to `stdout` with typical crates like [`env_logger`][env-logger], but connecting logging to [`debug`][debug] more seamlessly integrates with the Node ecosystem. | ||
|
||
## Usage | ||
|
||
```sh | ||
# Only `INFO` logs on the top level crate | ||
DEBUG="INFO:logging" npm start | ||
|
||
# All logs on the top level crate | ||
DEBUG="*:logging" npm start | ||
|
||
# All `INFO` logs on any Rust crate | ||
DEBUG="INFO:*" npm start | ||
|
||
# All `WARN` and higher logs in our crate | ||
DEBUG="WARN:logging,ERROR:logging" | ||
``` | ||
|
||
## Libraries | ||
|
||
### [`log`][log] crate | ||
|
||
The [`log`][log] crate provides a logging facade used throughout the Rust ecosystem. It provides convenient macros for logging, but does not provide any facility to write or display logs. | ||
|
||
### [`debug`][debug] module | ||
|
||
the [`debug`][debug] node module provides a decorated version of `console.error` and is used throughout the Node library ecosystem, including in the [`express`][express] HTTP framework. It allows configurable log filtering with the `DEBUG` environment variable. | ||
|
||
## Design | ||
|
||
Rust code uses the typical logging facilities, but in order for it to be used, the [`Log`][log-trait] must be implemented. This example provides a simple [`Log`][log-trait] implementation that delegates to the [`debug`][debug] node module. | ||
|
||
### Initialization | ||
|
||
At initialization, the module calls `global.require("debug")` to get a copy of the function used to create logger instances. This function, as well as `enabled` and a [`Channel`][channel] are used to create a `Logger` instance and initialize the `log` crate. | ||
|
||
### Loggers | ||
|
||
The `Logger` struct maintains a map of logger names to logger instances that are lazily created as needed. Each logger is in an `Option` with `None` representing the disabled state. If an entry is missing, it is assumed to be in the `enabled` state until it can be further evaluated. | ||
|
||
## Limitations | ||
|
||
### Levels | ||
|
||
The provided implementation does not understand logger levels. Each level needs to be enabled individually. As an improvement, the logger level could be determined by checking `debug.enabled(...)` for each level from lowest to highest. | ||
|
||
### Multiple Contexts | ||
|
||
The `log` crate only supports a single global logger instance in a process. If the module is initialized multiple times with Web Workers, all logs will be sent to the instance that initialized. | ||
|
||
### Runtime level changes | ||
|
||
The `debug` module supports enabling and disabling logging at runtime, but for efficiency, our `Logging` implementation assumes that the result of `debug.enabled(..)` never changes. | ||
|
||
[log]: https://crates.io/crates/log | ||
[log-trait]: https://docs.rs/log/latest/log/trait.Log.html | ||
[debug]: https://www.npmjs.com/package/debug | ||
[env-logger]: https://crates.io/crates/env-logger | ||
[express]: https://www.npmjs.com/package/express | ||
[channel]: https://docs.rs/neon/latest/neon/event/struct.Channel.html |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"name": "logging", | ||
"version": "0.1.0", | ||
"description": "Neon Logging Example", | ||
"main": "index.node", | ||
"scripts": { | ||
"build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics", | ||
"install": "npm run build", | ||
"start": "node run", | ||
"test": "cargo test" | ||
}, | ||
"license": "MIT", | ||
"devDependencies": { | ||
"cargo-cp-artifact": "^0.1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/neon-bindings/examples.git" | ||
}, | ||
"keywords": [ | ||
"Neon", | ||
"Examples" | ||
], | ||
"bugs": { | ||
"url": "https://github.com/neon-bindings/examples/issues" | ||
}, | ||
"homepage": "https://github.com/neon-bindings/examples#readme", | ||
"dependencies": { | ||
"debug": "^4.3.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
"use strict"; | ||
|
||
const debug = require("debug"); | ||
const { hello, init } = require("."); | ||
|
||
// Must be called to initialized logging | ||
init(debug); | ||
|
||
// Call an example function | ||
hello(); | ||
|
||
// Give logs a chance to flush | ||
setTimeout(() => {}, 500); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use neon::prelude::*; | ||
|
||
use crate::logger::Logger; | ||
|
||
mod logger; | ||
|
||
// `init(debug)` must be called before using any other functionality. | ||
// | ||
// An exported initialization function is a common pattern in Neon. Since | ||
// Node-API does not expose `require`, a JavaScript wrapper requires the | ||
// `debug` module and passes it to `init` where logging is initialized. | ||
fn init(mut cx: FunctionContext) -> JsResult<JsUndefined> { | ||
let debug = cx.argument::<JsFunction>(0)?; | ||
|
||
Logger::init(&mut cx, debug)?; | ||
|
||
log::info!("Module initialized"); | ||
|
||
Ok(cx.undefined()) | ||
} | ||
|
||
// Example function with logging | ||
fn hello(mut cx: FunctionContext) -> JsResult<JsString> { | ||
log::trace!("Called `hello` function"); | ||
|
||
Ok(cx.string("hello node")) | ||
} | ||
|
||
#[neon::main] | ||
fn main(mut cx: ModuleContext) -> NeonResult<()> { | ||
cx.export_function("init", init)?; | ||
cx.export_function("hello", hello)?; | ||
|
||
Ok(()) | ||
} |
Oops, something went wrong.