Skip to content

Commit

Permalink
Support building with local dependencies (no Hunter)
Browse files Browse the repository at this point in the history
Add support for finding jaeger-cpp's dependencies via the normal local
CMake package discovery mechanism of Find modules.

Improves jaegertracing#38 Offline builds

This introduces support for building with

   cmake -DHUNTER_ENABLED=0

Limitations:

  - Requires a locally installed Thrift 0.9.2 or 0.9.3 EXACTLY,
    not newer or older. These versions are not widely packaged
    so a local install is necessary.  (jaegertracing#45)

  - Requires nlohmann json 2.1.0 or newer, which is not widely
    packaged in Linux distros. Install a local copy. (jaegertracing#47)

Signed-off-by: Craig Ringer <craig@2ndquadrant.com>
  • Loading branch information
ringerc committed Jan 31, 2018
1 parent fcb90ce commit 18899ba
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 268 deletions.
40 changes: 32 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,26 @@ find_package(Boost ${hunter_config} REQUIRED ${boost_components})
list(APPEND package_deps Boost)

hunter_add_package(thrift)
find_package(thrift ${hunter_config} REQUIRED)
find_package(thrift 0.9.2 ${hunter_config} REQUIRED)
if(HUNTER_ENABLED)
list(APPEND LIBS thrift::thrift_static)
else()
list(APPEND LIBS ${THRIFT_LIBRARIES})
list(APPEND LIBS ${thrift_LIBRARIES})
endif()
list(APPEND package_deps thrift)
if(thrift_VERSION VERSION_GREATER "0.9.3")
message(WARNING "jaeger-cpp is only known to work with Thrift 0.9.2 and Thrift 0.9.3")
endif()

hunter_add_package(opentracing-cpp)
# Not `${hunter_config}` because OpenTracing provides its own
# OpenTracingConfig.cmake file
find_package(OpenTracing CONFIG REQUIRED)
list(APPEND LIBS OpenTracing::opentracing-static)
find_package(OpenTracing ${hunter_config} REQUIRED)
list(APPEND LIBS OpenTracing::opentracing)
list(APPEND package_deps opentracing-cpp)

hunter_add_package(nlohmann_json)
find_package(nlohmann_json CONFIG REQUIRED)
list(APPEND LIBS nlohmann_json)
find_package(nlohmann_json 2.1.0 ${hunter_config} REQUIRED)
list(APPEND package_deps nlohmann_json)

option(JAEGERTRACING_COVERAGE "Build with coverage" $ENV{COVERAGE})
Expand All @@ -78,7 +80,7 @@ if(JAEGERTRACING_WITH_YAML_CPP)
hunter_add_package(yaml-cpp)
# Not `${hunter_config}` because yaml-cpp provides its own
# yaml-cpp-config.cmake file
find_package(yaml-cpp CONFIG REQUIRED)
find_package(yaml-cpp ${hunter_config} REQUIRED)
if(HUNTER_ENABLED)
list(APPEND LIBS yaml-cpp::yaml-cpp)
else()
Expand Down Expand Up @@ -243,6 +245,13 @@ target_link_libraries(jaegertracing-static ${LIBS})
set_target_properties(jaegertracing-static PROPERTIES
OUTPUT_NAME jaegertracing)

SET(JAEGERTRACING_NLOHMANN_UNQUALIFIED_PATH 0)
if (nlohmann_json_INCLUDE_NAME STREQUAL "json.hpp")
SET(JAEGERTRACING_NLOHMANN_UNQUALIFIED_PATH 1)
endif()
set(JAEGERTRACING_NLOHMANN_UNQUALIFIED_PATH ${JAEGERTRACING_NLOHMANN_UNQUALIFIED_PATH}
CACHE BOOL "does nlohmann json lack the nlohmann/ path prefix")

configure_file(
src/jaegertracing/Constants.h.in
src/jaegertracing/Constants.h
Expand Down Expand Up @@ -278,18 +287,33 @@ if(BUILD_TESTING)
src/jaegertracing/utils/ErrorUtilTest.cpp
src/jaegertracing/utils/RateLimiterTest.cpp
src/jaegertracing/utils/UDPClientTest.cpp)

list(APPEND TEST_LIBS testutils ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY} pthread)

# Shared test
add_executable(UnitTest ${TEST_SRC})
target_compile_definitions(UnitTest PUBLIC
GTEST_HAS_TR1_TUPLE=0
GTEST_USE_OWN_TR1_TUPLE=0)
target_link_libraries(
UnitTest testutils GTest::main jaegertracing-static ${LIBS})
UnitTest ${LIBS} ${TEST_LIBS} jaegertracing)
add_test(NAME UnitTest COMMAND UnitTest)

# Also make sure static linkage works
add_executable(UnitTestStatic ${TEST_SRC})
target_compile_definitions(UnitTestStatic PUBLIC
GTEST_HAS_TR1_TUPLE=0
GTEST_USE_OWN_TR1_TUPLE=0)
target_link_libraries(
UnitTestStatic ${LIBS} ${TEST_LIBS} jaegertracing-static)
add_test(NAME UnitTestStatic COMMAND UnitTestStatic)

if(JAEGERTRACING_COVERAGE)
setup_target_for_coverage(NAME UnitTestCoverage
EXECUTABLE UnitTest
DEPENDENCIES UnitTest)
endif()

endif()

# Installation (https://github.com/forexample/package-example)
Expand Down
175 changes: 0 additions & 175 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,181 +3,6 @@
# cpp-client
C++ OpenTracing binding for Jaeger

jaeger-cpp is a client library to emit trace information for the Jaeger trace
collector <http://jaeger.readthedocs.io>.

It's written in C++11 and implements the OpenTracing API; see [ot-url] and
https://github.com/opentracing/opentracing-cpp.

This library is just an agent. It sends UDP packets to a trace collector, which
does all the real work. Agent libraries also exist for other languages like
Java and Go.

## Quick build

To do a test build and install in $HOME/jaeger-cpp-client:

git clone https://github.com/jaegertracing/cpp-client.git jaeger-cpp-client
mkdir jaeger-cpp-build
cd jaeger-cpp-build
cmake -DCMAKE_INSTALL_PREFIX=$HOME/jaeger-cpp-client ../jaeger-cpp-client
make
make install

## Usage

To use jaeger-cpp in your code you mostly use the OpenTracing C++ APIs. Your code
must instantiate and configure the Jaeger tracer, but the rest is the same as for
any other OpenTracing backend.

The simplest way to instantiate and configure a Jaeger tracer is to use the
yaml configuration support to create the tracer. Then set it as the OpenTracing
global tracer. Typically a caller would read the configuration in from a file,
but as an example:

#include <jaegertracing/Tracer.h>

void initTracing()
{
constexpr auto kConfigYAML = R"cfg(
disabled: false
sampler:
type: const
param: 1
reporter:
queueSize: 100
bufferFlushInterval: 10
logSpans: false
localAgentHostPort: 127.0.0.1:6831
headers:
jaegerDebugHeader: debug-id
jaegerBaggageHeader: baggage
TraceContextHeaderName: trace-id
traceBaggageHeaderPrefix: "testctx-"
baggage_restrictions:
denyBaggageOnInitializationFailure: false
hostPort: 127.0.0.1:5778
refreshInterval: 60
)cfg";

const auto config = jaegertracing::Config::parse(YAML::Load(kConfigYAML));
auto tracer = jaegertracing::Tracer::make("postgresql", config);
opentracing::Tracer::InitGlobal(tracer);
}

void teardownTracing()
{
opentracing::Tracer::Global()->Close
}

A C++-language configuration facility is also-available; see
`jaegertracing/Config.h` and the jaeger-cpp tests. A trivial example:

auto config = jaegertracing::Config(
false,
jaegertracing::samplers::Config(jaegertracing::kSamplerTypeConst, 1),
jaegertracing::reporters::Config(
jaegertracing::reporters::Config::kDefaultQueueSize,
std::chrono::seconds(1), true));


Once instantiated, simple traces may be performed with the usual opentracing
facilities e.g.:

#include <chrono>
#include <thread>

int main()
{
initTracing();

auto tracer = opentracing::Tracer::Global();
auto span = tracer->StartSpan("abc");
std::this_thread::sleep_for(std::chrono::milliseconds{10});
span->Finish();
std::this_thread::sleep_for(std::chrono::seconds{5});

teardownTracing();
}

The Jaeger tracing instance usually lives as long as the traced process.

The tracer should be closed before program exit so it can flush its buffers,
so traces aren't lost.

### Usage from C

It's possible to use `jaeger-cpp` from C with appropriate `extern "C"` thunks
and care around resource lifetime management etc. A real world example is the
support for opentracing and jaeger in ngnix; see
https://github.com/opentracing-contrib/nginx-opentracing . A simplified example
would be welcomed.

### Usage from C++98

No examples currently exist. It'll at least be possible to do so via an "extern
C" thunking layer and C-style coding.

## Dependencies
---

Compiling jaeger-cpp requires:

* opentracing-cpp <https://github.com/opentracing/opentracing-cpp>
* nlohmann json (2.1.0 or greater) <https://github.com/nlohmann/json>
* yaml-cpp <https://github.com/jbeder/yaml-cpp>
* boost regex <http://www.boost.org>
* Apache thrift <https://thrift.apache.org/>
* Google Test <https://github.com/google/googletest>

### Automatic dependencies - Hunter

By default, Jaeger uses Hunter <http://hunter.sh> to download and build
required dependencies (including opentracing) from the Internet as part of the
CMake build preparation.

Hunter does not install these dependencies as part of `jaeger-cpp`'s `make
install` target, so applications that wish to use a Hunter-built jaeger-cpp
should also use Hunter.

### Locally installed dependencies

To perform a traditional installation to the local system, install all the
above dependencies, then build jaeger-cpp with `-DHUNTER_ENABLED=0` and
`make install` as usual.

Specify the install directory with the `CMAKE_INSTALL_PREFIX` cmake variable.
The default is platform dependent, but `/usr/local` on most UNIXes.

#### Fedora

These dependencies are all in Fedora 25+ except for nlohmann json 2.1.x.

Install with:

sudo dnf install yaml-cpp-devel boost-devel thrift-devel gtest-devel

There's a nlohmann json package `json-cpp` too, but it's too old so you'll
have to compile it yourself.

## Build options

CMake flags available for setting with `-D`:

* `HUNTER_ENABLED`: set to 0 to disable the use of the Hunter dependency
fetching/building tool to download jaeger-cpp's dependencies. Enabled by
defualt.

* `BUILD_TESTING`: set to 0 to disable test compilation

* `JAEGERTRACING_WITH_YAML_CPP`: disable yaml configuration support

* `CMAKE_INSTALL_PREFIX`: base directory to install `jaeger-cpp`

Most other cmake standard variables
<https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html> are
supported.

[ci-img]: https://travis-ci.org/jaegertracing/cpp-client.svg?branch=master
[ci]: https://travis-ci.org/jaegertracing/cpp-client
[cov-img]: https://codecov.io/gh/jaegertracing/cpp-client/branch/master/graph/badge.svg
Expand Down
58 changes: 58 additions & 0 deletions cmake/Findnlohmann_json.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Find jsoncpp
#
# Find the nlohmann json header
#
# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH
#
# This module defines
#
# nlohmann_json_INCLUDE_DIR, where to find header, etc.
#
# nlohmann_json_FOUND, If false, do not try to use jsoncpp.
#
# nlohmann_json_LIBRARIES, empty since no linkage is required, this
# is a header-only library.
#
# nlohmann_json_INCLUDE_NAME, the actual header name. You only have
# to use this if you want to support 2.0.x which installs
# a top-level json.hpp instead of nlohmann/json.hpp
#

# only look in default directories
set(nlohmann_json_INCLUDE_NAME "nlohmann/json.hpp")
find_path(
nlohmann_json_INCLUDE_DIR
NAMES "${nlohmann_json_INCLUDE_NAME}"
DOC "nlohmann json include dir"
)

if (NOT nlohmann_json_INCLUDE_DIR)
set(nlohmann_json_INCLUDE_NAME "json.hpp")
find_path(
nlohmann_json_INCLUDE_DIR
NAMES "${nlohmann_json_INCLUDE_NAME}"
)
endif()

set(nlohmann_json_INCLUDE_NAME ${nlohmann_json_INCLUDE_NAME} CACHE STRING "nlohmann header file name")

set(nlohmann_json_LIBRARIES NOTFOUND CACHE STRING "no library is required by nlohmann_json")

# Version detection. Unfortunately the header doesn't expose a proper version
# define.
if (nlohmann_json_INCLUDE_DIR AND nlohmann_json_INCLUDE_NAME)
file(READ "${nlohmann_json_INCLUDE_DIR}/${nlohmann_json_INCLUDE_NAME}" NL_HDR_TXT LIMIT 1000)
if (NL_HDR_TXT MATCHES "version ([0-9]+\.[0-9]+\.[0-9]+)")
set(nlohmann_json_VERSION "${CMAKE_MATCH_1}")
endif()
endif()

set(nlohmann_json_VERSION "${nlohmann_json_VERSION}" CACHE STRING "nlohmann header version")

# handle the QUIETLY and REQUIRED arguments and set nlohmann_json_FOUND to TRUE
# if all listed variables are TRUE, hide their existence from configuration view
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
nlohmann_json
REQUIRED_VARS nlohmann_json_INCLUDE_DIR nlohmann_json_INCLUDE_NAME
VERSION_VAR nlohmann_json_VERSION)
Loading

0 comments on commit 18899ba

Please sign in to comment.