From 6f28a225a35fcbf3efd64aff3be381cef2bdb165 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Sun, 28 Sep 2025 14:59:13 -0400 Subject: [PATCH 01/24] remove extra tutorial --- docs/src/tutorial.md | 273 ------------------------------------------- 1 file changed, 273 deletions(-) delete mode 100644 docs/src/tutorial.md diff --git a/docs/src/tutorial.md b/docs/src/tutorial.md deleted file mode 100644 index 651e047..0000000 --- a/docs/src/tutorial.md +++ /dev/null @@ -1,273 +0,0 @@ -# Tutorial - -This tutorial demonstrates how to use SciMLLogging.jl to add verbosity control to your Julia packages. - -## Basic Concepts - -SciMLLogging.jl provides three main components: - -1. `Verbosity` - A sum type representing different verbosity levels -2. `AbstractVerbositySpecifier{T}` - Base type for custom verbosity types -3. `@SciMLMessage` - Macro for emitting messages based on verbosity settings - -## Creating a Verbosity System - -### Step 1: Create Your Verbosity Type - -Define a type that inherits from `AbstractVerbositySpecifier{T}` with verbosity level fields: - -```@example tutorial1 -using SciMLLogging -using Logging - -struct MyVerbosity{T} <: AbstractVerbositySpecifier{T} - startup::AbstractMessageLevel - progress::AbstractMessageLevel - warnings::AbstractMessageLevel - - function MyVerbosity{T}(; - startup = InfoLevel(), - progress = Silent(), - warnings = WarnLevel() - ) where T - new{T}(startup, progress, warnings) - end -end -nothing # hide -``` - -The type parameter `T` determines whether verbosity is enabled: -- `T = true`: Messages will be processed -- `T = false`: No runtime overhead (compiled away) - -### Step 2: Use the Verbosity System - -```@example tutorial1 -# Create an enabled verbosity instance -verbose = MyVerbosity{true}() - -# Emit messages at different levels -@SciMLMessage("Application starting...", verbose, :startup) -@SciMLMessage("Processing item 1/100", verbose, :progress) -@SciMLMessage("Memory usage high", verbose, :warnings) -nothing # hide -``` - -## Verbosity Levels - -SciMLLogging provides several built-in verbosity levels: - -```@example tutorial2 -using SciMLLogging - -Silent() # No output -InfoLevel() # Informational messages -WarnLevel() # Warning messages -ErrorLevel() # Error messages -CustomLevel(-1000) # Custom log level with integer n -``` - -## Dynamic Messages - -Use functions for lazy evaluation of expensive message generation: - -```@example tutorial3 -using SciMLLogging -using Logging - -# Define the verbosity system (same as before) -struct MyVerbosity2{T} <: AbstractVerbositySpecifier{T} - progress::AbstractMessageLevel - - MyVerbosity2{T}(progress = SciMLLogging.InfoLevel()) where T = new{T}(progress) -end - -verbose = MyVerbosity2{true}() - -# Variables from surrounding scope -iter = 5 -total = 100 - -@SciMLMessage(verbose, :progress) do - percentage = iter / total * 100 - "Progress: $iter/$total ($(round(percentage, digits=1))%)" -end -nothing # hide -``` - -The function is only evaluated if the message will actually be emitted. - -## Disabling Verbosity - -For zero runtime cost when disabled: - -```@example tutorial4 -using SciMLLogging -using Logging - -struct MyVerbosity3{T} <: AbstractVerbositySpecifier{T} - startup::AbstractMessageLevel - - MyVerbosity3{T}(startup = InfoLevel()) where T = new{T}(startup) -end - -# Disabled verbosity -silent = MyVerbosity3{false}() - -# This compiles to nothing - no runtime overhead -@SciMLMessage("This won't be shown", silent, :startup) -println("Message was not shown because verbosity is disabled") -``` - -## Utility Functions - -### Converting to Integer - -For compatibility with packages using integer verbosity levels: - -```@example tutorial5 -using SciMLLogging - -level = verbosity_to_int(WarnLevel()) # Returns 2 -``` - -### Converting to Boolean - -For packages using boolean verbosity flags: - -```@example tutorial6 -using SciMLLogging - -is_verbose = verbosity_to_bool(InfoLevel()) # Returns true -println("SciMLLogging.InfoLevel() converts to: $is_verbose") - -is_verbose = verbosity_to_bool(Silent()) # Returns false -println("SciMLLogging.Silent() converts to: $is_verbose") -``` - -## Custom Logger - -Route messages to different destinations: - -```@example tutorial7 -using SciMLLogging -using Logging - -# Create a logger that sends warnings and errors to files -logger = SciMLLogger( - info_repl = true, - warn_repl = true, - error_repl = true, - warn_file = "warnings.log", - error_file = "errors.log" -) - -# Define a simple verbosity system for testing -struct LoggerTestVerbosity{T} <: AbstractVerbositySpecifier{T} - test::AbstractMessageLevel - - LoggerTestVerbosity{T}(test = WarnLevel()) where T = new{T}(test) -end - -verbose = LoggerTestVerbosity{true}() - -# Use the logger -with_logger(logger) do - @SciMLMessage("This warning is logged", verbose, :test) -end - -# Clean up -isfile("warnings.log") && rm("warnings.log") -isfile("errors.log") && rm("errors.log") -nothing # hide -``` - -## Complete Example - -Here's a complete example showing a solver with verbosity: - -```@example tutorial8 -using SciMLLogging -using Logging -using Random -Random.seed!(123) # For reproducibility - -# Create verbosity type -struct SolverVerbosity{T} <: AbstractVerbositySpecifier{T} - initialization::AbstractMessageLevel - iterations::AbstractMessageLevel - convergence::AbstractMessageLevel - - function SolverVerbosity{T}(; - initialization = InfoLevel(), - iterations = Silent(), - convergence = InfoLevel() - ) where T - new{T}(initialization, iterations, convergence) - end -end - -# Solver function -function my_solver(problem, verbose::SolverVerbosity) - @SciMLMessage("Initializing solver...", verbose, :initialization) - - for i in 1:100 - # Do iteration work... - - @SciMLMessage(verbose, :iterations) do - "Iteration $i: residual = $(round(rand(), digits=4))" - end - - if rand() < 0.05 # Converged (5% chance per iteration for demo) - @SciMLMessage("Converged at iteration $i", verbose, :convergence) - return i - end - end - @SciMLMessage("Failed to converge", verbose, :convergence) - return nothing -end - -# Use the solver with verbosity -println("Running solver with verbosity enabled:") -verbose = SolverVerbosity{true}() -result = my_solver("problem", verbose) -println("Solver returned: $result") - -println("\nRunning solver in silent mode:") -# Or with silent mode -silent = SolverVerbosity{false}() -result = my_solver("problem", silent) # No output -println("Solver returned: $result (no messages shown)") -``` - -## Testing with Verbosity - -When testing code that uses SciMLLogging: - -```@example tutorial9 -using SciMLLogging -using Logging -using Test - -# Define a simple verbosity system for testing -struct TestVerbosity{T} <: AbstractVerbositySpecifier{T} - level::AbstractMessageLevel - - TestVerbosity{T}(level = InfoLevel()) where T = new{T}(level) -end - -@testset "Verbosity Tests" begin - verbose = TestVerbosity{true}() - - # Test that message is logged at correct level - @test_logs (:info, "Test message") begin - @SciMLMessage("Test message", verbose, :level) - end - - # Test that disabled verbosity produces no output - silent = TestVerbosity{false}() - @test_logs min_level=Logging.Debug begin - @SciMLMessage("Should not appear", silent, :level) - end -end -``` \ No newline at end of file From 1280e33bf4c9ddbfe458925e65c316a6afe02867 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Sun, 28 Sep 2025 14:59:24 -0400 Subject: [PATCH 02/24] update user_tutorial --- docs/src/user_tutorial.md | 247 +++++++++++--------------------------- 1 file changed, 68 insertions(+), 179 deletions(-) diff --git a/docs/src/user_tutorial.md b/docs/src/user_tutorial.md index 68afdd8..8213555 100644 --- a/docs/src/user_tutorial.md +++ b/docs/src/user_tutorial.md @@ -1,7 +1,6 @@ # User Tutorial: Configuring Package Verbosity -This tutorial is for end users who want to control the verbosity of packages that use SciMLLogging.jl. If you're using packages from the SciML ecosystem or other packages that support SciMLLogging. - +This tutorial is for end users who want to control the verbosity of packages that use SciMLLogging.jl. Each package will have it's own implementation of the `AbstractVerbositySpecifier` type, which defines the available verbosity options. This guide is meant to be a general guide to the specifics of SciMLLogging.jl, as well as give some examples of how the system is typically implemented. For details on the specific verbosity settings of a package, refer to the package's documentation. ## Understanding Verbosity Specifiers @@ -29,53 +28,11 @@ When `T=false`, all logging is disabled with zero runtime overhead. When `T=true ## Quick Start -Most packages that use SciMLLogging provide simple ways to control their verbosity: - -```julia -using SomePackage # A package that uses SciMLLogging - -# Default verbosity (usually shows important messages) -result = solve_problem(problem) - -# Silent mode (no output) -result = solve_problem(problem, verbose = None()) - -# Verbose mode (show more details) -result = solve_problem(problem, verbose = Detailed()) -``` - -## Understanding Verbosity Levels - -SciMLLogging packages typically categorize their messages into different types: - -- **Silent**: No output at all -- **InfoLevel**: General informational messages -- **WarnLevel**: Warning messages about potential issues -- **ErrorLevel**: Error messages (usually still shown even in quiet modes) - -## Common Usage Patterns - -### Using Verbosity Presets - -Many packages provide preset verbosity levels: - -```julia -using SciMLLogging # To access preset types - -# Minimal output - only critical messages -result = solve(problem, verbose = Minimal()) - -# Maximum output - show everything -result = solve(problem, verbose = All()) - -# No output at all -result = solve(problem, verbose = None()) -``` +Typically, packages that use SciMLLogging will provide a keyword argument such as `verbose` or `verbosity` to some top-level function. This keyword argument will take an `AbstractVerbositySpecifier` implementation, defined in that package, that will control which messages get passed to the logging system, and at what level these messages will be emitted at. ### Example of a typical AbstractVerbositySpecifier -Here's an example of how one might use a packages `AbstractVerbositySpecifier` implementation to control the output. - +Here's an example of how one might use a packages `AbstractVerbositySpecifier` implementation to control the output, using the same `SolverVerbosity` type as above. ```julia # Example: Customizing a solver's verbosity @@ -83,7 +40,7 @@ verbose_settings = SolverVerbosity{true}( initialization = InfoLevel(), # Show startup messages iterations = Silent(), # Don't show each iteration convergence = InfoLevel(), # Show when it converges - warnings = WarnLevel() # Show warnings + error_control = WarnLevel() # Show warnings ) result = solve(problem, verbose = verbose_settings) @@ -93,48 +50,62 @@ result = solve(problem, verbose = verbose_settings) - `SolverVerbosity{true}()` creates an enabled verbosity specifier - `initialization = InfoLevel()` means startup messages will be shown as informational logs - `iterations = Silent()` means iteration progress won't be shown at all -- `convergence = InfoLevel()` means convergence messages will be shown as informational logs -- `warnings = WarnLevel()` means warnings will be shown as warning-level logs +- `convergence = InfoLevel()` means messages related to convergence will be shown as informational logs +- `error_control = WarnLevel()` means message about controlling solver error will be shown as warning-level logs -## Working with Different Output Backends +### Using Verbosity Presets -### Standard Julia Logging +SciMLLogging also provides an abstract `VerbosityPreset` type. The ones provided by `SciMLLogging` are: +- `None()`: Log nothing at all +- `Minimal()`: Preset that shows only essential messages +- `Standard()`: Preset that provides balanced verbosity suitable for typical usage +- `Detailed()`: Preset that provides comprehensive verbosity for debugging and detailed +analysis +- `All()`: Preset that enables maximum verbosity -By default, messages go through Julia's standard logging system. You can control this with the logging level: +These types are meant to set each field of an `AbstractVerbositySpecifier` to a predefined `MessageLevel`. +For example: ```julia -using Logging - -# Only show warnings and errors -with_logger(ConsoleLogger(stderr, Logging.Warn)) do - result = solve_problem(problem, verbose = true) -end - -# Show everything including debug messages -with_logger(ConsoleLogger(stderr, Logging.Debug)) do - result = solve_problem(problem, verbose = true) -end +none_verbose = SolverVerbosity(None()) +# Would be equivalent to +SolverVerbosity{false}( + initialization = Silent(), + iterations = Silent(), + convergence = Silent(), + error_control = Silent()) + + +standard_verbose = SolverVerbosity(Standard()) +# Would be equivalent to +SolverVerbosity{true}( + initialization = Info(), + iterations = Silent(), + convergence = Warn(), + error_control = Info()) ``` -### Simple Console Output - -Some packages may be configured to use simple console output instead of the logging system: - ```julia -using SciMLLogging +using SciMLLogging # To access preset types -# Switch to simple Core.println output (if supported by the package) -SciMLLogging.set_logging_backend("core") +# Minimal output - only critical messages +result = solve(problem, verbose = SolverVerbosity(Minimal())) -# Switch back to standard logging -SciMLLogging.set_logging_backend("logging") +# Maximum output - show everything +result = solve(problem, verbose = SolverVerbosity(All())) + +# No output at all +result = solve(problem, verbose = SolverVerbosity(None())) ``` +## Working with Different Output Backends -Note: You need to restart Julia after changing the backend preference. +### Standard Julia Logging -## Redirecting Output to Files +By default, messages go through Julia's standard logging system. That means that onces a log message is emitted, it can be filtered, sent to other files, and generally processed using the standard Julia logging system. For more details see the [Logging documentation](https://docs.julialang.org/en/v1/stdlib/Logging/). -You can redirect verbose output to files using Julia's logging system: +#### Redirecting Output to Files + +If using the Logging.jl backend, you can redirect messages to files using Julia's logging system: ```julia using Logging @@ -159,13 +130,30 @@ logger = SciMLLogger( ) with_logger(logger) do - result = solve_problem(problem, verbose = true) + result = solve(problem, verbose = SolverVerbosity(Standard())) end ``` +### Simple Console Output + +SciMLLogging can also be configured to use `Core.println` to display messages instead of the full logging system. This is done through a [Preferences.jl](https://github.com/JuliaPackaging/Preferences.jl) setting. + +```julia +using SciMLLogging + +# Switch to simple Core.println output (if supported by the package) +SciMLLogging.set_logging_backend("core") + +# Switch back to standard logging +SciMLLogging.set_logging_backend("logging") +``` + +Note: You need to restart Julia after changing the backend preference in order to use the chosen backend. + + ## Common Scenarios -### Running Experiments Quietly +### Running Experiments with Minimal Output When running many experiments, you might want minimal output: @@ -173,7 +161,7 @@ When running many experiments, you might want minimal output: results = [] for param in parameter_sweep # Only show errors and critical information - result = solve_problem(param, verbose = Minimal()) + result = solve(param, verbose = SolverVerbosity(Minimal())) push!(results, result) end ``` @@ -184,7 +172,7 @@ When troubleshooting problems, enable maximum verbosity: ```julia # Show everything to understand what's happening -result = solve_problem(problematic_case, verbose = All()) +result = solve(problematic_case, verbose = SolverVerbosity(All())) # Or create custom settings to focus on specific aspects debug_verbose = SolverVerbosity{true}( @@ -195,103 +183,4 @@ debug_verbose = SolverVerbosity{true}( ) result = solve_problem(problematic_case, verbose = debug_verbose) -``` - -### Production Runs - -For production environments, you might want only warnings and errors: - -```julia -# Custom settings for production -production_verbose = SolverVerbosity{true}( - initialization = Silent(), # Don't show routine startup - iterations = Silent(), # Don't show progress - convergence = Silent(), # Don't show normal completion - warnings = WarnLevel() # But do show problems -) - -result = solve_problem(problem, verbose = production_verbose) -``` - -## Package-Specific Examples - -### Solver Packages - -Typical solver verbosity options: - -```julia -# Show convergence info but not each iteration -solver_verbose = SolverVerbosity{true}( - initialization = InfoLevel(), - iterations = Silent(), - convergence = InfoLevel(), - warnings = WarnLevel() -) - -solution = solve(problem, solver_verbose) -``` - -### Optimization Packages - -Optimization packages might have different categories: - -```julia -# Focus on optimization progress -opt_verbose = OptimizerVerbosity{true}( - initialization = Silent(), - objective = InfoLevel(), # Show objective function values - constraints = WarnLevel(), # Show constraint violations - convergence = InfoLevel() -) - -result = optimize(objective, constraints, opt_verbose) -``` - -## Tips and Best Practices - -### Finding Available Options - -To see what verbosity options a package provides: - -```julia -# Check the documentation -?SolverVerbosity - -# Look at the default constructor -SolverVerbosity() - -# Many packages document their verbosity categories -``` - -### Testing Your Settings - -Before long runs, test your verbosity settings on a small example: - -```julia -# Test with a quick example first -test_result = solve_problem(small_test_case, verbose_settings) - -# Then use the same settings for the full problem -result = solve_problem(full_problem, verbose_settings) -``` - -### Performance Considerations - -- Using `verbose = false` or `None()` typically has zero runtime overhead -- Custom verbosity settings have minimal overhead -- File logging might slow down execution if there are many messages - -### Combining with Julia's Built-in Logging - -You can combine package verbosity with Julia's logging filters: - -```julia -using Logging - -# Package shows its messages, but Julia filters to only warnings+ -with_logger(ConsoleLogger(stderr, Logging.Warn)) do - result = solve_problem(problem, verbose = true) -end -``` - -This gives you both package-level control (what messages to generate) and system-level control (what messages to display). \ No newline at end of file +``` \ No newline at end of file From 0cdeb2f426e47732db8d1b1416cb7bbec36bf434 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Sun, 28 Sep 2025 16:11:55 -0400 Subject: [PATCH 03/24] update developer tutorial --- docs/src/developer_tutorial.md | 170 ++++++++++++++++++--------------- 1 file changed, 95 insertions(+), 75 deletions(-) diff --git a/docs/src/developer_tutorial.md b/docs/src/developer_tutorial.md index b1e8813..16197ae 100644 --- a/docs/src/developer_tutorial.md +++ b/docs/src/developer_tutorial.md @@ -4,11 +4,41 @@ This tutorial is for Julia package developers who want to integrate SciMLLogging ## Overview -SciMLLogging.jl provides three main components for package developers: +SciMLLogging.jl provides four 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)`) +3. Log levels - Predefined log levels (`Silent`, `InfoLevel`, `WarnLevel`, `ErrorLevel`, `CustomLevel(n)`) +4. Verbosity preset levels - `None`, `Minimal`, `Standard`, `Detailed`, `All` + +### AbstractVerbositySpecifier + `AbstractVerbositySpecifier{T}` is the base type that package developers implement a subtype of to create custom verbosity type for their packages. + +- Type parameter T: Controls whether logging is enabled + (T=true) or disabled (T=false). When `T = false`, any use of the `SciMLLogging.emit_message` function points to any empty function. When the the type parameter is known at compile time, this allows for the compiler to make certain optimizations that can lead to this system having zero runtime overhead when not in use. +- Message levels: Fields of the `AbstractVerbositySpecifier` represent messages or groups of messages. These fields should be of the type `SciMLLogging.MessageLevel`. Each message level subtype represents a different level at which the message will be logged at. +### @SciMLMessage +```@docs +@SciMLMessage +``` +In order to use the the `@SciMLMessage` macro, simply choose which of the fields of your `AbstractVerbositySpecifier` should control that particular message. Then when the macro is called, the field of the verbosity object corresponding with the `option` argument to the macro is used to control the logging of the message. + +### Log Levels +Possible types for these are: +- `Silent()` : no message is emitted +- `InfoLevel()` : message is emitted as an `Info` log +- `WarnLevel()` : message is emitted as a `Warn` log +- `ErrorLevel()` : message is emitted as an `Error` log +- `CustomLevel(n)` : message is emitted at `LogLevel(n)` + +### Verbosity Presets +SciMLLogging also provides an abstract `VerbosityPreset` type. The ones provided by `SciMLLogging` are: +- `None()`: Log nothing at all +- `Minimal()`: Preset that shows only essential messages +- `Standard()`: Preset that provides balanced verbosity suitable for typical usage +- `Detailed()`: Preset that provides comprehensive verbosity for debugging and detailed +analysis +- `All()`: Preset that enables maximum verbosity ## Step 1: Design Your Verbosity Interface @@ -16,11 +46,11 @@ First, decide what aspects of your package should be controllable by users. For - Initialization messages - Iteration progress - Convergence information -- Warning messages +- Error control information ## Step 2: Create Your Verbosity Type -Define a struct that inherits from `AbstractVerbositySpecifier{T}`: +Define a struct that subtypes `AbstractVerbositySpecifier{T}`: ```julia using SciMLLogging @@ -41,16 +71,9 @@ struct MySolverVerbosity{T} <: AbstractVerbositySpecifier{T} 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: +Make it easy for users to create verbosity instances. Perhaps include a constructor that can take a VerbosityPreset, and use it to set the rest of the fields, and a constructor that takes all keyword arguments: ```julia # Default enabled verbosity @@ -59,6 +82,15 @@ MySolverVerbosity() = MySolverVerbosity{true}() # Boolean constructor MySolverVerbosity(enabled::Bool) = enabled ? MySolverVerbosity{true}() : MySolverVerbosity{false}() +function MySolverVerbosity{T}(; + initialization = InfoLevel(), + iterations = Silent(), + convergence = InfoLevel(), + error_control = WarnLevel() + ) where T + MySolverVerbosity{T}(initialization, iterations, convergence, error_control) + end +end # Preset-based constructor (optional) function MySolverVerbosity(preset::AbstractVerbosityPreset) if preset isa None @@ -68,14 +100,14 @@ function MySolverVerbosity(preset::AbstractVerbosityPreset) initialization = InfoLevel(), iterations = InfoLevel(), convergence = InfoLevel(), - warnings = WarnLevel() + error_control = WarnLevel() ) elseif preset isa Minimal MySolverVerbosity{true}( initialization = Silent(), iterations = Silent(), convergence = ErrorLevel(), - warnings = ErrorLevel() + error_control = ErrorLevel() ) else MySolverVerbosity{true}() # Default @@ -106,7 +138,7 @@ function my_solve(problem, verbose::MySolverVerbosity) end if should_warn_about_something() - @SciMLMessage("Convergence is slow, consider adjusting parameters", verbose, :warnings) + @SciMLMessage("Convergence is slow, consider adjusting parameters", verbose, :error_control) end end @@ -114,39 +146,7 @@ function my_solve(problem, verbose::MySolverVerbosity) 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 +## Step 5: Document for Users Provide clear documentation for your users: @@ -160,29 +160,17 @@ Controls verbosity output from MySolver functions. - `initialization = InfoLevel()`: Messages about solver setup - `iterations = Silent()`: Per-iteration progress messages - `convergence = InfoLevel()`: Convergence/failure notifications -- `warnings = WarnLevel()`: Warning messages during solving +- `error_control = WarnLevel()`: Messages about solver error control # 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 +## Step 6: Add Tests Test your verbosity implementation: @@ -195,7 +183,7 @@ using Logging # Test message emission verbose = MySolverVerbosity() - @test_logs (:info, r"Initializing solver") begin + @test_logs (:info, r"Initializing solver") match_mode=:any begin my_solve(test_problem, verbose) end @@ -209,23 +197,12 @@ 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 @@ -282,4 +259,47 @@ export ExampleVerbosity, solve_example end ``` -This example shows the minimal structure needed to integrate SciMLLogging into a package. \ No newline at end of file +This example shows the minimal structure needed to integrate SciMLLogging into a package. + +## Utility Functions for Integration + +SciMLLogging provides utility functions to help integrate with packages that use different verbosity systems. For example, perhaps the package you're developing depends on a package that has verbosity settings that are set using a Bool or an integer, but you still want to be able to control all of the verbosity through the SciMLLogging interface. + +### `verbosity_to_int()` + +Converts a `MessageLevel` to an integer value. This is useful when interfacing with packages that use integer-based verbosity levels: + +```julia +using SciMLLogging + +# Convert message levels to integers +verbosity_to_int(Silent()) # Returns 0 +verbosity_to_int(InfoLevel()) # Returns 1 +verbosity_to_int(WarnLevel()) # Returns 2 +verbosity_to_int(ErrorLevel()) # Returns 3 +verbosity_to_int(CustomLevel(5)) # Returns 5 + +# Example usage with a package that expects integer verbosity +solver_verbosity = SolverVerbosity(Standard()) +int_level = verbosity_to_int(solver_verbosity.convergence) +external_solve(problem, verbosity = int_level) +``` + +### `verbosity_to_bool()` + +Converts a `MessageLevel` to a boolean value. This is useful for packages that use simple on/off verbosity: + +```julia +# Convert message levels to booleans +verbosity_to_bool(Silent()) # Returns false +verbosity_to_bool(InfoLevel()) # Returns true +verbosity_to_bool(WarnLevel()) # Returns true +verbosity_to_bool(ErrorLevel()) # Returns true + +# Example usage with a package that expects boolean verbosity +solver_verbosity = SolverVerbosity(Minimal()) +should_log = verbosity_to_bool(solver_verbosity.iterations) +external_solve(problem, verbose = should_log) +``` + +These functions make it easier to integrate SciMLLogging with existing packages that have their own verbosity conventions. \ No newline at end of file From 200e8fe989487923fa939e79bb626e2d2e9dd89e Mon Sep 17 00:00:00 2001 From: jClugstor Date: Sun, 28 Sep 2025 16:13:49 -0400 Subject: [PATCH 04/24] fix line --- docs/src/developer_tutorial.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/src/developer_tutorial.md b/docs/src/developer_tutorial.md index 16197ae..0c9786c 100644 --- a/docs/src/developer_tutorial.md +++ b/docs/src/developer_tutorial.md @@ -14,8 +14,7 @@ SciMLLogging.jl provides four main components for package developers: ### AbstractVerbositySpecifier `AbstractVerbositySpecifier{T}` is the base type that package developers implement a subtype of to create custom verbosity type for their packages. -- Type parameter T: Controls whether logging is enabled - (T=true) or disabled (T=false). When `T = false`, any use of the `SciMLLogging.emit_message` function points to any empty function. When the the type parameter is known at compile time, this allows for the compiler to make certain optimizations that can lead to this system having zero runtime overhead when not in use. +- Type parameter T: Controls whether logging is enabled (T=true) or disabled (T=false). When `T = false`, any use of the `SciMLLogging.emit_message` function points to any empty function. When the the type parameter is known at compile time, this allows for the compiler to make certain optimizations that can lead to this system having zero runtime overhead when not in use. - Message levels: Fields of the `AbstractVerbositySpecifier` represent messages or groups of messages. These fields should be of the type `SciMLLogging.MessageLevel`. Each message level subtype represents a different level at which the message will be logged at. ### @SciMLMessage ```@docs From 335c2af0448602540c86936a17a569d819a3ede8 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Sun, 28 Sep 2025 20:49:09 -0400 Subject: [PATCH 05/24] rename VerbosityPreset to AbstractVerbosityPreset --- docs/src/developer_tutorial.md | 116 ++++++++++++++++++++------------- docs/src/user_tutorial.md | 23 +++---- src/utils.jl | 15 +++-- 3 files changed, 94 insertions(+), 60 deletions(-) diff --git a/docs/src/developer_tutorial.md b/docs/src/developer_tutorial.md index 0c9786c..ffde22b 100644 --- a/docs/src/developer_tutorial.md +++ b/docs/src/developer_tutorial.md @@ -6,7 +6,7 @@ This tutorial is for Julia package developers who want to integrate SciMLLogging SciMLLogging.jl provides four main components for package developers: -1. `AbstractVerbositySpecifier{T}` - Base type for creating custom verbosity types +1. `AbstractVerbositySpecifier` - Base type for creating custom verbosity types 2. `@SciMLMessage` - Macro for emitting conditional log messages 3. Log levels - Predefined log levels (`Silent`, `InfoLevel`, `WarnLevel`, `ErrorLevel`, `CustomLevel(n)`) 4. Verbosity preset levels - `None`, `Minimal`, `Standard`, `Detailed`, `All` @@ -53,63 +53,62 @@ Define a struct that subtypes `AbstractVerbositySpecifier{T}`: ```julia using SciMLLogging +using ConcreteStructs: @concrete -struct MySolverVerbosity{T} <: AbstractVerbositySpecifier{T} - initialization::AbstractMessageLevel - iterations::AbstractMessageLevel - convergence::AbstractMessageLevel - warnings::AbstractMessageLevel +@concrete struct MySolverVerbosity <: AbstractVerbositySpecifier + initialization + iterations + convergence + warnings +end - function MySolverVerbosity{T}(; +# Constructor with defaults +function MySolverVerbosity(; initialization = InfoLevel(), iterations = Silent(), convergence = InfoLevel(), warnings = WarnLevel() - ) where T - new{T}(initialization, iterations, convergence, warnings) - end +) + MySolverVerbosity(initialization, iterations, convergence, warnings) end ``` + +**Key Design Principles:** +- Use `@concrete` from ConcreteStructs.jl for better performance (eliminates type instabilities) +- 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. Perhaps include a constructor that can take a VerbosityPreset, and use it to set the rest of the fields, and a constructor that takes all keyword arguments: ```julia -# Default enabled verbosity -MySolverVerbosity() = MySolverVerbosity{true}() - -# Boolean constructor -MySolverVerbosity(enabled::Bool) = enabled ? MySolverVerbosity{true}() : MySolverVerbosity{false}() - -function MySolverVerbosity{T}(; - initialization = InfoLevel(), - iterations = Silent(), - convergence = InfoLevel(), - error_control = WarnLevel() - ) where T - MySolverVerbosity{T}(initialization, iterations, convergence, error_control) - end -end # Preset-based constructor (optional) function MySolverVerbosity(preset::AbstractVerbosityPreset) if preset isa None - MySolverVerbosity{false}() + MySolverVerbosity( + initialization = Silent(), + iterations = Silent(), + convergence = Silent(), + warnings = Silent() + ) elseif preset isa All - MySolverVerbosity{true}( + MySolverVerbosity( initialization = InfoLevel(), iterations = InfoLevel(), convergence = InfoLevel(), error_control = WarnLevel() ) elseif preset isa Minimal - MySolverVerbosity{true}( + MySolverVerbosity( initialization = Silent(), iterations = Silent(), convergence = ErrorLevel(), error_control = ErrorLevel() ) else - MySolverVerbosity{true}() # Default + MySolverVerbosity() # Default end end ``` @@ -166,6 +165,23 @@ Controls verbosity output from MySolver functions. - `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 +verbose = MySolverVerbosity( + initialization = Silent(), + iterations = Silent(), + convergence = Silent(), + warnings = Silent() +) +``` """ ``` @@ -187,7 +203,12 @@ using Logging end # Test silent mode produces no output - silent = MySolverVerbosity(false) + silent = MySolverVerbosity( + initialization = Silent(), + iterations = Silent(), + convergence = Silent(), + warnings = Silent() + ) @test_logs min_level=Logging.Debug begin my_solve(test_problem, silent) end @@ -196,6 +217,12 @@ end ## Best Practices +### Performance +- Use `@concrete` from ConcreteStructs.jl for better performance +- Use function-based messages for expensive computations +- Set fields to `Silent()` to disable specific message categories with zero overhead +- 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`) @@ -212,16 +239,18 @@ end For specialized needs, you can create custom log levels: ```julia -struct MySolverVerbosity{T} <: AbstractVerbositySpecifier{T} - debug::AbstractMessageLevel +using ConcreteStructs: @concrete + +@concrete struct MySolverVerbosity <: AbstractVerbositySpecifier + debug # ... other fields +end - function MySolverVerbosity{T}(; - debug = CustomLevel(-1000), # Custom level below Info - # ... other defaults - ) where T - new{T}(debug, ...) - end +function MySolverVerbosity(; + debug = CustomLevel(-1000), # Custom level below Info + # ... other defaults +) + MySolverVerbosity(debug, ...) end ``` @@ -233,16 +262,15 @@ Here's a complete minimal example: module ExampleSolver using SciMLLogging +using ConcreteStructs: @concrete import SciMLLogging: AbstractVerbositySpecifier -struct ExampleVerbosity{T} <: AbstractVerbositySpecifier{T} - progress::AbstractMessageLevel - - ExampleVerbosity{T}(progress = InfoLevel()) where T = new{T}(progress) +@concrete struct ExampleVerbosity <: AbstractVerbositySpecifier + progress end -ExampleVerbosity() = ExampleVerbosity{true}() -ExampleVerbosity(enabled::Bool) = enabled ? ExampleVerbosity{true}() : ExampleVerbosity{false}() +# Constructor with default +ExampleVerbosity(; progress = InfoLevel()) = ExampleVerbosity(progress) function solve_example(n::Int, verbose::ExampleVerbosity) result = 0 diff --git a/docs/src/user_tutorial.md b/docs/src/user_tutorial.md index 8213555..f17ceeb 100644 --- a/docs/src/user_tutorial.md +++ b/docs/src/user_tutorial.md @@ -9,22 +9,23 @@ Before diving into usage, let's understand what a VerbositySpecifier looks like ```julia using SciMLLogging +using ConcreteStructs: @concrete # Example VerbositySpecifier from a hypothetical solver package -struct SolverVerbosity{T} <: AbstractVerbositySpecifier{T} - initialization::AbstractMessageLevel # Controls startup messages - iterations::AbstractMessageLevel # Controls per-iteration output - convergence::AbstractMessageLevel # Controls convergence messages - warnings::AbstractMessageLevel # Controls warning messages +@concrete struct SolverVerbosity <: AbstractVerbositySpecifier + initialization # Controls startup messages + iterations # Controls per-iteration output + convergence # Controls convergence messages + warnings # Controls warning messages end ``` **What this means:** -- **`T` parameter**: Controls whether logging is enabled (`T=true`) or disabled (`T=false`) - **Each field**: Represents a category of messages the package can emit -- **AbstractMessageLevel values**: Can be `Silent()`, `InfoLevel()`, `WarnLevel()`, `ErrorLevel()`, or `CustomLevel(n)` for custom levels +- **Field values**: Can be `Silent()`, `InfoLevel()`, `WarnLevel()`, `ErrorLevel()`, or `CustomLevel(n)` for custom levels +- **`@concrete`**: Used for better performance by eliminating type instabilities -When `T=false`, all logging is disabled with zero runtime overhead. When `T=true`, each category can be individually controlled. +Each category can be individually controlled by setting the field to the appropriate message level. ## Quick Start @@ -36,7 +37,7 @@ Here's an example of how one might use a packages `AbstractVerbositySpecifier` i ```julia # Example: Customizing a solver's verbosity -verbose_settings = SolverVerbosity{true}( +verbose_settings = SolverVerbosity( initialization = InfoLevel(), # Show startup messages iterations = Silent(), # Don't show each iteration convergence = InfoLevel(), # Show when it converges @@ -47,7 +48,7 @@ result = solve(problem, verbose = verbose_settings) ``` **Explanation of the example above:** -- `SolverVerbosity{true}()` creates an enabled verbosity specifier +- `SolverVerbosity()` creates a verbosity specifier with the given settings - `initialization = InfoLevel()` means startup messages will be shown as informational logs - `iterations = Silent()` means iteration progress won't be shown at all - `convergence = InfoLevel()` means messages related to convergence will be shown as informational logs @@ -175,7 +176,7 @@ When troubleshooting problems, enable maximum verbosity: result = solve(problematic_case, verbose = SolverVerbosity(All())) # Or create custom settings to focus on specific aspects -debug_verbose = SolverVerbosity{true}( +debug_verbose = SolverVerbosity( initialization = InfoLevel(), iterations = InfoLevel(), # Now show iterations for debugging convergence = InfoLevel(), diff --git a/src/utils.jl b/src/utils.jl index 3c23c35..2c394b4 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -3,8 +3,9 @@ const LOGGING_BACKEND = @load_preference("logging_backend", "logging") """ -AbstractVerbositySpecifier{T} - Base for types which specify which log messages are emitted at what level. + `AbstractVerbositySpecifier` + +Base for types which specify which log messages are emitted at what level. """ abstract type AbstractVerbositySpecifier end @@ -59,6 +60,8 @@ end """ + `@SciMLMessage(message, verbosity, option)` + A macro that emits a log message based on the log level specified in the `option` of the `AbstractVerbositySpecifier` supplied. `f_or_message` may be a message String, or a 0-argument function that returns a String. @@ -104,6 +107,7 @@ end """ `verbosity_to_int(verb::AbstractMessageLevel)` + Takes a `AbstractMessageLevel` and gives a corresponding integer value. Verbosity settings that use integers or enums that hold integers are relatively common. This provides an interface so that these packages can be used with SciMLVerbosity. Each of the basic verbosity levels @@ -133,6 +137,7 @@ 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. @@ -147,7 +152,7 @@ function verbosity_to_bool(verb::AbstractMessageLevel) end """ - set_logging_backend(backend::String) + `set_logging_backend(backend::String)`` Set the logging backend preference. Valid options are: - "logging": Use Julia's standard Logging system (default) @@ -165,7 +170,7 @@ function set_logging_backend(backend::String) end """ - get_logging_backend() -> String + `get_logging_backend()` Get the current logging backend preference. """ @@ -174,7 +179,7 @@ function get_logging_backend() end """ - SciMLLogger(; kwargs...) + `SciMLLogger(; kwargs...)` Create a logger that routes messages to REPL and/or files based on log level. From b202d6b7bab141db3e32eea91e9bd9f3cdff6c77 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Mon, 29 Sep 2025 16:51:57 -0400 Subject: [PATCH 06/24] add manual pages --- docs/src/manual/manual_backends.md | 67 +++++++++++++++ .../src/manual/manual_conversion_utilities.md | 82 +++++++++++++++++++ docs/src/manual/manual_macro.md | 70 ++++++++++++++++ docs/src/manual/manual_message_levels.md | 78 ++++++++++++++++++ docs/src/manual/manual_presets.md | 2 +- .../src/manual/manual_verbosity_specifiers.md | 74 +++++++++++++++++ 6 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 docs/src/manual/manual_backends.md create mode 100644 docs/src/manual/manual_conversion_utilities.md create mode 100644 docs/src/manual/manual_macro.md create mode 100644 docs/src/manual/manual_message_levels.md create mode 100644 docs/src/manual/manual_verbosity_specifiers.md diff --git a/docs/src/manual/manual_backends.md b/docs/src/manual/manual_backends.md new file mode 100644 index 0000000..ce8c1ea --- /dev/null +++ b/docs/src/manual/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. + +## 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/manual_conversion_utilities.md b/docs/src/manual/manual_conversion_utilities.md new file mode 100644 index 0000000..96086d9 --- /dev/null +++ b/docs/src/manual/manual_conversion_utilities.md @@ -0,0 +1,82 @@ +# Conversion Utilities + +SciMLLogging provides utility functions to convert message levels to common formats used by other packages. + +## Integer Conversion + +```@docs +verbosity_to_int +``` + +Convert message levels to integers for packages that use numeric verbosity levels: + +```julia +using SciMLLogging + +# Standard levels +verbosity_to_int(Silent()) # Returns 0 +verbosity_to_int(InfoLevel()) # Returns 1 +verbosity_to_int(WarnLevel()) # Returns 2 +verbosity_to_int(ErrorLevel()) # Returns 3 + +# Custom levels +verbosity_to_int(CustomLevel(10)) # Returns 10 +verbosity_to_int(CustomLevel(-5)) # Returns -5 +``` + +## Boolean Conversion + +```@docs +verbosity_to_bool +``` + +Convert message levels to booleans for packages that use simple on/off verbosity: + +```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 +``` + +## 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/manual_macro.md b/docs/src/manual/manual_macro.md new file mode 100644 index 0000000..65b2f24 --- /dev/null +++ b/docs/src/manual/manual_macro.md @@ -0,0 +1,70 @@ +# 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. + +## Basic Usage + +```@docs +@SciMLMessage +``` + +## Simple String Messages + +The most basic usage emits a string message: + +```julia +@SciMLMessage("Starting computation", verbosity, :initialization) +@SciMLMessage("Iteration complete", verbosity, :progress) +@SciMLMessage("Convergence achieved", verbosity, :convergence) +``` + +## Function-Based Messages + +For expensive-to-compute messages, use a function to enable lazy evaluation: + +```julia +x = 10 +y = 20 + +@SciMLMessage(verbosity, :debug) do + z = expensive_calculation(x, y) + "Result: $z" +end +``` + +The function is only called if the message category is not `Silent()`, avoiding unnecessary computation. + +## Integration with Verbosity Specifiers + +The macro works with any `AbstractVerbositySpecifier` implementation: + +```julia +# Package defines verbosity specifier +@concrete struct SolverVerbosity <: AbstractVerbositySpecifier + initialization + progress + convergence + diagnostics + performance +end + +# Usage in package code +function solve_problem(problem; verbose = SolverVerbosity(Standard())) + @SciMLMessage("Initializing solver", verbose, :initialization) + + # ... solver setup ... + + for iteration in 1:max_iterations + @SciMLMessage("Iteration $iteration", verbose, :progress) + + # ... iteration work ... + + if converged + @SciMLMessage("Converged after $iteration iterations", verbose, :convergence) + break + end + end + + return result +end +``` \ No newline at end of file diff --git a/docs/src/manual/manual_message_levels.md b/docs/src/manual/manual_message_levels.md new file mode 100644 index 0000000..7b1b82e --- /dev/null +++ b/docs/src/manual/manual_message_levels.md @@ -0,0 +1,78 @@ +# 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. + +### 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. \ No newline at end of file diff --git a/docs/src/manual/manual_presets.md b/docs/src/manual/manual_presets.md index 880b845..c6dbd2b 100644 --- a/docs/src/manual/manual_presets.md +++ b/docs/src/manual/manual_presets.md @@ -12,7 +12,7 @@ AbstractVerbosityPreset ### None Preset ```@docs -SciMLLogging.None +None ``` The `None` preset is for when you want no output whatsoever. diff --git a/docs/src/manual/manual_verbosity_specifiers.md b/docs/src/manual/manual_verbosity_specifiers.md new file mode 100644 index 0000000..04d2c02 --- /dev/null +++ b/docs/src/manual/manual_verbosity_specifiers.md @@ -0,0 +1,74 @@ +# Verbosity Specifiers + +Verbosity specifiers are the core mechanism for controlling which messages are emitted and at what level. They provide fine-grained control over different categories of output in your applications. These are not provided by the SciMLLogging package, but instead must be implemented by a package wishing to use the SciMLLogging interface. + +## Abstract Base Type + +```@docs +AbstractVerbositySpecifier +``` + +## Creating Verbosity Specifiers + +Package authors typically define their own verbosity specifier types by subtyping `AbstractVerbositySpecifier`. Each field in the struct represents a different category of messages that can be controlled independently. + +### Example Implementation + +```julia +using SciMLLogging +using ConcreteStructs: @concrete + +@concrete struct MyPackageVerbosity <: AbstractVerbositySpecifier + initialization # Controls startup and setup messages + progress # Controls progress and iteration updates + convergence # Controls convergence-related messages + diagnostics # Controls diagnostic messages + performance # Controls performance-related messages +end +``` + +### Using the `@concrete` Macro + +The `@concrete` macro from ConcreteStructs.jl is recommended for performance reasons: + +- **Type stability**: Eliminates type instabilities that can hurt performance +- **Compile-time optimization**: Allows the compiler to generate more efficient code +- **Zero-cost abstraction**: Disabled verbosity ideally incurs no runtime + +## Configuring Message Categories + +Each field in a verbosity specifier can be set to any `AbstractMessageLevel`: + +```julia +# Create a custom configuration +custom_verbosity = MyPackageVerbosity( + initialization = InfoLevel(), # Show startup information + progress = Silent(), # Hide progress updates + convergence = InfoLevel(), # Show convergence status + diagnostics = WarnLevel(), # Show diagnostic messages + performance = InfoLevel() # Show performance info +) +``` + +## Integration with Packages + +Package authors should provide verbosity arguments in their main functions: + +```julia +function solve_problem(problem; verbose = MyPackageVerbosity(Standard()), kwargs...) + @SciMLMessage("Starting computation", verbose, :initialization) + + for i in 1:max_iterations + @SciMLMessage("Iteration $i", verbose, :progress) + + # ... computation ... + + if converged + @SciMLMessage("Converged after $i iterations", verbose, :convergence) + break + end + end + + return result +end +``` \ No newline at end of file From 0df9317826ea7d0046deea62eb9703b7838fc4b6 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Mon, 29 Sep 2025 16:52:27 -0400 Subject: [PATCH 07/24] remove api.md, move tutorials --- docs/src/api.md | 44 --- docs/src/developer_tutorial.md | 332 ----------------------- docs/src/tutorials/developer_tutorial.md | 5 +- docs/src/tutorials/user_tutorial.md | 153 +++++++++++ docs/src/user_tutorial.md | 187 ------------- 5 files changed, 157 insertions(+), 564 deletions(-) delete mode 100644 docs/src/api.md delete mode 100644 docs/src/developer_tutorial.md create mode 100644 docs/src/tutorials/user_tutorial.md delete mode 100644 docs/src/user_tutorial.md 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 ffde22b..0000000 --- a/docs/src/developer_tutorial.md +++ /dev/null @@ -1,332 +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 four main components for package developers: - -1. `AbstractVerbositySpecifier` - Base type for creating custom verbosity types -2. `@SciMLMessage` - Macro for emitting conditional log messages -3. Log levels - Predefined log levels (`Silent`, `InfoLevel`, `WarnLevel`, `ErrorLevel`, `CustomLevel(n)`) -4. Verbosity preset levels - `None`, `Minimal`, `Standard`, `Detailed`, `All` - -### AbstractVerbositySpecifier - `AbstractVerbositySpecifier{T}` is the base type that package developers implement a subtype of to create custom verbosity type for their packages. - -- Type parameter T: Controls whether logging is enabled (T=true) or disabled (T=false). When `T = false`, any use of the `SciMLLogging.emit_message` function points to any empty function. When the the type parameter is known at compile time, this allows for the compiler to make certain optimizations that can lead to this system having zero runtime overhead when not in use. -- Message levels: Fields of the `AbstractVerbositySpecifier` represent messages or groups of messages. These fields should be of the type `SciMLLogging.MessageLevel`. Each message level subtype represents a different level at which the message will be logged at. -### @SciMLMessage -```@docs -@SciMLMessage -``` -In order to use the the `@SciMLMessage` macro, simply choose which of the fields of your `AbstractVerbositySpecifier` should control that particular message. Then when the macro is called, the field of the verbosity object corresponding with the `option` argument to the macro is used to control the logging of the message. - -### Log Levels -Possible types for these are: -- `Silent()` : no message is emitted -- `InfoLevel()` : message is emitted as an `Info` log -- `WarnLevel()` : message is emitted as a `Warn` log -- `ErrorLevel()` : message is emitted as an `Error` log -- `CustomLevel(n)` : message is emitted at `LogLevel(n)` - -### Verbosity Presets -SciMLLogging also provides an abstract `VerbosityPreset` type. The ones provided by `SciMLLogging` are: -- `None()`: Log nothing at all -- `Minimal()`: Preset that shows only essential messages -- `Standard()`: Preset that provides balanced verbosity suitable for typical usage -- `Detailed()`: Preset that provides comprehensive verbosity for debugging and detailed -analysis -- `All()`: Preset that enables maximum verbosity - -## 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 -- Error control information - -## Step 2: Create Your Verbosity Type - -Define a struct that subtypes `AbstractVerbositySpecifier{T}`: - -```julia -using SciMLLogging -using ConcreteStructs: @concrete - -@concrete struct MySolverVerbosity <: AbstractVerbositySpecifier - initialization - iterations - convergence - warnings -end - -# Constructor with defaults -function MySolverVerbosity(; - initialization = InfoLevel(), - iterations = Silent(), - convergence = InfoLevel(), - warnings = WarnLevel() -) - MySolverVerbosity(initialization, iterations, convergence, warnings) -end -``` - -**Key Design Principles:** -- Use `@concrete` from ConcreteStructs.jl for better performance (eliminates type instabilities) -- 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. Perhaps include a constructor that can take a VerbosityPreset, and use it to set the rest of the fields, and a constructor that takes all keyword arguments: - -```julia -# Preset-based constructor (optional) -function MySolverVerbosity(preset::AbstractVerbosityPreset) - if preset isa None - MySolverVerbosity( - initialization = Silent(), - iterations = Silent(), - convergence = Silent(), - warnings = Silent() - ) - elseif preset isa All - MySolverVerbosity( - initialization = InfoLevel(), - iterations = InfoLevel(), - convergence = InfoLevel(), - error_control = WarnLevel() - ) - elseif preset isa Minimal - MySolverVerbosity( - initialization = Silent(), - iterations = Silent(), - convergence = ErrorLevel(), - error_control = ErrorLevel() - ) - else - MySolverVerbosity() # 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, :error_control) - end - end - - @SciMLMessage("Failed to converge after $maxiters iterations", verbose, :convergence) - return nothing -end -``` -## Step 5: 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 -- `error_control = WarnLevel()`: Messages about solver error control - -# 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 -verbose = MySolverVerbosity( - initialization = Silent(), - iterations = Silent(), - convergence = Silent(), - warnings = Silent() -) -``` -""" -``` - -## Step 6: 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") match_mode=:any begin - my_solve(test_problem, verbose) - end - - # Test silent mode produces no output - silent = MySolverVerbosity( - initialization = Silent(), - iterations = Silent(), - convergence = Silent(), - warnings = Silent() - ) - @test_logs min_level=Logging.Debug begin - my_solve(test_problem, silent) - end -end -``` - -## Best Practices - -### Performance -- Use `@concrete` from ConcreteStructs.jl for better performance -- Use function-based messages for expensive computations -- Set fields to `Silent()` to disable specific message categories with zero overhead -- 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 - -### 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 -using ConcreteStructs: @concrete - -@concrete struct MySolverVerbosity <: AbstractVerbositySpecifier - debug - # ... other fields -end - -function MySolverVerbosity(; - debug = CustomLevel(-1000), # Custom level below Info - # ... other defaults -) - MySolverVerbosity(debug, ...) -end -``` - -## Complete Example - -Here's a complete minimal example: - -```julia -module ExampleSolver - -using SciMLLogging -using ConcreteStructs: @concrete -import SciMLLogging: AbstractVerbositySpecifier - -@concrete struct ExampleVerbosity <: AbstractVerbositySpecifier - progress -end - -# Constructor with default -ExampleVerbosity(; progress = InfoLevel()) = ExampleVerbosity(progress) - -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. - -## Utility Functions for Integration - -SciMLLogging provides utility functions to help integrate with packages that use different verbosity systems. For example, perhaps the package you're developing depends on a package that has verbosity settings that are set using a Bool or an integer, but you still want to be able to control all of the verbosity through the SciMLLogging interface. - -### `verbosity_to_int()` - -Converts a `MessageLevel` to an integer value. This is useful when interfacing with packages that use integer-based verbosity levels: - -```julia -using SciMLLogging - -# Convert message levels to integers -verbosity_to_int(Silent()) # Returns 0 -verbosity_to_int(InfoLevel()) # Returns 1 -verbosity_to_int(WarnLevel()) # Returns 2 -verbosity_to_int(ErrorLevel()) # Returns 3 -verbosity_to_int(CustomLevel(5)) # Returns 5 - -# Example usage with a package that expects integer verbosity -solver_verbosity = SolverVerbosity(Standard()) -int_level = verbosity_to_int(solver_verbosity.convergence) -external_solve(problem, verbosity = int_level) -``` - -### `verbosity_to_bool()` - -Converts a `MessageLevel` to a boolean value. This is useful for packages that use simple on/off verbosity: - -```julia -# Convert message levels to booleans -verbosity_to_bool(Silent()) # Returns false -verbosity_to_bool(InfoLevel()) # Returns true -verbosity_to_bool(WarnLevel()) # Returns true -verbosity_to_bool(ErrorLevel()) # Returns true - -# Example usage with a package that expects boolean verbosity -solver_verbosity = SolverVerbosity(Minimal()) -should_log = verbosity_to_bool(solver_verbosity.iterations) -external_solve(problem, verbose = should_log) -``` - -These functions make it easier to integrate SciMLLogging with existing packages that have their own verbosity conventions. \ No newline at end of file diff --git a/docs/src/tutorials/developer_tutorial.md b/docs/src/tutorials/developer_tutorial.md index 11944e9..cac1c9e 100644 --- a/docs/src/tutorials/developer_tutorial.md +++ b/docs/src/tutorials/developer_tutorial.md @@ -14,7 +14,10 @@ SciMLLogging.jl provides four main components for package developers: ### AbstractVerbositySpecifier `AbstractVerbositySpecifier` is the base type that package developers implement a subtype of to create custom verbosity type for their packages. -### @SciMLMessage +### @SciMLMessage +```@docs +@SciMLMessage +``` In order to use the the `@SciMLMessage` macro, simply choose which of the fields of your `AbstractVerbositySpecifier` should control that particular message. Then when the macro is called, the field of the verbosity object corresponding with the `option` argument to the macro is used to control the logging of the message. diff --git a/docs/src/tutorials/user_tutorial.md b/docs/src/tutorials/user_tutorial.md new file mode 100644 index 0000000..1adecae --- /dev/null +++ b/docs/src/tutorials/user_tutorial.md @@ -0,0 +1,153 @@ +# User Tutorial: Configuring Package Verbosity + +This tutorial is for end users who want to control the verbosity of packages that use SciMLLogging.jl. +Each package will have it's own implementation of the `AbstractVerbositySpecifier` type, which defines the available verbosity options. This guide is meant to be a general guide to the specifics of SciMLLogging.jl, as well as give some examples of how the system is typically implemented. For details on the specific verbosity settings of a package, refer to that package's documentation. + +## Quick Start + +Packages that use SciMLLogging typically provide a keyword argument such as `verbose` or `verbosity` to control output. The easiest way to get started is with verbosity presets. + +### Using Verbosity Presets (Recommended) + +Most of the time, you'll want to use one of the built-in presets rather than configuring individual message categories: + +**Available Presets:** +- `None()`: Log nothing at all +- `Minimal()`: Only essential messages and warnings +- `Standard()`: Balanced verbosity suitable for typical usage +- `Detailed()`: Comprehensive verbosity for debugging and analysis +- `All()`: Maximum verbosity + +```julia +using SciMLLogging + +# No output at all - best for production +result = solve(problem, verbose = SolverVerbosity(None())) + +# Minimal output - only critical messages +result = solve(problem, verbose = SolverVerbosity(Minimal())) + +# Standard output - balanced for typical usage (recommended) +result = solve(problem, verbose = SolverVerbosity(Standard())) + +# Detailed output - comprehensive information for debugging +result = solve(problem, verbose = SolverVerbosity(Detailed())) + +# Maximum output - show everything +result = solve(problem, verbose = SolverVerbosity(All())) +``` + +### Custom Verbosity Configuration + +For more control, you can configure individual message categories: + +```julia +# Example: Customizing a solve's verbosity +verbose_settings = SolverVerbosity( + initialization = InfoLevel(), # Show startup messages + iterations = Silent(), # Don't show each iteration + convergence = InfoLevel(), # Show convergence information + error_control = WarnLevel() # Show warnings related to error control of the solver +) + +result = solve(problem, verbose = verbose_settings) +``` + +**Message Levels:** +- `Silent()`: No output for this category +- `InfoLevel()`: Informational messages +- `WarnLevel()`: Warning messages +- `ErrorLevel()`: Error messages +- `CustomLevel(n)`: Custom level with integer value `n` + +## Complete Working Example + +Here's a full example showing how SciMLLogging works in practice, using a simulated "solver": + +```@example +using SciMLLogging +using SciMLLogging: None, Standard, All +using ConcreteStructs: @concrete + +# 1. Define a verbosity specifier (this would typically be done by a package) +@concrete struct SolverVerbosity <: AbstractVerbositySpecifier + initialization + iterations + convergence + linear_solve + warnings +end + +# Likewise the constructors would typically be implemented by a package +function SolverVerbosity(; + initialization = Info(), + iterations = Silent(), + convergence = InfoLevel(), + linear_solve = Silent(), + warnings = WarnLevel() + ) + SolverVerbosity(initialization, iterations, convergence, linear_solve, warnings) +end + +# 2. Implement preset support +function SolverVerbosity(preset::None) + SolverVerbosity(Silent(), Silent(), Silent(), Silent(), Silent()) +end + +function SolverVerbosity(preset::Standard) + SolverVerbosity(InfoLevel(), Silent(), InfoLevel(), Silent(), WarnLevel()) +end + +function SolverVerbosity(preset::All) + SolverVerbosity(InfoLevel(), InfoLevel(), InfoLevel(), InfoLevel(), WarnLevel()) +end + +# 3. Example solver function using SciMLLogging, the specific messages and where the messages are emitted +# would be decided by the package +function example_solver(problem; verbose = SolverVerbosity(Standard()), max_iterations = 10) + @SciMLMessage("Initializing solver for problem of size $(length(problem))", verbose, :initialization) + + # Simulate solver iterations + for i in 1:max_iterations + @SciMLMessage("Iteration $i: residual = $(0.1^i)", verbose, :iterations) + + if i % 3 == 0 + @SciMLMessage("Solving linear system", verbose, :linear_solve) + end + + if 0.1^i < 1e-6 + @SciMLMessage("Converged after $i iterations", verbose, :convergence) + return "Solution found" + end + + if i == 8 + @SciMLMessage("Solver may be slow to converge", verbose, :warnings) + end + end + + @SciMLMessage("Maximum iterations reached", verbose, :warnings) + return "Max iterations" +end + +# 4. Try different verbosity levels +problem = [1.0, 2.0, 3.0] + +println("=== With Standard verbosity ===") +result1 = example_solver(problem, verbose = SolverVerbosity(Standard())) + +println("\n=== With All verbosity ===") +result2 = example_solver(problem, verbose = SolverVerbosity(All())) + +println("\n=== With None verbosity ===") +result3 = example_solver(problem, verbose = SolverVerbosity(None())) + +println("\n=== With custom verbosity ===") +custom_verbose = SolverVerbosity( + initialization = InfoLevel(), + iterations = Silent(), + convergence = InfoLevel(), + linear_solve = InfoLevel(), + warnings = ErrorLevel() # Treat warnings as errors for this run +) +result4 = example_solver(problem, verbose = custom_verbose) +``` diff --git a/docs/src/user_tutorial.md b/docs/src/user_tutorial.md deleted file mode 100644 index f17ceeb..0000000 --- a/docs/src/user_tutorial.md +++ /dev/null @@ -1,187 +0,0 @@ -# User Tutorial: Configuring Package Verbosity - -This tutorial is for end users who want to control the verbosity of packages that use SciMLLogging.jl. -Each package will have it's own implementation of the `AbstractVerbositySpecifier` type, which defines the available verbosity options. This guide is meant to be a general guide to the specifics of SciMLLogging.jl, as well as give some examples of how the system is typically implemented. For details on the specific verbosity settings of a package, refer to the package's documentation. - -## Understanding Verbosity Specifiers - -Before diving into usage, let's understand what a VerbositySpecifier looks like with a simple example. Typically, the `SolverVerbosity` type, would be implemented in a package like so: - -```julia -using SciMLLogging -using ConcreteStructs: @concrete - -# Example VerbositySpecifier from a hypothetical solver package -@concrete struct SolverVerbosity <: AbstractVerbositySpecifier - initialization # Controls startup messages - iterations # Controls per-iteration output - convergence # Controls convergence messages - warnings # Controls warning messages -end -``` - -**What this means:** -- **Each field**: Represents a category of messages the package can emit -- **Field values**: Can be `Silent()`, `InfoLevel()`, `WarnLevel()`, `ErrorLevel()`, or `CustomLevel(n)` for custom levels -- **`@concrete`**: Used for better performance by eliminating type instabilities - -Each category can be individually controlled by setting the field to the appropriate message level. - -## Quick Start - -Typically, packages that use SciMLLogging will provide a keyword argument such as `verbose` or `verbosity` to some top-level function. This keyword argument will take an `AbstractVerbositySpecifier` implementation, defined in that package, that will control which messages get passed to the logging system, and at what level these messages will be emitted at. - -### Example of a typical AbstractVerbositySpecifier - -Here's an example of how one might use a packages `AbstractVerbositySpecifier` implementation to control the output, using the same `SolverVerbosity` type as above. - -```julia -# Example: Customizing a solver's verbosity -verbose_settings = SolverVerbosity( - initialization = InfoLevel(), # Show startup messages - iterations = Silent(), # Don't show each iteration - convergence = InfoLevel(), # Show when it converges - error_control = WarnLevel() # Show warnings -) - -result = solve(problem, verbose = verbose_settings) -``` - -**Explanation of the example above:** -- `SolverVerbosity()` creates a verbosity specifier with the given settings -- `initialization = InfoLevel()` means startup messages will be shown as informational logs -- `iterations = Silent()` means iteration progress won't be shown at all -- `convergence = InfoLevel()` means messages related to convergence will be shown as informational logs -- `error_control = WarnLevel()` means message about controlling solver error will be shown as warning-level logs - -### Using Verbosity Presets - -SciMLLogging also provides an abstract `VerbosityPreset` type. The ones provided by `SciMLLogging` are: -- `None()`: Log nothing at all -- `Minimal()`: Preset that shows only essential messages -- `Standard()`: Preset that provides balanced verbosity suitable for typical usage -- `Detailed()`: Preset that provides comprehensive verbosity for debugging and detailed -analysis -- `All()`: Preset that enables maximum verbosity - - -These types are meant to set each field of an `AbstractVerbositySpecifier` to a predefined `MessageLevel`. -For example: -```julia -none_verbose = SolverVerbosity(None()) -# Would be equivalent to -SolverVerbosity{false}( - initialization = Silent(), - iterations = Silent(), - convergence = Silent(), - error_control = Silent()) - - -standard_verbose = SolverVerbosity(Standard()) -# Would be equivalent to -SolverVerbosity{true}( - initialization = Info(), - iterations = Silent(), - convergence = Warn(), - error_control = Info()) -``` - -```julia -using SciMLLogging # To access preset types - -# Minimal output - only critical messages -result = solve(problem, verbose = SolverVerbosity(Minimal())) - -# Maximum output - show everything -result = solve(problem, verbose = SolverVerbosity(All())) - -# No output at all -result = solve(problem, verbose = SolverVerbosity(None())) -``` -## Working with Different Output Backends - -### Standard Julia Logging - -By default, messages go through Julia's standard logging system. That means that onces a log message is emitted, it can be filtered, sent to other files, and generally processed using the standard Julia logging system. For more details see the [Logging documentation](https://docs.julialang.org/en/v1/stdlib/Logging/). - -#### Redirecting Output to Files - -If using the Logging.jl backend, you can redirect messages to files using Julia's logging system: - -```julia -using Logging - -# Save all output to a file -open("solver_output.log", "w") do io - with_logger(SimpleLogger(io)) do - result = solve_problem(problem, verbose = true) - end -end - -# Or use the built-in SciMLLogger for more control -using SciMLLogging - -logger = SciMLLogger( - info_repl = true, # Show info in REPL - warn_repl = true, # Show warnings in REPL - error_repl = true, # Show errors in REPL - info_file = "info.log", # Save info messages to file - warn_file = "warnings.log", # Save warnings to file - error_file = "errors.log" # Save errors to file -) - -with_logger(logger) do - result = solve(problem, verbose = SolverVerbosity(Standard())) -end -``` - -### Simple Console Output - -SciMLLogging can also be configured to use `Core.println` to display messages instead of the full logging system. This is done through a [Preferences.jl](https://github.com/JuliaPackaging/Preferences.jl) setting. - -```julia -using SciMLLogging - -# Switch to simple Core.println output (if supported by the package) -SciMLLogging.set_logging_backend("core") - -# Switch back to standard logging -SciMLLogging.set_logging_backend("logging") -``` - -Note: You need to restart Julia after changing the backend preference in order to use the chosen backend. - - -## Common Scenarios - -### Running Experiments with Minimal Output - -When running many experiments, you might want minimal output: - -```julia -results = [] -for param in parameter_sweep - # Only show errors and critical information - result = solve(param, verbose = SolverVerbosity(Minimal())) - push!(results, result) -end -``` - -### Debugging Issues - -When troubleshooting problems, enable maximum verbosity: - -```julia -# Show everything to understand what's happening -result = solve(problematic_case, verbose = SolverVerbosity(All())) - -# Or create custom settings to focus on specific aspects -debug_verbose = SolverVerbosity( - initialization = InfoLevel(), - iterations = InfoLevel(), # Now show iterations for debugging - convergence = InfoLevel(), - warnings = WarnLevel() -) - -result = solve_problem(problematic_case, verbose = debug_verbose) -``` \ No newline at end of file From 27fccab38d96aff8ed6332a76f62b8960e7e34d3 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Mon, 29 Sep 2025 16:52:41 -0400 Subject: [PATCH 08/24] add getting_started, update pages --- docs/pages.jl | 11 +++- docs/src/getting_started.md | 122 ++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 docs/src/getting_started.md diff --git a/docs/pages.jl b/docs/pages.jl index d97febf..b931a60 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" ], - "API Reference" => "api.md", + "Manual" => [ + "Message Levels" => "manual/manual_message_levels.md", + "Verbosity Specifiers" => "manual/manual_verbosity_specifiers.md", + "Verbosity Presets" => "manual/manual_presets.md", + "@SciMLMessage Macro" => "manual/manual_macro.md", + "Conversion Utilities" => "manual/manual_conversion_utilities.md", + "Logging Backends" => "manual/manual_backends.md" + ] ] \ 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..e3156f8 --- /dev/null +++ b/docs/src/getting_started.md @@ -0,0 +1,122 @@ +# 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) +``` + +**Available Presets:** +- `None()`: No output at all (zero overhead) +- `Minimal()`: Only essential messages and warnings +- `Standard()`: Balanced verbosity for typical usage +- `Detailed()`: Comprehensive information for debugging +- `All()`: Maximum verbosity + +## 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") +``` + +## 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 Guide](user_tutorial.md) for detailed information about controlling package verbosity +- **For package developers**: Check the [Developer Guide](developer_tutorial.md) 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 From 54ccf1c94c324571d5a07bcdd2e6923a11825950 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Mon, 29 Sep 2025 17:18:46 -0400 Subject: [PATCH 09/24] fix pages --- docs/pages.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages.jl b/docs/pages.jl index b931a60..7dc77d1 100644 --- a/docs/pages.jl +++ b/docs/pages.jl @@ -2,8 +2,8 @@ pages = [ "Home" => "index.md", "Getting Started" => "getting_started.md", "Tutorials" => [ - "User Guide" => "user_tutorial.md", - "Developer Guide" => "developer_tutorial.md", + "User Guide" => "tutorials/user_tutorial.md", + "Developer Guide" => "tutorials/developer_tutorial.md", ], "Manual" => [ "Message Levels" => "manual/manual_message_levels.md", From d554e3495ac46ad383d3b19fa9bb41c84cf192f0 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Mon, 29 Sep 2025 17:30:12 -0400 Subject: [PATCH 10/24] exports, fix up docs --- docs/Project.toml | 3 ++- docs/src/manual/manual_presets.md | 2 +- docs/src/tutorials/developer_tutorial.md | 5 +---- src/SciMLLogging.jl | 1 + 4 files changed, 5 insertions(+), 6 deletions(-) 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/src/manual/manual_presets.md b/docs/src/manual/manual_presets.md index c6dbd2b..880b845 100644 --- a/docs/src/manual/manual_presets.md +++ b/docs/src/manual/manual_presets.md @@ -12,7 +12,7 @@ AbstractVerbosityPreset ### None Preset ```@docs -None +SciMLLogging.None ``` The `None` preset is for when you want no output whatsoever. diff --git a/docs/src/tutorials/developer_tutorial.md b/docs/src/tutorials/developer_tutorial.md index cac1c9e..11944e9 100644 --- a/docs/src/tutorials/developer_tutorial.md +++ b/docs/src/tutorials/developer_tutorial.md @@ -14,10 +14,7 @@ SciMLLogging.jl provides four main components for package developers: ### AbstractVerbositySpecifier `AbstractVerbositySpecifier` is the base type that package developers implement a subtype of to create custom verbosity type for their packages. -### @SciMLMessage -```@docs -@SciMLMessage -``` +### @SciMLMessage In order to use the the `@SciMLMessage` macro, simply choose which of the fields of your `AbstractVerbositySpecifier` should control that particular message. Then when the macro is called, the field of the verbosity object corresponding with the `option` argument to the macro is used to control the logging of the message. diff --git a/src/SciMLLogging.jl b/src/SciMLLogging.jl index 8b11d37..ee9ab9c 100644 --- a/src/SciMLLogging.jl +++ b/src/SciMLLogging.jl @@ -14,5 +14,6 @@ export @SciMLMessage export verbosity_to_int, verbosity_to_bool export SciMLLogger export set_logging_backend, get_logging_backend +export None, Minimal, Standard, Detailed, All end From 16bdfca7241bb15cdc7e703e39e5698adb562bc2 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Mon, 29 Sep 2025 17:37:05 -0400 Subject: [PATCH 11/24] more doc fixes --- docs/src/getting_started.md | 4 ++-- docs/src/index.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/getting_started.md b/docs/src/getting_started.md index e3156f8..8f596bc 100644 --- a/docs/src/getting_started.md +++ b/docs/src/getting_started.md @@ -110,8 +110,8 @@ end ## Next Steps -- **For end users**: See the [User Guide](user_tutorial.md) for detailed information about controlling package verbosity -- **For package developers**: Check the [Developer Guide](developer_tutorial.md) to learn how to integrate SciMLLogging into your packages +- **For end users**: See the [User Guide](tutorial/user_tutorial.md) for detailed information about controlling package verbosity +- **For package developers**: Check the [Developer Guide](tutorial/developer_tutorial.md) to learn how to integrate SciMLLogging into your packages ## Getting Help 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 From 5b5d186300969e3e422b5dc27ad56fdd9dc4fd39 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Mon, 29 Sep 2025 17:43:07 -0400 Subject: [PATCH 12/24] fix local links --- docs/src/getting_started.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/getting_started.md b/docs/src/getting_started.md index 8f596bc..8120080 100644 --- a/docs/src/getting_started.md +++ b/docs/src/getting_started.md @@ -110,8 +110,8 @@ end ## Next Steps -- **For end users**: See the [User Guide](tutorial/user_tutorial.md) for detailed information about controlling package verbosity -- **For package developers**: Check the [Developer Guide](tutorial/developer_tutorial.md) to learn how to integrate SciMLLogging into your packages +- **For end users**: See the [User Guide](@ref) for detailed information about controlling package verbosity +- **For package developers**: Check the [Developer Guide](@ref) to learn how to integrate SciMLLogging into your packages ## Getting Help From fc6397c2a38730f8a571f8501d01fa78c87c9d00 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Mon, 29 Sep 2025 17:47:25 -0400 Subject: [PATCH 13/24] fix crossreferences --- docs/src/getting_started.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/getting_started.md b/docs/src/getting_started.md index 8120080..6187285 100644 --- a/docs/src/getting_started.md +++ b/docs/src/getting_started.md @@ -110,8 +110,8 @@ end ## Next Steps -- **For end users**: See the [User Guide](@ref) for detailed information about controlling package verbosity -- **For package developers**: Check the [Developer Guide](@ref) to learn how to integrate SciMLLogging into your packages +- **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 From d1351a101a90d1f096bb8e3fe7618a5e12c3102a Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 2 Oct 2025 12:08:04 -0400 Subject: [PATCH 14/24] tutorial updates --- docs/src/getting_started.md | 17 +++-- docs/src/manual/manual_backends.md | 2 +- .../src/manual/manual_conversion_utilities.md | 32 -------- docs/src/manual/manual_macro.md | 63 ---------------- src/utils.jl | 74 +++++++++++++++---- 5 files changed, 69 insertions(+), 119 deletions(-) diff --git a/docs/src/getting_started.md b/docs/src/getting_started.md index 6187285..ecf5188 100644 --- a/docs/src/getting_started.md +++ b/docs/src/getting_started.md @@ -27,14 +27,6 @@ all_verbose = MyPackageVerbosity(All()) # Maximum verbosity # Use in your code result = solve(problem, verbose = standard_verbose) ``` - -**Available Presets:** -- `None()`: No output at all (zero overhead) -- `Minimal()`: Only essential messages and warnings -- `Standard()`: Balanced verbosity for typical usage -- `Detailed()`: Comprehensive information for debugging -- `All()`: Maximum verbosity - ## Custom Configuration For more control, packages typically allow you to configure individual message categories: @@ -81,6 +73,15 @@ For simpler output without the logging infrastructure: # 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") +``` +Note that you will need to restart Julia for this to take affect. ## Saving Output to Files diff --git a/docs/src/manual/manual_backends.md b/docs/src/manual/manual_backends.md index ce8c1ea..848db1f 100644 --- a/docs/src/manual/manual_backends.md +++ b/docs/src/manual/manual_backends.md @@ -42,7 +42,7 @@ end ## Core Backend -Uses `Core.println` for direct console output. Simpler but less flexible. +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 diff --git a/docs/src/manual/manual_conversion_utilities.md b/docs/src/manual/manual_conversion_utilities.md index 96086d9..d9bf9ef 100644 --- a/docs/src/manual/manual_conversion_utilities.md +++ b/docs/src/manual/manual_conversion_utilities.md @@ -7,44 +7,12 @@ SciMLLogging provides utility functions to convert message levels to common form ```@docs verbosity_to_int ``` - -Convert message levels to integers for packages that use numeric verbosity levels: - -```julia -using SciMLLogging - -# Standard levels -verbosity_to_int(Silent()) # Returns 0 -verbosity_to_int(InfoLevel()) # Returns 1 -verbosity_to_int(WarnLevel()) # Returns 2 -verbosity_to_int(ErrorLevel()) # Returns 3 - -# Custom levels -verbosity_to_int(CustomLevel(10)) # Returns 10 -verbosity_to_int(CustomLevel(-5)) # Returns -5 -``` - ## Boolean Conversion ```@docs verbosity_to_bool ``` -Convert message levels to booleans for packages that use simple on/off verbosity: - -```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 -``` - ## Usage Examples ### Integrating with Integer-Based Packages diff --git a/docs/src/manual/manual_macro.md b/docs/src/manual/manual_macro.md index 65b2f24..4705659 100644 --- a/docs/src/manual/manual_macro.md +++ b/docs/src/manual/manual_macro.md @@ -2,69 +2,6 @@ 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. -## Basic Usage - ```@docs @SciMLMessage -``` - -## Simple String Messages - -The most basic usage emits a string message: - -```julia -@SciMLMessage("Starting computation", verbosity, :initialization) -@SciMLMessage("Iteration complete", verbosity, :progress) -@SciMLMessage("Convergence achieved", verbosity, :convergence) -``` - -## Function-Based Messages - -For expensive-to-compute messages, use a function to enable lazy evaluation: - -```julia -x = 10 -y = 20 - -@SciMLMessage(verbosity, :debug) do - z = expensive_calculation(x, y) - "Result: $z" -end -``` - -The function is only called if the message category is not `Silent()`, avoiding unnecessary computation. - -## Integration with Verbosity Specifiers - -The macro works with any `AbstractVerbositySpecifier` implementation: - -```julia -# Package defines verbosity specifier -@concrete struct SolverVerbosity <: AbstractVerbositySpecifier - initialization - progress - convergence - diagnostics - performance -end - -# Usage in package code -function solve_problem(problem; verbose = SolverVerbosity(Standard())) - @SciMLMessage("Initializing solver", verbose, :initialization) - - # ... solver setup ... - - for iteration in 1:max_iterations - @SciMLMessage("Iteration $iteration", verbose, :progress) - - # ... iteration work ... - - if converged - @SciMLMessage("Converged after $iteration iterations", verbose, :convergence) - break - end - end - - return result -end ``` \ No newline at end of file diff --git a/src/utils.jl b/src/utils.jl index 2c394b4..f241d91 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -72,21 +72,40 @@ To emit a simple string, `@SciMLMessage("message", verbosity, :option)` will emi `@SciMLMessage` can also be used to emit a log message coming from the evaluation of a 0-argument function. This function is resolved in the environment of the macro call. Therefore it can use variables from the surrounding environment. This may be useful if the log message writer wishes to carry out some calculations using existing variables -and use them in the log message. +and use them in the log message. The function is only called if the message category is not `Silent()`, avoiding unnecessary computation. + +The macro works with any `AbstractVerbositySpecifier` implementation: ```julia -# String message -@SciMLMessage("Hello", verbose, :test1) +# Package defines verbosity specifier +@concrete struct SolverVerbosity <: AbstractVerbositySpecifier + initialization + progress + convergence + diagnostics + performance +end + +# Usage in package code +function solve_problem(problem; verbose = SolverVerbosity(Standard())) + @SciMLMessage("Initializing solver", verbose, :initialization) + + # ... solver setup ... + + for iteration in 1:max_iterations + @SciMLMessage("Iteration $iteration", verbose, :progress) -# Function for lazy evaluation -x = 10 -y = 20 + # ... iteration work ... -@SciMLMessage(verbosity, :option) do - z = x + y - "Sum: \$z" + if converged + @SciMLMessage("Converged after $iteration iterations", verbose, :convergence) + break + end + end + + return result end -``` + """ macro SciMLMessage(f_or_message, verb, option) line = __source__.line @@ -113,11 +132,22 @@ end This provides an interface so that these packages can be used with SciMLVerbosity. Each of the basic verbosity levels are mapped to an integer. - - Silent() => 0 - - InfoLevel() => 1 - - WarnLevel() => 2 - - ErrorLevel() => 3 - - CustomLevel(i) => i + ```julia + + using SciMLLogging + + # Standard levels + + verbosity_to_int(Silent()) # Returns 0 + verbosity_to_int(InfoLevel()) # Returns 1 + verbosity_to_int(WarnLevel()) # Returns 2 + verbosity_to_int(ErrorLevel()) # Returns 3 + + # 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 @@ -142,6 +172,20 @@ end 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 From 23668c057b7d8ee1aad8e1bdc011f0ed02600b31 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 2 Oct 2025 13:10:17 -0400 Subject: [PATCH 15/24] fix docstring for SciMLMessage --- src/utils.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index f241d91..01f03eb 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -93,19 +93,19 @@ function solve_problem(problem; verbose = SolverVerbosity(Standard())) # ... solver setup ... for iteration in 1:max_iterations - @SciMLMessage("Iteration $iteration", verbose, :progress) + @SciMLMessage("Iteration \$iteration", verbose, :progress) # ... iteration work ... if converged - @SciMLMessage("Converged after $iteration iterations", verbose, :convergence) + @SciMLMessage("Converged after \$iteration iterations", verbose, :convergence) break end end return result end - +``` """ macro SciMLMessage(f_or_message, verb, option) line = __source__.line From dd20a20e29e5b93d46a2b856d4a6971fe718ec1d Mon Sep 17 00:00:00 2001 From: Jadon Clugston <34165782+jClugstor@users.noreply.github.com> Date: Tue, 7 Oct 2025 14:51:38 -0400 Subject: [PATCH 16/24] Apply suggestion from @ChrisRackauckas Co-authored-by: Christopher Rackauckas --- docs/src/getting_started.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/src/getting_started.md b/docs/src/getting_started.md index ecf5188..9b920bf 100644 --- a/docs/src/getting_started.md +++ b/docs/src/getting_started.md @@ -81,8 +81,6 @@ To switch back to using the logging infrastructure: ```julia SciMLLogging.set_logging_backend("logging") ``` -Note that you will need to restart Julia for this to take affect. - ## Saving Output to Files Combine with Julia's logging to save output: From 12a9e14420ea422410542bbc17bcbfe07fb67eb9 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Wed, 8 Oct 2025 11:43:04 -0400 Subject: [PATCH 17/24] rename files, add descriptions --- .../{manual_backends.md => backends.md} | 0 ...n_utilities.md => conversion_utilities.md} | 0 docs/src/manual/{manual_macro.md => macro.md} | 0 docs/src/manual/manual_presets.md | 97 ------------ ...al_message_levels.md => message_levels.md} | 0 docs/src/manual/presets.md | 149 ++++++++++++++++++ ..._verbosity_specifiers.md => specifiers.md} | 0 7 files changed, 149 insertions(+), 97 deletions(-) rename docs/src/manual/{manual_backends.md => backends.md} (100%) rename docs/src/manual/{manual_conversion_utilities.md => conversion_utilities.md} (100%) rename docs/src/manual/{manual_macro.md => macro.md} (100%) delete mode 100644 docs/src/manual/manual_presets.md rename docs/src/manual/{manual_message_levels.md => message_levels.md} (100%) create mode 100644 docs/src/manual/presets.md rename docs/src/manual/{manual_verbosity_specifiers.md => specifiers.md} (100%) diff --git a/docs/src/manual/manual_backends.md b/docs/src/manual/backends.md similarity index 100% rename from docs/src/manual/manual_backends.md rename to docs/src/manual/backends.md diff --git a/docs/src/manual/manual_conversion_utilities.md b/docs/src/manual/conversion_utilities.md similarity index 100% rename from docs/src/manual/manual_conversion_utilities.md rename to docs/src/manual/conversion_utilities.md diff --git a/docs/src/manual/manual_macro.md b/docs/src/manual/macro.md similarity index 100% rename from docs/src/manual/manual_macro.md rename to docs/src/manual/macro.md 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/manual_message_levels.md b/docs/src/manual/message_levels.md similarity index 100% rename from docs/src/manual/manual_message_levels.md rename to docs/src/manual/message_levels.md diff --git a/docs/src/manual/presets.md b/docs/src/manual/presets.md new file mode 100644 index 0000000..13b4c1e --- /dev/null +++ b/docs/src/manual/presets.md @@ -0,0 +1,149 @@ +# 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. + +**What to include:** +- Nothing - all message categories should be set to `Silent()` +- Use this preset when running automated scripts, batch jobs, or when you want complete silence + +### Minimal Preset +```@docs +Minimal +``` + +Use `Minimal` when you want to be informed of important issues but don't need detailed progress information. + +**What to include at each level:** +- **WarnLevel or higher**: Warnings about potential issues (e.g., convergence problems, parameter choices that may affect results, deprecated features) +- **ErrorLevel**: Critical failures and errors that stop computation +- **Silent**: Progress updates, routine diagnostics, initialization messages, performance metrics, and detailed state information + +**Typical message categories:** +- Errors: `ErrorLevel()` +- Warnings: `WarnLevel()` +- Everything else: `Silent()` + +### Standard Preset +```@docs +Standard +``` + +The `Standard` preset provides a balanced configuration suitable for most interactive use cases. + +**What to include at each level:** +- **InfoLevel or higher**: Important initialization messages (e.g., algorithm selection, key parameter values), significant milestones, convergence status, final results, warnings, and errors +- **WarnLevel or higher**: All warnings and errors as in `Minimal` +- **ErrorLevel**: All critical failures +- **Silent**: Detailed progress bars, iteration-by-iteration updates, verbose diagnostics, and low-level performance metrics + +**Typical message categories:** +- Errors: `ErrorLevel()` +- Warnings: `WarnLevel()` +- Initialization, convergence, results: `InfoLevel()` +- Progress, detailed diagnostics: `Silent()` + +### Detailed Preset +```@docs +Detailed +``` + +`Detailed` is for development, debugging, or when you need comprehensive information about what your code is doing. + +**What to include at each level:** +- **InfoLevel or higher**: Everything 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 +- **WarnLevel or higher**: All warnings and errors +- **ErrorLevel**: All critical failures +- **Silent**: Only truly verbose trace-level information that would clutter output even during debugging + +**Typical message categories:** +- Errors: `ErrorLevel()` +- Warnings: `WarnLevel()` +- Initialization, convergence, results, progress, diagnostics, performance: `InfoLevel()` +- Trace-level debugging: `Silent()` or `CustomLevel(-1000)` + +### All Preset +```@docs +All +``` + +The `All` preset enables maximum verbosity, useful for deep debugging or understanding complex behaviors. + +**What to include at each level:** +- **CustomLevel(-1000) or higher**: Absolutely everything - trace-level debugging, every function entry/exit, every variable change, memory allocations, internal calculations, and any other information that might be useful for understanding program flow +- **InfoLevel or higher**: All standard messages from `Detailed` +- **WarnLevel or higher**: All warnings and errors +- **ErrorLevel**: All critical failures +- **Silent**: Nothing should be silent in this preset + +**Typical message categories:** +- Errors: `ErrorLevel()` +- Warnings: `WarnLevel()` +- Standard messages: `InfoLevel()` +- Verbose debugging and trace: `CustomLevel(-1000)` or similar low-priority custom level +- Nothing should be `Silent()` + +## 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/manual_verbosity_specifiers.md b/docs/src/manual/specifiers.md similarity index 100% rename from docs/src/manual/manual_verbosity_specifiers.md rename to docs/src/manual/specifiers.md From 35184b7a770dd10527084644eea50a936d315283 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 9 Oct 2025 10:01:48 -0400 Subject: [PATCH 18/24] remove line --- docs/src/manual/presets.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/manual/presets.md b/docs/src/manual/presets.md index 13b4c1e..e44acff 100644 --- a/docs/src/manual/presets.md +++ b/docs/src/manual/presets.md @@ -19,7 +19,6 @@ The `None` preset is for when you want no output whatsoever. **What to include:** - Nothing - all message categories should be set to `Silent()` -- Use this preset when running automated scripts, batch jobs, or when you want complete silence ### Minimal Preset ```@docs From 4618f8ab122a16cff7cb27a75f34f3f999435e7f Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 9 Oct 2025 11:22:53 -0400 Subject: [PATCH 19/24] fix pages --- docs/pages.jl | 12 ++++++------ .../{specifiers.md => verbosity_specifiers.md} | 0 2 files changed, 6 insertions(+), 6 deletions(-) rename docs/src/manual/{specifiers.md => verbosity_specifiers.md} (100%) diff --git a/docs/pages.jl b/docs/pages.jl index 7dc77d1..b289d9e 100644 --- a/docs/pages.jl +++ b/docs/pages.jl @@ -6,11 +6,11 @@ pages = [ "Developer Guide" => "tutorials/developer_tutorial.md", ], "Manual" => [ - "Message Levels" => "manual/manual_message_levels.md", - "Verbosity Specifiers" => "manual/manual_verbosity_specifiers.md", - "Verbosity Presets" => "manual/manual_presets.md", - "@SciMLMessage Macro" => "manual/manual_macro.md", - "Conversion Utilities" => "manual/manual_conversion_utilities.md", - "Logging Backends" => "manual/manual_backends.md" + "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/manual/specifiers.md b/docs/src/manual/verbosity_specifiers.md similarity index 100% rename from docs/src/manual/specifiers.md rename to docs/src/manual/verbosity_specifiers.md From 970fb94760c95b28091417a8f1e8f299734a3154 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Fri, 10 Oct 2025 11:41:55 -0400 Subject: [PATCH 20/24] get rid of clutter, improve docstrings for presets --- docs/src/manual/presets.md | 66 -------------------------------------- src/verbosity.jl | 25 ++++++++++++--- 2 files changed, 21 insertions(+), 70 deletions(-) diff --git a/docs/src/manual/presets.md b/docs/src/manual/presets.md index e44acff..f1bfeab 100644 --- a/docs/src/manual/presets.md +++ b/docs/src/manual/presets.md @@ -14,88 +14,22 @@ AbstractVerbosityPreset ```@docs SciMLLogging.None ``` - -The `None` preset is for when you want no output whatsoever. - -**What to include:** -- Nothing - all message categories should be set to `Silent()` - ### Minimal Preset ```@docs Minimal ``` - -Use `Minimal` when you want to be informed of important issues but don't need detailed progress information. - -**What to include at each level:** -- **WarnLevel or higher**: Warnings about potential issues (e.g., convergence problems, parameter choices that may affect results, deprecated features) -- **ErrorLevel**: Critical failures and errors that stop computation -- **Silent**: Progress updates, routine diagnostics, initialization messages, performance metrics, and detailed state information - -**Typical message categories:** -- Errors: `ErrorLevel()` -- Warnings: `WarnLevel()` -- Everything else: `Silent()` - ### Standard Preset ```@docs Standard ``` - -The `Standard` preset provides a balanced configuration suitable for most interactive use cases. - -**What to include at each level:** -- **InfoLevel or higher**: Important initialization messages (e.g., algorithm selection, key parameter values), significant milestones, convergence status, final results, warnings, and errors -- **WarnLevel or higher**: All warnings and errors as in `Minimal` -- **ErrorLevel**: All critical failures -- **Silent**: Detailed progress bars, iteration-by-iteration updates, verbose diagnostics, and low-level performance metrics - -**Typical message categories:** -- Errors: `ErrorLevel()` -- Warnings: `WarnLevel()` -- Initialization, convergence, results: `InfoLevel()` -- Progress, detailed diagnostics: `Silent()` - ### Detailed Preset ```@docs Detailed ``` - -`Detailed` is for development, debugging, or when you need comprehensive information about what your code is doing. - -**What to include at each level:** -- **InfoLevel or higher**: Everything 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 -- **WarnLevel or higher**: All warnings and errors -- **ErrorLevel**: All critical failures -- **Silent**: Only truly verbose trace-level information that would clutter output even during debugging - -**Typical message categories:** -- Errors: `ErrorLevel()` -- Warnings: `WarnLevel()` -- Initialization, convergence, results, progress, diagnostics, performance: `InfoLevel()` -- Trace-level debugging: `Silent()` or `CustomLevel(-1000)` - ### All Preset ```@docs All ``` - -The `All` preset enables maximum verbosity, useful for deep debugging or understanding complex behaviors. - -**What to include at each level:** -- **CustomLevel(-1000) or higher**: Absolutely everything - trace-level debugging, every function entry/exit, every variable change, memory allocations, internal calculations, and any other information that might be useful for understanding program flow -- **InfoLevel or higher**: All standard messages from `Detailed` -- **WarnLevel or higher**: All warnings and errors -- **ErrorLevel**: All critical failures -- **Silent**: Nothing should be silent in this preset - -**Typical message categories:** -- Errors: `ErrorLevel()` -- Warnings: `WarnLevel()` -- Standard messages: `InfoLevel()` -- Verbose debugging and trace: `CustomLevel(-1000)` or similar low-priority custom level -- Nothing should be `Silent()` - ## Custom Presets Packages can define their own preset types for specialized use cases: diff --git a/src/verbosity.jl b/src/verbosity.jl index 8128df0..cdd6d7f 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -70,18 +70,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 @@ -90,7 +89,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 potential issues +(e.g., convergence problems, parameter choices that may affect results, deprecated features) +should be set to `WarnLevel()`. All other messages should be set to `Silent()`. """ struct Minimal <: AbstractVerbosityPreset end @@ -100,6 +104,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 important initialization messages (e.g., algorithm selection, key parameter values), +significant milestones, convergence status, final results to `InfoLevel()` or higher. """ struct Standard <: AbstractVerbosityPreset end @@ -109,6 +117,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. """ struct Detailed <: AbstractVerbosityPreset end @@ -117,5 +131,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 From 01a60246637a07e5db0325a288ed0e8af9db140f Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Mon, 13 Oct 2025 08:35:26 -0400 Subject: [PATCH 21/24] Update presets.md --- docs/src/manual/presets.md | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/docs/src/manual/presets.md b/docs/src/manual/presets.md index f1bfeab..11dd559 100644 --- a/docs/src/manual/presets.md +++ b/docs/src/manual/presets.md @@ -8,28 +8,16 @@ Presets provide convenient, predefined verbosity configurations that cover commo AbstractVerbosityPreset ``` -## Standard Presets +## Available Presets -### None Preset ```@docs SciMLLogging.None -``` -### Minimal Preset -```@docs Minimal -``` -### Standard Preset -```@docs Standard -``` -### Detailed Preset -```@docs Detailed -``` -### All Preset -```@docs All ``` + ## Custom Presets Packages can define their own preset types for specialized use cases: From 46a560480c1755d500e4ed7d2f596de65dab74ce Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Mon, 13 Oct 2025 09:11:03 -0400 Subject: [PATCH 22/24] Update presets.md --- docs/src/manual/presets.md | 45 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/docs/src/manual/presets.md b/docs/src/manual/presets.md index 11dd559..e00ac79 100644 --- a/docs/src/manual/presets.md +++ b/docs/src/manual/presets.md @@ -2,13 +2,54 @@ 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 +## 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 Date: Mon, 13 Oct 2025 09:17:49 -0400 Subject: [PATCH 23/24] Update verbosity.jl --- src/verbosity.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index cdd6d7f..0edf019 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -92,9 +92,9 @@ errors, and critical status information while suppressing routine progress and debugging messages. This verbosity preset should set messages related to critical failures and -errors that stop computation to `ErrorLevel`. Messages related to potential issues -(e.g., convergence problems, parameter choices that may affect results, deprecated features) -should be set to `WarnLevel()`. All other messages should be set to `Silent()`. +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 @@ -106,8 +106,8 @@ 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 important initialization messages (e.g., algorithm selection, key parameter values), -significant milestones, convergence status, final results to `InfoLevel()` or higher. +messages such as non-fatal deprecations and critical warnings that require handling +to `InfoLevel`. """ struct Standard <: AbstractVerbosityPreset end @@ -122,7 +122,7 @@ This verbosity preset should include the settings from `Standard`, plus progress (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. +clutter output even during debugging, and information that would be expensive to calculate. """ struct Detailed <: AbstractVerbosityPreset end @@ -135,4 +135,4 @@ 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 From 315d2655540394830fa3f52a71b718113fe75a70 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Mon, 13 Oct 2025 09:26:47 -0400 Subject: [PATCH 24/24] Update message_levels.md --- docs/src/manual/message_levels.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/src/manual/message_levels.md b/docs/src/manual/message_levels.md index 7b1b82e..cd555ce 100644 --- a/docs/src/manual/message_levels.md +++ b/docs/src/manual/message_levels.md @@ -19,6 +19,12 @@ Silent The `Silent` level is special - it completely suppresses output for a message. +### Debug Level +```@docs +DebugLevel +``` + + ### Information Level ```@docs InfoLevel @@ -75,4 +81,4 @@ The message levels have a natural hierarchy that affects logging behavior: - `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. \ No newline at end of file +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.