On Tuesday, 28 October 2014 at 11:11:09 UTC, Martin Nowak wrote:
I think part of the misunderstanding is that I'm thinking of an app as user code plus a number of libraries all on top of phobos. Say I have an app using vibe.d and I want to enable logging in my app, but disable it in phobos. Was it even a design goal that logging can be enabled on a per library level?

Whether it was an original design goal or not, I don't think it can be done with today's std.logger, and I would argue that it should not be a function of std.logger at all.

Selective logging of a mix of libraries requires a namespace to identify each library, along with a method for libraries to obtain their Loggers based on that namespace (e.g. giving Logger a name, which it does not have now, and using a factory method like Logger.getLogger()). We could assume that module names will always be available to do that job (and by default I do provide that as a reasonable default in log4d), but I can easily imagine other namespace choices for unknown future users. I also think that most end users would prefer their selective enabling/disabling of libraries' logging to happen at runtime, not compile time, and the HOW of turning things on/off will also be very user-dependent (regex, config file, environment var, ...).

We are bleeding between "mechanism" and "policy" here. I feel that std.logger is mechanism: given that a client has a Logger "thing" (struct, class, whatever), which methods will the client call on it to emit output to somewhere? Frameworks like log4d are policy: how are the Loggers that are obtained by lots of clients organized into a coherent whole, and the outputs filtered/directed/controlled by the final end-user? Policy should always be deferred to third party libraries. I obviously like the log4d/log4j approach, but other people will like vibe.d logger, some will roll-your-own, some will just send everything to syslog, etc.

If we really want to insist that std.logger provides selective control of libraries, then I think we will also need to establish policy at this time. I see two reasonable choices.

Option 1:  minimal change

1. The policy is that we control library logging by letting the client replace Logger references at runtime. 2. We say that libraries either use stdlog, i.e. info(...), error(...), etc., OR that they expose a Logger reference that clients can replace. 3. Clients replace stdlog or the libraries' Loggers with Loggers from their chosen framework.

Option 2:  invasive change

1. We make policy that there is a namespace of all loggers and it is __MODULE__.
2. stdlog is removed.
3. Loggers are obtained only via a getLogger() type call. Any function that wants to log must call getLogger() first. 4. log(...), info(...), etc. are removed. All logging goes through a Logger: Logger.info/error/etc(...) 5. Clients replace the getLogger() factory method with a function/delegate provided by their framework.

I think that option 1 would scale better long-term. Phobos can choose to use stdlog for its own logging, and other libraries can make their own (vibelog, foolog, ...). std.logger would need no changes.



Final thought: filtering. We have several filtering methods now, and I am confused as to what is actually missing:

* ANY AND ALL logging can be disabled at compile time via versions. This only includes client code and libraries the client is compiling too; I would assume that the default shipped phobos would not version-remove log calls.

* ALL logging can be disabled at runtime via globalLogLevel and a single if check at the call site.

* Per-Logger logging can be disabled at runtime via Logger.logLevel and a single if check at the call site.

* All other kinds of filtering (on msg, timestamp, method, etc.) are available at runtime to Logger subclasses, but happens after the logImpl call and setup of LogEntry.

What other capabilities are needed for filtering?

Reply via email to