diff --git a/Mcode/+logm/Log4jConfigurator.m b/Mcode/+logm/Log4jConfigurator.m index 6d7cf112..a1ea39e3 100644 --- a/Mcode/+logm/Log4jConfigurator.m +++ b/Mcode/+logm/Log4jConfigurator.m @@ -15,9 +15,12 @@ % log4j:WARN No appenders could be found for logger (unknown). % log4j:WARN Please initialize the log4j system properly. % - % If that happens, it means you need to call + % If that happens, it means you need to call % logm.Log4jConfigurator.configureBasicConsoleLogging. % + % This also provides a log4j configuration GUI that you can launch with + % `logm.Log4jConfigurator.showGui`. + % % Examples: % % logm.Log4jConfigurator.configureBasicConsoleLogging @@ -33,8 +36,11 @@ % % % Display fully-qualified class/category names in the log output: % logm.Log4jConfigurator.setRootAppenderPattern(... - % ['%d{HH:mm:ss.SSS} %-5p %c - %m' sprintf('\n')]); - + % ['%d{HH:mm:ss.SSS} %p %c - %m' sprintf('\n')]); + % + % % Bring up the configuration GUI + % logm.Log4jConfigurator.showGui + methods (Static) function configureBasicConsoleLogging @@ -51,20 +57,20 @@ rootAppender = rootLogger.getAllAppenders().nextElement(); % Use \n instead of %n because the Matlab console wants Unix-style line % endings, even on Windows. - pattern = ['%d{HH:mm:ss.SSS} %c{1} %x - %m' sprintf('\n')]; + pattern = ['%d{HH:mm:ss.SSS} %-5p %c{1} %x - %m' sprintf('\n')]; myLayout = org.apache.log4j.PatternLayout(pattern); rootAppender.setLayout(myLayout); end function setRootAppenderPattern(pattern) - % Sets the pattern on the root appender - % - % This is just a convenience method. Assumes there is a single - % appender on the root logger. - rootLogger = org.apache.log4j.Logger.getRootLogger(); - rootAppender = rootLogger.getAllAppenders().nextElement(); - myLayout = org.apache.log4j.PatternLayout(pattern); - rootAppender.setLayout(myLayout); + % Sets the pattern on the root appender + % + % This is just a convenience method. Assumes there is a single + % appender on the root logger. + rootLogger = org.apache.log4j.Logger.getRootLogger(); + rootAppender = rootLogger.getAllAppenders().nextElement(); + myLayout = org.apache.log4j.PatternLayout(pattern); + rootAppender.setLayout(myLayout); end function out = getLog4jLevel(levelName) @@ -107,17 +113,17 @@ function setLevels(levels) function prettyPrintLogConfiguration(verbose) % Displays the current log configuration to the console % - % logm.Log4jConfigurator() + % logm.Log4jConfigurator.prettyPrintLogConfiguration() if nargin < 1 || isempty(verbose); verbose = false; end - function out = getLevelName(lgr) - level = lgr.getLevel(); - if isempty(level) - out = ''; - else - out = char(level.toString()); - end + function out = getLevelName(lgr) + level = lgr.getLevel(); + if isempty(level) + out = ''; + else + out = char(level.toString()); + end end % Get all names first so we can display in sorted order @@ -168,6 +174,24 @@ function prettyPrintLogConfiguration(verbose) loggerNames{i}, str); end end + + function showGui() + % Display the log4j configuration GUI + + % Make sure the log4j1-config-gui JAR is on the path + libDir = fullfile(fileparts(fileparts(fileparts(mfilename('fullpath')))), ... + 'lib'); + jarFile = [libDir '/log4j1-config-gui/log4j1-config-gui-0.1.1.jar']; + jpath = javaclasspath('-all'); + if ~ismember(jarFile, jpath) + javaaddpath(jarFile); + end + + gui = javaObjectEDT('net.apjanke.log4j1gui.Log4jConfiguratorGui'); + gui.initializeGui(); + frame = gui.showInFrame(); + frame.setVisible(true); + end end end \ No newline at end of file diff --git a/README.md b/README.md index 24f681b6..6bc7307f 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,18 @@ SLF4M ====================== -SLF4M is a simple but flexible logging framework for Matlab, built on top of [SLF4J](https://www.slf4j.org/) and [Apache log4j](https://logging.apache.org/log4j/2.0/). You can -use it to do runtime-configurable logging from your Matlab scripts and programs. -This can be more informative and more manageable than commenting in and out -`fprintf()` statements. +SLF4M is a simple but flexible logging framework for Matlab, built on top of [SLF4J](https://www.slf4j.org/) and [Apache Log4j](https://logging.apache.org/log4j/2.0/). You can use it to do runtime-configurable logging from your Matlab scripts and programs. This can be more informative and more manageable than commenting in and out `fprintf()` statements. + +SLF4M provides: +* Logging functions (a Matlab layer of bindings for SLF4J) +* A `dispstr` API for customizing object display. +* A Log4j configuration GUI The API is simple enough that you can get up and running with it quickly, or even use it casually in scripts, but it's flexible and powerful enough to be useful for larger systems. -SLF4M consists of a Matlab binding layer for SLF4J, along with a new `dispstr` API for customizing object display. (The `dispstr` part is mostly optional; you don't have to learn it in order to use SLF4M logging.) +(The `dispstr` part is mostly optional; you don't have to learn it in order to use SLF4M logging.) + +![SLF4M screenshot showing log output and configuration GUI](doc/SLF4M-configurator-screenshot-scaled.png) ## Usage @@ -63,6 +67,8 @@ Thanks to `dispstr()`, you can also pass Matlab objects to the `%s` conversions. 09:52:29.809 INFO base - Hello, world! 2-by-1 containers.Map ``` +To launch the configuration GUI, run `logm.Log4jConfigurator.showGui`. This GUI lets you set the logging levels and other attributes of the various loggers in your Matlab session. + For more details, see the [User's Guide](doc/UserGuide.md). ## Requirements @@ -71,10 +77,9 @@ A kind of recent version of Matlab. SLF4M was developed and tested on Matlab R20 ## Implementation -SLF4M is a thin layer built on top of SLF4J and log4j. It is compatible with any -other Java or Matlab code that uses SLF4J or log4j. +SLF4M is a thin layer built on top of SLF4J and Log4j. It is compatible with any other Java or Matlab code that uses SLF4J or Log4j. -log4j was chosen as the back-end because that's what ships with Matlab. +Log4j was chosen as the back-end because that's what ships with Matlab. ## License diff --git a/VERSION b/VERSION index 6e8bf73a..0ea3a944 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0 +0.2.0 diff --git a/dev-tools/gen_dummy_log_entries.m b/dev-tools/gen_dummy_log_entries.m new file mode 100644 index 00000000..10712be3 --- /dev/null +++ b/dev-tools/gen_dummy_log_entries.m @@ -0,0 +1,23 @@ +function gen_dummy_log_entries(n) +% Generate a bunch of dummy log entries +% +% Example: +% logm.Log4jConfigurator.setLevels({'foo.bar', 'DEBUG'}); +% gen_dummy_log_entries + +if nargin < 1 || isempty(n); n = 50; end + +logDb = logm.Logger.getLogger('foo.bar.Database'); +logAlgo = logm.Logger.getLogger('foo.bar.Algorithm'); +for i = 1:n + item = sprintf('id%d', round(rand*10000)); + te = rand * 0.15; pause(te); + logDb.debug('Fetched data for %s in %0.03f s', item, te); + te = rand * 0.15; pause(te); + logAlgo.debug('Ran regression on %s in %0.03f s', item, te); + if rand < 0.2 + logAlgo.warn('Found %d missing values in item %s', round(rand*10), item); + end +end + +end \ No newline at end of file diff --git a/doc/SLF4M-configurator-screenshot-scaled.png b/doc/SLF4M-configurator-screenshot-scaled.png new file mode 100644 index 00000000..4fd08241 Binary files /dev/null and b/doc/SLF4M-configurator-screenshot-scaled.png differ diff --git a/doc/Text for File Exchange.md b/doc/Text for File Exchange.md index f79216ac..46bf801b 100644 --- a/doc/Text for File Exchange.md +++ b/doc/Text for File Exchange.md @@ -1,5 +1,9 @@ -SLF4M is a simple but flexible logging framework for Matlab, built on top of SLF4J and Apache log4j. You can -use it to do runtime-configurable logging from your Matlab scripts and programs. This can be more informative and more manageable than commenting in and out `fprintf()` statements. +SLF4M is a simple but flexible logging framework for Matlab, built on top of SLF4J and Apache Log4j. You can use it to do runtime-configurable logging from your Matlab scripts and programs. This can be more informative and more manageable than commenting `fprintf()` statements in and out. + +SLF4M provides: +* Logging functions +* A `dispstr` API for customizing object display. +* A Log4j configuration GUI The API is simple enough that you can get up and running with it quickly, or even use it casually in scripts, but it's flexible and powerful enough to be useful for larger systems. @@ -57,4 +61,3 @@ Author ----------------------------------- SLF4M's home page is the repo on GitHub: https://github.com/apjanke/SLF4M. - diff --git a/doc/UserGuide.md b/doc/UserGuide.md index 99abe6fa..75a13c32 100644 --- a/doc/UserGuide.md +++ b/doc/UserGuide.md @@ -7,7 +7,7 @@ SLF4M provides: * A set of logging functions to log events at various levels * Regular and "`j`" variants for sprintf-style or SLF4J-style formatting -* A `log4j` configurator tool +* A Log4j configurator tool and GUI * `dispstr`, a customizable string-conversion API All the code is in the `+logm` package. I chose a short, readable name because if you're using logging, it'll show up a lot in your code. @@ -39,7 +39,7 @@ Some Matlab objects may not convert to Java objects at all, so you'll get errors Error in loggerCallImpl (line 69) logger.infoj(msg, args{:}); Error in logm.infoj (line 13) - loggerCallImpl('info', msg, varargin, 'j'); + loggerCallImpl('info', msg, varargin, 'j'); ``` To avoid this, use the regular variants. @@ -60,7 +60,7 @@ classdef calling_Logger_directly properties (Constant) log = logm.Logger.getLogger('foo.bar.baz.qux.MyLoggerID'); end - + methods function hello(this) this.log.info('Hello, world!'); @@ -130,22 +130,21 @@ For most Matlab-defined objects, this just results in a "`m-by-n `" o ## Configuration -All the actual logging goes through the `log4j` back end; you can configure it as with any `log4j` installation. See the [`log4j` 1.2 documentation](http://logging.apache.org/log4j/1.2/) for details. (Note: you have to use the old 1.2 series doco, because that's what Matlab currently ships with.) +All the actual logging goes through the Log4j back end; you can configure it as with any Log4j installation. See the [Log4j 1.2 documentation](http://logging.apache.org/log4j/1.2/) for details. (Note: you have to use the old 1.2 series doco, because that's what Matlab currently ships with.) -The `logm.Log4jConfigurator` class provides a convenient Matlab-friendly interface for configuring `log4j` to do basic stuff. It's enough for simple cases. But all the configuration state is passed on the the `log4j` back end; none of it is stored in the Matlab layer. +The `logm.Log4jConfigurator` class provides a convenient Matlab-friendly interface for configuring Log4j to do basic stuff. It's enough for simple cases. But all the configuration state is passed on the the Log4j back end; none of it is stored in the Matlab layer. ## Implementation notes -I chose `log4j` as the back end because it's what ships with Matlab: Matlab includes the `log4j` JARs and the SLF4J-to-`log4j` binding, so it's already active, and it's hard to swap out another back end. (I probably would have chosen `logback` if I had my druthers.) +I chose Log4j as the back end because it's what ships with Matlab: Matlab includes the Log4j JARs and the SLF4J-to-Log4j binding, so it's already active, and it's hard to swap out another back end. (I probably would have chosen `logback` if I had my druthers.) Matlab's internals don't seem to make much use of logging, even though they've bundled it. But some of the third-party JARs they redistributed use it. Turn the levels up to `TRACE` and see what happens. -Aside from the `dispstr` formatting, everything is done purely in terms of the underlying SLF4J interface, so SLF4M is compatible with any other code or tools that use SLF4J or `log4j`. +Aside from the `dispstr` formatting, everything is done purely in terms of the underlying SLF4J interface, so SLF4M is compatible with any other code or tools that use SLF4J or Log4j. -Matlab ships with older versions of SLF4J and `log4j`. (They're slow to update their Java libraries.) Hopefully that's not a problem for people. +Matlab ships with older versions of SLF4J and Log4j. (They're slow to update their Java libraries.) Hopefully that's not a problem for people. -| Matlab Version | SLF4J Version | `log4j` Version | +| Matlab Version | SLF4J Version | Log4j Version | | -------------- | ------------- | --------------- | | R2016b | 1.5.8 | 1.2.15 | | R2017b | 1.5.8 | 1.2.15 | - diff --git a/lib/log4j1-config-gui/README.md b/lib/log4j1-config-gui/README.md new file mode 100644 index 00000000..ac9d4e7e --- /dev/null +++ b/lib/log4j1-config-gui/README.md @@ -0,0 +1,8 @@ +log4j1-config-gui +========================= + +This is the log4j1-config-gui library by Andrew Janke. It's available on GitHub at https://github.com/apjanke/log4j-config-gui. + +## License + +Apache 2.0 License. \ No newline at end of file diff --git a/lib/log4j1-config-gui/log4j1-config-gui-0.1.1.jar b/lib/log4j1-config-gui/log4j1-config-gui-0.1.1.jar new file mode 100644 index 00000000..f5aaa36c Binary files /dev/null and b/lib/log4j1-config-gui/log4j1-config-gui-0.1.1.jar differ