Theory ML_Logger_Examples

✐‹creator "Kevin Kappelmann"›
subsection ‹Examples›
theory ML_Logger_Examples
  imports
    ML_Logger
    Setup_Result_Commands
begin

text ‹First some simple, barebone logging: print some information.›
ML_command― ‹the following two are equivalent›
  val _ = Logger.log Logger.root Logger.INFO @{context} (K "hello root logger")
  val _ = @{log Logger.INFO Logger.root} @{context} (K "hello root logger")

ML_commandval logger = Logger.root
  val _ = @{log} @{context} (K "hello root logger")
  ― ‹@{log}› is equivalent to Logger.log logger Logger.INFO›

text ‹To guarantee the existence of a "logger" in an ML structure, one should use the
HAS_LOGGER› signature.›
MLstructure 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_commandval n = My_Struct.get_n @{context}

text‹We can set up a hierarchy of loggers›
MLval 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") ―‹prints nothings›
declare [[ML_map_context Logger.set_log_level parent1 Logger.DEBUG]]
ML_command@{log Logger.DEBUG parent1} @{context} (K "Hello parent1") ―‹prints message›
ML_commandLogger.ALL ―‹ctrl+click on the value to see all log levels›

text ‹We can set options for all loggers below a given logger. Below, we set the log level for all
loggers below (and including) MLparent1 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_commandLogger.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:›
― ‹ML_command‹@{log Logger.INFO local_logger} @{context} (K "Hello local world")››

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