-
Notifications
You must be signed in to change notification settings - Fork 23
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
logging tree support #146
Comments
Whatever does not mimic what happened in the JVM space is fine for me. I have written fairly complex applications, and every single time I have to fight the logger configuration, ovverride the imports for libraries, remove duplicated versions of loggin libraries and finally give up and ask a colleague |
I try to avoid "logging" as far as possible, I fill Sqlite DBs instead. Either the data is important, then it should end up in a database or it is not, then it's just noise filling up hard disks everywhere and slowing down the programs. Having said that, others believe in "logging" and the stdlib's facilities are pretty weak indeed. I'm not sure that a "hierarchy of logging configuration" will end up any better than a "hierarchy for styling" (CSS). Let's maybe instead add some "subsystem: string" idea that can be used to en/disable things? That would be on a "subsystem" level, flat, no hierarchy involved. |
It's not uncommon to store structured logging into databases. journald does that on localhost and remote logging is often stored into log databases with search and alarming capabilities. With a hierarchy similar to python , suppose my application uses httpclient directly and through a 3rd-party library for AWS and I want to debug the latter. Using |
AFAIK it is, you just can't do everything in your list of bullet points, in particular "changing logging level only for a submodule". Everything else is pretty much there AFAIK. I'm using |
Is this meant to integrate a library's logger with the application logger? https://github.com/dom96/jester/blob/master/jester.nim#L456 If so there should be a helper to do that and it should be recommended for library authors. |
Well, logging is really a solved problem for some people, and for other people it is an unsolvable problem. But I don't see why this is a language RFC. Logging is one of the easiest things that can be implemented in a nimble package, you can start by porting your favorite logging module from languagX to nim. When a good logging module has been written, it might be worth to check if it could be taken over as the standard logging package that will come with Nim. But I don't think the development of a logging module should happen in the Nim project. |
@krux02 The disadvantage of putting logging in a Nimble package instead is that there will be multiple conflicting logging packages, and you can be sure that the various libraries you import will use all of them. So at some point, someone will standardize an interface, and newer libraries will use that interface and there will arise packages that allow compatibility between this interface and existing logging libraries. This all happened in the JVM and the result is that there are people who are able to, say, train a machine learning algorithm on a distributed cluster but will have fear to configure the logger. My view is that the stdlib should:
This way we can hope to keep the whole thing sane |
There is a slow and simplistic implementation of a logger: As I said, everybody has a different perspective on how logging should be done. |
Third party "packages" should not log to begin with. Logging belongs into the application layer and nowhere else. Otherwise every complex subsystem will start to log some crap somewhere and you're just doomed. Using interfaces instead didn't help Java, it won't help Nim and is a symptom of mitigating a misdesign. Logging doesn't need to become simpler to use, it needs to go away entirely. |
I agree with the sentiment. Still, I don't think that logging in libraries will go away anytime soon... |
@andreaferretti there are external logging libraries e.g. https://github.com/FedericoCeratto/nim-morelogging but, as you said, we need a standard interface that all applications and libraries can use. Hence this RFC. |
All the packages I write log using the |
Well stop it and feel bad for doing that. :P |
@Araq I don't even know what to say to that. I will say this with as much respect as I can: you need more experience writing and maintaining long-running and scalable services to appreciate the importance of good logging. I'm really puzzled why you're against the logging module, didn't you design it? |
The services/web crawlers I wrote worked for months and did run 24 hours every day without crashes so no, I don't need more experience about how to write "long-running and scalable services". And they did use logging and then I wrote a program to analyse these logs... These days I would simply fill a database instead and skip the silly toString/parsing business. The data that I logged was crucial too, so using a database would have been justified.
I'm not against the logging module, I'm against logging itself. |
FWIW, our Chronicles library supports "logging to a database", allows you to disable the logging code on a per-library basis and has many other bells and whistles. |
@Araq Database require a lot more resources and maintenance than flat files. Sure, they are the ideal, and why I've created the prometheus package, but not every user wants to set up a DB for this. |
IMO if a library wants to give me a way to log what it's doing it should allow me to pass a proc to it, with the arguments of that proc defined by the library, but typically include the logging level (an int or enum) and whatever the library gives me to log. So in short: I don't think the stdlib needs a logging module, but rather the libraries should provide an API that lets me plug in my own logging solution. |
@Clyybber, enabling and disabling logging and choosing the output format at compile-time is nicer though. With the "injected proc" model, the API will be a bit more limited, because it will have to rely on type erasure to reduce all values that can be logged to something like a formatted string. And the libraries will still face the dilemma whether they should have logging at all, because it will still produce run-time code even when not used. With the model provided by Chronicles, you can just completely eliminate the logging from a certain library with a compile-time switch. |
A real-life example of a Python application using the boto3 library leads to the following nested loggers: application -> botocore -> s3transfer -> urllib3. Setting all loggers are set to "debug" level proved to be crucial to investigate an issue around a transfer. In other times the application level is set to "debug" while botocore and its children are set to "info" to prevent its very verbose logging. |
@arnetheduck gave another good argument against the "logging doesn't belong in libraries" philosophy. The best software nowadays is such that everything is a library. For example, is Clang a compiler or a library? If you examine their build scripts, you'll see that the "application" there consist of a single main file, everything else is a reusable library. The key enabler for having some logging in every library is the ability to turn it off with a compile time switch. Then it can have zero cost in the default configuration, but if you have to debug an issue, you have a richer set of tools at your disposal. |
@zah better a runtime switch. The majority of software is not run and debugged by upstream developers, especially libraires. |
Chronicles have options to either remove all logging at compile-time or to leave a run-time switch. You can control this for the individual third party libraries that you are using (as long as they play along and also use Chronicles). |
Same for the Nim compiler these days, it's usable as a library. It also doesn't log, so there, you can write sizable applications without logging. |
but nim does log: it prints compile errors, warnings and hints. clang also logs: it allows you to pass in a log collector (they call it a diagnostic collector) to the compilation process, thus avoiding the ugly global that a lot of logging ends up using (in fact, if doing a good library, this would likely be a cleaner approach rather than the global) server applications often log - that's often their only ui. not all applications are created equal and need the same amount of logging. that's the nature of the beast, just like not all applications benefit from a gui - nim for example doesn't have a gui. does that make guis less useful in the right context? the only argument against using logging in a library that I see is that it is that it leads to the information in the log not being exposed in the API so it's harder to get at it programmatically - in return, you get a more simple API with less noise. all this said, this is a prime example of something that can live in a separate library - there's no reason to have it in the std lib really.. like https://github.com/status-im/nim-chronicles for example. |
Ok, that's a good answer, however that's also what I was getting at: If you expose it in the API it will likely be some callback mechanism and these callbacks can have a typesafe, specialized interface, it's not some textblob you later have to parse. |
I want to offer a few opinions because I find myself both agreeing and disagreeing with a lot of what I see here, and GitHub rightly disallows offering both a 👍 and a 👎 on a single post. 😉
If those qualities can exist in a stdlib solution, regardless of how simple (or incapable) it may be, I think you have a real winner. To me, the rest of it is, really, gravy. Finally, and since issue #146 is titled as such, with just a small amount of introspection, libraries could be automatically tree'd into a logging system at compile-time, right? Doesn't the Python system use just a simple string, like "moduleA.submoduleB.subsubmoduleC"? |
That's what a logging module should do. Provide an API so that libraries can send log into something. Support pluggable backends so that application developer can send logs where needed at the required verbosity. Also, the API to create and extract log events can be typed and support key-value pairs. Logs are not necessarily opaque, raw text blobs. [Edit: I updated the RFC text to clarify this] |
Problem: the current logging module is not designed to be used in libraries.
If a library uses ConsoleLogger or FileLogger there is no way for the application to configure its logging behavior. As such, libraries do not do any logging.
To encourage good logging across the library ecosystem:
var logger = newLogger()
that is backend-independent and not opinionated on the logging format and is muted by default$
is used.[1] nim-lang/Nim#3270
The text was updated successfully, but these errors were encountered: