Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions doc/mpeg_validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ end select
- Output path validation
- FFmpeg availability verification

**Stage 2: Pipeline Monitoring**
**Stage 2: Pipeline Monitoring**
- Real-time pipe health during frame transmission
- Frame data integrity checking
- Memory usage and error detection
Expand All @@ -84,15 +84,15 @@ Animation save now returns comprehensive status reflecting all validation stages
subroutine enhanced_animation_save_example()
type(animation_t) :: anim
integer :: status

call anim%save("animation.mp4", fps=24, status=status)

select case (status)
case (0)
print *, "✓ Animation created and fully validated"
case (-1)
print *, "✗ FFmpeg not available"
case (-3)
case (-3)
print *, "✗ Invalid file format"
case (-4)
print *, "✗ Pipe connection failed"
Expand Down Expand Up @@ -167,7 +167,7 @@ File validation failed:
```fortran
! Enable detailed validation logging
use fortplot_logging
call set_log_level(LOG_DEBUG)
call set_log_level(LOG_LEVEL_DEBUG)
call anim%save("debug.mp4", fps=24, status=status)
! Outputs detailed pipe and validation diagnostics
```
Expand Down Expand Up @@ -266,7 +266,7 @@ type(animation_t) :: anim
integer :: status

! Enable detailed diagnostics
call set_log_level(LOG_DEBUG)
call set_log_level(LOG_LEVEL_DEBUG)

! Save with enhanced error reporting
call anim%save("debug.mp4", fps=24, status=status)
Expand All @@ -282,4 +282,4 @@ end if
- Frame transmission progress and validation
- File system operations and validation results
- FFmpeg command execution and output parsing
- Memory usage and performance metrics
- Memory usage and performance metrics
25 changes: 22 additions & 3 deletions doc/warning_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ The system automatically detects CI environments and suppresses warnings:

## Priority Order

1. **Manual Suppression**: `FORTPLOT_SUPPRESS_WARNINGS` takes highest priority
2. **Force Override**: `FORTPLOT_FORCE_WARNINGS` overrides CI auto-detection
1. **Force Override**: `FORTPLOT_FORCE_WARNINGS` takes highest priority and forces warnings ON
2. **Manual Suppression**: `FORTPLOT_SUPPRESS_WARNINGS` suppresses warnings when set
3. **CI Auto-Detection**: Automatic suppression in detected CI environments
4. **Default**: Warnings visible in development environments

Expand Down Expand Up @@ -148,8 +148,27 @@ FORTPLOT_SUPPRESS_WARNINGS=1 make test 2>&1 | grep WARNING
2. Verify CI detection: May be auto-suppressing
3. Set explicit control: `export FORTPLOT_SUPPRESS_WARNINGS=0`

## Querying And Restoring Log Level

When temporarily increasing verbosity (for example during debugging), capture the
current level with `get_log_level()` and restore it afterwards to avoid leaking
state into other tests or applications:

```fortran
use fortplot, only: set_log_level, get_log_level, &
LOG_LEVEL_DEBUG

integer :: prev
prev = get_log_level()
call set_log_level(LOG_LEVEL_DEBUG)

! ... perform debug operations ...

call set_log_level(prev)
```

### Performance Impact
The warning suppression system has minimal performance impact:
- Environment variables checked once during initialization
- Boolean flag checks for each warning (negligible overhead)
- No impact when warnings are suppressed
- No impact when warnings are suppressed
4 changes: 2 additions & 2 deletions src/core/fortplot.f90
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ module fortplot
use fortplot_animation, only: animation_t, FuncAnimation

! Logging functionality
use fortplot_logging, only: set_log_level, &
use fortplot_logging, only: set_log_level, get_log_level, &
LOG_LEVEL_SILENT, LOG_LEVEL_ERROR, &
LOG_LEVEL_WARNING, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG

Expand Down Expand Up @@ -144,7 +144,7 @@ module fortplot
public :: animation_t, FuncAnimation

! Logging interface
public :: set_log_level
public :: set_log_level, get_log_level
public :: LOG_LEVEL_SILENT, LOG_LEVEL_ERROR
public :: LOG_LEVEL_WARNING, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG

Expand Down
92 changes: 53 additions & 39 deletions src/external/fortplot_logging.f90
Original file line number Diff line number Diff line change
@@ -1,46 +1,60 @@
module fortplot_logging
!! Simple logging facility for fortplot library
!! Allows control over console output verbosity and warning suppression
!!
!!
!! Supports environment variable-based warning suppression:
!! - FORTPLOT_SUPPRESS_WARNINGS: Manual warning suppression control
!! - Automatic CI detection: GITHUB_ACTIONS, CI, CONTINUOUS_INTEGRATION
!! - FORTPLOT_FORCE_WARNINGS: Force warnings even in CI environments

use fortplot_string_utils, only: parse_boolean_env
implicit none
private
public :: set_log_level, log_info, log_warning, log_error, log_debug

public :: set_log_level, get_log_level, log_info, log_warning, log_error, log_debug
public :: LOG_LEVEL_SILENT, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG
public :: initialize_warning_suppression, is_warnings_suppressed

! Log levels (in increasing verbosity)
integer, parameter :: LOG_LEVEL_SILENT = 0
integer, parameter :: LOG_LEVEL_ERROR = 1
integer, parameter :: LOG_LEVEL_ERROR = 1
integer, parameter :: LOG_LEVEL_WARNING = 2
integer, parameter :: LOG_LEVEL_INFO = 3
integer, parameter :: LOG_LEVEL_DEBUG = 4

! Default log level (warnings and errors only)
integer :: current_log_level = LOG_LEVEL_WARNING

! Warning suppression state
logical :: warnings_suppressed = .false.
logical :: suppression_initialized = .false.

contains

subroutine set_log_level(level)
!! Set the global logging level
!!
!! Set the global logging level with input validation
!!
!! Arguments:
!! level: LOG_LEVEL_SILENT, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING,
!! level: LOG_LEVEL_SILENT, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING,
!! LOG_LEVEL_INFO, or LOG_LEVEL_DEBUG
integer, intent(in) :: level
current_log_level = level
integer :: lvl

! Clamp to valid range to avoid undefined states
lvl = level
if (lvl < LOG_LEVEL_SILENT) lvl = LOG_LEVEL_SILENT
if (lvl > LOG_LEVEL_DEBUG) lvl = LOG_LEVEL_DEBUG
current_log_level = lvl
end subroutine set_log_level

function get_log_level() result(level)
!! Get the current global logging level
!! Returns one of: LOG_LEVEL_SILENT, LOG_LEVEL_ERROR,
!! LOG_LEVEL_WARNING, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG
integer :: level
level = current_log_level
end function get_log_level

subroutine log_info(message)
!! Log an informational message
character(len=*), intent(in) :: message
Expand All @@ -53,17 +67,17 @@ subroutine log_warning(message)
!! Log a warning message with suppression support
!! Respects FORTPLOT_SUPPRESS_WARNINGS and CI environment detection
character(len=*), intent(in) :: message

! Initialize suppression state if not already done
if (.not. suppression_initialized) then
call initialize_warning_suppression()
end if

! Check if warnings should be suppressed
if (warnings_suppressed) then
return ! Suppress warning output
end if

if (current_log_level >= LOG_LEVEL_WARNING) then
print *, "[WARNING] ", trim(message)
end if
Expand Down Expand Up @@ -91,18 +105,10 @@ subroutine initialize_warning_suppression()
character(len=256) :: env_value
integer :: status
logical :: ci_detected, force_warnings

if (suppression_initialized) return

! Check for manual warning suppression override
call get_environment_variable('FORTPLOT_SUPPRESS_WARNINGS', env_value, status=status)
if (status == 0 .and. len_trim(env_value) > 0) then
warnings_suppressed = parse_boolean_env(env_value)
suppression_initialized = .true.
return
end if

! Check for force warnings override (takes precedence)

! Check for force warnings override (takes precedence over all)
call get_environment_variable('FORTPLOT_FORCE_WARNINGS', env_value, status=status)
if (status == 0 .and. len_trim(env_value) > 0) then
force_warnings = parse_boolean_env(env_value)
Expand All @@ -112,25 +118,33 @@ subroutine initialize_warning_suppression()
return
end if
end if


! Check for manual warning suppression override
call get_environment_variable('FORTPLOT_SUPPRESS_WARNINGS', env_value, status=status)
if (status == 0 .and. len_trim(env_value) > 0) then
warnings_suppressed = parse_boolean_env(env_value)
suppression_initialized = .true.
return
end if

! Auto-detect CI environment
ci_detected = detect_ci_environment()
if (ci_detected) then
warnings_suppressed = .true.
else
warnings_suppressed = .false.
end if

suppression_initialized = .true.
end subroutine initialize_warning_suppression

logical function detect_ci_environment()
!! Detect common CI environments
character(len=256) :: env_value
integer :: status

detect_ci_environment = .false.

! GitHub Actions
call get_environment_variable('GITHUB_ACTIONS', env_value, status=status)
if (status == 0 .and. len_trim(env_value) > 0) then
Expand All @@ -139,7 +153,7 @@ logical function detect_ci_environment()
return
end if
end if

! Generic CI indicator
call get_environment_variable('CI', env_value, status=status)
if (status == 0 .and. len_trim(env_value) > 0) then
Expand All @@ -148,7 +162,7 @@ logical function detect_ci_environment()
return
end if
end if

! Jenkins CI
call get_environment_variable('CONTINUOUS_INTEGRATION', env_value, status=status)
if (status == 0 .and. len_trim(env_value) > 0) then
Expand All @@ -157,14 +171,14 @@ logical function detect_ci_environment()
return
end if
end if

! Jenkins BUILD_ID
call get_environment_variable('BUILD_ID', env_value, status=status)
if (status == 0 .and. len_trim(env_value) > 0) then
detect_ci_environment = .true.
return
end if

! Travis CI
call get_environment_variable('TRAVIS', env_value, status=status)
if (status == 0 .and. len_trim(env_value) > 0) then
Expand All @@ -173,7 +187,7 @@ logical function detect_ci_environment()
return
end if
end if

! CircleCI
call get_environment_variable('CIRCLECI', env_value, status=status)
if (status == 0 .and. len_trim(env_value) > 0) then
Expand All @@ -183,8 +197,8 @@ logical function detect_ci_environment()
end if
end if
end function detect_ci_environment


logical function is_warnings_suppressed()
!! Check if warnings are currently suppressed
if (.not. suppression_initialized) then
Expand Down
40 changes: 40 additions & 0 deletions test/test_log_level_getter.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
program test_log_level_getter
!! Verify get_log_level() reflects the current logging level
!! and stays consistent across transitions.

use fortplot, only: set_log_level, get_log_level, &
LOG_LEVEL_SILENT, LOG_LEVEL_ERROR, &
LOG_LEVEL_WARNING, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG
implicit none

call ensure(get_log_level() == LOG_LEVEL_WARNING, 'default level is WARNING')

call set_log_level(LOG_LEVEL_SILENT)
call ensure(get_log_level() == LOG_LEVEL_SILENT, 'level SILENT after set')

call set_log_level(LOG_LEVEL_ERROR)
call ensure(get_log_level() == LOG_LEVEL_ERROR, 'level ERROR after set')

call set_log_level(LOG_LEVEL_INFO)
call ensure(get_log_level() == LOG_LEVEL_INFO, 'level INFO after set')

call set_log_level(LOG_LEVEL_DEBUG)
call ensure(get_log_level() == LOG_LEVEL_DEBUG, 'level DEBUG after set')

! Reset to default for other tests
call set_log_level(LOG_LEVEL_WARNING)
call ensure(get_log_level() == LOG_LEVEL_WARNING, 'level reset to WARNING')

contains

subroutine ensure(cond, msg)
logical, intent(in) :: cond
character(len=*), intent(in) :: msg
if (.not. cond) then
print *, 'ASSERTION FAILED:', trim(msg)
stop 1
end if
end subroutine ensure

end program test_log_level_getter

Loading
Loading