Errors and Logging

By default, libOmexMeta and its dependencies librdf, raptor and sparql log information, errors and warnings to console. In the following, an error is produced because the rdfxml string is being treated as turtle syntax.

Information, warnings and errors are logged to console by libOmexMeta and its dependencies
# Information, warnings and errors are logged to console by default
from pyomexmeta import RDF, Logger, Message

cellml = '''<?xml version=\"1.1\" encoding=\"UTF-8\"?>
            <model xmlns=\"http://www.cellml.org/cellml/1.1#\" xmlns:cmeta=\"http://www.cellml.org/metadata/1.0#\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:bqs=\"http://www.cellml.org/bqs/1.0#\" xmlns:semsim=\"http://bime.uw.edu/semsim/#\" xmlns:dc=\"http://purl.org/dc/terms/\" xmlns:vCard=\"http://www.w3.org/2001/vcard-rdf/3.0#\" name=\"annotation_examples\" cmeta:id=\"annExamples\">
              <component name=\"main\">
                <variable cmeta:id=\"main.Volume\" initial_value=\"100\" name=\"Volume\" units=\"dimensionless\" />
                <variable cmeta:id=\"main.MembraneVoltage\" initial_value=\"-80\" name=\"MembraneVoltage\" units=\"dimensionless\" />
                <variable cmeta:id=\"main.ReactionRate\" initial_value=\"1\" name=\"ReactionRate\" units=\"dimensionless\" />
              </component>
            </model>'''

# oops - did a whoops. Parsing rdfxml as turtle
rdf = RDF.from_string(cellml, syntax="turtle")  # See Python console for logging message

assert len(Logger()) == 1

# get the message as a object
message = Logger()[0]

# print as string
print(message)

# or collect the message content / level as objects
message_string  = message.get_message()
message_level = message.get_level()

print("message_string: ", message_string)
print("message_level: ", message_level)

# now clear the logger
Logger.clear()

assert len(Logger()) == 0

Output
[16:33:35 +01:00]  error : syntax error at '<' 
error: syntax error at '<'
message_string:  syntax error at '<'
message_level:  error

Logging Levels

The default logging level is warn which will cause libOmexMeta to display all logging messages with a precedence level equal to or greater than warn. The logging levels and their precedence levels are:

  • trace = 0

  • debug = 1

  • info = 2

  • warn = 3

  • err = 4

  • critical = 5

  • off = 6

Users can choose their preferred logging level.

How to change the logging level python
# Switching logging levels
from pyomexmeta import RDF, Logger, eLogLevel

cellml = '''<?xml version=\"1.1\" encoding=\"UTF-8\"?>
            <model xmlns=\"http://www.cellml.org/cellml/1.1#\" xmlns:cmeta=\"http://www.cellml.org/metadata/1.0#\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:bqs=\"http://www.cellml.org/bqs/1.0#\" xmlns:semsim=\"http://bime.uw.edu/semsim/#\" xmlns:dc=\"http://purl.org/dc/terms/\" xmlns:vCard=\"http://www.w3.org/2001/vcard-rdf/3.0#\" name=\"annotation_examples\" cmeta:id=\"annExamples\">
              <component name=\"main\">
                <variable cmeta:id=\"main.Volume\" initial_value=\"100\" name=\"Volume\" units=\"dimensionless\" />
                <variable cmeta:id=\"main.MembraneVoltage\" initial_value=\"-80\" name=\"MembraneVoltage\" units=\"dimensionless\" />
                <variable cmeta:id=\"main.ReactionRate\" initial_value=\"1\" name=\"ReactionRate\" units=\"dimensionless\" />
              </component>
            </model>'''

# changing the logging level to critical is one way to hide error messages or messages with lower precedence
Logger.set_level(eLogLevel.critical)
rdf = RDF.from_string(cellml, syntax="ntriples")  # See console - nothing is emitted

# turning the logger ff is another
Logger.set_level(eLogLevel.off)
rdf = RDF.from_string(cellml, syntax="ntriples")  # See console - nothing is emitted
Output

Custom Formatting

Users can choose how the logging messages are formatted. Logging in libOmexMeta is handled by a dependency library called spdlog. Users should see their documentation for a list of valid formatting symbols and their purpose.

Custom formatting for the logger
# custom logging formatter
from pyomexmeta import RDF, Logger, eLogLevel

cellml = '''<?xml version=\"1.1\" encoding=\"UTF-8\"?>
            <model xmlns=\"http://www.cellml.org/cellml/1.1#\" xmlns:cmeta=\"http://www.cellml.org/metadata/1.0#\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:bqs=\"http://www.cellml.org/bqs/1.0#\" xmlns:semsim=\"http://bime.uw.edu/semsim/#\" xmlns:dc=\"http://purl.org/dc/terms/\" xmlns:vCard=\"http://www.w3.org/2001/vcard-rdf/3.0#\" name=\"annotation_examples\" cmeta:id=\"annExamples\">
              <component name=\"main\">
                <variable cmeta:id=\"main.Volume\" initial_value=\"100\" name=\"Volume\" units=\"dimensionless\" />
                <variable cmeta:id=\"main.MembraneVoltage\" initial_value=\"-80\" name=\"MembraneVoltage\" units=\"dimensionless\" />
                <variable cmeta:id=\"main.ReactionRate\" initial_value=\"1\" name=\"ReactionRate\" units=\"dimensionless\" />
              </component>
            </model>'''


# users can customize the formatting of the logger
# See https://github.com/gabime/spdlog/wiki/3.-Custom-formatting#pattern-flags
# for more information on the supported symbols and their meanings
Logger.set_formatter("%^ [%H-%M-%S] - %t - %P - %n - %l : %v %$")
rdf = RDF.from_string(cellml, syntax="rdfxml")
Output
 [16-33-36] - 8008 - 12964 - console - warning : XML parser warning: Unsupported version '1.1' 

Switching to the file logger

Users can optionally redirect logging messages to a file of their choosing. Activating the file logger automatically deactivates the console logger, and reactivating the console logger disables the file logger. Properties such as current logging level and formatting strings are preserved when switching between the file and console loggers.

Switching between file and console logging
# switching to the file logger
from os.path import join, exists, dirname, abspath
from os import remove, getcwd
from pyomexmeta import RDF, Logger

cellml = '''<?xml version=\"1.1\" encoding=\"UTF-8\"?>
            <model xmlns=\"http://www.cellml.org/cellml/1.1#\" xmlns:cmeta=\"http://www.cellml.org/metadata/1.0#\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:bqs=\"http://www.cellml.org/bqs/1.0#\" xmlns:semsim=\"http://bime.uw.edu/semsim/#\" xmlns:dc=\"http://purl.org/dc/terms/\" xmlns:vCard=\"http://www.w3.org/2001/vcard-rdf/3.0#\" name=\"annotation_examples\" cmeta:id=\"annExamples\">
              <component name=\"main\">
                <variable cmeta:id=\"main.Volume\" initial_value=\"100\" name=\"Volume\" units=\"dimensionless\" />
                <variable cmeta:id=\"main.MembraneVoltage\" initial_value=\"-80\" name=\"MembraneVoltage\" units=\"dimensionless\" />
                <variable cmeta:id=\"main.ReactionRate\" initial_value=\"1\" name=\"ReactionRate\" units=\"dimensionless\" />
              </component>
            </model>'''

logger_file = join(getcwd(), "log.log")
print(f"Logger file is: \"{logger_file}\"")

# if already exists, remove
if exists(logger_file):
    remove(logger_file)
assert not exists(logger_file)

# activate the file logger
Logger.file_logger(logger_file)
rdf = RDF.from_string(cellml, syntax="turtle")  # nothing is emitted to console

# ensure logging content has been written to disk
Logger.flush()

# now check logger_file
print(f"Reading logging data from \"{logger_file}\":")
with open(logger_file) as f:
    print(f.read())


# now activate the console logger again
Logger.console_logger()
print("Switching back to the console logger:")
rdf = RDF.from_string(cellml, syntax="turtle")  # and our log message is back
Output
[16:33:36 +01:00]  error : syntax error at '<' 
Logger file is: "D:\libOmexMeta\cmake-build-release\docs\log.log"
Reading logging data from "D:\libOmexMeta\cmake-build-release\docs\log.log":
[16:33:36 +01:00]  error : syntax error at '<' 

Switching back to the console logger:

Using the logger

The logger is also available for use in your own programs.

Using the logger
# using the logger
from pyomexmeta import RDF, Logger, eLogLevel

Logger.set_level(eLogLevel.trace)  # switch to trace log level
Logger.trace("trace message")
Logger.info("info message")
Logger.debug("debug message")
Logger.warn("warn message")
Logger.error("error message")
Logger.critical("critical message")
Output
[16:33:36 +01:00]  trace : trace message 
[16:33:36 +01:00]  info : info message 
[16:33:36 +01:00]  debug : debug message 
[16:33:36 +01:00]  warning : warn message 
[16:33:36 +01:00]  error : error message 
[16:33:36 +01:00]  critical : critical message