Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds the basic logging capabilities for Omega #27

Merged
merged 1 commit into from
Aug 24, 2023
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
23 changes: 15 additions & 8 deletions components/omega/OmegaBuild.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ set(OMEGA_DEFAULT_BUILD_TYPE Release) # Debug or Release
###########################
macro(setup_common_variables)

option(OMEGA_DEBUG "Turn on error message throwing (default OFF)." OFF)

if(NOT DEFINED OMEGA_CXX_FLAGS )
# initialize cxx flags as an empty list
set(OMEGA_CXX_FLAGS "")
Expand Down Expand Up @@ -72,13 +74,6 @@ endmacro()

macro(setup_e3sm_build)

# prints generates all cmake variables
#get_cmake_property(_variableNames VARIABLES)
#list (SORT _variableNames)
#foreach (_variableName ${_variableNames})
# message(STATUS "${_variableName}=${${_variableName}}")
#endforeach()

setup_common_variables()

set(OMEGA_BUILD_TYPE ${E3SM_DEFAULT_BUILD_TYPE})
Expand All @@ -99,6 +94,12 @@ endmacro()
################################
macro(update_variables)


if(OMEGA_DEBUG)
add_compile_definitions(OMEGA_DEBUG)
add_compile_definitions(LOG_UNBUFFERED_LOGGING="1")
endif()

# Set the build type
set(CMAKE_BUILD_TYPE ${OMEGA_BUILD_TYPE})

Expand All @@ -121,11 +122,17 @@ macro(update_variables)
endif()

else()

set(YAKL_ARCH "")

endif()

# # prints generates all cmake variables
# get_cmake_property(_variableNames VARIABLES)
# list (SORT _variableNames)
# foreach (_variableName ${_variableNames})
# message(STATUS "${_variableName}=${${_variableName}}")
# endforeach()

endmacro()


Expand Down
2 changes: 1 addition & 1 deletion components/omega/doc/design/Logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ message:
```c++
Array1DR8 var;
...
LOG_INFO("log message", var);
LOG_INFO("log message {}", var);
```

## 5 Verification and Testing
Expand Down
48 changes: 48 additions & 0 deletions components/omega/doc/devGuide/Logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
(omega-dev-logging)=

# Developing Omega Logging

Omega's logging system is built upon the
[spdlog](https://github.com/gabime/spdlog) logging tool.

Logging macros and custom formatters for YAKL data types have been
integrated into the Omega logging system via the Logging.h header file
located in the src/infra directory. Users who wish to utilize Omega's
logging capabilities must include this header file in their code.

The `src/infra/Logging.cpp` file encompasses various functions related
to logging. As of the current version, this file contains the
`OMEGA::initLogging` function, which initialize the logging process.
It is recommended to invoke the `OMEGA::initLogging` function at the beginning
of an Omega application to properly initialize the logging system.

## Initializing Omega Logger

The `OMEGA::initLogging` function, located within the `src/infra/Logging.cpp`
file, serves as a pivotal component for initializing the Omega logging system.

The function establishes the default logger configuration, ensuring that
logging messages are effectively saved to a designated file. The path to
this file is determined by utilizing the `OMEGA_LOG_FILEPATH` macro, which
allows users to specify the desired file location for logging purposes.

## Creating Logging Macros

The Omega logging macros, denoted by the prefix `LOG_`, are defined within
the `src/infra/Logging.h` file. These macros constitute a main part of
the logging infrastructure, enabling users to seamlessly incorporate
logging functionality into their Omega applications.

Furthermore, the logging framework includes a distinct set of macros that
commence with the prefix `LOGGER_`. These macros offer enhanced
versatility by accommodating the utilization of the spdlog logger as
their first argument. This approach facilitats the integration of various
logger types.

## Customer formatter for YAKL

Within the same header file, you will encounter specialized spdlog formatter
structs designed to accommodate YAKL data types.

For further information on customizing the spdlog formatter, refer to
[Custom formatting](https://github.com/gabime/spdlog/wiki/3.-Custom-formatting).
2 changes: 2 additions & 0 deletions components/omega/doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ userGuide/QuickStart
userGuide/OmegaBuild
userGuide/DataTypes
userGuide/MachEnv
userGuide/Logging
```

```{toctree}
Expand All @@ -37,6 +38,7 @@ devGuide/CondaEnv
devGuide/Docs
devGuide/BuildDocs
devGuide/CMakeBuild
devGuide/Logging
```

```{toctree}
Expand Down
70 changes: 70 additions & 0 deletions components/omega/doc/userGuide/Logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
(omega-user-logging)=

# Omega Logging

Omega's logging system is built upon the [spdlog](https://github.com/gabime/spdlog)
logging tool. As of this version, It only supports Standalone build mode.

## Logging in Standalone Build mode

To use Omega's logging system in Standalone build mode, you need to include
the Logging.h header file in your code.

```c
#include "Logging.h"
```

You can then use the following macros to write logs of different severity
levels:

```c
LOG_TRACE (logmsg);
LOG_DEBUG (logmsg);
LOG_INFO (logmsg);
LOG_WARN (logmsg);
LOG_ERROR (logmsg);
LOG_CRITICAL(logmsg);
```

The "logmsg" argument in these macros can be any string that follows the syntax
of C++'s std::format function. For example, the following code writes a
"Hello, World!" message as a TRACE level log:

```c
LOG_TRACE("Hello, {}!", "World");
```
For more information about the syntax of logmsg, please see the spdlog documentation.

Here is a table that summarizes the different log severities and their meanings:

1. `LOG_CRITICAL`: Used to indicate a critical error or issue that requires
immediate attention and could potentially cause data loss or application
failure.
2. `LOG_ERROR`: Used to indicate an error or issue that could cause
application instability or incorrect behavior.
3. `LOG_WARN`: Used to indicate a warning or potential issue that should be
addressed but does not necessarily require immediate attention.
4. `LOG_INFO`: Used to provide general informational messages about the
application's operation or progress.
5. `LOG_DEBUG`: Used to provide detailed debugging information for
developers to track down issues or analyze behavior.
6. `LOG_TRACE`: Used to provide the most detailed level of information,
including function calls and variable values, and is typically used for deep
analysis and debugging.


You can replace the string "World" with any variable whose type is
a C++ basic data type, such as an int, a float, or a string. You can
also use a limited set of YAKL variables. For example, the following code
writes the value of the variable `MyInt` as a TRACE level log:

```c
int MyInt = 10;
LOG_TRACE("The value of MyInt is: {}", MyInt);
```

By default, the logfile will be created in the build directory.

## E3SM Component Build

T.B.D.
7 changes: 7 additions & 0 deletions components/omega/external/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ add_subdirectory(${E3SM_EXTERNALS_ROOT}/YAKL ${CMAKE_CURRENT_BINARY_DIR}/YAKL)
if (CMAKE_VERSION VERSION_GREATER "3.18.0")
set_property(TARGET yakl PROPERTY CUDA_ARCHITECTURES OFF)
endif()

if(OMEGA_DEBUG)
target_compile_definitions(yakl INTERFACE YAKL_DEBUG=1)
endif()

# Add the spdlog library
add_subdirectory(${E3SM_EXTERNALS_ROOT}/ekat/extern/spdlog ${CMAKE_CURRENT_BINARY_DIR}/ekat/extern/spdlog)
31 changes: 25 additions & 6 deletions components/omega/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
# build Omega

# Add source files for the library
file(GLOB _LIBSRC_FILES ocn/*.cpp)
file(GLOB _LIBSRC_FILES ocn/*.cpp infra/*.cpp)

list(JOIN OMEGA_CXX_FLAGS " " _CXX_FLAGS_EXPANDED)

# Create the library target
add_library(${OMEGA_LIB_NAME} ${_LIBSRC_FILES})
set_target_properties(${OMEGA_LIB_NAME} PROPERTIES COMPILE_FLAGS "${_CXX_FLAGS_EXPANDED}")
set_target_properties(
${OMEGA_LIB_NAME}
PROPERTIES COMPILE_FLAGS "${_CXX_FLAGS_EXPANDED}"
)

# add link directories
target_link_libraries(${OMEGA_LIB_NAME} spdlog "${OMEGA_LDFLAGS}")

# add include directories
target_include_directories(${OMEGA_LIB_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/infra")
target_include_directories(
${OMEGA_LIB_NAME}
PRIVATE
"${OMEGA_SOURCE_DIR}/src/base"
"${OMEGA_SOURCE_DIR}/src/infra"
)

# include yakl cmake utility
include(${E3SM_EXTERNALS_ROOT}/YAKL/yakl_utils.cmake)
Expand All @@ -29,12 +40,20 @@ endif()
# build Omega executable
if(OMEGA_BUILD_EXECUTABLE)
set(EXESRC_FILES
drivers/drvdummy.cpp
drivers/DrvDummy.cpp
)
# Create the executable target
add_executable(${OMEGA_EXE_NAME} ${EXESRC_FILES})
set_target_properties(${OMEGA_EXE_NAME} PROPERTIES COMPILE_FLAGS "${_CXX_FLAGS_EXPANDED}")
target_include_directories(${OMEGA_EXE_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/infra")
set_target_properties(
${OMEGA_EXE_NAME}
PROPERTIES COMPILE_FLAGS "${_CXX_FLAGS_EXPANDED}"
)
target_include_directories(
${OMEGA_EXE_NAME}
PRIVATE
"${OMEGA_SOURCE_DIR}/src/base"
"${CMAKE_CURRENT_SOURCE_DIR}/infra"
)
target_link_libraries(${OMEGA_EXE_NAME} ${OMEGA_LIB_NAME})

# help the executable target to be built with yakl
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
// OCN dummy driver

#include "Logging.h"
#include <iostream>

using namespace std;

void dummy(int argc, char **argv);

int main(int argc, char **argv) {

cout << "Starting driver..." << endl;
std::cout << std::endl << "Starting driver..." << std::endl;

dummy(argc, argv);

cout << "Stopped driver." << endl;
std::cout << "Stopped driver." << std::endl;

return 0;
}
41 changes: 41 additions & 0 deletions components/omega/src/infra/LogFormatters.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#ifndef OMEGA_LOG_FORMATTERS_H
#define OMEGA_LOG_FORMATTERS_H
//===-- infra/LogFormatters.h - Omega specific log formatters --*- C++ -*-===//
//
/// \file
/// \brief Defines spdlog custom formatters
///
/// This header defines custom formatters for Omega logging.
//
//===----------------------------------------------------------------------===//

#include "DataTypes.h"
#include <spdlog/spdlog.h>

template <>
struct fmt::formatter<OMEGA::ArrayHost1DReal> : fmt::formatter<std::string> {
auto format(OMEGA::ArrayHost1DReal my, format_context &ctx)
-> decltype(ctx.out()) {
#ifdef OMEGA_DEBUG
return fmt::format_to(
ctx.out(), "[data type of '{}' is ArrayHost1DReal.]", my.label());
#else
return fmt::format_to(ctx.out(), "[data type of '' is ArrayHost1DReal.]");
#endif
}
};

template <>
struct fmt::formatter<OMEGA::ArrayHost2DReal> : fmt::formatter<std::string> {
auto format(OMEGA::ArrayHost2DReal my, format_context &ctx)
-> decltype(ctx.out()) {
#ifdef OMEGA_DEBUG
return fmt::format_to(
ctx.out(), "[data type of '{}' is ArrayHost2DReal.]", my.label());
#else
return fmt::format_to(ctx.out(), "[data type of '' is ArrayHost2DReal.]");
#endif
}
};

#endif // OMEGA_LOG_FORMATTERS_H
31 changes: 31 additions & 0 deletions components/omega/src/infra/Logging.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//===-- infra/Logging.cpp - Implements Omega Logging functions --*- C++ -*-===//
//
/// \file
/// \brief implements Omega logging functions
///
/// This implements Omega logging initialization.
//
//===----------------------------------------------------------------------===//

#include "Logging.h"
#include <spdlog/sinks/basic_file_sink.h>

namespace OMEGA {

void initLogging(std::shared_ptr<spdlog::logger> Logger) {

try {
Logger->flush_on(spdlog::level::warn);
spdlog::set_default_logger(Logger);

} catch (spdlog::spdlog_ex const &Ex) {
std::cout << "Log init failed: " << Ex.what() << std::endl;
}
}

void initLogging(std::string const &LogFilePath) {
auto Logger = spdlog::basic_logger_mt("*", LogFilePath);
initLogging(Logger);
}

} // namespace OMEGA
Loading