Conversation
leventeBajczi
left a comment
There was a problem hiding this comment.
Thanks for the changes, I think these really help clear up the logging infrastructure of Theta!
I've skimmed through the changes, and these were my initial impressions. Please take a look -- but overall, I'm really happy with this PR.
There was a problem hiding this comment.
Was this change deliberate?
There was a problem hiding this comment.
I wrote this above in the pull request text:
Some other tests have been changes trying to fix issues which have to be reverted back like CFATest.
As mentioned this is "half pull" request. I just wanted to get an approval if turning it into a singleton is something desirable, so know I can spend more time fixing every detail and making ti nice.
|
|
||
| @Parameter( | ||
| names = {"--grep", "-grep"}, | ||
| description = "Log type pattern for the new logger API") |
There was a problem hiding this comment.
Saying "new" won't age well, just say "Log type pattern" -- also, add a line of documentation on its use with an example (either here as a comment, or in one of the doc markdown files)
There was a problem hiding this comment.
Also, explicitly say that either this pattern, or -- if not given -- the loglevel takes effect, but never their conjunction.
| ) | ||
| if (expandingNode.state.isBottom()) { | ||
| logger.write(Logger.Level.VERBOSE, "Node is a dead end since its bottom%n") | ||
| Logger.verbose("Node is a dead end since its bottom%n") |
There was a problem hiding this comment.
if we're already changing this line, please fix the original typo (its -> it's / it is), even though I find the current literal meaning quite funny
There was a problem hiding this comment.
I will need to take a closer look at this file. However, what I can already say, is that I don't like to see "yices" here -- that is very specific to one half-supported SMT solver. Can you give a reason why that is here, but no other solver is?
There was a problem hiding this comment.
That is just me trying to use the logger and giving an example how I accept it to be used in the future. Yices is not special at all its just where I spend more time trying to find a workaround to the SSL expired certificate problem, and therefore I used the logger their more extensively so I can also use it as a concreate example. The main idea is that eventually every class will have a type. (and also subtypes with in the that class type, is a tree of types with "grep" used to query it).
Lets suppose that I want to get the logs inside the CegarChecker. I would put as type:
INFO_CEGARCHECKER-> create a func infoCegarCheckerMAINSTEP_CEGARCHECKER-> create a func mainstepCegarCheckerSUBSTEP_CEGARCHECKER-> create a func substepCegarChecker
when I initialize with Logger.init("MAINSTEP|SUBSTEP") I would have both theMAINSTEP_CEGARCHECKER,SUBSTEP_CEGARCHECKER(and all the other types that have a substring ofMAINSTEPandSUBSTEP). But if I want onlyCEGARCHECKERthen Logger.init("CEGARCHECKER") and it will showSUBSTEP_CEGARCHECKER,MAINSTEP_CEGARCHECKERandINFO_CEGARCHECKER.
Sorry I didn't do it justice explaining how it works. I will have to write better docs.
There was a problem hiding this comment.
So, familiarizing myself with the logger, the main idea is that you have a more complex filtering than just a few levels of increasing verbosity. I think the filtering side (how you use --grep) is mostly clear to me.
My question is rather about how and where the possible values that are filtered are defined.
Here is what I understand about that:
I see the logTypes in the logger. I see that level is passed as a string to the log method and I see the enabled set. I can see that enabled just contains all matches of logTypes to the regex from --grep.
I think what Levi did not like (or will not like? :D ) is that someone implementing something new - let's say a new checker - will have to think about adding stuff in the logger. So the logger becomes cluttered with information from literally everywhere in Theta, and logTypes becomes huge.
I did not fully think the solution through, but I think there are roughly two directions:
- the central
logTypescollection of all the log types is avoided and these values should be distributed, e.g., per class/per file. Something likeSTMT_LABELs and things like that - an extra "utility" constant. Pro: if I develop a new checker, I just add a constant or two and I instantly have a working, customized logger; (BIG) Con: extra constant value in practically every file - I think the other solution is to just keep
logTypes, expect it to be huge and try to make that usable and maintainable - put it in it's own file and somehow make it foolproof in a way so that I don't forget to add my new log values to the new log checker
Also, the question is: how much do we plan to fill up logTypes right now? Do we want to 1) go through a lot of places and add a lot of custom log types OR 2) do we do it gradually - e.g., you add what you needed (yices, cegar, whatever) and the next person who needs it elsewhere, say IC3, can add it there. I would prefer the latter - just with some really well shown / highlighted doc, so that people know that they can do this?
(I'm curious about everyone's and anyone's input on this.)
| dataInitPrec, | ||
| Z3LegacySolverFactory.getInstance(), | ||
| logger, | ||
| Logger, |
There was a problem hiding this comment.
Why pass it here at all? (this is also relevant for all other tests here)
There was a problem hiding this comment.
Mainly I don't understand why some places had their logger parameters removed, and then here some just receive the singleton object. I think we should opt for one of these solutions.
There was a problem hiding this comment.
I will eventually fix all those places. There are a lot of shortcuts I took. And I also have to do a better review myself. The main point was if the this type of "Logger API" is preferred,
This PR is barely finished I just wanted a review if the API is nice and fits theta's ecosystem and mindset. |
|
Thank you for the PR, this is something that was needed for a while now:D Levi commented above that he would like to see "new" gone from the CLI parameter descriptions. I think this is something that we should go even further with and completely avoid maintaining both a "new" and "old/legacy" logging system, and instead remove the legacy logging completely, including:
If we reach a stable new logging system that can provide everything the legacy logging did, I think there is no need to maintain the legacy parts, they would only lead to confusion. |
Also I think it would be better to arrive on one option instead of having "grep", "log" and "loglevel" on the CLI interfaces. We have proper versioning, so we don't necessarily have to stick to older CLI parameters. |
Maybe it's just nostalgia, but I would vouch to keep the current loglevel flag. :D But I agree that we should only have one flag. If it can do complex regex expressions then it can do simple ones as well, so maybe with a different syntax, but it can still express what the old levels expressed. And I agree about being able to change the flag syntax due to versioning. |
|
@AdamZsofi To implement the Legacy (old flags) I just translated them to the appropriate regex expressions for the "grep" API. |
…disable support - Replace multiple Logger classes (BaseLogger, ConsoleLogger, FileLogger, NullLogger, UniqueWarningLogger) with a single Kotlin object Logger - Add Logger.enabled.kt / Logger.disabled.kt templates for compile-time logging toggle via -PnoLogging - Make Level enum public, remove isEnabled(String) overload - Update all call sites across analysis algorithms, CLI tools, tests, and solver installers to use the new Logger API - Fix corrupted StsMddCheckerTest.java (missing block comment opener) - Remove stale bin/.gitignore files - Add Logging.md documentation
|
I finished refactoring all the logger to a singleton:
Another important thing is that I could see |
PR: Logger singleton
Read
Logging.md