October 15, 2013
On Tuesday, 15 October 2013 at 07:52:28 UTC, Robert Schadek wrote:
> On 10/15/2013 04:06 AM, Eric Anderton wrote:
>> On Monday, 14 October 2013 at 11:39:52 UTC, Dicebot wrote:
>> Here's what I think is missing:
>> - System log support (as others have mentioned).  This would be syslog
>> or WEL, depending on environment.
> This is sort of the idea of the design, I can't anticipate your needs
> therefor I should not try. I should try to give you guidelines or a
> framework to work against.

Totally disagree. We need a powerful logger, not only file logger.
I can implement a file logger myself for a few hours, and it will cover 90% of my needs. For other 10% I would like to have a standart logger with advanced features like speed and reliability.

If you need help, please tell us. For example, jkm already implemented syslog for Vibe.d with support files (via file streams) and the network (via TCP or SSL streams):
https://github.com/rejectedsoftware/vibe.d/pull/294
It's under the MIT license, that similar to the Boost license.

Sönke Ludwig, can you allow to use syslog code for `std.logger` under the Boost license? Robert Schadek can use it as initial point.
October 15, 2013
On 10/15/2013 03:21 PM, Sönke Ludwig wrote:
> Am 15.10.2013 10:41, schrieb Robert Schadek:
>> On 10/15/2013 02:44 AM, Kapps wrote:
>>> The simple act of logging a message is very verbose right now:
>>> log(LogLevel.trace, "Creating new pool") is a lot of boiler plate. I'd
>>> prefer something like log.trace("Creating new pool") and log("Creating
>>> new pool") where the latter would use opCall to forward to the default
>>> log level. If it's intentional that you can assign the result of log,
>>> this also helps that because log = new StdIOLogger would be possible
>>> (log being a property that returns a Logger, and so a setter could be
>>> made), but log("Creating new pool") = new StdIOLogger() would not be.
>> The LogLevel is optional. And always writing log.trace might become more typing work and assigning a LogLevel and than calling log("..."). Both have pros and cons
>
> What happens when a called function alters the default log level?
The default log level is altered.
>
> ---
> void func1() {
>     log.logLevel = LogLevel.debug;
>     log("This is a debug message");
>     func2();
>     log("This is supposed to be a debug message");
> }
>
> void func2() {
>     log.logLevel = LogLevel.warning;
>     log("This is a warning");
> }
> ---
If you don't specify a logger nor a LogLevel the currently set default logger will log the message with its currently set LogLevel.
>
>
> I don't think it's a good idea to use such kind of global state, especially for a logging framework that is supposed to be shared between libraries, so that it is difficult to predict what a particular function does. With a logger that is shared between threads, things get worse of course.
I think this is good, as it gives you a way to quite libraries down. The idea behind the free standing "log" function is to provide an ultra easy way to log. It is not meant to be used for the 2<<31 line program. In that case you will properly have very specific needs on how to log. Hence implement the abstract Logger class to your needs.
>
> A related question: It seems like Logger.logLevel at the same time means the minimum log level that is output and the default log level, is that right?
Yes. The LogLevel of each logger is the LogLevel used if non is specified and only messages are logged by this logger if their LogLevel is greater equal to that Level. Additionally the LogLevel must be >= to the global LogLevel.

October 15, 2013
On Tuesday, 15 October 2013 at 13:31:40 UTC, ilya-stromberg wrote:
> ...

I think such stuff should go as an extra module in same package with various useful out-of-the box logger implementations at the very best. Probably even dub package built on top of std.logger;

Phobos has very specific general design I like a lot - self-contained modules/packages with zero external dependencies (please kill std.net.curl!), which do work by simply importing certain modules. No extra configuration, no creation of weird useless classes - just reasonable defaults that work as-is in most cases.

In that sense what is 100% needed is enhancing current API so that it may allow more fine grained tweaking of loggers (addition of module info, providing built-in multiplexing logger). There should be no temptation to build own stuff with own API because you can't write own logger that fits standard one.

But actual batteries - no, this does belong to Phobos.
October 15, 2013
> But actual batteries - no, this does belong to Phobos.

* does not belong
October 15, 2013
On 10/15/2013 03:31 PM, ilya-stromberg wrote:
> On Tuesday, 15 October 2013 at 07:52:28 UTC, Robert Schadek wrote:
>> On 10/15/2013 04:06 AM, Eric Anderton wrote:
>>> On Monday, 14 October 2013 at 11:39:52 UTC, Dicebot wrote:
>>> Here's what I think is missing:
>>> - System log support (as others have mentioned).  This would be syslog
>>> or WEL, depending on environment.
>> This is sort of the idea of the design, I can't anticipate your needs therefor I should not try. I should try to give you guidelines or a framework to work against.
>
> Totally disagree. We need a powerful logger, not only file logger. I can implement a file logger myself for a few hours, and it will cover 90% of my needs. For other 10% I would like to have a standart logger with advanced features like speed and reliability.
I bet your 10% and mine 10% do not overlap. And than either you or I will complain about it.
>
> If you need help, please tell us. For example, jkm already implemented
> syslog for Vibe.d with support files (via file streams) and the
> network (via TCP or SSL streams):
> https://github.com/rejectedsoftware/vibe.d/pull/294
> It's under the MIT license, that similar to the Boost license.
>
> Sönke Ludwig, can you allow to use syslog code for `std.logger` under the Boost license? Robert Schadek can use it as initial point.
Before any time is spent to implement x number of logger the design must be done.
October 15, 2013
On Tuesday, 15 October 2013 at 13:52:17 UTC, Robert Schadek wrote:
> I think this is good, as it gives you a way to quite libraries down. The
> idea behind the free standing "log" function is to provide an ultra easy
> way to log. It is not meant to be used for the 2<<31 line program. In
> that case you will properly have very specific needs on how to log.
> Hence implement the abstract Logger class to your needs.

I'll consider any logging library that forces me to use logger instance explicitly for typical tasks a failure. Once the system is configured upon program startup, using free functions and/or system-wide defaults should be enough.
October 15, 2013
On 10/15/2013 03:54 PM, Dicebot wrote:
> On Tuesday, 15 October 2013 at 13:31:40 UTC, ilya-stromberg wrote:
>> ...
>
> I think such stuff should go as an extra module in same package with various useful out-of-the box logger implementations at the very best. Probably even dub package built on top of std.logger;
>
> Phobos has very specific general design I like a lot - self-contained modules/packages with zero external dependencies (please kill std.net.curl!), which do work by simply importing certain modules. No extra configuration, no creation of weird useless classes - just reasonable defaults that work as-is in most cases.
>
> In that sense what is 100% needed is enhancing current API so that it may allow more fine grained tweaking of loggers (addition of module info, providing built-in multiplexing logger). There should be no temptation to build own stuff with own API because you can't write own logger that fits standard one.
>
> But actual batteries - no, this does belong to Phobos.
+1


October 15, 2013
On 10/15/2013 03:57 PM, Dicebot wrote:
> On Tuesday, 15 October 2013 at 13:52:17 UTC, Robert Schadek wrote:
>> I think this is good, as it gives you a way to quite libraries down. The idea behind the free standing "log" function is to provide an ultra easy way to log. It is not meant to be used for the 2<<31 line program. In that case you will properly have very specific needs on how to log. Hence implement the abstract Logger class to your needs.
>
> I'll consider any logging library that forces me to use logger instance explicitly for typical tasks a failure. Once the system is configured upon program startup, using free functions and/or system-wide defaults should be enough.
I don't think that there are enough compiler generated marked that you can pass as default parameter to a free standing function in a way that you can create a logger that fulfills this need. At some point you properly have to write a string of and identifier to specify a logger.
October 15, 2013
On Tuesday, 15 October 2013 at 13:54:12 UTC, Dicebot wrote:
> On Tuesday, 15 October 2013 at 13:31:40 UTC, ilya-stromberg wrote:
>> ...
>
> I think such stuff should go as an extra module in same package with various useful out-of-the box logger implementations at the very best. Probably even dub package built on top of std.logger;
>
> Phobos has very specific general design I like a lot - self-contained modules/packages with zero external dependencies (please kill std.net.curl!), which do work by simply importing certain modules. No extra configuration, no creation of weird useless classes - just reasonable defaults that work as-is in most cases.
>
> In that sense what is 100% needed is enhancing current API so that it may allow more fine grained tweaking of loggers (addition of module info, providing built-in multiplexing logger). There should be no temptation to build own stuff with own API because you can't write own logger that fits standard one.
>
> But actual batteries - no, this does belong to Phobos.

I did not talk about additional external libraries. As I know, Vibe.d use OpenSSL to provide SSL streams. Since we haven't got encryption support in Phobos, we can provide only TCP streams.
October 15, 2013
Am 15.10.2013 15:52, schrieb Robert Schadek:
> On 10/15/2013 03:21 PM, Sönke Ludwig wrote:
>> Am 15.10.2013 10:41, schrieb Robert Schadek:
>>> On 10/15/2013 02:44 AM, Kapps wrote:
>>>> The simple act of logging a message is very verbose right now:
>>>> log(LogLevel.trace, "Creating new pool") is a lot of boiler plate. I'd
>>>> prefer something like log.trace("Creating new pool") and log("Creating
>>>> new pool") where the latter would use opCall to forward to the default
>>>> log level. If it's intentional that you can assign the result of log,
>>>> this also helps that because log = new StdIOLogger would be possible
>>>> (log being a property that returns a Logger, and so a setter could be
>>>> made), but log("Creating new pool") = new StdIOLogger() would not be.
>>> The LogLevel is optional. And always writing log.trace might become more
>>> typing work and assigning a LogLevel and than calling log("..."). Both
>>> have pros and cons
>>
>> What happens when a called function alters the default log level?
> The default log level is altered.

Believe it or not, for some reason I suspected as much.

>>
>> ---
>> void func1() {
>>      log.logLevel = LogLevel.debug;
>>      log("This is a debug message");
>>      func2();
>>      log("This is supposed to be a debug message");
>> }
>>
>> void func2() {
>>      log.logLevel = LogLevel.warning;
>>      log("This is a warning");
>> }
>> ---
> If you don't specify a logger nor a LogLevel the currently set default
> logger will log the message with its currently set LogLevel.

Yes, but the point is that when looking only at func1, you might expect that all messages are logged as debug messages, but the last one will be logged as a warning instead. func2 may be hidden in library where the function body is not readily available.

>>
>>
>> I don't think it's a good idea to use such kind of global state,
>> especially for a logging framework that is supposed to be shared
>> between libraries, so that it is difficult to predict what a
>> particular function does. With a logger that is shared between
>> threads, things get worse of course.
> I think this is good, as it gives you a way to quite libraries down. The
> idea behind the free standing "log" function is to provide an ultra easy
> way to log. It is not meant to be used for the 2<<31 line program. In
> that case you will properly have very specific needs on how to log.
> Hence implement the abstract Logger class to your needs.

But if it's available people _will_ use it in complex contexts. Also if the writer of a 2<<8 loc library uses it and the library is used by a large piece of software, that will also be affected. The point is that it is unhygienic and requires non-trivial extra work when using a logger in a multi-threaded environment. Some kind of scoped stack of default log levels would get around this issue, but that smells like over engineering.

>>
>> A related question: It seems like Logger.logLevel at the same time
>> means the minimum log level that is output and the default log level,
>> is that right?
> Yes. The LogLevel of each logger is the LogLevel used if non is
> specified and only messages are logged by this logger if their LogLevel
> is greater equal to that Level. Additionally the LogLevel must be >= to
> the global LogLevel.

But these are two different concepts and it's hard for me to imagine why they should be conflated. But I guess it's time to stop complaining about the whole log("message") complex.