Skip to content

Commit

Permalink
Release 1.6.1
Browse files Browse the repository at this point in the history
- add methods info-on, error-on or so to check will a log will be written
- separate sprintf-slyte and contatenation-slyte logs into separate methods
  • Loading branch information
atroxaper committed Apr 29, 2019
2 parents 4388cbf + fa932e3 commit 856f091
Show file tree
Hide file tree
Showing 11 changed files with 430 additions and 139 deletions.
4 changes: 4 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Version history:

1.6.1 2019-04-29 'conditional log calls'
- add methods info-on, error-on or so to check will a log will be written
- separate sprintf-slyte and contatenation-slyte logs into separate methods

1.5.2 2019-04-25 'fix broken compatibility'
- LogP6::Writer::Journald module is broken by previous release. Fix it.

Expand Down
94 changes: 49 additions & 45 deletions META6.json
Original file line number Diff line number Diff line change
@@ -1,47 +1,51 @@
{
"auth": "github:atroxaper",
"depends": [
"UUID",
"JSON::Fast"
],
"description": "Full customisable logging library inspired by idea of separate logging and its configuration.",
"resources": [],
"version": "1.5.2",
"tags": [
"LOG",
"LOGGING",
"LOGGER"
],
"license": "Artistic-2.0",
"source-url": "git://github.com/atroxaper/p6-LogP6.git",
"provides": {
"LogP6::Wrapper::SyncAbstract": "lib/LogP6/Wrapper/SyncAbstract.pm6",
"LogP6::LoggerPure": "lib/LogP6/LoggerPure.pm6",
"LogP6::WriterConf::Std": "lib/LogP6/WriterConf/Std.pm6",
"LogP6::Logger": "lib/LogP6/Logger.pm6",
"LogP6::Wrapper": "lib/LogP6/Wrapper.pm6",
"LogP6::Writer::Std": "lib/LogP6/Writer/Std.pm6",
"LogP6::Filter::Std": "lib/LogP6/Filter/Std.pm6",
"LogP6": "lib/LogP6.pm6",
"LogP6::Context": "lib/LogP6/Context.pm6",
"LogP6::FilterConf": "lib/LogP6/FilterConf.pm6",
"LogP6::LogGetter": "lib/LogP6/LogGetter.pm6",
"LogP6::WriterConf::Pattern": "lib/LogP6/WriterConf/Pattern.pm6",
"LogP6::Filter": "lib/LogP6/Filter.pm6",
"LogP6::Level": "lib/LogP6/Level.pm6",
"LogP6::Wrapper::SyncTime": "lib/LogP6/Wrapper/SyncTime.pm6",
"LogP6::Cliche": "lib/LogP6/Cliche.pm6",
"LogP6::FilterConf::Std": "lib/LogP6/FilterConf/Std.pm6",
"LogP6::Writer": "lib/LogP6/Writer.pm6",
"LogP6::ThreadLocal": "lib/LogP6/ThreadLocal.pm6",
"LogP6::WriterConf": "lib/LogP6/WriterConf.pm6",
"LogP6::ConfigFile": "lib/LogP6/ConfigFile.pm6",
"LogP6::Wrapper::Transparent": "lib/LogP6/Wrapper/Transparent.pm6",
"LogP6::Exceptions": "lib/LogP6/Exceptions.pm6",
"LogP6::Wrapper::SyncEach": "lib/LogP6/Wrapper/SyncEach.pm6"
},
"name": "LogP6",
"perl": "6.d",
"test-depends": ["Test"],
"authors": ["Mikhail Khorkov"]
"name": "LogP6",
"description": "Full customisable logging library inspired by idea of separate logging and its configuration.",
"version": "1.6.1",
"perl": "6.d",
"authors": [
"Mikhail Khorkov"
],
"auth": "github:atroxaper",
"depends": [
"UUID",
"JSON::Fast"
],
"test-depends": [
"Test"
],
"provides": {
"LogP6": "lib/LogP6.pm6",
"LogP6::Cliche": "lib/LogP6/Cliche.pm6",
"LogP6::ConfigFile": "lib/LogP6/ConfigFile.pm6",
"LogP6::Context": "lib/LogP6/Context.pm6",
"LogP6::Exceptions": "lib/LogP6/Exceptions.pm6",
"LogP6::Filter": "lib/LogP6/Filter.pm6",
"LogP6::Filter::Std": "lib/LogP6/Filter/Std.pm6",
"LogP6::FilterConf": "lib/LogP6/FilterConf.pm6",
"LogP6::FilterConf::Std": "lib/LogP6/FilterConf/Std.pm6",
"LogP6::Level": "lib/LogP6/Level.pm6",
"LogP6::LogGetter": "lib/LogP6/LogGetter.pm6",
"LogP6::Logger": "lib/LogP6/Logger.pm6",
"LogP6::LoggerPure": "lib/LogP6/LoggerPure.pm6",
"LogP6::ThreadLocal": "lib/LogP6/ThreadLocal.pm6",
"LogP6::Wrapper": "lib/LogP6/Wrapper.pm6",
"LogP6::Wrapper::SyncAbstract": "lib/LogP6/Wrapper/SyncAbstract.pm6",
"LogP6::Wrapper::SyncEach": "lib/LogP6/Wrapper/SyncEach.pm6",
"LogP6::Wrapper::SyncTime": "lib/LogP6/Wrapper/SyncTime.pm6",
"LogP6::Wrapper::Transparent": "lib/LogP6/Wrapper/Transparent.pm6",
"LogP6::Writer": "lib/LogP6/Writer.pm6",
"LogP6::Writer::Std": "lib/LogP6/Writer/Std.pm6",
"LogP6::WriterConf": "lib/LogP6/WriterConf.pm6",
"LogP6::WriterConf::Pattern": "lib/LogP6/WriterConf/Pattern.pm6",
"LogP6::WriterConf::Std": "lib/LogP6/WriterConf/Std.pm6"
},
"resources": [],
"license": "Artistic-2.0",
"tags": [
"LOG",
"LOGGING",
"LOGGER"
],
"source-url": "git://github.com/atroxaper/p6-LogP6.git"
}
64 changes: 56 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ even in your own libraries.
- [EXAMPLES](#examples)
- [Use external library witch uses LogP6](#use-external-library-witch-uses-logp6)
- [Change console application verbosity level](#change-console-application-verbosity-level)
- [Conditional log calls](#conditional-log-calls)
- [Associate logs with concrete user](#associate-logs-with-concrete-user)
- [Filter log by its content](#filter-log-by-its-content)
- [Write one log in several outputs](#write-one-log-in-several-outputs)
Expand Down Expand Up @@ -113,8 +114,8 @@ Using logger:
use LogP6; # use library in general mode

my \log = get-logger('audit'); # create or get logger with 'audit' trait
log.info('property ' ~ 'foo' ~ ' setted as ' ~ 5); # log string with concatenation
log.info('property %s setted as %d', 'foo', 5); # log sprintf like style
log.info('property ', 'foo', ' setted as ', 5); # log string with concatenation
log.infof('property %s setted as %d', 'foo', 5); # log sprintf like style
```

Configure the logger in code:
Expand Down Expand Up @@ -217,10 +218,20 @@ Logger has the following methods:
them from copy. The methods are useful when you want to share NDC and MDC values
across multiple threads.
- `trace(*@args, :$x)`, `debug(*@args, :$x)`, `info(*@args, :$x)`,
`warn(*@args, :$x)`, `error(*@args, :$x)` - logging the arguments with specified
importance log level. `:$x` is an optional exception argument. `@args` - data
for logging. If the array has more then one element then the first element is
used as format for `sprintf` sub and the rest elements as `sprintf` args;
`warn(*@args, :$x)`, `error(*@args, :$x)`, `level($level, *@args, :$x)` -
logging the arguments with specified importance log level. `:$x` is an optional
exception argument. `@args` - data for logging. Elements of the array will be
concatenated with empty string;
- `tracef(*@args, :$x)`, `debugf(*@args, :$x)`, `infof(*@args, :$x)`,
`warnf(*@args, :$x)`, `errorf(*@args, :$x)`, `levelf($level, *@args, :$x)` -
logging the arguments with specified importance log level. `:$x` is an optional
exception argument. `@args` - data for logging. The first element is used as
`sprintf` format and the rest element as `sprintf` args;
- `trace-on()`, `debug-on()`, `info-on()`, `warn-on()`, `error-on()`,
`level-on($level)` - help methods to use as condition. The method will return
`Any` in case the specified log level if forbidden now and will return special
object with `log(*@args, :$x)` and `logf(*@args, :$x)` methods which can be used
for log with asked log level (see [example](#conditional-log-calls)).

## Logger Wrapper

Expand Down Expand Up @@ -762,7 +773,7 @@ sub MAIN(Bool :$verbose) {
filter(:name<verbosity>, :level($debug), :update) if $verbose;
my $say = get-logger('say');
$say.info('Greetings');
$say.debug('You set verbose flag to %s value', $verbose);
$say.debugf('You set verbose flag to %s value', $verbose);
}
```

Expand All @@ -777,6 +788,43 @@ can remove line with `cliche` creation and add the following configuration file:
}
```

## Conditional log calls

Sometimes you may need to log an information required additional calculation.
In such cases it is useful to know will the log be written or not before
the calculation. Logger `-on` methods created specially for that. It will return
special object (or Any) with `log` and `logf` methods you can use to log with
corresponding log level. Please look at the example below:

```perl6
use LogP6 :configure;

# set logger allowed level as INFO
filter(:name(''), :level($info), :update);
my $log = get-logger('condition');
my %map;
my $str;
# ...

# to-json will not be called here, because .debug-on returned Any for now
.log(to-json(%map, :pretty, :sorted-keys)) with $log.debug-on;

# from-json will be called here, because .warn-on returned a 'little logger'
# log will be with WARN level
.log(from-json($str)<key>) with $log.warn-on;

with $log.trace-on {
# this block will bot be executed for now
my $user-id = retrive-the-first-user-id-from-db();
# use logf method to use sprintf-style logs
.logf('the first user id in the database is %d', $user-id);
}

# Be careful with '.?' operator. Sins it is not an operator but syntax-sugar
# to-json will be called in any case, but log will not be written for now.
$log.debug-on.?log(to-json(%map, :pretty, :sorted-keys));
```

## Associate logs with concrete user

Lets imagine we write a server application. Many users at the same time can
Expand Down Expand Up @@ -860,7 +908,7 @@ sub drop-passwords($context) {
}

sub connect(User $user) {
get-logger('log').info('user with name %s and password %s connected', $user.id, $user.passwd);
get-logger('log').infof('user with name %s and password %s connected', $user.id, $user.passwd);
}
```

Expand Down
22 changes: 15 additions & 7 deletions lib/LogP6/Context.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,22 @@ method sync-put($trait, $obj) {
#| Gets callframe of log caller level.
method callframe() {
return $_ with $!callframe;
# start with 3. it is much save and optimal
for 3..* -> $level {

my $first-non-logp6;
my $in-logp6 = True;
my $inverts = 0;

for 0..* -> $level {
with callframe($level) -> $frame {
next unless $frame.code.name
~~ any('trace', 'debug', 'info', 'warn', 'error');
# +1 to caller code and +1 to go from `with` block
$!callframe = callframe($level + 2);
last;
if $in-logp6 ne (so $frame.file ~~ / '(LogP6' /) {
$in-logp6 = !$in-logp6;
given ++$inverts {
when 1 { $first-non-logp6 = $frame }
when 3 { $!callframe = $frame; last }
}
}
} else {
$!callframe = $first-non-logp6; last
}
}
return $!callframe;
Expand Down
94 changes: 79 additions & 15 deletions lib/LogP6/Logger.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,100 @@ role LogP6::Logger {
method dc-copy() { ... }
#| Restore values of NDC and MDC from its copy
method dc-restore($dc) { ... }
#|[Writes log with specified importance level.
#| $level - importance level of log
#| @args - data for logging. Elements of the array will be concatenated with
#| empty string;
#| :$x - optional exception argument.]
method level($level, *@args, :$x) { ... }
#|[Writes log with specified importance level.
#| $level - importance level of log
#| @args - data for logging. The first element is used as sprintf format
#| and the rest element as sprintf args;
#| :$x - optional exception argument.]
method levelf($level, *@args, :$x) { ... }
#|[Writes log with trace importance level.
#| @args - data for logging. If the array has more then one element then the
#| first element is used as format for sprintf sub and the rest element as
#| sprintf args;
#| @args - data for logging. Elements of the array will be concatenated with
#| empty string;
#| :$x - optional exception argument.]
method trace(*@args, :$x) { ... }
#|[Writes log with trace importance level.
#| @args - data for logging. The first element is used as sprintf format
#| and the rest element as sprintf args;
#| :$x - optional exception argument.]
method tracef(*@args, :$x) { ... }
#|[Writes log with debug importance level.
#| @args - data for logging. If the array has more then one element then the
#| first element is used as format for sprintf sub and the rest element as
#| sprintf args;
#| @args - data for logging. Elements of the array will be concatenated with
#| empty string;
#| :$x - optional exception argument.]
method debug(*@args, :$x) { ... }
#|[Writes log with debug importance level.
#| @args - data for logging. The first element is used as sprintf format
#| and the rest element as sprintf args;
#| :$x - optional exception argument.]
method debugf(*@args, :$x) { ... }
#|[Writes log with info importance level.
#| @args - data for logging. If the array has more then one element then the
#| first element is used as format for sprintf sub and the rest element as
#| sprintf args;
#| @args - data for logging. Elements of the array will be concatenated with
#| empty string;
#| :$x - optional exception argument.]
method info(*@args, :$x) { ... }
#|[Writes log with info importance level.
#| @args - data for logging. The first element is used as sprintf format
#| and the rest element as sprintf args;
#| :$x - optional exception argument.]
method infof(*@args, :$x) { ... }
#|[Writes log with warn importance level.
#| @args - data for logging. If the array has more then one element then the
#| first element is used as format for sprintf sub and the rest element as
#| sprintf args;
#| @args - data for logging. Elements of the array will be concatenated with
#| empty string;
#| :$x - optional exception argument.]
method warn(*@args, :$x) { ... }
#|[Writes log with warn importance level.
#| @args - data for logging. The first element is used as sprintf format
#| and the rest element as sprintf args;
#| :$x - optional exception argument.]
method warnf(*@args, :$x) { ... }
#|[Writes log with error importance level.
#| @args - data for logging. If the array has more then one element then the
#| first element is used as format for sprintf sub and the rest element as
#| sprintf args;
#| @args - data for logging. Elements of the array will be concatenated with
#| empty string;
#| :$x - optional exception argument.]
method error(*@args, :$x) { ... }
#|[Writes log with error importance level.
#| @args - data for logging. The first element is used as sprintf format
#| and the rest element as sprintf args;
#| :$x - optional exception argument.]
method errorf(*@args, :$x) { ... }
#|[Check if a log will be written with trace importance level.
#| Returns Any if not, or `little logger` with `log` and `logf` methods
#| to write a log message with trace level.]
method trace-on() { ... }
#|[Check if a log will be written with debug importance level.
#| Returns Any if not, or `little logger` with `log` and `logf` methods
#| to write a log message with debug level.]
method debug-on() { ... }
#|[Check if a log will be written with info importance level.
#| Returns Any if not, or `little logger` with `log` and `logf` methods
#| to write a log message with info level.]
method info-on() { ... }
#|[Check if a log will be written with warn importance level.
#| Returns Any if not, or `little logger` with `log` and `logf` methods
#| to write a log message with warn level.]
method warn-on() { ... }
#|[Check if a log will be written with error importance level.
#| Returns Any if not, or `little logger` with `log` and `logf` methods
#| to write a log message with error level.]
method error-on() { ... }
#|[Check if a log will be written with specified importance level.
#| Returns Any if not, or `little logger` with `log` and `logf` methods
#| to write a log message with specified level.]
method level-on($level) { ... }
}

class LogP6::IfLogger {
has $.log;
has $.level;

method log(*@args, :$x) { $!log.level($!level, |@args, :$x) }
method logf(*@args, :$x) { $!log.levelf($!level, |@args, :$x) }
}

sub get-context() is export {
Expand Down
Loading

0 comments on commit 856f091

Please sign in to comment.