Hi Keith -
Thanks for the code review....see my response inline.
ginnie
On 07/16/10 02:18 PM, Keith Mitchell wrote:
On 07/16/10 12:46 PM, Ginnie Wray wrote:
Hi -
I've posted the python logging files for code review.
http://cr.opensolaris.org/~ginnie/install_logging_pyfiles/
I would like feedback by July 27th, COB.
Thanks,
ginnie
_______________________________________________
caiman-discuss mailing list
[email protected]
http://mail.opensolaris.org/mailman/listinfo/caiman-discuss
Hi Ginnie,
I spent a lot of time on this review, as I feel any CUD component
deserve a detailed review. For the most part, I think my comments are
"clean-up" related - making code easier to read, more flexible for the
long-term, etc. The only main implementation component I have concerns
about is the building of a ProgressLogRecord to not have a levelno,
and the amount of extra code that results from that.
(I also plan on reviewing the C portion early next week)
- Keith
Hi Ginnie,
usr/src/lib/Makefile:
Copyright: Should be 2007, 2010
Ordering of entries in COMSUBDIRS is backwards compared to SUBDIRS (in
the latter, XXX_pymod entries come after XXX). Could you fix this for
both the logging module and errsvc (assuming there's not some obscure
Makefile related reason they have to be in the opposite order, of
course).
Fixed.
install_common_vals.py:
These values can be defined in install_logging.py as module or class
variables, and this file removed.
I originally had them defined a globals, but then thought it would make
more sense to have
them in a separate file. I moved them when I was writing the unit
tests....because I needed to use the same variables in the tests. My
thinking was that for remote logging, we might want to have access to
some variables used by the logger, but not necessarily the whole logging
module.
Your feedback on this?
install_logging.py:
Naming nit: Given that this file goes under
vendor-packages/osol_install, the "install" part of install_logging is
redundant.
True. I was trying to differentiate if from the logging.py module. I
thought maybe that would get too confusing. Are you suggesting
osol_install.logging instead of osol_install.install_logging? Now that I
type it, it does look better. :)
General: Rather than stripping out "level" from Progress Records and
splitting logic paths down those lines, perhaps it would be better to
simply have the 'level' for Progress Records be <MAXINT> (or some
other large value that would pass all logging level checks). This
would let them fit in with the logging paradigm more smoothly, and
remove the need to override callHandlers in line 339.
57-58: Function isn't needed.
ok. I'll remove that. thanks.
81: This seems like a stub that will be completed later, as preamble
isn't used anywhere that I can tell as of yet?
Yes...Sanjay and I talked about this and we will be adding more for
remote logging as it is implemented.
101-102: If the error is not 17, I imagine there will be a further
error raised by the __init__ call below, so printing the traceback
seems redundant. Need to either error out here, or simply pass
(regardless of the error code) and let the below __init__ call raise
exceptions if things aren't set-up right.
Here is my logic for setting this up. The FileHandler Class doesn't do
any checking for directory paths, and it is sporadic on creating them
and returns a traceback in some instances.
For example, if /var/tmp/install exists, and I want to create
/var/tmp/install/log/default_log, it will work because the log directory
doesn't exist. But, if I create /var/tmp/install/default_log, it fails
because I'm not creating a new directory in that scenario.
I didn't think the install logger should fail because the directory
didn't exist, so I added the os.mkdirs command to check for that. It
returns a traceback if the directory already exists (that is error 17),
and that seems like an error that can be ignored in this case.
103-104: In what scenario does the try clause raise a TypeError?
The pydoc for os.makedirs shows mode as an optional keyword, but it's
actually not a keyword; it's an arg that can be passed. My thought was
to catch that if someone passes that in incorrectly because of the
incorrect pydoc information.
109: I'm concerned that the need to override the "format" method of
the default FileHandler reduces the extensibility of our module -
would something similar need to be done for any other of the default
Python logging module's handler classes? If so, that's a bit of a
stopper in terms of extensibility. I think we can find a way around
this; perhaps by having a default formatter that itself contains two
separate format strings - one that gets applied to records with a
progress attribute, and one that gets applied to records without
progress data.
I'm not clear what your concern is here. I believe that what I'm doing
is what your suggesting.
The scenario I'm expressing in this code is the following...
When logging is invoked a default log file is created. If a Progress
Handler is invoked, there is a default progress log file created.
If a call to log a record to a file comes in the format method checks to
see if it's a progress log. If it is, it uses progress log formatting.
That's the only change I made to the Filehandler format method from the
logging.py module.
149: Should this be a subclass of logging.LogRecord? If not, should we
be mimic-ing more of the functionality (in particular, setting things
like self.created (time stamp), self.thread, self.threadName, etc.?
I'll take a look at that. I didn't do it because there wasn't any
overlap in the information passed in to the records.
226-228: I think this could be simplified by weighting the progress
value at creation of the progress record, rather than upon emission of
the record (if necessary, ProgressRecord could be updated to store
both the original value and the weighted value). This would also
change it so that InstallLogger is dependent on
InstallEngine.get_weighted_progress(), rather than ProgressHandler -
which would allow for more long-term flexibility in terms of defining
classes that can receive/send progress. Along this same vein, I'd
suggest shifting how the instance of the install engine gets set - let
InstallEngine._init_logging set the engine instance (where the engine
instance is a class variable of InstallLogger). This provides cleaner
breakage between the modules, and allows for better management of
dependencies between the two - as well as providing a convenient way
for the unit tests to insert a mock engine (thus allowing the unit
test file to avoid having any need for the InstallEngine proper).
ok. This seems reasonable. Let me review it and see what I can come up with.
258: default_log and base_name - appear to be read-only properties.
May be better off removing them entirely and simply referencing the
constants they're initialized to.
259-262: Similarly, if these are intended to be constants, I'd
recommend having them be at the class or module level rather than the
instance level.
Ok. I can do that.
251: Default logging levels look strange - I'd expect this to either
be INFO or NOTSET, and the value passed to logging.Logger.__init__ to
be the variable "level" instead of hard-coded to a different default
value than InstallLogger.__init__.
267: Should also use the variable "level" to make changes consistent.
ok. I'll clean this up.
270, 290: These removeFilter calls seem unnecessary.
That might be an artifact from an earlier version that I somehow missed.
I'll review that.
307: overzealous except clause
No one has ever said I shouldn't be over-zealous.
355: pep-8 nit: no spaces around '=' in keyword arguments
Missed that one in my cleanup.
Function seems inflexible for future extension (no support for, for
example, transferring all registered FileHandlers' log files to a
single destination folder).
I actually had that in, but I had a discussion with Karen, and the
result was that we decided only the default files would be transferred.
363: As destination is transient, there's no need to set
self.destination here - that'll just lead to stale data and confusion
during debugging. (This goes for many other places as well - no need
to store self.local_function_variable, just use the local variable
directly)
ok.
370: Printing to stderr here seems like the wrong choice - this will
cause problems with both text install (display will be distorted) and
gui install (nothing will get seen). It'd be better to let the
exception propagate and let the caller decide what to do (ignore, send
a message to the user, try again, etc.). Note: I think printing to
stderr is fine during initialization stages, as there's may be no
other reasonable method for communication.
ok. I'll fix this.
374: More of a design consideration, so perhaps it's too late, but
would "shutdown" be a more appropriate name for this function?
I don't have any strong feelings about this. I was following the
architecture doc. However, I have coded it that way, and that is the
info that has been propagated to test. I kind of hate to change things
on them.
378, 395: Similarly, printing to stderr seems like a bad idea here as
well. Perhaps this function could return a value (a list of files, for
example) that the caller could then use as needed?
ok. I can add that.
387, 390: These AttributeErrors should be avoidable with use of
"hasattr(object, attr)"
ok. I'll give that a try.
install_engine.py:
Is this file temporary?
On a related note, the install engine will be under
osol_install.engine, so the imports in install_logging.py will need an
adjustment (although if the suggestion for shifting the dependency on
the engine is followed, the imports become completely unneeded).
Actually, at the time, I thought I might need to include it for the
tests, but there is not reason not to use the osol engine.
install_logging_unittest.py
General: Suggest rename to test_install_logging.py (works better with
automatic recognition by nose).
I also think there is need for unit tests that target specific
functions of the classes defined in install_logging.py. The test cases
given cover the module as a whole, but don't drive down to the unit
level just yet.
ok.
24-51: I'd remove this, and add the test directory to
usr/src/tools/test/tests.nose, as that should be the preferred method
for running tests. (Once done, you should be able to generate a code
coverage report, which would be valuable to include with the review)
ok.
55: It should be possible to have this unit test file be completely
independent of the engine, if following the previous suggestions
regarding dependency on the engine. I believe the only necessary
action would be a call to logging.setLoggerClass(InstallLogger) as
part of setUp().
ok. I'll look at that.
64-70: Simply setting self.test_logger to None should be sufficient.
ok.
73-80: The cleanup code will not fully cleanup in all cases. For
example, if line 74 raises an exception, line 77 won't get run, which
means that directory won't get cleaned up.
ok. I'll look at that.
240-254: Have simpleprogressrecvr register a callback function or
something similar, instead of writing to a log file, to remove the
dependency on the filesystem (unit tests should strive for minimal
file I/O, though of course this module will be reliant on file I/O to
a degree when testing FileHandler). This would also then serve as a
good example for how gui/text installer might create an in-process
progress receiver to receive the socket updates and update the UI's
progress bar.
ok. I'll take a look at that too.
Thanks again. I appreciate the feedback.
ginnie
_______________________________________________
caiman-discuss mailing list
[email protected]
http://mail.opensolaris.org/mailman/listinfo/caiman-discuss