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
27 changes: 27 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,33 @@ The `namelist.input` file in `/run` includes all the setup and options info you

You can examine model output in the `/data/output.nc` file (requires [Panoply](https://www.giss.nasa.gov/tools/panoply/) or other NetCDF viewer).

## Logger

The Errror Warning and Trapping Systems (EWTS) has been added to this module using a logging schema. All write statements have been converted to `write_log` statements, which saves the ouptut to a log file based on the log level.

When running within the ngen framework, the log file and log level are handled programatically. When running standalone, logging is defaulted to DISABLED.

**Running Standalone**

In order to generate log messages when running standalone, the `NGEN_EWTS_LOGGING` environment variable must be set to `ENABLED`. This is the only required environment variable . Other optional logger environment variables exist for specifying the log file full pathname and setting the log level. If the user only enables logging, the log level will be set to INFO and the filename will be created based on the user and module names. All logger setup details are written to the console when the module is run.
```
# Case Sensitive
export NGEN_EWTS_LOGGING=ENABLED
export NGEN_LOG_FILE_PATH=<full pathname for log file>
export NOAHOWP_LOGLEVEL=<DEBUG, INFO, WARNING, SEVERE, FATAL>
```
**Log Levels**
| Level | Description | Typical Use |
|---------|-----------------------------------------------------|-----------------------------------------------|
| DEBUG | Detailed diagnostic info for development/troubleshooting. | Variable values, function entry/exit. |
| FATAL | Critical failure that aborts or makes app unrecoverable. | Crashes, memory errors, invalid state. |
| INFO | General events confirming expected operations. | Startup/shutdown, configs, task completions. |
| SEVERE | Significant problem; app may continue in degraded state. | Failed services, corrupted configs, data loss.|
| WARNING | Potential issue that doesn’t stop execution. | Deprecated APIs, missing files, repeatable errors. |

Default log level is INFO. The log level is hierarchical. Setting it to INFO, will log INFO, WARNING, SEVERE and FATAL
messages.

## BMI unit tests

To run unit tests, first compile and link the test program from the main-level directory:
Expand Down
29 changes: 12 additions & 17 deletions src/noahowpLogger.f90
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ module noahowp_log_module
logical :: opened_once = .false.
logical :: logger_initialized = .false. ! Flag to track if the logger has been initialized

! To use Logger while running this module stand-alone, set
! the following environment variables, case-sensitive:
! NGEN_EWTS_LOGGING=ENABLED
! NGEN_LOG_FILE_PATH=<full pathname for log file>
! NOAHOWP_LOGLEVEL=<DEBUG, INFO, WARNING, SEVERE, FATAL>
!
Comment thread
zhengtaocui marked this conversation as resolved.
! Constants character(len=1), parameter :: DS = "/"
character(len=16), parameter :: MODULE_NAME = "Noah-OWP-Modular"
character(len=14), parameter :: LOG_DIR_NGENCERF = "/ngencerf/data"
Expand All @@ -36,8 +42,7 @@ module noahowp_log_module
contains

subroutine initialize_logger()
character(len=256) :: log_env, log_msg
character(len=8) :: log_str
character(len=256) :: log_env, log_str
integer :: save_log_level

logger_initialized = .true.
Expand All @@ -48,7 +53,7 @@ subroutine initialize_logger()
call flush(6)
else
logging_enabled = .false.
print *,trim(MODULE_NAME)," Logging ", trim(log_env)
print *,trim(MODULE_NAME)," Logging NOT enabled. EV_EWTS_LOGGING=", trim(log_env)
call flush(6)
return
end if
Expand All @@ -68,19 +73,15 @@ subroutine initialize_logger()
else if (log_str == "FATAL" ) then
log_level = LOG_LEVEL_FATAL
else
log_str = "INFO (" // trim(EV_MODULE_LOGLEVEL) // " = '" // trim(log_str) // "' INVALID Log Level) Defaulted to INFO"
log_level = LOG_LEVEL_INFO ! Default level
end if
print *, trim(MODULE_NAME),"Log level set to ", log_str
call flush(6)

! Get the log file path by calling set_log_file_path
call set_log_file_path()

save_log_level = log_level
log_level = LOG_LEVEL_INFO ! Ensure this INFO message is always logged
log_msg = "Log level set to " // log_str
call write_log(log_msg, log_level);
log_level = save_log_level;
print *, trim(MODULE_NAME)," Log level: ", log_str
call flush(6)
end subroutine initialize_logger

function fit_string(str, target_len) result(fixed_str)
Expand Down Expand Up @@ -206,7 +207,6 @@ subroutine set_log_file_path()
character(len=512) :: log_file_dir
character(len=40) :: timestamp
integer :: save_log_level
character(len=1100) :: log_msg

append_entries = .true.
module_log_env_exists = .false.
Expand Down Expand Up @@ -257,13 +257,8 @@ subroutine set_log_file_path()
if (log_file_ready(append_entries)) then
if (.not. module_log_env_exists) then
call write_env_var(EV_MODULE_LOGFILEPATH, log_file_path)
print *, "Module ", trim(MODULE_NAME), " Log File: ", trim(log_file_path)
print *, trim(MODULE_NAME), " Log File: ", trim(log_file_path)
call flush(6)
save_log_level = log_level
log_level = LOG_LEVEL_INFO ! Ensure this INFO message is always logged
log_msg = "Logging started. Log File Path: " // log_file_path
call write_log(log_msg, log_level);
log_level = save_log_level;
end if
else
print *, "Unable to open log file. Log entries will be writen to stdout"
Expand Down