Skip to content

Commit

Permalink
Development Tools WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyGauge committed May 2, 2018
1 parent 203b063 commit f45cac2
Show file tree
Hide file tree
Showing 19 changed files with 532 additions and 454 deletions.
7 changes: 6 additions & 1 deletion src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@
- [Data Structures](data_structures.md)
- [Constants](data_structures/constant.md)
- [Custom](data_structures/custom.md)
- [Development Tools](development_tools.md)
- [Debugging](development_tools/debugging.md)
- [Log Messages](development_tools/debugging/log.md)
- [Configure Logging](development_tools/debugging/config_log.md)
- [Versioning](development_tools/versioning.md)
- [Build Time Tooling](development_tools/build_tools.md)
- [Basics](basics.md)
- [Encoding](encoding.md)
- [Networking](net.md)
- [Application development](app.md)
- [Logging](logging.md)
- [Build Time Tooling](build_tools.md)
2 changes: 0 additions & 2 deletions src/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -689,8 +689,6 @@ fn run() -> Result<()> {

{{#include cryptography/encryption/pbkdf2.md}}


[ex-bitflags]: #ex-bitflags
{{#include data_structures/custom/bitfield.md}}

[ex-random-file-access]: #ex-random-file-access
Expand Down
15 changes: 15 additions & 0 deletions src/development_tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Development Tools

| Recipe | Crates | Categories |
|--------|--------|------------|
| [Log a debug message to the console][ex-log-debug] | [![log-badge]][log] [![env_logger-badge]][env_logger] | [![cat-debugging-badge]][cat-debugging] |
| [Log an error message to the console][ex-log-error] | [![log-badge]][log] [![env_logger-badge]][env_logger] | [![cat-debugging-badge]][cat-debugging] |
| [Enable log levels per module][ex-log-mod] | [![log-badge]][log] [![env_logger-badge]][env_logger] | [![cat-debugging-badge]][cat-debugging] |
| [Log to stdout instead of stderr][ex-log-stdout] | [![log-badge]][log] [![env_logger-badge]][env_logger] | [![cat-debugging-badge]][cat-debugging] |
| [Log messages with a custom logger][ex-log-custom-logger] | [![log-badge]][log] | [![cat-debugging-badge]][cat-debugging] |
| [Use a custom environment variable to set up logging][ex-log-env-variable] | [![log-badge]][log] [![env_logger-badge]][env_logger] | [![cat-debugging-badge]][cat-debugging] |
| [Include timestamp in log messages][ex-log-timestamp] | [![log-badge]][log] [![env_logger-badge]][env_logger] [![chrono-badge]][chrono] | [![cat-debugging-badge]][cat-debugging] |
| [Log to the Unix syslog][ex-log-syslog] | [![log-badge]][log] [![syslog-badge]][syslog] | [![cat-debugging-badge]][cat-debugging] |
| [Log messages to a custom location][ex-log-custom] | [![log-badge]][log] [![log4rs-badge]][log4rs] | [![cat-debugging-badge]][cat-debugging] |

[ex-log-debug]: development_tools/debugging/log.html#log-a-debug-message-to-the-console
4 changes: 2 additions & 2 deletions src/build_tools.md → src/development_tools/build_tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ fn main(){

[![cc-badge]][cc] [![cat-development-tools-badge]][cat-development-tools]

It is simple to build bundled C code with custom defines using [`cc::Build::define`].
It is simple to build bundled C code with custom defines using [`cc::Build::define`].
It takes an [`Option`] value, so it is possible to create defines such as `#define APP_NAME "foo"`
as well as `#define WELCOME` (pass `None` as the value for a value-less defne). This example builds
a bundled C file with dynamic defines set in `build.rs` and prints "**Welcome to foo - version 1.0.2**"
Expand Down Expand Up @@ -238,7 +238,7 @@ fn main(){
}
```

{{#include links.md}}
{{#include ../links.md}}

<!-- Other Reference -->

Expand Down
1 change: 1 addition & 0 deletions src/development_tools/debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Debugging
11 changes: 11 additions & 0 deletions src/development_tools/debugging/config_log.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Configure Logging

{{#include config_log/log-mod.md}}

{{#include config_log/log-env-variable.md}}

{{#include config_log/log-timestamp.md}}

{{#include config_log/log-custom.md}}

{{#include ../../links.md}}
57 changes: 57 additions & 0 deletions src/development_tools/debugging/config_log/log-custom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<a name="ex-log-custom"></a>
## Log messages to a custom location

[![log-badge]][log] [![log4rs-badge]][log4rs] [![cat-debugging-badge]][cat-debugging]

Configures log to be output into custom location with [log4rs]. [log4rs] can use either an external YAML file or a programmatically constructed configuration.

Firstly creates the log configuration with [`log4rs::append::file::FileAppender`]
using a custom pattern from [`log4rs::encode::pattern`].

Secondly assigns it to the [`log4rs::config::Config`] which has a root appender that uses the previously created `logfile` appender. Subsequently sets the default [`log::LogLevelFilter`] so that any logs with `Info` level or higher will be sent to the logger.

```rust,no_run
# #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate log;
extern crate log4rs;
use log::LogLevelFilter;
use log4rs::append::file::FileAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{Appender, Config, Root};
#
# error_chain! {
# foreign_links {
# Io(std::io::Error);
# LogConfig(log4rs::config::Errors);
# SetLogger(log::SetLoggerError);
# }
# }
fn run() -> Result<()> {
let logfile = FileAppender::builder()
.encoder(Box::new(PatternEncoder::new("{l} - {m}\n")))
.build("log/output.log")?;
let config = Config::builder()
.appender(Appender::builder().build("logfile", Box::new(logfile)))
.build(Root::builder()
.appender("logfile")
.build(LogLevelFilter::Info))?;
log4rs::init_config(config)?;
info!("Hello, world!");
Ok(())
}
#
# quick_main!(run);
```

[`log4rs::append::file::FileAppender`]: https://docs.rs/log4rs/*/log4rs/append/file/struct.FileAppender.html
[`log4rs::config::Config`]: https://docs.rs/log4rs/*/log4rs/config/struct.Config.html
[`log4rs::encode::pattern`]: https://docs.rs/log4rs/*/log4rs/encode/pattern/index.html
[`log::LogLevelFilter`]: https://doc.rust-lang.org/log/log/enum.LogLevelFilter.html
48 changes: 48 additions & 0 deletions src/development_tools/debugging/config_log/log-env-variable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<a name="ex-log-env-variable"></a>
## Use a custom environment variable to set up logging

[![log-badge]][log] [![env_logger-badge]][env_logger] [![cat-debugging-badge]][cat-debugging]

Logging is configured with [`LogBuilder`].

[`LogBuilder::parse`] parses `MY_APP_LOG`
environmental variable contents in the form of [`RUST_LOG`] syntax.
Then [`LogBuilder::init`] initializes the logger.
All these steps are normally done internally by [`env_logger::init`].

```rust
# #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;
use env_logger::LogBuilder;

# error_chain! {
# foreign_links {
# EnvLogger(log::SetLoggerError);
# }
# }
#
fn run() -> Result<()> {
LogBuilder::new()
.parse(&env::var("MY_APP_LOG").unwrap_or_default())
.init()?;

info!("informational message");
warn!("warning message");
error!("this is an error {}", "message");

Ok(())
}
#
# quick_main!(run);
```

[`env_logger::init`]: https://doc.rust-lang.org/log/env_logger/fn.init.html
[`LogBuilder`]: https://doc.rust-lang.org/log/env_logger/struct.Builder.html
[`LogBuilder::init`]: https://doc.rust-lang.org/log/env_logger/struct.LogBuilder.html#method.init
[`LogBuilder::parse`]: https://doc.rust-lang.org/log/env_logger/struct.LogBuilder.html#method.parse
[`RUST_LOG`]: https://doc.rust-lang.org/log/env_logger/#enabling-logging
73 changes: 73 additions & 0 deletions src/development_tools/debugging/config_log/log-mod.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<a name="ex-log-mod"></a>
## Enable log levels per module

[![log-badge]][log] [![env_logger-badge]][env_logger] [![cat-debugging-badge]][cat-debugging]

Creates two modules `foo` and nested `foo::bar` with logging directives
controlled separately with [`RUST_LOG`] environmental variable.

```rust
# #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate log;
extern crate env_logger;

mod foo {
mod bar {
pub fn run() {
warn!("[bar] warn");
info!("[bar] info");
debug!("[bar] debug");
}
}

pub fn run() {
warn!("[foo] warn");
info!("[foo] info");
debug!("[foo] debug");
bar::run();
}
}
#
# error_chain! {
# foreign_links {
# SetLogger(log::SetLoggerError);
# }
# }

fn run() -> Result<()> {
env_logger::init()?;
warn!("[root] warn");
info!("[root] info");
debug!("[root] debug");
foo::run();

Ok(())
}
#
# quick_main!(run);
```

[`env_logger`][env_logger] output is controlled by [`RUST_LOG`] environmental
variable on per module basis with comma separated entries in format `path::to::module=log_level`.
Running the `test` application as follows:

```bash
RUST_LOG="warn,test::foo=info,test::foo::bar=debug" ./test
```

Sets the default [`log::LogLevel`] to `warn`, module's `foo` and module's `foo::bar`
respectively to `info` and `debug`. The output is:

```bash
WARN:test: [root] warn
WARN:test::foo: [foo] warn
INFO:test::foo: [foo] info
WARN:test::foo::bar: [bar] warn
INFO:test::foo::bar: [bar] info
DEBUG:test::foo::bar: [bar] debug
```

[`log::LogLevel`]: https://doc.rust-lang.org/log/log/enum.LogLevel.html
[`RUST_LOG`]: https://doc.rust-lang.org/log/env_logger/#enabling-logging
63 changes: 63 additions & 0 deletions src/development_tools/debugging/config_log/log-timestamp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<a name="ex-log-timestamp"></a>
## Include timestamp in log messages

[![log-badge]][log] [![env_logger-badge]][env_logger] [![chrono-badge]][chrono] [![cat-debugging-badge]][cat-debugging]

Creates a custom logger configuration with [`LogBuilder`].
Each log entry calls [`Local::now`] to get the current [`DateTime`] in local timezone and uses [`DateTime::format`] with [`strftime::specifiers`] to format a timestamp used in the final log.

The example calls [`LogBuilder::format`] to set a closure which formats each
message text with timestamp, [`LogRecord::level`] and body ([`LogRecord::args`]).

```rust
# #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate chrono;

use std::env;
use env_logger::LogBuilder;
use chrono::Local;

#
# error_chain! {
# foreign_links {
# SetLogger(log::SetLoggerError);
# }
# }

fn run() -> Result<()> {
LogBuilder::new()
.format(|record| {
format!("{} [{}] - {}",
Local::now().format("%Y-%m-%dT%H:%M:%S"),
record.level(),
record.args())
})
.parse(&env::var("MY_APP_LOG").unwrap_or_default())
.init()?;

warn!("warn");
info!("info");
debug!("debug");
Ok(())
}
#
# quick_main!(run);
```
Calling `MY_APP_LOG="info" cargo run` will result in similar output:
```
2017-05-22T21:57:06 [WARN] - warn
2017-05-22T21:57:06 [INFO] - info
```

[`DateTime::format`]: https://docs.rs/chrono/*/chrono/datetime/struct.DateTime.html#method.format
[`DateTime`]: https://docs.rs/chrono/*/chrono/datetime/struct.DateTime.html
[`Local::now`]: https://docs.rs/chrono/*/chrono/offset/local/struct.Local.html#method.now
[`LogBuilder`]: https://doc.rust-lang.org/log/env_logger/struct.Builder.html
[`LogBuilder::format`]: https://doc.rust-lang.org/log/env_logger/struct.LogBuilder.html#method.format
[`LogRecord::args`]: https://doc.rust-lang.org/log/log/struct.LogRecord.html#method.args
[`LogRecord::level`]: https://doc.rust-lang.org/log/log/struct.LogRecord.html#method.level
[`strftime::specifiers`]: https://docs.rs/chrono/*/chrono/format/strftime/index.html#specifiers
13 changes: 13 additions & 0 deletions src/development_tools/debugging/log.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Log Messages

{{#include log/log-debug.md}}

{{#include log/log-error.md}}

{{#include log/log-stdout.md}}

{{#include log/log-custom-logger.md}}

{{#include log/log-syslog.md}}

{{#include ../../links.md}}
51 changes: 51 additions & 0 deletions src/development_tools/debugging/log/log-custom-logger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<a name="ex-log-custom-logger"></a>
## Log messages with a custom logger

[![log-badge]][log] [![cat-debugging-badge]][cat-debugging]

Implements a custom logger `ConsoleLogger` which prints to stdout.
In order to use the logging macros, `ConsoleLogger` implements
the [`log::Log`] trait and has to be installed via [`log::set_logger`].

```rust
# #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate log;

use log::{LogRecord, LogLevel, LogMetadata, LogLevelFilter};

struct ConsoleLogger;

impl log::Log for ConsoleLogger {
fn enabled(&self, metadata: &LogMetadata) -> bool {
metadata.level() <= LogLevel::Info
}

fn log(&self, record: &LogRecord) {
if self.enabled(record.metadata()) {
println!("Rust says: {} - {}", record.level(), record.args());
}
}
}
#
# error_chain! {
# foreign_links {
# SetLogger(log::SetLoggerError);
# }
# }

fn run() -> Result<()> {
log::set_logger(|max_log_level| {
max_log_level.set(LogLevelFilter::Info);
Box::new(ConsoleLogger)
})?;

info!("hello log");
warn!("warning");
error!("oops");
Ok(())
}
#
# quick_main!(run);
```
Loading

0 comments on commit f45cac2

Please sign in to comment.