Skip to content

Commit

Permalink
Add a configuration GUI
Browse files Browse the repository at this point in the history
This pulls in my `log4j-config-gui` library from
https://github.com/apjanke/log4j-config-gui.
  • Loading branch information
apjanke committed Feb 22, 2018
1 parent fe18953 commit 458ba87
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 42 deletions.
64 changes: 44 additions & 20 deletions Mcode/+logm/Log4jConfigurator.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0
0.2.0
23 changes: 23 additions & 0 deletions dev-tools/gen_dummy_log_entries.m
Original file line number Diff line number Diff line change
@@ -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
Binary file added doc/SLF4M-configurator-screenshot-scaled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 6 additions & 3 deletions doc/Text for File Exchange.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -57,4 +61,3 @@ Author
-----------------------------------

SLF4M's home page is the repo on GitHub: https://github.com/apjanke/SLF4M.

19 changes: 9 additions & 10 deletions doc/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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!');
Expand Down Expand Up @@ -130,22 +130,21 @@ For most Matlab-defined objects, this just results in a "`m-by-n <classname>`" 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 |

8 changes: 8 additions & 0 deletions lib/log4j1-config-gui/README.md
Original file line number Diff line number Diff line change
@@ -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.
Binary file not shown.

0 comments on commit 458ba87

Please sign in to comment.