Theory ML_Logger_Examples
subsection ‹Examples›
theory ML_Logger_Examples
imports
ML_Logger
Setup_Result_Commands
begin
text ‹First some simple, barebone logging: print some information.›
ML_command‹
val _ = Logger.log Logger.root Logger.INFO @{context} (K "hello root logger")
val _ = @{log Logger.INFO Logger.root} @{context} (K "hello root logger")
›
ML_command‹
val logger = Logger.root
val _ = @{log} @{context} (K "hello root logger")
›
text ‹To guarantee the existence of a "logger" in an ML structure, one should use the
‹HAS_LOGGER› signature.›
ML‹
structure My_Struct : sig
include HAS_LOGGER
val get_n : Proof.context -> int
end = struct
val logger = Logger.setup_new_logger Logger.root "My_Struct"
fun get_n ctxt = (@{log} ctxt (K "retrieving n..."); 42)
end
›
ML_command‹val n = My_Struct.get_n @{context}›
text‹We can set up a hierarchy of loggers›
ML‹
val logger = Logger.root
val parent1 = Logger.setup_new_logger Logger.root "Parent1"
val child1 = Logger.setup_new_logger parent1 "Child1"
val child2 = Logger.setup_new_logger parent1 "Child2"
val parent2 = Logger.setup_new_logger Logger.root "Parent2"
›
ML_command‹
(@{log Logger.INFO Logger.root} @{context} (K "Hello root logger");
@{log Logger.INFO parent1} @{context} (K "Hello parent1");
@{log Logger.INFO child1} @{context} (K "Hello child1");
@{log Logger.INFO child2} @{context} (K "Hello child2");
@{log Logger.INFO parent2} @{context} (K "Hello parent2"))
›
text ‹We can use different log levels to show/surpress messages. The log levels are based on
Apache's Log4J 2 🌐‹https://logging.apache.org/log4j/2.x/manual/customloglevels.html›.›
ML_command‹@{log Logger.DEBUG parent1} @{context} (K "Hello parent1")›
declare [[ML_map_context ‹Logger.set_log_level parent1 Logger.DEBUG›]]
ML_command‹@{log Logger.DEBUG parent1} @{context} (K "Hello parent1")›
ML_command‹Logger.ALL›
text ‹We can set options for all loggers below a given logger. Below, we set the log level for all
loggers below (and including) \<^ML>‹parent1› to error, thus disabling warning messages.›
ML_command‹
(@{log Logger.WARN parent1} @{context} (K "Warning from parent1");
@{log Logger.WARN child1} @{context} (K "Warning from child1"))
›
declare [[ML_map_context ‹Logger.set_log_levels parent1 Logger.ERR›]]
ML_command‹
(@{log Logger.WARN parent1} @{context} (K "Warning from parent1");
@{log Logger.WARN child1} @{context} (K "Warning from child1"))
›
declare [[ML_map_context ‹Logger.set_log_levels parent1 Logger.INFO›]]
text ‹We can set message filters.›
declare [[ML_map_context ‹Logger.set_msg_filters Logger.root (match_string "Third")›]]
ML_command‹
(@{log Logger.INFO parent1} @{context} (K "First message");
@{log Logger.INFO child1} @{context} (K "Second message");
@{log Logger.INFO child2} @{context} (K "Third message");
@{log Logger.INFO parent2} @{context} (K "Fourth message"))
›
declare [[ML_map_context ‹Logger.set_msg_filters Logger.root (K true)›]]
text ‹One can also use different output channels (e.g. files) and hide/show some additional
logging information. Ctrl+click on below values and explore.›
ML_command‹Logger.set_output; Logger.set_show_logger; Logging_Antiquotation.show_log_pos›
text ‹To set up (local) loggers outside ML environments,
@{theory ML_Unification.Setup_Result_Commands} contains two commands,
@{command setup_result} and @{command local_setup_result}.›
experiment
begin
local_setup_result local_logger = ‹Logger.new_logger Logger.root "Local"›
ML_command‹@{log Logger.INFO local_logger} @{context} (K "Hello local world")›
end
text ‹‹local_logger› is no longer available. The follow thus does not work:›
text ‹Let us create another logger in the global context.›
setup_result some_logger = ‹Logger.new_logger Logger.root "Some_Logger"›
ML_command‹@{log Logger.INFO some_logger} @{context} (K "Hello world")›
text ‹Let us delete it again.›
declare [[ML_map_context ‹Logger.delete_logger some_logger›]]
text ‹The logger can no longer be found in the logger hierarchy›
ML_command‹@{log Logger.INFO some_logger} @{context} (K "Hello world")›
end