diff --git a/docs/Project.toml b/docs/Project.toml index 131ec1e..5ad45ab 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,6 +1,7 @@ [deps] +ConcreteStructs = "2569d6c7-a4a2-43d3-a901-331e8e4be471" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" SciMLLogging = "a6db7da4-7206-11f0-1eab-35f2a5dbe1d1" [compat] -Documenter = "1" \ No newline at end of file +Documenter = "1" diff --git a/docs/pages.jl b/docs/pages.jl index d97febf..b289d9e 100644 --- a/docs/pages.jl +++ b/docs/pages.jl @@ -1,9 +1,16 @@ pages = [ "Home" => "index.md", + "Getting Started" => "getting_started.md", "Tutorials" => [ - "User Guide" => "user_tutorial.md", - "Developer Guide" => "developer_tutorial.md", - "Complete Examples" => "tutorial.md" + "User Guide" => "tutorials/user_tutorial.md", + "Developer Guide" => "tutorials/developer_tutorial.md", ], - "API Reference" => "api.md", + "Manual" => [ + "Message Levels" => "manual/message_levels.md", + "Verbosity Specifiers" => "manual/verbosity_specifiers.md", + "Verbosity Presets" => "manual/presets.md", + "@SciMLMessage Macro" => "manual/macro.md", + "Conversion Utilities" => "manual/conversion_utilities.md", + "Logging Backends" => "manual/backends.md" + ] ] \ No newline at end of file diff --git a/docs/src/api.md b/docs/src/api.md deleted file mode 100644 index 7469e65..0000000 --- a/docs/src/api.md +++ /dev/null @@ -1,44 +0,0 @@ -# API Reference - -```@meta -CurrentModule = SciMLLogging -``` - -## Types - -```@docs -AbstractVerbositySpecifier -AbstractMessageLevel -Silent -InfoLevel -WarnLevel -ErrorLevel -CustomLevel -AbstractVerbosityPreset -None -All -Minimal -Standard -Detailed -``` - -## Macros - -```@docs -@SciMLMessage -``` - -## Functions - -```@docs -verbosity_to_int -verbosity_to_bool -SciMLLogger -set_logging_backend -get_logging_backend -``` - -## Index - -```@index -``` \ No newline at end of file diff --git a/docs/src/developer_tutorial.md b/docs/src/developer_tutorial.md deleted file mode 100644 index b1e8813..0000000 --- a/docs/src/developer_tutorial.md +++ /dev/null @@ -1,285 +0,0 @@ -# Developer Tutorial: Adding SciMLLogging to Your Package - -This tutorial is for Julia package developers who want to integrate SciMLLogging.jl into their packages to provide users with fine-grained verbosity control. - -## Overview - -SciMLLogging.jl provides three main components for package developers: - -1. `AbstractVerbositySpecifier{T}` - Base type for creating custom verbosity types -2. `@SciMLMessage` - Macro for emitting conditional log messages -3. Verbosity levels - Predefined log levels (`Silent`, `InfoLevel`, `WarnLevel`, `ErrorLevel`, `CustomLevel(n)`) - -## Step 1: Design Your Verbosity Interface - -First, decide what aspects of your package should be controllable by users. For example, a solver might have: -- Initialization messages -- Iteration progress -- Convergence information -- Warning messages - -## Step 2: Create Your Verbosity Type - -Define a struct that inherits from `AbstractVerbositySpecifier{T}`: - -```julia -using SciMLLogging - -struct MySolverVerbosity{T} <: AbstractVerbositySpecifier{T} - initialization::AbstractMessageLevel - iterations::AbstractMessageLevel - convergence::AbstractMessageLevel - warnings::AbstractMessageLevel - - function MySolverVerbosity{T}(; - initialization = InfoLevel(), - iterations = Silent(), - convergence = InfoLevel(), - warnings = WarnLevel() - ) where T - new{T}(initialization, iterations, convergence, warnings) - end -end -``` - -**Key Design Principles:** -- The type parameter `T` controls whether any logging is enabled or not: `T=true` enables messages, `T=false` disables them -- Each field represents a category of messages your package can emit -- Provide sensible defaults that work for most users -- Use keyword arguments for flexibility - -## Step 3: Add Convenience Constructors - -Make it easy for users to create verbosity instances: - -```julia -# Default enabled verbosity -MySolverVerbosity() = MySolverVerbosity{true}() - -# Boolean constructor -MySolverVerbosity(enabled::Bool) = enabled ? MySolverVerbosity{true}() : MySolverVerbosity{false}() - -# Preset-based constructor (optional) -function MySolverVerbosity(preset::AbstractVerbosityPreset) - if preset isa None - MySolverVerbosity{false}() - elseif preset isa All - MySolverVerbosity{true}( - initialization = InfoLevel(), - iterations = InfoLevel(), - convergence = InfoLevel(), - warnings = WarnLevel() - ) - elseif preset isa Minimal - MySolverVerbosity{true}( - initialization = Silent(), - iterations = Silent(), - convergence = ErrorLevel(), - warnings = ErrorLevel() - ) - else - MySolverVerbosity{true}() # Default - end -end -``` - -## Step 4: Integrate Messages Into Your Code - -Use `@SciMLMessage` throughout your package code: - -```julia -function my_solve(problem, verbose::MySolverVerbosity) - @SciMLMessage("Initializing solver for $(typeof(problem))", verbose, :initialization) - - # Setup code here... - - for iteration in 1:maxiters - # Solver iteration... - - @SciMLMessage(verbose, :iterations) do - "Iteration $iteration: residual = $(compute_residual())" - end - - if converged - @SciMLMessage("Converged after $iteration iterations", verbose, :convergence) - return solution - end - - if should_warn_about_something() - @SciMLMessage("Convergence is slow, consider adjusting parameters", verbose, :warnings) - end - end - - @SciMLMessage("Failed to converge after $maxiters iterations", verbose, :convergence) - return nothing -end -``` - -**Message Types:** -- **String messages**: `@SciMLMessage("Fixed message", verbose, :category)` -- **Function messages**: `@SciMLMessage(verbose, :category) do; "Dynamic message"; end` - -Use function messages when: -- Message generation is expensive -- Message includes computed values -- You want lazy evaluation - -## Step 5: Export Your Verbosity Type - -In your main module file: - -```julia -module MySolver - -using SciMLLogging -import SciMLLogging: AbstractVerbositySpecifier - -# Your verbosity type definition... -include("verbosity.jl") - -# Your solver code... -include("solver.jl") - -# Export the verbosity type -export MySolverVerbosity - -end -``` - -## Step 6: Document for Users - -Provide clear documentation for your users: - -```julia -""" - MySolverVerbosity{T}(; kwargs...) - -Controls verbosity output from MySolver functions. - -# Keyword Arguments -- `initialization = InfoLevel()`: Messages about solver setup -- `iterations = Silent()`: Per-iteration progress messages -- `convergence = InfoLevel()`: Convergence/failure notifications -- `warnings = WarnLevel()`: Warning messages during solving - -# Constructors -- `MySolverVerbosity()`: Default enabled verbosity -- `MySolverVerbosity(false)`: Disabled (zero overhead) -- `MySolverVerbosity(All())`: Enable all message categories -- `MySolverVerbosity(Minimal())`: Only errors and convergence - -# Example -```julia -# Default verbosity -verbose = MySolverVerbosity() - -# Custom verbosity - show everything except iterations -verbose = MySolverVerbosity(iterations = Silent()) - -# Silent mode (no runtime overhead) -verbose = MySolverVerbosity(false) -``` -""" -``` - -## Step 7: Add Tests - -Test your verbosity implementation: - -```julia -using Test -using MySolver -using Logging - -@testset "Verbosity Tests" begin - # Test message emission - verbose = MySolverVerbosity() - - @test_logs (:info, r"Initializing solver") begin - my_solve(test_problem, verbose) - end - - # Test silent mode produces no output - silent = MySolverVerbosity(false) - @test_logs min_level=Logging.Debug begin - my_solve(test_problem, silent) - end -end -``` - -## Best Practices - -### Performance -- Always use the type parameter `T` to control whether logging is enabled or not -- Use function-based messages for expensive computations -- Consider message frequency - don't spam users with too many messages - -### User Experience -- Provide sensible defaults that work for most users -- Use descriptive category names (`:initialization` not `:init`) -- Group related messages into logical categories -- Document what each category controls - -### Message Content -- Include relevant context (iteration numbers, values, etc.) -- Use consistent formatting across your package -- Make messages actionable when possible -- Avoid overly technical jargon in user-facing messages - -### Integration -- Accept verbosity parameters in your main API functions -- Consider making verbosity optional with sensible defaults -- Thread verbosity through your call stack as needed - -## Advanced: Custom Log Levels - -For specialized needs, you can create custom log levels: - -```julia -struct MySolverVerbosity{T} <: AbstractVerbositySpecifier{T} - debug::AbstractMessageLevel - # ... other fields - - function MySolverVerbosity{T}(; - debug = CustomLevel(-1000), # Custom level below Info - # ... other defaults - ) where T - new{T}(debug, ...) - end -end -``` - -## Complete Example - -Here's a complete minimal example: - -```julia -module ExampleSolver - -using SciMLLogging -import SciMLLogging: AbstractVerbositySpecifier - -struct ExampleVerbosity{T} <: AbstractVerbositySpecifier{T} - progress::AbstractMessageLevel - - ExampleVerbosity{T}(progress = InfoLevel()) where T = new{T}(progress) -end - -ExampleVerbosity() = ExampleVerbosity{true}() -ExampleVerbosity(enabled::Bool) = enabled ? ExampleVerbosity{true}() : ExampleVerbosity{false}() - -function solve_example(n::Int, verbose::ExampleVerbosity) - result = 0 - for i in 1:n - result += i - @SciMLMessage("Step $i: sum = $result", verbose, :progress) - end - return result -end - -export ExampleVerbosity, solve_example - -end -``` - -This example shows the minimal structure needed to integrate SciMLLogging into a package. \ No newline at end of file diff --git a/docs/src/getting_started.md b/docs/src/getting_started.md new file mode 100644 index 0000000..9b920bf --- /dev/null +++ b/docs/src/getting_started.md @@ -0,0 +1,121 @@ +# Getting Started with SciMLLogging.jl + +This guide will help you get up and running with SciMLLogging.jl quickly. SciMLLogging provides fine-grained verbosity control for scientific computing workflows in Julia. + +## Basic Concepts + +SciMLLogging.jl is built around three core concepts: + +1. **Message Levels**: Define the importance of messages (`Silent()`, `InfoLevel()`, `WarnLevel()`, `ErrorLevel()`) +2. **Verbosity Specifiers**: Control which categories of messages are shown and at what level +3. **Verbosity Presets**: Predefined settings for common use cases (`None()`, `Minimal()`, `Standard()`, `Detailed()`, `All()`) + +## Quick Start with Presets + +The easiest way to get started is with verbosity presets. Most packages that use SciMLLogging will provide these options: + +```julia +using SciMLLogging + +# Use presets for quick setup (assuming MyPackageVerbosity from a package) +none_verbose = MyPackageVerbosity(None()) # No output (best for production) +minimal_verbose = MyPackageVerbosity(Minimal()) # Only essential messages +standard_verbose = MyPackageVerbosity(Standard()) # Balanced output (recommended) +detailed_verbose = MyPackageVerbosity(Detailed()) # Comprehensive output for debugging +all_verbose = MyPackageVerbosity(All()) # Maximum verbosity + +# Use in your code +result = solve(problem, verbose = standard_verbose) +``` +## Custom Configuration + +For more control, packages typically allow you to configure individual message categories: + +```julia +# Custom configuration +custom_verbose = MyPackageVerbosity( + startup = InfoLevel(), # Show startup messages + progress = Silent(), # Hide progress updates + diagnostics = WarnLevel(), # Show diagnostic warnings + performance = InfoLevel() # Show performance info +) + +result = solve(problem, verbose = custom_verbose) +``` + +**Message Levels:** +- `Silent()`: No output for this category +- `InfoLevel()`: Informational messages +- `WarnLevel()`: Warning messages +- `ErrorLevel()`: Error messages +- `CustomLevel(n)`: Custom level with integer value + +## Logging Backends + +By default, SciMLLogging integrates with Julia's standard logging system, but there is also a backend that uses `Core.println` to emit messages. This is configurable via a [Preferences.jl](https://github.com/JuliaPackaging/Preferences.jl) preference setting. + +### Standard Julia Logging (Default) + +```julia +using Logging + +# Use with Julia's built-in loggers +with_logger(ConsoleLogger(stdout, Logging.Info)) do + # Your code here with verbose output + run_simulation(verbose = standard_verbose) +end +``` +### Simple Console Output + +For simpler output without the logging infrastructure: + +```julia +# Switch to simple println-style output (r) +SciMLLogging.set_logging_backend("core") +``` +This makes the logging compatible with binary building via JuliaC and reduces the overhead. + +### Switching Back + +To switch back to using the logging infrastructure: +```julia +SciMLLogging.set_logging_backend("logging") +``` +## Saving Output to Files + +Combine with Julia's logging to save output: + +```julia +using Logging + +# Save all output to a file +open("computation_log.txt", "w") do io + with_logger(SimpleLogger(io)) do + result = long_computation(verbose = MyPackageVerbosity(Standard())) + end +end + +# Or use SciMLLogger for more control +logger = SciMLLogger( + info_file = "info.log", + warn_file = "warnings.log", + error_file = "errors.log" +) + +with_logger(logger) do + result = computation(verbose = MyPackageVerbosity(Detailed())) +end +``` + +## Next Steps + +- **For end users**: See the [User Tutorial: Configuring Package Verbosity](@ref) for detailed information about controlling package verbosity +- **For package developers**: Check the [Developer Tutorial: Adding SciMLLogging to Your Package](@ref) to learn how to integrate SciMLLogging into your packages + +## Getting Help + +If you encounter issues: +- Check package-specific documentation for their verbosity settings +- Use maximum verbosity (`All()`) to see what's happening +- Consult the Julia logging documentation for advanced output control +- Visit the [SciML Community page](https://sciml.ai/community/) for support \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md index 15c2bdd..96c52c4 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -33,7 +33,7 @@ If you use SciMLLogging.jl in your research, please cite the SciML organization: ## Getting Started -See the [Tutorial](@ref) for a quick introduction to using SciMLLogging.jl. +See [Getting Started with SciMLLogging.jl](@ref) for a quick introduction to using SciMLLogging.jl. ## Contributing diff --git a/docs/src/manual/backends.md b/docs/src/manual/backends.md new file mode 100644 index 0000000..848db1f --- /dev/null +++ b/docs/src/manual/backends.md @@ -0,0 +1,67 @@ +# Logging Backends + +SciMLLogging supports two output backends: Julia's standard logging system (default) and simple console output. + +## Backend Configuration + +```@docs +set_logging_backend +get_logging_backend +``` + +Switch between backends: +```julia +# Switch to simple console output +set_logging_backend("core") + +# Switch back to standard logging (default) +set_logging_backend("logging") +``` + +**Note:** Restart Julia after changing backends. + +## Standard Logging Backend + +Uses Julia's Logging system. Messages integrate with loggers and can be filtered or redirected using standard filters or other packages that integrate with the logging system, e.g. [LoggingExtras.jl](https://github.com/JuliaLogging/LoggingExtras.jl). + +```julia +using Logging + +# Route to console +with_logger(ConsoleLogger(stdout, Logging.Info)) do + result = solve(problem, verbose = SolverVerbosity(Standard())) +end + +# Route to file +open("output.log", "w") do io + with_logger(SimpleLogger(io)) do + result = solve(problem, verbose = SolverVerbosity(Detailed())) + end +end +``` + +## Core Backend + +Uses `Core.println` for direct console output. Simpler but less flexible. This allows messages to emitted, while still being compatible with static compilation and JuliaC. + +## SciMLLogger + +```@docs +SciMLLogger +``` + +Convenient logger that routes messages by level: + +```julia +# Route info to file, warnings/errors to console and file +logger = SciMLLogger( + info_repl = false, + info_file = "info.log", + warn_file = "warnings.log", + error_file = "errors.log" +) + +with_logger(logger) do + result = solve(problem, verbose = SolverVerbosity(Standard())) +end +``` \ No newline at end of file diff --git a/docs/src/manual/conversion_utilities.md b/docs/src/manual/conversion_utilities.md new file mode 100644 index 0000000..d9bf9ef --- /dev/null +++ b/docs/src/manual/conversion_utilities.md @@ -0,0 +1,50 @@ +# Conversion Utilities + +SciMLLogging provides utility functions to convert message levels to common formats used by other packages. + +## Integer Conversion + +```@docs +verbosity_to_int +``` +## Boolean Conversion + +```@docs +verbosity_to_bool +``` + +## Usage Examples + +### Integrating with Integer-Based Packages + +```julia +# Package that expects integer verbosity levels +function external_solver(problem; verbosity_level = 0) + if verbosity_level >= 1 + println("Starting solver...") + end + # ... +end + +# Use with SciMLLogging +verbose_spec = MyPackageVerbosity(Standard()) +level = verbosity_to_int(verbose_spec.progress) +result = external_solver(problem, verbosity_level = level) +``` + +### Integrating with Boolean-Based Packages + +```julia +# Package that expects boolean verbosity +function simple_algorithm(data; verbose = false) + if verbose + println("Processing data...") + end + # ... +end + +# Use with SciMLLogging +verbose_spec = MyPackageVerbosity(Standard()) +is_verbose = verbosity_to_bool(verbose_spec.progress) +result = simple_algorithm(data, verbose = is_verbose) +``` \ No newline at end of file diff --git a/docs/src/manual/macro.md b/docs/src/manual/macro.md new file mode 100644 index 0000000..4705659 --- /dev/null +++ b/docs/src/manual/macro.md @@ -0,0 +1,7 @@ +# The @SciMLMessage Macro + +The `@SciMLMessage` macro is the primary interface for emitting log messages in the SciMLLogging system. It allows you to emit messages that are controlled by verbosity specifiers. + +```@docs +@SciMLMessage +``` \ No newline at end of file diff --git a/docs/src/manual/manual_presets.md b/docs/src/manual/manual_presets.md deleted file mode 100644 index 880b845..0000000 --- a/docs/src/manual/manual_presets.md +++ /dev/null @@ -1,97 +0,0 @@ -# Verbosity Presets - -Presets provide convenient, predefined verbosity configurations that cover common use cases. Instead of manually setting each message category, users can choose from standard presets that automatically configure appropriate message levels. SciMLLogging provides the `AbstractVerbosityPreset` type, along with five subtypes meant to represent different verbosity levels. It is up to the implementer of the `AbstractVerbositySpecifier` to ensure that the verbosity presets are able to be used. - -## Abstract Base Type - -```@docs -AbstractVerbosityPreset -``` - -## Standard Presets - -### None Preset -```@docs -SciMLLogging.None -``` - -The `None` preset is for when you want no output whatsoever. - -### Minimal Preset -```@docs -Minimal -``` - -Use `Minimal` when you want to be informed of important issues but don't need detailed progress information. - -### Standard Preset -```@docs -Standard -``` - -The `Standard` preset provides a balanced configuration suitable for most interactive use cases. - -### Detailed Preset -```@docs -Detailed -``` - -`Detailed` is for development, debugging, or when you need comprehensive information about what your code is doing. - -### All Preset -```@docs -All -``` - -The `All` preset enables maximum verbosity, useful for deep debugging or understanding complex behaviors. - -## Custom Presets - -Packages can define their own preset types for specialized use cases: - -```julia -# Package-specific preset -struct DebuggingPreset <: AbstractVerbosityPreset end - -function MyPackageVerbosity(::DebuggingPreset) - MyPackageVerbosity{true}( - initialization = InfoLevel(), - progress = CustomLevel(-100), # Extra detailed progress - convergence = InfoLevel(), - warnings = WarnLevel(), - errors = ErrorLevel() - ) -end -``` - -## Using Presets - -Presets are typically used as constructor arguments for verbosity specifiers: - -```julia -using SciMLLogging - -# Assuming a package defines MyPackageVerbosity -quiet_config = MyPackageVerbosity(None()) # No output -default_config = MyPackageVerbosity(Standard()) # Balanced output -debug_config = MyPackageVerbosity(All()) # Maximum output -``` - -## How Presets Work - -When you pass a preset to a verbosity specifier constructor, the package implementation maps the preset to appropriate message levels for each category. For example: - -```julia -# This preset usage... -verbosity = SolverVerbosity(Standard()) - -# ...might be equivalent to this manual configuration: -verbosity = SolverVerbosity( - initialization = InfoLevel(), - progress = Silent(), - convergence = InfoLevel(), - diagnostics = WarnLevel(), - performance = InfoLevel() -) -``` - diff --git a/docs/src/manual/message_levels.md b/docs/src/manual/message_levels.md new file mode 100644 index 0000000..cd555ce --- /dev/null +++ b/docs/src/manual/message_levels.md @@ -0,0 +1,84 @@ +# Message Levels + +Message levels in SciMLLogging determine the severity and importance of log messages. Understanding these levels is essential for configuring appropriate verbosity in your applications. + +## Overview + +SciMLLogging provides a hierarchy of message levels that correspond to different types of information: + +```@docs +AbstractMessageLevel +``` + +## Standard Message Levels + +### Silent Level +```@docs +Silent +``` + +The `Silent` level is special - it completely suppresses output for a message. + +### Debug Level +```@docs +DebugLevel +``` + + +### Information Level +```@docs +InfoLevel +``` + +Use `InfoLevel()` for general status updates, progress information, and routine diagnostic messages that users might want to see during normal operation. + +### Warning Level +```@docs +WarnLevel +``` + +`WarnLevel()` should be used for potentially problematic situations that don't prevent execution but may require user attention. + +### Error Level +```@docs +ErrorLevel +``` + +`ErrorLevel()` is reserved for serious problems and failures that indicate something has gone wrong in the computation. + +## Custom Message Levels + +```@docs +CustomLevel +``` + +Custom levels provide flexibility for specialized use cases where the standard Info/Warn/Error hierarchy isn't sufficient. + +## Usage Examples + +```julia +using SciMLLogging + +# Standard levels +info_level = InfoLevel() +warn_level = WarnLevel() +error_level = ErrorLevel() +silent_level = Silent() + +# Custom levels for specialized needs +debug_level = CustomLevel(-1000) # Very low priority +trace_level = CustomLevel(-500) # Low priority debugging +critical_level = CustomLevel(2000) # Higher than standard error level +``` + +## Level Hierarchy + +The message levels have a natural hierarchy that affects logging behavior: + +- `CustomLevel(n)`: Priority determined by integer value `n` +- `ErrorLevel()`: Highest standard priority +- `WarnLevel()`: Medium priority +- `InfoLevel()`: Low priority for general information +- `Silent()`: No output (always suppressed) + +Higher priority messages are more likely to be displayed by logging systems, while lower priority messages may be filtered out depending on the logger configuration. diff --git a/docs/src/manual/presets.md b/docs/src/manual/presets.md new file mode 100644 index 0000000..e00ac79 --- /dev/null +++ b/docs/src/manual/presets.md @@ -0,0 +1,111 @@ +# Verbosity Presets + +Presets provide convenient, predefined verbosity configurations that cover common use cases. Instead of manually setting each message category, users can choose from standard presets that automatically configure appropriate message levels. SciMLLogging provides the `AbstractVerbosityPreset` type, along with five subtypes meant to represent different verbosity levels. It is up to the implementer of the `AbstractVerbositySpecifier` to ensure that the verbosity presets are able to be used. + +## General Idea of Preset Levels + +### Definition of the Preset Levels + +The general idea behind the preset levels is as follows. Each lower level keeps everything enabled from the level above it, and adds the additional information: + +* `None` makes it easy to turn off all printing/logging to ensure 0 overhead and 0 noise. +* `Minimal` turns on only the fatal errors, for example solvers exiting early due to instability, which the user must react to in order to appropriately compute correctly. +* `Standard` turns on non-fatal but critical warnings, for example major performance warnings or deprecations which have been flagged that the user almost certaintly should + respond to. While the program is still running correctly if these are firing, this is the level on by default to signal to the wider userbase issues which should be + handled in order to have "normal" running code. +* `Detailed` turns on additional information as part of the run which can be helpful for in-depth debugging. This includes information about critical quantities at each step + of the calculation, behaviors of the solver that are chosen behind the scenes, and critical numerical issues which are detected. This level should be detailed, but it should + be something that does not necessarily overflow the standard REPL output and should not introduce major performance overhead. +* `All` turns on all logging available in the system. This can include detailed printing that happens in every iteration (i.e. overflowing the terminal output maximum lines), + expensive calculations of critical quantities like condition numbers which can be more expensive than the standard solver but serve as good diagnostics to understand the + numerical quantities better, and other verbose output which could be found interesting to package developers looking for obscure issues. It is generally recommended that + `All` output is redirected to a file as it likely will need to be parsed to be human understandable. + +### Preset Level Examples + +* In the ODE solver, if `dt 0 - - DebugLevel() => 1 - - InfoLevel() => 2 - - WarnLevel() => 3 - - ErrorLevel() => 4 - - CustomLevel(i) => i + ```julia + + using SciMLLogging + + # Standard levels + + verbosity_to_int(Silent()) # Returns 0 + verbosity_to_int(DebugLevel()) # Returns 1 + verbosity_to_int(InfoLevel()) # Returns 2 + verbosity_to_int(WarnLevel()) # Returns 3 + verbosity_to_int(ErrorLevel()) # Returns 4 + + # Custom levels + + verbosity_to_int(CustomLevel(10)) # Returns 10 + verbosity_to_int(CustomLevel(-5)) # Returns -5 + ``` """ function verbosity_to_int(verb::AbstractMessageLevel) if verb isa Silent @@ -147,10 +181,25 @@ end """ `verbosity_to_bool(verb::AbstractMessageLevel)` + Takes a `AbstractMessageLevel` and gives a corresponding boolean value. Verbosity settings that use booleans are relatively common. This provides an interface so that these packages can be used with SciMLVerbosity. If the verbosity is `Silent`, then `false` is returned. Otherwise, `true` is returned. + + ```julia + using SciMLLogging + + # Silent returns false + verbosity_to_bool(Silent()) # Returns false + + # All other levels return true + verbosity_to_bool(InfoLevel()) # Returns true + verbosity_to_bool(WarnLevel()) # Returns true + verbosity_to_bool(ErrorLevel()) # Returns true + verbosity_to_bool(CustomLevel(5)) # Returns true + ``` + """ function verbosity_to_bool(verb::AbstractMessageLevel) if verb isa Silent @@ -160,6 +209,33 @@ function verbosity_to_bool(verb::AbstractMessageLevel) end end +""" + `set_logging_backend(backend::String)`` + +Set the logging backend preference. Valid options are: +- "logging": Use Julia's standard Logging system (default) +- "core": Use Core.println for simple output + +Note: You must restart Julia for this preference change to take effect. +""" +function set_logging_backend(backend::String) + if backend in ["logging", "core"] + @set_preferences!("logging_backend" => backend) + @info("Logging backend set to '$backend'. Restart Julia for changes to take effect!") + else + throw(ArgumentError("Invalid backend '$backend'. Valid options are: 'logging', 'core'")) + end +end + +""" + `get_logging_backend()` + +Get the current logging backend preference. +""" +function get_logging_backend() + return @load_preference("logging_backend", "logging") +end + """ SciMLLogger(; kwargs...) diff --git a/src/verbosity.jl b/src/verbosity.jl index 8cc6e0a..d7dc705 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -80,18 +80,17 @@ Abstract base type for predefined verbosity configurations. Presets provide convenient ways for users to configure verbosity without needing to specify individual message categories. Concrete subtypes include: - `None`: Disable all verbosity -- `All`: Enable all message categories - `Minimal`: Only essential messages - `Standard`: Balanced verbosity for typical use - `Detailed`: Comprehensive verbosity for debugging +- `All`: Enable all message categories """ abstract type AbstractVerbosityPreset end """ None <: AbstractVerbosityPreset -Preset that disables all verbosity. When used, typically results in -a verbosity specifier with `T=false`, providing zero runtime overhead. +Preset that disables all verbosity. All message categories should be set to to `Silent()`. """ struct None <: AbstractVerbosityPreset end @@ -100,7 +99,12 @@ struct None <: AbstractVerbosityPreset end Preset that shows only essential messages. Typically includes only warnings, errors, and critical status information while suppressing routine progress -and debugging messages. +and debugging messages. + +This verbosity preset should set messages related to critical failures and +errors that stop computation to `ErrorLevel`. Messages related to fatal issues +(e.g., convergence problems, solver exiting, etc.) should be set to `WarnLevel()`. +All other messages should be set to `Silent()`. """ struct Minimal <: AbstractVerbosityPreset end @@ -110,6 +114,10 @@ struct Minimal <: AbstractVerbosityPreset end Preset that provides balanced verbosity suitable for typical usage. Shows important progress and status information without overwhelming the user with details. + +This verbosity preset should include the settings from `Minimal`, while also setting +messages such as non-fatal deprecations and critical warnings that require handling +to `InfoLevel`. """ struct Standard <: AbstractVerbosityPreset end @@ -119,6 +127,12 @@ struct Standard <: AbstractVerbosityPreset end Preset that provides comprehensive verbosity for debugging and detailed analysis. Shows most or all available message categories to help with troubleshooting and understanding program behavior. + +This verbosity preset should include the settings from `Standard`, plus progress updates +(e.g., iteration counters, intermediate state), performance metrics +(e.g., timing information, memory usage), detailed diagnostics, and internal state information. +The only messages that should be `Silent()` at this preset are very small details that would +clutter output even during debugging, and information that would be expensive to calculate. """ struct Detailed <: AbstractVerbosityPreset end @@ -127,5 +141,8 @@ struct Detailed <: AbstractVerbosityPreset end Preset that enables maximum verbosity. All message categories are typically set to show informational messages or their appropriate levels. + +This verbosity preset should include the settings from `Detailed`, plus even more details. +At this preset, no messages should be `Silent()`. """ -struct All <: AbstractVerbosityPreset end \ No newline at end of file +struct All <: AbstractVerbosityPreset end