-
Notifications
You must be signed in to change notification settings - Fork 51
Log Refactor #654
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
base: dev
Are you sure you want to change the base?
Log Refactor #654
Conversation
…atabase can feed the log back.
Public Enum eErrorLevel | ||
eelUninitialized ' Used to indicate the erorr level wasn't set correctly. | ||
eelLoggingOff ' Logging is turned off completely. | ||
eelNoError ' Text event; logged and displayed at all log levels except off. | ||
eelDebugTrace | ||
eelDebugEvent | ||
eelDebugInfo | ||
eelWarning ' Logged to file | ||
eelError ' Displayed and logged | ||
eelCritical ' Cancel operation | ||
[_Last] | ||
End Enum |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eelLoggingOff ... should error level and LogOn/Off be separated so that the error level can be retained?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The LogLevel
and ErrorLevel
are not retained the same; the Log.LogLevel
is stored in the Log
class, and the ErrorLevel
is stored in clsOperation
Operation.ErrorLevel
; this way we can reuse the enum for both. If an error level is set but not logged, it's still retained in the Operation.ErrorLevel
(despite not being logged) if this makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the error handling to show this in Log2.Error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would not name this class clsErrorInfo but clsErrorLevel or similar.
Unlike my clsErrorInfo (#652), it only provides the ErrorLevel data.
When designing the clsErrorInfo, I encapsulated the complete error information - i.e. including the error message.
This enables the delegation of an ErrorInfo instance to the logger class.
This means that the composition of the text can be implemented in this class and the logger class can concentrate on the task of generating log entries.
Just a thought:
In principle, you could use 3 (or more?) classes:
- class with the error data (clsErrorInfo)
- class for formatting and output this data (here perhaps even several classes, depending on the output type)
- class to control above: clsLog
clsLog:
RaiseEvent LogError(eInfo as clsErrorInfo)
clsLogOutputToFile, clsLogOutputToTexbox, ..
listen to event clsLog.LogError
This would allow you to switch log output classes on/off at will.
Similar (AccUnitLoader):
DebugPrintTestResultReporter.cls
LogFileTestResultReporter.cls
MsAccessVcsTestResultReporter.cls
/edit:
https://github.com/josef-poetzl/msaccess-vcs-addin/tree/dev-refactor-log
This would make it possible to attach any logger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, these are good points.
I think for the purposes of this addin, while being able to have an extensible log would be nice, having a consistent entrypoint and keeping it easier would be better in this case. Especially since most of the log entries should hopefully be simply notifications of state and process notes, not errors.
Also, I am not sure having extra classes to handle errors helps more than the cost of carry. To me, having the clsErrorInfo
(or whatever we end up calling it) is really only there to help with consistently handling the warning/color notes as presented to users, not to format the error message. To me, that's the job of the calling function. I don't know we want to have the same error message type presented to the user if we expect an error and just need to make sure they're good with continuing vs an unexpected critical error (where they will probably need more information to debug it), and the best place for that would be the calling function, which would know if you want to use Log.Error
, Log.Prompt
, or Log.AddEntry
and skip presenting the user with info entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... I am not sure having extra classes to handle errors ...
Only extra classes to present or save the log.
For example: I personally do not need a permanently saved log. Then I simply do not activate this “listener” and the rest continues to run without any changes.
Or: Automated export via PowerShell ... then you could create an extra logger for this, which outputs to the shell console etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went ahead and made the functionality of the existing log export the same as before; this ensures the operation stays the same until we determine if more extensibility is needed (or wanted).
… events in there, too.
@josef-poetzl I have this just about finished up; though, I'm having trouble getting I did discover that the LogTable in the addin (when the addin is loaded as an addin) DOES keep the data from operation to operation, which is a neat thing, but I can't seem to get the thing exported correctly. I even went so far as to use the |
Maybe use a querydef (in the FE) that accesses the table in the add-in? The ADODB XML export is probably not an alternative, is it? By the way: don't forget that the data is gone when you update the add-in. |
Correct, it's actually desired; in actuality, I'm not sure I even wanted it to persist between sessions (to keep it lightweight), but that's another discussion. I don't know if we want the log to be muddied between different files being built/export, keeping the log to a single project is probably ok long term though. Depending on how long it takes to import/[do operation]/export to project log it may end up being more efficient to simply keep a per-operation log like is done now.
Hmm, I'll give that a shot; I was hoping to use a consistent XML export routine in case we ended up needing to sanitize it like we do with the tables; this gives the advantage of using the same XML parsing tools used by the addin for the built db and therefore a consistent XML look. |
Figured it out! was what I needed; it's also stupid fast; exporting about 900 records in a half second. I'm going to tidy it up and push up the finished up code; this first version will export the log, clear out the log after each operation so it's not persisted (as is the case now). If this works well I'll add some options to allow the log to be appended to the existing XML file or simply continue as-is (the current system). If that works well, the next step will be to expose the new log class externally via the API (so that the pre/post called functions can log their state if desired). |
this is guestimation; I haven't timed it, I suspect it's faster than that, I just wanted to point out that this operation doesn't take any more time than the current log saving mechanism. |
…any connected file. Also correct to clear out the correct log table.
ooh, unintended upside: because this class now relies on a table in the addin, if you somehow crash the addin/MS Access the log table remains and it will export next time you run an operation. This has been nice when I've caused a bug and needed to force close but don't know what went wrong during the export. |
…with the in-use parameter
…e already logged before exporting.
…ich simplifies the `IsLogged` code).
… update the tab order.
…t display factors.
…t loaded the first time)
I tested this version: works fine. One minor issue: Personally, I prefer the more compact display of 4.1. I would move the log table to an external file (accdu extension is a good choice) so that the add-in file does not keep getting bigger, as you probably won't compress the add-in file regularly. |
Thanks for the review!
This is due to how the Log.Flush runs; to speed up the export (causing a DoEvents slows things down a lot) the data may not show up instantly. Tuning how often a Log.Flush happens could improve that. Personally, I think the
Fair point! Because I didn't want to refactor the rest of the code (yet) to accommodate the log levels, I set the Refactoring to instead use an example I'm working on which would allow us to set the type of log information (and therefore how much/little is being displayed) ' In "ExportSource"
.AddEntry T("Beginning Export of Source Files"), FunctionName, eelDebugInfo
.AddEntry CurrentProject.Name, FunctionName, eelNoError
.AddEntry T("VCS Version {0}", var0:=GetVCSVersion), FunctionName, eelNoError
.AddEntry T("Full Path: {0}", var0:=CurrentProject.FullName), FunctionName, eelDebugInfo
.AddEntry T("Export Folder: {0}", var0:=Options.GetExportFolder), FunctionName, eelDebugInfo
.AddEntry IIf(blnFullExport, T("Performing Full Export"), T("Using Fast Save")), FunctionName, eelNoError
.AddEntry "Time: " & ISO8601TimeStamp(False, True), FunctionName, eelNoError
Hmm, I'll do some testing on this. my goal to start with is that it is just as fast as the original log class and has additional features; I didn't want to create additional dependencies without careful consideration. We could just have the file auto-compress on close/unload which (in my testing) doesn't impact it much. I'll do some testing on this.
Agreed; any log persistence would be a result of storing the logs in the source files, not the addin. |
Very good idea!
Please don't. :) |
🤣 |
I don't see any particular dependency. If necessary, you can simply (re)create the file in the add-in directory. |
Less of a class dependency, more of a "external file" dependency that has to be managed. Not insurmountable, but I didn't want to begin by creating a ton of complexity.
Good idea; I'll test that out; I think that may be the best way to do it. |
Tested "Build from Source": Console log is empty. BTW: |
Huh. I'll take another look and see if I didn't commit a fix on accident.
I agree, I think I may export the data column and strip the HTML out of it may be easiest. Lastly, I am having some trouble generating a temp ACCDU file. Connecting to it is no problem, and it seems fast enough when it's connected, but my simpleton lines aren't able to build the file. I will try and get those pushed today and maybe you have some ideas. |
An example from one of my add-ins: |
Made some progress; thanks for the tip! Worked a treat. Will hopefully get this tidied up and pushed up today. |
This is the first part of #507
First to demonstrate the log speed (this new one is FAST), and to maintain the functionality of the existing code (a whole-system refactor is not super duper desirable), and to incorporate the remaining elements of the log tool.
Remaining elements:
Log Level
(currently natively part of the new log class, but is not implemented in options) (Added to options)DisplayLogLevel
ShowDebug
ShowDebug
as an option.ShowDebug
is used 32 times. Suggest setting those use cases to an event level ofeelDebugTrace
,eelDebugEvent
, oreelDebugInfo
If Options.DisplayLogLevel < eelNoError Then Options.ShowDebug = True
(this seems the easiest way to handle it, actually)LogLevel
andDisplayLogLevel
after Options are loadedShow Debug
Checkbox to dropdown option forDisplayLogLevel
.LogLevel
This first PR is to build out others, create discussion, and have some review before we go forth. I've implemented it here as a ridealong to demonstrate feasibility and speed impacts (in my testing, it did not impact speed of export or build at all) and provided a ton more information and time stamp detail than I had.
The log also allows us to set the log level and thus keep the log a lot cleaner when users don't need ultragranular detail. For instance, if you're troubleshooting an export, you can set the log to log everything, even Debug Tracing. If you're in production, and you just want to know if warnings or more happen, you set it to warning.
Let me know what you all think!
If this initial implementation looks ok, I will refactor the rest of the
clsLog2
class into the new one, but wanted to start off by showing a proof of concept.@joyfullservice @josef-poetzl @bclothier anyone else?