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

Add logging to libcudf #12637

Merged
merged 56 commits into from
Mar 10, 2023
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
60f6157
remove unused function
vuule Jan 28, 2023
a888ac8
logger
vuule Jan 28, 2023
5108371
log env var reads
vuule Jan 28, 2023
b2cc531
remove repeated env var reads of PREFER_PAGEABLE_TMP_MEMORY
vuule Jan 28, 2023
d7ecd33
copyright year
vuule Jan 28, 2023
830ab00
docs
vuule Jan 28, 2023
a4c51c0
yaml
vuule Jan 28, 2023
d029e1e
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Jan 30, 2023
3d7c2ca
move impl to cpp
vuule Jan 31, 2023
cbda9d0
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Jan 31, 2023
87c5d3a
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Feb 2, 2023
0df8e97
anon namespace
vuule Feb 2, 2023
92f53f9
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Feb 3, 2023
36004e5
tests mostly
vuule Feb 3, 2023
0a90a8f
style
vuule Feb 3, 2023
0e95828
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Feb 6, 2023
498ac21
use macro
vuule Feb 6, 2023
f0ae3e2
fixture
vuule Feb 7, 2023
680f425
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Feb 9, 2023
6ab194c
separate public logger API from logging macros
vuule Feb 9, 2023
404fa1d
Merge branch 'branch-23.04' into fea-logger
vuule Feb 9, 2023
bc12b13
guide start
vuule Feb 9, 2023
38da9b5
Merge branch 'fea-logger' of https://github.com/vuule/cudf into fea-l…
vuule Feb 9, 2023
c736164
header docs
vuule Feb 10, 2023
b0ec318
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Feb 11, 2023
bae202c
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Feb 13, 2023
df803a4
dev guide
vuule Feb 14, 2023
d6b8145
clean up
vuule Feb 14, 2023
e813cb9
build changes
vuule Feb 14, 2023
b1f0994
style
vuule Feb 14, 2023
c1ceb73
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Feb 15, 2023
30fcd28
Apply suggestions from code review
vuule Feb 15, 2023
af09276
Merge branch 'fea-logger' of https://github.com/vuule/cudf into fea-l…
vuule Feb 15, 2023
588d6f5
remove GCC workaround
vuule Feb 15, 2023
0c24717
fix string constant
vuule Feb 15, 2023
5f090e2
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Feb 18, 2023
6fea0bf
update default level, sink
vuule Feb 18, 2023
c77426d
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Feb 27, 2023
5581c8a
switch to stderr
vuule Feb 27, 2023
6378bf7
missing doc
vuule Feb 27, 2023
553a57b
docs improvement
vuule Feb 27, 2023
49f3896
remove outdated docs
vuule Feb 27, 2023
0b6b27c
update dev guide
vuule Feb 28, 2023
a540928
small fixes
vuule Feb 28, 2023
dcd3b29
style
vuule Feb 28, 2023
e49f007
Merge branch 'branch-23.04' into fea-logger
vuule Feb 28, 2023
fd2636f
Merge branch 'branch-23.04' of https://github.com/rapidsai/cudf into …
vuule Mar 6, 2023
c75ff33
cmake changes
vuule Mar 6, 2023
a8c3e11
conda changes
vuule Mar 6, 2023
57f6d05
Merge branch 'fea-logger' of https://github.com/vuule/cudf into fea-l…
vuule Mar 6, 2023
eb045f7
style
vuule Mar 6, 2023
2280ecf
doc improvement
vuule Mar 10, 2023
e7fe0cd
docs that killed timezone refactor
vuule Mar 10, 2023
06893a3
Merge branch 'branch-23.04' into fea-logger
vuule Mar 10, 2023
1d1950c
Update cpp/CMakeLists.txt
vuule Mar 10, 2023
855fcc0
Merge branch 'branch-23.04' into fea-logger
vuule Mar 10, 2023
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
2 changes: 2 additions & 0 deletions conda/recipes/libcudf/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ outputs:
- test -f $PREFIX/include/cudf/detail/utilities/int_fastdiv.h
- test -f $PREFIX/include/cudf/detail/utilities/integer_utils.hpp
- test -f $PREFIX/include/cudf/detail/utilities/linked_column.hpp
- test -f $PREFIX/include/cudf/detail/utilities/logger.hpp
- test -f $PREFIX/include/cudf/detail/utilities/pinned_allocator.hpp
- test -f $PREFIX/include/cudf/detail/utilities/vector_factories.hpp
- test -f $PREFIX/include/cudf/detail/utilities/visitor_overload.hpp
Expand Down Expand Up @@ -276,6 +277,7 @@ outputs:
- test -f $PREFIX/include/cudf/utilities/bit.hpp
- test -f $PREFIX/include/cudf/utilities/default_stream.hpp
- test -f $PREFIX/include/cudf/utilities/error.hpp
- test -f $PREFIX/include/cudf/utilities/logger.hpp
- test -f $PREFIX/include/cudf/utilities/span.hpp
- test -f $PREFIX/include/cudf/utilities/traits.hpp
- test -f $PREFIX/include/cudf/utilities/type_checks.hpp
Expand Down
15 changes: 10 additions & 5 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,16 @@ set(CUDF_CUDA_FLAGS "")
set(CUDF_CXX_DEFINITIONS "")
set(CUDF_CUDA_DEFINITIONS "")

# Set RMM logging level
set(RMM_LOGGING_LEVEL
# Set logging level
set(LIBCUDF_LOGGING_LEVEL
"INFO"
CACHE STRING "Choose the logging level."
)
set_property(
CACHE RMM_LOGGING_LEVEL PROPERTY STRINGS "TRACE" "DEBUG" "INFO" "WARN" "ERROR" "CRITICAL" "OFF"
CACHE LIBCUDF_LOGGING_LEVEL PROPERTY STRINGS "TRACE" "DEBUG" "INFO" "WARN" "ERROR" "CRITICAL"
"OFF"
)
message(VERBOSE "CUDF: RMM_LOGGING_LEVEL = '${RMM_LOGGING_LEVEL}'.")
message(VERBOSE "CUDF: LIBCUDF_LOGGING_LEVEL = '${LIBCUDF_LOGGING_LEVEL}'.")

if(NOT CUDF_GENERATED_INCLUDE_DIR)
set(CUDF_GENERATED_INCLUDE_DIR ${CUDF_BINARY_DIR})
Expand Down Expand Up @@ -597,6 +598,7 @@ add_library(
src/unary/nan_ops.cu
src/unary/null_ops.cu
src/utilities/default_stream.cpp
src/utilities/logger.cpp
src/utilities/traits.cpp
src/utilities/type_checks.cpp
src/utilities/type_dispatcher.cpp
Expand Down Expand Up @@ -677,8 +679,11 @@ if(NOT USE_NVTX)
target_compile_definitions(cudf PUBLIC NVTX_DISABLE)
endif()

# Define RMM logging level
target_compile_definitions(cudf PUBLIC "RMM_LOGGING_LEVEL=LIBCUDF_LOGGING_LEVEL")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should logging levels of RMM and cuDF be independently controlled?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming they do - how do we handle setting SPDLOG_ACTIVE_LEVEL? RMM sets it based on RMM_LOGGING_LEVEL, and we need to set it based on LIBCUDF_LOGGING_LEVEL.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. Good point. I don't have feelings on this, we can keep it all the same.

I think spdlog may have multiple ways to set the logging level, and compile-time options are only one of the methods. It would be hard to ensure that debug messages are compiled out while retaining runtime control over two different loggers. 😖

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the logging level can be set the runtime. This is what we use to set the level if LIBCUDF_LOGGING_LEVEL env var is set.

The CMake config var can be seen as minimal logging level that the build includes, since it literally undefines logging macros for level below its value (which is great for security/perf). AFAIK, the logging level for both libcudf will stay at INFO (or whatever is the default) even if CMake config var is TRACE/DEBUG.

I'm wary of having different SPDLOG_ACTIVE_LEVEL values in RMM and libcudf as it feels like possible ODR violation 🤷

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you would run into any issues. RMM only sets this for compiled components i.e. its tests and benchmarks. The main rmm code is header-only so there are no compiled components where SPDLOG_ACTIVE_LEVEL would be set to conflict with whatever libcudf sets.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this more we might need to make this PRIVATE.
If a downstream consumer uses cudf and rmm they can't specify an RMM logging level since we are specifying one already.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point, yeah that makes sense. I believe RMM sets this PUBLIC, but again it's only done in tests and benchmarks so it probably doesn't matter.

vuule marked this conversation as resolved.
Show resolved Hide resolved

# Define spdlog level
target_compile_definitions(cudf PUBLIC "SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_${RMM_LOGGING_LEVEL}")
target_compile_definitions(cudf PUBLIC "SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_${LIBCUDF_LOGGING_LEVEL}")

# Compile stringified JIT sources first
add_dependencies(cudf jitify_preprocess_run)
Expand Down
38 changes: 38 additions & 0 deletions cpp/doxygen/developer_guide/DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,44 @@ void trivial_types_only(T t){
}
```

# Logging

libcudf includes logging utilities (built on top of [spdlog](https://github.com/gabime/spdlog)
library), which should be used to log important events (e.g. user warnings). This utility can also
be used to log debug information, as long as the correct logging level is used. There are six macros
that should be used for logging at different levels:

* `CUDF_LOG_TRACE` - verbose debug messages (targeted at developers)
* `CUDF_LOG_DEBUG` - debug messages (targeted at developers)
* `CUDF_LOG_INFO` - information about rare events (e.g. once per run) that occur during normal
execution
* `CUDF_LOG_WARN` - user warnings about potentially unexpected behavior or deprecations
* `CUDF_LOG_ERROR` - recoverable errors
* `CUDF_LOG_CRITICAL` - unrecoverable errors (e.g. memory corruption)

By default, `TRACE`, `DEBUG` and `INFO` messages are excluded from the log. In addition, in public
builds, the code that logs at `TRACE` and `DEBUG` levels is compiled out. This prevents logging of
potentially sensitive data that might be done for debug purposes. Also, this allows developers to
include expensive computation in the trace/debug logs, as the overhead will not be present in the
public builds.
The minimum enabled logging level is `WARN`, and it can be modified in multiple ways:

* CMake configuration variable `LIBCUDF_LOGGING_LEVEL` - controls the minimum level of logging that
will be compiled in the build.
Available levels are `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `CRITICAL`, and `OFF`.
* Environment variable `LIBCUDF_LOGGING_LEVEL`, with the same values as the CMake variable.
The difference is that disabled levels are present in the build, but the messages are excluded from
the log.
vuule marked this conversation as resolved.
Show resolved Hide resolved
* Global logger object exposed via `cudf::logger()`. This API should not be used within libcudf to
vuule marked this conversation as resolved.
Show resolved Hide resolved
manipulate logging, its purpose is to allow upstream users to configure libcudf logging to fit their
application.

By default, logging messages are output to stderr.
Setting the environment variable `LIBCUDF_DEBUG_LOG_FILE` redirects the log to a file with the
specified path (can be relative to the current directory).
Upstream users can also manipulate `cudf::logger().sinks()` to add sinks or divert the log to
standard output or even a custom spdlog sink.

# Data Types

Columns may contain data of a number of types (see `enum class type_id` in `include/cudf/types.hpp`)
Expand Down
27 changes: 27 additions & 0 deletions cpp/include/cudf/detail/utilities/logger.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2023, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <cudf/utilities/logger.hpp>

// Log messages that require computation should only be used at level TRACE and DEBUG
#define CUDF_LOG_TRACE(...) SPDLOG_LOGGER_TRACE(&cudf::logger(), __VA_ARGS__)
#define CUDF_LOG_DEBUG(...) SPDLOG_LOGGER_DEBUG(&cudf::logger(), __VA_ARGS__)
#define CUDF_LOG_INFO(...) SPDLOG_LOGGER_INFO(&cudf::logger(), __VA_ARGS__)
#define CUDF_LOG_WARN(...) SPDLOG_LOGGER_WARN(&cudf::logger(), __VA_ARGS__)
#define CUDF_LOG_ERROR(...) SPDLOG_LOGGER_ERROR(&cudf::logger(), __VA_ARGS__)
#define CUDF_LOG_CRITICAL(...) SPDLOG_LOGGER_CRITICAL(&cudf::logger(), __VA_ARGS__)
46 changes: 46 additions & 0 deletions cpp/include/cudf/utilities/logger.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2023, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <spdlog/spdlog.h>

namespace cudf {

/**
* @brief Returns the global logger.
*
* This is a global instance of a spdlog logger. It can be used to configure logging behavior in
* libcudf.
*
* Examples:
* @code{.cpp}
* // Turn off logging at runtime
* cudf::logger().set_level(spdlog::level::off);
* // Add a stdout sink to the logger
* cudf::logger().sinks().push_back(std::make_shared<spdlog::sinks::stdout_sink_mt>());
* // Replace the default sink
* cudf::logger().sinks() ={std::make_shared<spdlog::sinks::stderr_sink_mt>()};
* @endcode
*
* Note: Changes to the sinks are not thread safe and should only be done during global
* initialization.
*
* @return spdlog::logger& The logger.
*/
spdlog::logger& logger();

} // namespace cudf
6 changes: 0 additions & 6 deletions cpp/src/io/utilities/config_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@

namespace cudf::io::detail {

std::string getenv_or(std::string const& env_var_name, std::string_view default_val)
{
auto const env_val = std::getenv(env_var_name.c_str());
return std::string{(env_val == nullptr) ? default_val : env_val};
}

namespace cufile_integration {

namespace {
Expand Down
11 changes: 10 additions & 1 deletion cpp/src/io/utilities/config_utils.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022, NVIDIA CORPORATION.
* Copyright (c) 2021-2023, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,6 +15,8 @@
*/
#pragma once

#include <cudf/detail/utilities/logger.hpp>

#include <sstream>
#include <string>

Expand All @@ -28,6 +30,13 @@ template <typename T>
T getenv_or(std::string_view env_var_name, T default_val)
{
auto const env_val = std::getenv(env_var_name.data());
if (env_val != nullptr) {
CUDF_LOG_INFO("Environment variable {} read as {}", env_var_name, env_val);
} else {
CUDF_LOG_INFO(
"Environment variable {} is not set, using default value {}", env_var_name, default_val);
}

if (env_val == nullptr) { return default_val; }

std::stringstream sstream(env_val);
Expand Down
11 changes: 8 additions & 3 deletions cpp/src/io/utilities/hostdevice_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@

#include <variant>

inline bool hostdevice_vector_uses_pageable_buffer()
vyasr marked this conversation as resolved.
Show resolved Hide resolved
{
static bool const use_pageable =
cudf::io::detail::getenv_or("LIBCUDF_IO_PREFER_PAGEABLE_TMP_MEMORY", 0);
return use_pageable;
}

/**
* @brief A helper class that wraps fixed-length device memory for the GPU, and
* a mirror host pinned memory for the CPU.
Expand All @@ -56,9 +63,7 @@ class hostdevice_vector {
{
CUDF_EXPECTS(initial_size <= max_size, "initial_size cannot be larger than max_size");

auto const use_pageable_buffer =
cudf::io::detail::getenv_or("LIBCUDF_IO_PREFER_PAGEABLE_TMP_MEMORY", 0);
if (use_pageable_buffer) {
if (hostdevice_vector_uses_pageable_buffer()) {
h_data_owner = thrust::host_vector<T>();
} else {
h_data_owner = thrust::host_vector<T, cudf::detail::pinned_allocator<T>>();
Expand Down
81 changes: 81 additions & 0 deletions cpp/src/utilities/logger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2023, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <cudf/utilities/error.hpp>
#include <cudf/utilities/logger.hpp>

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

#include <string>

namespace {

/**
* @brief Creates a sink for libcudf logging.
*
* Returns a file sink if the file name has been specified, otherwise returns a stderr sink.
*/
[[nodiscard]] spdlog::sink_ptr make_libcudf_sink()
{
if (auto filename = std::getenv("LIBCUDF_DEBUG_LOG_FILE"); filename != nullptr) {
return std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
} else {
return std::make_shared<spdlog::sinks::stderr_sink_mt>();
}
}

/**
* @brief Converts the level name into the `spdlog` level enum.
*/
[[nodiscard]] spdlog::level::level_enum libcudf_log_level()
{
auto const env_level = std::getenv("LIBCUDF_LOGGING_LEVEL");
if (env_level == nullptr) { return spdlog::level::warn; }
vuule marked this conversation as resolved.
Show resolved Hide resolved

auto const env_lvl_str = std::string(env_level);
if (env_lvl_str == "TRACE") return spdlog::level::trace;
if (env_lvl_str == "DEBUG") return spdlog::level::debug;
if (env_lvl_str == "INFO") return spdlog::level::info;
if (env_lvl_str == "WARN") return spdlog::level::warn;
if (env_lvl_str == "ERROR") return spdlog::level::err;
if (env_lvl_str == "CRITICAL") return spdlog::level::critical;
if (env_lvl_str == "OFF") return spdlog::level::off;

CUDF_FAIL("Invalid value for LIBCUDF_LOGGING_LEVEL environment variable");
}

/**
* @brief Simple wrapper around a spdlog::logger that performs cuDF-specific initialization.
*/
struct logger_wrapper {
vuule marked this conversation as resolved.
Show resolved Hide resolved
spdlog::logger logger_;

logger_wrapper() : logger_{"CUDF", make_libcudf_sink()}
{
logger_.set_pattern("[%6t][%H:%M:%S:%f][%-6l] %v");
logger_.set_level(libcudf_log_level());
logger_.flush_on(spdlog::level::warn);
}
};

} // namespace

spdlog::logger& cudf::logger()
{
static logger_wrapper wrapped{};
return wrapped.logger_;
}
1 change: 1 addition & 0 deletions cpp/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ ConfigureTest(
utilities_tests/column_utilities_tests.cpp
utilities_tests/column_wrapper_tests.cpp
utilities_tests/lists_column_wrapper_tests.cpp
utilities_tests/logger_tests.cpp
utilities_tests/default_stream_tests.cpp
utilities_tests/type_check_tests.cpp
)
Expand Down
Loading