Before a new Shell can be integrated (see #5), it needs to be defined how output to the shell and to different logs should be done.
Currently (USE 7.0.1), there are different technqiues used to output information. These techniques are:
1. org.tzi.use.util.USEWriter
classDiagram-v2
class USEWriter {
-out:PrintStream
-noProtocolOut:PrintStream
-err:PrintStream
-log:ByteArrayOutputStream
-logWriter:PrintStream
-quietMode:boolean
+getOut():PrintStream
+getErr():PrintStream
+getProtocolOut():PrintStream
+protocol(line:String)
+writeProtocolFile(out:OutputStream)
+isQuietMode():boolean
+setQuietMode(quietMode:boolean)
+clearLog()
}
class LoggingOutputStreamDecorator {
-out:OutputStream
+write(b:int)
}
class OutputStream
OutputStream <|-- LoggingOutputStreamDecorator
USEWriter ..> LoggingOutputStreamDecorator: use
Description
The class USEWriter represents a singleton that logs output to an additional logWriter. This behaviour can be changed by setting the quiteModeflag. Further, the logWriter can be bypassed by using the original stream getNoProtocolOut().
It represents some kind of manager for the decorated streams and a data sink for all output of USE.
Functionality
Log output to additional log-buffer
Suppress output to default stream, but write to log-buffer by using setQuietMode
Bypass log-buffer by using getNoProtocolOut
Usage
The USEWriter itself is used for the default outputs System.out and System.err at the very beginning of main, to be able to record all outputs of USE.
The addtional functionality of USEWriter is used as follows:
Log output to additional log-buffer: Used by MainWindow to write a protocol to a file.
Suppress output: No usage found in USE or USE plugins
Bypass log-buffer: No usage found in USE or USE plugins
org.tzi.use.gen.tool.GGenerator OUT
Suppresses warnings globally by switching them of Log.setShowWarnings(false); and restoring them afterwards.
This is a strong argument for passing an output object around instead of using a static logger class.
org.tzi.use.gen.tool.GGeneratorArguments OUT
org.tzi.use.uml.ocl.extension.ExtensionManager OUT
org.tzi.use.uml.ocl.extension.ExtensionOperation OUT
Uses a also a StringWriter to capture errors from Ruby execution. Is this really needed? ScriptContext of Ruby just uses a Writer.
org.tzi.use.uml.sys.DerivedLinkControllerDerivedEnd OUT
org.tzi.use.uml.sys.MSystemState OUT
org.tzi.use.main.Main OUT
org.tzi.use.main.shell.HelpForCmd OUT
org.tzi.use.main.shell.ReadlineStack ERR
org.tzi.use.main.shell.Shell OUT, DEV, ERR
Uses also the functionality to reset the output flag: Log.resetOutputFlag();
However, Log.didOutput() is never called from USE. Maybe from plugins?
org.tzi.use.main.shell.ShellCoverageCommandProcessor OUT
Log.trace(String) is called from 1 place in the following class:
org.tzi.use.uml.ocl.expr.Evaluator
Log.trace(Object location, String msg) is called from 11 places in the following classes:
org.tzi.use.uml.ocl.expr.EvalContext
org.tzi.use.uml.sys.MSystem
org.tzi.use.uml.sys.MSystemState
org.tzi.use.main.shell.Shell
Log.trace(Object location, String msg, boolean flush) is called from 1 place in the following classes:
org.tzi.use.util.Log
3. Direct output to System.out and System.err
Many places access System.out or System.err. A detailed list can be generated using ArchUnit with the following test:
@ArchTest
public static final ArchRule noSystemOut = GeneralCodingRules.NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS;
Shell
The class Shell outputs to System.err if there is an exception "on a lower level". This is done to be as less dependent as possible.
Sometimes output to the shell is done by System.out, without any reason. This should be replaced by some explicit handling of the shell output.
Options
Prints help on System.out
4. Usage of PrintWriter on execution
Some areas of USE pass loggers as arguments. For example, the USECompiler takes an argument PrintWriter err to report compilation errors. However, there is just one kind of output with no differentiation between errors, warnings, debug, ... on the USE application level. For this, sometimes awkward solutions are implemented. For example, the BaseParser uses System.err to provide a warning writer.
Proposed Solution
The new approach to output information should
separate output for users and output for developers
allow for multiple output targets, i.g., shell and logwindow
allow for decorated output, i.g., output warnings in yellow, etc.
To achieve 1., a class UserOutput is proposed. This class is used instead of the currently used PrintWriter. To output information to developers, a well accepted logging framework should be used. This clearly separates user output from development information.
The proposed UserOutput class provides methods for different output levels for USE:
Output in USE 7.0
Before a new Shell can be integrated (see #5), it needs to be defined how output to the shell and to different logs should be done.
Currently (USE 7.0.1), there are different technqiues used to output information. These techniques are:
1. org.tzi.use.util.USEWriter
Description
The class
USEWriter
represents a singleton that logs output to an additionallogWriter
. This behaviour can be changed by setting thequiteMode
flag. Further, thelogWriter
can be bypassed by using the original streamgetNoProtocolOut()
.It represents some kind of manager for the decorated streams and a data sink for all output of USE.
Functionality
setQuietMode
getNoProtocolOut
Usage
The
USEWriter
itself is used for the default outputsSystem.out
andSystem.err
at the very beginning ofmain
, to be able to record all outputs of USE.The addtional functionality of
USEWriter
is used as follows:MainWindow
to write a protocol to a file.2. org.tzi.use.util.Log
Description
The class
Log
allows to separate between normal output, warning, errors and debug information. It is a static utility class.Functionality
Inconsistencies
print
,println(String)
,println()
, all other levels notfDidOutput
Usage
The class
Log
is used for different intensions:While 1 and 3 are in my opinion valid usages, 2 isn't.
Log.println(String)
is called from:quiet
andcompileOnly
are queried. Should be considered in new version.Log.error(String)
is called from 104 places in the following classes:org.tzi.use.analysis.metrics.AbstractShellCommandProcessor (unused class?)deletedorg.tzi.use.analysis.metrics.GSMetricConfigurationdeletedLog.setShowWarnings(false);
and restoring them afterwards. This is a strong argument for passing an output object around instead of using a static logger class.ScriptContext
of Ruby just uses aWriter
.Log.resetOutputFlag();
However,Log.didOutput()
is never called from USE. Maybe from plugins?Log.error(Object location, String msg)
is called from 0 placesLog.error(Exception)
is called from 3 places in the following classes:Log.error(String s, Exception e)
is called from 23 places in the following classes:Log.warn(String string)
is called from 17 places in the following classes:Log.debug(String)
is called from 130 places in the following classes:Log.verbose(String)
is called from 17 places in the following classes::Log.trace(String)
is called from 1 place in the following class:Log.trace(Object location, String msg)
is called from 11 places in the following classes:Log.trace(Object location, String msg, boolean flush)
is called from 1 place in the following classes:3. Direct output to System.out and System.err
Many places access
System.out
orSystem.err
. A detailed list can be generated using ArchUnit with the following test:Shell
The class
Shell
outputs toSystem.err
if there is an exception "on a lower level". This is done to be as less dependent as possible.Sometimes output to the shell is done by
System.out
, without any reason. This should be replaced by some explicit handling of the shell output.Options
Prints help on
System.out
4. Usage of
PrintWriter
on executionSome areas of USE pass loggers as arguments. For example, the
USECompiler
takes an argumentPrintWriter err
to report compilation errors. However, there is just one kind of output with no differentiation between errors, warnings, debug, ... on the USE application level. For this, sometimes awkward solutions are implemented. For example, theBaseParser
usesSystem.err
to provide a warning writer.Proposed Solution
The new approach to output information should
To achieve 1., a class
UserOutput
is proposed. This class is used instead of the currently usedPrintWriter
. To output information to developers, a well accepted logging framework should be used. This clearly separates user output from development information.The proposed
UserOutput
class provides methods for different output levels for USE:Originally posted by @h-man2 in https://github.com/useocl/use/issues/5#issuecomment-1359066237