Skip to content

Commit

Permalink
ARROW-3187: [C++] Add support for using glog (Google logging library)
Browse files Browse the repository at this point in the history
1. `glog` provides richer information.
2. `glog` can print good call stack while crashing, which is very helpful for debugging.
3. Make logging pluggable with `glog` or original log using a macro. Users can enable/disable `glog` using the cmake option `ARROW_USE_GLOG`.

Author: Yuhong Guo <yuhong.gyh@antfin.com>
Author: Wes McKinney <wesm+git@apache.org>

Closes #2522 from guoyuhong/glog and squashes the following commits:

b359640 <Yuhong Guo> Revert some useless changes.
38560c0 <Yuhong Guo> Change back the test code to fix logging-test
e3203a5 <Wes McKinney> Some fixes, run logging-test
4a9d172 <Wes McKinney> Fix Flatbuffers download url
f364308 <Yuhong Guo> Add test code to only include glog lib and init it without other use.
c8269fd <Yuhong Guo> Change ARROW_JEMALLOC_LINK_LIBS setting to ARROW_LINK_LIBS
34e6841 <Yuhong Guo> Add pthread
48afa34 <Yuhong Guo> Address comment
12f9ba7 <Yuhong Guo> Disable glog from ARROW_BUILD_TOOLCHAIN
62f2000 <Yuhong Guo> Add -pthread to glog
673dbeb <Yuhong Guo> Try to fix ci FAILURE
69c1e79 <Yuhong Guo> Add pthread for glog
fbe9cc9 <Yuhong Guo> Change Thirdpart to use EP_CXX_FLAGS
6f4d1b8 <Yuhong Guo> Add lib64 to lib path suffix.
84532e3 <Yuhong Guo> Add glog to Dockerfile
ccc03cb <Yuhong Guo> Fix a bug
7bacd53 <Yuhong Guo> Add LICENSE information.
9a3834c <Yuhong Guo> Enable glog and fix building error
2b1f7e0 <Yuhong Guo> Turn glog off.
7d92091 <Yuhong Guo> Hide glog symbols from libarrow.so
a6ff671 <Yuhong Guo> Support offline build of glog
14865ee <Yuhong Guo> Try to fix MSVC building failure
53ceceb <Yuhong Guo> Change log level to enum and refine code
09c6af7 <Yuhong Guo> Enable glog in plasma
  • Loading branch information
guoyuhong authored and wesm committed Sep 19, 2018
1 parent 92a2e6a commit 7104d64
Show file tree
Hide file tree
Showing 18 changed files with 651 additions and 93 deletions.
20 changes: 20 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -696,3 +696,23 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

--------------------------------------------------------------------------------

cpp/src/arrow/util/logging.cc, cpp/src/arrow/util/logging.h and
cpp/src/arrow/util/logging-test.cc are adapted from
Ray Project (https://github.com/ray-project/ray) (Apache 2.0).

Copyright (c) 2016 Ray Project (https://github.com/ray-project/ray)

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.
1 change: 1 addition & 0 deletions ci/travis_install_toolchain.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ if [ ! -e $CPP_TOOLCHAIN ]; then
snappy \
thrift-cpp=0.11.0 \
zlib \
glog \
zstd
fi
11 changes: 11 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ Pass multiple labels by dividing with semicolons")
"If off, 'quiet' flags will be passed to linting tools"
OFF)

option(ARROW_USE_GLOG
"Build libraries with glog support for pluggable logging"
ON)

if (MSVC)
option(ARROW_USE_CLCACHE
"Use clcache if available"
Expand Down Expand Up @@ -302,6 +306,8 @@ endif()
if (MSVC)
# ORC doesn't build on windows
set(ARROW_ORC OFF)
# Plasma using glog is not fully tested on windows.
set(ARROW_USE_GLOG OFF)
endif()

if(ARROW_ORC)
Expand Down Expand Up @@ -642,6 +648,11 @@ if (ARROW_ORC)
orc)
endif()

if (ARROW_USE_GLOG)
#add_definitions(-DARROW_USE_GLOG)
SET(ARROW_STATIC_LINK_LIBS glog_static ${ARROW_STATIC_LINK_LIBS})
endif()

if (ARROW_STATIC_LINK_LIBS)
add_dependencies(arrow_dependencies ${ARROW_STATIC_LINK_LIBS})
endif()
Expand Down
92 changes: 92 additions & 0 deletions cpp/cmake_modules/FindGLOG.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#
# 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.
#
# Tries to find GLog headers and libraries.
#
# Usage of this module as follows:
#
# find_package(GLOG)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# GLOG_HOME - When set, this path is inspected instead of standard library
# locations as the root of the GLog installation.
# The environment variable GLOG_HOME overrides this veriable.
#
# This module defines
# GLOG_INCLUDE_DIR, directory containing headers
# GLOG_STATIC_LIB, path to libglog.a
# GLOG_FOUND, whether glog has been found

if( NOT "${GLOG_HOME}" STREQUAL "")
file( TO_CMAKE_PATH "${GLOG_HOME}" _native_path )
list( APPEND _glog_roots ${_native_path} )
endif()

message(STATUS "GLOG_HOME: ${GLOG_HOME}")
# Try the parameterized roots, if they exist
if ( _glog_roots )
set (lib_dirs "lib")
if (EXISTS "${_glog_roots}/lib64")
set (lib_dirs "lib64" ${lib_dirs})
endif ()

find_path( GLOG_INCLUDE_DIR NAMES glog/logging.h
PATHS ${_glog_roots} NO_DEFAULT_PATH
PATH_SUFFIXES "include" )
find_library( GLOG_LIBRARIES NAMES glog
PATHS ${_glog_roots} NO_DEFAULT_PATH
PATH_SUFFIXES ${lib_dirs})
else ()
find_path( GLOG_INCLUDE_DIR NAMES glog/logging.h )
find_library( GLOG_LIBRARIES NAMES glog )
endif ()


if (GLOG_INCLUDE_DIR AND GLOG_LIBRARIES)
set(GLOG_FOUND TRUE)
get_filename_component( GLOG_LIBS ${GLOG_LIBRARIES} PATH )
set(GLOG_LIB_NAME glog)
set(GLOG_STATIC_LIB ${GLOG_LIBS}/${CMAKE_STATIC_LIBRARY_PREFIX}${GLOG_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX})
set(GLOG_SHARED_LIB ${GLOG_LIBS}/${CMAKE_SHARED_LIBRARY_PREFIX}${GLOG_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX})
else ()
set(GLOG_FOUND FALSE)
endif ()

if (GLOG_FOUND)
if (NOT GLOG_FIND_QUIETLY)
message(STATUS "Found the GLog library: ${GLOG_LIBRARIES}")
endif ()
else ()
if (NOT GLOG_FIND_QUIETLY)
set(GLOG_ERR_MSG "Could not find the GLog library. Looked in ")
if ( _glog_roots )
set(GLOG_ERR_MSG "${GLOG_ERR_MSG} ${_glog_roots}.")
else ()
set(GLOG_ERR_MSG "${GLOG_ERR_MSG} system search paths.")
endif ()
if (GLOG_FIND_REQUIRED)
message(FATAL_ERROR "${GLOG_ERR_MSG}")
else (GLOG_FIND_REQUIRED)
message(STATUS "${GLOG_ERR_MSG}")
endif (GLOG_FIND_REQUIRED)
endif ()
endif ()

mark_as_advanced(
GLOG_INCLUDE_DIR
GLOG_LIBS
GLOG_LIBRARIES
GLOG_STATIC_LIB
)
69 changes: 68 additions & 1 deletion cpp/cmake_modules/ThirdpartyToolchain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ if (NOT "$ENV{ARROW_BUILD_TOOLCHAIN}" STREQUAL "")
set(JEMALLOC_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")
set(LZ4_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")
# orc disabled as it's not in conda-forge (but in Anaconda with an incompatible ABI)
# set(ORC_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")
# set(ORC_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")
set(PROTOBUF_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")
set(RAPIDJSON_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")
set(SNAPPY_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")
set(THRIFT_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")
set(ZLIB_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")
set(ZSTD_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")
set(GLOG_HOME "$ENV{ARROW_BUILD_TOOLCHAIN}")

if (NOT DEFINED ENV{BOOST_ROOT})
# Since we have to set this in the environment, we check whether
Expand Down Expand Up @@ -106,6 +107,10 @@ if (DEFINED ENV{ZSTD_HOME})
set(ZSTD_HOME "$ENV{ZSTD_HOME}")
endif()

if (DEFINED ENV{GLOG_HOME})
set(GLOG_HOME "$ENV{GLOG_HOME}")
endif()

# ----------------------------------------------------------------------
# Some EP's require other EP's

Expand Down Expand Up @@ -238,6 +243,12 @@ else()
set(ZSTD_SOURCE_URL "https://github.com/facebook/zstd/archive/v${ZSTD_VERSION}.tar.gz")
endif()

if (DEFINED ENV{ARROW_GLOG_URL})
set(GLOG_SOURCE_URL "$ENV{ARROW_GLOG_URL}")
else()
set(GLOG_SOURCE_URL "https://github.com/google/glog/archive/v${GLOG_VERSION}.tar.gz")
endif()

# ----------------------------------------------------------------------
# ExternalProject options

Expand Down Expand Up @@ -1261,3 +1272,59 @@ if (THRIFT_VENDORED)
endif()

endif() # ARROW_HIVESERVER2

if (ARROW_USE_GLOG)
# ----------------------------------------------------------------------
# GLOG

if("${GLOG_HOME}" STREQUAL "")
set(GLOG_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/glog_ep-prefix/src/glog_ep")
set(GLOG_INCLUDE_DIR "${GLOG_BUILD_DIR}/include")
set(GLOG_STATIC_LIB "${GLOG_BUILD_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}glog${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(GLOG_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
set(GLOG_CMAKE_C_FLAGS "${EP_C_FLAGS} -fPIC")
if (PTHREAD_LIBRARY)
set(GLOG_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -pthread")
set(GLOG_CMAKE_C_FLAGS "${EP_C_FLAGS} -fPIC -pthread")
endif()
message(STATUS "GLOG_CMAKE_CXX_FLAGS: ${GLOG_CMAKE_CXX_FLAGS}")
message(STATUS "CMAKE_CXX_FLAGS in glog: ${GLOG_CMAKE_CXX_FLAGS}")

if(APPLE)
# If we don't set this flag, the binary built with 10.13 cannot be used in 10.12.
set(GLOG_CMAKE_CXX_FLAGS "${GLOG_CMAKE_CXX_FLAGS} -mmacosx-version-min=10.9")
endif()

set(GLOG_CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${GLOG_BUILD_DIR}
-DBUILD_SHARED_LIBS=OFF
-DBUILD_TESTING=OFF
-DWITH_GFLAGS=OFF
-DCMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}=${GLOG_CMAKE_CXX_FLAGS}
-DCMAKE_C_FLAGS_${UPPERCASE_BUILD_TYPE}=${GLOG_CMAKE_C_FLAGS}
-DCMAKE_CXX_FLAGS=${GLOG_CMAKE_CXX_FLAGS})
message(STATUS "Glog version: ${GLOG_VERSION}")
ExternalProject_Add(glog_ep
URL ${GLOG_SOURCE_URL}
BUILD_IN_SOURCE 1
BUILD_BYPRODUCTS "${GLOG_STATIC_LIB}"
CMAKE_ARGS ${GLOG_CMAKE_ARGS}
${EP_LOG_OPTIONS})

set(GLOG_VENDORED 1)
else()
find_package(GLOG REQUIRED)
set(GLOG_VENDORED 0)
endif()

message(STATUS "Glog include dir: ${GLOG_INCLUDE_DIR}")
message(STATUS "Glog static library: ${GLOG_STATIC_LIB}")

include_directories(SYSTEM ${GLOG_INCLUDE_DIR})
ADD_THIRDPARTY_LIB(glog_static
STATIC_LIB ${GLOG_STATIC_LIB})

if (GLOG_VENDORED)
add_dependencies(glog_static glog_ep)
endif()
endif()
1 change: 1 addition & 0 deletions cpp/src/arrow/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ set(ARROW_SRCS
util/io-util.cc
util/key_value_metadata.cc
util/thread-pool.cc
util/logging.cc
)

if ("${COMPILER_FAMILY}" STREQUAL "clang")
Expand Down
2 changes: 2 additions & 0 deletions cpp/src/arrow/symbols.map
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
# Statically linked C++ dependencies
boost::*;
google::*;
# glog
*MakeCheckOpValueString*;
orc::*;
snappy::*;
};
Expand Down
1 change: 1 addition & 0 deletions cpp/src/arrow/util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ ADD_ARROW_TEST(parsing-util-test)
ADD_ARROW_TEST(stl-util-test)
ADD_ARROW_TEST(thread-pool-test)
ADD_ARROW_TEST(lazy-test)
ADD_ARROW_TEST(logging-test)

ADD_ARROW_BENCHMARK(bit-util-benchmark)
ADD_ARROW_BENCHMARK(decimal-benchmark)
Expand Down
109 changes: 109 additions & 0 deletions cpp/src/arrow/util/logging-test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 <chrono>
#include <cstdlib>
#include <iostream>

#include "arrow/util/logging.h"
#include "gtest/gtest.h"

// This code is adapted from
// https://github.com/ray-project/ray/blob/master/src/ray/util/logging_test.cc.

namespace arrow {

int64_t current_time_ms() {
std::chrono::milliseconds ms_since_epoch =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch());
return ms_since_epoch.count();
}

// This is not really test.
// This file just print some information using the logging macro.

void PrintLog() {
ARROW_LOG(DEBUG) << "This is the"
<< " DEBUG"
<< " message";
ARROW_LOG(INFO) << "This is the"
<< " INFO message";
ARROW_LOG(WARNING) << "This is the"
<< " WARNING message";
ARROW_LOG(ERROR) << "This is the"
<< " ERROR message";
ARROW_CHECK(true) << "This is a ARROW_CHECK"
<< " message but it won't show up";
// The following 2 lines should not run since it will cause program failure.
// ARROW_LOG(FATAL) << "This is the FATAL message";
// ARROW_CHECK(false) << "This is a ARROW_CHECK message but it won't show up";
}

TEST(PrintLogTest, LogTestWithoutInit) {
// Without ArrowLog::StartArrowLog, this should also work.
PrintLog();
}

TEST(PrintLogTest, LogTestWithInit) {
// Test empty app name.
ArrowLog::StartArrowLog("", ArrowLogLevel::ARROW_DEBUG);
PrintLog();
ArrowLog::ShutDownArrowLog();
}

// This test will output large amount of logs to stderr, should be disabled in travis.
TEST(LogPerfTest, PerfTest) {
ArrowLog::StartArrowLog("/fake/path/to/appdire/LogPerfTest", ArrowLogLevel::ARROW_ERROR,
"/tmp/");
int rounds = 10000;

int64_t start_time = current_time_ms();
for (int i = 0; i < rounds; ++i) {
ARROW_LOG(DEBUG) << "This is the "
<< "ARROW_DEBUG message";
}
int64_t elapsed = current_time_ms() - start_time;
std::cout << "Testing DEBUG log for " << rounds << " rounds takes " << elapsed << " ms."
<< std::endl;

start_time = current_time_ms();
for (int i = 0; i < rounds; ++i) {
ARROW_LOG(ERROR) << "This is the "
<< "RARROW_ERROR message";
}
elapsed = current_time_ms() - start_time;
std::cout << "Testing ARROW_ERROR log for " << rounds << " rounds takes " << elapsed
<< " ms." << std::endl;

start_time = current_time_ms();
for (int i = 0; i < rounds; ++i) {
ARROW_CHECK(i >= 0) << "This is a ARROW_CHECK "
<< "message but it won't show up";
}
elapsed = current_time_ms() - start_time;
std::cout << "Testing ARROW_CHECK(true) for " << rounds << " rounds takes " << elapsed
<< " ms." << std::endl;
ArrowLog::ShutDownArrowLog();
}

} // namespace arrow

int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Loading

0 comments on commit 7104d64

Please sign in to comment.