Coder Social home page Coder Social logo

octave-slf4o's Introduction

SLF4O

SLF4O is a simple but flexible logging framework for GNU Octave, built on top of SLF4J and Apache Log4j. You can use it to do runtime-configurable logging from your Octave scripts and programs. This can be more informative and more manageable than commenting in and out fprintf() statements.

SLF4O provides:

  • Logging functions (an Octave 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.

(The dispstr part is mostly optional; you don't have to learn it in order to use SLF4O logging.)

SLF4O is an Octave port of the SLF4M package for Matlab.

Usage

Installation

You can install SLF4O using Octave's pkg command:

pkg install https://github.com/apjanke/octave-slf4o/archive/master.zip

Use

In your Octave session:

  • Call pkg load slf4o to load the SLF4O package.

In your Octave program:

  • Call logger.initSLF4O() to initialize SLF4O. This needs to be done before any logging calls are made.

The logging functions are in the +logger package. Call them from within your Octave code. In order of logging level, they are:

  • logger.error()
  • logger.warn()
  • logger.info()
  • logger.debug()
  • logger.trace()

The logging functions take sprintf()-style formatting arguments. You can also pass an MException as the first argument to include the error message and stack trace in the log message.

function helloWorld(x)

if nargin < 1 || isempty(x)
    x = 123.456;
    % These debug() calls will only show up if you set log level to DEBUG
    logger.debug('Got empty x input; defaulted to %f', x);
end
z = x + 42;

logger.info('Answer z=%f', z);
if z > intmax('int32')
    logger.warn('Large value z=%f will overflow int32', z);
end

try
    some_bad_operation(x);
catch err
    logger.error(err, 'Something went wrong in some_bad_operation(x=%f)', x);
end

end

The output looks like this:

>> helloWorld
16:53:18.279 INFO helloWorld() - Answer z=165.456000
16:53:18.291 ERROR helloWorld() - Something went wrong in some_bad_operation(123.456000)
Undefined function 'some_bad_operation' for input arguments of type 'double'.
Error in helloWorld (line 16)
    some_bad_operation(x);

Thanks to dispstr(), you can also pass Octave objects to the %s conversions.

>> m = containers.Map;
>> m('foo') = 42; m('bar') = struct;
>> logger.info('Hello, world! %s', m)
09:52:29.809 INFO  base - Hello, world! 2-by-1 containers.Map

To launch the configuration GUI, run logger.Log4jConfigurator.showGui. This GUI lets you set the logging levels and other attributes of the various loggers in your Octave session.

For more details, see the User's Guide.

Requirements

Octave 4.4.1 or newer, built with Java enabled.

Implementation

SLF4O is a thin layer built on top of SLF4J and Log4j. It is compatible with any other Java or Octave code that uses SLF4J or Log4j.

Log4j was chosen as the back-end because that’s what ships with Matlab, and SLF4O attempts to be maximally compatible with SLF4M.

License

SLF4O is licensed under the GNU General Public License, like GNU Octave itself.

Author

SLF4O is developed by Andrew Janke. Its home page is the repo on GitHub.

octave-slf4o's People

Contributors

apjanke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

octave-slf4o's Issues

isa() does not work to check Java interface implementation

Unlike Matlab's isa(), Octave's isa() does not answer true if you do isa(someJavaObject, 'some.interface.it.Implements'). This means we can't use mustBeA() in some of our stuff.

Report this upstream to Octave.

Possibly implement our own workaround using Java instanceof checks/reflection.

How do I reference Java constants?

I need to do this from M-code:

                rootLogger.setLevel(org.apache.log4j.Level.INFO);

where org.apache.log4j.Level.INFO is referencing the public static final field INFO defined on the Java class org.apache.log4j.Level. How do I do that?

"## -*- texinfo -*-" is ignored if it is the first line in file

Because of this logic for slurping up leading blank lines and copyright blocks:

    my $fh = IO::File->new($mfile, "r")
        or die "Error: Could not open file $mfile: $!\n";

    # Skip leading blank lines
    while (<$fh>) {
        last if /\S/;
    }
    # First block may be copyright statement; skip it
    if (m/\s*[%\#][\s\#%]* Copyright/) {
        print "Skipping Copyright block\n";
        while (<$fh>) {
            last unless /^\s*[%\#]/;
        }
    }

   [...]

   while (<$fh>) {
        my $line_num = $fh->input_line_number();
        [...]
   }

See how that attempt to skip leading blank lines will actually slurp in the "## -- texinfo --" line if it's the first line in the file, and it'll then be discarded?

We're disabling the shadowed-function warning

We define a package-scoped function error() inside the +logger package. Octave mistakenly thinks that this shadows the built-in error() function, and repeatedly issues warnings like this:

warning: function [...]/SLF4O/inst/+logger/error.m shadows a built-in function

So we're just doing warning off Octave:shadowed-function in PKG_ADD. That's a gross hack. See if that can be fixed.

logger.version is broken

logger.version is broken because it relies on the VERSION file, which is outside the inst/ directory and thus not installed as part of the package.

Change its implementation to parse the DESCRIPTION file instead. (That gets installed as part of the package, right?) It should detect DESCRIPTION in its location in both source repo and installed-package cases.

Unify error identifiers

The error() calls variously use the "dispstrlib:", "slf4o:", or "logger:" prefix in the error identifiers. Pick one and use it throughout.

"class not found" warning upon pkg installation

>> pkg install https://github.com/apjanke/octave-slf4o/archive/master.zip
warning: function /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/+logger/error.m shadows a built-infunction
warning: function /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/+logger/error.m shadows a built-infunction
class not found: dispstrlib.Displayable
error: called from
    doc_cache_create>create_cache at line 109 column 18
    gen_doc_cache_in_dir>@<anonymous> at line 143 column 16
    doc_cache_create>gen_doc_cache_in_dir at line 144 column 9
    doc_cache_create at line 55 column 12
    install>generate_lookfor_cache at line 793 column 5
    install at line 223 column 7
    pkg at line 437 column 9
>>

This looks ignorable. Looks like it's because the library is not initialized at package installation time.

The sub-library loading might be too fancy for Octave. Maybe I should just merge the Dispstr stuff into the main inst/ directory and forget about the lib/matlab/dispstr/ approach.

Octave crashes when trying to launch the configurator GUI

When I try to launch the configurator GUI, Octave throws some Java errors and crashes. This happens on both Octave.app 4.4.1 and vanilla Homebrewed Octave 5.2.0 on my macOS 10.14.6 system.

When this happens, the prompt for the legacy Java 6 installer pops up.

Here's what it looks like when run from command line Octave 5.2.0:

octave:5> logger.initSLF4O
warning: function ./+logger/error.m shadows a built-in function
OpenJDK 64-Bit Server VM warning: Archived non-system classes are disabled because the java.system.class.loader property is specified (value = "org.octave.OctClassLoader"). To use archived non-system classes, this property must not be set
octave:6> logger.Log4jConfigurator.showGui
warning: function ./+logger/error.m shadows a built-in function
No Java runtime present, requesting install.
$

(That $ is me being dropped back to the shell after Octave crashed.)

Finish conversion to Octave `pkg` package format

Finish converting this to Octave pkg package format:

  • Add INDEX file
  • Add DESCRIPTION files
  • Add COPYING file
  • Convert the documentation to texinfo
  • Documentation-building scripts to turn those in to QHelp files, and add the PKG_ADD hack to load the QHelp manual
  • Convert the Makefile to Octave package style
  • Probably re-license under GPL

This can be done based on the Tablicious package.

pkg installation not working in Octave.app

I tried installing it under Octave.app, and all I got was this.

>> pkg load slf4o
warning: load_path: /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/lib/matlab/dispstr/dispstr-1.1.1/Mcode-examples: No such file or directory
warning: load_path: /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/lib/matlab/dispstr/dispstr-1.1.1/Mcode-examples: No such file or directory
warning: called from
    installed_packages at line 42 column 19
    load_packages at line 27 column 22
    pkg at line 457 column 7
error: package slf4o is not installed
error: called from
    load_packages at line 41 column 7
    pkg at line 457 column 7
>> logger.initSLF4O
warning: load_path: /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/lib/matlab/dispstr/dispstr-1.1.1/Mcode-examples: No such file or directory
warning: load_path: /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/lib/matlab/dispstr/dispstr-1.1.1/Mcode-examples: No such file or directory
error: 'logger' undefined near line 1 column 1
>> logger.info('hello world!')
warning: load_path: /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/lib/matlab/dispstr/dispstr-1.1.1/Mcode-examples: No such file or directory
warning: load_path: /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/lib/matlab/dispstr/dispstr-1.1.1/Mcode-examples: No such file or directory
error: 'logger' undefined near line 1 column 1
>> path
warning: load_path: /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/lib/matlab/dispstr/dispstr-1.1.1/Mcode-examples: No such file or directory

Octave's search path contains the following directories:

.
/Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/lib/matlab/dispstr/dispstr-1.1.1/Mcode-examples
/Users/janke/Documents/octave
/Applications/Octave-4.4.1.app/Contents/Resources/usr/Cellar/[email protected]/4.4.1/share/octave/site/m
/Applications/Octave-4.4.1.app/Contents/Resources/usr/Cellar/[email protected]/4.4.1/share/octave/site/m/startup

Have Makefile build dist from current workspace state instead of HEAD commit

I think you should be able to build and test your distribution against the pending changes in your working copy before committing those changes. That means that the make dist target should use the current file state, instead of doing a git archive export from the last commit. (Maybe that git archive version could be kept around as a make realdist or make commitdist target.)

Convert code to GNU Octave code style

Right now my source code is mostly in Matlab style. Consider converting it to GNU Octave style, as a courtesy to Octave users who are probably more used to that.

Warning about Mcode-examples upon load

>> pkg load slf4o
warning: load_path: /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/lib/matlab/dispstr/dispstr-1.1.1/Mcode-examples: No such file or directory
warning: load_path: /Users/janke/Library/Application Support/Octave.app/4.4.1/pkg/slf4o-0.1.0-SNAPSHOT/lib/matlab/dispstr/dispstr-1.1.1/Mcode-examples: No such file or directory
warning: called from
    installed_packages at line 42 column 19
    load_packages at line 27 column 22
    pkg at line 457 column 7
error: package slf4o is not installed
error: called from
    load_packages at line 41 column 7
    pkg at line 457 column 7
>>

Hmmmmm...

Get documentation into Octave/QHelp format

  • Convert the documentation in doc/ to texinfo
  • Convert the helptext for all funtions and methods to texinfo
  • Documentation-building scripts to turn those in to QHelp files, and add the PKG_ADD hack to load the QHelp manual
  • Convert the Makefile to Octave package style
  • Fix bugs!

The documentation-building scripts and Makefile can be taken from the Tablicious package.

Follows up #3.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.