-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Basic logging in Base #13515
Comments
seems sufficient to me to keep this as a package. no need to make #5155 harder |
Forgot to mention: one challenge right now is that, since (Previously, only Which does leave the second idea above as an option for packages. @vtjnash, to clarify option1 above: why not at least move This would possibly be a breaking change (in a good way) by not having |
I quite agree, all these dances around extending logging functions in Base are miserable. I like the idea of |
I feel if anything deserves to be "blessed" as official, it's a logging system so that you could eg set up in your main script that logs of a certain severity should save to a certain directory and trust that all packages will respect that. Whether that means this logging module should be in Base or just that community coalesce around one logging module or API that shares configuration data, I don't have thoughts on. |
I've run into the same issues in the past when implementing my own On Fri, Oct 9, 2015 at 4:23 PM, Jon Malmaud [email protected]
|
I emphatically disagree with this. We need to provide the basic user-side logging API in Base because every package should use that API. By default it should just print logging messages, but it should be possible to load different logging backend packages that do different, more advanced things with the log messages. |
I like the |
it seems confusing to me to have so many functions that do the same thing (presumably they should be implemented by dispatching to a single function "log" rather than duplicating code), and yet the meaning of
I don't see this as a real argument. Enterprisey logging should be source and domain aware so that appropriate filtering can be done (e.g. it also can't address the fact that many C library wrappers and existing packages will never switch, so the "one true solution" is not attainable either.
sure, it sounds reasonable to stop exporting them from base. it looks like Pkg.jl / libgit2.jl is the only user of |
Are "enterprisey" packages supposed to not use any non-enterprisey packages? What makes something "enterprisey"? Does it have something to do with XML? The point is that when you need to start logging what's happening with your application, you want to log events in packages that you use, so they should all use a common logging infrastructure – which should therefore be provided by Base. We should come up with a lightweight but usable logging API and then encourage people to use it. We can automatically insert things like file name, line number and module, so making that an argument to logging seems silly. |
The main argument for |
I cooked up some general logging interface using a dependency injection and |
what, by 4 characters? we print WARNING in all caps, why shouldn't that be the input form also? @wildart let's not go crazy with the code generation and number of alternative ways to call into this. an enum (or other equivalent value object) should suffice for the level. it shouldn't allow passing a number instead of a category. and it really doesn't need any of this indirection via type parameters. having |
I hate that we print "warning" in all caps. |
But are you not warned? |
@vtjnash I agree that it was far fetched to have a non-enum level but I would like to see a a user defined levels and enums are not extensible. |
yes, i do seem to recall that was part of your commit message that made all WARNINGS uppercase ffe157e :) user-defined levels would be possible essentially by using a reimplementation of enums as an open set. however, i suspect this is not a good feature to have. it's more complicated to implement, reduces code commonality if used, makes it harder for a client application to design an interface and filter for all cases, and makes it harder to discover/enumerate the possible error levels.
|
That's certainly the way it works right now. I had proposed above that we move entirely to using (Although, it is true that |
Can't this be written as
Because 99% of people don't care at all about levels and don't want to spend one microsecond learning about them. To be used by them, your API has to be just like Python is an example of a failure here: many people use The most effective way would be to make |
@RauliRuohonen gets it. |
+1 for deprecating +1 for I actually don't care if the Base versions are anything more than printing On Tue, Oct 27, 2015 at 10:16 AM, Stefan Karpinski <[email protected]
|
After much though, I see only one solution - move current logging functions into separate module. That is the only way to reuse verbs. |
I've started some work on a minimal logging frontend API which I think addresses most of the points raised here: https://github.com/c42f/MicroLogging.jl. We need some good logging verbs in Design overview:
A tiny taste: julia> x = 42
julia> @info "My value is $x"
INFO: [Main:REPL:109]: My value is 42 |
I think we can call this closed by #16213 |
Ugh, how did I miss that? Thanks @tkelman. Regardless though, I don't think #16213 addresses all the problems with the current logging backend in 0.5, and in fact introduces some new problems to the user-visible API. As I see it:
@colinfang @Rory-Finnegan - you guys have had a recent go at this stuff in packages, and I'd like to hear your thoughts. What I'd really like is a logging API in Base which feels just as easy to the casual user as |
I should add that I'm grateful for the work done in #16213, I just don't think it hits the API sweet spot yet. |
Would love to have this in 1.0. If you have thoughts on how to accomplish such a design it would be excellent to have. Since effective logging often needs to be spread through libraries that one uses, the ideal is to have a single logging API that all packages can use, and which the user can then connect to whatever logging backend they want (or none if they just don't care). |
I strongly agree with this (as you may have guessed), but I'm not sure what the best way to represent those records is. I see log records sitting somewhere between a custom type (for dispatching) and a dict. Maybe folks have a clearer perspective of how records should be represented and stored?
Assuming I'm understanding what you mean... I don't really feel like this is a big issue as there are several ways you could address this. For example, Memento.jl only creates a log record and logs it if the level is >= to the logger level. Now I need to do that check for each parent logger in the hierarchy, but I don't think that's overly expensive in most cases. Alternatively, we could probably use macros to turn those calls into no-ops, but that may get complicated with the hierarchical logging functionality that some folks want (myself included).
I strongly agree with this. I do like the simplicity of logging to an IO type, but when you get into sending http requests to a logging service that design starts to break down. I'd be fine with some kind of Finally, I'm not sure I agree that the logging API needs to be in base julia by 0.1, but it would be nice if we could consolidate our requirements and preferences into a single package, maintained by multiple members of the julia community (I realize Memento.jl didn't help with that objective). |
@StefanKarpinski Great, I'll keep working on
@Rory-Finnegan What I'm mainly interested in is how the user-visible API should look and behave, so that the package ecosystem is encouraged to use something consistent. It's this API consistency for users who "don't care about logging" which is important for julia-1.0; the actual logger backend details are a secondary concern. I'm not sure, but it's possible that the details of a record type could be left to any logger package which plugs into a minimal frontend provided by Base. A custom record type makes sense so we can at least do things like overload
The issue here is that the the client side (that is, the module doing the logging) may have expensive work to do before being able to log the message. For example, suppose I've got a largeish matrix @debug "Condition of A is $(cond(A))" turn into if shouldlog(module_logger, Debug)
logmsg(module_logger, "Condition of A is $(cond(A))")
end which solves the problem. It also seems to solve the problem of the work required to look up (and optionally autocreate) a per-module logger, as this can be done at compile time.
Hah :) and neither did myself creating |
|
I don't want to distract too much from the conversation here, but I will point to my feeble attempts at logging/debugging in the new HTTP.jl package. The logging is way, way trivial, basically just printing a statement to an IO if the user said Anyway, just count me in as interested in seeing what develops, even if I can't provide that much actually useful code. I will say the approach of having Base define an extensible, but universal user-facing interface, w/ packages able to define their own custom |
I'd call it ZeptoLogging.jl, but then I'd have to limit the source code to one byte ;-) |
To me the really hard part is that you want logging to have negligible cost when you're not using it, yet ideally be able to turn it on dynamically to see what's happening in an already-running production process. Otherwise, it can be done with macros which compile to emit no code when logging is off. The only solution I can think of that might work for zero-cost is something like patch points. |
@quinnj I think something along those lines ( @StefanKarpinski patch points are super cool, but perhaps somewhat overkill for this use case. I think I've already got a rough solution for per-module log level testing which can get the cost of a non-logged message down to an integer load, comparison, and branch to skip the logging . The idea is that you look up the module logger in lexical scope (via current_module()) at macro expansion time, and hardcode the resulting reference into the AST. The test |
I'm pretty sure you also want negligible cost when you are using it, otherwise the logs will probably be too big to be useful. Would be nice for this to generalize the Lines 241 to 244 in 021e11e
depwarn command line flag. For other prior work, I'll also point to Gtk (https://developer.gnome.org/gtk3/stable/gtk-running.html#GTK-Debug-Options) and LLVM/Clang (http://llvm.org/docs/ProgrammersManual.html#the-debug-macro-and-debug-option). Common patterns here I would point out here is that:
For general logging, Glib provides a more structured API for connecting to the system log: https://developer.gnome.org/glib/stable/glib-Message-Logging.html. There's some overlap (they can also be filtered by sender), but seems to be a mostly different use case / different implementation? |
If you're logging so often that performance of logging becomes an issue then I think you need to be doing some kind of lightweight statistical logging like statsd clients do. |
Nice, the module Test
using MicroLogging
import MicroLogging: Logger, get_logger, Info, Debug
# logger setup, and add to the hierarchy with current module as parent.
const load_logger = Logger(:JL_DEBUG_LOADING, get_logger(current_module()))
configure_logging(load_logger, level=haskey(ENV, "JULIA_DEBUG_LOADING") ? Debug : Info)
function usage()
@debug load_logger "Rejecting cache file due to it containing an invalid cache header"
@warn load_logger "Module Foo with uuid cc4d520e-f2d7-422d-845f-04fec687968a is missing from the cache."
end
end
Test.usage() I guess |
This makes a lot of sense. There's a separate reason to have low cost on the "invisible logs" path: it's not that you want to turn those logs on, but when using third party packages it would be nice if the logs you're not seeing have negligible cost. So it would be nice to make design choices such that writing the slow version is more work for the user. |
Having a requirements list for logging infrastructure would be a great first step. Once we can get agreement on that, we can figure out what the design needs to look like. |
Would it make sense to put those requirements and proposed solutions into a Julep? |
Yes, absolutely. That's a great start, IMO. |
I've started reorganizing my thoughts into a julep which I'll put up as soon as I think it's presentable. |
Ok, I've got a WIP julep over at JuliaLang/Juleps#30 :-) |
As @StefanKarpinski noted here, it would be nice to have (very basic) logging as part of Base, which logs messages to output (STDOUT or other). This could then be extended by packages to add more complicated logging features (syslog, etc.).
Some ideas:
info
,warn
,error
,debug
,critical
) toBase
, perhaps wrapped in a module (Logging.info
,Logging.debug
, etc.)log
function (Logging.log(DEBUG, "some debug message"); Logging.log(INFO, "Here's some info")
, etc.)Thoughts? If we go with the first idea above, I would propose to move
Logging.jl
to theJuliaLang
organization as a start.For additional reference and ideas, current logging packages include my
Logging.jl
andLumberjack.jl
.The text was updated successfully, but these errors were encountered: