diff --git a/AUTHORS b/AUTHORS index d9b736a..6db9cfc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,6 +1,7 @@ AUTHORS ------- - - OpenTracing Developers +Dmitrios Kouzis-Loukas : dkouzislouka AT bloomberg DOT net +James Wells : jwells31 AT bloomberg DOT net +Jim Quinn : jquinn47 AT bloomberg DOT net diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8662e46 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required (VERSION 2.8) +set(PROJECT_NAME "opentracing") +project (${PROJECT_NAME}) + +set(lib_major_version "2") +set(lib_minor_version "0") +set(lib_patch_version "0") +set(opentracing_version "${lib_major_version}.${lib_minor_version}.${lib_patch_version}") +set(opentracing_url "https://github.com/opentracing/opentracing-cpp") + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +option(enable_noop "Build noop tracer." OFF) +option(enable_tests "Build unit tests." OFF) + +add_subdirectory(opentracing) + +if(enable_tests) + enable_testing() + add_subdirectory(thirdparty/googletest/googletest) + add_subdirectory(test) +endif() diff --git a/ChangeLog b/ChangeLog index 7a1533c..89f6a9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,46 @@ - -opentracing-cpp ChangeLog - -* initial release +f18e949 (HEAD -> master, jq/cmake-fun) Remove default contructors and handle side effects +29e1285 Remove cmake makefile +a83c752 Merge branch 'master' of https://bbgithub.dev.bloomberg.com/jquinn1/opentracing-cpp +963d016 Cmake, removing unused template functionality, ditching config.h for now +1120bb0 (jq/master) Merge pull request #3 from jquinn1/noop-shift +bde3545 Clean up build system, ability to turn off no-op, integrate tests +ef885ee (jq/noop-shift) Update reqs for tracerimps +88e1e8b Merge branch 'master' of https://bbgithub.dev.bloomberg.com/jquinn1/opentracing-cpp +a8b9017 Moving noop into its own package, updated tests +5e3885a Merge pull request #2 from jquinn1/changes +5ff6015 (jq/changes) Review feedback, removing guards, updated docs +eeb6fa3 typo +05f3bf3 Example compiler problem +b5e5486 Update examples +9f1daca formatting never ends +8f1025e formatting never ends +59e565f formatting +1f77d05 formatting +63ff455 Updating docs +9656c0b Adding iterator behaviors +3b86ccf Adding log/tags/baggage usage +d35931b Update usage +47a9047 Adding constants.h +c8d422c Adding guards, updating documentation and tests +d42770a Updating documentation +419580e Updating tests, adding spanoptions, consistently documented +1ee01dc Minor formatting +94227b4 Adding No-op implementation +b45a540 Adding noop, Baggage/BaggageWide, StringRefWide, and docs +2f37155 Solving the wide baggage problem +06ff151 Some documentation, StringRefWide +70d1545 Remove bad example +3381ca1 Testing everything, at least a little +ded4c0c StringRef, BaggageRef, BaggageIterator drafted +efadeda (origin/master, origin/HEAD) keep gcc specific flags specific to a gcc build (#5) +012743c Update configure.ac +3933120 Update configure.ac +6623183 Update ChangeLog +e1c9ea6 Update AUTHORS +7fecd71 a clarification (#4) +e0ea9eb Converting TextMapReader callback to functor (#2) +8b1efd1 Initial opentracing C++ version +368f2cd Merge pull request #1 from gitter-badger/gitter-badge +574ef91 Add Gitter badge +9ec9136 Update README.md +bfb0b74 Initial commit diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index abdab58..0000000 --- a/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -AUTOMAKE_OPTIONS = gnu - -lib_LTLIBRARIES = libopentracing.la - -libopentracing_la_SOURCES = opentracing/span.cc opentracing/tracer.cc - -nobase_include_HEADERS = opentracing/span.h opentracing/tracer.h - -libopentracing_la_LDFLAGS = -version-info 1:0:0 - - -ACLOCAL_AMFLAGS = -I m4 - -AM_CXXFLAGS= -fno-elide-constructors -pedantic-errors -ansi -std=c++98 - -if COMPILER_IS_GCC -AM_CXXFLAGS+= -Wall -Werror -Wextra -Winit-self -Wold-style-cast -AM_CXXFLAGS+= -Woverloaded-virtual -Wuninitialized -Wmissing-declarations -endif diff --git a/PROPOSED b/PROPOSED new file mode 100644 index 0000000..787a75e --- /dev/null +++ b/PROPOSED @@ -0,0 +1,12 @@ +# Virtual inheritance model + +## Pros +* Traditional OO/Simpler (major) +* Decouples Tracer from span/carrier +* Moves physical organization problem into carriers, (still messy, but much better than defining details in tracer) + +##Cons +* Spec adjustment, requiring reset/externalize for carrier fallback +* More complicated carrier code (minor) +* more expensive 'no-ops', always hit v-table (minor) +* No longer header only. Tracer singleton interface requires static storage is defined (more annoying, but still minor) diff --git a/README.md b/README.md index fb6568e..f707458 100644 --- a/README.md +++ b/README.md @@ -3,35 +3,57 @@ C++ implementation of the OpenTracing API http://opentracing.io [![Join the chat at https://gitter.im/opentracing/opentracing-cpp](https://badges.gitter.im/opentracing/opentracing-cpp.svg)](https://gitter.im/opentracing/opentracing-cpp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + ## Required Reading -In order to understand the C++ platform API, one must first be familiar with the -[OpenTracing project](http://opentracing.io) and -[terminology](http://opentracing.io/spec/) more generally. This is a C++98 API that -is used as a "common denominator". Ît's up to implementors to choose the C++ level -they are going to use for their implementations: +In order to understand the C++ platform API, one must first be familiar with the [OpenTracing project](http://opentracing.io) and +[terminology](http://opentracing.io/spec/) more generally. This is a C++98 API that is used as a "common denominator". +Ît is up to implementors to choose the C++ level they are going to use for their implementations: ![stack of libraries](img/stack-of-libraries.png "Stack of Libraries") ## Compile and install +The default package is a header-only library. It can be installed as such + ``` -libtoolize # or glibtoolize -./autogen.sh -./configure -sudo make install +mkdir build +cd build +cmake .. +make install ``` -To test (requires gtest - see [here for OS X](http://stackoverflow.com/questions/20746232/how-to-properly-setup-googletest-on-os-x-aside-from-xcode), [here for ubuntu](http://www.eriksmistad.no/getting-started-with-google-test-on-ubuntu/) and [here for Red Hat](http://stackoverflow.com/questions/13513905/how-to-setup-googletest-as-a-shared-library-on-linux)/for Red Hat note also [this](http://stackoverflow.com/questions/4743233/is-usr-local-lib-searched-for-shared-libraries)): +If you would like to include the NoopTracer, a static library is created in addition to the headers. ``` -cd test +mkdir build +cd build +cmake -Denable_noop=ON .. +make install +``` + +#### Tests + +Testing requires the use of `gtest`. The `gtest` library is added as a submodule to this repository. +To build all of the tests, from the root repository: + +``` +git submodule init +git submodule update +mkdir build +cd build +cmake -Denable_tests=ON .. make -./test +./bin/unittest ``` +If you're using the `NoopTracer`, you would want to add `-Denable_noop=ON` as well. + ## API overview for those adding instrumentation -Everyday consumers of this `opentracing` package really only need to worry -about a couple of key abstractions: the `StartSpan` function, the `Span` -interface, and binding a `Tracer` at `main()`-time. +Clients of this `OpenTracing` only need to understand the key abstractions: + * Installing a Tracer + * Using the Global `Tracer` to create `Spans` and `SpanContexts` + * Adding tags, logs, or baggage to `Spans` + +See the detailed [usage](./docs/usage.md) documentation for details. diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index 52a86ed..0000000 --- a/autogen.sh +++ /dev/null @@ -1,5 +0,0 @@ -#! /bin/sh - -aclocal \ -&& automake --add-missing \ -&& autoconf diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 9b89f54..0000000 --- a/configure.ac +++ /dev/null @@ -1,29 +0,0 @@ -AC_INIT([libopentracing], [1.0.0]) -#AC_CONFIG_SRCDIR(libopentracing.cc) -#AM_INIT_AUTOMAKE([-Wall -Werror foreign]) -AM_INIT_AUTOMAKE([subdir-objects]) - -AM_CONDITIONAL(COMPILER_IS_GCC, test "x$GCC" = "xyes") - -AC_CONFIG_MACRO_DIR([m4]) - -#AC_CONFIG_HEADERS([config.h]) - -AM_PROG_LIBTOOL - -AC_PROG_INSTALL - -AC_LANG_C -AC_PROG_CC -AC_PROG_CXX -AC_PROG_MAKE_SET - -AC_HEADER_STDC - -#AC_CHECK_HEADERS(unistd.h netdb.h netinet/in.h sys/types.h sys/socket.h,,AC_MSG_ERROR([required header file missing])) -#AC_CHECK_FUNCS(gethostbyname socket htons connect shutdown,,AC_MSG_ERROR([required standard library function missing])) - -AC_CONFIG_FILES([ - Makefile -]) -AC_OUTPUT diff --git a/opentracing/CMakeLists.txt b/opentracing/CMakeLists.txt new file mode 100644 index 0000000..838e377 --- /dev/null +++ b/opentracing/CMakeLists.txt @@ -0,0 +1,42 @@ +include_directories(${CMAKE_SOURCE_DIR}) + +set(headers + carriers.h + constants.h + spancontext.h + span.h + spanoptions.h + stringref.h + tracer.h) + +if(enable_noop) + # Used by pc file + set(opentracing_libs "-L${libdir} -lopentracing") + + # Updated set of included files + set(headers ${headers} noop.h) + + # Build our opentracing library + add_library(opentracing STATIC noop.cc) + + # Add the opentracing install target + install (TARGETS opentracing + DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} + COMPONENT dev) +endif() + +# Install the opentracing headers into /path/to/include/opentracing/ +install (FILES ${headers} + DESTINATION ${CMAKE_INSTALL_PREFIX}/include/opentracing + COMPONENT dev) + +# pkg-config +if("${UNIX}" OR "${CYGWIN}") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + @ONLY) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig + COMPONENT pkgconfig) +endif() diff --git a/opentracing/Makefile.am b/opentracing/Makefile.am deleted file mode 100644 index e69de29..0000000 diff --git a/opentracing/carriers.h b/opentracing/carriers.h new file mode 100644 index 0000000..b97c08f --- /dev/null +++ b/opentracing/carriers.h @@ -0,0 +1,29 @@ +#ifndef INCLUDED_OPENTRACING_CARRIERS_H +#define INCLUDED_OPENTRACING_CARRIERS_H + +#include +#include + +namespace opentracing { + +class Writer { + public: + virtual int inject(const Span&) = 0; + virtual int inject(const SpanContext&) = 0; + + protected: + Writer(); + Writer(const Writer&); +}; + +class Reader { + public: + int extract(SpanContext*) const = 0; + + protected: + Reader(); + Reader(const Reader&); +}; + +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_CARRIERS_H diff --git a/opentracing/constants.h b/opentracing/constants.h new file mode 100644 index 0000000..827f080 --- /dev/null +++ b/opentracing/constants.h @@ -0,0 +1,28 @@ +#ifndef INCLUDED_OPENTRACING_CONSTANTS_H +#define INCLUDED_OPENTRACING_CONSTANTS_H + +// =========== +// constants.h +// =========== +// This header provides a set of macros for the "standard" OpenTracing tag and +// log fields. For a description of each value, and how it should be used, see: +// https://github.com/opentracing/specification/blob/master/data_conventions.yaml + +#define OPENTRACING_TAG_ERROR "error" +#define OPENTRACING_TAG_COMPONENT "component" +#define OPENTRACING_TAG_SAMPLING_PRIORITY "sampling.priority " + +#define OPENTRACING_TAG_HTTP_URL "http.url" +#define OPENTRACING_TAG_HTTP_METHOD "http.method" +#define OPENTRACING_TAG_HTTP_STATUS "http.status" + +#define OPENTRACING_TAG_SPAN_KIND "span.kind" +#define OPENTRACING_TAG_PEER_HOSTNAME "peer.hostname" +#define OPENTRACING_TAG_PEER_IPV4 "peer.ipv4" +#define OPENTRACING_TAG_PEER_IPV6 "peer.ipv6" +#define OPENTRACING_TAG_PEER_PORT "peer.port" +#define OPENTRACING_TAG_PEER_SERVICE "peer.service" + +#define OPENTRACING_LOG_EVENT "event" + +#endif diff --git a/opentracing/globaltracer.cpp b/opentracing/globaltracer.cpp new file mode 100644 index 0000000..74fdf15 --- /dev/null +++ b/opentracing/globaltracer.cpp @@ -0,0 +1,21 @@ +#include +#include + +namespace opentracing{ + +void GlobalTracer::install(Tracer *) +{ + s_tracer = tracer; +} + +void GlobalTracer::uninstall() +{ + s_tracer = 0; +} + +Tracer* GlobalTracer::instance() +{ + return s_Tracer; +} + +} diff --git a/opentracing/globaltracer.h b/opentracing/globaltracer.h new file mode 100644 index 0000000..5dba3af --- /dev/null +++ b/opentracing/globaltracer.h @@ -0,0 +1,25 @@ +#ifndef INCLUDED_OPENTRACING_GLOBALTRACER_H +#define INCLUDED_OPENTRACING_GLOBALTRACER_H + +// Only if the singleton interface is included do we require that opentracing +// produce a .a or .so library. To avoid building a physical lib for a 'flea on +// the elephant', I've moved the singleton GlobalTracer struct. It's only +// built if requested. + +namespace opentracing { + +class Tracer; + +struct GlobalTracer +{ + public: + static void install(Tracer*); + static void uninstall(); + static Tracer* instance(); + + private: + static GlobalTracer* s_tracer; +}; + +} // namespace opentracing +// #INCLUDED_OPENTRACING_GLOBALTRACER_H diff --git a/opentracing/opentracing.pc.in b/opentracing/opentracing.pc.in new file mode 100644 index 0000000..debaed1 --- /dev/null +++ b/opentracing/opentracing.pc.in @@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/include + +Name: @PROJECT_NAME@ +Description: C++ interface for the OpenTracing specification +URL: @opentracing_url@ +Version: @opentracing_version@ +Requires: +Requires.private: +Libs: @opentracing_libs@ +Libs.private: +Cflags: -I${includedir} diff --git a/opentracing/span.cc b/opentracing/span.cc deleted file mode 100644 index 49fb1ac..0000000 --- a/opentracing/span.cc +++ /dev/null @@ -1,111 +0,0 @@ -#include -#include - -namespace opentracing -{ - -Span::~Span() -{ -} - -Span * Span::setOperationName(const std::string & operationName) -{ - (void)operationName; - - return this; -} - -Span * Span::setTag(const std::string & key, const std::string & value) -{ - (void)key; - (void)value; - - return this; -} - -Span * Span::log(const LogData & data) -{ - (void)data; - - return this; -} - -Span * Span::log(const std::vector & logData) -{ - for (std::vector::const_iterator i = logData.begin(); i != logData.end(); ++i) - { - log(*i); - } - return this; -} - -Span * Span::setBaggageItem(const std::string & restrictedKey, const std::string & value) -{ - (void)restrictedKey; - (void)value; - - return this; -} - -bool Span::getBaggageItem(const std::string & restrictedKey, std::string * targetValue) const -{ - (void)restrictedKey; - (void)targetValue; - - return false; -} - -void Span::finish() -{ - finish(0); -} - -void Span::finish(const uint64_t & finishTime) -{ - (void)finishTime; -} - -LogData::LogData(const std::string & event_, const Payload & payload_) - : timestamp(0) - , event(event_) - , payload(payload_) -{ -} - -LogData::LogData(const uint64_t & timestamp_, const std::string & event_, const Payload & payload_) - : timestamp(timestamp_) - , event(event_) - , payload(payload_) -{ -} - -bool canonicalizeBaggageKey(std::string & key) -{ - if (key.empty()) - { - return false; - } - - for (std::string::iterator i = key.begin(); i != key.end(); ++i) - { - *i = tolower(*i); - } - - for (std::string::iterator i = key.begin(); i != key.end(); ++i) - { - char c(*i); - - if ((c>='a' && c<='z') || (c>='0' && c<='9') || (c=='-' && i != key.begin())) - { - // This is ok. - } - else - { - return false; - } - } - - return true; -} - -} diff --git a/opentracing/span.h b/opentracing/span.h index 3706a47..4d10a21 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -1,200 +1,119 @@ -#ifndef OPENTRACING_SPAN_H -#define OPENTRACING_SPAN_H +#ifndef INCLUDED_OPENTRACING_SPAN_H +#define INCLUDED_OPENTRACING_SPAN_H + +#include #include -#include -#include #include -namespace opentracing -{ - -class Tracer; -class LogData; +namespace opentracing { -/** - * A `Span` represents an active, un-finished span in the OpenTracing system. - * Spans are created by the `Tracer` interface. - */ -class Span -{ -public: - /** - * Destroys this Span. - */ +class Span { + public: virtual ~Span(); - /** - * Sets or changes the operation name. - */ - virtual Span * setOperationName(const std::string & operationName); - - /** - * Adds a tag with any value to the `Span`. If there is a - * existing tag set for `key`, it is overwritten. - */ + virtual int setOperation(const StringRef& operation) = 0; + + virtual int finish() = 0; + virtual int finish(const uint64_t tsp) = 0; + + virtual int tag(const StringRef& key, int16_t) = 0; + virtual int tag(const StringRef& key, int32_t) = 0; + virtual int tag(const StringRef& key, int64_t) = 0; + + virtual int tag(const StringRef& key, uint16_t) = 0; + virtual int tag(const StringRef& key, uint32_t) = 0; + virtual int tag(const StringRef& key, uint64_t) = 0; + + virtual int tag(const StringRef& key, signed char) = 0; + virtual int tag(const StringRef& key, unsigned char) = 0; + virtual int tag(const StringRef& key, char) = 0; + + virtual int tag(const StringRef& key, bool) = 0; + virtual int tag(const StringRef& key, float) = 0; + virtual int tag(const StringRef& key, double) = 0; + + template + int tag(const StringRef& key, const T& val); + + virtual int log(const StringRef& key, int16_t) = 0; + virtual int log(const StringRef& key, int32_t) = 0; + virtual int log(const StringRef& key, int64_t) = 0; + + virtual int log(const StringRef& key, uint16_t) = 0; + virtual int log(const StringRef& key, uint32_t) = 0; + virtual int log(const StringRef& key, uint64_t) = 0; + + virtual int log(const StringRef& key, signed char) = 0; + virtual int log(const StringRef& key, unsigned char) = 0; + virtual int log(const StringRef& key, char) = 0; + + virtual int log(const StringRef& key, bool) = 0; + virtual int log(const StringRef& key, float) = 0; + virtual int log(const StringRef& key, double) = 0; + + template + int log(const StringRef& key, const T& val); + + virtual int log(const StringRef& key, int16_t, uint64_t) = 0; + virtual int log(const StringRef& key, int32_t, uint64_t) = 0; + virtual int log(const StringRef& key, int64_t, uint64_t) = 0; + + virtual int log(const StringRef& key, uint16_t, uint64_t) = 0; + virtual int log(const StringRef& key, uint32_t, uint64_t) = 0; + virtual int log(const StringRef& key, uint64_t, uint64_t) = 0; + + virtual int log(const StringRef& key, signed char, uint64_t) = 0; + virtual int log(const StringRef& key, unsigned char, uint64_t) = 0; + virtual int log(const StringRef& key, char, uint64_t) = 0; + + virtual int log(const StringRef& key, bool, uint64_t) = 0; + virtual int log(const StringRef& key, float, uint64_t) = 0; + virtual int log(const StringRef& key, double, uint64_t) = 0; + template - Span * setTag(const std::string & key, const T & value); - - /** - * Adds a tag with a `std::string` value to the `Span`. If there is a - * existing tag set for `key`, it is overwritten. - */ - virtual Span * setTag(const std::string & key, const std::string & value); - - /** - * Log() records `data` to this Span. - * See LogData for semantic details. - */ - virtual Span * log(const LogData & data); - - /** - * Bulk, potentially more efficient version of log(). - */ - virtual Span * log(const std::vector & logData); - - /** - * `setBaggageItem()` sets a key:value pair on this `Span` that also - * propagates to future `Span` children. - * - * `setBaggageItem()` enables powerful functionality given a full-stack - * opentracing integration (e.g., arbitrary application data from a mobile - * app can make it, transparently, all the way into the depths of a storage - * system), and with it some powerful costs: use this feature with care. - * - * IMPORTANT NOTE #1: `setBaggageItem()` will only propagate trace - * baggage items to *future* children of the `Span`. - * - * IMPORTANT NOTE #2: Use this thoughtfully and with care. Every key and - * value is copied into every local *and remote* child of this `Span`, and - * that can add up to a lot of network and CPU overhead. - * - * IMPORTANT NOTE #3: Baggage item keys have a restricted format: - * implementations may wish to use them as HTTP header keys (or key - * suffixes), and of course HTTP headers are case insensitive. - * - * As such, `restrictedKey` MUST match the regular expression - * `(?i:[a-z0-9][-a-z0-9]*)` and is case-insensitive. That is, it must - * start with a letter or number, and the remaining characters must be - * letters, numbers, or hyphens. See `canonicalizeBaggageKey()`. If - * `restrictedKey` does not meet these criteria, `setBaggageItem()` - * results in undefined behavior. - * - * Returns a pointer to this `Span` for chaining, etc. - */ - virtual Span * setBaggageItem(const std::string & restrictedKey, const std::string & value); - - /* - * If `targetValue` is `NULL`, this method quickly returns true/false depending on - * if baggage is set for given key or not. If `targetValue` isn't `NULL` then the - * baggage value is assigned to `*targetValue` if it exists, otherwise `*targetValue` - * doesn't get modified. - * - * See the `setBaggageItem()` notes about `restrictedKey`. - */ - virtual bool getBaggageItem(const std::string & restrictedKey, std::string * targetValue = 0) const; - - /** - * Provides access to the `Tracer` that created this `Span`. Implementation should - * ensure the reference remains valid potentially in a multi-threaded context (might - * require some form of reference counting). - */ - virtual const Tracer & getTracer() const = 0; - - /** - * Stops this span. `finish()` should be the last call made to any span instance, - * and to do otherwise leads to undefined behavior. - */ - virtual void finish(); - - /** - * Same as `finish()` above but also sets explicitly the finishing time - * in microseconds since epoch. If set to the default value (the unix - * epoch), implementations should use the current time implicitly. - */ - virtual void finish(const uint64_t & finishTime); + int log(const StringRef& key, const T& val, uint64_t); + + virtual int setBaggage(const StringRef& key, const StringRef& value) = 0; + + virtual int getBaggage(const StringRef& key, + std::string* baggage) const = 0; + + virtual int getBaggage(const StringRef& key, + std::vector* baggage) const = 0; + + virtual int externalize(std::vector *) = 0; + virtual int externalize(std::vector* buf) = 0; + + protected: + Span(); + Span(const Span&); + // Protected to avoid direct construction }; -/** - * LogData is data associated to a Span. Every LogData instance should specify - * at least one of Event and/or Payload. - */ -class LogData +template +int Span::tag(const StringRef& key, const T& val) { -public: - /** - * Payload should support arbitrary binary data. `std::string` can support - * this. - */ - typedef std::string Payload; - - /** - * Creates an empty `LogData` for current time and with optional parameters. - */ - explicit LogData(const std::string & event = "", const Payload & payload = Payload()); - - /** - * Creates an empty `LogData` for the given timestamp and with optional - * parameters. If set to the default value (the unix epoch), implementations - * should use the current time implicitly. - */ - explicit LogData(const uint64_t & timestamp, const std::string & event = "", const Payload & payload = Payload()); - - /** - * The timestamp of the log record; if set to the default value (the unix - * epoch), implementations should use the current time implicitly. - */ - uint64_t timestamp; - - /** - * Event (if non-empty) should be the stable name of some notable moment in - * the lifetime of a `Span`. For instance, a `Span` representing a browser page - * load might add an Event for each of the Performance.timing moments - * here: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming - * - * While it is not a formal requirement, Event strings will be most useful - * if they are *not* unique; rather, tracing systems should be able to use - * them to understand how two similar `Span`s relate from an internal timing - * perspective. - */ - std::string event; - - /** - * Payload is a free-form potentially structured object which Tracer - * implementations may retain and record all, none, or part of. - * - * If included, `payload` should be restricted to data derived from the - * instrumented application; in particular, it should not be used to pass - * semantic flags to a log() implementation. - * - * For example, an RPC system could log the wire contents in both - * directions, or a SQL library could log the query (with or without - * parameter bindings); tracing implementations may truncate or otherwise - * record only a snippet of these payloads (or may strip out PII, etc, - * etc). - */ - Payload payload; -}; + std::ostringstream ss; + ss << val; + return log(key, ss.str()); +} -/** - * `canonicalizeBaggageKey()` returns the canonicalized version of baggage item - * key `key`, and true if and only if the key was valid. Note: It might alter - * `key` irrespectively of if it is valid or not. - */ -bool canonicalizeBaggageKey(std::string & key); - -/** - * Default `setTag()` implementation. - */ -template -Span * Span::setTag(const std::string & key, const T & value) +template +int Span::log(const StringRef& key, const T& val) { - std::ostringstream oss; - oss << value; - setTag(key, oss.str()); - return this; + std::ostringstream ss; + ss << val; + return log(key, ss.str()); } +template +int Span::log(const StringRef& key, const T& val, uint64_t tsp) +{ + std::ostringstream ss; + ss << val; + return log(key, ss.str(), tsp); } -#endif // #define OPENTRACING_SPAN_H +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_SPAN_H diff --git a/opentracing/spancontext.h b/opentracing/spancontext.h new file mode 100644 index 0000000..77510bb --- /dev/null +++ b/opentracing/spancontext.h @@ -0,0 +1,50 @@ +#ifndef INCLUDED_OPENTRACING_SPANCONTEXT_H +#define INCLUDED_OPENTRACING_SPANCONTEXT_H + +#include +#include +#include +#include +#include + +namespace opentracing { + +struct BaggageCallback { + public: + virtual void operator()(const opentracing::StringRef &key, + const opentracing::StringRef &value) = 0; + protected: + BaggageCallback() {} + BaggageCallback(const BaggageCallback&) {} + BaggageCallback& operator=(BaggageCallback&) {} + // Protected to avoid direct construction + + virtual ~BaggageCallback() {} +}; + +template class SpanContext { + public: + virtual void forAllBaggage(BaggageCallback &cb) = 0; + + virtual int getBaggage(const StringRef &key, + std::string * baggage) const = 0; + + virtual int getBaggage(const StringRef & key, + std::vector *baggage) const = 0; + + virtual int reset(const std::vector& textmap) = 0; + virtual int reset(void * buf, size_t len) = 0; + + virtual int externalize(std::vector *) = 0; + virtual int externalize(std::vector* buf) = 0; + + protected: + virtual ~SpanContext(){} + SpanContext(){} + SpanContext(const SpanContext &){} + SpanContext & operator=(SpanContext &){} + // Protected to avoid direct construction +}; + +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_SPANCONTEXT_H diff --git a/opentracing/spanoptions.h b/opentracing/spanoptions.h new file mode 100644 index 0000000..f639a4c --- /dev/null +++ b/opentracing/spanoptions.h @@ -0,0 +1,81 @@ +#ifndef INCLUDED_OPENTRACING_SPANOPTIONS_H +#define INCLUDED_OPENTRACING_SPANOPTIONS_H + +#include +#include + +namespace opentracing { + +// ======================= +// class SpanReferenceType +// ======================= +// Spans may reference zero or more other SpanContexts that are causally +// related. +// OpenTracing presently defines two types of references: ChildOf and +// FollowsFrom. Both reference types specifically model direct causal +// relationships between a child Span and a parent Span. +// +// * e_ChildOf - A Span may be the ChildOf a parent Span. In a ChildOf +// reference, +// the parent Span depends on the child Span in some capacity. +// +// * e_FollowsFrom - Some parent Spans do not depend in any way on the result +// of +// their child Spans. In these cases, we say merely that the +// child Span FollowsFrom the parent Span in a causal sense. + +class SpanReferenceType { + public: + enum Value + { + e_ChildOf = 0, + e_FollowsFrom = 1 + }; +}; + +class SpanOptions { + public: + virtual int setOperation(const StringRef&) = 0; + + virtual int setStartTime(const uint64_t) = 0; + + virtual int setReference(const SpanReferenceType::Value relationship, + const SpanContext& context) = 0; + + virtual int setTag(const StringRef& key, int16_t) = 0; + virtual int setTag(const StringRef& key, int32_t) = 0; + virtual int setTag(const StringRef& key, int64_t) = 0; + + virtual int setTag(const StringRef& key, uint16_t) = 0; + virtual int setTag(const StringRef& key, uint32_t) = 0; + virtual int setTag(const StringRef& key, uint64_t) = 0; + + virtual int setTag(const StringRef& key, signed char) = 0; + virtual int setTag(const StringRef& key, unsigned char) = 0; + virtual int setTag(const StringRef& key, char) = 0; + + virtual int setTag(const StringRef& key, bool) = 0; + virtual int setTag(const StringRef& key, float) = 0; + virtual int setTag(const StringRef& key, double) = 0; + + template + int setTag(const StringRef& key, const T& val); + + protected: + SpanOptions() {} + SpanOptions(const SpanOptions&) {} + SpanOptions& operator=(const SpanOptions&) {} + virtual ~SpanOptions() {}; +}; + +template +int +SpanOptions::setTag(const StringRef& key, const T& val) +{ + std::ostringstream ss; + ss << val; + return setTag(key, ss.str()); +} + +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_SPANOPTIONS_H diff --git a/opentracing/stringref.h b/opentracing/stringref.h new file mode 100644 index 0000000..1fe39ac --- /dev/null +++ b/opentracing/stringref.h @@ -0,0 +1,185 @@ +#ifndef INCLUDED_OPENTRACING_STRINGREF_H +#define INCLUDED_OPENTRACING_STRINGREF_H + +// =========== +// stringref.h +// =========== +// class StringRef - Constant reference to an external string +// +// ----------------- +// String References +// ----------------- +// This string references is a simplified version of the boost::string_ref. +// Its purpose is to avoid a number of efficiency problems that appear +// commonly when interacting with 'std::string' and c-strings. +// +// See the boost documentation for more background: +// http://www.boost.org/doc/libs/master/libs/utility/doc/html/string_ref.html + +#include +#include +#include + +namespace opentracing { + +// =============== +// class StringRef +// =============== +// Represent a constant reference to an external character array. The external +// array need not be null-terminated, if explicitly created with a known length. +// +// This class does not own the data. It is expected to be used in situations +// where the character data resides in some other buffer, whose lifetime extends +// past that of the StringRef. For this reason, it is not in general safe to +// store a StringRef. + +class StringRef { + public: + StringRef(); + // Construct an empty StringRef + + template + StringRef(const char (&str)[N]); + // Explicitly create string reference from a const character array + + explicit StringRef(const char* str); + // Explicitly create string reference from const character pointer + + StringRef(const std::basic_string& str); + // Create constant string reference from pointer and length + + StringRef(const char* str, size_t len); + // Create constant string reference from pointer and length + + operator const char*() const; + // Implicit conversion to plain char * + + template + void reset(const char (&str)[N]); + // Reset the string reference given a const character array + + void reset(const char* str); + // Reset this string ref to point at the supplied c-string + + void reset(const std::basic_string& str); + // Reset the string reference given a std::string + + void reset(const char* str, const size_t length); + // Reset this string ref to point at the supplied 'str' of 'length' bytes. + + const char* data() const; + // Return address of the referenced string + + size_t length() const; + // Return the length of the referenced string + + private: + template + StringRef(char (&str)[N]); + // Disallow construction from non-const array + + template + void reset(char (&str)[N]); + // Disallow reset from non-const array + + const char* m_data; // Pointer to external storage + size_t m_length; // Length of data pointed to by 'm_data' +}; + +// ----- +// Note: +// ----- +// Although we have the ability to use wide string refs, there are side +// effects in exposing an OpenTracing interface that works with narrow and wide +// strings at the same time. Storage on the implementation will have a 'native' +// format. +// +// Exposing references to that format avoid copies means clients would be +// dependent on that format. If they're dependent on that detail and then switch +// out the implementation to a different format, there would be lots of code +// that breaks if it was expecting wstring and starts receiving string all of a +// sudden. That design issue still needs to be addressed. + +// --------------- +// Class StringRef +// --------------- + +inline StringRef::StringRef() : m_data(0), m_length(0) +{ +} + +template +StringRef::StringRef(const char (&str)[N]) : m_data(str), m_length(N - 1) +{ +} + +inline StringRef::StringRef(const char* str) +: m_data(str), m_length(std::strlen(str)) +{ +} + +inline StringRef::StringRef(const std::basic_string& str) +: m_data(str.c_str()), m_length(str.length()) +{ +} + +inline StringRef::StringRef(const char* str, size_t len) +: m_data(str), m_length(len) +{ +} + +inline StringRef::operator const char*() const +{ + return m_data; +} + +inline void +StringRef::reset(const char* str, const size_t length) +{ + m_data = str; + m_length = length; +} + +template +void +StringRef::reset(const char (&str)[N]) +{ + m_data = str; + m_length = N; +} + +inline void +StringRef::reset(const char* str) +{ + m_data = str; + m_length = std::strlen(str); +} + +inline void +StringRef::reset(const std::basic_string& str) +{ + m_data = str.data(); + m_length = str.length(); +} + +inline const char* +StringRef::data() const +{ + return m_data; +} + +inline size_t +StringRef::length() const +{ + return m_length; +} + +} // namespace opentracing + +inline std::ostream& +operator<<(std::ostream& os, const opentracing::StringRef& ref) +{ + return os.write(ref.data(), ref.length()); +} + +#endif // INCLUDED_OPENTRACING_STRINGREF_H diff --git a/opentracing/textpair.h b/opentracing/textpair.h new file mode 100644 index 0000000..18fc91d --- /dev/null +++ b/opentracing/textpair.h @@ -0,0 +1,17 @@ +#ifndef INCLUDED_OPENTRACING_TEXTPAIR_H +#define INCLUDED_OPENTRACING_TEXTPAIR_H + +#include + +namespace opentracing { + +class TextPair { + public: + TextPair(); + TextPair(const StringRef& name, const StringRef& value); + + std::string m_key; + std::string m_value; +}; +} +#endif diff --git a/opentracing/tracer.cc b/opentracing/tracer.cc deleted file mode 100644 index 9411982..0000000 --- a/opentracing/tracer.cc +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include - -#include -#include - - -#if defined(OPENTRACING_USE_STD_ATOMIC) || defined(OPENTRACING_USE_BOOST_ATOMIC) - #ifdef OPENTRACING_USE_STD_ATOMIC - #include - #define TRACER_PTR_T std::atomic - #else - #include - #define TRACER_PTR_T boost::atomic - #endif - - #define SWAP_TRACER_PTR(ptr, value) ((value) = (ptr).exchange(value)) - #define RETRIEVE_TRACER_PTR(ptr) ((ptr).load()) -#else - #define TRACER_PTR_T Tracer * - #define SWAP_TRACER_PTR(ptr, value) do { TRACER_PTR_T tmp(ptr); (ptr) = (value); (value) = tmp; } while (0) - #define RETRIEVE_TRACER_PTR(ptr) (ptr) -#endif - - -namespace opentracing -{ - -StartSpanOptions::StartSpanOptions(const Span * parent_, const uint64_t & startTime_) - : parent(parent_) - , startTime(startTime_) -{ -} - -StartSpanOptions::StartSpanOptions(const uint64_t & startTime_) - : parent(0) - , startTime(startTime_) -{ -} - -Tracer::~Tracer() -{ -} - -Writer::~Writer() -{ -} - -TextMapWriter::~TextMapWriter() -{ -} - -Reader::~Reader() -{ -} - -TextMapReader::~TextMapReader() -{ -} - -TextMapReader::ReadCallback::~ReadCallback() -{ -} - -namespace { - -class NoopSpan : public virtual Span -{ -public: - - NoopSpan(const NoopTracer & noopTracer) - : m_noopTracer(noopTracer) - { - } - - virtual ~NoopSpan() - { - } - - virtual const Tracer & getTracer() const - { - return m_noopTracer; - } - -private: - - const NoopTracer & m_noopTracer; -}; - -} - -NoopTracer::~NoopTracer() -{ -} - -Span * NoopTracer::startSpan(const std::string & operationName, const StartSpanOptions & startSpanOptions) const -{ - (void)operationName; - (void)startSpanOptions; - return new NoopSpan(*this); -} - -Tracer::Result NoopTracer::inject(const Span & sp, const Writer & writer, std::string & error) const -{ - (void)sp; - (void)writer; - (void)error; - - return Success; -} - -Tracer::Result NoopTracer::join(Span ** sp, const std::string & operationName, const Reader & reader, std::string & error) const -{ - (void)sp; - (void)operationName; - (void)reader; - (void)error; - - return ErrTraceNotFound; -} - -namespace -{ - -NoopTracer defaultNoopTracer; -TRACER_PTR_T the_globalTracer(&defaultNoopTracer); - -} - -Tracer * globalTracer() -{ - return RETRIEVE_TRACER_PTR(the_globalTracer); -} - -Tracer * initGlobalTracer(Tracer * tracer) -{ - if (!tracer) - { - throw std::runtime_error("tracer is NULL"); - } - - SWAP_TRACER_PTR(the_globalTracer, tracer); - - return tracer == &defaultNoopTracer ? NULL : tracer; -} - -} diff --git a/opentracing/tracer.h b/opentracing/tracer.h index c1433a6..0203c1d 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -1,322 +1,39 @@ -#ifndef OPENTRACING_TRACER_H -#define OPENTRACING_TRACER_H +#ifndef INCLUDED_OPENTRACING_TRACER_H +#define INCLUDED_OPENTRACING_TRACER_H -#include -#include +#include +#include +#include +#include -namespace opentracing -{ +namespace opentracing { -class Span; -class Writer; -class Reader; +class Tracer { + private: + static Tracer* s_tracer; -/** - * Options used when you start a `Span`. - */ -struct StartSpanOptions -{ - /** - * The parent span. `NULL` if there's no parent `Span`. - */ - const Span * parent; + public: + virtual SpanOptions* makeSpanOptions() = 0; - /** - * The `Span` start time. Set to 0 to use current time. - */ - const uint64_t startTime; - - /** - * Start a child `Span` with the given parent and `startTime`. - */ - StartSpanOptions(const Span * parent_, const uint64_t & startTime_ = 0); - - /** - * Start a child `Span` with the given `startTime`. - */ - explicit StartSpanOptions(const uint64_t & startTime_ = 0); -}; - -/** - * Tracer is a simple, thin interface for `Span` creation. - */ -class Tracer -{ -public: - /** - * Destroys the `Tracer`. - */ - virtual ~Tracer(); - - /** - * Return statuses for the `inject()` and `join()` methods. - */ - enum Result - { - /** - * Operation completed successfully. - */ - Success, - - /** - * `ErrUnsupportedFormat` occurs when the `format` passed to `Tracer::inject()` or - * `Tracer::join()` is not recognized by the Tracer implementation. - */ - ErrUnsupportedFormat, - - /** - * `ErrTraceNotFound` occurs when the `carrier` passed to `Tracer::join()` is - * valid and uncorrupted but has insufficient information to join or resume - * a trace. - */ - ErrTraceNotFound, - - /** - * `ErrInvalidSpan` errors occur when `Tracer::inject()` is asked to operate on - * a `Span` which it is not prepared to handle (for example, since it was - * created by a different tracer implementation). - */ - ErrInvalidSpan, - - /** - * `ErrInvalidCarrier` errors occur when `Tracer::inject()` or `Tracer::join()` - * implementations expect a different type of `carrier` than they are - * given. - */ - ErrInvalidCarrier, + virtual Span* start(const StringRef& op) = 0; + virtual Span* start(const SpanOptions& opts) = 0; - /** - * `ErrTraceCorrupted` occurs when the `carrier` passed to `Tracer::join()` is - * of the expected type but is corrupted. - */ - ErrTraceCorrupted - }; + virtual const SpanContext* getContext(const Span*) = 0; - /** - * Create, start, and return a new Span with the given `operationName`, all - * without specifying a parent `Span` that can be used to incorporate the - * newly-returned `Span` into an existing trace. (I.e., the returned `Span` is - * the "root" of its trace). - * - * Examples: - * - * Span * sp = globalTracer()->startSpan("GetFeed()"); - * - * Span * sp = globalTracer()->startSpan("LoggedHTTPRequest()", StartSpanOptions(now, &parent)) - * ->setTag("user_agent", loggedReq.UserAgent); - * - * This method isn't expected to fail except of the usual out of memory errors. - */ - virtual Span * startSpan(const std::string & operationName, const StartSpanOptions & startSpanOptions = StartSpanOptions()) const = 0; + virtual int inject(Writer* carrier, const Span& span) const = 0; + virtual int inject(Writer* carrier, const SpanContext& context) const = 0; - /** - * `inject()` takes the `sp` `Span` instance and sends information topropagation - * carriers via the `Writer` interface. It returns `Result::Success` on success - * or some error otherwise. In the latter case, `error` will be set with a - * debug message. - * - * Example usage: - * - * CarrierT carrier; - * std::string error; - * - * Tracer::Result result = globalTracer()->inject(*span, - * MapTextAdapter(carrier), - * error); - * if (result != Tracer::Success) { ... - * - * NOTE: All opentracing.Tracer implementations MUST support `TextMapWriter` - * `Writer`s. - * - * Implementations may return `Result::ErrUnsupportedFormat` if `writer` - * is of unknown or unsupported type. - * - * Implementations may return `Result::ErrInvalidCarrier` or any other - * implementation-specific error if the format is supported but injection - * fails anyway. - * - * There's not specific reason for `Writer` being const. It's just to support - * the nice inline form described above. This might mean that you might have - * to use `mutable` in some cases. This `const` will be revised if there prove - * to be issues. - * - * See also `Tracer::join()`. - */ - virtual Result inject(const Span & sp, const Writer & writer, std::string & error) const = 0; + virtual const SpanContext* extract(const Carrier& carrier) const = 0; - /** - * `join()` returns a `Span` instance with operation name `operationName` given - * a carrier reader `reader`. - * - * `join()` is responsible for extracting and joining to the trace of a `Span` - * instance embedded in a format-specific "carrier" object. Typically the - * joining will take place on the server side of an RPC boundary, but - * message queues and other IPC mechanisms are also reasonable places to - * use `join()`. - * - * OpenTracing defines an extensible set of `Reader`s (see `Reader`), and - * each supports potentially many carrier types. - * - * - * - * Example usage: - * - * CarrierT carrier; - * std::string error; - * - * Span * span(0); - * Tracer::Result result = globalTracer()->join(&span, - * "operation()", - * MapTextAdapter(carrier), - * error); - * if (result != Tracer::Success) { ... - * - * NOTE: All `Tracer` implementations MUST support `TextMapReader` `Reader`s. - * - * Return values: - * - A successful `join()` will return `Tracer::Success` and will set `sp` to - * the value of an appropriately initialized `Span` pointer. - * - If there was simply no trace to join with in `carrier`, `join()` - * returns `Tracer::ErrTraceNotFound` and `sp` isn't modified. - * - If the `reader` is unsupported or unrecognized, `join()` returns - * `Tracer::ErrUnsupportedFormat` and `sp` isn't modified. - * - If there are more fundamental problems with the `reader` object, - * `join()` may return `Tracer::ErrInvalidCarrier` or - * `Tracer::ErrTraceCorrupted` and `sp` won't be modified. - * - * See also `Tracer::inject()`. - */ - virtual Result join(Span ** sp, const std::string & operationName, const Reader & reader, std::string & error) const = 0; -}; - -/** - * This is the base interface for writing data to carriers. Not much - * functionality here but provides through `dynamic_cast<>`ing the means - * to check if an implementation is supported or not. - */ -class Writer -{ -public: - /** - * Destroys this Writer. - */ - virtual ~Writer(); -}; + virtual void cleanup(const SpanOptions* opts) = 0; + virtual void cleanup(const Span* sp) = 0; + virtual void cleanup(const SpanContext* sp) = 0; -/** - * This is the base interface for reading data from carriers. Not much - * functionality here but provides through `dynamic_cast<>`ing the means - * to check if an implementation is supported or not. - */ -class Reader -{ -public: - /** - * Destroys this Reader. - */ - virtual ~Reader(); + protected: + Tracer(); + Tracer(const Tracer&); + // Avoid direct construction }; -/** - * This is an implementation of `Writer` which should be supported - * by every tracing system. It allows the propagation of string key-value - * pairs through carriers. - */ -class TextMapWriter : public virtual Writer -{ -public: - /** - * Destroys this TextMapWriter. - */ - virtual ~TextMapWriter(); - - /** - * Sets a key-value pair to the carrier. `isBaggage` will be true for baggage key-values. - */ - virtual void set(const std::string& key, const std::string& value, bool isBaggage) const = 0; -}; - -/** - * This is an implementation of `Reader` which should be supported - * by every tracing system. It allows joining Spans by using information - * on the form of string key-value pairs from the carriers. - */ -class TextMapReader : public virtual Reader -{ -public: - /** - * Destroys this TextMapWriter. - */ - virtual ~TextMapReader(); - - /** - * Callback functor typically implemented from the tracer in order to retrieve - * key-value pairs from the `TextMapReader`. - */ - struct ReadCallback - { - /** - * Destroys this ReadCallback. - */ - virtual ~ReadCallback(); - - /** - * Will be called for each key-value pair. - */ - virtual void operator() (const std::string& key, const std::string& value, bool isBaggage) const = 0; - }; - - /** - * Reads from the carrier and calls the `callback()` for each key-value pair. - */ - virtual void forEachPair(const ReadCallback & callback) const = 0; -}; - -/** - * Default No-op implementation. Doesn't crash nor has any side-effects. - */ -struct NoopTracer : public Tracer -{ - /** - * Destroys this NoopTracer. - */ - virtual ~NoopTracer(); - - /** - * Starts a `Span` for a given operation name and options defined in - * `startSpanOptions`. - */ - virtual Span * startSpan(const std::string & operationName, const StartSpanOptions & startSpanOptions = StartSpanOptions()) const; - - /** - * The no-op Tracer's `inject()` method should always succeed - */ - virtual Result inject(const Span & sp, const Writer & writer, std::string & error) const; - - - /** - * The no-op Tracer's `join()` method should always return a "trace not found" - * status. - */ - virtual Result join(Span ** sp, const std::string & operationName, const Reader & reader, std::string & error) const; -}; - -/** - * Returns the previous instance of the global tracer or `NULL` if - * the previous version was the default no-op `Tracer`. This method isn't - * thread safe by default. To make it thread-safe define - * `OPENTRACING_USE_STD_ATOMIC` to use `std::atomic<>` or - * `OPENTRACING_USE_BOOST_ATOMIC` to use `boost::atomic<>`. This function - * throws `std::runtime_error` if the `tracer` argument is `NULL`. - */ -Tracer * initGlobalTracer(Tracer * tracer); - -/** - * Returns the global tracer object. It's guaranteed to not be `NULL`. The - * same thread safety rules as for `initGlobalTracer()` apply. - */ -Tracer * globalTracer(); - -} - -#endif // #ifndef OPENTRACING_TRACER_H +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_TRACER_H diff --git a/test/Makefile b/test/Makefile deleted file mode 100644 index 23781c7..0000000 --- a/test/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -CC=g++ -CFLAGS=-Wall -fno-elide-constructors -pedantic-errors -Wextra -Wall -Winit-self -Wold-style-cast -Woverloaded-virtual -Winit-self -Wuninitialized -Wmissing-declarations -Werror -std=c++98 - -# Requires gtest. -# For example for mac: http://stackoverflow.com/questions/20746232/how-to-properly-setup-googletest-on-os-x-aside-from-xcode -# For ubuntu: http://www.eriksmistad.no/getting-started-with-google-test-on-ubuntu/ - -LDFLAGS= - -ODIR=. -LDIR =../lib - -LIBS=-lopentracing -lgtest -lgtest_main -lpthread - -_OBJ = opentracing.t.o -OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) - -$(ODIR)/%.o: %.cc - $(CC) -c -o $@ $< $(CFLAGS) - -test: $(OBJ) - $(CC) -o $@ $^ $(CFLAGS) $(LIBS) $(LDFLAGS) - -.PHONY: clean - -clean: - rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ diff --git a/test/opentracing.t.cc b/test/opentracing.t.cc deleted file mode 100644 index f5d42a0..0000000 --- a/test/opentracing.t.cc +++ /dev/null @@ -1,212 +0,0 @@ -#include -#include - -#include - -#include - -#include - -using namespace opentracing; - -TEST(opentracing, init) -{ - // Get the default tracer. - Tracer * tracer = globalTracer(); - - // The default tracer is non-NULL. - ASSERT_TRUE(tracer); - - // We aren't allowed to set the value to NULL. - ASSERT_THROW(initGlobalTracer(NULL), std::runtime_error); - - // Create a local noop Tracer. - NoopTracer localTracer; - - // It's previous value should be the default tracer - // thus null is returned. We assign to a random value - ASSERT_FALSE(initGlobalTracer(&localTracer)); - - // Note - at this point the globalTracer() points to a completely - // random address. Any operation (apart from retrieval) would be - // expected to fail. - - // This should return the value we just set. - ASSERT_EQ(&localTracer, globalTracer()); - - // Restore tracer (to the default tracer). The value returned should - // be the one we set last. Here the application might be required to - // perform finalizations and/or `delete` the old `tracer` object. - ASSERT_EQ(&localTracer, initGlobalTracer(tracer)); - - // Once again, this should return the value we just set. - ASSERT_EQ(tracer, globalTracer()); -} - -TEST(opentracing, creation) -{ - // Accidentaly forget to assign it anywhere. Doesn't matter. Auto-deletes. - globalTracer()->startSpan("test()"); - - // You can create it and store it. - Span * parent(globalTracer()->startSpan("test()")); - - ASSERT_TRUE(parent); - ASSERT_EQ(&parent->getTracer(), globalTracer()); - - // Or you can create it and use the builder to populate it. - Span * child(globalTracer()->startSpan("test()", StartSpanOptions(parent, 100)) - ->setOperationName("update()") - ->setTag("stringValue", "test") - ->setTag("boolValue", true) - ->setTag("doubleValue", 3.14) - ->setTag("intValue", 12)); - - ASSERT_TRUE(child); - ASSERT_EQ(&child->getTracer(), globalTracer()); - - delete child; - delete parent; -} - -TEST(opentracing, span_ops) -{ - // Create a Span - Span * span = globalTracer()->startSpan("test()"); - - ASSERT_TRUE(span); - - // Set the operation name - span->setOperationName("newName()"); - - // Exercise various setTag() methods - span->setTag("stringValue", "test"); - span->setTag("boolValue", true); - span->setTag("doubleValue", 3.14); - span->setTag("intValue", 12); - - // Exercise different log() cases - LogData tmp; - span->log(tmp); - span->log(LogData("ready")); - span->log(LogData("ready", "{\"j\":\"son\"}")); - - uint64_t now(100); - span->log(LogData(now)); - span->log(LogData(now, "ready")); - span->log(LogData(now, "ready", "{\"j\":\"son\"}")); - - // Exercise bulk log() case - std::vector bulk; - bulk.push_back(tmp); - bulk.push_back(tmp); - span->log(bulk); - - // Exercise baggage functions - span->setBaggageItem("key1", "value1") - ->setBaggageItem("key2", "value2") - ->setBaggageItem("key3", "value3"); - - // No-op implementation shouldn't incur any baggage overhead i.e. - // it should ignore the values despite the fact they're set with - // the previous statement - std::string target; - ASSERT_FALSE(span->getBaggageItem("key1")); - ASSERT_FALSE(span->getBaggageItem("key2")); - ASSERT_FALSE(span->getBaggageItem("key3", &target)); - - // Exercise getTracer() - ASSERT_EQ(&span->getTracer(), globalTracer()); - - // Exercise finish() - span->finish(); - - delete span; -} - -TEST(opentracing, canonicalize_baggage_key) -{ - std::string badKey("some-weird-sign!#"); - ASSERT_FALSE(canonicalizeBaggageKey(badKey)); - - std::string badKey2("-another-sign"); - ASSERT_FALSE(canonicalizeBaggageKey(badKey2)); - - std::string goodKey("000-Capitalized-9"); - ASSERT_TRUE(canonicalizeBaggageKey(goodKey)); - ASSERT_EQ("000-capitalized-9", goodKey); -} - -namespace -{ - -template -class MapTextAdapter : public TextMapWriter, public TextMapReader -{ -public: - MapTextAdapter(T & carrier) - : m_carrier(carrier) - { - } - - virtual ~MapTextAdapter() - { - } - - virtual void set(const std::string& key, const std::string& value, bool isBaggage) const - { - m_carrier.insert(typename T::value_type(key, std::make_pair(value, isBaggage))); - } - - virtual void forEachPair(const ReadCallback & callback) const - { - for (typename T::const_iterator i = m_carrier.begin(); i != m_carrier.end(); ++i) - { - callback(i->first, i->second.first, i->second.second); - } - } - -private: - T & m_carrier; -}; - -} - -typedef std::map > CarrierT; - -TEST(opentracing, propagation_inject) -{ - Span * span = globalTracer()->startSpan("test()"); - - ASSERT_TRUE(span); - - CarrierT carrier; - std::string error; - - Tracer::Result result = globalTracer()->inject( - *span, - MapTextAdapter(carrier), - error); - - ASSERT_EQ(Tracer::Success, result); - - span->finish(); - - delete span; -} - -TEST(opentracing, propagation_join) -{ - CarrierT carrier; - std::string error; - - Span * span(0); - Tracer::Result result = globalTracer()->join( - &span, - "operation()", - MapTextAdapter(carrier), - error); - - ASSERT_EQ(Tracer::ErrTraceNotFound, result); - ASSERT_EQ(0, span); -}