Skip to content
This repository has been archived by the owner on Jan 26, 2024. It is now read-only.

Add support for dynamic loading. #45

Merged
merged 52 commits into from
Feb 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
6b8bc2b
Dynamic load changes.
rnburn Nov 2, 2017
4030ec8
Remove default timestamping.
rnburn Nov 2, 2017
ed6e121
Add dynamic load functions.
rnburn Nov 5, 2017
ae66b6b
Add dynamic load code.
rnburn Nov 5, 2017
c184ee5
Merge branch 'master' of github.com:rnburn/opentracing-cpp into dlopen
rnburn Dec 5, 2017
9ad435f
Use factory interface for dynamic loading.
rnburn Dec 7, 2017
fc45b0e
Separate TracerFactory from dynamic loading.
rnburn Dec 11, 2017
920b2a0
Support specifying an error_code when dynamic load fails.
rnburn Dec 12, 2017
931b239
Allow DynamicTracingLibraryHandle to be default constructible.
rnburn Dec 13, 2017
b037065
Add documentation for make_opentracing_factory.
rnburn Dec 18, 2017
5368976
Comment dynamic_load interface.
rnburn Dec 18, 2017
3e20e42
Document tracer_factory.h
rnburn Dec 18, 2017
c41edee
Fix order in destructors.
rnburn Dec 19, 2017
16ad19b
Correct typo.
rnburn Dec 20, 2017
75b1da5
Merge branch 'master' of https://github.com/opentracing/opentracing-c…
rnburn Jan 19, 2018
4ad8a70
Remove windows stub.
rnburn Jan 19, 2018
6821cd6
Update naming convention to be more consistent.
rnburn Jan 19, 2018
ff26d65
Run clang-format.
rnburn Jan 19, 2018
c5bf3c3
Merge branch 'master' of https://github.com/opentracing/opentracing-c…
rnburn Jan 23, 2018
5955aec
Correct typo.
rnburn Jan 23, 2018
99a8f57
Add dynamic loading support to mocktracer.
rnburn Jan 23, 2018
0484533
Add tests for dynamic loading.
rnburn Jan 24, 2018
365f7ea
Run clang-format.
rnburn Jan 24, 2018
749ed80
Test for weak symbols.
rnburn Jan 25, 2018
09ed628
Run clang-format.
rnburn Jan 25, 2018
5daa522
Fix bazel build for dynamic loading support.
rnburn Jan 25, 2018
43cedf7
link 3rd party libraries in statically.
rnburn Jan 30, 2018
61f959a
Correct include guards.
rnburn Jan 31, 2018
83d97b6
Rearrange base64 code.
rnburn Jan 31, 2018
9c5c8c6
Add missing base64 code.
rnburn Jan 31, 2018
2123ae7
Include apache license.
rnburn Jan 31, 2018
4262eba
Correct typo.
rnburn Jan 31, 2018
c6dad55
Writing manual serialization code.
rnburn Feb 2, 2018
2502ce8
Add plugin library.
rnburn Feb 2, 2018
e3b1648
Add serialization for SpanData.
rnburn Feb 2, 2018
a53744b
Suppress false positive from undefined behavior sanitizer.
rnburn Feb 3, 2018
dc1e79e
Represent duration with a string.
rnburn Feb 5, 2018
152218a
Use string to represent trace/span-ids.
rnburn Feb 7, 2018
bb817a3
Remove 3rd-party json library dependency.
rnburn Feb 11, 2018
cfe28ef
Run clang-format.
rnburn Feb 11, 2018
4a30061
Add missing include.
rnburn Feb 11, 2018
9deeb34
Use strings for IDs in JSON.
rnburn Feb 12, 2018
b3717a9
Merge branch 'jsonlib' into dlopen
rnburn Feb 13, 2018
4131731
Run clang-format.
rnburn Feb 13, 2018
b9a40ff
Add dl library dependency.
rnburn Feb 13, 2018
d2297f5
Return const pointer from const member function.
rnburn Feb 14, 2018
6796a85
Remove constexpr from rvalue-ref member.
rnburn Feb 14, 2018
0d275cb
Merge branch 'expected-bug' into dlopen
rnburn Feb 14, 2018
1368b7d
Fix bazel build.
rnburn Feb 15, 2018
52d0a5c
Add example usage with mocktracer.
rnburn Feb 20, 2018
bf1189a
Add example for dynamic loading.
rnburn Feb 20, 2018
3a198e9
Add missing include.
rnburn Feb 20, 2018
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
4 changes: 2 additions & 2 deletions 3rd_party/include/opentracing/expected/expected.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ union storage_t
return std::move( m_value );
}

value_type * value_ptr() const
const value_type * value_ptr() const
{
return &m_value;
}
Expand Down Expand Up @@ -694,7 +694,7 @@ class expected
: ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
}

constexpr value_type && value() &&
value_type && value() &&
{
return has_value()
? ( contained.value() )
Expand Down
14 changes: 10 additions & 4 deletions BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
cc_library(
name = "opentracing",
srcs = glob(["src/*.cpp"]),
srcs = glob(["src/*.cpp"], exclude=["src/dynamic_load_unsupported.cpp"]),
hdrs = glob(["include/opentracing/*.h"]) + [
":include/opentracing/config.h",
":include/opentracing/version.h",
],
strip_include_prefix = "include",
Expand All @@ -19,14 +20,19 @@ genrule(
"cmake/*",
"src/*",
]),
outs = ["include/opentracing/version.h"],
outs = [
"include/opentracing/config.h",
"include/opentracing/version.h"
],
cmd = """
TEMP_DIR=$$(mktemp -d)
TARGET=$${PWD}/$@
CONFIG_H_OUT=$${PWD}/$(location :include/opentracing/config.h)
VERSION_H_OUT=$${PWD}/$(location :include/opentracing/version.h)
OPENTRACING_ROOT=$$(dirname $${PWD}/$(location :CMakeLists.txt))
cd $$TEMP_DIR
cmake -DBUILD_TESTING=OFF -DBUILD_MOCKTRACER=OFF -L $$OPENTRACING_ROOT
mv include/opentracing/version.h $$TARGET
mv include/opentracing/config.h $$CONFIG_H_OUT
mv include/opentracing/version.h $$VERSION_H_OUT
rm -rf $$TEMP_DIR
""",
)
72 changes: 60 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,14 @@ SET(CPACK_PACKAGE_VERSION_MINOR ${OPENTRACING_VERSION_MINOR})
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENTRACING_VERSION_PATCH})
include(CPack)

# ==============================================================================
# Set up generated version.h

configure_file(version.h.in include/opentracing/version.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/opentracing
DESTINATION include)

# ==============================================================================
# Configure compilers

set(CMAKE_CXX_STANDARD 11)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything \
-Wno-c++98-compat \
-Wno-c++98-compat-pedantic \
-Wno-c++98-compat-bind-to-temporary-copy \
-Wno-weak-vtables \
-Wno-exit-time-destructors \
Expand All @@ -65,23 +58,70 @@ if(ENABLE_LINTING)
endif()

# ==============================================================================
# OpenTracing library targets
# Check for weak symbol support

include_directories(include)
include_directories(SYSTEM 3rd_party/include)
try_compile(
SUPPORTS_WEAK_SYMBOLS
"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp"
SOURCES ${CMAKE_SOURCE_DIR}/cmake/weak_symbol.cpp)

# ==============================================================================
# Set up options

option(BUILD_SHARED_LIBS "Build as a shared library" ON)
option(BUILD_STATIC_LIBS "Build as a static library" ON)
option(BUILD_MOCKTRACER "Build mocktracer library" ON)
option(BUILD_DYNAMIC_LOADING "Build with dynamic loading support" ON)

if (BUILD_DYNAMIC_LOADING)
if (NOT SUPPORTS_WEAK_SYMBOLS OR NOT UNIX)
message(WARNING "Building without dynamic loading support.")
set(BUILD_DYNAMIC_LOADING OFF)
endif()
endif()

set(OPENTRACING_BUILD_DYNAMIC_LOADING ${BUILD_DYNAMIC_LOADING})

if (NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
message(FATAL_ERROR "One or both of BUILD_SHARED_LIBS or BUILD_STATIC_LIBS must be set to ON to build")
endif()

set(SRCS src/propagation.cpp src/noop.cpp src/tracer.cpp)
# ==============================================================================
# Set up generated header files config.h and version.h

configure_file(version.h.in include/opentracing/version.h)
configure_file(config.h.in include/opentracing/config.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/opentracing
DESTINATION include)

# ==============================================================================
# OpenTracing library targets

include_directories(include)
include_directories(SYSTEM 3rd_party/include)

set(SRCS src/propagation.cpp
src/dynamic_load.cpp
src/noop.cpp
src/tracer.cpp
src/tracer_factory.cpp)

if (BUILD_DYNAMIC_LOADING)
list(APPEND SRCS src/dynamic_load_unix.cpp)
else()
list(APPEND SRCS src/dynamic_load_unsupported.cpp)
endif()

list(APPEND LIBRARIES "")
if (BUILD_DYNAMIC_LOADING)
list(APPEND LIBRARIES ${CMAKE_DL_LIBS})
endif()


if (BUILD_SHARED_LIBS)
add_library(opentracing SHARED ${SRCS})
target_link_libraries(opentracing ${LIBRARIES})
target_include_directories(opentracing INTERFACE "$<INSTALL_INTERFACE:include/>")
set_target_properties(opentracing PROPERTIES VERSION ${OPENTRACING_VERSION_STRING}
SOVERSION ${OPENTRACING_VERSION_MAJOR})
Expand All @@ -96,6 +136,7 @@ endif()

if (BUILD_STATIC_LIBS)
add_library(opentracing-static STATIC ${SRCS})
target_link_libraries(opentracing-static ${LIBRARIES})
set_target_properties(opentracing-static PROPERTIES OUTPUT_NAME opentracing)
target_include_directories(opentracing-static INTERFACE "$<INSTALL_INTERFACE:include/>")
install(TARGETS opentracing-static EXPORT OpenTracingTargets
Expand Down Expand Up @@ -147,3 +188,10 @@ include(CTest)
if(BUILD_TESTING)
add_subdirectory(test)
endif()

# ==============================================================================
# Examples

if(BUILD_TESTING)
add_subdirectory(example)
endif()
3 changes: 3 additions & 0 deletions cmake/weak_symbol.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
void __attribute((weak)) f();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the way to write it for all compilers? If not, I can devise a simple CMake loop to determine which, if any, weak symbol attribute notation works.

Copy link
Contributor Author

@rnburn rnburn Feb 16, 2018

Choose a reason for hiding this comment

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

GCC, Clang, ICC, and XL C all use the same weak symbol syntax.

MSVC has something different, but it's not quite the same as weak symbols and would have to be handled differently. Probably best to deal with that whenever we add the other pieces for MSVC.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK makes sense to me. Just like to leverage build tools for compatibility when it is straightforward to do so.


int main() { return 0; }
3 changes: 3 additions & 0 deletions config.h.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

#cmakedefine OPENTRACING_BUILD_DYNAMIC_LOADING
2 changes: 2 additions & 0 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_subdirectory(tutorial)
add_subdirectory(dynamic_load)
4 changes: 4 additions & 0 deletions example/dynamic_load/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
if (BUILD_DYNAMIC_LOADING AND BUILD_SHARED_LIBS)
add_executable(dynamic_load-example dynamic_load-example.cpp)
target_link_libraries(dynamic_load-example opentracing)
endif()
64 changes: 64 additions & 0 deletions example/dynamic_load/dynamic_load-example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Demonstrates how to load a tracer library in at runtime and how to use it
// to construct spans. To run it using the mocktracer, invoke with
//
// TRACER_CONFIG=`mktemp`
// echo '{ "output_file": "/dev/stdout" }' > $TRACER_CONFIG
// dynamic_load-example /path/to/libopentracing_mocktracer.so $TRACER_CONFIG

#include <opentracing/dynamic_load.h>
#include <cassert>
#include <cerrno>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>

int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "Usage: <tracer_library> <tracer_config_file>\n";
return -1;
}

// Load the tracer library.
std::string error_message;
auto handle_maybe =
opentracing::DynamicallyLoadTracingLibrary(argv[1], error_message);
if (!handle_maybe) {
std::cerr << "Failed to load tracer library " << error_message << "\n";
return -1;
}

// Read in the tracer's configuration.
std::ifstream istream{argv[2]};
if (!istream.good()) {
std::cerr << "Failed to open tracer config file " << argv[2] << ": "
<< std::strerror(errno) << "\n";
return -1;
}
std::string tracer_config{std::istreambuf_iterator<char>{istream},
std::istreambuf_iterator<char>{}};

// Construct a tracer.
auto& tracer_factory = handle_maybe->tracer_factory();
auto tracer_maybe =
tracer_factory.MakeTracer(tracer_config.c_str(), error_message);
if (!tracer_maybe) {
std::cerr << "Failed to create tracer " << error_message << "\n";
return -1;
}
auto& tracer = *tracer_maybe;

// Use the tracer to create some spans.
{
auto span_a = tracer->StartSpan("A");
assert(span_a != nullptr);
span_a->SetTag("abc", 123);
auto span_b =
tracer->StartSpan("B", {opentracing::ChildOf(&span_a->context())});
assert(span_b != nullptr);
span_b->SetTag("xyz", 987);
}

tracer->Close();
return 0;
}
5 changes: 5 additions & 0 deletions example/tutorial/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if (BUILD_MOCKTRACER AND BUILD_SHARED_LIBS)
include_directories(${CMAKE_SOURCE_DIR}/mocktracer/include)
add_executable(tutorial-example tutorial-example.cpp)
target_link_libraries(tutorial-example opentracing_mocktracer)
endif()
37 changes: 37 additions & 0 deletions example/tutorial/text_map_carrier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef LIGHTSTEP_TEXT_MAP_CARRIER
#define LIGHTSTEP_TEXT_MAP_CARRIER

#include <opentracing/propagation.h>
#include <string>
#include <unordered_map>

using opentracing::TextMapReader;
using opentracing::TextMapWriter;
using opentracing::expected;
using opentracing::string_view;

class TextMapCarrier : public TextMapReader, public TextMapWriter {
public:
TextMapCarrier(std::unordered_map<std::string, std::string>& text_map)
: text_map_(text_map) {}

expected<void> Set(string_view key, string_view value) const override {
text_map_[key] = value;
return {};
}

expected<void> ForeachKey(
std::function<expected<void>(string_view key, string_view value)> f)
const override {
for (const auto& key_value : text_map_) {
auto result = f(key_value.first, key_value.second);
if (!result) return result;
}
return {};
}

private:
std::unordered_map<std::string, std::string>& text_map_;
};

#endif // LIGHTSTEP_TEXT_MAP_CARRIER
99 changes: 99 additions & 0 deletions example/tutorial/tutorial-example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Demonstrates basic usage of the OpenTracing API. Uses OpenTracing's
// mocktracer to capture all the recorded spans as JSON.

#include <opentracing/mocktracer/json_recorder.h>
#include <opentracing/mocktracer/tracer.h>
#include <cassert>
#include <iostream>
#include <sstream>
#include <unordered_map>
#include "text_map_carrier.h"
using namespace opentracing;
using namespace opentracing::mocktracer;

int main() {
MockTracerOptions options;
std::unique_ptr<std::ostringstream> output{new std::ostringstream{}};
std::ostringstream& oss = *output;
options.recorder = std::unique_ptr<mocktracer::Recorder>{
new JsonRecorder{std::move(output)}};

std::shared_ptr<opentracing::Tracer> tracer{
new MockTracer{std::move(options)}};

auto parent_span = tracer->StartSpan("parent");
assert(parent_span);

// Create a child span.
{
auto child_span =
tracer->StartSpan("childA", {ChildOf(&parent_span->context())});
assert(child_span);

// Set a simple tag.
child_span->SetTag("simple tag", 123);

// Set a complex tag.
child_span->SetTag("complex tag",
Values{123, Dictionary{{"abc", 123}, {"xyz", 4.0}}});

// Log simple values.
child_span->Log({{"event", "simple log"}, {"abc", 123}});

// Log complex values.
child_span->Log({{"event", "complex log"},
{"data", Dictionary{{"a", 1}, {"b", Values{1, 2}}}}});

child_span->Finish();
}

// Create a follows from span.
{
auto child_span =
tracer->StartSpan("childB", {FollowsFrom(&parent_span->context())});

// child_span's destructor will finish the span if not done so explicitly.
}

// Use custom timestamps.
{
auto t1 = SystemClock::now();
auto t2 = SteadyClock::now();
auto span = tracer->StartSpan(
"useCustomTimestamps",
{ChildOf(&parent_span->context()), StartTimestamp(t1)});
assert(span);
span->Finish({FinishTimestamp(t2)});
}

// Extract and Inject a span context.
{
std::unordered_map<std::string, std::string> text_map;
TextMapCarrier carrier(text_map);
auto err = tracer->Inject(parent_span->context(), carrier);
assert(err);
auto span_context_maybe = tracer->Extract(carrier);
assert(span_context_maybe);
auto span = tracer->StartSpan("propagationSpan",
{ChildOf(span_context_maybe->get())});
}

// You get an error when trying to extract a corrupt span.
{
std::unordered_map<std::string, std::string> text_map = {
{"x-ot-span-context", "123"}};
TextMapCarrier carrier(text_map);
auto err = tracer->Extract(carrier);
assert(!err);
assert(err.error() == span_context_corrupted_error);
// How to get a readable message from the error.
std::cout << "Example error message: \"" << err.error().message() << "\"\n";
}

parent_span->Finish();
tracer->Close();

std::cout << "\nRecorded spans as JSON:\n\n";
std::cout << oss.str() << "\n";
return 0;
}
Loading