From ded4c0c296fd91d399c8e4aa87cbc07a138dd193 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Wed, 4 Jan 2017 23:24:04 -0500 Subject: [PATCH 01/48] StringRef, BaggageRef, BaggageIterator drafted --- .clang-format | 46 ++++ .gitmodules | 3 + Makefile.am | 15 +- autogen.sh | 1 + configure.ac | 31 ++- example/span_context.h | 90 +++++++ opentracing/baggage.h | 123 ++++++++++ opentracing/carriers.h | 190 +++++++++++++++ opentracing/span.cc | 111 --------- opentracing/span.h | 387 +++++++++++++++--------------- opentracing/spancontext.h | 75 ++++++ opentracing/stringref.h | 91 +++++++ opentracing/tracer.cc | 147 ------------ opentracing/tracer.h | 491 +++++++++++++++----------------------- test/Makefile | 27 ++- test/baggage.t.cc | 205 ++++++++++++++++ test/baggate.t.cc | 35 +++ test/opentracing.t.cc | 212 ---------------- test/stringref.t.cc | 45 ++++ test/unittest.h | 10 + test/unittest.t.cc | 7 + thirdparty/build-gtest.sh | 8 + thirdparty/googletest | 1 + 23 files changed, 1358 insertions(+), 993 deletions(-) create mode 100644 .clang-format create mode 100644 .gitmodules create mode 100644 example/span_context.h create mode 100644 opentracing/baggage.h create mode 100644 opentracing/carriers.h delete mode 100644 opentracing/span.cc create mode 100644 opentracing/spancontext.h create mode 100644 opentracing/stringref.h delete mode 100644 opentracing/tracer.cc create mode 100644 test/baggage.t.cc create mode 100644 test/baggate.t.cc delete mode 100644 test/opentracing.t.cc create mode 100644 test/stringref.t.cc create mode 100644 test/unittest.h create mode 100644 test/unittest.t.cc create mode 100755 thirdparty/build-gtest.sh create mode 160000 thirdparty/googletest diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..baf8fe8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,46 @@ +--- +Language : Cpp +BasedOnStyle : Google +AccessModifierOffset: -2 +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignOperands: true +AllowShortIfStatementsOnASingleLine: false +AllowShortBlocksOnASingleLine: false +AllowShortFunctionsOnASingleLine: false +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakAfterDefinitionReturnType: true +AlwaysBreakAfterReturnType: None +BinPackArguments: false +BinPackParameters: false +BreakConstructorInitializersBeforeComma: true +BraceWrapping: + AfterClass: false + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: true + BeforeElse: true + IndentBraces: false +BreakBeforeBraces: Custom + +ColumnLimit: 80 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 0 +IndentCaseLabels: true +IndentWidth: 4 +MaxEmptyLinesToKeep: 1 +PointerAlignment: Left +SpaceAfterCStyleCast: true +SpaceBeforeParens: ControlStatements +SpacesInContainerLiterals: true +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp03 +TabWidth: 4 +UseTab: Never +... diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b20a243 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "thirdparty/googletest"] + path = thirdparty/googletest + url = https://github.com/google/googletest diff --git a/Makefile.am b/Makefile.am index abdab58..7b965cc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,19 +1,14 @@ 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 +lib_LTLIBRARIES = +nobase_include_HEADERS = opentracing/*.h opentracing/internal/*.h ACLOCAL_AMFLAGS = -I m4 -AM_CXXFLAGS= -fno-elide-constructors -pedantic-errors -ansi -std=c++98 +AM_CXXFLAGS= -fno-elide-constructors -pedantic-errors -ansi if COMPILER_IS_GCC -AM_CXXFLAGS+= -Wall -Werror -Wextra -Winit-self -Wold-style-cast -AM_CXXFLAGS+= -Woverloaded-virtual -Wuninitialized -Wmissing-declarations +AM_CXXFLAGS+= -Wall -Werror -Wextra -Winit-self -Wold-style-cast +AM_CXXFLAGS+= -Woverloaded-virtual -Wuninitialized -Wmissing-declarations endif diff --git a/autogen.sh b/autogen.sh index 52a86ed..7ef875f 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,5 +1,6 @@ #! /bin/sh aclocal \ +&& autoheader \ && automake --add-missing \ && autoconf diff --git a/configure.ac b/configure.ac index 9b89f54..bc70b8d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,29 +1,26 @@ -AC_INIT([libopentracing], [1.0.0]) -#AC_CONFIG_SRCDIR(libopentracing.cc) -#AM_INIT_AUTOMAKE([-Wall -Werror foreign]) -AM_INIT_AUTOMAKE([subdir-objects]) +AC_INIT([libopentracing], [2.0.0]) + +AC_PACKAGE_URL([https://github.com/opentracing/opentracing-cpp]) +AC_PACKAGE_BUGREPORT([https://github.com/opentracing/opentracing-cpp/issues]) +AC_CONFIG_HEADERS([opentracing/config.h]) +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_INCLUDES_DEFAULT +AC_HEADER_ASSERT +AC_TYPE_INT32_T +AC_TYPE_INT64_T +AC_TYPE_UINT64_T +AC_TYPE_UINT64_T +AC_TYPE_SIZE_T -AC_CONFIG_FILES([ - Makefile -]) +AC_CONFIG_FILES([ Makefile ]) AC_OUTPUT diff --git a/example/span_context.h b/example/span_context.h new file mode 100644 index 0000000..18cefc9 --- /dev/null +++ b/example/span_context.h @@ -0,0 +1,90 @@ +#ifndef INCLUDED_OPENTRACING_EXAMPLE_SPAN_CONTEXT_H +#define INCLUDED_OPENTRACING_EXAMPLE_SPAN_CONTEXT_H + +#include + +#include + +namespace example { + +struct span_context : public generic_span_context +{ + public: + typedef std::vector baggage_list; + typedef baggage_list::iterator iterator; + typedef baggage_list::const_iterator iterator; + + iterator + begin() + { + return m_baggage.begin(); + } + + iterator + end() + { + return m_baggage.end(); + } + + const_iterator + begin() const + { + return m_baggage.begin(); + } + + const_iterator + end() const + { + return m_baggage.end(); + } + + int set_baggage(const char* const key, + const size_t klen, + const void* const src, + const size_t src); + + int get_baggage(char* const dest, + const size_t dlen, + const char* const key, + const size_t klen); + + private: + std::vector m_baggage; + +}; + +struct span : public generic_span +{ +} + +struct tracer : public generic_tracer +{ +}; + +typedef generic_tracer Tracer; + + +//// +Tracer* get_instance(); + +Tracer::span_type span; +get_instance->create(&span); +get_instance->create(&span, context[s]); + +span.context().get_baggage(); + +SpanType::SpanContext& c = span.context(); + +c.setBaggage("name", "value"); +c.setBaggage("id", "10"); + +for(const auto& b: c) +{ +} + +get_instance()->inject("key", 3, "val", 3); + + +}; + +#endif diff --git a/opentracing/baggage.h b/opentracing/baggage.h new file mode 100644 index 0000000..5a834c6 --- /dev/null +++ b/opentracing/baggage.h @@ -0,0 +1,123 @@ +#ifndef INCLUDED_OPENTRACING_BAGGAGE_H +#define INCLUDED_OPENTRACING_BAGGAGE_H + +#include + +namespace opentracing { + +class BaggageRef { + public: + BaggageRef(const StringRef& name, const StringRef& value); + + const StringRef& name() const; + const StringRef& value() const; + + const BaggageRef* operator->() const; + + private: + StringRef m_name; + StringRef m_value; +}; + +template +struct BaggageIterator { + public: + typedef typename ADAPTER::iterator iterator; + typedef typename ADAPTER::const_iterator const_iterator; + + BaggageIterator(const iterator& iter); + BaggageIterator(const const_iterator& iter); + + BaggageRef operator*() const; + BaggageRef operator->() const; + + BaggageIterator operator++(int); + BaggageIterator operator++(); + + bool operator==(const BaggageIterator& other) const; + bool operator!=(const BaggageIterator& other) const; + + private: + const_iterator d_iterator; + ADAPTER d_handler; +}; + +inline BaggageRef::BaggageRef(const StringRef& name, const StringRef& value) +: m_name(name), m_value(value) +{ +} + +inline const StringRef& +BaggageRef::name() const +{ + return m_name; +} + +inline const StringRef& +BaggageRef::value() const +{ + return m_value; +} + +inline const BaggageRef* BaggageRef::operator->() const +{ + return this; +} + +template +BaggageIterator::BaggageIterator(const iterator& iter) +: d_iterator(iter), d_handler() +{ +} + +template +BaggageIterator::BaggageIterator(const const_iterator& iter) +: d_iterator(iter), d_handler() +{ +} + +template +BaggageRef BaggageIterator::operator*() const +{ + return d_handler(d_iterator); +} + +template +BaggageRef BaggageIterator::operator->() const +{ + return d_handler(d_iterator); +} + +template +BaggageIterator BaggageIterator::operator++(int) +{ + BaggageIterator tmp(*this); + ++d_iterator; + return tmp; +} + +template +BaggageIterator BaggageIterator::operator++() +{ + ++d_iterator; + return *this; +} + +template +bool +BaggageIterator::operator==( + const BaggageIterator& other) const +{ + return d_iterator == other.d_iterator; +} + +template +bool +BaggageIterator::operator!=( + const BaggageIterator& other) const +{ + return d_iterator != other.d_iterator; +} + +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_BAGGAGE_H diff --git a/opentracing/carriers.h b/opentracing/carriers.h new file mode 100644 index 0000000..8c6ca39 --- /dev/null +++ b/opentracing/carriers.h @@ -0,0 +1,190 @@ +#ifndef INCLUDED_OPENTRACING_CARRIERS_H +#define INCLUDED_OPENTRACING_CARRIERS_H + +#include + +#if HAVE_STDINT_H +#include +#endif + +#include +#include + +namespace opentracing { + +// Text map carriers +template +class GenericTextWriter { + public: + int inject(const std::map& Textmap); + // Inject the supplied 'Textmap' into this carrier. + + protected: + GenericTextWriter(); + GenericTextWriter(const GenericTextWriter&); + // Protected to avoid direct construction +}; + +template +class GenericTextReader { + public: + int extract(std::map* const Textmap) const; + // Extract the supplied 'Textmap' from this carrier. + + protected: + GenericTextReader(); + GenericTextReader(const GenericTextReader&); +}; + +// Binary carriers +template +class GenericBinaryWriter { + public: + int inject(const void* const buf, const size_t len); + // Inject the supplied 'buf' of 'len' bytes into this carrier. + + protected: + GenericBinaryWriter(); + GenericBinaryWriter(const GenericBinaryWriter&); +}; + +template +class GenericBinaryReader { + public: + int extract(void* const buf, const size_t len) const; + // Extract up to 'len' bytes of the binary representation of a span context + // into 'buf'. + + protected: + GenericBinaryReader(); + GenericBinaryReader(const GenericBinaryReader&); +}; + +// Explicit carriers +template +class GenericWriter { + public: + int inject(const SPAN_CONTEXT& context); + // Inject the supplied 'context' directly into this carrier. + + protected: + GenericWriter(); + GenericWriter(const GenericWriter&); +}; + +template +class GenericReader { + public: + int extract(SPAN_CONTEXT* const context) const; + // Extract the supplied 'context' directly from this carrier. + + private: + GenericReader(); + GenericReader(const GenericReader&); +}; + +template +int +GenericTextWriter::inject(const std::map& Textmap) +{ + return static_cast(this)->inject(Textmap); +} + +template +GenericTextWriter::GenericTextWriter() +{ +} + +template +GenericTextWriter::GenericTextWriter(const GenericTextWriter&) +{ +} + +template +int +GenericTextReader::extract( + std::map* const Textmap) const +{ + return static_cast(this)->extract(Textmap); +} + +template +GenericTextReader::GenericTextReader() +{ +} + +template +GenericTextReader::GenericTextReader(const GenericTextReader&) +{ +} + +template +int +GenericBinaryWriter::inject(const void* buf, const size_t len) +{ + return static_cast(this)->inject(buf, len); +} + +template +GenericBinaryWriter::GenericBinaryWriter() +{ +} + +template +GenericBinaryWriter::GenericBinaryWriter(const GenericBinaryWriter&) +{ +} + +template +int +GenericBinaryReader::extract(void* const buf, const size_t len) const +{ + return static_cast(this)->extract(buf, len); +} + +template +GenericBinaryReader::GenericBinaryReader() +{ +} + +template +GenericBinaryReader::GenericBinaryReader(const GenericBinaryReader&) +{ +} + +template +int +GenericWriter::inject(const SPAN_CONTEXT& context) +{ + return static_cast(this)->inject(context); +} + +template +GenericWriter::GenericWriter() +{ +} + +template +GenericWriter::GenericWriter(const GenericWriter&) +{ +} + +template +int +GenericReader::extract(SPAN_CONTEXT* const context) const +{ + return static_cast(this)->extract(context); +} + +template +GenericReader::GenericReader() +{ +} + +template +GenericReader::GenericReader(const GenericReader&) +{ +} + +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_CARRIERS_H 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..097aed3 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -1,200 +1,205 @@ -#ifndef OPENTRACING_SPAN_H -#define OPENTRACING_SPAN_H - -#include -#include -#include -#include - -namespace opentracing -{ - -class Tracer; -class LogData; - -/** - * 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. - */ - 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. - */ - 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); +#ifndef INCLUDED_OPENTRACING_SPAN_H +#define INCLUDED_OPENTRACING_SPAN_H + +#include +#include + +namespace opentracing { + +template +class GenericSpan { + public: + typedef IMPL Span; + typedef Span::SpanContext SpanContext; + + SpanContext& context(); + const SpanContext& context() const; + // Return the SpanContext associated with this span. Baggage can + // be set or accessed through the underlying context directly. + + int finish(); + int finish(const uint64_t tsp); + // Finish this span. Mark the end of the span (in microseconds since epoch) + // using the 'tsp' time-stamp. If 'tsp' is not supplied, the internal + // wall-time should be used to mark the end of the span instead. It is + // undefined behavior to call any method on this span after 'finish' is + // called, except for 'context()'. + + int tag(const StringRef& key, const bool val); + int tag(const StringRef& key, const int64_t val); + int tag(const StringRef& key, const uint64_t val); + int tag(const StringRef& key, const double val); + int tag(const StringRef& key, const StringRef& val); + // Set a tag on this span, associating the supplied 'key' characters to + // the supplied value. + + int log(const StringRef& key, const bool val); + int log(const StringRef& key, const int64_t val); + int log(const StringRef& key, const uint64_t val); + int log(const StringRef& key, const double val); + int log(const StringRef& key, const StringRef& val); + + int log(const StringRef& key, const bool val, const uint64_t tsp); + int log(const StringRef& key, const int64_t val, const uint64_t tsp); + int log(const StringRef& key, const uint64_t val, const uint64_t tsp); + int log(const StringRef& key, const double val, const uint64_t tsp); + int log(const StringRef& key, const StringRef& val, const uint64_t tsp); + // Structured data should be logged through one of the calls to 'log'. + // From this point forward, this span will associate 'key' with the + // supplied 'value'. This is similar to 'tag()', but additionally includes + // a time-stamp noting the number of microseconds that have elapsed since + // the Unix epoch. If time-stamp is not supplied, the current wall-time + // is used, otherwise the explicit time-stamp is used. The time-stamp + // should be between the start and finish times for this span. + + protected: + GenericSpan(); + GenericSpan(const GenericSpan&); + // 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 -{ -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; -}; +template +GenericSpan::GenericSpan() +{ +} + +template +GenericSpan::GenericSpan(const GenericSpan&) +{ +} + +template +GenericSpan::SpanContext& +GenericSpan::context() +{ + return static_cast(this)->context(); +} + +template +const GenericSpan::SpanContext& +GenericSpan::context() const +{ + return static_cast(this)->context(); +} + +template +int +GenericSpan::finish() +{ + return static_cast(this)->finish(); +} -/** - * `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); +template +int +GenericSpan::finish(const uint64_t tsp) +{ + return static_cast(this)->finish(tsp); +} + +template +int +GenericSpan::tag(const StringRef& key, const bool val) +{ + return static_cast(this)->tag(val); +} + +template +int +GenericSpan::tag(const StringRef& key, const int64_t val) +{ + return static_cast(this)->tag(key, val); +} + +template +int +GenericSpan::tag(const StringRef& key, const uint64_t val) +{ + return static_cast(this)->tag(key, val); +} + +template +int +GenericSpan::tag(const StringRef& key, const double val) +{ + return static_cast(this)->tag(key, val); +} -/** - * Default `setTag()` implementation. - */ -template -Span * Span::setTag(const std::string & key, const T & value) +template +int +GenericSpan::tag(const StringRef& key, const StringRef& val) { - std::ostringstream oss; - oss << value; - setTag(key, oss.str()); - return this; + return static_cast(this)->tag(key, val, vlen); } +template +int +GenericSpan::log(const StringRef& key, const bool val) +{ + return static_cast(this)->log(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, const int64_t val) +{ + return static_cast(this)->log(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, const uint64_t val) +{ + return static_cast(this)->log(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, const double val) +{ + return static_cast(this)->log(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, const StringRef& val) +{ + return static_cast(this)->log(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, const bool val, const uint64_t tsp) +{ + return static_cast(this)->log(key, val, tsp); +} + +template +int +GenericSpan::log(const StringRef& key, const int64_t val, const uint64_t tsp) +{ + return static_cast(this)->log(key, val, tsp); +} + +template +int +GenericSpan::log(const StringRef& key, const uint64_t val, const uint64_t tsp) +{ + return static_cast(this)->log(key, val, tsp); +} + +template +int +GenericSpan::log(const StringRef& key, const double val, const uint64_t tsp) +{ + return static_cast(this)->log(key, val, tsp); +} + +template +int +GenericSpan::log(const StringRef& key, const StringRef& val, const uint64_t tsp) +{ + return static_cast(this)->log(key, val, tsp); } -#endif // #define OPENTRACING_SPAN_H +} // end namespace opentracing +#endif // INCLUDED_OPENTRACING_SPAN_H diff --git a/opentracing/spancontext.h b/opentracing/spancontext.h new file mode 100644 index 0000000..42bff41 --- /dev/null +++ b/opentracing/spancontext.h @@ -0,0 +1,75 @@ +#ifndef INCLUDED_OPENTRACING_SPANCONTEXT_H +#define INCLUDED_OPENTRACING_SPANCONTEXT_H + +#include +#include + +namespace opentracing { + +template +class GenericSpanContext { + public: + typedef IMPL SpanContext; + typedef SpanContext::BaggageIteratorImpl IteratorImpl; + typedef SpanContext::BaggageHandler BaggageHandler; + + typedef BaggageIterator const_iterator; + + typedef BaggageIterator const_iterator; + + const_iterator begin() const; + const_iterator end() const; + // Return iterators to baggage managed by this span_context. + + int setBaggage(const StringRef& key, const StringRef& baggage); + // Associate the supplied 'key' with the 'baggage'. + + int getBaggage(StringRef* const baggage, const StringRef& key); + // Load the 'baggage' associated with 'key'. + + private: + GenericSpanContext(); + GenericSpanContext(const GenericSpanContext&); + // Protected to avoid direct construction +}; + +template +GenericSpanContext::GenericSpanContext() +{ +} + +template +GenericSpanContext::GenericSpanContext(const GenericSpanContext&) +{ +} + +template +GenericSpanContext::const_iterator +GenericSpanContext::begin() const +{ + return const_iterator(static_cast(this)->begin()); +} + +template +GenericSpanContext::const_iterator +GenericSpanContext::end() const +{ + return const_iterator(static_cast(this)->end()); +} + +template +int +GenericSpanContext::setBaggage(const StringRef& key, const StringRef& baggage) +{ + return static_cast(this)->setBaggage(key, baggage); +} + +template +int +GenericSpanContext::get_baggage(StringRef* const baggage, + const StringRef& key) const +{ + return static_cast(this)->get_baggage(baggage, key); +} +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_SPANCONTEXT_H diff --git a/opentracing/stringref.h b/opentracing/stringref.h new file mode 100644 index 0000000..426020e --- /dev/null +++ b/opentracing/stringref.h @@ -0,0 +1,91 @@ +#ifndef INCLUDED_OPENTRACING_STRINGREF_H +#define INCLUDED_OPENTRACING_STRINGREF_H + +#include + +#include +#include + +namespace opentracing { + +// --------- +// StringRef +// --------- +// Represent a constant reference to an external character, which does not have +// to be null terminated. This class does not own the string 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. + +struct StringRef { + public: + 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::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 * + + 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 + + const char* m_data; + size_t m_length; +}; + +template +inline StringRef::StringRef(const char (&str)[N]) : m_data(str), m_length(N - 1) +{ +} + +inline StringRef::StringRef(const char* const str) +: m_data(str), m_length(std::strlen(str)) +{ +} + +inline StringRef::StringRef(const std::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 const char* +StringRef::data() const +{ + return m_data; +} + +inline size_t +StringRef::length() const +{ + return m_length; +} + +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_STRINGREF_H 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..a28620a 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -1,322 +1,219 @@ -#ifndef OPENTRACING_TRACER_H -#define OPENTRACING_TRACER_H +#ifndef INCLUDED_OPENTRACING_TRACER_H +#define INCLUDED_OPENTRACING_TRACER_H -#include +#include + +#ifdef HAVE_STDINT_H #include +#endif + +#include +#include + +namespace opentracing { + +template +class GenericTracer { + typedef IMPL Tracer; + typedef Tracer::Span Span; + typedef Span::SpanContext SpanContext; + + int start(Span* const sp, const StringRef& operation); + int start(Span* const sp, const StringRef& operation, const uint64_t tsp); + + int start(Span* const sp, + const StringRef& operation, + const SpanContext& parent); + + int start(Span* const sp, + const StringRef& operation, + const SpanContext& parent, + const uint64_t tsp); + + template + int start(Span* const sp, + const StringRef& operation, + const ITER begin, + const ITER end); + + template + int start(Span* const sp, + const StringRef& operation, + const ITER begin, + const ITER end, + const uint64_t tsp); + // The 'start' methods are used to load a new 'Span'. The only required + // parameter is the 'operation' description, which should outline the + // work being performed during the Span. + // + // The optional arguments are: + // parent: + // Reference a single parent Span's context, establishing this + // Span's trace id + // + // begin/end: + // A set of iterators that outline a range of parent Span contexts. + // This Span should be marked as a child of all the supplied + // parents. ITER must be a forward iterator, that when dereferenced, + // can be stored in a `const SpanContext&`. + // + // tsp: + // The time-stamp marking the start of the Span, in microseconds. + // If not supplied, the current wall-time should be used. + + template + int inject(GenericTextWriter* const carrier, + const SpanContext& context) const; + // Inject the supplied 'context' into the text map writer 'carrier'. + + template + int extract(SpanContext* const context, + const GenericTextReader& carrier); + // Extract the supplied 'context' from the text map reader 'carrier'. + + template + int inject(GenericBinaryWriter* const carrier, + const SpanContext& context) const; + // Inject the supplied 'context' into the binary writer 'carrier'. + + template + int extract(SpanContext* const context, + const GenericBinaryReader& carrier); + // Extract the supplied 'context' from the binary reader 'carrier'. + + template + int inject(GenericWriter* const carrier, + const SpanContext& context) const; + // Inject the SpanContext directly into the specialized 'carrier'. + // + // Note: The carrier will be passed the 'SpanContext' directly. Using + // this may make your carrier code more efficient, but it removes + // flexibility if you want to swap Tracer/Span implementations later. + + template + int extract(SpanContext* const context, + const GenericReader& carrier); + // Extract the SpanContext from the specialized 'carrier'. + // + // Note: The carrier will be passed the 'SpanContext' directly. Using + // this may make your carrier code more efficient, but it removes + // flexibility if you want to swap Tracer/Span implementations later. + + protected: + GenericTracer(); + GenericTracer(const GenericTracer&); + // Protected to avoid direct construction +}; -namespace opentracing +template +GenericTracer::GenericTracer() { +} -class Span; -class Writer; -class Reader; - -/** - * Options used when you start a `Span`. - */ -struct StartSpanOptions +template +GenericTracer::GenericTracer(const GenericTracer&) { - /** - * The parent span. `NULL` if there's no parent `Span`. - */ - const Span * parent; - - /** - * 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 +template +int +GenericTracer::start(Span* const Span) { -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, - - /** - * `ErrTraceCorrupted` occurs when the `carrier` passed to `Tracer::join()` is - * of the expected type but is corrupted. - */ - ErrTraceCorrupted - }; - - /** - * 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; - - /** - * `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; - - /** - * `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; -}; + return static_cast(this)->start(Span); +} -/** - * 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 +template +int +GenericTracer::start(Span* const sp, const uint64_t tsp) { -public: - /** - * Destroys this Writer. - */ - virtual ~Writer(); -}; + return static_cast(this)->start(sp, tsp); +} -/** - * 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 +template +int +GenericTracer::start(Span* const sp, const SpanContext& parent) { -public: - /** - * Destroys this Reader. - */ - virtual ~Reader(); -}; + return static_cast(this)->start(sp, parent); +} -/** - * 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 +template +int +GenericTracer::start(Span* const sp, + const SpanContext& parent, + const uint64_t tsp) { -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; -}; + return static_cast(this)->start(sp, parent, tsp); +} -/** - * 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 +template +int +GenericTracer::start(Span* const sp, const ITER begin, const ITER end) { -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; -}; + return static_cast(this)->start(sp, begin, end); +} -/** - * Default No-op implementation. Doesn't crash nor has any side-effects. - */ -struct NoopTracer : public Tracer +template +int +GenericTracer::start(Span* const sp, + const ITER begin, + const ITER end, + const uint64_t tsp) { - /** - * 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; + return static_cast(this)->start(sp, begin, end, tsp); +} +template +template +int +GenericTracer::inject(GenericTextWriter* const carrier, + const SpanContext& context) const +{ + return static_cast(this)->inject(carrier, context); +} - /** - * 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; -}; +template +template +int +GenericTracer::extract(SpanContext* const context, + const GenericTextReader& carrier) +{ + return static_cast(this)->extract(context, carrier); +} -/** - * 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); +template +template +int +GenericTracer::inject(GenericBinaryWriter* const carrier, + const SpanContext& context) const +{ + return static_cast(this)->inject(carrier, context); +} -/** - * Returns the global tracer object. It's guaranteed to not be `NULL`. The - * same thread safety rules as for `initGlobalTracer()` apply. - */ -Tracer * globalTracer(); +template +template +int +GenericTracer::extract(SpanContext* const context, + const GenericBinaryReader& carrier) +{ + return static_cast(this)->extract(context, carrier); +} +template +template +int +GenericTracer::inject(GenericWriter* const carrier, + const SpanContext& context) const +{ + return static_cast(this)->inject(carrier, context); } -#endif // #ifndef OPENTRACING_TRACER_H +template +template +int +GenericTracer::extract(SpanContext* const context, + const GenericReader& carrier) +{ + return static_cast(this)->extract(context, carrier); +} +} +#endif diff --git a/test/Makefile b/test/Makefile index 23781c7..4101664 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,25 +1,36 @@ 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. +OPENTRACING_INCLUDE=../ +OPENTRACING_SRC=$(wildcard ${OPENTRACING_INCLUDED}/*.h) +OPENTRACING_HEADERS= $(wildcard ${OPENTRACING_INCLUDE} +THIRDPARTY_ROOT=../thirdparty + +GTEST_INCLUDE=${THIRDPARTY_ROOT}/googletest/googletest/include +GTEST_LIBS=${THIRDPARTY_ROOT}/ + +INCLUDES=-I. -I${GTEST_INCLUDE} -I${OPENTRACING_INCLUDE} + +CXXFLAGS=-Wall -fno-elide-constructors -Wextra -Wall -Winit-self -Wold-style-cast -Woverloaded-virtual -Winit-self -Wuninitialized -Wmissing-declarations -Werror ${INCLUDES} + +# 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 +LDIR =${GTEST_LIBS} -LIBS=-lopentracing -lgtest -lgtest_main -lpthread +LIBS=-L${GTEST_LIBS} -lgtest -lpthread -_OBJ = opentracing.t.o +_OBJ = baggage.t.o stringref.t.o unittest.t.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) -$(ODIR)/%.o: %.cc - $(CC) -c -o $@ $< $(CFLAGS) +$(ODIR)/%.o: %.cc ${OPENTRACING_SRC} + $(CC) -c -o $@ $< $(CXXFLAGS) test: $(OBJ) - $(CC) -o $@ $^ $(CFLAGS) $(LIBS) $(LDFLAGS) + $(CC) -o $@ $^ $(CXXFLAGS) $(LIBS) $(LDFLAGS) .PHONY: clean diff --git a/test/baggage.t.cc b/test/baggage.t.cc new file mode 100644 index 0000000..77dac12 --- /dev/null +++ b/test/baggage.t.cc @@ -0,0 +1,205 @@ +#include "unittest.h" + +#include // test include guard +#include + +#include +#include +#include + +TEST(BaggageRef, Constructor) +{ + const char n[] = "hello"; + const char v[] = "world"; + + BaggageRef ref(n, v); + + ASSERT_EQ(n, ref.name().data()); + ASSERT_EQ(v, ref.value().data()); +} + +TEST(BaggageRef, CopyConstructor) +{ + const char n[] = "hello"; + const char v[] = "world"; + + BaggageRef ref(n, v); + BaggageRef cpy(ref); + + ASSERT_EQ(n, cpy.name().data()); + ASSERT_EQ(v, cpy.value().data()); +} + +TEST(BaggageRef, Assignment) +{ + const char n[] = "hello"; + const char v[] = "world"; + + const char n2[] = "hello"; + const char v2[] = "world"; + + BaggageRef ref(n, v); + BaggageRef ref2(n2, v2); + + ref = ref2; + + ASSERT_EQ(n2, ref.name().data()); + ASSERT_EQ(v2, ref.value().data()); +} + +// BaggageIterator adapter for map +struct MapBaggage { + typedef std::map Map; + typedef Map::iterator iterator; + typedef Map::const_iterator const_iterator; + + BaggageRef + operator()(const Map::const_iterator& iter) const + { + return BaggageRef(iter->first, iter->second); + } +}; + +TEST(BaggageIterator, MapBaggageAdapter) +{ + MapBaggage::Map m; + m["animal"] = "dog"; + m["fruit"] = "apple"; + m["veggie"] = "carrot"; + + BaggageIterator it(m.begin()); + BaggageIterator end(m.end()); + + ASSERT_FALSE(end == it); + BaggageRef ref = *it; + + ASSERT_STREQ("animal", ref.name()); + ASSERT_STREQ("dog", ref.value()); + + BaggageIterator prev = it++; + ASSERT_FALSE(prev == end); + ASSERT_FALSE(it == end); + + ref = *prev; + + ASSERT_STREQ("animal", ref.name()); + ASSERT_STREQ("dog", ref.value()); + + ref = *it; + + ASSERT_STREQ("fruit", ref.name()); + ASSERT_STREQ("apple", ref.value()); + + ++it; + ASSERT_FALSE(end == it); + + ref = *it; + + ASSERT_STREQ("veggie", ref.name()); + ASSERT_STREQ("carrot", ref.value()); + + ++it; + + ASSERT_TRUE(end == it); +} + +TEST(BaggageIterator, EmptyMapBaggage) +{ + MapBaggage::Map m; + + BaggageIterator it(m.begin()); + BaggageIterator end(m.end()); + + ASSERT_TRUE(end == it); +} + +TEST(BaggageIterator, ForLoopSyntax) +{ + MapBaggage::Map m; + m["animal"] = "dog"; + m["fruit"] = "apple"; + m["veggie"] = "carrot"; + + const char * expectedKeys[] = {"animal", "fruit", "veggie"}; + const char * expectedVals[] = {"dog", "apple", "carrot"}; + size_t index = 0; + + for (BaggageIterator it = m.begin(), end = m.end(); it != end; + ++it, ++index) + { + // Test the -> syntax works + ASSERT_STREQ(expectedKeys[index], it->name()); + ASSERT_STREQ(expectedVals[index], it->value()); + } +} + +// Adapter for BaggageIterator, wrapping a stl list +struct ListBaggageAdapter { + struct KVP { + std::string key; + std::string val; + }; + + typedef std::list List; + typedef List::iterator iterator; + typedef List::const_iterator const_iterator; + + BaggageRef + operator()(const const_iterator& iter) const + { + return BaggageRef(iter->key, iter->val); + } +}; + +TEST(BaggageIterator, ListBaggageAdapter) +{ + ListBaggageAdapter::List seq; + + ListBaggageAdapter::KVP tmp; + tmp.key = "animal"; + tmp.val = "dog"; + seq.push_back(tmp); + + tmp.key = "fruit"; + tmp.val = "apple"; + seq.push_back(tmp); + + tmp.key = "veggie"; + tmp.val = "carrot"; + seq.push_back(tmp); + + BaggageIterator it(seq.begin()); + BaggageIterator end(seq.end()); + + ASSERT_FALSE(end == it); + BaggageRef ref = *it; + + ASSERT_STREQ("animal", ref.name()); + ASSERT_STREQ("dog", it->value()); + + BaggageIterator prev = it++; + ASSERT_FALSE(prev == end); + ASSERT_FALSE(it == end); + + ref = *prev; + + ASSERT_STREQ("animal", ref.name()); + ASSERT_STREQ("dog", ref.value()); + + ref = *it; + + ASSERT_STREQ("fruit", ref.name()); + ASSERT_STREQ("apple", ref.value()); + + ++it; + ASSERT_FALSE(end == it); + + ref = *it; + + ASSERT_STREQ("veggie", ref.name()); + ASSERT_STREQ("carrot", ref.value()); + + ++it; + + ASSERT_TRUE(end == it); +} diff --git a/test/baggate.t.cc b/test/baggate.t.cc new file mode 100644 index 0000000..c8a85eb --- /dev/null +++ b/test/baggate.t.cc @@ -0,0 +1,35 @@ +#include "unittest.h" + +#include // test include guard +#include + +TEST(StringRef, CString) +{ + const char * val = "hello world"; + + StringRef ref(val); + + ASSERT_EQ(val, ref.m_string); + ASSERT_EQ(std::strlen(val), ref.m_length); +} + +TEST(StringRef, CStringArray) +{ + const char val[] = "hello world"; + + StringRef ref(val); + + ASSERT_EQ(val, ref.m_string); + ASSERT_EQ(std::strlen(val), ref.m_length); +} + +TEST(StringRef, StdString) +{ + const std::string val = "hello world"; + + StringRef ref(val); + + ASSERT_EQ(val, ref.m_string); + ASSERT_EQ(val.length(), ref.m_length); +} + 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); -} diff --git a/test/stringref.t.cc b/test/stringref.t.cc new file mode 100644 index 0000000..7986732 --- /dev/null +++ b/test/stringref.t.cc @@ -0,0 +1,45 @@ +#include "unittest.h" + +#include // test include guard +#include + +TEST(StringRef, CString) +{ + const char * val = "hello world"; + + StringRef ref(val); + + ASSERT_EQ(val, ref.data()); + ASSERT_EQ(std::strlen(val), ref.length()); +} + +TEST(StringRef, CStringArray) +{ + const char val[] = "hello world"; + + StringRef ref(val); + + ASSERT_EQ(val, ref.data()); + ASSERT_EQ(std::strlen(val), ref.length()); +} + +TEST(StringRef, StdString) +{ + const std::string val = "hello world"; + + StringRef ref(val); + + ASSERT_EQ(val, ref.data()); + ASSERT_EQ(val.length(), ref.length()); +} + +TEST(StringRef, Copy) +{ + const std::string val = "hello world"; + + StringRef ref(val); + StringRef cpy(ref); + + ASSERT_EQ(val, cpy.data()); + ASSERT_EQ(val.length(), cpy.length()); +} diff --git a/test/unittest.h b/test/unittest.h new file mode 100644 index 0000000..0a33a6a --- /dev/null +++ b/test/unittest.h @@ -0,0 +1,10 @@ +#ifndef INCLUDED_OPENTRACING_UNITTEST_H +#define INCLUDED_OPENTRACING_UNITTEST_H + +#include + +namespace opentracing{}; + +using namespace opentracing; + +#endif diff --git a/test/unittest.t.cc b/test/unittest.t.cc new file mode 100644 index 0000000..3c5739a --- /dev/null +++ b/test/unittest.t.cc @@ -0,0 +1,7 @@ +#include "unittest.h" + +int main(int argc, char *argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/thirdparty/build-gtest.sh b/thirdparty/build-gtest.sh new file mode 100755 index 0000000..ec2a624 --- /dev/null +++ b/thirdparty/build-gtest.sh @@ -0,0 +1,8 @@ + +mkdir -f gtest-build +cd gtest-build + +GTEST_DIR=../googletest/googletest + +g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} -pthread -c ${GTEST_DIR}/src/gtest-all.cc +ar -rv libgtest.a gtest-all.o diff --git a/thirdparty/googletest b/thirdparty/googletest new file mode 160000 index 0000000..ec44c6c --- /dev/null +++ b/thirdparty/googletest @@ -0,0 +1 @@ +Subproject commit ec44c6c1675c25b9827aacd08c02433cccde7780 From 3381ca1b52c519c8b1cdc3ffa8465ac3d6315b2a Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Thu, 5 Jan 2017 16:48:28 -0500 Subject: [PATCH 02/48] Testing everything, at least a little --- .gitignore | 21 +++ configure.ac | 4 +- opentracing/carriers.h | 146 +++++++++++----- opentracing/span.h | 343 +++++++++++++++++++++++++++++--------- opentracing/spancontext.h | 62 +++---- opentracing/stringref.h | 52 ++++++ opentracing/tracer.h | 264 +++++++++++++++++------------ test/Makefile | 8 +- test/baggate.t.cc | 35 ---- test/carriers.h | 95 +++++++++++ test/carriers.t.cc | 149 +++++++++++++++++ test/span.h | 212 +++++++++++++++++++++++ test/span.t.cc | 74 ++++++++ test/spancontext.h | 88 ++++++++++ test/spancontext.t.cc | 51 ++++++ test/stringref.t.cc | 55 ++++++ test/tracer.h | 178 ++++++++++++++++++++ test/tracer.t.cc | 237 ++++++++++++++++++++++++++ test/unittest.h | 7 + 19 files changed, 1788 insertions(+), 293 deletions(-) create mode 100644 .gitignore delete mode 100644 test/baggate.t.cc create mode 100644 test/carriers.h create mode 100644 test/carriers.t.cc create mode 100644 test/span.h create mode 100644 test/span.t.cc create mode 100644 test/spancontext.h create mode 100644 test/spancontext.t.cc create mode 100644 test/tracer.h create mode 100644 test/tracer.t.cc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6b2160c --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +*.o +*.a +*.so +config.h +config.h.in +*.in +*.m4 +Makefile +config.* +*/.deps/* +stamp-h1 +*/.dirstamp +INSTALL +autom4te.cache/* +compile +configure +depcomp +install-sh +libtool +ltmain.sh +missing diff --git a/configure.ac b/configure.ac index bc70b8d..efa1826 100644 --- a/configure.ac +++ b/configure.ac @@ -16,9 +16,11 @@ AC_PROG_MAKE_SET AC_INCLUDES_DEFAULT AC_HEADER_ASSERT +AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T -AC_TYPE_UINT64_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_SIZE_T diff --git a/opentracing/carriers.h b/opentracing/carriers.h index 8c6ca39..76f2954 100644 --- a/opentracing/carriers.h +++ b/opentracing/carriers.h @@ -7,16 +7,28 @@ #include #endif -#include +#include + #include +#include namespace opentracing { +struct TextMapPair { + TextMapPair(); + TextMapPair(const StringRef& name, const StringRef& value); + + std::string m_name; + std::string m_value; +}; + // Text map carriers template class GenericTextWriter { public: - int inject(const std::map& Textmap); + virtual ~GenericTextWriter(); + + int inject(const std::vector& textmap); // Inject the supplied 'Textmap' into this carrier. protected: @@ -28,7 +40,9 @@ class GenericTextWriter { template class GenericTextReader { public: - int extract(std::map* const Textmap) const; + virtual ~GenericTextReader(); + + int extract(std::vector* const textmap) const; // Extract the supplied 'Textmap' from this carrier. protected: @@ -40,6 +54,8 @@ class GenericTextReader { template class GenericBinaryWriter { public: + virtual ~GenericBinaryWriter(); + int inject(const void* const buf, const size_t len); // Inject the supplied 'buf' of 'len' bytes into this carrier. @@ -51,9 +67,11 @@ class GenericBinaryWriter { template class GenericBinaryReader { public: - int extract(void* const buf, const size_t len) const; + virtual ~GenericBinaryReader(); + + int extract(void* const buf, size_t* const written, const size_t len) const; // Extract up to 'len' bytes of the binary representation of a span context - // into 'buf'. + // into 'buf' then store the number of bytes 'written'. protected: GenericBinaryReader(); @@ -61,10 +79,12 @@ class GenericBinaryReader { }; // Explicit carriers -template +template class GenericWriter { public: - int inject(const SPAN_CONTEXT& context); + virtual ~GenericWriter(); + + int inject(const CONTEXT& context); // Inject the supplied 'context' directly into this carrier. protected: @@ -72,117 +92,161 @@ class GenericWriter { GenericWriter(const GenericWriter&); }; -template +template class GenericReader { public: - int extract(SPAN_CONTEXT* const context) const; + virtual ~GenericReader(); + + int extract(CONTEXT* const context) const; // Extract the supplied 'context' directly from this carrier. - private: + protected: GenericReader(); GenericReader(const GenericReader&); }; +// Inline Definitions + +inline TextMapPair::TextMapPair() : m_name(), m_value() +{ +} + +inline TextMapPair::TextMapPair(const StringRef& name, const StringRef& value) +: m_name(name.data(), name.length()), m_value(value.data(), value.length()) +{ +} + template int -GenericTextWriter::inject(const std::map& Textmap) +GenericTextWriter::inject(const std::vector& textmap) +{ + return static_cast(this)->injectImp(textmap); +} + +template +GenericTextWriter::~GenericTextWriter() { - return static_cast(this)->inject(Textmap); } template -GenericTextWriter::GenericTextWriter() +GenericTextWriter::GenericTextWriter() { } template -GenericTextWriter::GenericTextWriter(const GenericTextWriter&) +GenericTextWriter::GenericTextWriter(const GenericTextWriter&) { } template int -GenericTextReader::extract( - std::map* const Textmap) const +GenericTextReader::extract(std::vector* const textmap) const { - return static_cast(this)->extract(Textmap); + return static_cast(this)->extractImp(textmap); } template -GenericTextReader::GenericTextReader() +GenericTextReader::~GenericTextReader() { } template -GenericTextReader::GenericTextReader(const GenericTextReader&) +GenericTextReader::GenericTextReader() +{ +} + +template +GenericTextReader::GenericTextReader(const GenericTextReader&) { } template int -GenericBinaryWriter::inject(const void* buf, const size_t len) +GenericBinaryWriter::inject(const void* buf, const size_t len) { - return static_cast(this)->inject(buf, len); + return static_cast(this)->injectImp(buf, len); } template -GenericBinaryWriter::GenericBinaryWriter() +GenericBinaryWriter::~GenericBinaryWriter() { } template -GenericBinaryWriter::GenericBinaryWriter(const GenericBinaryWriter&) +GenericBinaryWriter::GenericBinaryWriter() +{ +} + +template +GenericBinaryWriter::GenericBinaryWriter(const GenericBinaryWriter&) { } template int -GenericBinaryReader::extract(void* const buf, const size_t len) const +GenericBinaryReader::extract(void* const buf, + size_t* const written, + const size_t len) const +{ + return static_cast(this)->extractImp(buf, written, len); +} + +template +GenericBinaryReader::~GenericBinaryReader() { - return static_cast(this)->extract(buf, len); } template -GenericBinaryReader::GenericBinaryReader() +GenericBinaryReader::GenericBinaryReader() { } template -GenericBinaryReader::GenericBinaryReader(const GenericBinaryReader&) +GenericBinaryReader::GenericBinaryReader(const GenericBinaryReader&) { } -template +template int -GenericWriter::inject(const SPAN_CONTEXT& context) +GenericWriter::inject(const CONTEXT& context) { - return static_cast(this)->inject(context); + return static_cast(this)->injectImp(context); } -template -GenericWriter::GenericWriter() +template +GenericWriter::~GenericWriter() { } -template -GenericWriter::GenericWriter(const GenericWriter&) +template +GenericWriter::GenericWriter() +{ +} + +template +GenericWriter::GenericWriter(const GenericWriter&) { } -template +template int -GenericReader::extract(SPAN_CONTEXT* const context) const +GenericReader::extract(CONTEXT* const context) const { - return static_cast(this)->extract(context); + return static_cast(this)->extractImp(context); } -template -GenericReader::GenericReader() +template +GenericReader::~GenericReader() { } -template -GenericReader::GenericReader(const GenericReader&) +template +GenericReader::GenericReader() +{ +} + +template +GenericReader::GenericReader(const GenericReader&) { } diff --git a/opentracing/span.h b/opentracing/span.h index 097aed3..afee1e8 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -1,19 +1,28 @@ #ifndef INCLUDED_OPENTRACING_SPAN_H #define INCLUDED_OPENTRACING_SPAN_H +#include + +#ifdef HAVE_STDINT_H +#include +#endif + #include #include namespace opentracing { -template +template class GenericSpan { public: - typedef IMPL Span; - typedef Span::SpanContext SpanContext; + virtual ~GenericSpan(); + + typedef IMPL Span; + typedef GenericSpanContext SpanContext; SpanContext& context(); const SpanContext& context() const; + // Return the SpanContext associated with this span. Baggage can // be set or accessed through the underlying context directly. @@ -26,28 +35,52 @@ class GenericSpan { // called, except for 'context()'. int tag(const StringRef& key, const bool val); - int tag(const StringRef& key, const int64_t val); - int tag(const StringRef& key, const uint64_t val); + int tag(const StringRef& key, const float val); int tag(const StringRef& key, const double val); int tag(const StringRef& key, const StringRef& val); + + int tag(const StringRef& key, const int16_t val); + int tag(const StringRef& key, const int32_t val); + int tag(const StringRef& key, const int64_t val); + + int tag(const StringRef& key, const uint16_t val); + int tag(const StringRef& key, const uint32_t val); + int tag(const StringRef& key, const uint64_t val); + // Set a tag on this span, associating the supplied 'key' characters to - // the supplied value. + // the supplied value. Overloads are supplied for common primitive types, + // and a string blob int log(const StringRef& key, const bool val); - int log(const StringRef& key, const int64_t val); - int log(const StringRef& key, const uint64_t val); + int log(const StringRef& key, const float val); int log(const StringRef& key, const double val); int log(const StringRef& key, const StringRef& val); + int log(const StringRef& key, const int16_t val); + int log(const StringRef& key, const int32_t val); + int log(const StringRef& key, const int64_t val); + + int log(const StringRef& key, const uint16_t val); + int log(const StringRef& key, const uint32_t val); + int log(const StringRef& key, const uint64_t val); + int log(const StringRef& key, const bool val, const uint64_t tsp); - int log(const StringRef& key, const int64_t val, const uint64_t tsp); - int log(const StringRef& key, const uint64_t val, const uint64_t tsp); + int log(const StringRef& key, const float val, const uint64_t tsp); int log(const StringRef& key, const double val, const uint64_t tsp); int log(const StringRef& key, const StringRef& val, const uint64_t tsp); - // Structured data should be logged through one of the calls to 'log'. - // From this point forward, this span will associate 'key' with the - // supplied 'value'. This is similar to 'tag()', but additionally includes - // a time-stamp noting the number of microseconds that have elapsed since + + int log(const StringRef& key, const int16_t val, const uint64_t tsp); + int log(const StringRef& key, const int32_t val, const uint64_t tsp); + int log(const StringRef& key, const int64_t val, const uint64_t tsp); + + int log(const StringRef& key, const uint16_t val, const uint64_t tsp); + int log(const StringRef& key, const uint32_t val, const uint64_t tsp); + int log(const StringRef& key, const uint64_t val, const uint64_t tsp); + + // Structured data should be logged through one of the calls to 'log'. From + // this point forward, this span will associate 'key' with the supplied + // 'value'. This is similar to 'tag()', but additionally includes a + // time-stamp noting the number of microseconds that have elapsed since // the Unix epoch. If time-stamp is not supplied, the current wall-time // is used, otherwise the explicit time-stamp is used. The time-stamp // should be between the start and finish times for this span. @@ -58,147 +91,303 @@ class GenericSpan { // Protected to avoid direct construction }; -template -GenericSpan::GenericSpan() +// Virtual destructor + +template +GenericSpan::~GenericSpan() +{ +} + +// Protected Constructors + +template +GenericSpan::GenericSpan() +{ +} + +template +GenericSpan::GenericSpan(const GenericSpan&) +{ +} + +// Context Accessors + +template +typename GenericSpan::SpanContext& +GenericSpan::context() +{ + return static_cast(this)->contextImp(); +} + +template +const typename GenericSpan::SpanContext& +GenericSpan::context() const +{ + return static_cast(this)->contextImp(); +} + +// Tags + +template +int +GenericSpan::finish() +{ + return static_cast(this)->finishImp(); +} + +template +int +GenericSpan::finish(const uint64_t tsp) +{ + return static_cast(this)->finishImp(tsp); +} + +template +int +GenericSpan::tag(const StringRef& key, const bool val) +{ + return static_cast(this)->tagImp(key, val); +} + +template +int +GenericSpan::tag(const StringRef& key, const float val) +{ + return static_cast(this)->tagImp(key, val); +} + +template +int +GenericSpan::tag(const StringRef& key, const double val) +{ + return static_cast(this)->tagImp(key, val); +} + +template +int +GenericSpan::tag(const StringRef& key, + const StringRef& val) +{ + return static_cast(this)->tagImp(key, val); +} + +template +int +GenericSpan::tag(const StringRef& key, + const int16_t val) +{ + return static_cast(this)->tagImp(key, val); +} + +template +int +GenericSpan::tag(const StringRef& key, + const int32_t val) +{ + return static_cast(this)->tagImp(key, val); +} + +template +int +GenericSpan::tag(const StringRef& key, + const int64_t val) { + return static_cast(this)->tagImp(key, val); } -template -GenericSpan::GenericSpan(const GenericSpan&) +template +int +GenericSpan::tag(const StringRef& key, + const uint16_t val) { + return static_cast(this)->tagImp(key, val); } -template -GenericSpan::SpanContext& -GenericSpan::context() +template +int +GenericSpan::tag(const StringRef& key, + const uint32_t val) { - return static_cast(this)->context(); + return static_cast(this)->tagImp(key, val); } -template -const GenericSpan::SpanContext& -GenericSpan::context() const +template +int +GenericSpan::tag(const StringRef& key, + const uint64_t val) +{ + return static_cast(this)->tagImp(key, val); +} + +// Logs + +template +int +GenericSpan::log(const StringRef& key, const bool val) +{ + return static_cast(this)->logImp(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, const float val) +{ + return static_cast(this)->logImp(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, const double val) { - return static_cast(this)->context(); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::finish() +GenericSpan::log(const StringRef& key, + const StringRef& val) { - return static_cast(this)->finish(); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::finish(const uint64_t tsp) +GenericSpan::log(const StringRef& key, + const int16_t val) { - return static_cast(this)->finish(tsp); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, const bool val) +GenericSpan::log(const StringRef& key, + const int32_t val) { - return static_cast(this)->tag(val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, const int64_t val) +GenericSpan::log(const StringRef& key, + const int64_t val) { - return static_cast(this)->tag(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, const uint64_t val) +GenericSpan::log(const StringRef& key, + const uint16_t val) { - return static_cast(this)->tag(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, const double val) +GenericSpan::log(const StringRef& key, + const uint32_t val) { - return static_cast(this)->tag(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, const StringRef& val) +GenericSpan::log(const StringRef& key, + const uint64_t val) { - return static_cast(this)->tag(key, val, vlen); + return static_cast(this)->logImp(key, val); } -template +// Logs with timestamps +// +template int -GenericSpan::log(const StringRef& key, const bool val) +GenericSpan::log(const StringRef& key, + const bool val, + const uint64_t tsp) { - return static_cast(this)->log(key, val); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, const int64_t val) +GenericSpan::log(const StringRef& key, + const float val, + const uint64_t tsp) { - return static_cast(this)->log(key, val); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, const uint64_t val) +GenericSpan::log(const StringRef& key, + const double val, + const uint64_t tsp) { - return static_cast(this)->log(key, val); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, const double val) +GenericSpan::log(const StringRef& key, + const StringRef& val, + const uint64_t tsp) { - return static_cast(this)->log(key, val); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, const StringRef& val) +GenericSpan::log(const StringRef& key, + const int16_t val, + const uint64_t tsp) { - return static_cast(this)->log(key, val); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, const bool val, const uint64_t tsp) +GenericSpan::log(const StringRef& key, + const int32_t val, + const uint64_t tsp) { - return static_cast(this)->log(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, const int64_t val, const uint64_t tsp) +GenericSpan::log(const StringRef& key, + const int64_t val, + const uint64_t tsp) { - return static_cast(this)->log(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, const uint64_t val, const uint64_t tsp) +GenericSpan::log(const StringRef& key, + const uint16_t val, + const uint64_t tsp) { - return static_cast(this)->log(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, const double val, const uint64_t tsp) +GenericSpan::log(const StringRef& key, + const uint32_t val, + const uint64_t tsp) { - return static_cast(this)->log(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, const StringRef& val, const uint64_t tsp) +GenericSpan::log(const StringRef& key, + const uint64_t val, + const uint64_t tsp) { - return static_cast(this)->log(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } } // end namespace opentracing diff --git a/opentracing/spancontext.h b/opentracing/spancontext.h index 42bff41..4d78a3a 100644 --- a/opentracing/spancontext.h +++ b/opentracing/spancontext.h @@ -6,70 +6,74 @@ namespace opentracing { -template +template class GenericSpanContext { public: - typedef IMPL SpanContext; - typedef SpanContext::BaggageIteratorImpl IteratorImpl; - typedef SpanContext::BaggageHandler BaggageHandler; + typedef IMPL SpanContext; + typedef ADAPTER BaggageAdapter; + typedef BaggageIterator const_iterator; - typedef BaggageIterator const_iterator; - - typedef BaggageIterator const_iterator; + virtual ~GenericSpanContext(); const_iterator begin() const; const_iterator end() const; - // Return iterators to baggage managed by this span_context. + // Return iterators to baggage managed by this SpanContext. int setBaggage(const StringRef& key, const StringRef& baggage); // Associate the supplied 'key' with the 'baggage'. - int getBaggage(StringRef* const baggage, const StringRef& key); + int getBaggage(StringRef* const baggage, const StringRef& key) const; // Load the 'baggage' associated with 'key'. - private: + protected: GenericSpanContext(); GenericSpanContext(const GenericSpanContext&); // Protected to avoid direct construction }; -template -GenericSpanContext::GenericSpanContext() +template +GenericSpanContext::~GenericSpanContext() +{ +} + +template +GenericSpanContext::GenericSpanContext() { } -template -GenericSpanContext::GenericSpanContext(const GenericSpanContext&) +template +GenericSpanContext::GenericSpanContext(const GenericSpanContext&) { } -template -GenericSpanContext::const_iterator -GenericSpanContext::begin() const +template +typename GenericSpanContext::const_iterator +GenericSpanContext::begin() const { - return const_iterator(static_cast(this)->begin()); + return const_iterator(static_cast(this)->beginImp()); } -template -GenericSpanContext::const_iterator -GenericSpanContext::end() const +template +typename GenericSpanContext::const_iterator +GenericSpanContext::end() const { - return const_iterator(static_cast(this)->end()); + return const_iterator(static_cast(this)->endImp()); } -template +template int -GenericSpanContext::setBaggage(const StringRef& key, const StringRef& baggage) +GenericSpanContext::setBaggage(const StringRef& key, + const StringRef& baggage) { - return static_cast(this)->setBaggage(key, baggage); + return static_cast(this)->setBaggageImp(key, baggage); } -template +template int -GenericSpanContext::get_baggage(StringRef* const baggage, - const StringRef& key) const +GenericSpanContext::getBaggage(StringRef* const baggage, + const StringRef& key) const { - return static_cast(this)->get_baggage(baggage, key); + return static_cast(this)->getBaggageImp(baggage, key); } } // namespace opentracing #endif // INCLUDED_OPENTRACING_SPANCONTEXT_H diff --git a/opentracing/stringref.h b/opentracing/stringref.h index 426020e..640fa42 100644 --- a/opentracing/stringref.h +++ b/opentracing/stringref.h @@ -19,6 +19,8 @@ namespace opentracing { struct StringRef { public: + StringRef(); + template StringRef(const char (&str)[N]); // Explicitly create string reference from a const character array @@ -35,6 +37,19 @@ struct StringRef { 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* const str); + // Reset this string ref to point at the supplied c-string + + void reset(const std::string& str); + // Reset the string reference given a std::string + + void reset(const char* const 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 @@ -46,10 +61,18 @@ struct StringRef { 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; size_t m_length; }; +inline StringRef::StringRef() : m_data(0), m_length(0) +{ +} + template inline StringRef::StringRef(const char (&str)[N]) : m_data(str), m_length(N - 1) { @@ -75,6 +98,35 @@ inline StringRef::operator const char*() const return m_data; } +inline void +StringRef::reset(const char* const str, const size_t length) +{ + m_data = str; + m_length = length; +} + +template +inline void +StringRef::reset(const char (&str)[N]) +{ + m_data = str; + m_length = N; +} + +inline void +StringRef::reset(const char* const str) +{ + m_data = str; + m_length = std::strlen(str); +} + +inline void +StringRef::reset(const std::string& str) +{ + m_data = str.data(); + m_length = str.length(); +} + inline const char* StringRef::data() const { diff --git a/opentracing/tracer.h b/opentracing/tracer.h index a28620a..ce98acb 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -8,58 +8,70 @@ #endif #include +#include #include namespace opentracing { -template +template class GenericTracer { - typedef IMPL Tracer; - typedef Tracer::Span Span; - typedef Span::SpanContext SpanContext; + public: + typedef GenericSpan Span; + typedef GenericSpanContext SpanContext; - int start(Span* const sp, const StringRef& operation); - int start(Span* const sp, const StringRef& operation, const uint64_t tsp); + static void install(GenericTracer* const tracer); + // Install 'tracer' to be referenced globally. This method is not thread + // safe. + // It should be called once, in main, before any other thread or trace work + // is performed. Undefined behavior otherwise. - int start(Span* const sp, - const StringRef& operation, - const SpanContext& parent); + static void uninstall(); + // Uninstall any 'tracer' that may have been previously installed. This + // method + // is not thread safe. It should only be called in test environments. - int start(Span* const sp, - const StringRef& operation, - const SpanContext& parent, - const uint64_t tsp); + static GenericTracer* instance(); + // Return an instance to the globally installed tracer. Returns null if a + // tracer has not been previously installed. It is undefined behavior + // to call this method without previously calling 'install()'. + + virtual ~GenericTracer(); + + Span* start(const StringRef& op); + Span* start(const StringRef& op, const uint64_t tsp); + + Span* start(const StringRef& op, const SpanContext& parent); + + Span* start(const StringRef& op, + const SpanContext& parent, + const uint64_t tsp); template - int start(Span* const sp, - const StringRef& operation, - const ITER begin, - const ITER end); + Span* start(const StringRef& op, const ITER& pbegin, const ITER& pend); template - int start(Span* const sp, - const StringRef& operation, - const ITER begin, - const ITER end, - const uint64_t tsp); - // The 'start' methods are used to load a new 'Span'. The only required - // parameter is the 'operation' description, which should outline the - // work being performed during the Span. + Span* start(const StringRef& op, + const ITER& pbegin, + const ITER& pend, + const uint64_t tsp); + // The 'start' methods are used to create a new 'Span'. The only required + // parameter is the operation string 'op', which should describe the work + // being performed during the span. // // The optional arguments are: // parent: - // Reference a single parent Span's context, establishing this - // Span's trace id + // Refer a SpanContext, establishing the new span as a child of the + // supplied context // - // begin/end: - // A set of iterators that outline a range of parent Span contexts. - // This Span should be marked as a child of all the supplied - // parents. ITER must be a forward iterator, that when dereferenced, - // can be stored in a `const SpanContext&`. + // pbegin/pend: + // Supply a range of iterators, which when dereferenced refer to + // a SpanContext&. The new span would be a child of all of the + // supplied parents. // // tsp: - // The time-stamp marking the start of the Span, in microseconds. - // If not supplied, the current wall-time should be used. + // The time-stamp marking the start of the new Span. 'tsp' should + // represent the number of microseconds that have elapsed since + // the Unix epoch. template int inject(GenericTextWriter* const carrier, @@ -67,8 +79,7 @@ class GenericTracer { // Inject the supplied 'context' into the text map writer 'carrier'. template - int extract(SpanContext* const context, - const GenericTextReader& carrier); + SpanContext* extract(const GenericTextReader& carrier); // Extract the supplied 'context' from the text map reader 'carrier'. template @@ -77,143 +88,184 @@ class GenericTracer { // Inject the supplied 'context' into the binary writer 'carrier'. template - int extract(SpanContext* const context, - const GenericBinaryReader& carrier); + SpanContext* extract(const GenericBinaryReader& carrier); // Extract the supplied 'context' from the binary reader 'carrier'. template - int inject(GenericWriter* const carrier, - const SpanContext& context) const; + int inject(GenericWriter* const carrier, + const SpanContext& context) const; // Inject the SpanContext directly into the specialized 'carrier'. // - // Note: The carrier will be passed the 'SpanContext' directly. Using - // this may make your carrier code more efficient, but it removes - // flexibility if you want to swap Tracer/Span implementations later. + // Note: The carrier will be passed the 'SpanContext' directly. + // Using this may make your carrier code more efficient, but it + // removes flexibility if you want to swap Tracer/Span + // implementations. template - int extract(SpanContext* const context, - const GenericReader& carrier); + SpanContext* extract(const GenericReader& carrier); // Extract the SpanContext from the specialized 'carrier'. // - // Note: The carrier will be passed the 'SpanContext' directly. Using - // this may make your carrier code more efficient, but it removes - // flexibility if you want to swap Tracer/Span implementations later. + // Note: The carrier will be passed the 'SpanContext' directly. + // Using this may make your carrier code more efficient, but it + // removes flexibility if you want to swap Tracer/Span implementations + // later. protected: GenericTracer(); GenericTracer(const GenericTracer&); // Protected to avoid direct construction + + private: + static GenericTracer* s_tracer; }; -template -GenericTracer::GenericTracer() +template +GenericTracer* + GenericTracer::s_tracer = 0; + +template +void +GenericTracer::install( + GenericTracer* const tracer) { + s_tracer = tracer; } -template -GenericTracer::GenericTracer(const GenericTracer&) +template +void +GenericTracer::uninstall() { + s_tracer = 0; } -template -int -GenericTracer::start(Span* const Span) +template +GenericTracer* +GenericTracer::instance() { - return static_cast(this)->start(Span); + return s_tracer; } -template -int -GenericTracer::start(Span* const sp, const uint64_t tsp) +template +GenericTracer::~GenericTracer() { - return static_cast(this)->start(sp, tsp); } -template -int -GenericTracer::start(Span* const sp, const SpanContext& parent) +template +GenericTracer::GenericTracer() { - return static_cast(this)->start(sp, parent); } -template -int -GenericTracer::start(Span* const sp, - const SpanContext& parent, - const uint64_t tsp) +template +GenericTracer::GenericTracer(const GenericTracer&) { - return static_cast(this)->start(sp, parent, tsp); } +template +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op) +{ + return static_cast(this)->startImp(op); +} + +template +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op, + const uint64_t tsp) +{ + return static_cast(this)->startImp(op, tsp); +} + +template +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op, + const SpanContext& parent) +{ + return static_cast(this)->startImp(op, parent); +} + +template +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op, + const SpanContext& parent, + const uint64_t tsp) +{ + return static_cast(this)->startImp(op, parent, tsp); +} + +template template -int -GenericTracer::start(Span* const sp, const ITER begin, const ITER end) +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op, + const ITER& begin, + const ITER& end) { - return static_cast(this)->start(sp, begin, end); + return static_cast(this)->startImp(op, begin, end); } +template template -int -GenericTracer::start(Span* const sp, - const ITER begin, - const ITER end, - const uint64_t tsp) +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op, + const ITER& begin, + const ITER& end, + const uint64_t tsp) { - return static_cast(this)->start(sp, begin, end, tsp); + return static_cast(this)->startImp(op, begin, end, tsp); } -template +template template int -GenericTracer::inject(GenericTextWriter* const carrier, - const SpanContext& context) const +GenericTracer::inject( + GenericTextWriter* const carrier, const SpanContext& context) const { - return static_cast(this)->inject(carrier, context); + return static_cast(this)->injectImp(carrier, context); } -template +template template -int -GenericTracer::extract(SpanContext* const context, - const GenericTextReader& carrier) +typename GenericTracer::SpanContext* +GenericTracer::extract( + const GenericTextReader& carrier) { - return static_cast(this)->extract(context, carrier); + return static_cast(this)->extractImp(carrier); } -template +template template int -GenericTracer::inject(GenericBinaryWriter* const carrier, - const SpanContext& context) const +GenericTracer::inject( + GenericBinaryWriter* const carrier, const SpanContext& context) const { - return static_cast(this)->inject(carrier, context); + return static_cast(this)->injectImp(carrier, context); } -template +template template -int -GenericTracer::extract(SpanContext* const context, - const GenericBinaryReader& carrier) +typename GenericTracer::SpanContext* +GenericTracer::extract( + const GenericBinaryReader& carrier) { - return static_cast(this)->extract(context, carrier); + return static_cast(this)->extractImp(carrier); } -template +template template int -GenericTracer::inject(GenericWriter* const carrier, - const SpanContext& context) const +GenericTracer::inject( + GenericWriter* const carrier, + const SpanContext& context) const { - return static_cast(this)->inject(carrier, context); + return static_cast(this)->injectImp(carrier, context); } -template +template template -int -GenericTracer::extract(SpanContext* const context, - const GenericReader& carrier) +typename GenericTracer::SpanContext* +GenericTracer::extract( + const GenericReader& carrier) { - return static_cast(this)->extract(context, carrier); + return static_cast(this)->extractImp(carrier); } } #endif diff --git a/test/Makefile b/test/Makefile index 4101664..91c94e1 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,10 +1,10 @@ CC=g++ OPENTRACING_INCLUDE=../ -OPENTRACING_SRC=$(wildcard ${OPENTRACING_INCLUDED}/*.h) +OPENTRACING_SRC=$(wildcard ${OPENTRACING_INCLUDE}/*.h) OPENTRACING_HEADERS= $(wildcard ${OPENTRACING_INCLUDE} -THIRDPARTY_ROOT=../thirdparty +THIRDPARTY_ROOT=../thirdparty GTEST_INCLUDE=${THIRDPARTY_ROOT}/googletest/googletest/include GTEST_LIBS=${THIRDPARTY_ROOT}/ @@ -23,10 +23,10 @@ LDIR =${GTEST_LIBS} LIBS=-L${GTEST_LIBS} -lgtest -lpthread -_OBJ = baggage.t.o stringref.t.o unittest.t.o +_OBJ = tracer.t.o carriers.t.o span.t.o spancontext.t.o baggage.t.o stringref.t.o unittest.t.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) -$(ODIR)/%.o: %.cc ${OPENTRACING_SRC} +$(ODIR)/%.o: %.cc %.h ${OPENTRACING_SRC} $(CC) -c -o $@ $< $(CXXFLAGS) test: $(OBJ) diff --git a/test/baggate.t.cc b/test/baggate.t.cc deleted file mode 100644 index c8a85eb..0000000 --- a/test/baggate.t.cc +++ /dev/null @@ -1,35 +0,0 @@ -#include "unittest.h" - -#include // test include guard -#include - -TEST(StringRef, CString) -{ - const char * val = "hello world"; - - StringRef ref(val); - - ASSERT_EQ(val, ref.m_string); - ASSERT_EQ(std::strlen(val), ref.m_length); -} - -TEST(StringRef, CStringArray) -{ - const char val[] = "hello world"; - - StringRef ref(val); - - ASSERT_EQ(val, ref.m_string); - ASSERT_EQ(std::strlen(val), ref.m_length); -} - -TEST(StringRef, StdString) -{ - const std::string val = "hello world"; - - StringRef ref(val); - - ASSERT_EQ(val, ref.m_string); - ASSERT_EQ(val.length(), ref.m_length); -} - diff --git a/test/carriers.h b/test/carriers.h new file mode 100644 index 0000000..1439f4a --- /dev/null +++ b/test/carriers.h @@ -0,0 +1,95 @@ +#ifndef INCLUDED_OPENTRACING_TEST_CARRIERS_H +#define INCLUDED_OPENTRACING_TEST_CARRIERS_H + +#include "unittest.h" + +#include // test include guard +#include + +#include "spancontext.h" + +struct TestTextWriter : public GenericTextWriter { + int + injectImp(const std::vector& textmap) + { + pairs = textmap; + return 0; + } + + std::vector pairs; +}; + +struct TestTextReader : public GenericTextReader { + int + extractImp(std::vector* const textmap) const + { + *textmap = pairs; + return 0; + } + + std::vector pairs; +}; + +struct TestBinaryWriter : public GenericBinaryWriter { + int + injectImp(const void* buf, const size_t len) + { + if (len > sizeof(m_raw)) + { + return 1; + } + + std::memcpy(&m_raw, buf, len); + return 0; + } + + int32_t m_raw; +}; + +struct TestBinaryReader : public GenericBinaryReader { + int + extractImp(void* const buf, size_t* const written, const size_t len) const + { + if (sizeof(m_raw) > len) + { + return 1; + } + + std::memcpy(buf, &m_raw, sizeof(m_raw)); + *written = sizeof(m_raw); + return 0; + } + + int32_t m_raw; +}; + +struct TestWriter : public GenericWriter +{ + int injectImp(const TestContextImpl& context) + { + carrier = context.baggageMap(); + return 0; + } + + std::map carrier; +}; + +struct TestReader : public GenericReader +{ + int extractImp(TestContextImpl * const context) const + { + context->baggageMap() = carrier; + return 0; + } + + std::map carrier; +}; + +typedef GenericTextWriter TextWriter; +typedef GenericTextReader TextReader; +typedef GenericBinaryWriter BinaryWriter; +typedef GenericBinaryReader BinaryReader; +typedef GenericWriter ExplicitWriter; +typedef GenericReader ExplicitReader; + +#endif diff --git a/test/carriers.t.cc b/test/carriers.t.cc new file mode 100644 index 0000000..bb9fbe7 --- /dev/null +++ b/test/carriers.t.cc @@ -0,0 +1,149 @@ +#include "carriers.h" +#include "unittest.h" + +TEST(Carriers, TextMapWriter) +{ + TestTextWriter imp; + TextWriter& t = imp; + + std::vector v; + v.push_back(TextMapPair("animal", "dog")); + v.push_back(TextMapPair("fruit", "apple")); + v.push_back(TextMapPair("veggie", "carrot")); + + int rc = t.inject(v); + + ASSERT_EQ(0, rc); + + ASSERT_EQ(3u, imp.pairs.size()); + + ASSERT_EQ(imp.pairs[0].m_name, "animal"); + ASSERT_EQ(imp.pairs[0].m_value, "dog"); + + ASSERT_EQ(imp.pairs[1].m_name, "fruit"); + ASSERT_EQ(imp.pairs[1].m_value, "apple"); + + ASSERT_EQ(imp.pairs[2].m_name, "veggie"); + ASSERT_EQ(imp.pairs[2].m_value, "carrot"); +} + +TEST(Carriers, TextMapReader) +{ + TestTextReader imp; + + std::vector& v = imp.pairs; + v.push_back(TextMapPair("animal", "dog")); + v.push_back(TextMapPair("fruit", "apple")); + v.push_back(TextMapPair("veggie", "carrot")); + + TextReader& t = imp; + + std::vector o; + + int rc = t.extract(&o); + + ASSERT_EQ(0, rc); + + ASSERT_EQ(3u, o.size()); + + ASSERT_EQ(o[0].m_name, "animal"); + ASSERT_EQ(o[0].m_value, "dog"); + + ASSERT_EQ(o[1].m_name, "fruit"); + ASSERT_EQ(o[1].m_value, "apple"); + + ASSERT_EQ(o[2].m_name, "veggie"); + ASSERT_EQ(o[2].m_value, "carrot"); +} + +TEST(Carriers, BinaryReader) +{ + TestBinaryReader imp; + imp.m_raw = 0xdeadbeef; + + BinaryReader& t = imp; + + char smallbuf[3]; // too small for int32_t + size_t written = 0; + + int rc = t.extract(smallbuf, &written, sizeof(smallbuf)); + ASSERT_NE(0, rc); + + char buf[100]; + rc = t.extract(buf, &written, sizeof(buf)); + ASSERT_EQ(0, rc); + ASSERT_EQ(written, sizeof(imp.m_raw)); + + int32_t out = 0; + std::memcpy(&out, buf, written); + + ASSERT_EQ(out, imp.m_raw); +} + +TEST(Carriers, BinaryWriter) +{ + TestBinaryWriter imp; + BinaryWriter& t = imp; + + const int64_t tooBig= 0x00000000deadbeef; + + int rc = t.inject(&tooBig, sizeof(tooBig)); + ASSERT_NE(0, rc); + + const int32_t expected = 0xdeadbeef; + + rc = t.inject(&expected, sizeof(expected)); + ASSERT_EQ(0, rc); + + ASSERT_EQ(expected, imp.m_raw); +} + +TEST(Carriers, ExplicitWriter) +{ + TestContextImpl context; + ASSERT_EQ(0, context.setBaggage("animal", "dog")); + ASSERT_EQ(0, context.setBaggage("fruit", "apple")); + ASSERT_EQ(0, context.setBaggage("veggie", "carrot")); + + TestWriter imp; + ExplicitWriter& t = imp; + + int rc = t.inject(context); + ASSERT_EQ(0, rc); + + ASSERT_EQ(3u, imp.carrier.size()); + ASSERT_EQ(imp.carrier["animal"], "dog"); + ASSERT_EQ(imp.carrier["fruit"], "apple"); + ASSERT_EQ(imp.carrier["veggie"], "carrot"); +} + +TEST(Carriers, ExplicitReader) +{ + TestReader imp; + imp.carrier["animal"] = "dog"; + imp.carrier["fruit"] = "apple"; + imp.carrier["veggie"] = "carrot"; + + ExplicitReader& t = imp; + + TestContextImpl context; + int rc = t.extract(&context); + ASSERT_EQ(0, rc); + + const std::map& m = context.baggageMap(); + + ASSERT_EQ(3u, m.size()); + + std::map::const_iterator it = m.find("animal"); + + ASSERT_NE(m.end(), it); + ASSERT_EQ(it->second, "dog"); + + it = m.find("fruit"); + ASSERT_NE(m.end(), it); + ASSERT_EQ(it->second, "apple"); + + it = m.find("veggie"); + ASSERT_NE(m.end(), it); + ASSERT_EQ(it->second, "carrot"); +} diff --git a/test/span.h b/test/span.h new file mode 100644 index 0000000..9868580 --- /dev/null +++ b/test/span.h @@ -0,0 +1,212 @@ +#ifndef INCLUDED_OPENTRACING_TEST_SPAN_H +#define INCLUDED_OPENTRACING_TEST_SPAN_H + +#include "unittest.h" +#include "spancontext.h" + +#include // test include guard +#include + +class TestSpanImpl : public GenericSpan { + public: + TestContextImpl& contextImp() { + return d_context; + } + + const TestContextImpl& contextImp() const { + return d_context; + } + + int + finishImp() + { + return 0; + } + + int + finishImp(const uint64_t ) + { + return 0; + } + + int + tagImp(const StringRef&, const bool) + { + return 0; + } + + int + tagImp(const StringRef&, const float) + { + return 0; + } + + int + tagImp(const StringRef&, const double) + { + return 0; + } + + int + tagImp(const StringRef&, const StringRef&) + { + return 0; + } + + int + tagImp(const StringRef&, const int16_t) + { + return 0; + } + int + tagImp(const StringRef&, const int32_t) + { + return 0; + } + int + tagImp(const StringRef&, const int64_t) + { + return 0; + } + int + tagImp(const StringRef&, const uint16_t) + { + return 0; + } + + int + tagImp(const StringRef&, const uint32_t) + { + return 0; + } + + int + tagImp(const StringRef&, const uint64_t) + { + return 0; + } + + int + logImp(const StringRef&, const bool) + { + return 0; + } + + int + logImp(const StringRef&, const float) + { + return 0; + } + + int + logImp(const StringRef&, const double) + { + return 0; + } + + int + logImp(const StringRef&, const StringRef&) + { + return 0; + } + + int + logImp(const StringRef&, const int16_t) + { + return 0; + } + int + logImp(const StringRef&, const int32_t) + { + return 0; + } + int + logImp(const StringRef&, const int64_t) + { + return 0; + } + int + logImp(const StringRef&, const uint16_t) + { + return 0; + } + + int + logImp(const StringRef&, const uint32_t) + { + return 0; + } + + int + logImp(const StringRef&, const uint64_t) + { + return 0; + } + + int + logImp(const StringRef&, const bool, const uint64_t) + { + return 0; + } + + int + logImp(const StringRef&, const float, const uint64_t) + { + return 0; + } + + int + logImp(const StringRef&, const double, const uint64_t) + { + return 0; + } + + int + logImp(const StringRef&, const StringRef&, const uint64_t) + { + return 0; + } + + int + logImp(const StringRef&, const int16_t, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const int32_t, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const int64_t, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const uint16_t, const uint64_t) + { + return 0; + } + + int + logImp(const StringRef&, const uint32_t, const uint64_t) + { + return 0; + } + + int + logImp(const StringRef&, const uint64_t, const uint64_t) + { + return 0; + } + + private: + TestContextImpl d_context; +}; + +typedef GenericSpan + TestSpan; + +#endif diff --git a/test/span.t.cc b/test/span.t.cc new file mode 100644 index 0000000..38e0402 --- /dev/null +++ b/test/span.t.cc @@ -0,0 +1,74 @@ +#include "unittest.h" +#include "span.h" + +TEST(Span, BasicTests) +{ + TestSpanImpl impl; + TestSpan& t = impl; + + int rc = impl.context().setBaggage("hello", "world"); + + { + // Make sure const references work + const TestSpan& tc = impl; + + StringRef ref; + rc = tc.context().getBaggage(&ref, "hello"); + + ASSERT_EQ(0, rc); + ASSERT_STREQ("world", ref); + + const TestSpan::SpanContext& cc = tc.context(); + rc = cc.getBaggage(&ref, "miss"); + + ASSERT_NE(0, rc); + + TestSpan::SpanContext::const_iterator it = cc.begin(); + ASSERT_FALSE(it == cc.end()); + } + + t.finish(); + t.finish(1234567); +} + +template +class SpanTypeTests : public ::testing::Test { +}; + +typedef ::testing::Types + OverloadedTypes; + +TYPED_TEST_CASE(SpanTypeTests, OverloadedTypes); + +TYPED_TEST(SpanTypeTests, TagInterface) +{ + TestSpanImpl impl; + TestSpan& t = impl; + int rc = t.tag("key", TypeParam()); + ASSERT_EQ(0, rc); +} + +TYPED_TEST(SpanTypeTests, LogInterface) +{ + TestSpanImpl impl; + TestSpan& t = impl; + int rc = t.log("key", TypeParam()); + ASSERT_EQ(0, rc); +} + +TYPED_TEST(SpanTypeTests, LogTspInterface) +{ + TestSpanImpl impl; + TestSpan& t = impl; + int rc = t.log("key", TypeParam(), 0); + ASSERT_EQ(0, rc); +} diff --git a/test/spancontext.h b/test/spancontext.h new file mode 100644 index 0000000..9cc8fcc --- /dev/null +++ b/test/spancontext.h @@ -0,0 +1,88 @@ +#ifndef INCLUDED_OPENTRACING_TEST_SPANCONTEXT_H +#define INCLUDED_OPENTRACING_TEST_SPANCONTEXT_H + +#include "unittest.h" + +#include +#include // test include guard + +#include +#include + +typedef std::map TestBaggageContainer; + +struct TestContextBaggageAdapter { + typedef TestBaggageContainer::iterator iterator; + typedef TestBaggageContainer::const_iterator const_iterator; + + BaggageRef + operator()(const const_iterator& it) const + { + return BaggageRef(it->first, it->second); + } +}; + +class TestContextImpl + : public GenericSpanContext { + public: + typedef GenericSpanContext Base; + + int + setBaggageImp(const StringRef& key, const StringRef& baggage) + { + m_baggage[std::string(key.data(), key.length())] = + std::string(baggage.data(), baggage.length()); + + return 0; + } + + int + getBaggageImp(StringRef* const baggage, const StringRef& key) const + { + const std::string mkey(key.data(), key.length()); + + const TestBaggageContainer::const_iterator it = m_baggage.find(mkey); + + if (m_baggage.end() != it) + { + baggage->reset(it->second.data(), it->second.length()); + return 0; + } + else + { + return 1; + } + } + + Base::const_iterator + beginImp() const + { + return Base::const_iterator(m_baggage.begin()); + } + + Base::const_iterator + endImp() const + { + return Base::const_iterator(m_baggage.end()); + } + + TestBaggageContainer& + baggageMap() + { + return m_baggage; + } + + const TestBaggageContainer& + baggageMap() const + { + return m_baggage; + } + + private: + TestBaggageContainer m_baggage; +}; + +typedef GenericSpanContext + TestContext; + +#endif // INCLUDED_OPENTRACING_TEST_SPANCONTEXT_H diff --git a/test/spancontext.t.cc b/test/spancontext.t.cc new file mode 100644 index 0000000..5d8c04e --- /dev/null +++ b/test/spancontext.t.cc @@ -0,0 +1,51 @@ +#include "unittest.h" +#include "spancontext.h" + +#include // test include guard +#include + +TEST(GenericSpanContext, Baggage) +{ + TestContextImpl imp; + TestContext& t = imp; + + int rc = t.setBaggage("hello", "world"); + + StringRef ref; + rc = t.getBaggage(&ref, "hello"); + + ASSERT_EQ(0, rc); + ASSERT_STREQ("world", ref.data()); + + rc = t.getBaggage(&ref, "unknown"); + ASSERT_NE(0, rc); + + ASSERT_TRUE(t.begin() != t.end()); + + TestContext::const_iterator it = t.begin(); + + ASSERT_STREQ("hello", it->name().data()); + ASSERT_STREQ("world", it->value().data()); + + ++it; + + ASSERT_TRUE(it == t.end()); +} + +TEST(GenericSpanContext, CopyConstructor) +{ + TestContextImpl impl; + TestContext& t = impl; + + int rc = t.setBaggage("hello", "world"); + ASSERT_EQ(0, rc); + + TestContextImpl implCopy = impl; + TestContext& tc = implCopy; + + StringRef ref; + rc = tc.getBaggage(&ref, "hello"); + + ASSERT_EQ(0, rc); + ASSERT_STREQ("world", ref); +} diff --git a/test/stringref.t.cc b/test/stringref.t.cc index 7986732..725e24c 100644 --- a/test/stringref.t.cc +++ b/test/stringref.t.cc @@ -3,6 +3,14 @@ #include // test include guard #include +TEST(StringRef, Empty) +{ + StringRef ref; + + ASSERT_EQ(0, ref.data()); + ASSERT_EQ(0, ref.length()); +} + TEST(StringRef, CString) { const char * val = "hello world"; @@ -43,3 +51,50 @@ TEST(StringRef, Copy) ASSERT_EQ(val, cpy.data()); ASSERT_EQ(val.length(), cpy.length()); } + +TEST(StringRef, Reset) +{ + StringRef ref; + ASSERT_EQ(0, ref.data()); + ASSERT_EQ(0, ref.length()); + + ref.reset("hello world"); + + ASSERT_STREQ("hello world", ref); + ASSERT_STREQ("hello world", ref.data()); + ASSERT_EQ(std::strlen("hello world"), ref.length()); + + const char arr[] = "hello world 1"; + + ref.reset(arr); + ASSERT_EQ(arr, ref); + ASSERT_EQ(arr, ref.data()); + ASSERT_EQ(std::strlen(arr), ref.length()); + ASSERT_STREQ(arr, ref); + ASSERT_STREQ(arr, ref.data()); + + const char * p = "hello world 2"; + + ref.reset(p); + ASSERT_EQ(p, ref); + ASSERT_EQ(p, ref.data()); + ASSERT_EQ(std::strlen(p), ref.length()); + ASSERT_STREQ(p, ref); + ASSERT_STREQ(p, ref.data()); + + const std::string s = "hello world 3"; + + ref.reset(s); + ASSERT_EQ(s.data(), ref); + ASSERT_EQ(s.data(), ref.data()); + ASSERT_EQ(s.length(), ref.length()); + ASSERT_STREQ(s.c_str(), ref); + ASSERT_STREQ(s.c_str(), ref.data()); + + ref.reset(p, std::strlen(p)); + ASSERT_EQ(p, ref); + ASSERT_EQ(p, ref.data()); + ASSERT_EQ(std::strlen(p), ref.length()); + ASSERT_STREQ(p, ref); + ASSERT_STREQ(p, ref.data()); +} diff --git a/test/tracer.h b/test/tracer.h new file mode 100644 index 0000000..2abcfd4 --- /dev/null +++ b/test/tracer.h @@ -0,0 +1,178 @@ +#ifndef INCLUDED_OPENTRACING_TEST_TRACER_H +#define INCLUDED_OPENTRACING_TEST_TRACER_H + +#include "unittest.h" + +#include // test include guard +#include + +#include "span.h" +#include "spancontext.h" + +class TestTracerImpl : public GenericTracer { + public: + Span* + startImp(const StringRef&) + { + return new TestSpanImpl(); + } + + Span* + startImp(const StringRef&, const uint64_t) + { + return new TestSpanImpl(); + } + + Span* + startImp(const StringRef&, const SpanContext&) + { + return new TestSpanImpl(); + } + + Span* + startImp(const StringRef&, const SpanContext&, const uint64_t) + { + return new TestSpanImpl(); + } + + template + Span* + startImp(const StringRef&, const ITER& pbegin, const ITER& pend) + { + for (ITER it = pbegin; it != pend; ++it) + { + const TestContextImpl * ctx = static_cast(&(*it)); + // Output is ignored, but I want to flex the compiler here. Let's force + // a dereference to make sure the types are okay + + StringRef ref; + ctx->getBaggageImp(&ref, "hello"); + } + return new TestSpanImpl(); + } + + template + Span* + startImp(const StringRef&, const ITER pbegin, const ITER pend, const uint64_t) + { + for (ITER it = pbegin; it != pend; ++it) + { + const TestContextImpl * ctx = static_cast(&(*it)); + + StringRef ref; + ctx->getBaggageImp(&ref, "hello"); + } + + return new TestSpanImpl(); + } + + template + int + injectImp(GenericTextWriter* const carrier, + const TestContext& context) const + { + const TestContextImpl& imp = static_cast(context); + + std::vector pairs; + pairs.reserve(imp.baggageMap().size()); + + for (std::map::const_iterator it = + imp.baggageMap().begin(); + it != imp.baggageMap().end(); + ++it) + { + pairs.push_back(TextMapPair(it->first, it->second)); + } + + return carrier->inject(pairs); + } + + template + SpanContext* + extractImp(const GenericTextReader& carrier) const + { + std::vector pairs; + + if (int rc = carrier.extract(&pairs)) + { + return NULL; + } + + TestContextImpl* imp = new TestContextImpl(); + + for (std::vector::const_iterator it = pairs.begin(); + it != pairs.end(); + ++it) + { + imp->baggageMap()[it->m_name] = it->m_value; + } + return imp; + } + + template + int + injectImp(GenericBinaryWriter* const carrier, + const TestContext&) const + { + // Context unused for test. Implementations should encode + // the context for a wire protocol here, most likely + const int deadbeef = 0xdeadbeef; + return carrier->inject(&deadbeef, sizeof(deadbeef)); + } + + template + SpanContext* + extractImp(const GenericBinaryReader& carrier) + { + size_t written = 0; + int output = 0; + + if (int rc = carrier.extract(&output, &written, sizeof(output))) + { + return NULL; + } + else if (output == 0xdeadbeef) + { + return new TestContextImpl(); + } + else + { + return NULL; + } + } + + template + int + injectImp(GenericWriter* const carrier, + const TestContext& context) const + { + return carrier->inject(static_cast(context)); + } + + template + SpanContext* + extractImp(const GenericReader& carrier) + { + TestContextImpl* imp = new TestContextImpl; + if (int rc = carrier.extract(imp)) + { + delete imp; + return NULL; + } + else + { + return imp; + } + } +}; + +typedef GenericTracer + Tracer; + +#endif diff --git a/test/tracer.t.cc b/test/tracer.t.cc new file mode 100644 index 0000000..4fcc7df --- /dev/null +++ b/test/tracer.t.cc @@ -0,0 +1,237 @@ +#include "unittest.h" +#include "tracer.h" + +#include "carriers.h" + +struct SpanGuard { + SpanGuard(Tracer::Span* s) : sp(s) {} + ~SpanGuard() { delete sp; } + Tracer::Span * sp; +}; + +struct SpanContextGuard { + SpanContextGuard(Tracer::SpanContext* s) : sp(s) {} + ~SpanContextGuard() { delete sp; } + Tracer::SpanContext * sp; +}; + +TEST(Tracer, SingletonTests) +{ + TestTracerImpl imp; + Tracer::install(&imp); + ASSERT_EQ(&imp, Tracer::instance()); + + Tracer::uninstall(); + ASSERT_EQ(0, Tracer::instance()); +} + +TEST(Tracer, StartWithOp) +{ + TestTracerImpl imp; + Tracer& t = imp; + + SpanGuard guard(t.start("hello")); + EXPECT_TRUE(guard.sp); + + int rc = 0; + + rc = guard.sp->log("server", "blahblahblah"); + ASSERT_EQ(0, rc); + + rc = guard.sp->context().setBaggage("hello", "world"); + ASSERT_EQ(0, rc); + + rc = guard.sp->context().setBaggage("apple", "banana"); + ASSERT_EQ(0, rc); + + StringRef ref; + rc = guard.sp->context().getBaggage(&ref, "apple"); + + ASSERT_EQ(0, rc); + ASSERT_STREQ("banana", ref); +} + +TEST(Tracer, StartWithOpAndTsp) +{ + TestTracerImpl imp; + Tracer& t = imp; + + SpanGuard guard(t.start("hello", 125125)); + EXPECT_TRUE(guard.sp); +} + +TEST(Tracer, StartWithOpAndParent) +{ + // We create spans, which have contexts or create contexts directly + // through the 'extract' interface. Either way, clients only deal + // with the 'TestContext' type. Rather than make this simple start + // test dependent on those other interfaces, I'm going to just pull + // a context out of thin air to test the interface. + + TestContextImpl contextImp; + TestContext& context = contextImp; + + TestTracerImpl imp; + Tracer& t = imp; + + SpanGuard guard(t.start("hello", context)); + EXPECT_TRUE(guard.sp); +} + +TEST(Tracer, StartWithOpAndParentAndTsp) +{ + // We create spans, which have contexts or create contexts directly + // through the 'extract' interface. Either way, clients only deal + // with the 'TestContext' type. Rather than make this simple start + // test dependent on those other interfaces, I'm going to just pull + // a context out of thin air to test the interface. + + TestContextImpl contextImp; + TestContext& context = contextImp; + + TestTracerImpl imp; + Tracer& t = imp; + + SpanGuard guard(t.start("hello", context, 125125)); + EXPECT_TRUE(guard.sp); +} + +TEST(Tracer, StartWithOpAndMultipleParents) +{ + TestContextImpl contextImp1; + TestContextImpl contextImp2; + TestContextImpl contextImp3; + + std::vector contexts(3, TestContextImpl()); + + TestTracerImpl imp; + Tracer& t = imp; + + SpanGuard guard(t.start("hello", contexts.begin(), contexts.end())); + EXPECT_TRUE(guard.sp); +} + +TEST(Tracer, StartWithOpAndMultipleParentsAndTsp) +{ + TestContextImpl contextImp1; + TestContextImpl contextImp2; + TestContextImpl contextImp3; + + std::vector contexts(3, TestContextImpl()); + + TestTracerImpl imp; + Tracer& t = imp; + + SpanGuard guard(t.start("hello", contexts.begin(), contexts.end(), 125125)); + EXPECT_TRUE(guard.sp); +} + +TEST(Tracer, InjectText) +{ + TestTextWriter writer; + TestTracerImpl imp; + + Tracer& t = imp; + + SpanGuard g(t.start("op")); + ASSERT_TRUE(g.sp); + + g.sp->context().setBaggage("animal", "tiger"); + g.sp->context().setBaggage("animal", "cat"); + + int rc = t.inject(&writer, g.sp->context()); + ASSERT_EQ(0, rc); + + ASSERT_EQ(1u, writer.pairs.size()); + // Note there is no requirement that implementation make baggage keys + // unique, but the test suite does so its nice to verify that. + ASSERT_EQ(writer.pairs[0].m_name, "animal"); + ASSERT_EQ(writer.pairs[0].m_value, "cat"); +} + +TEST(Tracer, ExtractText) +{ + TestTextReader reader; + reader.pairs.push_back(TextMapPair("animal", "tiger")); + reader.pairs.push_back(TextMapPair("fruit", "apple")); + reader.pairs.push_back(TextMapPair("veggie", "carrot")); + + TestTracerImpl imp; + + Tracer& t = imp; + + SpanContextGuard g(t.extract(reader)); + ASSERT_TRUE(g.sp); + + size_t index = 0; + + const char * names[] = {"animal", "fruit", "veggie"}; + const char * values[] = {"tiger", "apple", "carrot"}; + + for(Tracer::SpanContext::const_iterator it = g.sp->begin(); it != g.sp->end(); ++it) + { + ASSERT_STREQ(names[index], it->name()); + ASSERT_STREQ(values[index], it->value()); + ++index; + } +} + +TEST(Tracer, InjectBinary) +{ + TestBinaryWriter writer; + TestTracerImpl imp; + + Tracer& t = imp; + + SpanGuard g(t.start("op")); + ASSERT_TRUE(g.sp); + + int rc = t.inject(&writer, g.sp->context()); + ASSERT_EQ(0, rc); + ASSERT_EQ(0xdeadbeef, writer.m_raw); +} + +TEST(Tracer, ExtractBinary) +{ + TestBinaryReader reader; + reader.m_raw = 0xdeadbeef; + + TestTracerImpl imp; + + Tracer& t = imp; + SpanContextGuard g(t.extract(reader)); + ASSERT_TRUE(g.sp); +} + +TEST(Tracer, InjectExplicit) +{ + TestWriter w; + TestTracerImpl imp; + Tracer& t = imp; + + SpanGuard g(t.start("span")); + ASSERT_TRUE(g.sp); + + g.sp->context().setBaggage("animal", "tiger"); + g.sp->context().setBaggage("fruit", "apple"); + + int rc = t.inject(&w, g.sp->context()); + ASSERT_EQ(0, rc); + + ASSERT_EQ(2u, w.carrier.size()); + ASSERT_EQ(w.carrier["animal"], "tiger"); + ASSERT_EQ(w.carrier["fruit"], "apple"); +} + +TEST(Tracer, ExtractExplicit) +{ + TestReader reader; + reader.carrier["animal"] = "tiger"; + reader.carrier["fruit"] = "apple"; + + TestTracerImpl imp; + Tracer& t = imp; + + SpanContextGuard g(t.extract(reader)); + ASSERT_TRUE(g.sp); +} diff --git a/test/unittest.h b/test/unittest.h index 0a33a6a..42e4a20 100644 --- a/test/unittest.h +++ b/test/unittest.h @@ -2,6 +2,13 @@ #define INCLUDED_OPENTRACING_UNITTEST_H #include +#include + +#if HAVE_STDINT_H +#include +#endif + +#include namespace opentracing{}; From 70d15457e3f6cce9999e3899277e22fdcf7b7e6e Mon Sep 17 00:00:00 2001 From: vagrant Date: Thu, 5 Jan 2017 22:04:29 +0000 Subject: [PATCH 03/48] Remove bad example --- example/span_context.h | 90 ------------------------------------------ 1 file changed, 90 deletions(-) delete mode 100644 example/span_context.h diff --git a/example/span_context.h b/example/span_context.h deleted file mode 100644 index 18cefc9..0000000 --- a/example/span_context.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef INCLUDED_OPENTRACING_EXAMPLE_SPAN_CONTEXT_H -#define INCLUDED_OPENTRACING_EXAMPLE_SPAN_CONTEXT_H - -#include - -#include - -namespace example { - -struct span_context : public generic_span_context -{ - public: - typedef std::vector baggage_list; - typedef baggage_list::iterator iterator; - typedef baggage_list::const_iterator iterator; - - iterator - begin() - { - return m_baggage.begin(); - } - - iterator - end() - { - return m_baggage.end(); - } - - const_iterator - begin() const - { - return m_baggage.begin(); - } - - const_iterator - end() const - { - return m_baggage.end(); - } - - int set_baggage(const char* const key, - const size_t klen, - const void* const src, - const size_t src); - - int get_baggage(char* const dest, - const size_t dlen, - const char* const key, - const size_t klen); - - private: - std::vector m_baggage; - -}; - -struct span : public generic_span -{ -} - -struct tracer : public generic_tracer -{ -}; - -typedef generic_tracer Tracer; - - -//// -Tracer* get_instance(); - -Tracer::span_type span; -get_instance->create(&span); -get_instance->create(&span, context[s]); - -span.context().get_baggage(); - -SpanType::SpanContext& c = span.context(); - -c.setBaggage("name", "value"); -c.setBaggage("id", "10"); - -for(const auto& b: c) -{ -} - -get_instance()->inject("key", 3, "val", 3); - - -}; - -#endif From 06ff1515a57633f977ca8a682baf723413f94dd8 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Fri, 6 Jan 2017 10:33:22 -0500 Subject: [PATCH 04/48] Some documentation, StringRefWide --- opentracing/baggage.h | 155 +++++++++++- opentracing/span.h | 519 +++++++++++++++++++++++++++----------- opentracing/spancontext.h | 155 +++++++++--- opentracing/stringref.h | 146 +++++++---- opentracing/tracer.h | 238 ++++++++--------- test/baggage.t.cc | 24 +- test/spancontext.t.cc | 2 +- test/stringref.t.cc | 96 ++++++- test/tracer.t.cc | 2 +- test/unittest.h | 1 + 10 files changed, 976 insertions(+), 362 deletions(-) diff --git a/opentracing/baggage.h b/opentracing/baggage.h index 5a834c6..751e49d 100644 --- a/opentracing/baggage.h +++ b/opentracing/baggage.h @@ -1,56 +1,183 @@ #ifndef INCLUDED_OPENTRACING_BAGGAGE_H #define INCLUDED_OPENTRACING_BAGGAGE_H +// ========= +// baggage.h +// ========= +// class BaggageRef - Client wrapper for referencing key:value pairs +// class BaggageIterator - Client interface to traverse span baggage +// +// ------------------- +// OpenTracing Baggage +// ------------------- +// Baggage items are key:value string pairs that apply to a given Span, its +// SpanContext, and all Spans which directly or transitively reference the local +// Span. That is, baggage items propagate in-band along with the trace itself. +// +// Baggage items enable powerful functionality given a full-stack OpenTracing +// integration (for example, 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. +// +// Use this feature thoughtfully and with care. Every key and value is copied +// into every local and remote child of the associated Span, and that can add up +// to a lot of network and cpu overhead. +// +// See: https://github.com/opentracing/specification + #include namespace opentracing { +// ================ +// class BaggageRef +// ================ +// +// This class wraps references to the key:value pairs that make up 'baggage'. +// The references themselves refer to data managed by SpanContext +// implementations. +// +// Since the implementations of SpanContexts is deferred, it is impossible to +// make strong gurantees on the liftetime of the references. At a minimum, the +// references should be valid until the iterator is destroyed, or until +// 'setBaggage' is called again on a SpanContext. + class BaggageRef { public: - BaggageRef(const StringRef& name, const StringRef& value); + BaggageRef(); + // Construct a 'BaggageRef' with empty references. + + BaggageRef(const StringRef& key, const StringRef& value); + // Construct a 'BaggageRef' referencing 'key' and 'value' + + const StringRef& key() const; + // Return the non-modifiable 'key' associated with this baggage. - const StringRef& name() const; const StringRef& value() const; + // Return the non-modifiable 'value' associated with this baggage. const BaggageRef* operator->() const; + // Syntatic sugar to support dereferencing BaggageIterator's with + // the '->' operator: this method only returns 'this'. private: - StringRef m_name; + StringRef m_key; StringRef m_value; }; +// ===================== +// class BaggageIterator +// ===================== +// ------- +// Clients +// ------- +// For flexibility between implementations, 'BaggageIterator' classes should +// never be created directly. Instead, a typedef is provided by 'SpanContext's +// which allow callers to be agnostic of the underlying implementation. +// By using 'SpanContext::const_iterator', the call sites will be unaffected +// if implementations change in the future. +// +// The iterators themselves satisfy the requirements of C++ "Input Iterators". +// They can read from the pointed-to baggage element, returning 'BaggageRef' for +// the key:value pairs. +// +// Those references only guarantee validity for a single pass: once an iterator +// has been incremented, all copies of its previous value may be invalidated. +// +// See http://en.cppreference.com/w/cpp/concept/InputIterator for more details +// on semantics input iterators. +// +// ------------ +// Implementors +// ------------ +// 'BaggageIterator' is used to obscure the data structure(s) used to store +// and traverse span baggage. Implementors are free to store the key:value +// baggage pairs however they see fit, so long as they provide an +// "Input Iterator" to traverse the structure. +// +// We do not want to expose the details of these data structure(s) to clients; +// If their code were to rely on any detail, it would make it difficult +// to change opentracing implementations. Instead, we define an 'Adapter' +// class, to translate the implementation's iterator into baggage references. +// +// The 'Adapter' class must satisfy the following: +// 1) Provide an 'iterator' typedef, potentially used during construction +// 2) Provide a 'const_iterator' typedef, potentially used during +// construction. +// 3) Overload operator() to convert a const_iterator into a BaggageRef +// +// To achieve this, implementors define a class like so: +// +// struct AdapterClass { +// typedef ImplementationIterator iterator; +// typedef ImplementationIterator const_iterator; +// BaggageRef operator()(const const_iterator& it) const; +// }; +// +// Now, when clients create a 'BaggageIterator' through 'SpanContext::begin()', +// the BaggageIterator should be created with an iterator to the underlying +// baggage implementation. It caches the iterator, incrementing it as +// clients move forward through the sequence. +// +// When clients dreference the baggage iterator, the 'Adapter' is invoked, +// passing the implementation's iterator to the adapter. It is expected that the +// 'Adapter' can convert the iterator into a BaggageRef that client code can +// use in a read-only fashion. + template -struct BaggageIterator { +class BaggageIterator { public: typedef typename ADAPTER::iterator iterator; typedef typename ADAPTER::const_iterator const_iterator; BaggageIterator(const iterator& iter); BaggageIterator(const const_iterator& iter); + // Construct a 'BaggageIterator' object which will be used to traverse the + // sequence pointed to by the input iterator 'iter'. BaggageRef operator*() const; BaggageRef operator->() const; + // Returns a 'BaggageRef' to return the key:value pair pointed to by this + // iterator. BaggageIterator operator++(int); - BaggageIterator operator++(); + // Return a copy of this iterator, then post-increment this iterator to + // point to the next key:value pair in the sequence. + + BaggageIterator& operator++(); + // Increment this iterator, pointing to the next key:value pair in the + // sequence. bool operator==(const BaggageIterator& other) const; + // Returns true if this iterator points to the same key:value pair as + // 'other', and false otherwise. + bool operator!=(const BaggageIterator& other) const; + // Returns true if this iterator points at a different key:value pair + // than 'other', and false otherwise. private: - const_iterator d_iterator; - ADAPTER d_handler; + const_iterator d_iterator; // Traverses implementation storage + ADAPTER d_handler; // Converts 'd_iterator' to BaggageRef }; -inline BaggageRef::BaggageRef(const StringRef& name, const StringRef& value) -: m_name(name), m_value(value) +// ---------------- +// class BaggageRef +// ---------------- + +inline BaggageRef::BaggageRef() : m_key(), m_value() +{ +} + +inline BaggageRef::BaggageRef(const StringRef& key, const StringRef& value) +: m_key(key), m_value(value) { } inline const StringRef& -BaggageRef::name() const +BaggageRef::key() const { - return m_name; + return m_key; } inline const StringRef& @@ -64,6 +191,10 @@ inline const BaggageRef* BaggageRef::operator->() const return this; } +// --------------------- +// class BaggageIterator +// --------------------- + template BaggageIterator::BaggageIterator(const iterator& iter) : d_iterator(iter), d_handler() @@ -97,7 +228,7 @@ BaggageIterator BaggageIterator::operator++(int) } template -BaggageIterator BaggageIterator::operator++() +BaggageIterator& BaggageIterator::operator++() { ++d_iterator; return *this; diff --git a/opentracing/span.h b/opentracing/span.h index afee1e8..ed0e62b 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -1,6 +1,20 @@ #ifndef INCLUDED_OPENTRACING_SPAN_H #define INCLUDED_OPENTRACING_SPAN_H +// ====== +// span.h +// ====== +// class GenericSpan - CRTP interface for Spans +// +// ---- +// Span +// ---- +// Every Trace is made up of one or more Spans. Spans are used to: +// * TODO +// +// See the specification for more details: +// https://github.com/opentracing/specification/blob/master/specification.md#span + #include #ifdef HAVE_STDINT_H @@ -12,32 +26,120 @@ namespace opentracing { -template +// ================= +// class GenericSpan +// ================= +// GenericSpan is a static, polymorphic interface for interacting with +// Spans. It uses the Curiously Repeating Template Patttern (CRTP) to +// avoid unnecessary v-table hits we would encounter with traditional +// polymorphism. +// +// See this CRTP article for more details on the design pattern: +// https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern +// +// ------- +// Clients +// ------- +// GenericSpans are not created directly by clients. They are instead +// created and cleaned up through the installed Tracer interface. +// +// Clients should never need to reference the GenericSpan type explicitly. +// Instead, clients should use the Tracer::Span typedef. By using the typedef, +// clients will avoid code changes necessary if a different Tracer +// implementation is installed later. +// +// Once clients have access to a Span, they can: +// * Access the underlying SpanContext via 'context()' +// * 'log()' timestamped key:value pairs +// * 'tag()' a span, with key:value pairs +// * 'finish()' a span +// +// After 'finish()' is called, it is undefined behavior to invoke any other +// method on the Span, except for accessing 'context()' in a read-only fashion. +// When clients are finished with a Span, it should be passed back to the +// Tracer via 'Tracer::cleanup()'. +// +// For more details on: +// * Accessing/retrieving Baggage, see 'spancontext.h' +// * Creating/Cleaning up Spans, see 'tracer.h' +// +// ------------ +// Implementors +// ------------ +// The GenericSpan has three template parameters: +// * SPAN - A Span implementation derived class (CRTP) +// * CONTEXT - A SpanContext implementation derived class (CRTP) +// * ADAPTER - A Baggage iterator adapter +// +// The CONTEXT and ADAPTER are only used to establish the GenericSpanContext +// interface used for the SpanContext typedef. +// +// SPAN implementations have to support the following: +// +// class SpanImpl: GenericSpan +// { +// public: +// SpanContext& contextImp(); +// const SpanContext& contextImp() const; +// +// int finishImp(); +// int finishImp(const uint64_t); +// +// int tagImp(const StringRef& key, const Fundamental val); +// int tagImp(const StringRef& key, const StringRef& val); +// +// int logImp(const StringRef& key, const Fundamental val); +// int logImp(const StringRef& key, const StringRef& val); +// +// int logImp(const StringRef& key, const Fundamental val, const uint64_t +// tsp); +// int logImp(const StringRef& key, const StringRef& val, const uint64_t +// tsp); +// }; +// +// For brevities sake, the above example collapses the overloads on fundamental +// C++ types for 'tagImp()' and 'logImp()' into a single declaration on the +// 'Fundamental' type. For actual implementations, overloads must be supplied +// for each of the following fundamental types. +// +// http://en.cppreference.com/w/cpp/language/types: +// * float * int16_t * uint16_t * char * wchar_t +// * double * int32_t * uint32_t * signed char * bool +// * long double * int64_t * uint64_t * unsigned char +// +// The overloads are used instead of a single template to: +// * Avoid passing references larger than the types they refer to (64-bit) +// * Avoid ambiguities at compile time when clients use the overloads + +template class GenericSpan { public: - virtual ~GenericSpan(); - - typedef IMPL Span; typedef GenericSpanContext SpanContext; SpanContext& context(); const SpanContext& context() const; - // Return the SpanContext associated with this span. Baggage can - // be set or accessed through the underlying context directly. + // be retrieved/modified through the SpanContext. int finish(); int finish(const uint64_t tsp); - // Finish this span. Mark the end of the span (in microseconds since epoch) - // using the 'tsp' time-stamp. If 'tsp' is not supplied, the internal - // wall-time should be used to mark the end of the span instead. It is - // undefined behavior to call any method on this span after 'finish' is - // called, except for 'context()'. + // This should be the last method called on the Span. It marks the end of + // this Span (in microseconds since epoch) using the current wall-time, or + // an explicit timestamp 'tsp'. It is undefined behavior to call any method + // on this span after 'finish' is called, except for 'context()'. + // Returns 0 upon success and a non-zero value otherwise. + int tag(const StringRef& key, const StringRef& val); int tag(const StringRef& key, const bool val); + int tag(const StringRef& key, const float val); int tag(const StringRef& key, const double val); - int tag(const StringRef& key, const StringRef& val); + int tag(const StringRef& key, const long double val); + + int tag(const StringRef& key, const char val); + int tag(const StringRef& key, const signed char val); + int tag(const StringRef& key, const unsigned char val); + int tag(const StringRef& key, const wchar_t val); int tag(const StringRef& key, const int16_t val); int tag(const StringRef& key, const int32_t val); @@ -46,15 +148,21 @@ class GenericSpan { int tag(const StringRef& key, const uint16_t val); int tag(const StringRef& key, const uint32_t val); int tag(const StringRef& key, const uint64_t val); + // Set a tag on this span, associating the supplied 'key' to the supplied + // 'val'. Overloads are supplied for common primitive types and a string + // blob. Returns 0 upon success and a non-zero value otherwise. - // Set a tag on this span, associating the supplied 'key' characters to - // the supplied value. Overloads are supplied for common primitive types, - // and a string blob - + int log(const StringRef& key, const StringRef& val); int log(const StringRef& key, const bool val); + int log(const StringRef& key, const float val); int log(const StringRef& key, const double val); - int log(const StringRef& key, const StringRef& val); + int log(const StringRef& key, const long double val); + + int log(const StringRef& key, const char val); + int log(const StringRef& key, const signed char val); + int log(const StringRef& key, const unsigned char val); + int log(const StringRef& key, const wchar_t val); int log(const StringRef& key, const int16_t val); int log(const StringRef& key, const int32_t val); @@ -63,11 +171,21 @@ class GenericSpan { int log(const StringRef& key, const uint16_t val); int log(const StringRef& key, const uint32_t val); int log(const StringRef& key, const uint64_t val); + // Log structured data for this span, associating the current wall-time + // with the supplied key:val pair. Returns 0 upon success and a non-zero + // value otherwise. + int log(const StringRef& key, const StringRef& val, const uint64_t tsp); int log(const StringRef& key, const bool val, const uint64_t tsp); + int log(const StringRef& key, const float val, const uint64_t tsp); int log(const StringRef& key, const double val, const uint64_t tsp); - int log(const StringRef& key, const StringRef& val, const uint64_t tsp); + int log(const StringRef& key, const long double val, const uint64_t tsp); + + int log(const StringRef& key, const char val, const uint64_t tsp); + int log(const StringRef& key, const signed char val, const uint64_t tsp); + int log(const StringRef& key, const unsigned char val, const uint64_t tsp); + int log(const StringRef& key, const wchar_t val, const uint64_t tsp); int log(const StringRef& key, const int16_t val, const uint64_t tsp); int log(const StringRef& key, const int32_t val, const uint64_t tsp); @@ -76,14 +194,10 @@ class GenericSpan { int log(const StringRef& key, const uint16_t val, const uint64_t tsp); int log(const StringRef& key, const uint32_t val, const uint64_t tsp); int log(const StringRef& key, const uint64_t val, const uint64_t tsp); - - // Structured data should be logged through one of the calls to 'log'. From - // this point forward, this span will associate 'key' with the supplied - // 'value'. This is similar to 'tag()', but additionally includes a - // time-stamp noting the number of microseconds that have elapsed since - // the Unix epoch. If time-stamp is not supplied, the current wall-time - // is used, otherwise the explicit time-stamp is used. The time-stamp - // should be between the start and finish times for this span. + // Log structured data for this span, associating the explicit timestamp + // 'tsp' with the supplied 'key':'val' pair. Timestamp should be the + // number of microseconds since the Unix Epoch. Returns 0 upon success and a + // non-zero value otherwise. protected: GenericSpan(); @@ -91,303 +205,418 @@ class GenericSpan { // Protected to avoid direct construction }; -// Virtual destructor +// Protected Constructors -template -GenericSpan::~GenericSpan() +template +GenericSpan::GenericSpan() { } -// Protected Constructors +template +GenericSpan::GenericSpan(const GenericSpan&) +{ +} -template -GenericSpan::GenericSpan() +// Context Accessors + +template +typename GenericSpan::SpanContext& +GenericSpan::context() { + return static_cast(this)->contextImp(); } -template -GenericSpan::GenericSpan(const GenericSpan&) +template +const typename GenericSpan::SpanContext& +GenericSpan::context() const { + return static_cast(this)->contextImp(); } -// Context Accessors +// Tags -template -typename GenericSpan::SpanContext& -GenericSpan::context() +template +int +GenericSpan::finish() { - return static_cast(this)->contextImp(); + return static_cast(this)->finishImp(); } -template -const typename GenericSpan::SpanContext& -GenericSpan::context() const +template +int +GenericSpan::finish(const uint64_t tsp) { - return static_cast(this)->contextImp(); + return static_cast(this)->finishImp(tsp); } -// Tags +template +int +GenericSpan::tag(const StringRef& key, + const StringRef& val) +{ + return static_cast(this)->tagImp(key, val); +} -template +template int -GenericSpan::finish() +GenericSpan::tag(const StringRef& key, const bool val) { - return static_cast(this)->finishImp(); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::finish(const uint64_t tsp) +GenericSpan::tag(const StringRef& key, const float val) { - return static_cast(this)->finishImp(tsp); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, const bool val) +GenericSpan::tag(const StringRef& key, const double val) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, const float val) +GenericSpan::tag(const StringRef& key, + const long double val) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, const double val) +GenericSpan::tag(const StringRef& key, const char val) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, - const StringRef& val) +GenericSpan::tag(const StringRef& key, + const signed char val) +{ + return static_cast(this)->tagImp(key, val); +} + +template +int +GenericSpan::tag(const StringRef& key, + const unsigned char val) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, +GenericSpan::tag(const StringRef& key, + const wchar_t val) +{ + return static_cast(this)->tagImp(key, val); +} + +template +int +GenericSpan::tag(const StringRef& key, const int16_t val) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, +GenericSpan::tag(const StringRef& key, const int32_t val) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, +GenericSpan::tag(const StringRef& key, const int64_t val) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, +GenericSpan::tag(const StringRef& key, const uint16_t val) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, +GenericSpan::tag(const StringRef& key, const uint32_t val) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->tagImp(key, val); } -template +template int -GenericSpan::tag(const StringRef& key, +GenericSpan::tag(const StringRef& key, const uint64_t val) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->tagImp(key, val); } // Logs -template +template +int +GenericSpan::log(const StringRef& key, + const StringRef& val) +{ + return static_cast(this)->logImp(key, val); +} + +template int -GenericSpan::log(const StringRef& key, const bool val) +GenericSpan::log(const StringRef& key, const bool val) { - return static_cast(this)->logImp(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::log(const StringRef& key, const float val) +GenericSpan::log(const StringRef& key, const float val) { - return static_cast(this)->logImp(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::log(const StringRef& key, const double val) +GenericSpan::log(const StringRef& key, const double val) { - return static_cast(this)->logImp(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::log(const StringRef& key, - const StringRef& val) +GenericSpan::log(const StringRef& key, + const long double val) +{ + return static_cast(this)->logImp(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, const char val) +{ + return static_cast(this)->logImp(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, + const signed char val) +{ + return static_cast(this)->logImp(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, + const unsigned char val) +{ + return static_cast(this)->logImp(key, val); +} + +template +int +GenericSpan::log(const StringRef& key, + const wchar_t val) { - return static_cast(this)->logImp(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const int16_t val) { - return static_cast(this)->logImp(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const int32_t val) { - return static_cast(this)->logImp(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const int64_t val) { - return static_cast(this)->logImp(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const uint16_t val) { - return static_cast(this)->logImp(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const uint32_t val) { - return static_cast(this)->logImp(key, val); + return static_cast(this)->logImp(key, val); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const uint64_t val) { - return static_cast(this)->logImp(key, val); + return static_cast(this)->logImp(key, val); } // Logs with timestamps -// -template +template +int +GenericSpan::log(const StringRef& key, + const StringRef& val, + const uint64_t tsp) +{ + return static_cast(this)->logImp(key, val, tsp); +} + +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const bool val, const uint64_t tsp) { - return static_cast(this)->logImp(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const float val, const uint64_t tsp) { - return static_cast(this)->logImp(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const double val, const uint64_t tsp) { - return static_cast(this)->logImp(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, - const StringRef& val, - const uint64_t tsp) +GenericSpan::log(const StringRef& key, + const long double val, + const uint64_t tsp) +{ + return static_cast(this)->logImp(key, val, tsp); +} + +template +int +GenericSpan::log(const StringRef& key, + const char val, + const uint64_t tsp) +{ + return static_cast(this)->logImp(key, val, tsp); +} + +template +int +GenericSpan::log(const StringRef& key, + const signed char val, + const uint64_t tsp) +{ + return static_cast(this)->logImp(key, val, tsp); +} + +template +int +GenericSpan::log(const StringRef& key, + const unsigned char val, + const uint64_t tsp) +{ + return static_cast(this)->logImp(key, val, tsp); +} + +template +int +GenericSpan::log(const StringRef& key, + const wchar_t val, + const uint64_t tsp) { - return static_cast(this)->logImp(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const int16_t val, const uint64_t tsp) { - return static_cast(this)->logImp(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const int32_t val, const uint64_t tsp) { - return static_cast(this)->logImp(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const int64_t val, const uint64_t tsp) { - return static_cast(this)->logImp(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const uint16_t val, const uint64_t tsp) { - return static_cast(this)->logImp(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const uint32_t val, const uint64_t tsp) { - return static_cast(this)->logImp(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } -template +template int -GenericSpan::log(const StringRef& key, +GenericSpan::log(const StringRef& key, const uint64_t val, const uint64_t tsp) { - return static_cast(this)->logImp(key, val, tsp); + return static_cast(this)->logImp(key, val, tsp); } } // end namespace opentracing diff --git a/opentracing/spancontext.h b/opentracing/spancontext.h index 4d78a3a..2b5b377 100644 --- a/opentracing/spancontext.h +++ b/opentracing/spancontext.h @@ -1,29 +1,120 @@ #ifndef INCLUDED_OPENTRACING_SPANCONTEXT_H #define INCLUDED_OPENTRACING_SPANCONTEXT_H -#include +// ============= +// spancontext.h +// ============= +// class GenericSpanContext - CRTP interface for SpanContexts +// +// ----------- +// SpanContext +// ----------- +// Every Span has a SpanContext. This context is used to: +// * Inject Spans into Carriers +// * Represent a Span in-band, across process boundaries +// * Extract Spans from Carriers +// * Create new Spans, related to the SpanContext +// +// Since the Span has to represent the entire Span in-band, and baggage must +// also be propagated across process boundaries, the SpanContext is also +// responsible for baggage. +// +// In most OpenTracing implementations, the SpanContext is made immutable in +// order to avoid complicated lifetime issues. The C++ interface relaxes those +// requirements, exposing the 'GenericSpanContext::setBaggage()' method directly +// on the context. +// +// See the specification for more details: +// https://github.com/opentracing/specification/blob/master/specification.md#Spancontext + #include +#include namespace opentracing { -template +// ======================== +// class GenericSpanContext +// ======================== +// GenericSpanContext is a static, polymorphic interface for interacting with +// SpanContexts. It uses the Curiously Repeating Template Pattern (CRTP) to +// avoid unnecessary v-table hits we would encounter with traditional +// polymorphism. +// +// See this CRTP article for more details on the design pattern: +// https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern +// +// ------- +// Clients +// ------- +// After a Span is created, the 'Span::context()' method is used to access +// a context that supports the 'GenericSpanContext' interface. +// +// Clients should never need to reference the GenericSpanContext type +// explicitly, but instead, clients should use the Tracer::Span::SpanContext +// typedef. By using the typedef, clients will avoid code changes necessary if a +// different Tracer implementation is installed later. +// +// Once clients have access to a SpanContext, they can: +// * 'setBaggage()' key:value pairs +// * 'getBaggage()' for a given key +// * Iterate over all Baggage via 'begin()'/'end()' +// +// For more details on: +// * accessing a SpanContext, see 'span.h' +// * iterating over Baggage, see 'baggage.h' +// * inject/extract, see 'tracer.h +// +// ------------ +// Implementors +// ------------ +// The 'GenericSpanContext' has two template parameters: +// * CONTEXT - A SpanContext implementation derived class (CRTP) +// * ADAPTER - A BaggageIterator adapter +// +// CONTEXT implementations are required to implement the following: +// +// class ContextImpl : GenericSpanContext +// { +// public: +// const_iterator beginImp() const; +// const_iterator endImp() const; +// int setBaggageImp(const StringRef& const, const StringRef& baggage); +// int getBaggageImp(StringRef *const, const StringRef& key) const; +// }; +// +// Implementations may choose how they implement Baggage, but the +// beginImp/endImp iterators should interact with the installed +// BaggageIterator/Adapter correctly. +// +// Since the SpanContext implementation type is decided at compile time, Span +// and Tracer implementations may safely static_cast GenericSpanContext +// references down to the installed SpanContext implementation. Doing so allows +// access to methods/members that would be otherwise inaccessible through the +// base class interface. This is a useful tool when implementing inject/extract +// in Tracers. + +template class GenericSpanContext { public: - typedef IMPL SpanContext; + typedef CONTEXT SpanContext; typedef ADAPTER BaggageAdapter; typedef BaggageIterator const_iterator; - virtual ~GenericSpanContext(); - const_iterator begin() const; + // Return a BaggageIterator to the beginning of the Baggage maintained + // by this SpanContext. + const_iterator end() const; - // Return iterators to baggage managed by this SpanContext. + // Return a BaggageIterator to mark the end of the baggage maintained + // by this SpanContext. int setBaggage(const StringRef& key, const StringRef& baggage); - // Associate the supplied 'key' with the 'baggage'. + // Associate the supplied 'key' with the 'baggage'. Returns 0 upon + // success and a non-zero value otherwise. int getBaggage(StringRef* const baggage, const StringRef& key) const; - // Load the 'baggage' associated with 'key'. + // Load the 'baggage' associated with 'key'. Returns 0 if the + // baggage is loaded succesfully, and a non-zero value otherwise. protected: GenericSpanContext(); @@ -31,49 +122,49 @@ class GenericSpanContext { // Protected to avoid direct construction }; -template -GenericSpanContext::~GenericSpanContext() -{ -} +// ------------------------ +// class GenericSpanContext +// ------------------------ -template -GenericSpanContext::GenericSpanContext() +template +GenericSpanContext::GenericSpanContext() { } -template -GenericSpanContext::GenericSpanContext(const GenericSpanContext&) +template +GenericSpanContext::GenericSpanContext( + const GenericSpanContext&) { } -template -typename GenericSpanContext::const_iterator -GenericSpanContext::begin() const +template +typename GenericSpanContext::const_iterator +GenericSpanContext::begin() const { - return const_iterator(static_cast(this)->beginImp()); + return const_iterator(static_cast(this)->beginImp()); } -template -typename GenericSpanContext::const_iterator -GenericSpanContext::end() const +template +typename GenericSpanContext::const_iterator +GenericSpanContext::end() const { - return const_iterator(static_cast(this)->endImp()); + return const_iterator(static_cast(this)->endImp()); } -template +template int -GenericSpanContext::setBaggage(const StringRef& key, - const StringRef& baggage) +GenericSpanContext::setBaggage(const StringRef& key, + const StringRef& baggage) { - return static_cast(this)->setBaggageImp(key, baggage); + return static_cast(this)->setBaggageImp(key, baggage); } -template +template int -GenericSpanContext::getBaggage(StringRef* const baggage, - const StringRef& key) const +GenericSpanContext::getBaggage(StringRef* const baggage, + const StringRef& key) const { - return static_cast(this)->getBaggageImp(baggage, key); + return static_cast(this)->getBaggageImp(baggage, key); } } // namespace opentracing #endif // INCLUDED_OPENTRACING_SPANCONTEXT_H diff --git a/opentracing/stringref.h b/opentracing/stringref.h index 640fa42..ddce810 100644 --- a/opentracing/stringref.h +++ b/opentracing/stringref.h @@ -1,143 +1,199 @@ #ifndef INCLUDED_OPENTRACING_STRINGREF_H #define INCLUDED_OPENTRACING_STRINGREF_H -#include +// =========== +// stringref.h +// =========== +// class StringRefImp - Templated implementation for a constant reference to an external string +// typedef StringRef - Typedef for StringRefImp +// typedef StringRefWide - Typedef for StringRefImp +// +// ----------------- +// 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 #include namespace opentracing { -// --------- -// StringRef -// --------- -// Represent a constant reference to an external character, which does not have -// to be null terminated. This class does not own the string 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. - -struct StringRef { +// ================== +// class StringRefImp +// ================== +// 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 StringRefImp. For this reason, it is not in general safe to +// store a StringRefImp. + +template +class StringRefImp { public: - StringRef(); + StringRefImp(); + // Conststruct an empty StringRef template - StringRef(const char (&str)[N]); - // Explicitly create string reference from a const character array + StringRefImp(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 + explicit StringRefImp(const CHAR* str); + // Explicitly create string reference from const CHARacter pointer - StringRef(const std::string& str); + StringRefImp(const std::basic_string& str); // Create constant string reference from pointer and length - StringRef(const char* str, size_t len); + StringRefImp(const CHAR* str, size_t len); // Create constant string reference from pointer and length - operator const char*() const; - // Implicit conversion to plain char * + 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)[N]); + // Reset the string reference given a const CHARacter array - void reset(const char* const str); + void reset(const CHAR* const str); // Reset this string ref to point at the supplied c-string - void reset(const std::string& str); + void reset(const std::basic_string& str); // Reset the string reference given a std::string - void reset(const char* const str, const size_t length); + void reset(const CHAR* const str, const size_t length); // Reset this string ref to point at the supplied 'str' of 'length' bytes. - const char* data() const; + const CHAR* data() const; // Return address of the referenced string size_t length() const; // Return the length of the referenced string private: + static size_t getLength(const CHAR* len); + // Similar to strlen, but for both char/wchar types + template - StringRef(char (&str)[N]); + StringRefImp(CHAR (&str)[N]); // Disallow construction from non-const array template - void reset(char (&str)[N]); + void reset(CHAR (&str)[N]); // Disallow reset from non-const array - const char* m_data; - size_t m_length; + const CHAR* m_data; // Pointer to external storage + size_t m_length; // Length of data pointed to by 'm_data' }; -inline StringRef::StringRef() : m_data(0), m_length(0) +// -------- +// Typedefs +// -------- + +typedef StringRefImp StringRef; +typedef StringRefImp StringRefWide; + +// ------------------ +// Class StringRefImp +// ------------------ + +template +inline StringRefImp::StringRefImp() : m_data(0), m_length(0) { } +template template -inline StringRef::StringRef(const char (&str)[N]) : m_data(str), m_length(N - 1) +inline StringRefImp::StringRefImp(const CHAR (&str)[N]) : m_data(str), m_length(N - 1) { } -inline StringRef::StringRef(const char* const str) -: m_data(str), m_length(std::strlen(str)) +template +inline StringRefImp::StringRefImp(const CHAR* const str) +: m_data(str), m_length(getLength(str)) { } -inline StringRef::StringRef(const std::string& str) +template +inline StringRefImp::StringRefImp(const std::basic_string& str) : m_data(str.c_str()), m_length(str.length()) { } -inline StringRef::StringRef(const char* str, size_t len) +template +inline StringRefImp::StringRefImp(const CHAR* str, size_t len) : m_data(str), m_length(len) { } -inline StringRef::operator const char*() const +template +inline StringRefImp::operator const CHAR*() const { return m_data; } +template inline void -StringRef::reset(const char* const str, const size_t length) +StringRefImp::reset(const CHAR* const str, const size_t length) { m_data = str; m_length = length; } +template template inline void -StringRef::reset(const char (&str)[N]) +StringRefImp::reset(const CHAR (&str)[N]) { m_data = str; m_length = N; } +template inline void -StringRef::reset(const char* const str) +StringRefImp::reset(const CHAR* const str) { m_data = str; - m_length = std::strlen(str); + m_length = getLength(str); } +template inline void -StringRef::reset(const std::string& str) +StringRefImp::reset(const std::basic_string& str) { m_data = str.data(); m_length = str.length(); } -inline const char* -StringRef::data() const +template +inline const CHAR* +StringRefImp::data() const { return m_data; } +template inline size_t -StringRef::length() const +StringRefImp::length() const { return m_length; } +template +inline size_t +StringRefImp::getLength(const CHAR* s) +{ + const CHAR* p = s; + while (*p) ++p; + return size_t(p - s); +} + } // namespace opentracing #endif // INCLUDED_OPENTRACING_STRINGREF_H diff --git a/opentracing/tracer.h b/opentracing/tracer.h index ce98acb..70a0c2b 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -13,103 +13,107 @@ namespace opentracing { -template +template class GenericTracer { public: typedef GenericSpan Span; typedef GenericSpanContext SpanContext; static void install(GenericTracer* const tracer); - // Install 'tracer' to be referenced globally. This method is not thread - // safe. - // It should be called once, in main, before any other thread or trace work - // is performed. Undefined behavior otherwise. + // Install Tracer to be referenced globally with calls to 'instance()'. + // This method is not thread safe. It should be called once, in main, before + // any other thread or trace work is performed. Undefined behavior if called + // otherwise. static void uninstall(); - // Uninstall any 'tracer' that may have been previously installed. This - // method - // is not thread safe. It should only be called in test environments. + // Uninstall a previously installed Tracer. This method is not thread safe, + // nor is it required for production code. It is used to sanitize test + // environments if needed. static GenericTracer* instance(); - // Return an instance to the globally installed tracer. Returns null if a + // Return an instance to the globally installed tracer. Returns NULL if a // tracer has not been previously installed. It is undefined behavior // to call this method without previously calling 'install()'. - virtual ~GenericTracer(); - Span* start(const StringRef& op); - Span* start(const StringRef& op, const uint64_t tsp); - Span* start(const StringRef& op, const SpanContext& parent); + template + Span* start(const StringRef& op, const ITER& pbegin, const ITER& pend); + + Span* start(const StringRef& op, const uint64_t tsp); Span* start(const StringRef& op, const SpanContext& parent, const uint64_t tsp); - template - Span* start(const StringRef& op, const ITER& pbegin, const ITER& pend); - template Span* start(const StringRef& op, const ITER& pbegin, const ITER& pend, const uint64_t tsp); - // The 'start' methods are used to create a new 'Span'. The only required + // The 'start' methods are used to create a new Span. The only required // parameter is the operation string 'op', which should describe the work // being performed during the span. // // The optional arguments are: // parent: - // Refer a SpanContext, establishing the new span as a child of the - // supplied context + // Establish the new Span as a child of the supplied parent // // pbegin/pend: // Supply a range of iterators, which when dereferenced refer to // a SpanContext&. The new span would be a child of all of the - // supplied parents. + // supplied parents Spans. // // tsp: // The time-stamp marking the start of the new Span. 'tsp' should // represent the number of microseconds that have elapsed since // the Unix epoch. - template - int inject(GenericTextWriter* const carrier, + void cleanup(Span *const sp); + // All Span pointers returned by the Tracer should be passed back + // to the Tracer when client's are done with them via 'cleanup()'. + + template + int inject(GenericTextWriter* const carrier, const SpanContext& context) const; // Inject the supplied 'context' into the text map writer 'carrier'. - template - SpanContext* extract(const GenericTextReader& carrier); - // Extract the supplied 'context' from the text map reader 'carrier'. - - template - int inject(GenericBinaryWriter* const carrier, + template + int inject(GenericBinaryWriter* const carrier, const SpanContext& context) const; // Inject the supplied 'context' into the binary writer 'carrier'. - template - SpanContext* extract(const GenericBinaryReader& carrier); - // Extract the supplied 'context' from the binary reader 'carrier'. - - template - int inject(GenericWriter* const carrier, + template + int inject(GenericWriter* const carrier, const SpanContext& context) const; // Inject the SpanContext directly into the specialized 'carrier'. // - // Note: The carrier will be passed the 'SpanContext' directly. - // Using this may make your carrier code more efficient, but it + // Note: The carrier will be passed the SpanContext directly. + // Using this may make your carrier code more efficient, but, it // removes flexibility if you want to swap Tracer/Span // implementations. - template - SpanContext* extract(const GenericReader& carrier); + template + SpanContext* extract(const GenericTextReader& carrier); + // Extract the supplied 'context' from the text map reader 'carrier'. + + template + SpanContext* extract(const GenericBinaryReader& carrier); + // Extract the supplied 'context' from the binary reader 'carrier'. + + template + SpanContext* extract(const GenericReader& carrier); // Extract the SpanContext from the specialized 'carrier'. // - // Note: The carrier will be passed the 'SpanContext' directly. - // Using this may make your carrier code more efficient, but it + // Note: The carrier will be passed the SpanContext directly. + // Using this may make your carrier code more efficient, but, it // removes flexibility if you want to swap Tracer/Span implementations // later. + void cleanup(SpanContext* const sp); + // All SpanContext pointers returned by the Tracer should be passed back + // to the Tracer when client's are done with them via 'cleanup()'. + protected: GenericTracer(); GenericTracer(const GenericTracer&); @@ -119,153 +123,161 @@ class GenericTracer { static GenericTracer* s_tracer; }; -template -GenericTracer* - GenericTracer::s_tracer = 0; +template +GenericTracer* + GenericTracer::s_tracer = 0; -template +template void -GenericTracer::install( +GenericTracer::install( GenericTracer* const tracer) { s_tracer = tracer; } -template +template void -GenericTracer::uninstall() +GenericTracer::uninstall() { s_tracer = 0; } -template -GenericTracer* -GenericTracer::instance() +template +GenericTracer* +GenericTracer::instance() { return s_tracer; } -template -GenericTracer::~GenericTracer() +template +GenericTracer::GenericTracer() { } -template -GenericTracer::GenericTracer() +template +GenericTracer::GenericTracer(const GenericTracer&) { } -template -GenericTracer::GenericTracer(const GenericTracer&) +template +void +GenericTracer::cleanup(Span *const sp) +{ + return static_cast(this)->cleanupImp(sp); +} +template +void +GenericTracer::cleanup(SpanContext *const spc) { + return static_cast(this)->cleanupImp(spc); } -template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op) +template +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op) { - return static_cast(this)->startImp(op); + return static_cast(this)->startImp(op); } -template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op, +template +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op, const uint64_t tsp) { - return static_cast(this)->startImp(op, tsp); + return static_cast(this)->startImp(op, tsp); } -template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op, +template +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op, const SpanContext& parent) { - return static_cast(this)->startImp(op, parent); + return static_cast(this)->startImp(op, parent); } -template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op, +template +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op, const SpanContext& parent, const uint64_t tsp) { - return static_cast(this)->startImp(op, parent, tsp); + return static_cast(this)->startImp(op, parent, tsp); } -template +template template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op, +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op, const ITER& begin, const ITER& end) { - return static_cast(this)->startImp(op, begin, end); + return static_cast(this)->startImp(op, begin, end); } -template +template template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op, +typename GenericTracer::Span* +GenericTracer::start(const StringRef& op, const ITER& begin, const ITER& end, const uint64_t tsp) { - return static_cast(this)->startImp(op, begin, end, tsp); + return static_cast(this)->startImp(op, begin, end, tsp); } -template -template +template +template int -GenericTracer::inject( - GenericTextWriter* const carrier, const SpanContext& context) const +GenericTracer::inject( + GenericTextWriter* const carrier, const SpanContext& context) const { - return static_cast(this)->injectImp(carrier, context); + return static_cast(this)->injectImp(carrier, context); } -template -template -typename GenericTracer::SpanContext* -GenericTracer::extract( - const GenericTextReader& carrier) +template +template +typename GenericTracer::SpanContext* +GenericTracer::extract( + const GenericTextReader& carrier) { - return static_cast(this)->extractImp(carrier); + return static_cast(this)->extractImp(carrier); } -template -template +template +template int -GenericTracer::inject( - GenericBinaryWriter* const carrier, const SpanContext& context) const +GenericTracer::inject( + GenericBinaryWriter* const carrier, const SpanContext& context) const { - return static_cast(this)->injectImp(carrier, context); + return static_cast(this)->injectImp(carrier, context); } -template -template -typename GenericTracer::SpanContext* -GenericTracer::extract( - const GenericBinaryReader& carrier) +template +template +typename GenericTracer::SpanContext* +GenericTracer::extract( + const GenericBinaryReader& carrier) { - return static_cast(this)->extractImp(carrier); + return static_cast(this)->extractImp(carrier); } -template -template +template +template int -GenericTracer::inject( - GenericWriter* const carrier, +GenericTracer::inject( + GenericWriter* const carrier, const SpanContext& context) const { - return static_cast(this)->injectImp(carrier, context); + return static_cast(this)->injectImp(carrier, context); } -template -template -typename GenericTracer::SpanContext* -GenericTracer::extract( - const GenericReader& carrier) +template +template +typename GenericTracer::SpanContext* +GenericTracer::extract( + const GenericReader& carrier) { - return static_cast(this)->extractImp(carrier); + return static_cast(this)->extractImp(carrier); } } #endif diff --git a/test/baggage.t.cc b/test/baggage.t.cc index 77dac12..92cbd75 100644 --- a/test/baggage.t.cc +++ b/test/baggage.t.cc @@ -14,7 +14,7 @@ TEST(BaggageRef, Constructor) BaggageRef ref(n, v); - ASSERT_EQ(n, ref.name().data()); + ASSERT_EQ(n, ref.key().data()); ASSERT_EQ(v, ref.value().data()); } @@ -26,7 +26,7 @@ TEST(BaggageRef, CopyConstructor) BaggageRef ref(n, v); BaggageRef cpy(ref); - ASSERT_EQ(n, cpy.name().data()); + ASSERT_EQ(n, cpy.key().data()); ASSERT_EQ(v, cpy.value().data()); } @@ -43,7 +43,7 @@ TEST(BaggageRef, Assignment) ref = ref2; - ASSERT_EQ(n2, ref.name().data()); + ASSERT_EQ(n2, ref.key().data()); ASSERT_EQ(v2, ref.value().data()); } @@ -73,7 +73,7 @@ TEST(BaggageIterator, MapBaggageAdapter) ASSERT_FALSE(end == it); BaggageRef ref = *it; - ASSERT_STREQ("animal", ref.name()); + ASSERT_STREQ("animal", ref.key()); ASSERT_STREQ("dog", ref.value()); BaggageIterator prev = it++; @@ -82,12 +82,12 @@ TEST(BaggageIterator, MapBaggageAdapter) ref = *prev; - ASSERT_STREQ("animal", ref.name()); + ASSERT_STREQ("animal", ref.key()); ASSERT_STREQ("dog", ref.value()); ref = *it; - ASSERT_STREQ("fruit", ref.name()); + ASSERT_STREQ("fruit", ref.key()); ASSERT_STREQ("apple", ref.value()); ++it; @@ -95,7 +95,7 @@ TEST(BaggageIterator, MapBaggageAdapter) ref = *it; - ASSERT_STREQ("veggie", ref.name()); + ASSERT_STREQ("veggie", ref.key()); ASSERT_STREQ("carrot", ref.value()); ++it; @@ -128,7 +128,7 @@ TEST(BaggageIterator, ForLoopSyntax) ++it, ++index) { // Test the -> syntax works - ASSERT_STREQ(expectedKeys[index], it->name()); + ASSERT_STREQ(expectedKeys[index], it->key()); ASSERT_STREQ(expectedVals[index], it->value()); } } @@ -174,7 +174,7 @@ TEST(BaggageIterator, ListBaggageAdapter) ASSERT_FALSE(end == it); BaggageRef ref = *it; - ASSERT_STREQ("animal", ref.name()); + ASSERT_STREQ("animal", ref.key()); ASSERT_STREQ("dog", it->value()); BaggageIterator prev = it++; @@ -183,12 +183,12 @@ TEST(BaggageIterator, ListBaggageAdapter) ref = *prev; - ASSERT_STREQ("animal", ref.name()); + ASSERT_STREQ("animal", ref.key()); ASSERT_STREQ("dog", ref.value()); ref = *it; - ASSERT_STREQ("fruit", ref.name()); + ASSERT_STREQ("fruit", ref.key()); ASSERT_STREQ("apple", ref.value()); ++it; @@ -196,7 +196,7 @@ TEST(BaggageIterator, ListBaggageAdapter) ref = *it; - ASSERT_STREQ("veggie", ref.name()); + ASSERT_STREQ("veggie", ref.key()); ASSERT_STREQ("carrot", ref.value()); ++it; diff --git a/test/spancontext.t.cc b/test/spancontext.t.cc index 5d8c04e..5cb5d2e 100644 --- a/test/spancontext.t.cc +++ b/test/spancontext.t.cc @@ -24,7 +24,7 @@ TEST(GenericSpanContext, Baggage) TestContext::const_iterator it = t.begin(); - ASSERT_STREQ("hello", it->name().data()); + ASSERT_STREQ("hello", it->key().data()); ASSERT_STREQ("world", it->value().data()); ++it; diff --git a/test/stringref.t.cc b/test/stringref.t.cc index 725e24c..a13149b 100644 --- a/test/stringref.t.cc +++ b/test/stringref.t.cc @@ -6,7 +6,6 @@ TEST(StringRef, Empty) { StringRef ref; - ASSERT_EQ(0, ref.data()); ASSERT_EQ(0, ref.length()); } @@ -98,3 +97,98 @@ TEST(StringRef, Reset) ASSERT_STREQ(p, ref); ASSERT_STREQ(p, ref.data()); } + +TEST(StringRefWide, Empty) +{ + StringRefWide ref; + ASSERT_EQ(0, ref.data()); + ASSERT_EQ(0, ref.length()); +} + +TEST(StringRefWide, WideCString) +{ + const wchar_t * val = L"hello world"; + + StringRefWide ref(val); + + ASSERT_EQ(val, ref.data()); + ASSERT_EQ(wcslen(val), ref.length()); +} + +TEST(StringRefWide, WideCStringArray) +{ + const wchar_t val[] = L"hello world"; + + StringRefWide ref(val); + + ASSERT_EQ(val, ref.data()); + ASSERT_EQ(wcslen(val), ref.length()); +} + +TEST(StringRefWide, StdWideString) +{ + const std::wstring val = L"hello world"; + + StringRefWide ref(val); + + ASSERT_EQ(val, ref.data()); + ASSERT_EQ(val.length(), ref.length()); +} + +TEST(StringRefWide, WideCopy) +{ + const std::wstring val = L"hello world"; + + StringRefWide ref(val); + StringRefWide cpy(ref); + + ASSERT_EQ(val, cpy.data()); + ASSERT_EQ(val.length(), cpy.length()); +} + +TEST(StringRefWide, WideReset) +{ + StringRefWide ref; + ASSERT_EQ(0, ref.data()); + ASSERT_EQ(0, ref.length()); + + ref.reset(L"hello world"); + + ASSERT_STREQ(L"hello world", ref); + ASSERT_STREQ(L"hello world", ref.data()); + ASSERT_EQ(wcslen(L"hello world"), ref.length()); + + const wchar_t arr[] = L"hello world 1"; + + ref.reset(arr); + ASSERT_EQ(arr, ref); + ASSERT_EQ(arr, ref.data()); + ASSERT_EQ(wcslen(arr), ref.length()); + ASSERT_STREQ(arr, ref); + ASSERT_STREQ(arr, ref.data()); + + const wchar_t * p = L"hello world 2"; + + ref.reset(p); + ASSERT_EQ(p, ref); + ASSERT_EQ(p, ref.data()); + ASSERT_EQ(wcslen(p), ref.length()); + ASSERT_STREQ(p, ref); + ASSERT_STREQ(p, ref.data()); + + const std::wstring s = L"hello world 3"; + + ref.reset(s); + ASSERT_EQ(s.data(), ref); + ASSERT_EQ(s.data(), ref.data()); + ASSERT_EQ(s.length(), ref.length()); + ASSERT_STREQ(s.c_str(), ref); + ASSERT_STREQ(s.c_str(), ref.data()); + + ref.reset(p, wcslen(p)); + ASSERT_EQ(p, ref); + ASSERT_EQ(p, ref.data()); + ASSERT_EQ(wcslen(p), ref.length()); + ASSERT_STREQ(p, ref); + ASSERT_STREQ(p, ref.data()); +} diff --git a/test/tracer.t.cc b/test/tracer.t.cc index 4fcc7df..b0f47b9 100644 --- a/test/tracer.t.cc +++ b/test/tracer.t.cc @@ -170,7 +170,7 @@ TEST(Tracer, ExtractText) for(Tracer::SpanContext::const_iterator it = g.sp->begin(); it != g.sp->end(); ++it) { - ASSERT_STREQ(names[index], it->name()); + ASSERT_STREQ(names[index], it->key()); ASSERT_STREQ(values[index], it->value()); ++index; } diff --git a/test/unittest.h b/test/unittest.h index 42e4a20..2e56f17 100644 --- a/test/unittest.h +++ b/test/unittest.h @@ -9,6 +9,7 @@ #endif #include +#include namespace opentracing{}; From 2f3715518c0b5743a5c4bbb041a6a770857ec1c9 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Fri, 6 Jan 2017 12:12:46 -0500 Subject: [PATCH 05/48] Solving the wide baggage problem --- opentracing/baggage.h | 247 +++++++++++++++++++++++++++++++++--------- test/baggage.t.cc | 82 +++++++++----- test/spancontext.h | 17 ++- test/tracer.t.cc | 4 +- test/unittest.h | 10 +- test/unittest.t.cc | 7 +- 6 files changed, 280 insertions(+), 87 deletions(-) diff --git a/opentracing/baggage.h b/opentracing/baggage.h index 751e49d..40fab39 100644 --- a/opentracing/baggage.h +++ b/opentracing/baggage.h @@ -4,7 +4,14 @@ // ========= // baggage.h // ========= -// class BaggageRef - Client wrapper for referencing key:value pairs +// class BaggageImp - Client wrapper for copies of key:value pairs +// class Baggage - Typedef for Baggage working with char +// class BaggageWide - Typedef for Baggage working with wchar_t +// +// class BaggageRefImp - Client wrapper for referencing key:value pairs +// class BaggageRef - Typedef for BaggageRef working with char +// class BaggageRefWide - Typedef for BaggageRef working with wchar_t +// // class BaggageIterator - Client interface to traverse span baggage // // ------------------- @@ -15,9 +22,9 @@ // Span. That is, baggage items propagate in-band along with the trace itself. // // Baggage items enable powerful functionality given a full-stack OpenTracing -// integration (for example, 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. +// integration (for example, arbitrary application data from a mobile +// application 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. // // Use this feature thoughtfully and with care. Every key and value is copied // into every local and remote child of the associated Span, and that can add up @@ -30,59 +37,107 @@ namespace opentracing { // ================ -// class BaggageRef +// class BaggageImp // ================ -// +// This class copies to the key:value pairs that make up 'baggage'. Once they +// value is returned, clients are free to move it around as they see fit. +// Baggage is the default value returned by iterators when they are +// dereferenced. + +template +class BaggageImp { + public: + BaggageImp(); + // Construct a Baggage with empty values. + + BaggageImp(const StringRefImp& key, const StringRefImp& value); + // Construct a Baggage referencing 'key' and 'value' + + std::basic_string& key(); + // Mutable reference to the underlying 'key'. + + std::basic_string& value(); + // Mutable reference to the underlying 'value'. + + const std::basic_string& key() const; + // Return the non-modifiable 'key' associated with this baggage. + + const std::basic_string& value() const; + // Return the non-modifiable 'value' associated with this baggage. + + BaggageImp* operator->(); + const BaggageImp* operator->() const; + // Syntactic sugar to support dereferencing BaggageIterator's with + // the '->' operator: this method only returns 'this'. + + private: + std::basic_string m_key; + std::basic_string m_value; +}; + +typedef BaggageImp Baggage; +typedef BaggageImp BaggageWide; + +// =================== +// class BaggageRefImp +// =================== // This class wraps references to the key:value pairs that make up 'baggage'. // The references themselves refer to data managed by SpanContext // implementations. // // Since the implementations of SpanContexts is deferred, it is impossible to -// make strong gurantees on the liftetime of the references. At a minimum, the +// make strong guarantees on the lifetime of the references. At a minimum, the // references should be valid until the iterator is destroyed, or until // 'setBaggage' is called again on a SpanContext. -class BaggageRef { +template +class BaggageRefImp { public: - BaggageRef(); - // Construct a 'BaggageRef' with empty references. + BaggageRefImp(); + // Construct a BaggageRef with empty references. - BaggageRef(const StringRef& key, const StringRef& value); - // Construct a 'BaggageRef' referencing 'key' and 'value' + BaggageRefImp(const StringRefImp& key, + const StringRefImp& value); + // Construct a BaggageRef referencing 'key' and 'value' - const StringRef& key() const; + const StringRefImp& key() const; // Return the non-modifiable 'key' associated with this baggage. - const StringRef& value() const; + const StringRefImp& value() const; // Return the non-modifiable 'value' associated with this baggage. - const BaggageRef* operator->() const; - // Syntatic sugar to support dereferencing BaggageIterator's with + const BaggageRefImp* operator->() const; + // Syntactic sugar to support dereferencing BaggageIterator's with // the '->' operator: this method only returns 'this'. private: - StringRef m_key; - StringRef m_value; + StringRefImp m_key; + StringRefImp m_value; }; +typedef BaggageRefImp BaggageRef; +typedef BaggageRefImp BaggageRefWide; + // ===================== // class BaggageIterator // ===================== // ------- // Clients // ------- -// For flexibility between implementations, 'BaggageIterator' classes should -// never be created directly. Instead, a typedef is provided by 'SpanContext's +// For flexibility between implementations, BaggageIterator classes should +// never be created directly. Instead, a typedef is provided by SpanContexts // which allow callers to be agnostic of the underlying implementation. // By using 'SpanContext::const_iterator', the call sites will be unaffected // if implementations change in the future. // // The iterators themselves satisfy the requirements of C++ "Input Iterators". -// They can read from the pointed-to baggage element, returning 'BaggageRef' for +// They can read from the pointed-to baggage element, returning Baggage for // the key:value pairs. // -// Those references only guarantee validity for a single pass: once an iterator -// has been incremented, all copies of its previous value may be invalidated. +// BaggageRef objects may be returned instead of copying the Baggage with +// calls to 'ref()'. Those references only guarantee validity for a single pass: +// once an iterator has been incremented, all copies of its previous value may +// be invalidated. // // See http://en.cppreference.com/w/cpp/concept/InputIterator for more details // on semantics input iterators. @@ -90,39 +145,44 @@ class BaggageRef { // ------------ // Implementors // ------------ -// 'BaggageIterator' is used to obscure the data structure(s) used to store -// and traverse span baggage. Implementors are free to store the key:value -// baggage pairs however they see fit, so long as they provide an -// "Input Iterator" to traverse the structure. +// BaggageIterator is used to obscure the data structure(s) used to store +// and traverse span baggage. Implementors should store the values as +// std::string types. The underlying data structure decision is left to +// implementors. // // We do not want to expose the details of these data structure(s) to clients; // If their code were to rely on any detail, it would make it difficult -// to change opentracing implementations. Instead, we define an 'Adapter' +// to change OpenTracing implementations. Instead, we define an 'Adapter' // class, to translate the implementation's iterator into baggage references. // // The 'Adapter' class must satisfy the following: -// 1) Provide an 'iterator' typedef, potentially used during construction -// 2) Provide a 'const_iterator' typedef, potentially used during +// * Provide an iterator typedef, potentially used during construction +// * Provide a const_iterator typedef, potentially used during // construction. -// 3) Overload operator() to convert a const_iterator into a BaggageRef +// * Provide narrow() to convert a const_iterator into Baggage +// * Provide wide() to convert a const_iterator into BaggageWide +// * Provide ref() to convert a const_iterator into a BaggageRef // // To achieve this, implementors define a class like so: // // struct AdapterClass { // typedef ImplementationIterator iterator; // typedef ImplementationIterator const_iterator; -// BaggageRef operator()(const const_iterator& it) const; +// +// Baggage narrow()(const const_iterator& it) const; +// Baggage wide()(const const_iterator& it) const; +// BaggageRef ref()(const const_iterator& it) const; // }; // -// Now, when clients create a 'BaggageIterator' through 'SpanContext::begin()', +// Now, when clients create a BaggageIterator through 'SpanContext::begin()', // the BaggageIterator should be created with an iterator to the underlying // baggage implementation. It caches the iterator, incrementing it as // clients move forward through the sequence. // -// When clients dreference the baggage iterator, the 'Adapter' is invoked, +// When clients dereference the baggage iterator, the 'Adapter' is invoked, // passing the implementation's iterator to the adapter. It is expected that the -// 'Adapter' can convert the iterator into a BaggageRef that client code can -// use in a read-only fashion. +// 'Adapter' can convert the iterator into a Baggage, BaggageWide, or BaggageRef +// object that client code can use in a read-only fashion. template class BaggageIterator { @@ -132,14 +192,23 @@ class BaggageIterator { BaggageIterator(const iterator& iter); BaggageIterator(const const_iterator& iter); - // Construct a 'BaggageIterator' object which will be used to traverse the + // Construct a BaggageIterator object which will be used to traverse the // sequence pointed to by the input iterator 'iter'. - BaggageRef operator*() const; - BaggageRef operator->() const; - // Returns a 'BaggageRef' to return the key:value pair pointed to by this + Baggage operator*() const; + Baggage operator->() const; + // Returns a Baggage to return the key:value pair pointed to by this // iterator. + BaggageWide wide() const; + // Returns a BaggageWide object, containing wide versions of the key:value + // pairs pointed to by this iterator. + + BaggageRef ref() const; + // Returns a BaggageRef object, containing references to the underlying + // storage of the key:value pairs. References are invalided if the + // associated SpanContext is destoryed or modified. + BaggageIterator operator++(int); // Return a copy of this iterator, then post-increment this iterator to // point to the next key:value pair in the sequence. @@ -162,31 +231,93 @@ class BaggageIterator { }; // ---------------- -// class BaggageRef +// class BaggageImp // ---------------- -inline BaggageRef::BaggageRef() : m_key(), m_value() +template +inline BaggageImp::BaggageImp() : m_key(), m_value() +{ +} + +template +inline BaggageImp::BaggageImp(const StringRefImp& key, + const StringRefImp& value) +: m_key(key.data(), key.length()), m_value(value.data(), value.length()) +{ +} + +template +inline std::basic_string& +BaggageImp::key() +{ + return m_key; +} + +template +inline std::basic_string& +BaggageImp::value() +{ + return m_value; +} + +template +inline const std::basic_string& +BaggageImp::key() const +{ + return m_key; +} + +template +inline const std::basic_string& +BaggageImp::value() const +{ + return m_value; +} + +template +BaggageImp* BaggageImp::operator->() +{ + return this; +} + +template +const BaggageImp* BaggageImp::operator->() const +{ + return this; +} + +// ------------------- +// class BaggageRefImp +// ------------------- + +template +inline BaggageRefImp::BaggageRefImp() : m_key(), m_value() { } -inline BaggageRef::BaggageRef(const StringRef& key, const StringRef& value) +template +inline BaggageRefImp::BaggageRefImp(const StringRefImp& key, + const StringRefImp& value) : m_key(key), m_value(value) { } -inline const StringRef& -BaggageRef::key() const +template +inline const StringRefImp& +BaggageRefImp::key() const { return m_key; } -inline const StringRef& -BaggageRef::value() const +template +inline const StringRefImp& +BaggageRefImp::value() const { return m_value; } -inline const BaggageRef* BaggageRef::operator->() const +template +inline const BaggageRefImp* BaggageRefImp::operator->() const { return this; } @@ -208,15 +339,27 @@ BaggageIterator::BaggageIterator(const const_iterator& iter) } template -BaggageRef BaggageIterator::operator*() const +Baggage BaggageIterator::operator*() const +{ + return d_handler.narrow(d_iterator); +} + +template +Baggage BaggageIterator::operator->() const +{ + return d_handler.narrow(d_iterator); +} + +template +BaggageWide BaggageIterator::wide() const { - return d_handler(d_iterator); + return d_handler.wide(d_iterator); } template -BaggageRef BaggageIterator::operator->() const +BaggageRef BaggageIterator::ref() const { - return d_handler(d_iterator); + return d_handler.ref(d_iterator); } template diff --git a/test/baggage.t.cc b/test/baggage.t.cc index 92cbd75..451ac0b 100644 --- a/test/baggage.t.cc +++ b/test/baggage.t.cc @@ -48,13 +48,27 @@ TEST(BaggageRef, Assignment) } // BaggageIterator adapter for map -struct MapBaggage { +class MapBaggage { + public: typedef std::map Map; - typedef Map::iterator iterator; + typedef Map::iterator iterator; typedef Map::const_iterator const_iterator; - BaggageRef - operator()(const Map::const_iterator& iter) const + Baggage narrow(const Map::const_iterator& iter) const + { + return Baggage(iter->first, iter->second); + } + BaggageWide wide(const Map::const_iterator& iter) const + { + std::wstring first; + std::wstring second; + + test_widen(&first, iter->first); + test_widen(&second, iter->second); + + return BaggageWide(first, second); + } + BaggageRef ref(const Map::const_iterator& iter) const { return BaggageRef(iter->first, iter->second); } @@ -71,10 +85,10 @@ TEST(BaggageIterator, MapBaggageAdapter) BaggageIterator end(m.end()); ASSERT_FALSE(end == it); - BaggageRef ref = *it; + Baggage ref = *it; - ASSERT_STREQ("animal", ref.key()); - ASSERT_STREQ("dog", ref.value()); + ASSERT_EQ("animal", ref.key()); + ASSERT_EQ("dog", ref.value()); BaggageIterator prev = it++; ASSERT_FALSE(prev == end); @@ -82,21 +96,21 @@ TEST(BaggageIterator, MapBaggageAdapter) ref = *prev; - ASSERT_STREQ("animal", ref.key()); - ASSERT_STREQ("dog", ref.value()); + ASSERT_EQ("animal", ref.key()); + ASSERT_EQ("dog", ref.value()); ref = *it; - ASSERT_STREQ("fruit", ref.key()); - ASSERT_STREQ("apple", ref.value()); + ASSERT_EQ("fruit", ref.key()); + ASSERT_EQ("apple", ref.value()); ++it; ASSERT_FALSE(end == it); ref = *it; - ASSERT_STREQ("veggie", ref.key()); - ASSERT_STREQ("carrot", ref.value()); + ASSERT_EQ("veggie", ref.key()); + ASSERT_EQ("carrot", ref.value()); ++it; @@ -128,13 +142,14 @@ TEST(BaggageIterator, ForLoopSyntax) ++it, ++index) { // Test the -> syntax works - ASSERT_STREQ(expectedKeys[index], it->key()); - ASSERT_STREQ(expectedVals[index], it->value()); + ASSERT_EQ(expectedKeys[index], it->key()); + ASSERT_EQ(expectedVals[index], it->value()); } } // Adapter for BaggageIterator, wrapping a stl list -struct ListBaggageAdapter { +class ListBaggageAdapter { + public: struct KVP { std::string key; std::string val; @@ -144,8 +159,21 @@ struct ListBaggageAdapter { typedef List::iterator iterator; typedef List::const_iterator const_iterator; - BaggageRef - operator()(const const_iterator& iter) const + Baggage narrow(const List::const_iterator& iter) const + { + return Baggage(iter->key, iter->val); + } + BaggageWide wide(const List::const_iterator& iter) const + { + std::wstring first; + std::wstring second; + + test_widen(&first, iter->key); + test_widen(&second, iter->val); + + return BaggageWide(first, second); + } + BaggageRef ref(const List::const_iterator& iter) const { return BaggageRef(iter->key, iter->val); } @@ -172,10 +200,10 @@ TEST(BaggageIterator, ListBaggageAdapter) BaggageIterator end(seq.end()); ASSERT_FALSE(end == it); - BaggageRef ref = *it; + Baggage ref = *it; - ASSERT_STREQ("animal", ref.key()); - ASSERT_STREQ("dog", it->value()); + ASSERT_EQ("animal", ref.key()); + ASSERT_EQ("dog", it->value()); BaggageIterator prev = it++; ASSERT_FALSE(prev == end); @@ -183,21 +211,21 @@ TEST(BaggageIterator, ListBaggageAdapter) ref = *prev; - ASSERT_STREQ("animal", ref.key()); - ASSERT_STREQ("dog", ref.value()); + ASSERT_EQ("animal", ref.key()); + ASSERT_EQ("dog", ref.value()); ref = *it; - ASSERT_STREQ("fruit", ref.key()); - ASSERT_STREQ("apple", ref.value()); + ASSERT_EQ("fruit", ref.key()); + ASSERT_EQ("apple", ref.value()); ++it; ASSERT_FALSE(end == it); ref = *it; - ASSERT_STREQ("veggie", ref.key()); - ASSERT_STREQ("carrot", ref.value()); + ASSERT_EQ("veggie", ref.key()); + ASSERT_EQ("carrot", ref.value()); ++it; diff --git a/test/spancontext.h b/test/spancontext.h index 9cc8fcc..909421f 100644 --- a/test/spancontext.h +++ b/test/spancontext.h @@ -15,8 +15,21 @@ struct TestContextBaggageAdapter { typedef TestBaggageContainer::iterator iterator; typedef TestBaggageContainer::const_iterator const_iterator; - BaggageRef - operator()(const const_iterator& it) const + Baggage narrow(const const_iterator& it) const + { + return Baggage(it->first, it->second); + } + BaggageWide wide(const const_iterator& it) const + { + std::wstring key; + std::wstring value; + + test_widen(&key, it->first); + test_widen(&value, it->second); + + return BaggageWide(key, value); + } + BaggageRef ref(const const_iterator& it) const { return BaggageRef(it->first, it->second); } diff --git a/test/tracer.t.cc b/test/tracer.t.cc index b0f47b9..f23fd89 100644 --- a/test/tracer.t.cc +++ b/test/tracer.t.cc @@ -170,8 +170,8 @@ TEST(Tracer, ExtractText) for(Tracer::SpanContext::const_iterator it = g.sp->begin(); it != g.sp->end(); ++it) { - ASSERT_STREQ(names[index], it->key()); - ASSERT_STREQ(values[index], it->value()); + ASSERT_STREQ(names[index], it.ref().key()); + ASSERT_STREQ(values[index], it.ref().value()); ++index; } } diff --git a/test/unittest.h b/test/unittest.h index 2e56f17..436f1c8 100644 --- a/test/unittest.h +++ b/test/unittest.h @@ -10,8 +10,16 @@ #include #include +#include -namespace opentracing{}; +namespace opentracing{ +inline void +test_widen(std::wstring* const dest, const std::string& src) +{ + dest->resize(src.size()); + std::mbstowcs(&(*dest)[0], src.c_str(), src.size()); +} +} using namespace opentracing; diff --git a/test/unittest.t.cc b/test/unittest.t.cc index 3c5739a..f0eec43 100644 --- a/test/unittest.t.cc +++ b/test/unittest.t.cc @@ -1,7 +1,8 @@ #include "unittest.h" -int main(int argc, char *argv[]) +int +main(int argc, char* argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } From b45a54042a92a96b50bc47821d32b166332979bf Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Fri, 6 Jan 2017 13:21:20 -0500 Subject: [PATCH 06/48] Adding noop, Baggage/BaggageWide, StringRefWide, and docs --- opentracing/baggage.h | 48 +++--- opentracing/noop.h | 330 ++++++++++++++++++++++++++++++++++++++ opentracing/span.h | 30 ++-- opentracing/spancontext.h | 1 + test/baggage.t.cc | 325 ++++++++++++++++++++++++++++--------- test/span.h | 100 +++++++++--- test/span.t.cc | 9 +- 7 files changed, 713 insertions(+), 130 deletions(-) create mode 100644 opentracing/noop.h diff --git a/opentracing/baggage.h b/opentracing/baggage.h index 40fab39..68f989f 100644 --- a/opentracing/baggage.h +++ b/opentracing/baggage.h @@ -39,7 +39,7 @@ namespace opentracing { // ================ // class BaggageImp // ================ -// This class copies to the key:value pairs that make up 'baggage'. Once they +// This class copies to the key:value pairs stored in SpanContexts. Once the // value is returned, clients are free to move it around as they see fit. // Baggage is the default value returned by iterators when they are // dereferenced. @@ -81,14 +81,15 @@ typedef BaggageImp BaggageWide; // =================== // class BaggageRefImp // =================== -// This class wraps references to the key:value pairs that make up 'baggage'. +// This class wraps references to the key:value pairs stored in SpanContexts. // The references themselves refer to data managed by SpanContext -// implementations. +// implementations, but make them available in a read-only fashion to avoid +// unnecessary copies. // // Since the implementations of SpanContexts is deferred, it is impossible to // make strong guarantees on the lifetime of the references. At a minimum, the -// references should be valid until the iterator is destroyed, or until -// 'setBaggage' is called again on a SpanContext. +// references should be valid until the iterator is destroyed, the SpanContext +// is destoryed, or until 'setBaggage' is called on the SpanContext. template class BaggageRefImp { @@ -107,7 +108,7 @@ class BaggageRefImp { // Return the non-modifiable 'value' associated with this baggage. const BaggageRefImp* operator->() const; - // Syntactic sugar to support dereferencing BaggageIterator's with + // Syntactic sugar to support dereferencing BaggageIterators with // the '->' operator: this method only returns 'this'. private: @@ -195,19 +196,24 @@ class BaggageIterator { // Construct a BaggageIterator object which will be used to traverse the // sequence pointed to by the input iterator 'iter'. - Baggage operator*() const; - Baggage operator->() const; - // Returns a Baggage to return the key:value pair pointed to by this - // iterator. + BaggageRef operator*() const; + BaggageRef operator->() const; + // Returns a BaggageRef to return references to the key:value pair pointed + // to by this iterator. Undefined behavior if the iterator is equal to + // 'end()'. + + Baggage narrow() const; + // Returns a copy of the key:value pairs pointed at by this iterator. + // Undefined behavior if the iterator is equal to 'end()'. BaggageWide wide() const; - // Returns a BaggageWide object, containing wide versions of the key:value - // pairs pointed to by this iterator. + // Returns a wide copies of the key:value pairs pointed at by this iterator. + // Undefined behavior if the iterator is equal to 'end()'. BaggageRef ref() const; // Returns a BaggageRef object, containing references to the underlying // storage of the key:value pairs. References are invalided if the - // associated SpanContext is destoryed or modified. + // associated SpanContext is destroyed or modified. BaggageIterator operator++(int); // Return a copy of this iterator, then post-increment this iterator to @@ -215,7 +221,7 @@ class BaggageIterator { BaggageIterator& operator++(); // Increment this iterator, pointing to the next key:value pair in the - // sequence. + // sequence, then return a reference to this iterator. bool operator==(const BaggageIterator& other) const; // Returns true if this iterator points to the same key:value pair as @@ -227,7 +233,7 @@ class BaggageIterator { private: const_iterator d_iterator; // Traverses implementation storage - ADAPTER d_handler; // Converts 'd_iterator' to BaggageRef + ADAPTER d_handler; // Converts d_iterator to Baggage wrappers }; // ---------------- @@ -339,13 +345,19 @@ BaggageIterator::BaggageIterator(const const_iterator& iter) } template -Baggage BaggageIterator::operator*() const +BaggageRef BaggageIterator::operator*() const { - return d_handler.narrow(d_iterator); + return d_handler.ref(d_iterator); +} + +template +BaggageRef BaggageIterator::operator->() const +{ + return d_handler.ref(d_iterator); } template -Baggage BaggageIterator::operator->() const +Baggage BaggageIterator::narrow() const { return d_handler.narrow(d_iterator); } diff --git a/opentracing/noop.h b/opentracing/noop.h new file mode 100644 index 0000000..6bfa19a --- /dev/null +++ b/opentracing/noop.h @@ -0,0 +1,330 @@ +#ifndef INCLUDED_OPENTRACING_NOOP_H +#define INCLUDED_OPENTRACING_NOOP_H + +#include +#include +#include +#include +#include +#include + +#if HAVE_STDINT_H +#include +#endif + +// These are No-Op implementations of the GenericAdapter, GenericSpanContext, +// GenericSpan, and GenericTracer interfaces. These can be used to begin +// instrumenting applications in advanced of a concrete implementation +// being installed. + +struct NoopContext; + +struct NoopAdapter { + typedef NoopContext* iterator; + typedef const NoopContext* const_iterator; + + BaggageRef + ref()(const const_iterator& it) const + { + return BaggageRef(); + } + Baggage + narrow(const const_iterator& it) const + { + return Baggage(); + } + BaggageWide + wide(const const_iterator& it) const + { + return BaggageWide(); + } +}; + +struct NoopContext : public GenericSpanContext { + int + setBaggageImp(const StringRef& key, const StringRef& baggage) + { + return 0; + } + int + getBaggageImp(StringRef* const baggage, const StringRef& key) + { + return 1; + } + const_iterator + beginImp() const + { + return const_iterator(this); + } + const_iterator + endImp() const + { + return const_iterator(this); + } +}; + +struct NoopSpan : public GenericSpan { + public: + NoopContext& + contextImp() + { + return m_context; + } + + const NoopContext& + contextImp() + { + return m_context; + } + + int + finishImp() + { + return 0; + } + + int + finishImp(const uint64_t) + { + return 0; + } + + int + tagImp(const StringRef&, const bool) + { + return 0; + } + int + tagImp(const StringRef&, const float) + { + return 0; + } + int + tagImp(const StringRef&, const double) + { + return 0; + } + int + tagImp(const StringRef&, const StringRef&) + { + return 0; + } + int + tagImp(const StringRef&, const int16_t) + { + return 0; + } + int + tagImp(const StringRef&, const int32_t) + { + return 0; + } + int + tagImp(const StringRef&, const int64_t) + { + return 0; + } + int + tagImp(const StringRef&, const uint16_t) + { + return 0; + } + int + tagImp(const StringRef&, const uint32_t) + { + return 0; + } + int + tagImp(const StringRef&, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const bool) + { + return 0; + } + int + logImp(const StringRef&, const float) + { + return 0; + } + int + logImp(const StringRef&, const double) + { + return 0; + } + int + logImp(const StringRef&, const StringRef&) + { + return 0; + } + int + logImp(const StringRef&, const int16_t) + { + return 0; + } + int + logImp(const StringRef&, const int32_t) + { + return 0; + } + int + logImp(const StringRef&, const int64_t) + { + return 0; + } + int + logImp(const StringRef&, const uint16_t) + { + return 0; + } + int + logImp(const StringRef&, const uint32_t) + { + return 0; + } + int + logImp(const StringRef&, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const bool, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const float, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const double, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const StringRef&, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const int16_t, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const int32_t, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const int64_t, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const uint16_t, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const uint32_t, const uint64_t) + { + return 0; + } + int + logImp(const StringRef&, const uint64_t, const uint64_t) + { + return 0; + } + + private: + NoopContext m_context; +}; + +struct NoopTracer + : public GenericTracer { + Span* + startImp(const StringRef&) + { + return NoopSpan(); + } + Span* + startImp(const StringRef&, const SpanContext&) + { + return NoopSpan(); + } + template + Span* + startImp(const StringRef&, const ITER&, const ITER&) + { + return NoopSpan(); + } + Span* + startImp(const StringRef&, const uint64_t) + { + return NoopSpan(); + } + Span* + startImp(const StringRef&, const SpanContext&, const uint64_t) + { + return NoopSpan(); + } + template + Span* + startImp(const StringRef&, const ITER&, const ITER&, const uint64_t) + { + return NoopSpan(); + } + void cleanupImp(Span* const sp) + { + delete static_cast(sp); + } + template + int + injectImp(GenericTextWriter* const carrier, + const SpanContext& context) const + { + return 0; + } + template + int + injectImp(GenericBinaryWriter* const carrier, + const SpanContext& context) const + { + return 0; + } + template + int + injectImp(GenericTextWriter* const carrier, + const SpanContext& context) const + { + return 0; + } + template + SpanContext* + extractImp(const GenericTextReader& carrier) + { + return NULL; + } + template + SpanContext* + extractImp(const GenericBinaryReader& carrier) + { + return NULL; + } + template + SpanContext* + extractImp(const GenericBinaryReader& carrier) + { + return NULL; + } + void cleanupImp(SpanContext* const sp) + { + delete static_cast(sp); + } +}; + +#endif diff --git a/opentracing/span.h b/opentracing/span.h index ed0e62b..3e54f4f 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -4,13 +4,23 @@ // ====== // span.h // ====== +// // class GenericSpan - CRTP interface for Spans // // ---- // Span // ---- -// Every Trace is made up of one or more Spans. Spans are used to: -// * TODO +// Every Trace is made up of one or more Spans. Spans are used encapuslate: +// * An operation name +// * A start timestamp +// * A finish timestamp +// * A set of zero or more key:value SpanTags +// * A set of zero or more timestamped key:value SpanLogs +// * A SpanContext (see spancontext.h) +// * References to zero or more causally-related Spans +// +// The installed Tracer acts as a factory for Spans, keeping clients agnostic +// of the implementation. // // See the specification for more details: // https://github.com/opentracing/specification/blob/master/specification.md#span @@ -85,16 +95,14 @@ namespace opentracing { // int finishImp(); // int finishImp(const uint64_t); // -// int tagImp(const StringRef& key, const Fundamental val); -// int tagImp(const StringRef& key, const StringRef& val); +// int tagImp(const StringRef&, const Fundamental); +// int tagImp(const StringRef&, const StringRef&); // -// int logImp(const StringRef& key, const Fundamental val); -// int logImp(const StringRef& key, const StringRef& val); +// int logImp(const StringRef&, const Fundamental); +// int logImp(const StringRef&, const StringRef&); // -// int logImp(const StringRef& key, const Fundamental val, const uint64_t -// tsp); -// int logImp(const StringRef& key, const StringRef& val, const uint64_t -// tsp); +// int logImp(const StringRef&, const Fundamental, const uint64_t); +// int logImp(const StringRef&, const StringRef&, const uint64_t); // }; // // For brevities sake, the above example collapses the overloads on fundamental @@ -102,10 +110,10 @@ namespace opentracing { // 'Fundamental' type. For actual implementations, overloads must be supplied // for each of the following fundamental types. // -// http://en.cppreference.com/w/cpp/language/types: // * float * int16_t * uint16_t * char * wchar_t // * double * int32_t * uint32_t * signed char * bool // * long double * int64_t * uint64_t * unsigned char +// (http://en.cppreference.com/w/cpp/language/types) // // The overloads are used instead of a single template to: // * Avoid passing references larger than the types they refer to (64-bit) diff --git a/opentracing/spancontext.h b/opentracing/spancontext.h index 2b5b377..a3d574a 100644 --- a/opentracing/spancontext.h +++ b/opentracing/spancontext.h @@ -4,6 +4,7 @@ // ============= // spancontext.h // ============= +// // class GenericSpanContext - CRTP interface for SpanContexts // // ----------- diff --git a/test/baggage.t.cc b/test/baggage.t.cc index 451ac0b..1d6a98b 100644 --- a/test/baggage.t.cc +++ b/test/baggage.t.cc @@ -7,6 +7,128 @@ #include #include +TEST(Baggage, Constructor) +{ + Baggage b; + ASSERT_EQ("", b.key()); + ASSERT_EQ("", b.value()); +} + +TEST(Baggage, CopyConstructor) +{ + Baggage b("apple", "banana"); + Baggage cp(b); + + ASSERT_EQ("apple", cp.key()); + ASSERT_EQ("banana", cp.value()); +} + +TEST(Baggage, Assignment) +{ + Baggage b("apple", "banana"); + Baggage cp; + cp = b; + + ASSERT_EQ("apple", cp.key()); + ASSERT_EQ("banana", cp.value()); +} + +TEST(Baggage, Manipulate) +{ + Baggage b("apple", "banana"); + b.key() = "cranberry"; + b.value() = "dates"; + + ASSERT_EQ("cranberry", b.key()); + ASSERT_EQ("dates", b.value()); +} + +TEST(Baggage, ManipulateThroughDeref) +{ + Baggage b("apple", "banana"); + b->key() = "cranberry"; + b->value() = "dates"; + + ASSERT_EQ("cranberry", b.key()); + ASSERT_EQ("dates", b.value()); +} + +TEST(Baggage, ConstBehavior) +{ + const Baggage b("apple", "banana"); + ASSERT_EQ("apple", b.key()); + ASSERT_EQ("banana", b.value()); +} + +TEST(Baggage, ConstBehaviorThroughDeref) +{ + const Baggage b("apple", "banana"); + ASSERT_EQ("apple", b->key()); + ASSERT_EQ("banana", b->value()); +} + +TEST(BaggageWide, Constructor) +{ + BaggageWide b; + ASSERT_EQ(L"", b.key()); + ASSERT_EQ(L"", b.value()); +} + +TEST(BaggageWide, CopyConstructor) +{ + BaggageWide b(L"apple", L"banana"); + BaggageWide cp(b); + + ASSERT_EQ(L"apple", cp.key()); + ASSERT_EQ(L"banana", cp.value()); +} + +TEST(BaggageWide, Assignment) +{ + BaggageWide b(L"apple", L"banana"); + BaggageWide cp; + cp = b; + + ASSERT_EQ(L"apple", cp.key()); + ASSERT_EQ(L"banana", cp.value()); +} + +TEST(BaggageWide, Manipulate) +{ + BaggageWide b(L"apple", L"banana"); + b.key() = L"cranberry"; + b.value() = L"dates"; + + ASSERT_EQ(L"cranberry", b.key()); + ASSERT_EQ(L"dates", b.value()); +} + +TEST(BaggageWide, ManipulateThroughDeref) +{ + BaggageWide b(L"apple", L"banana"); + b->key() = L"cranberry"; + b->value() = L"dates"; + + ASSERT_EQ(L"cranberry", b.key()); + ASSERT_EQ(L"dates", b.value()); +} + +TEST(BaggageWide, ConstBehavior) +{ + const BaggageWide b(L"apple", L"banana"); + + ASSERT_EQ(L"apple", b.key()); + ASSERT_EQ(L"banana", b.value()); +} + +TEST(BaggageWide, ConstBehaviorThroughDeref) +{ + const BaggageWide b(L"apple", L"banana"); + + ASSERT_EQ(L"apple", b->key()); + ASSERT_EQ(L"banana", b->value()); +} + TEST(BaggageRef, Constructor) { const char n[] = "hello"; @@ -74,7 +196,7 @@ class MapBaggage { } }; -TEST(BaggageIterator, MapBaggageAdapter) +TEST(BaggageIterator, NarrowAdapter) { MapBaggage::Map m; m["animal"] = "dog"; @@ -85,149 +207,196 @@ TEST(BaggageIterator, MapBaggageAdapter) BaggageIterator end(m.end()); ASSERT_FALSE(end == it); - Baggage ref = *it; + Baggage narrow = it.narrow();; - ASSERT_EQ("animal", ref.key()); - ASSERT_EQ("dog", ref.value()); + ASSERT_EQ("animal", narrow.key()); + ASSERT_EQ("dog", narrow.value()); BaggageIterator prev = it++; ASSERT_FALSE(prev == end); ASSERT_FALSE(it == end); - ref = *prev; + narrow = prev.narrow(); - ASSERT_EQ("animal", ref.key()); - ASSERT_EQ("dog", ref.value()); + ASSERT_EQ("animal", narrow.key()); + ASSERT_EQ("dog", narrow.value()); - ref = *it; + narrow = it.narrow(); - ASSERT_EQ("fruit", ref.key()); - ASSERT_EQ("apple", ref.value()); + ASSERT_EQ("fruit", narrow.key()); + ASSERT_EQ("apple", narrow.value()); ++it; ASSERT_FALSE(end == it); - ref = *it; + narrow = it.narrow(); - ASSERT_EQ("veggie", ref.key()); - ASSERT_EQ("carrot", ref.value()); + ASSERT_EQ("veggie", narrow.key()); + ASSERT_EQ("carrot", narrow.value()); ++it; ASSERT_TRUE(end == it); } -TEST(BaggageIterator, EmptyMapBaggage) +TEST(BaggageIterator, WideAdapter) { MapBaggage::Map m; + m["animal"] = "dog"; + m["fruit"] = "apple"; + m["veggie"] = "carrot"; BaggageIterator it(m.begin()); BaggageIterator end(m.end()); + ASSERT_FALSE(end == it); + BaggageWide wide = it.wide(); + + ASSERT_EQ(L"animal", wide.key()); + ASSERT_EQ(L"dog", wide.value()); + + BaggageIterator prev = it++; + ASSERT_FALSE(prev == end); + ASSERT_FALSE(it == end); + + wide = prev.wide(); + + ASSERT_EQ(L"animal", wide.key()); + ASSERT_EQ(L"dog", wide.value()); + + wide = it.wide(); + + ASSERT_EQ(L"fruit", wide.key()); + ASSERT_EQ(L"apple", wide.value()); + + ++it; + ASSERT_FALSE(end == it); + + wide = it.wide(); + + ASSERT_EQ(L"veggie", wide.key()); + ASSERT_EQ(L"carrot", wide.value()); + + ++it; + ASSERT_TRUE(end == it); } -TEST(BaggageIterator, ForLoopSyntax) +TEST(BaggageIterator, RefAdapter) { MapBaggage::Map m; m["animal"] = "dog"; m["fruit"] = "apple"; m["veggie"] = "carrot"; - const char * expectedKeys[] = {"animal", "fruit", "veggie"}; - const char * expectedVals[] = {"dog", "apple", "carrot"}; - size_t index = 0; + BaggageIterator it(m.begin()); + BaggageIterator end(m.end()); - for (BaggageIterator it = m.begin(), end = m.end(); it != end; - ++it, ++index) - { - // Test the -> syntax works - ASSERT_EQ(expectedKeys[index], it->key()); - ASSERT_EQ(expectedVals[index], it->value()); - } -} + ASSERT_FALSE(end == it); + BaggageRef ref = it.ref(); -// Adapter for BaggageIterator, wrapping a stl list -class ListBaggageAdapter { - public: - struct KVP { - std::string key; - std::string val; - }; + ASSERT_STREQ("animal", ref.key()); + ASSERT_STREQ("dog", ref.value()); - typedef std::list List; - typedef List::iterator iterator; - typedef List::const_iterator const_iterator; + BaggageIterator prev = it++; - Baggage narrow(const List::const_iterator& iter) const - { - return Baggage(iter->key, iter->val); - } - BaggageWide wide(const List::const_iterator& iter) const - { - std::wstring first; - std::wstring second; + ASSERT_FALSE(prev == end); + ASSERT_FALSE(it == end); - test_widen(&first, iter->key); - test_widen(&second, iter->val); + ref = prev.ref(); - return BaggageWide(first, second); - } - BaggageRef ref(const List::const_iterator& iter) const - { - return BaggageRef(iter->key, iter->val); - } -}; + ASSERT_STREQ("animal", ref.key()); + ASSERT_STREQ("dog", ref.value()); -TEST(BaggageIterator, ListBaggageAdapter) -{ - ListBaggageAdapter::List seq; + ref = it.ref(); - ListBaggageAdapter::KVP tmp; - tmp.key = "animal"; - tmp.val = "dog"; - seq.push_back(tmp); + ASSERT_STREQ("fruit", ref.key()); + ASSERT_STREQ("apple", ref.value()); - tmp.key = "fruit"; - tmp.val = "apple"; - seq.push_back(tmp); + ++it; + ASSERT_FALSE(end == it); + + ref = it.ref(); + + ASSERT_STREQ("veggie", ref.key()); + ASSERT_STREQ("carrot", ref.value()); + + ++it; + + ASSERT_TRUE(end == it); +} - tmp.key = "veggie"; - tmp.val = "carrot"; - seq.push_back(tmp); +TEST(BaggageIterator, Implicit) +{ + MapBaggage::Map m; + m["animal"] = "dog"; + m["fruit"] = "apple"; + m["veggie"] = "carrot"; - BaggageIterator it(seq.begin()); - BaggageIterator end(seq.end()); + BaggageIterator it(m.begin()); + BaggageIterator end(m.end()); ASSERT_FALSE(end == it); - Baggage ref = *it; + BaggageRef ref = *it; - ASSERT_EQ("animal", ref.key()); - ASSERT_EQ("dog", it->value()); + ASSERT_STREQ("animal", ref.key()); + ASSERT_STREQ("dog", ref.value()); + + BaggageIterator prev = it++; - BaggageIterator prev = it++; ASSERT_FALSE(prev == end); ASSERT_FALSE(it == end); ref = *prev; - ASSERT_EQ("animal", ref.key()); - ASSERT_EQ("dog", ref.value()); + ASSERT_STREQ("animal", ref.key()); + ASSERT_STREQ("dog", ref.value()); ref = *it; - ASSERT_EQ("fruit", ref.key()); - ASSERT_EQ("apple", ref.value()); + ASSERT_STREQ("fruit", ref.key()); + ASSERT_STREQ("apple", ref.value()); ++it; ASSERT_FALSE(end == it); ref = *it; - ASSERT_EQ("veggie", ref.key()); - ASSERT_EQ("carrot", ref.value()); + ASSERT_STREQ("veggie", ref.key()); + ASSERT_STREQ("carrot", ref.value()); ++it; ASSERT_TRUE(end == it); } + + +TEST(BaggageIterator, EmptyMapBaggage) +{ + MapBaggage::Map m; + + BaggageIterator it(m.begin()); + BaggageIterator end(m.end()); + + ASSERT_TRUE(end == it); +} + +TEST(BaggageIterator, ForLoopSyntax) +{ + MapBaggage::Map m; + m["animal"] = "dog"; + m["fruit"] = "apple"; + m["veggie"] = "carrot"; + + const char * expectedKeys[] = {"animal", "fruit", "veggie"}; + const char * expectedVals[] = {"dog", "apple", "carrot"}; + size_t index = 0; + + for (BaggageIterator it = m.begin(), end = m.end(); it != end; + ++it, ++index) + { + // Test the -> syntax works + ASSERT_STREQ(expectedKeys[index], it->key()); + ASSERT_STREQ(expectedVals[index], it->value()); + } +} diff --git a/test/span.h b/test/span.h index 9868580..3617b2e 100644 --- a/test/span.h +++ b/test/span.h @@ -31,6 +31,12 @@ class TestSpanImpl : public GenericSpan class SpanTypeTests : public ::testing::Test { }; -typedef ::testing::Types Date: Fri, 6 Jan 2017 14:42:29 -0500 Subject: [PATCH 07/48] Adding No-op implementation --- opentracing/noop.h | 875 ++++++++++++++++++++++++++++++--------------- opentracing/span.h | 1 - test/Makefile | 2 +- test/noop.t.cc | 284 +++++++++++++++ test/tracer.h | 28 +- test/tracer.t.cc | 37 +- test/unittest.h | 29 ++ 7 files changed, 929 insertions(+), 327 deletions(-) create mode 100644 test/noop.t.cc diff --git a/opentracing/noop.h b/opentracing/noop.h index 6bfa19a..b2ef2b4 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -1,6 +1,29 @@ #ifndef INCLUDED_OPENTRACING_NOOP_H #define INCLUDED_OPENTRACING_NOOP_H +// ====== +// noop.h +// ====== +// class NoopAdapter - No-op adapter for NoopContext baggage +// class NoopContext - No-op span context implementation +// class NoopSpan - No-op span implementation +// class NoopTracer - No-op tracer implementation +// +// ----- +// No-Op +// ----- +// This header provides a No-Op implementation for the generic OpenTracing +// classes. It can be installed globally in your application to begin +// instrumenting or testing the interface, but it has no side-effects, with +// one exception. +// +// In order to have client code behave the same when a concrete implementation +// is used, clients should be calling finish() and cleanup() appropriately. +// See span.h and tracer.h for details. +// +// See the specification for requirements of NoopTracers: +// https://github.com/opentracing/specification/blob/master/specification.md#nooptracer + #include #include #include @@ -12,319 +35,579 @@ #include #endif -// These are No-Op implementations of the GenericAdapter, GenericSpanContext, -// GenericSpan, and GenericTracer interfaces. These can be used to begin -// instrumenting applications in advanced of a concrete implementation -// being installed. +namespace opentracing{ + +class NoopAdapter; +class NoopContext; +class NoopSpan; +class NoopTracer; -struct NoopContext; +// ================= +// Class NoopAdapter +// ================= +// The NoopAdapter has no container to iterator over. Regardless of +// what iterator is passed in, it will always return empty baggage +// objects or references. -struct NoopAdapter { +class NoopAdapter { + public: typedef NoopContext* iterator; typedef const NoopContext* const_iterator; - BaggageRef - ref()(const const_iterator& it) const - { - return BaggageRef(); - } - Baggage - narrow(const const_iterator& it) const - { - return Baggage(); - } - BaggageWide - wide(const const_iterator& it) const - { - return BaggageWide(); - } + BaggageRef ref(const const_iterator& it) const; + Baggage narrow(const const_iterator& it) const; + BaggageWide wide(const const_iterator& it) const; }; -struct NoopContext : public GenericSpanContext { - int - setBaggageImp(const StringRef& key, const StringRef& baggage) - { - return 0; - } - int - getBaggageImp(StringRef* const baggage, const StringRef& key) - { - return 1; - } - const_iterator - beginImp() const - { - return const_iterator(this); - } - const_iterator - endImp() const - { - return const_iterator(this); - } +// ================= +// Class NoopContext +// ================= +// The NoopContext implements the GenericSpanContext interface. It +// provides no-op overloads for 'setBaggageImp' and 'getBaggageImp'. +// +// The baggage container iterator interface is faked by always +// using the address of the NoopContext itself for both the begin() +// and end() implementations. Since those pointers should always be +// equal, the iterator range will always be considered empty. +// +// If clients are using iterators correctly, the iterator should never +// be dereferenced, however, if they do dereference the BaggageIterator, +// they will be returned empty string references/copies. + +class NoopContext : public GenericSpanContext { + public: + int setBaggageImp(const StringRef& key, const StringRef& baggage); + int getBaggageImp(StringRef* const baggage, const StringRef& key) const; + const_iterator beginImp() const; + const_iterator endImp() const; }; -struct NoopSpan : public GenericSpan { +// ============== +// Class NoopSpan +// ============== +// The NoopSpan implements the GenericSpan interface. It provides no-op +// overloads for all of the required Span behaviors. +// +// It owns a NoopContext to support the context() interface. Every method +// on the returned context() is also a no-op. + +class NoopSpan : public GenericSpan { public: - NoopContext& - contextImp() - { - return m_context; - } - - const NoopContext& - contextImp() - { - return m_context; - } - - int - finishImp() - { - return 0; - } - - int - finishImp(const uint64_t) - { - return 0; - } - - int - tagImp(const StringRef&, const bool) - { - return 0; - } - int - tagImp(const StringRef&, const float) - { - return 0; - } - int - tagImp(const StringRef&, const double) - { - return 0; - } - int - tagImp(const StringRef&, const StringRef&) - { - return 0; - } - int - tagImp(const StringRef&, const int16_t) - { - return 0; - } - int - tagImp(const StringRef&, const int32_t) - { - return 0; - } - int - tagImp(const StringRef&, const int64_t) - { - return 0; - } - int - tagImp(const StringRef&, const uint16_t) - { - return 0; - } - int - tagImp(const StringRef&, const uint32_t) - { - return 0; - } - int - tagImp(const StringRef&, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const bool) - { - return 0; - } - int - logImp(const StringRef&, const float) - { - return 0; - } - int - logImp(const StringRef&, const double) - { - return 0; - } - int - logImp(const StringRef&, const StringRef&) - { - return 0; - } - int - logImp(const StringRef&, const int16_t) - { - return 0; - } - int - logImp(const StringRef&, const int32_t) - { - return 0; - } - int - logImp(const StringRef&, const int64_t) - { - return 0; - } - int - logImp(const StringRef&, const uint16_t) - { - return 0; - } - int - logImp(const StringRef&, const uint32_t) - { - return 0; - } - int - logImp(const StringRef&, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const bool, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const float, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const double, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const StringRef&, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const int16_t, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const int32_t, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const int64_t, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const uint16_t, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const uint32_t, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const uint64_t, const uint64_t) - { - return 0; - } + NoopContext& contextImp(); + const NoopContext& contextImp() const; + + int finishImp(); + int finishImp(const uint64_t); + + int tagImp(const StringRef&, const StringRef&); + int tagImp(const StringRef&, const bool); + int tagImp(const StringRef&, const float); + int tagImp(const StringRef&, const double); + int tagImp(const StringRef&, const long double); + int tagImp(const StringRef&, const char); + int tagImp(const StringRef&, const signed char); + int tagImp(const StringRef&, const unsigned char); + int tagImp(const StringRef&, const wchar_t); + int tagImp(const StringRef&, const int16_t); + int tagImp(const StringRef&, const int32_t); + int tagImp(const StringRef&, const int64_t); + int tagImp(const StringRef&, const uint16_t); + int tagImp(const StringRef&, const uint32_t); + int tagImp(const StringRef&, const uint64_t); + + int logImp(const StringRef&, const StringRef&); + int logImp(const StringRef&, const bool); + int logImp(const StringRef&, const float); + int logImp(const StringRef&, const double); + int logImp(const StringRef&, const long double); + int logImp(const StringRef&, const char); + int logImp(const StringRef&, const signed char); + int logImp(const StringRef&, const unsigned char); + int logImp(const StringRef&, const wchar_t); + int logImp(const StringRef&, const int16_t); + int logImp(const StringRef&, const int32_t); + int logImp(const StringRef&, const int64_t); + int logImp(const StringRef&, const uint16_t); + int logImp(const StringRef&, const uint32_t); + int logImp(const StringRef&, const uint64_t); + + int logImp(const StringRef&, const StringRef&, const uint64_t); + int logImp(const StringRef&, const bool, const uint64_t); + int logImp(const StringRef&, const float, const uint64_t); + int logImp(const StringRef&, const double, const uint64_t); + int logImp(const StringRef&, const long double, const uint64_t); + int logImp(const StringRef&, const char, const uint64_t); + int logImp(const StringRef&, const signed char, const uint64_t); + int logImp(const StringRef&, const unsigned char, const uint64_t); + int logImp(const StringRef&, const wchar_t, const uint64_t); + int logImp(const StringRef&, const int16_t, const uint64_t); + int logImp(const StringRef&, const int32_t, const uint64_t); + int logImp(const StringRef&, const int64_t, const uint64_t); + int logImp(const StringRef&, const uint16_t, const uint64_t); + int logImp(const StringRef&, const uint32_t, const uint64_t); + int logImp(const StringRef&, const uint64_t, const uint64_t); private: NoopContext m_context; }; -struct NoopTracer +// ================ +// Class NoopTracer +// ================ +// The NoopTracer implements the GenericTracer interface. It provides no-op +// overloads for all of the required Tracer behaviors. +// +// Clients can start spans and are still required to call 'cleanup' on +// returned Span and SpanContext pointers. + +class NoopTracer : public GenericTracer { - Span* - startImp(const StringRef&) - { - return NoopSpan(); - } - Span* - startImp(const StringRef&, const SpanContext&) - { - return NoopSpan(); - } + // Note that Span' and SpanContext typedefs are provided by the base class + public: + Span* startImp(const StringRef&); + Span* startImp(const StringRef&, const SpanContext&); + template - Span* - startImp(const StringRef&, const ITER&, const ITER&) - { - return NoopSpan(); - } - Span* - startImp(const StringRef&, const uint64_t) - { - return NoopSpan(); - } - Span* - startImp(const StringRef&, const SpanContext&, const uint64_t) - { - return NoopSpan(); - } + Span* startImp(const StringRef&, const ITER&, const ITER&); + + Span* startImp(const StringRef&, const uint64_t); + Span* startImp(const StringRef&, const SpanContext&, const uint64_t); + template - Span* - startImp(const StringRef&, const ITER&, const ITER&, const uint64_t) - { - return NoopSpan(); - } - void cleanupImp(Span* const sp) - { - delete static_cast(sp); - } - template - int - injectImp(GenericTextWriter* const carrier, - const SpanContext& context) const - { - return 0; - } - template - int - injectImp(GenericBinaryWriter* const carrier, - const SpanContext& context) const - { - return 0; - } - template - int - injectImp(GenericTextWriter* const carrier, - const SpanContext& context) const - { - return 0; - } - template - SpanContext* - extractImp(const GenericTextReader& carrier) - { - return NULL; - } - template - SpanContext* - extractImp(const GenericBinaryReader& carrier) - { - return NULL; - } - template - SpanContext* - extractImp(const GenericBinaryReader& carrier) - { - return NULL; - } - void cleanupImp(SpanContext* const sp) - { - delete static_cast(sp); - } + Span* startImp(const StringRef&, const ITER&, const ITER&, const uint64_t); + + void cleanupImp(Span* const sp); + + template + int injectImp(GenericTextWriter* const carrier, + const SpanContext& context) const; + + template + int injectImp(GenericBinaryWriter* const carrier, + const SpanContext& context) const; + + template + int injectImp(GenericWriter* const carrier, + const SpanContext& context) const; + + template + SpanContext* extractImp(const GenericTextReader& carrier); + + template + SpanContext* extractImp(const GenericBinaryReader& carrier); + + template + SpanContext* extractImp(const GenericReader& carrier); + + void cleanupImp(SpanContext* const sp); + + private: + NoopSpan m_span; }; -#endif +// ----------------- +// class NoopAdapter +// ----------------- + +inline BaggageRef +NoopAdapter::ref(const const_iterator&) const +{ + return BaggageRef(); +} +inline Baggage +NoopAdapter::narrow(const const_iterator&) const +{ + return Baggage(); +} +inline BaggageWide +NoopAdapter::wide(const const_iterator&) const +{ + return BaggageWide(); +} + +// ----------------- +// class NoopContext +// ----------------- + +inline int +NoopContext::setBaggageImp(const StringRef&, const StringRef&) +{ + return 0; +} + +inline int +NoopContext::getBaggageImp(StringRef* const, const StringRef&) const +{ + return 1; +} + +inline NoopContext::const_iterator +NoopContext::beginImp() const +{ + return const_iterator(this); +} + +inline NoopContext::const_iterator +NoopContext::endImp() const +{ + return const_iterator(this); +} + +// ------------- +// class NooSpan +// ------------- + +inline NoopContext& +NoopSpan::contextImp() +{ + return m_context; +} + +inline const NoopContext& +NoopSpan::contextImp() const +{ + return m_context; +} + +// -------------- +// class NoopSpan +// -------------- + +inline int +NoopSpan::finishImp() +{ + return 0; +} +inline int +NoopSpan::finishImp(const uint64_t) +{ + return 0; +} + +inline int +NoopSpan::tagImp(const StringRef&, const StringRef&) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const bool) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const float) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const double) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const long double) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const char) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const signed char) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const unsigned char) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const wchar_t) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const int16_t) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const int32_t) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const int64_t) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const uint16_t) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const uint32_t) +{ + return 0; +} +inline int +NoopSpan::tagImp(const StringRef&, const uint64_t) +{ + return 0; +} + +inline int +NoopSpan::logImp(const StringRef&, const StringRef&) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const bool) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const float) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const double) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const long double) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const char) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const signed char) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const unsigned char) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const wchar_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const int16_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const int32_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const int64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const uint16_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const uint32_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const uint64_t) +{ + return 0; +} + +inline int +NoopSpan::logImp(const StringRef&, const StringRef&, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const bool, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const float, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const double, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const long double, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const char, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const signed char, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const unsigned char, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const wchar_t, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const int16_t, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const int32_t, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const int64_t, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const uint16_t, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const uint32_t, const uint64_t) +{ + return 0; +} +inline int +NoopSpan::logImp(const StringRef&, const uint64_t, const uint64_t) +{ + return 0; +} + +// ---------------- +// class NoopTracer +// ---------------- + +inline NoopTracer::Span* +NoopTracer::startImp(const StringRef&) +{ + return &m_span; +} + +inline NoopTracer::Span* +NoopTracer::startImp(const StringRef&, const SpanContext&) +{ + return &m_span; +} + +template +inline NoopTracer::Span* +NoopTracer::startImp(const StringRef&, const ITER&, const ITER&) +{ + return &m_span; +} + +inline NoopTracer::Span* +NoopTracer::startImp(const StringRef&, const uint64_t) +{ + return &m_span; +} + +inline NoopTracer::Span* +NoopTracer::startImp(const StringRef&, const SpanContext&, const uint64_t) +{ + return &m_span; +} + +template +inline NoopTracer::Span* +NoopTracer::startImp(const StringRef&, const ITER&, const ITER&, const uint64_t) +{ + return &m_span; +} + +inline void +NoopTracer::cleanupImp(Span* const) +{ +} + +template +inline int +NoopTracer::injectImp(GenericTextWriter* const, + const SpanContext&) const +{ + return 0; +} + +template +inline int +NoopTracer::injectImp(GenericBinaryWriter* const, + const SpanContext&) const +{ + return 0; +} + +template +inline int +NoopTracer::injectImp(GenericWriter* const, + const SpanContext&) const +{ + return 0; +} + +template +inline NoopTracer::SpanContext* +NoopTracer::extractImp(const GenericTextReader&) +{ + return &m_span.context(); +} + +template +inline NoopTracer::SpanContext* +NoopTracer::extractImp(const GenericBinaryReader&) +{ + return &m_span.context(); +} + +template +inline NoopTracer::SpanContext* +NoopTracer::extractImp(const GenericReader&) +{ + return &m_span.context(); +} + +inline void +NoopTracer::cleanupImp(SpanContext* const) +{ +} + +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_NOOP_H diff --git a/opentracing/span.h b/opentracing/span.h index 3e54f4f..f57d3bb 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -4,7 +4,6 @@ // ====== // span.h // ====== -// // class GenericSpan - CRTP interface for Spans // // ---- diff --git a/test/Makefile b/test/Makefile index 91c94e1..261fa3c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -23,7 +23,7 @@ LDIR =${GTEST_LIBS} LIBS=-L${GTEST_LIBS} -lgtest -lpthread -_OBJ = tracer.t.o carriers.t.o span.t.o spancontext.t.o baggage.t.o stringref.t.o unittest.t.o +_OBJ = noop.t.o tracer.t.o carriers.t.o span.t.o spancontext.t.o baggage.t.o stringref.t.o unittest.t.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) $(ODIR)/%.o: %.cc %.h ${OPENTRACING_SRC} diff --git a/test/noop.t.cc b/test/noop.t.cc new file mode 100644 index 0000000..6d85afb --- /dev/null +++ b/test/noop.t.cc @@ -0,0 +1,284 @@ +#include "unittest.h" + +#include "carriers.h" + +#include +#include // test include guard + +// These run the same tests as the tracer.t.cc. The interface should be the +// same, however, there may be some differences in return codes due +// to the differing implementations. + +typedef GenericSpanContext GlobalContext; +typedef GenericSpan GlobalSpan; +typedef GenericTracer GlobalTracer; + +typedef GenericSpanGuard SpanGuard; +typedef GenericSpanContextGuard SpanContextGuard; + +TEST(NoopTracer, Intantiation){ + NoopTracer noop; + + GlobalTracer::install(&noop); + ASSERT_EQ(GlobalTracer::instance(), &noop); + + GlobalTracer::uninstall(); + ASSERT_FALSE(GlobalTracer::instance()); +} + +TEST(NoopTracer, StartWithOp) +{ + NoopTracer imp; + GlobalTracer& t = imp; + + SpanGuard guard(&t, t.start("hello")); + EXPECT_TRUE(guard.sp); + + int rc = 0; + + rc = guard.sp->log("server", "blahblahblah"); + ASSERT_EQ(0, rc); + + rc = guard.sp->context().setBaggage("hello", "world"); + ASSERT_EQ(0, rc); + + rc = guard.sp->context().setBaggage("apple", "banana"); + ASSERT_EQ(0, rc); + + StringRef ref; + rc = guard.sp->context().getBaggage(&ref, "apple"); + + ASSERT_NE(0, rc); +} + +TEST(NoopTracer, StartWithOpAndTsp) +{ + NoopTracer imp; + GlobalTracer& t = imp; + + SpanGuard guard(&t, t.start("hello", 125125)); + EXPECT_TRUE(guard.sp); +} + +TEST(NoopTracer, StartWithOpAndParent) +{ + // We create spans, which have contexts or create contexts directly + // through the 'extract' interface. Either way, clients only deal + // with the 'GlobalContext' type. Rather than make this simple start + // test dependent on those other interfaces, I'm going to just pull + // a context out of thin air to test the interface. + + NoopContext contextImp; + GlobalContext& context = contextImp; + + NoopTracer imp; + GlobalTracer& t = imp; + + SpanGuard guard(&t, t.start("hello", context)); + EXPECT_TRUE(guard.sp); +} + +TEST(NoopTracer, StartWithOpAndParentAndTsp) +{ + // We create spans, which have contexts or create contexts directly + // through the 'extract' interface. Either way, clients only deal + // with the 'GlobalContext' type. Rather than make this simple start + // test dependent on those other interfaces, I'm going to just pull + // a context out of thin air to test the interface. + + NoopContext contextImp; + GlobalContext& context = contextImp; + + NoopTracer imp; + GlobalTracer& t = imp; + + SpanGuard guard(&t, t.start("hello", context, 125125)); + EXPECT_TRUE(guard.sp); +} + +TEST(NoopTracer, StartWithOpAndMultipleParents) +{ + NoopContext contextImp1; + NoopContext contextImp2; + NoopContext contextImp3; + + std::vector contexts(3, NoopContext()); + + NoopTracer imp; + GlobalTracer& t = imp; + + SpanGuard guard(&t, t.start("hello", contexts.begin(), contexts.end())); + EXPECT_TRUE(guard.sp); +} + +TEST(NoopTracer, StartWithOpAndMultipleParentsAndTsp) +{ + NoopContext contextImp1; + NoopContext contextImp2; + NoopContext contextImp3; + + std::vector contexts(3, NoopContext()); + + NoopTracer imp; + GlobalTracer& t = imp; + + SpanGuard guard(&t, t.start("hello", contexts.begin(), contexts.end(), 125125)); + EXPECT_TRUE(guard.sp); +} + +TEST(NoopTracer, InjectText) +{ + TestTextWriter writer; + NoopTracer imp; + + GlobalTracer& t = imp; + + SpanGuard g(&t, t.start("op")); + ASSERT_TRUE(g.sp); + + g.sp->context().setBaggage("animal", "tiger"); + g.sp->context().setBaggage("animal", "cat"); + + int rc = t.inject(&writer, g.sp->context()); + ASSERT_EQ(0, rc); +} + +TEST(NoopTracer, ExtractText) +{ + TestTextReader reader; + reader.pairs.push_back(TextMapPair("animal", "tiger")); + reader.pairs.push_back(TextMapPair("fruit", "apple")); + reader.pairs.push_back(TextMapPair("veggie", "carrot")); + + NoopTracer imp; + + GlobalTracer& t = imp; + + SpanContextGuard g(&t, t.extract(reader)); + ASSERT_TRUE(g.sp); + + size_t index = 0; + + const char * names[] = {"animal", "fruit", "veggie"}; + const char * values[] = {"tiger", "apple", "carrot"}; + + for (GlobalTracer::SpanContext::const_iterator it = g.sp->begin(); + it != g.sp->end(); + ++it) + { + ASSERT_STREQ(names[index], it.ref().key()); + ASSERT_STREQ(values[index], it.ref().value()); + ++index; + } +} + +TEST(NoopTracer, InjectBinary) +{ + TestBinaryWriter writer; + NoopTracer imp; + + GlobalTracer& t = imp; + + SpanGuard g(&t, t.start("op")); + ASSERT_TRUE(g.sp); + + int rc = t.inject(&writer, g.sp->context()); + ASSERT_EQ(0, rc); +} + +TEST(NoopTracer, ExtractBinary) +{ + TestBinaryReader reader; + reader.m_raw = 0xdeadbeef; + + NoopTracer imp; + + GlobalTracer& t = imp; + SpanContextGuard g(&t, t.extract(reader)); + ASSERT_TRUE(g.sp); +} + +struct NoopWriter: public GenericWriter +{ + int injectImp(const NoopContext&) + { + return 0; + } +}; + +TEST(NoopTracer, InjectExplicit) +{ + NoopWriter w; + NoopTracer imp; + GlobalTracer& t = imp; + + SpanGuard g(&t, t.start("span")); + ASSERT_TRUE(g.sp); + + int rc = t.inject(&w, g.sp->context()); + ASSERT_EQ(0, rc); +} + +struct NoopReader : public GenericReader +{ + int injectImp(const NoopContext&) + { + return 0; + } +}; + +TEST(NoopTracer, ExtractExplicit) +{ + NoopReader reader; + NoopTracer imp; + GlobalTracer& t = imp; + SpanContextGuard g(&t, t.extract(reader)); + ASSERT_TRUE(g.sp); +} + +template +class NoopSpanTypeTests : public ::testing::Test { +}; + +typedef ::testing::Types + OverloadedTypes; + +TYPED_TEST_CASE(NoopSpanTypeTests, OverloadedTypes); + +TYPED_TEST(NoopSpanTypeTests, TagInterface) +{ + NoopSpan impl; + GlobalSpan& t = impl; + int rc = t.tag("key", TypeParam()); + ASSERT_EQ(0, rc); +} + +TYPED_TEST(NoopSpanTypeTests, LogInterface) +{ + NoopSpan impl; + GlobalSpan& t = impl; + int rc = t.log("key", TypeParam()); + ASSERT_EQ(0, rc); +} + +TYPED_TEST(NoopSpanTypeTests, LogTspInterface) +{ + NoopSpan impl; + GlobalSpan& t = impl; + int rc = t.log("key", TypeParam(), 0); + ASSERT_EQ(0, rc); +} diff --git a/test/tracer.h b/test/tracer.h index 2abcfd4..44f3f84 100644 --- a/test/tracer.h +++ b/test/tracer.h @@ -44,8 +44,9 @@ class TestTracerImpl : public GenericTracer(&(*it)); - // Output is ignored, but I want to flex the compiler here. Let's force + const TestContextImpl* ctx = static_cast(&(*it)); + // Output is ignored, but I want to flex the compiler here. Let's + // force // a dereference to make sure the types are okay StringRef ref; @@ -56,11 +57,14 @@ class TestTracerImpl : public GenericTracer Span* - startImp(const StringRef&, const ITER pbegin, const ITER pend, const uint64_t) + startImp(const StringRef&, + const ITER pbegin, + const ITER pend, + const uint64_t) { for (ITER it = pbegin; it != pend; ++it) { - const TestContextImpl * ctx = static_cast(&(*it)); + const TestContextImpl* ctx = static_cast(&(*it)); StringRef ref; ctx->getBaggageImp(&ref, "hello"); @@ -68,13 +72,25 @@ class TestTracerImpl : public GenericTracer(sp); + } + + void + cleanupImp(SpanContext* const spc) + { + delete static_cast(spc); + } template int injectImp(GenericTextWriter* const carrier, const TestContext& context) const { - const TestContextImpl& imp = static_cast(context); + const TestContextImpl& imp = + static_cast(context); std::vector pairs; pairs.reserve(imp.baggageMap().size()); @@ -128,7 +144,7 @@ class TestTracerImpl : public GenericTracer& carrier) { size_t written = 0; - int output = 0; + int output = 0; if (int rc = carrier.extract(&output, &written, sizeof(output))) { diff --git a/test/tracer.t.cc b/test/tracer.t.cc index f23fd89..7c1ec1c 100644 --- a/test/tracer.t.cc +++ b/test/tracer.t.cc @@ -3,17 +3,8 @@ #include "carriers.h" -struct SpanGuard { - SpanGuard(Tracer::Span* s) : sp(s) {} - ~SpanGuard() { delete sp; } - Tracer::Span * sp; -}; - -struct SpanContextGuard { - SpanContextGuard(Tracer::SpanContext* s) : sp(s) {} - ~SpanContextGuard() { delete sp; } - Tracer::SpanContext * sp; -}; +typedef GenericSpanGuard SpanGuard; +typedef GenericSpanContextGuard SpanContextGuard; TEST(Tracer, SingletonTests) { @@ -30,7 +21,7 @@ TEST(Tracer, StartWithOp) TestTracerImpl imp; Tracer& t = imp; - SpanGuard guard(t.start("hello")); + SpanGuard guard(&t, t.start("hello")); EXPECT_TRUE(guard.sp); int rc = 0; @@ -56,7 +47,7 @@ TEST(Tracer, StartWithOpAndTsp) TestTracerImpl imp; Tracer& t = imp; - SpanGuard guard(t.start("hello", 125125)); + SpanGuard guard(&t, t.start("hello", 125125)); EXPECT_TRUE(guard.sp); } @@ -74,7 +65,7 @@ TEST(Tracer, StartWithOpAndParent) TestTracerImpl imp; Tracer& t = imp; - SpanGuard guard(t.start("hello", context)); + SpanGuard guard(&t, t.start("hello", context)); EXPECT_TRUE(guard.sp); } @@ -92,7 +83,7 @@ TEST(Tracer, StartWithOpAndParentAndTsp) TestTracerImpl imp; Tracer& t = imp; - SpanGuard guard(t.start("hello", context, 125125)); + SpanGuard guard(&t, t.start("hello", context, 125125)); EXPECT_TRUE(guard.sp); } @@ -107,7 +98,7 @@ TEST(Tracer, StartWithOpAndMultipleParents) TestTracerImpl imp; Tracer& t = imp; - SpanGuard guard(t.start("hello", contexts.begin(), contexts.end())); + SpanGuard guard(&t, t.start("hello", contexts.begin(), contexts.end())); EXPECT_TRUE(guard.sp); } @@ -122,7 +113,7 @@ TEST(Tracer, StartWithOpAndMultipleParentsAndTsp) TestTracerImpl imp; Tracer& t = imp; - SpanGuard guard(t.start("hello", contexts.begin(), contexts.end(), 125125)); + SpanGuard guard(&t, t.start("hello", contexts.begin(), contexts.end(), 125125)); EXPECT_TRUE(guard.sp); } @@ -133,7 +124,7 @@ TEST(Tracer, InjectText) Tracer& t = imp; - SpanGuard g(t.start("op")); + SpanGuard g(&t, t.start("op")); ASSERT_TRUE(g.sp); g.sp->context().setBaggage("animal", "tiger"); @@ -160,7 +151,7 @@ TEST(Tracer, ExtractText) Tracer& t = imp; - SpanContextGuard g(t.extract(reader)); + SpanContextGuard g(&t, t.extract(reader)); ASSERT_TRUE(g.sp); size_t index = 0; @@ -183,7 +174,7 @@ TEST(Tracer, InjectBinary) Tracer& t = imp; - SpanGuard g(t.start("op")); + SpanGuard g(&t, t.start("op")); ASSERT_TRUE(g.sp); int rc = t.inject(&writer, g.sp->context()); @@ -199,7 +190,7 @@ TEST(Tracer, ExtractBinary) TestTracerImpl imp; Tracer& t = imp; - SpanContextGuard g(t.extract(reader)); + SpanContextGuard g(&t, t.extract(reader)); ASSERT_TRUE(g.sp); } @@ -209,7 +200,7 @@ TEST(Tracer, InjectExplicit) TestTracerImpl imp; Tracer& t = imp; - SpanGuard g(t.start("span")); + SpanGuard g(&t, t.start("span")); ASSERT_TRUE(g.sp); g.sp->context().setBaggage("animal", "tiger"); @@ -232,6 +223,6 @@ TEST(Tracer, ExtractExplicit) TestTracerImpl imp; Tracer& t = imp; - SpanContextGuard g(t.extract(reader)); + SpanContextGuard g(&t, t.extract(reader)); ASSERT_TRUE(g.sp); } diff --git a/test/unittest.h b/test/unittest.h index 436f1c8..a2cbd98 100644 --- a/test/unittest.h +++ b/test/unittest.h @@ -19,6 +19,35 @@ test_widen(std::wstring* const dest, const std::string& src) dest->resize(src.size()); std::mbstowcs(&(*dest)[0], src.c_str(), src.size()); } + +template +struct GenericSpanGuard { + GenericSpanGuard(TRACER* tracer, typename TRACER::Span* s) : t(tracer), sp(s) + { + } + ~GenericSpanGuard() + { + t->cleanup(sp); + } + + TRACER* t; + typename TRACER::Span* sp; +}; + +template +struct GenericSpanContextGuard { + GenericSpanContextGuard(TRACER* tracer, typename TRACER::SpanContext* s) + : t(tracer), sp(s) + { + } + ~GenericSpanContextGuard() + { + t->cleanup(sp); + } + + TRACER* t; + typename TRACER::SpanContext* sp; +}; } using namespace opentracing; From 1ee01dc89646b17de1a9351577dcfa88b14a8d89 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Fri, 6 Jan 2017 14:44:46 -0500 Subject: [PATCH 08/48] Minor formatting --- opentracing/span.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/opentracing/span.h b/opentracing/span.h index f57d3bb..a46be6a 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -212,6 +212,10 @@ class GenericSpan { // Protected to avoid direct construction }; +// ----------------- +// class GenericSpan +// ----------------- + // Protected Constructors template @@ -626,5 +630,5 @@ GenericSpan::log(const StringRef& key, return static_cast(this)->logImp(key, val, tsp); } -} // end namespace opentracing +} // namespace opentracing #endif // INCLUDED_OPENTRACING_SPAN_H From 419580ef357e57b5f3e3a9d7193828764d65b2ec Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Sun, 8 Jan 2017 23:05:40 -0500 Subject: [PATCH 09/48] Updating tests, adding spanoptions, consistently documented --- opentracing/baggage.h | 212 ++++++------- opentracing/noop.h | 474 ++++++++--------------------- opentracing/span.h | 609 ++++++-------------------------------- opentracing/spancontext.h | 160 +++++----- opentracing/spanoptions.h | 97 ++++++ opentracing/stringref.h | 34 ++- opentracing/tracer.h | 451 ++++++++++++++++++---------- test/Makefile | 2 +- test/baggage.t.cc | 166 ++--------- test/carriers.h | 4 +- test/carriers.t.cc | 29 +- test/noop.t.cc | 26 +- test/span.h | 228 ++------------ test/span.t.cc | 14 +- test/spancontext.h | 69 +++-- test/spancontext.t.cc | 33 ++- test/tracer.h | 140 ++++----- test/tracer.t.cc | 110 +++---- test/unittest.h | 22 +- 19 files changed, 1103 insertions(+), 1777 deletions(-) create mode 100644 opentracing/spanoptions.h diff --git a/opentracing/baggage.h b/opentracing/baggage.h index 68f989f..efd1379 100644 --- a/opentracing/baggage.h +++ b/opentracing/baggage.h @@ -4,16 +4,15 @@ // ========= // baggage.h // ========= -// class BaggageImp - Client wrapper for copies of key:value pairs -// class Baggage - Typedef for Baggage working with char -// class BaggageWide - Typedef for Baggage working with wchar_t +// class BaggageImp - Client wrapper for copies of key:value pairs +// class Baggage - Typedef for Baggage working with char // -// class BaggageRefImp - Client wrapper for referencing key:value pairs -// class BaggageRef - Typedef for BaggageRef working with char -// class BaggageRefWide - Typedef for BaggageRef working with wchar_t -// -// class BaggageIterator - Client interface to traverse span baggage +// class BaggageRefImp - Client wrapper for referencing key:value pairs +// class BaggageRef - Typedef for BaggageRef working with char // +// class BaggageIteratorImp - Client interface to traverse span baggage +// class BaggageRangeImp - A range of BaggageIterators + // ------------------- // OpenTracing Baggage // ------------------- @@ -24,7 +23,7 @@ // Baggage items enable powerful functionality given a full-stack OpenTracing // integration (for example, arbitrary application data from a mobile // application 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. +// storage system), and with it some powerful costs. // // Use this feature thoughtfully and with care. Every key and value is copied // into every local and remote child of the associated Span, and that can add up @@ -75,8 +74,7 @@ class BaggageImp { std::basic_string m_value; }; -typedef BaggageImp Baggage; -typedef BaggageImp BaggageWide; +typedef BaggageImp Baggage; // =================== // class BaggageRefImp @@ -117,83 +115,49 @@ class BaggageRefImp { }; typedef BaggageRefImp BaggageRef; -typedef BaggageRefImp BaggageRefWide; -// ===================== -// class BaggageIterator -// ===================== -// ------- -// Clients -// ------- -// For flexibility between implementations, BaggageIterator classes should -// never be created directly. Instead, a typedef is provided by SpanContexts -// which allow callers to be agnostic of the underlying implementation. -// By using 'SpanContext::const_iterator', the call sites will be unaffected -// if implementations change in the future. -// -// The iterators themselves satisfy the requirements of C++ "Input Iterators". -// They can read from the pointed-to baggage element, returning Baggage for -// the key:value pairs. -// -// BaggageRef objects may be returned instead of copying the Baggage with -// calls to 'ref()'. Those references only guarantee validity for a single pass: -// once an iterator has been incremented, all copies of its previous value may -// be invalidated. -// -// See http://en.cppreference.com/w/cpp/concept/InputIterator for more details -// on semantics input iterators. -// -// ------------ -// Implementors -// ------------ -// BaggageIterator is used to obscure the data structure(s) used to store -// and traverse span baggage. Implementors should store the values as -// std::string types. The underlying data structure decision is left to +// ======================== +// class BaggageIteratorImp +// ======================== +// BaggageIteratorImp is used to obscure the data structure(s) used to store +// and traverse Span Baggage. Implementors should store the values as +// std::string types, but the underlying data structure decision is left to // implementors. // // We do not want to expose the details of these data structure(s) to clients; // If their code were to rely on any detail, it would make it difficult -// to change OpenTracing implementations. Instead, we define an 'Adapter' -// class, to translate the implementation's iterator into baggage references. -// -// The 'Adapter' class must satisfy the following: -// * Provide an iterator typedef, potentially used during construction -// * Provide a const_iterator typedef, potentially used during -// construction. -// * Provide narrow() to convert a const_iterator into Baggage -// * Provide wide() to convert a const_iterator into BaggageWide -// * Provide ref() to convert a const_iterator into a BaggageRef +// to change OpenTracing implementations. Instead, we define an Adapter class, +// to translate the implementation's iterators into baggage structures +// which clients can interact with. // -// To achieve this, implementors define a class like so: +// Adapter implementations are required to implement the following: // // struct AdapterClass { // typedef ImplementationIterator iterator; // typedef ImplementationIterator const_iterator; // -// Baggage narrow()(const const_iterator& it) const; -// Baggage wide()(const const_iterator& it) const; +// Baggage copy()(const const_iterator& it) const; // BaggageRef ref()(const const_iterator& it) const; // }; // -// Now, when clients create a BaggageIterator through 'SpanContext::begin()', +// When clients create a BaggageIterator via 'SpanContext::baggageBegin()', // the BaggageIterator should be created with an iterator to the underlying -// baggage implementation. It caches the iterator, incrementing it as -// clients move forward through the sequence. +// baggage implementation. The BaggageIterator caches the implementation +// iterator, incrementing the implementation iterator under the hood as clients +// move forward through the underlying sequence. // -// When clients dereference the baggage iterator, the 'Adapter' is invoked, -// passing the implementation's iterator to the adapter. It is expected that the -// 'Adapter' can convert the iterator into a Baggage, BaggageWide, or BaggageRef -// object that client code can use in a read-only fashion. +// When clients dereference the baggage iterator, the Adapter is invoked to +// convert the implementation iterator into Baggage/BaggageRefs. template -class BaggageIterator { +class BaggageIteratorImp { public: typedef typename ADAPTER::iterator iterator; typedef typename ADAPTER::const_iterator const_iterator; - BaggageIterator(const iterator& iter); - BaggageIterator(const const_iterator& iter); - // Construct a BaggageIterator object which will be used to traverse the + BaggageIteratorImp(const iterator& iter); + BaggageIteratorImp(const const_iterator& iter); + // Construct a BaggageIteratorImp object which will be used to traverse the // sequence pointed to by the input iterator 'iter'. BaggageRef operator*() const; @@ -202,32 +166,28 @@ class BaggageIterator { // to by this iterator. Undefined behavior if the iterator is equal to // 'end()'. - Baggage narrow() const; + Baggage copy() const; // Returns a copy of the key:value pairs pointed at by this iterator. // Undefined behavior if the iterator is equal to 'end()'. - BaggageWide wide() const; - // Returns a wide copies of the key:value pairs pointed at by this iterator. - // Undefined behavior if the iterator is equal to 'end()'. - BaggageRef ref() const; // Returns a BaggageRef object, containing references to the underlying // storage of the key:value pairs. References are invalided if the // associated SpanContext is destroyed or modified. - BaggageIterator operator++(int); + BaggageIteratorImp operator++(int); // Return a copy of this iterator, then post-increment this iterator to // point to the next key:value pair in the sequence. - BaggageIterator& operator++(); + BaggageIteratorImp& operator++(); // Increment this iterator, pointing to the next key:value pair in the // sequence, then return a reference to this iterator. - bool operator==(const BaggageIterator& other) const; + bool operator==(const BaggageIteratorImp& other) const; // Returns true if this iterator points to the same key:value pair as // 'other', and false otherwise. - bool operator!=(const BaggageIterator& other) const; + bool operator!=(const BaggageIteratorImp& other) const; // Returns true if this iterator points at a different key:value pair // than 'other', and false otherwise. @@ -236,6 +196,32 @@ class BaggageIterator { ADAPTER d_handler; // Converts d_iterator to Baggage wrappers }; +// ===================== +// class BaggageRangeImp +// ===================== +// If clients have access to C++11 features, BaggageRanges are a convenience +// class that allows an easy way to use range based for loops: +// +// `for(const auto& b: context.baggageRange()){ ... }` +// +// They define a 'begin' and 'end' method that allows the compiler to use +// this syntax. The class is otherwise redundant. + +template +class BaggageRangeImp { + public: + typedef BaggageIteratorImp BaggageIterator; + + BaggageRangeImp(const BaggageIterator& begin, const BaggageIterator& end); + + BaggageIterator begin() const; + BaggageIterator end() const; + + private: + const BaggageIterator m_begin; + const BaggageIterator m_end; +}; + // ---------------- // class BaggageImp // ---------------- @@ -281,13 +267,13 @@ BaggageImp::value() const } template -BaggageImp* BaggageImp::operator->() +inline BaggageImp* BaggageImp::operator->() { return this; } template -const BaggageImp* BaggageImp::operator->() const +inline const BaggageImp* BaggageImp::operator->() const { return this; } @@ -328,82 +314,104 @@ inline const BaggageRefImp* BaggageRefImp::operator->() const return this; } -// --------------------- -// class BaggageIterator -// --------------------- +// ------------------------ +// class BaggageIteratorImp +// ------------------------ template -BaggageIterator::BaggageIterator(const iterator& iter) +inline BaggageIteratorImp::BaggageIteratorImp(const iterator& iter) : d_iterator(iter), d_handler() { } template -BaggageIterator::BaggageIterator(const const_iterator& iter) +inline BaggageIteratorImp::BaggageIteratorImp( + const const_iterator& iter) : d_iterator(iter), d_handler() { } template -BaggageRef BaggageIterator::operator*() const +inline BaggageRef BaggageIteratorImp::operator*() const { return d_handler.ref(d_iterator); } template -BaggageRef BaggageIterator::operator->() const +inline BaggageRef BaggageIteratorImp::operator->() const { return d_handler.ref(d_iterator); } template -Baggage BaggageIterator::narrow() const +inline Baggage +BaggageIteratorImp::copy() const { - return d_handler.narrow(d_iterator); + return d_handler.copy(d_iterator); } template -BaggageWide BaggageIterator::wide() const -{ - return d_handler.wide(d_iterator); -} - -template -BaggageRef BaggageIterator::ref() const +inline BaggageRef +BaggageIteratorImp::ref() const { return d_handler.ref(d_iterator); } template -BaggageIterator BaggageIterator::operator++(int) +inline BaggageIteratorImp BaggageIteratorImp::operator++(int) { - BaggageIterator tmp(*this); + BaggageIteratorImp tmp(*this); ++d_iterator; return tmp; } template -BaggageIterator& BaggageIterator::operator++() +inline BaggageIteratorImp& BaggageIteratorImp::operator++() { ++d_iterator; return *this; } template -bool -BaggageIterator::operator==( - const BaggageIterator& other) const +inline bool +BaggageIteratorImp::operator==( + const BaggageIteratorImp& other) const { return d_iterator == other.d_iterator; } template -bool -BaggageIterator::operator!=( - const BaggageIterator& other) const +inline bool +BaggageIteratorImp::operator!=( + const BaggageIteratorImp& other) const { return d_iterator != other.d_iterator; } +// --------------------- +// class BaggageRangeImp +// --------------------- + +template +inline BaggageRangeImp::BaggageRangeImp(const BaggageIterator& begin, + const BaggageIterator& end) +: m_begin(begin), m_end(end) +{ +} + +template +inline typename BaggageRangeImp::BaggageIterator +BaggageRangeImp::begin() const +{ + return m_begin; +} + +template +inline typename BaggageRangeImp::BaggageIterator +BaggageRangeImp::end() const +{ + return m_end; +} + } // namespace opentracing #endif // INCLUDED_OPENTRACING_BAGGAGE_H diff --git a/opentracing/noop.h b/opentracing/noop.h index b2ef2b4..2948827 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -6,6 +6,7 @@ // ====== // class NoopAdapter - No-op adapter for NoopContext baggage // class NoopContext - No-op span context implementation +// class NoopOptions - No-op span options implementation // class NoopSpan - No-op span implementation // class NoopTracer - No-op tracer implementation // @@ -14,12 +15,10 @@ // ----- // This header provides a No-Op implementation for the generic OpenTracing // classes. It can be installed globally in your application to begin -// instrumenting or testing the interface, but it has no side-effects, with -// one exception. +// instrumenting or testing the interface; it has no-side effects. // // In order to have client code behave the same when a concrete implementation // is used, clients should be calling finish() and cleanup() appropriately. -// See span.h and tracer.h for details. // // See the specification for requirements of NoopTracers: // https://github.com/opentracing/specification/blob/master/specification.md#nooptracer @@ -28,6 +27,7 @@ #include #include #include +#include #include #include @@ -35,19 +35,20 @@ #include #endif -namespace opentracing{ +namespace opentracing { class NoopAdapter; class NoopContext; +class NoopOptions; class NoopSpan; class NoopTracer; // ================= // Class NoopAdapter // ================= -// The NoopAdapter has no container to iterator over. Regardless of -// what iterator is passed in, it will always return empty baggage -// objects or references. +// The NoopAdapter has no container to iterator over. Regardless of what +// iterator is passed in, it will always return empty baggage objects or +// references. class NoopAdapter { public: @@ -55,20 +56,18 @@ class NoopAdapter { typedef const NoopContext* const_iterator; BaggageRef ref(const const_iterator& it) const; - Baggage narrow(const const_iterator& it) const; - BaggageWide wide(const const_iterator& it) const; + Baggage copy(const const_iterator& it) const; }; // ================= // Class NoopContext // ================= -// The NoopContext implements the GenericSpanContext interface. It -// provides no-op overloads for 'setBaggageImp' and 'getBaggageImp'. +// The NoopContext implements the GenericSpanContext interface. // -// The baggage container iterator interface is faked by always -// using the address of the NoopContext itself for both the begin() -// and end() implementations. Since those pointers should always be -// equal, the iterator range will always be considered empty. +// The baggage iterator interface is faked by always using the address of the +// encompassing NoopContext for both the baggageBeginImp() and baggageEndImp() +// calls. Since those pointers should always be equal for the same SpanContext, +// the iterator range will always be considered empty. // // If clients are using iterators correctly, the iterator should never // be dereferenced, however, if they do dereference the BaggageIterator, @@ -76,10 +75,27 @@ class NoopAdapter { class NoopContext : public GenericSpanContext { public: - int setBaggageImp(const StringRef& key, const StringRef& baggage); - int getBaggageImp(StringRef* const baggage, const StringRef& key) const; - const_iterator beginImp() const; - const_iterator endImp() const; + BaggageIterator baggageBeginImp() const; + BaggageIterator baggageEndImp() const; + + int setBaggageImp(const StringRef& key, const StringRef& value); + int getBaggageImp(BaggageValue* const, const StringRef& key) const; + int getBaggageRefsImp(BaggageValues* const, const StringRef& key) const; +}; + +// ================= +// Class NoopOptions +// ================= +// NoopOptions implements the GenericSpanOptions interface. It holds +// onto no references, nor does it manipulate the start time or operation +// names; it does not need to. + +class NoopOptions + : public GenericSpanOptions { + public: + void setOperationImp(const StringRef&); + void setStartTimeImp(const uint64_t); + void addReferenceImp(const SpanRelationship::Value, const NoopContext&); }; // ============== @@ -99,53 +115,14 @@ class NoopSpan : public GenericSpan { int finishImp(); int finishImp(const uint64_t); - int tagImp(const StringRef&, const StringRef&); - int tagImp(const StringRef&, const bool); - int tagImp(const StringRef&, const float); - int tagImp(const StringRef&, const double); - int tagImp(const StringRef&, const long double); - int tagImp(const StringRef&, const char); - int tagImp(const StringRef&, const signed char); - int tagImp(const StringRef&, const unsigned char); - int tagImp(const StringRef&, const wchar_t); - int tagImp(const StringRef&, const int16_t); - int tagImp(const StringRef&, const int32_t); - int tagImp(const StringRef&, const int64_t); - int tagImp(const StringRef&, const uint16_t); - int tagImp(const StringRef&, const uint32_t); - int tagImp(const StringRef&, const uint64_t); - - int logImp(const StringRef&, const StringRef&); - int logImp(const StringRef&, const bool); - int logImp(const StringRef&, const float); - int logImp(const StringRef&, const double); - int logImp(const StringRef&, const long double); - int logImp(const StringRef&, const char); - int logImp(const StringRef&, const signed char); - int logImp(const StringRef&, const unsigned char); - int logImp(const StringRef&, const wchar_t); - int logImp(const StringRef&, const int16_t); - int logImp(const StringRef&, const int32_t); - int logImp(const StringRef&, const int64_t); - int logImp(const StringRef&, const uint16_t); - int logImp(const StringRef&, const uint32_t); - int logImp(const StringRef&, const uint64_t); - - int logImp(const StringRef&, const StringRef&, const uint64_t); - int logImp(const StringRef&, const bool, const uint64_t); - int logImp(const StringRef&, const float, const uint64_t); - int logImp(const StringRef&, const double, const uint64_t); - int logImp(const StringRef&, const long double, const uint64_t); - int logImp(const StringRef&, const char, const uint64_t); - int logImp(const StringRef&, const signed char, const uint64_t); - int logImp(const StringRef&, const unsigned char, const uint64_t); - int logImp(const StringRef&, const wchar_t, const uint64_t); - int logImp(const StringRef&, const int16_t, const uint64_t); - int logImp(const StringRef&, const int32_t, const uint64_t); - int logImp(const StringRef&, const int64_t, const uint64_t); - int logImp(const StringRef&, const uint16_t, const uint64_t); - int logImp(const StringRef&, const uint32_t, const uint64_t); - int logImp(const StringRef&, const uint64_t, const uint64_t); + template + int tagImp(const StringRef&, const T&); + + template + int logImp(const StringRef&, const T&); + + template + int logImp(const StringRef&, const T&, const uint64_t); private: NoopContext m_context; @@ -157,52 +134,49 @@ class NoopSpan : public GenericSpan { // The NoopTracer implements the GenericTracer interface. It provides no-op // overloads for all of the required Tracer behaviors. // -// Clients can start spans and are still required to call 'cleanup' on -// returned Span and SpanContext pointers. - -class NoopTracer - : public GenericTracer { - // Note that Span' and SpanContext typedefs are provided by the base class +// Although clients can 'start()' spans or 'makeSpanOptions()', there are +// no allocations made. Clients should call 'finish()'/'cleanup()', however, +// this implementation has no side effects of them doing so. + +class NoopTracer : public GenericTracer { public: - Span* startImp(const StringRef&); - Span* startImp(const StringRef&, const SpanContext&); - - template - Span* startImp(const StringRef&, const ITER&, const ITER&); + NoopOptions* makeSpanOptionsImp(); + void cleanupImp(const NoopOptions* const opts); - Span* startImp(const StringRef&, const uint64_t); - Span* startImp(const StringRef&, const SpanContext&, const uint64_t); - - template - Span* startImp(const StringRef&, const ITER&, const ITER&, const uint64_t); - - void cleanupImp(Span* const sp); + NoopSpan* startImp(const StringRef&); + NoopSpan* startImp(const NoopOptions&); + void cleanupImp(const Span* const sp); template int injectImp(GenericTextWriter* const carrier, - const SpanContext& context) const; + const NoopContext& context) const; template int injectImp(GenericBinaryWriter* const carrier, - const SpanContext& context) const; + const NoopContext& context) const; template int injectImp(GenericWriter* const carrier, - const SpanContext& context) const; + const NoopContext& context) const; template - SpanContext* extractImp(const GenericTextReader& carrier); + NoopContext* extractImp(const GenericTextReader& carrier); template - SpanContext* extractImp(const GenericBinaryReader& carrier); + NoopContext* extractImp(const GenericBinaryReader& carrier); template - SpanContext* extractImp(const GenericReader& carrier); + NoopContext* extractImp(const GenericReader& carrier); - void cleanupImp(SpanContext* const sp); + void cleanupImp(const NoopContext* const sp); private: - NoopSpan m_span; + NoopOptions m_opts; + NoopSpan m_span; }; // ----------------- @@ -214,21 +188,29 @@ NoopAdapter::ref(const const_iterator&) const { return BaggageRef(); } + inline Baggage -NoopAdapter::narrow(const const_iterator&) const +NoopAdapter::copy(const const_iterator&) const { return Baggage(); } -inline BaggageWide -NoopAdapter::wide(const const_iterator&) const -{ - return BaggageWide(); -} // ----------------- // class NoopContext // ----------------- +inline NoopContext::BaggageIterator +NoopContext::baggageBeginImp() const +{ + return baggageEndImp(); +} + +inline NoopContext::BaggageIterator +NoopContext::baggageEndImp() const +{ + return BaggageIterator(this); +} + inline int NoopContext::setBaggageImp(const StringRef&, const StringRef&) { @@ -236,21 +218,34 @@ NoopContext::setBaggageImp(const StringRef&, const StringRef&) } inline int -NoopContext::getBaggageImp(StringRef* const, const StringRef&) const +NoopContext::getBaggageImp(BaggageValue* const, const StringRef&) const { return 1; } -inline NoopContext::const_iterator -NoopContext::beginImp() const +inline int +NoopContext::getBaggageRefsImp(BaggageValues* const, const StringRef&) const { - return const_iterator(this); + return 1; } -inline NoopContext::const_iterator -NoopContext::endImp() const +// ----------------- +// class NoopOptions +// ----------------- + +inline void +NoopOptions::setOperationImp(const StringRef&) +{ +} + +inline void +NoopOptions::setStartTimeImp(const uint64_t) +{ +} + +inline void +NoopOptions::addReferenceImp(const SpanRelationship::Value, const NoopContext&) { - return const_iterator(this); } // ------------- @@ -278,236 +273,30 @@ NoopSpan::finishImp() { return 0; } + inline int NoopSpan::finishImp(const uint64_t) { return 0; } +template inline int -NoopSpan::tagImp(const StringRef&, const StringRef&) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const bool) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const float) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const double) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const long double) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const char) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const signed char) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const unsigned char) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const wchar_t) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const int16_t) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const int32_t) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const int64_t) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const uint16_t) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const uint32_t) -{ - return 0; -} -inline int -NoopSpan::tagImp(const StringRef&, const uint64_t) +NoopSpan::tagImp(const StringRef&, const T&) { return 0; } +template inline int -NoopSpan::logImp(const StringRef&, const StringRef&) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const bool) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const float) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const double) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const long double) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const char) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const signed char) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const unsigned char) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const wchar_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const int16_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const int32_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const int64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const uint16_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const uint32_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const uint64_t) +NoopSpan::logImp(const StringRef&, const T&) { return 0; } +template inline int -NoopSpan::logImp(const StringRef&, const StringRef&, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const bool, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const float, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const double, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const long double, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const char, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const signed char, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const unsigned char, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const wchar_t, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const int16_t, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const int32_t, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const int64_t, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const uint16_t, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const uint32_t, const uint64_t) -{ - return 0; -} -inline int -NoopSpan::logImp(const StringRef&, const uint64_t, const uint64_t) +NoopSpan::logImp(const StringRef&, const T&, const uint64_t) { return 0; } @@ -516,53 +305,38 @@ NoopSpan::logImp(const StringRef&, const uint64_t, const uint64_t) // class NoopTracer // ---------------- -inline NoopTracer::Span* -NoopTracer::startImp(const StringRef&) +inline NoopOptions* +NoopTracer::makeSpanOptionsImp() { - return &m_span; + return &m_opts; } -inline NoopTracer::Span* -NoopTracer::startImp(const StringRef&, const SpanContext&) -{ - return &m_span; -} - -template -inline NoopTracer::Span* -NoopTracer::startImp(const StringRef&, const ITER&, const ITER&) -{ - return &m_span; -} - -inline NoopTracer::Span* -NoopTracer::startImp(const StringRef&, const uint64_t) +inline void +NoopTracer::cleanupImp(const NoopOptions* const) { - return &m_span; } -inline NoopTracer::Span* -NoopTracer::startImp(const StringRef&, const SpanContext&, const uint64_t) +inline NoopSpan* +NoopTracer::startImp(const StringRef&) { return &m_span; } -template -inline NoopTracer::Span* -NoopTracer::startImp(const StringRef&, const ITER&, const ITER&, const uint64_t) +inline NoopSpan* +NoopTracer::startImp(const NoopOptions&) { return &m_span; } inline void -NoopTracer::cleanupImp(Span* const) +NoopTracer::cleanupImp(const Span* const) { } template inline int NoopTracer::injectImp(GenericTextWriter* const, - const SpanContext&) const + const NoopContext&) const { return 0; } @@ -570,7 +344,7 @@ NoopTracer::injectImp(GenericTextWriter* const, template inline int NoopTracer::injectImp(GenericBinaryWriter* const, - const SpanContext&) const + const NoopContext&) const { return 0; } @@ -578,34 +352,34 @@ NoopTracer::injectImp(GenericBinaryWriter* const, template inline int NoopTracer::injectImp(GenericWriter* const, - const SpanContext&) const + const NoopContext&) const { return 0; } template -inline NoopTracer::SpanContext* +inline NoopContext* NoopTracer::extractImp(const GenericTextReader&) { return &m_span.context(); } template -inline NoopTracer::SpanContext* +inline NoopContext* NoopTracer::extractImp(const GenericBinaryReader&) { return &m_span.context(); } template -inline NoopTracer::SpanContext* +inline NoopContext* NoopTracer::extractImp(const GenericReader&) { return &m_span.context(); } inline void -NoopTracer::cleanupImp(SpanContext* const) +NoopTracer::cleanupImp(const NoopContext* const) { } diff --git a/opentracing/span.h b/opentracing/span.h index a46be6a..5e1bbfb 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -5,24 +5,10 @@ // span.h // ====== // class GenericSpan - CRTP interface for Spans -// -// ---- -// Span -// ---- -// Every Trace is made up of one or more Spans. Spans are used encapuslate: -// * An operation name -// * A start timestamp -// * A finish timestamp -// * A set of zero or more key:value SpanTags -// * A set of zero or more timestamped key:value SpanLogs -// * A SpanContext (see spancontext.h) -// * References to zero or more causally-related Spans -// -// The installed Tracer acts as a factory for Spans, keeping clients agnostic -// of the implementation. -// -// See the specification for more details: -// https://github.com/opentracing/specification/blob/master/specification.md#span + +#include +#include +#include #include @@ -30,9 +16,6 @@ #include #endif -#include -#include - namespace opentracing { // ================= @@ -40,83 +23,47 @@ namespace opentracing { // ================= // GenericSpan is a static, polymorphic interface for interacting with // Spans. It uses the Curiously Repeating Template Patttern (CRTP) to -// avoid unnecessary v-table hits we would encounter with traditional -// polymorphism. +// avoid v-table hits we would encounter with traditional polymorphism. // // See this CRTP article for more details on the design pattern: // https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern // -// ------- -// Clients -// ------- -// GenericSpans are not created directly by clients. They are instead -// created and cleaned up through the installed Tracer interface. -// -// Clients should never need to reference the GenericSpan type explicitly. -// Instead, clients should use the Tracer::Span typedef. By using the typedef, -// clients will avoid code changes necessary if a different Tracer -// implementation is installed later. -// -// Once clients have access to a Span, they can: -// * Access the underlying SpanContext via 'context()' -// * 'log()' timestamped key:value pairs -// * 'tag()' a span, with key:value pairs -// * 'finish()' a span -// -// After 'finish()' is called, it is undefined behavior to invoke any other -// method on the Span, except for accessing 'context()' in a read-only fashion. -// When clients are finished with a Span, it should be passed back to the -// Tracer via 'Tracer::cleanup()'. -// -// For more details on: -// * Accessing/retrieving Baggage, see 'spancontext.h' -// * Creating/Cleaning up Spans, see 'tracer.h' -// -// ------------ -// Implementors -// ------------ // The GenericSpan has three template parameters: // * SPAN - A Span implementation derived class (CRTP) // * CONTEXT - A SpanContext implementation derived class (CRTP) // * ADAPTER - A Baggage iterator adapter // -// The CONTEXT and ADAPTER are only used to establish the GenericSpanContext -// interface used for the SpanContext typedef. +// The CONTEXT and ADAPTER are used to alias the related GenericSpanContext +// class as the SpanContext. This is a convenience typedef to ensure what is +// exposed to clients is the same as the type used by the interface. // -// SPAN implementations have to support the following: +// SPAN implementations must support the following: // // class SpanImpl: GenericSpan // { // public: -// SpanContext& contextImp(); -// const SpanContext& contextImp() const; +// ContextImpl& contextImp(); +// const ContextImpl& contextImp() const; +// +// int addReferenceImp(const ContextImpl&, const SpanRelationship::Value); +// int setOperationImp(const StringRef& operation); // // int finishImp(); // int finishImp(const uint64_t); // -// int tagImp(const StringRef&, const Fundamental); -// int tagImp(const StringRef&, const StringRef&); +// template +// int tagImp(const StringRef&, const T&); // -// int logImp(const StringRef&, const Fundamental); -// int logImp(const StringRef&, const StringRef&); +// template +// int logImp(const StringRef&, const T&); // -// int logImp(const StringRef&, const Fundamental, const uint64_t); -// int logImp(const StringRef&, const StringRef&, const uint64_t); +// template +// int logImp(const StringRef&, const T&, const uint64_t); // }; // -// For brevities sake, the above example collapses the overloads on fundamental -// C++ types for 'tagImp()' and 'logImp()' into a single declaration on the -// 'Fundamental' type. For actual implementations, overloads must be supplied -// for each of the following fundamental types. -// -// * float * int16_t * uint16_t * char * wchar_t -// * double * int32_t * uint32_t * signed char * bool -// * long double * int64_t * uint64_t * unsigned char -// (http://en.cppreference.com/w/cpp/language/types) -// -// The overloads are used instead of a single template to: -// * Avoid passing references larger than the types they refer to (64-bit) -// * Avoid ambiguities at compile time when clients use the overloads +// The templated 'tagImp' and 'logImp' methods may assume that the following +// method is defined for any type 'T': +// `std::ostream& operator<<(std::ostream&, const T& val);` template class GenericSpan { @@ -125,86 +72,58 @@ class GenericSpan { SpanContext& context(); const SpanContext& context() const; - // Return the SpanContext associated with this span. Baggage can - // be retrieved/modified through the SpanContext. + // Return the SpanContext associated with this span. Baggage can be + // retrieved/modified through the SpanContext. The context can be injected + // into carriers, or added as a reference to other causally related Spans. + // It is undefined behavior to modify the context after 'finish()' has been + // called on this Span. + + int setOperation(const StringRef& operation); + // Modify the Span's operation. Return 0 upon success and a non-zero + // value otherwise. It is undefined behavior to call this method after + // 'finish()'. + + int addReference(const SpanContext& context, + const SpanRelationship::Value relationship); + // Add a reference to another SpanContext, after the Span was created. + // Returns 0 upon success and a non-zero value otherwise. + // It is undefined behavior to call this method after 'finish()'. int finish(); int finish(const uint64_t tsp); // This should be the last method called on the Span. It marks the end of // this Span (in microseconds since epoch) using the current wall-time, or - // an explicit timestamp 'tsp'. It is undefined behavior to call any method - // on this span after 'finish' is called, except for 'context()'. - // Returns 0 upon success and a non-zero value otherwise. - - int tag(const StringRef& key, const StringRef& val); - int tag(const StringRef& key, const bool val); - - int tag(const StringRef& key, const float val); - int tag(const StringRef& key, const double val); - int tag(const StringRef& key, const long double val); - - int tag(const StringRef& key, const char val); - int tag(const StringRef& key, const signed char val); - int tag(const StringRef& key, const unsigned char val); - int tag(const StringRef& key, const wchar_t val); - - int tag(const StringRef& key, const int16_t val); - int tag(const StringRef& key, const int32_t val); - int tag(const StringRef& key, const int64_t val); - - int tag(const StringRef& key, const uint16_t val); - int tag(const StringRef& key, const uint32_t val); - int tag(const StringRef& key, const uint64_t val); - // Set a tag on this span, associating the supplied 'key' to the supplied - // 'val'. Overloads are supplied for common primitive types and a string - // blob. Returns 0 upon success and a non-zero value otherwise. - - int log(const StringRef& key, const StringRef& val); - int log(const StringRef& key, const bool val); - - int log(const StringRef& key, const float val); - int log(const StringRef& key, const double val); - int log(const StringRef& key, const long double val); - - int log(const StringRef& key, const char val); - int log(const StringRef& key, const signed char val); - int log(const StringRef& key, const unsigned char val); - int log(const StringRef& key, const wchar_t val); - - int log(const StringRef& key, const int16_t val); - int log(const StringRef& key, const int32_t val); - int log(const StringRef& key, const int64_t val); - - int log(const StringRef& key, const uint16_t val); - int log(const StringRef& key, const uint32_t val); - int log(const StringRef& key, const uint64_t val); - // Log structured data for this span, associating the current wall-time - // with the supplied key:val pair. Returns 0 upon success and a non-zero - // value otherwise. - - int log(const StringRef& key, const StringRef& val, const uint64_t tsp); - int log(const StringRef& key, const bool val, const uint64_t tsp); - - int log(const StringRef& key, const float val, const uint64_t tsp); - int log(const StringRef& key, const double val, const uint64_t tsp); - int log(const StringRef& key, const long double val, const uint64_t tsp); - - int log(const StringRef& key, const char val, const uint64_t tsp); - int log(const StringRef& key, const signed char val, const uint64_t tsp); - int log(const StringRef& key, const unsigned char val, const uint64_t tsp); - int log(const StringRef& key, const wchar_t val, const uint64_t tsp); - - int log(const StringRef& key, const int16_t val, const uint64_t tsp); - int log(const StringRef& key, const int32_t val, const uint64_t tsp); - int log(const StringRef& key, const int64_t val, const uint64_t tsp); - - int log(const StringRef& key, const uint16_t val, const uint64_t tsp); - int log(const StringRef& key, const uint32_t val, const uint64_t tsp); - int log(const StringRef& key, const uint64_t val, const uint64_t tsp); - // Log structured data for this span, associating the explicit timestamp - // 'tsp' with the supplied 'key':'val' pair. Timestamp should be the - // number of microseconds since the Unix Epoch. Returns 0 upon success and a - // non-zero value otherwise. + // an explicit timestamp 'tsp'. Retrusn 0 upon success and a non-zero + // value otherwise. It is undefined behavior to call any method on this span + // after 'finish()' is called, except for accessing 'context()' in a + // read-only fashion. + + template + int tag(const StringRef& key, const T& val); + // Tag this span with the supplied key:val pair. Returns 0 upon success and + // a non-zero value otherwise. It is undefined behavior to call this method + // after 'finish()'. + // + // Note: Any type passed must support being externalized: + // `std::ostream& operator<<(std::ostream& os, const T& val); + + template + int log(const StringRef& key, const T& val); + // Log the supplied key:val pair on this span with the current wall-time. + // Returns 0 upon success and a non-zero value otherwise. It is undefined + // behavior to call this method after 'finish()'. + // + // Note: Any type passed must support being externalized: + // `std::ostream& operator<<(std::ostream& os, const T& val); + + template + int log(const StringRef& key, const T& val, const uint64_t tsp); + // Log the supplied key:val pair on this span with the supplied 'tsp' + // timestamp. Returns 0 upon success and a non-zero value otherwise. + // It is undefined behavior to call this method after 'finish()'. + // + // Note: Any type passed must support being externalized: + // `std::ostream& operator<<(std::ostream& os, const T& val); protected: GenericSpan(); @@ -216,415 +135,81 @@ class GenericSpan { // class GenericSpan // ----------------- -// Protected Constructors - template -GenericSpan::GenericSpan() +inline GenericSpan::GenericSpan() { } template -GenericSpan::GenericSpan(const GenericSpan&) +inline GenericSpan::GenericSpan(const GenericSpan&) { } -// Context Accessors - template -typename GenericSpan::SpanContext& +inline typename GenericSpan::SpanContext& GenericSpan::context() { return static_cast(this)->contextImp(); } template -const typename GenericSpan::SpanContext& +inline const typename GenericSpan::SpanContext& GenericSpan::context() const { return static_cast(this)->contextImp(); } -// Tags - -template -int -GenericSpan::finish() -{ - return static_cast(this)->finishImp(); -} - -template -int -GenericSpan::finish(const uint64_t tsp) -{ - return static_cast(this)->finishImp(tsp); -} - -template -int -GenericSpan::tag(const StringRef& key, - const StringRef& val) -{ - return static_cast(this)->tagImp(key, val); -} - -template -int -GenericSpan::tag(const StringRef& key, const bool val) -{ - return static_cast(this)->tagImp(key, val); -} - -template -int -GenericSpan::tag(const StringRef& key, const float val) -{ - return static_cast(this)->tagImp(key, val); -} - -template -int -GenericSpan::tag(const StringRef& key, const double val) -{ - return static_cast(this)->tagImp(key, val); -} - -template -int -GenericSpan::tag(const StringRef& key, - const long double val) -{ - return static_cast(this)->tagImp(key, val); -} - -template -int -GenericSpan::tag(const StringRef& key, const char val) -{ - return static_cast(this)->tagImp(key, val); -} - -template -int -GenericSpan::tag(const StringRef& key, - const signed char val) -{ - return static_cast(this)->tagImp(key, val); -} - -template -int -GenericSpan::tag(const StringRef& key, - const unsigned char val) -{ - return static_cast(this)->tagImp(key, val); -} - template -int -GenericSpan::tag(const StringRef& key, - const wchar_t val) +inline int +GenericSpan::setOperation(const StringRef& operation) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->setOperationImp(operation); } template -int -GenericSpan::tag(const StringRef& key, - const int16_t val) +inline int +GenericSpan::addReference( + const SpanContext& context, const SpanRelationship::Value relationship) { - return static_cast(this)->tagImp(key, val); + const CONTEXT& contextImp = static_cast(context); + return static_cast(this)->addReferenceImp(contextImp, relationship); } template -int -GenericSpan::tag(const StringRef& key, - const int32_t val) -{ - return static_cast(this)->tagImp(key, val); -} - -template -int -GenericSpan::tag(const StringRef& key, - const int64_t val) +inline int +GenericSpan::finish() { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->finishImp(); } template -int -GenericSpan::tag(const StringRef& key, - const uint16_t val) +inline int +GenericSpan::finish(const uint64_t tsp) { - return static_cast(this)->tagImp(key, val); + return static_cast(this)->finishImp(tsp); } template -int -GenericSpan::tag(const StringRef& key, - const uint32_t val) +template +inline int +GenericSpan::tag(const StringRef& key, const T& val) { return static_cast(this)->tagImp(key, val); } template -int -GenericSpan::tag(const StringRef& key, - const uint64_t val) -{ - return static_cast(this)->tagImp(key, val); -} - -// Logs - -template -int -GenericSpan::log(const StringRef& key, - const StringRef& val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, const bool val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, const float val) +template +inline int +GenericSpan::log(const StringRef& key, const T& val) { return static_cast(this)->logImp(key, val); } template -int -GenericSpan::log(const StringRef& key, const double val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, - const long double val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, const char val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, - const signed char val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, - const unsigned char val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, - const wchar_t val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, - const int16_t val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, - const int32_t val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, - const int64_t val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, - const uint16_t val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, - const uint32_t val) -{ - return static_cast(this)->logImp(key, val); -} - -template -int -GenericSpan::log(const StringRef& key, - const uint64_t val) -{ - return static_cast(this)->logImp(key, val); -} - -// Logs with timestamps -template -int -GenericSpan::log(const StringRef& key, - const StringRef& val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const bool val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const float val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const double val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const long double val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const char val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const signed char val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const unsigned char val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const wchar_t val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const int16_t val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const int32_t val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const int64_t val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const uint16_t val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int -GenericSpan::log(const StringRef& key, - const uint32_t val, - const uint64_t tsp) -{ - return static_cast(this)->logImp(key, val, tsp); -} - -template -int +template +inline int GenericSpan::log(const StringRef& key, - const uint64_t val, + const T& val, const uint64_t tsp) { return static_cast(this)->logImp(key, val, tsp); diff --git a/opentracing/spancontext.h b/opentracing/spancontext.h index a3d574a..78c299e 100644 --- a/opentracing/spancontext.h +++ b/opentracing/spancontext.h @@ -4,32 +4,12 @@ // ============= // spancontext.h // ============= -// // class GenericSpanContext - CRTP interface for SpanContexts -// -// ----------- -// SpanContext -// ----------- -// Every Span has a SpanContext. This context is used to: -// * Inject Spans into Carriers -// * Represent a Span in-band, across process boundaries -// * Extract Spans from Carriers -// * Create new Spans, related to the SpanContext -// -// Since the Span has to represent the entire Span in-band, and baggage must -// also be propagated across process boundaries, the SpanContext is also -// responsible for baggage. -// -// In most OpenTracing implementations, the SpanContext is made immutable in -// order to avoid complicated lifetime issues. The C++ interface relaxes those -// requirements, exposing the 'GenericSpanContext::setBaggage()' method directly -// on the context. -// -// See the specification for more details: -// https://github.com/opentracing/specification/blob/master/specification.md#Spancontext -#include #include +#include +#include +#include namespace opentracing { @@ -44,82 +24,67 @@ namespace opentracing { // See this CRTP article for more details on the design pattern: // https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern // -// ------- -// Clients -// ------- -// After a Span is created, the 'Span::context()' method is used to access -// a context that supports the 'GenericSpanContext' interface. -// -// Clients should never need to reference the GenericSpanContext type -// explicitly, but instead, clients should use the Tracer::Span::SpanContext -// typedef. By using the typedef, clients will avoid code changes necessary if a -// different Tracer implementation is installed later. -// -// Once clients have access to a SpanContext, they can: -// * 'setBaggage()' key:value pairs -// * 'getBaggage()' for a given key -// * Iterate over all Baggage via 'begin()'/'end()' -// -// For more details on: -// * accessing a SpanContext, see 'span.h' -// * iterating over Baggage, see 'baggage.h' -// * inject/extract, see 'tracer.h -// -// ------------ -// Implementors -// ------------ // The 'GenericSpanContext' has two template parameters: // * CONTEXT - A SpanContext implementation derived class (CRTP) -// * ADAPTER - A BaggageIterator adapter +// * ADAPTER - A BaggageIteratorImp adapter // // CONTEXT implementations are required to implement the following: // // class ContextImpl : GenericSpanContext // { // public: -// const_iterator beginImp() const; -// const_iterator endImp() const; -// int setBaggageImp(const StringRef& const, const StringRef& baggage); -// int getBaggageImp(StringRef *const, const StringRef& key) const; +// typename Adapter::const_iterator baggageBeginImp() const; +// typename Adapter::const_iterator baggageEndImp() const; +// +// int setBaggageImp(const StringRef&, const StringRef&); +// +// int getBaggageImp(std::string* const, const StringRef&) const; +// int getBaggageImp(BaggageValues* const, const StringRef&) const; // }; // -// Implementations may choose how they implement Baggage, but the -// beginImp/endImp iterators should interact with the installed +// Implementations may choose how they implement storage of Baggage, but the +// baggageBeginImp/baggageEndImp iterators should interact with the installed // BaggageIterator/Adapter correctly. -// -// Since the SpanContext implementation type is decided at compile time, Span -// and Tracer implementations may safely static_cast GenericSpanContext -// references down to the installed SpanContext implementation. Doing so allows -// access to methods/members that would be otherwise inaccessible through the -// base class interface. This is a useful tool when implementing inject/extract -// in Tracers. template class GenericSpanContext { public: - typedef CONTEXT SpanContext; - typedef ADAPTER BaggageAdapter; - typedef BaggageIterator const_iterator; + typedef CONTEXT SpanContext; + typedef ADAPTER BaggageAdapter; + typedef BaggageIteratorImp BaggageIterator; + typedef BaggageRangeImp BaggageRange; + + typedef std::string BaggageValue; + typedef std::vector BaggageValues; - const_iterator begin() const; + BaggageIterator baggageBegin() const; // Return a BaggageIterator to the beginning of the Baggage maintained // by this SpanContext. - const_iterator end() const; - // Return a BaggageIterator to mark the end of the baggage maintained + BaggageIterator baggageEnd() const; + // Return a BaggageIterator to mark the end of the Baggage maintained // by this SpanContext. - int setBaggage(const StringRef& key, const StringRef& baggage); - // Associate the supplied 'key' with the 'baggage'. Returns 0 upon - // success and a non-zero value otherwise. + BaggageRange baggageRange() const; + // Return a structure containing the range of iterators: + // [baggageBegin, baggageEnd). The object supports range-based for loops. + + int setBaggage(const StringRef &key, const StringRef &baggage); + // Set or append the single 'baggage' value for the given 'key'. Return 0 + // upon success and a non-zero value otherwise. + + int getBaggage(BaggageValue *const baggage, const StringRef &key) const; + // Load a single 'baggage' value associated with 'key'. Returns 0 if there + // is only one value associated with 'key' and that value was loaded + // succesfully. Return a non-zero value otherwise. - int getBaggage(StringRef* const baggage, const StringRef& key) const; + int getBaggage(BaggageValues *const baggage, const StringRef &key) const; // Load the 'baggage' associated with 'key'. Returns 0 if the // baggage is loaded succesfully, and a non-zero value otherwise. protected: GenericSpanContext(); - GenericSpanContext(const GenericSpanContext&); + GenericSpanContext(const GenericSpanContext &); // Protected to avoid direct construction }; @@ -128,44 +93,61 @@ class GenericSpanContext { // ------------------------ template -GenericSpanContext::GenericSpanContext() +inline GenericSpanContext::GenericSpanContext() { } template -GenericSpanContext::GenericSpanContext( - const GenericSpanContext&) +inline GenericSpanContext::GenericSpanContext( + const GenericSpanContext &) { } template -typename GenericSpanContext::const_iterator -GenericSpanContext::begin() const +inline typename GenericSpanContext::BaggageIterator +GenericSpanContext::baggageBegin() const { - return const_iterator(static_cast(this)->beginImp()); + return BaggageIterator( + static_cast(this)->baggageBeginImp()); } template -typename GenericSpanContext::const_iterator -GenericSpanContext::end() const +inline typename GenericSpanContext::BaggageIterator +GenericSpanContext::baggageEnd() const { - return const_iterator(static_cast(this)->endImp()); + return BaggageIterator(static_cast(this)->baggageEndImp()); } template -int -GenericSpanContext::setBaggage(const StringRef& key, - const StringRef& baggage) +inline typename GenericSpanContext::BaggageRange +GenericSpanContext::baggageRange() const { - return static_cast(this)->setBaggageImp(key, baggage); + return BaggageRange(baggageBegin(), baggageEnd()); } template -int -GenericSpanContext::getBaggage(StringRef* const baggage, - const StringRef& key) const +inline int +GenericSpanContext::setBaggage(const StringRef &key, + const StringRef &baggage) { - return static_cast(this)->getBaggageImp(baggage, key); + return static_cast(this)->setBaggageImp(key, baggage); } + +template +inline int +GenericSpanContext::getBaggage(BaggageValue *const baggage, + const StringRef &key) const +{ + return static_cast(this)->getBaggageImp(baggage, key); +} + +template +inline int +GenericSpanContext::getBaggage(BaggageValues *const baggage, + const StringRef &key) const +{ + return static_cast(this)->getBaggageImp(baggage, key); +} + } // namespace opentracing #endif // INCLUDED_OPENTRACING_SPANCONTEXT_H diff --git a/opentracing/spanoptions.h b/opentracing/spanoptions.h new file mode 100644 index 0000000..7ba9722 --- /dev/null +++ b/opentracing/spanoptions.h @@ -0,0 +1,97 @@ +#ifndef INCLUDED_OPENTRACING_SPANOPTIONS_H +#define INCLUDED_OPENTRACING_SPANOPTIONS_H + +// ============= +// spanoptions.h +// ============= +// class SpanRelationship - Enumeration for Span relationship types +// class GenericSpanOptions - CRTP interface for SpanOptions + +#include + +#include +#if HAVE_STDINT_H +#include +#endif + +namespace opentracing { + +// ====================== +// class SpanRelationship +// ====================== +// 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. +// +// * 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. +// +// * 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 SpanRelationship { + public: + enum Value + { + e_ChildOf = 0, + e_FollowsFrom = 1 + }; +}; + +// ======================== +// class GenericSpanOptions +// ======================== +// This class defines the interface that clients can use to configure how a +// Span is created. These options are passed to the Tracer through the +// 'Tracer::start(const SpanOptions&)` method.. + +template +class GenericSpanOptions { + public: + typedef GenericSpanContext SpanContext; + + void setOperation(const StringRef&); + // Set the operation name to be used for any Span created with these + // options. + + void setStartTime(const uint64_t); + // Set the start time from this span. If start time is not supplied, the + // default is to use the current wall-time. + + void addReference(const SpanRelationship::Value relationship, + const SpanContext& context); + // A new Span created with these options would have a 'relationship' + // referenced added for 'context'. +}; + +// ------------------------ +// class GenericSpanOptions +// ------------------------ + +template +inline void +GenericSpanOptions::setOperation(const StringRef& op) +{ + static_cast(this)->setOperationImp(op); +} + +template +inline void +GenericSpanOptions::setStartTime(const uint64_t tsp) +{ + static_cast(this)->setStartTimeImp(tsp); +} + +template +inline void +GenericSpanOptions::addReference( + const SpanRelationship::Value rel, const SpanContext& context) +{ + const CONTEXT& contextImp = static_cast(context); + static_cast(this)->addReferenceImp(rel, contextImp); +} + +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_SPANOPTIONS_H diff --git a/opentracing/stringref.h b/opentracing/stringref.h index ddce810..98a2dba 100644 --- a/opentracing/stringref.h +++ b/opentracing/stringref.h @@ -18,10 +18,15 @@ // See the boost documentation for more background: // http://www.boost.org/doc/libs/master/libs/utility/doc/html/string_ref.html -#include #include #include #include +#include + +#include +#if HAVE_STDING_H +#include +#endif namespace opentracing { @@ -96,10 +101,23 @@ class StringRefImp { // -------- // Typedefs // -------- - typedef StringRefImp StringRef; typedef StringRefImp StringRefWide; +// ----- +// 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 implmentation 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 StringRefImp // ------------------ @@ -191,9 +209,19 @@ inline size_t StringRefImp::getLength(const CHAR* s) { const CHAR* p = s; - while (*p) ++p; + while (*p) + { + ++p; + } return size_t(p - s); } } // 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/tracer.h b/opentracing/tracer.h index 70a0c2b..b6a7880 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -1,29 +1,117 @@ #ifndef INCLUDED_OPENTRACING_TRACER_H #define INCLUDED_OPENTRACING_TRACER_H -#include - -#ifdef HAVE_STDINT_H -#include -#endif +// ======== +// tracer.h +// ======== +// class GenericTracer - CRTP interface for the Tracer #include #include +#include #include +#include +#ifdef HAVE_STDINT_H +#include +#endif + namespace opentracing { -template +// =================== +// class GenericTracer +// =================== +// GenericTracer is a static, polymorphic interface for interacting with +// the installed Tracer implementation. It uses the Curiously Repeating Template +// Pattern (CRTP) to avoid v-table hits we would encounter with traditional +// polymorphism. +// +// See this CRTP article for more details on the design pattern: +// https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern +// +// The GenericTracer acts as a factory for the other OpenTracing types. It has +// the most functionality, and also requires the most details to be instantiated +// appropriately at compile time. As such, it has the most template parameters, +// giving it access to otherwise unknowable details, at compile time. +// +// The template parameters are: +// * TRACER - A Tracer implementation (CRTP) +// * SPAN - A Span implementation (CRTP) +// * OPTIONS - A SpanOptions implementation (CRTP) +// * CONTEXT - A SpanContext implementation (CRTP) +// * ADAPTER - A Baggage iterator adapter +// +// The Tracer also exposes a set of typedefs which obfuscate the details of +// the implementation. These typedefs make it possible for clients to +// rely on the installed implementation, without having to know about any of the +// underlying types. +// +// * Span - Aliasing GenericSpan +// * SpanContext - Aliasing GenericSpanContex +// * SpanOptions - Aliasing GenericSpanOptions +// +// TRACER implementations must support the following: +// +// class TracerImp : +// GenericTracer +// { +// public: +// Options * makeSpanOptionsImp(); +// void cleanupImp(const Options * const opts); +// +// SpanImp * start(const StringRef& op); +// SpanImp * start(const OptionsImp& opts); +// void cleanupImp(const SpanImp * const sp); +// +// template +// int injectImp( +// GenericTextWriter* const carrier, +// const ContextImp& context) const; +// +// template +// int injectImp( +// GenericBinaryWriter* const carrier, +// const ContextImp& context) const; +// +// template +// int injectImp( +// GenericWriter* const carrier, +// const ContextImp& context) const; +// +// template +// const ContextImp* extractImp( +// const GenericTextReader& carrier); +// +// template +// const ContextImp* extractImp( +// const GenericBinaryReader& carrier); +// +// template +// const ContextImp* extractImp( +// const GenericReader& carrier); +// +// void cleanupImp(const ContextImp * const); +// }; + +template class GenericTracer { public: typedef GenericSpan Span; typedef GenericSpanContext SpanContext; + typedef GenericSpanOptions SpanOptions; + // Public typedefs used by clients to use underlying implementation + // interfaces reliably. These must exist in order to support O(1) compile + // time changes of the Tracer implementations. static void install(GenericTracer* const tracer); // Install Tracer to be referenced globally with calls to 'instance()'. // This method is not thread safe. It should be called once, in main, before // any other thread or trace work is performed. Undefined behavior if called - // otherwise. + // differently. static void uninstall(); // Uninstall a previously installed Tracer. This method is not thread safe, @@ -35,84 +123,79 @@ class GenericTracer { // tracer has not been previously installed. It is undefined behavior // to call this method without previously calling 'install()'. + SpanOptions* makeSpanOptions(); + // This is a factory method to create SpanOptions. Options can be passed + // to 'start()' to control how Spans are created. Options should be + // subsequently cleaned up with a call to 'cleanup()' Returns NULL on + // failure. + + void cleanup(SpanOptions* const opts); + // All SpanOptions pointers returned by the Tracer via 'makeSpanOptions()' + // must be passed back to the Tracer when client's are done with them via + // 'cleanup()'. + Span* start(const StringRef& op); - Span* start(const StringRef& op, const SpanContext& parent); - - template - Span* start(const StringRef& op, const ITER& pbegin, const ITER& pend); - - Span* start(const StringRef& op, const uint64_t tsp); - Span* start(const StringRef& op, - const SpanContext& parent, - const uint64_t tsp); - - template - Span* start(const StringRef& op, - const ITER& pbegin, - const ITER& pend, - const uint64_t tsp); - // The 'start' methods are used to create a new Span. The only required - // parameter is the operation string 'op', which should describe the work - // being performed during the span. + Span* start(const SpanOptions& opts); + // The 'start()' functions are factory methods to create a new Span. The + // only required parameter is the operation string 'op', which should + // describe the work being performed during the span. // - // The optional arguments are: - // parent: - // Establish the new Span as a child of the supplied parent + // Optional arguments are encapsulated in the 'opts' argument. Those options + // can be used to modify the start time, set the operation name, and/or + // establish the causal relationship between other Spans. // - // pbegin/pend: - // Supply a range of iterators, which when dereferenced refer to - // a SpanContext&. The new span would be a child of all of the - // supplied parents Spans. - // - // tsp: - // The time-stamp marking the start of the new Span. 'tsp' should - // represent the number of microseconds that have elapsed since - // the Unix epoch. + // Returns NULL on error. - void cleanup(Span *const sp); - // All Span pointers returned by the Tracer should be passed back - // to the Tracer when client's are done with them via 'cleanup()'. + void cleanup(Span* const sp); + // All Span pointers returned by the Tracer via 'start()' must be passed + // back to the Tracer when clients are done with them via 'cleanup()'. template int inject(GenericTextWriter* const carrier, - const SpanContext& context) const; + const SpanContext& context) const; // Inject the supplied 'context' into the text map writer 'carrier'. + // Returns 0 upon success and a non-zero value otherwise. template int inject(GenericBinaryWriter* const carrier, - const SpanContext& context) const; + const SpanContext& context) const; // Inject the supplied 'context' into the binary writer 'carrier'. + // Returns 0 upon success and a non-zero value otherwise. template int inject(GenericWriter* const carrier, const SpanContext& context) const; // Inject the SpanContext directly into the specialized 'carrier'. + // Returns 0 upon success and a non-zero value otherwise. // - // Note: The carrier will be passed the SpanContext directly. - // Using this may make your carrier code more efficient, but, it - // removes flexibility if you want to swap Tracer/Span - // implementations. + // Note: The carrier will be passed the SpanContext directly. Using this may + // make your carrier code more efficient, but, it removes flexibility if you + // want to swap Tracer/Span implementations. template - SpanContext* extract(const GenericTextReader& carrier); - // Extract the supplied 'context' from the text map reader 'carrier'. + const SpanContext* extract(const GenericTextReader& carrier); + // Extract the read-only supplied 'context' from the text map reader + // 'carrier' upon success, and NULL otherwise. Returns NULL on error. template - SpanContext* extract(const GenericBinaryReader& carrier); - // Extract the supplied 'context' from the binary reader 'carrier'. + const SpanContext* extract(const GenericBinaryReader& carrier); + // Extract the read-only SpanContext from the binary reader 'carrier' + // upon success, and NULL otherwise. Returns NULL on error. template - SpanContext* extract(const GenericReader& carrier); - // Extract the SpanContext from the specialized 'carrier'. + const SpanContext* extract(const GenericReader& carrier); + // Extract the read-only SpanContext from the specialized 'carrier'. Returns + // NULL on error. // // Note: The carrier will be passed the SpanContext directly. // Using this may make your carrier code more efficient, but, it // removes flexibility if you want to swap Tracer/Span implementations // later. - void cleanup(SpanContext* const sp); - // All SpanContext pointers returned by the Tracer should be passed back - // to the Tracer when client's are done with them via 'cleanup()'. + void cleanup(const SpanContext* const sp); + // All SpanContext pointers created by the Tracer through 'extract()' should + // be passed back to the Tracer when client's are done with them via + // 'cleanup()'. protected: GenericTracer(); @@ -123,161 +206,227 @@ class GenericTracer { static GenericTracer* s_tracer; }; -template -GenericTracer* - GenericTracer::s_tracer = 0; - -template -void -GenericTracer::install( +template +GenericTracer* + GenericTracer::s_tracer = 0; + +template +inline void +GenericTracer::install( GenericTracer* const tracer) { s_tracer = tracer; } -template -void -GenericTracer::uninstall() +template +inline void +GenericTracer::uninstall() { s_tracer = 0; } -template -GenericTracer* -GenericTracer::instance() +template +inline GenericTracer* +GenericTracer::instance() { return s_tracer; } -template -GenericTracer::GenericTracer() +template +inline GenericTracer::GenericTracer() { } -template -GenericTracer::GenericTracer(const GenericTracer&) +template +inline GenericTracer::GenericTracer( + const GenericTracer&) { } -template -void -GenericTracer::cleanup(Span *const sp) -{ - return static_cast(this)->cleanupImp(sp); -} -template -void -GenericTracer::cleanup(SpanContext *const spc) -{ - return static_cast(this)->cleanupImp(spc); -} - -template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op) +template +inline typename GenericTracer::Span* +GenericTracer::start( + const StringRef& op) { return static_cast(this)->startImp(op); } -template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op, - const uint64_t tsp) +template +inline typename GenericTracer:: + SpanOptions* + GenericTracer::makeSpanOptions() { - return static_cast(this)->startImp(op, tsp); + return static_cast(this)->makeSpanOptionsImp(); } -template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op, - const SpanContext& parent) +template +inline void +GenericTracer::cleanup( + SpanOptions* const opts) { - return static_cast(this)->startImp(op, parent); + OPTIONS* const optsImp = static_cast(opts); + return static_cast(this)->cleanupImp(optsImp); } -template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op, - const SpanContext& parent, - const uint64_t tsp) +template +inline typename GenericTracer::Span* +GenericTracer::start( + const SpanOptions& opts) { - return static_cast(this)->startImp(op, parent, tsp); + const OPTIONS& optsImp = static_cast(opts); + return static_cast(this)->startImp(opts); } -template -template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op, - const ITER& begin, - const ITER& end) +template +inline void +GenericTracer::cleanup(Span* const sp) { - return static_cast(this)->startImp(op, begin, end); + SPAN* const spanImp = static_cast(sp); + return static_cast(this)->cleanupImp(spanImp); } -template -template -typename GenericTracer::Span* -GenericTracer::start(const StringRef& op, - const ITER& begin, - const ITER& end, - const uint64_t tsp) -{ - return static_cast(this)->startImp(op, begin, end, tsp); -} - -template +template template -int -GenericTracer::inject( +inline int +GenericTracer::inject( GenericTextWriter* const carrier, const SpanContext& context) const { - return static_cast(this)->injectImp(carrier, context); + const CONTEXT& contextImp = static_cast(context); + return static_cast(this)->injectImp(carrier, contextImp); } -template +template template -typename GenericTracer::SpanContext* -GenericTracer::extract( - const GenericTextReader& carrier) +inline int +GenericTracer::inject( + GenericBinaryWriter* const carrier, + const SpanContext& context) const { - return static_cast(this)->extractImp(carrier); + const CONTEXT& contextImp = static_cast(context); + return static_cast(this)->injectImp(carrier, contextImp); } -template +template template -int -GenericTracer::inject( - GenericBinaryWriter* const carrier, const SpanContext& context) const +inline int +GenericTracer::inject( + GenericWriter* const carrier, + const SpanContext& context) const { - return static_cast(this)->injectImp(carrier, context); + const CONTEXT& contextImp = static_cast(context); + return static_cast(this)->injectImp(carrier, contextImp); } -template +template template -typename GenericTracer::SpanContext* -GenericTracer::extract( - const GenericBinaryReader& carrier) +inline const typename GenericTracer:: + SpanContext* + GenericTracer::extract( + const GenericTextReader& carrier) { return static_cast(this)->extractImp(carrier); } -template +template template -int -GenericTracer::inject( - GenericWriter* const carrier, - const SpanContext& context) const +inline const typename GenericTracer:: + SpanContext* + GenericTracer::extract( + const GenericBinaryReader& carrier) { - return static_cast(this)->injectImp(carrier, context); + return static_cast(this)->extractImp(carrier); } -template +template template -typename GenericTracer::SpanContext* -GenericTracer::extract( - const GenericReader& carrier) +inline const typename GenericTracer:: + SpanContext* + GenericTracer::extract( + const GenericReader& carrier) { return static_cast(this)->extractImp(carrier); } + +template +inline void +GenericTracer::cleanup( + const SpanContext* const spc) +{ + const CONTEXT* const contextImp = static_cast(spc); + return static_cast(this)->cleanupImp(contextImp); } -#endif + +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_TRACER_H diff --git a/test/Makefile b/test/Makefile index 261fa3c..af73ce9 100644 --- a/test/Makefile +++ b/test/Makefile @@ -23,7 +23,7 @@ LDIR =${GTEST_LIBS} LIBS=-L${GTEST_LIBS} -lgtest -lpthread -_OBJ = noop.t.o tracer.t.o carriers.t.o span.t.o spancontext.t.o baggage.t.o stringref.t.o unittest.t.o +_OBJ = stringref.t.o baggage.t.o spancontext.t.o span.t.o carriers.t.o tracer.t.o noop.t.o unittest.t.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) $(ODIR)/%.o: %.cc %.h ${OPENTRACING_SRC} diff --git a/test/baggage.t.cc b/test/baggage.t.cc index 1d6a98b..8bfda73 100644 --- a/test/baggage.t.cc +++ b/test/baggage.t.cc @@ -67,67 +67,6 @@ TEST(Baggage, ConstBehaviorThroughDeref) ASSERT_EQ("banana", b->value()); } -TEST(BaggageWide, Constructor) -{ - BaggageWide b; - ASSERT_EQ(L"", b.key()); - ASSERT_EQ(L"", b.value()); -} - -TEST(BaggageWide, CopyConstructor) -{ - BaggageWide b(L"apple", L"banana"); - BaggageWide cp(b); - - ASSERT_EQ(L"apple", cp.key()); - ASSERT_EQ(L"banana", cp.value()); -} - -TEST(BaggageWide, Assignment) -{ - BaggageWide b(L"apple", L"banana"); - BaggageWide cp; - cp = b; - - ASSERT_EQ(L"apple", cp.key()); - ASSERT_EQ(L"banana", cp.value()); -} - -TEST(BaggageWide, Manipulate) -{ - BaggageWide b(L"apple", L"banana"); - b.key() = L"cranberry"; - b.value() = L"dates"; - - ASSERT_EQ(L"cranberry", b.key()); - ASSERT_EQ(L"dates", b.value()); -} - -TEST(BaggageWide, ManipulateThroughDeref) -{ - BaggageWide b(L"apple", L"banana"); - b->key() = L"cranberry"; - b->value() = L"dates"; - - ASSERT_EQ(L"cranberry", b.key()); - ASSERT_EQ(L"dates", b.value()); -} - -TEST(BaggageWide, ConstBehavior) -{ - const BaggageWide b(L"apple", L"banana"); - - ASSERT_EQ(L"apple", b.key()); - ASSERT_EQ(L"banana", b.value()); -} - -TEST(BaggageWide, ConstBehaviorThroughDeref) -{ - const BaggageWide b(L"apple", L"banana"); - - ASSERT_EQ(L"apple", b->key()); - ASSERT_EQ(L"banana", b->value()); -} TEST(BaggageRef, Constructor) { @@ -176,106 +115,53 @@ class MapBaggage { typedef Map::iterator iterator; typedef Map::const_iterator const_iterator; - Baggage narrow(const Map::const_iterator& iter) const + Baggage copy(const Map::const_iterator& iter) const { return Baggage(iter->first, iter->second); } - BaggageWide wide(const Map::const_iterator& iter) const - { - std::wstring first; - std::wstring second; - - test_widen(&first, iter->first); - test_widen(&second, iter->second); - - return BaggageWide(first, second); - } BaggageRef ref(const Map::const_iterator& iter) const { return BaggageRef(iter->first, iter->second); } }; -TEST(BaggageIterator, NarrowAdapter) -{ - MapBaggage::Map m; - m["animal"] = "dog"; - m["fruit"] = "apple"; - m["veggie"] = "carrot"; - - BaggageIterator it(m.begin()); - BaggageIterator end(m.end()); - - ASSERT_FALSE(end == it); - Baggage narrow = it.narrow();; - - ASSERT_EQ("animal", narrow.key()); - ASSERT_EQ("dog", narrow.value()); - - BaggageIterator prev = it++; - ASSERT_FALSE(prev == end); - ASSERT_FALSE(it == end); - - narrow = prev.narrow(); - - ASSERT_EQ("animal", narrow.key()); - ASSERT_EQ("dog", narrow.value()); - - narrow = it.narrow(); - - ASSERT_EQ("fruit", narrow.key()); - ASSERT_EQ("apple", narrow.value()); - - ++it; - ASSERT_FALSE(end == it); - - narrow = it.narrow(); - - ASSERT_EQ("veggie", narrow.key()); - ASSERT_EQ("carrot", narrow.value()); - - ++it; - - ASSERT_TRUE(end == it); -} - -TEST(BaggageIterator, WideAdapter) +TEST(BaggageIterator, CopyAdapter) { MapBaggage::Map m; m["animal"] = "dog"; m["fruit"] = "apple"; m["veggie"] = "carrot"; - BaggageIterator it(m.begin()); - BaggageIterator end(m.end()); + BaggageIteratorImp it(m.begin()); + BaggageIteratorImp end(m.end()); ASSERT_FALSE(end == it); - BaggageWide wide = it.wide(); + Baggage copy = it.copy();; - ASSERT_EQ(L"animal", wide.key()); - ASSERT_EQ(L"dog", wide.value()); + ASSERT_EQ("animal", copy.key()); + ASSERT_EQ("dog", copy.value()); - BaggageIterator prev = it++; + BaggageIteratorImp prev = it++; ASSERT_FALSE(prev == end); ASSERT_FALSE(it == end); - wide = prev.wide(); + copy = prev.copy(); - ASSERT_EQ(L"animal", wide.key()); - ASSERT_EQ(L"dog", wide.value()); + ASSERT_EQ("animal", copy.key()); + ASSERT_EQ("dog", copy.value()); - wide = it.wide(); + copy = it.copy(); - ASSERT_EQ(L"fruit", wide.key()); - ASSERT_EQ(L"apple", wide.value()); + ASSERT_EQ("fruit", copy.key()); + ASSERT_EQ("apple", copy.value()); ++it; ASSERT_FALSE(end == it); - wide = it.wide(); + copy = it.copy(); - ASSERT_EQ(L"veggie", wide.key()); - ASSERT_EQ(L"carrot", wide.value()); + ASSERT_EQ("veggie", copy.key()); + ASSERT_EQ("carrot", copy.value()); ++it; @@ -289,8 +175,8 @@ TEST(BaggageIterator, RefAdapter) m["fruit"] = "apple"; m["veggie"] = "carrot"; - BaggageIterator it(m.begin()); - BaggageIterator end(m.end()); + BaggageIteratorImp it(m.begin()); + BaggageIteratorImp end(m.end()); ASSERT_FALSE(end == it); BaggageRef ref = it.ref(); @@ -298,7 +184,7 @@ TEST(BaggageIterator, RefAdapter) ASSERT_STREQ("animal", ref.key()); ASSERT_STREQ("dog", ref.value()); - BaggageIterator prev = it++; + BaggageIteratorImp prev = it++; ASSERT_FALSE(prev == end); ASSERT_FALSE(it == end); @@ -333,8 +219,8 @@ TEST(BaggageIterator, Implicit) m["fruit"] = "apple"; m["veggie"] = "carrot"; - BaggageIterator it(m.begin()); - BaggageIterator end(m.end()); + BaggageIteratorImp it(m.begin()); + BaggageIteratorImp end(m.end()); ASSERT_FALSE(end == it); BaggageRef ref = *it; @@ -342,7 +228,7 @@ TEST(BaggageIterator, Implicit) ASSERT_STREQ("animal", ref.key()); ASSERT_STREQ("dog", ref.value()); - BaggageIterator prev = it++; + BaggageIteratorImp prev = it++; ASSERT_FALSE(prev == end); ASSERT_FALSE(it == end); @@ -375,8 +261,8 @@ TEST(BaggageIterator, EmptyMapBaggage) { MapBaggage::Map m; - BaggageIterator it(m.begin()); - BaggageIterator end(m.end()); + BaggageIteratorImp it(m.begin()); + BaggageIteratorImp end(m.end()); ASSERT_TRUE(end == it); } @@ -392,7 +278,7 @@ TEST(BaggageIterator, ForLoopSyntax) const char * expectedVals[] = {"dog", "apple", "carrot"}; size_t index = 0; - for (BaggageIterator it = m.begin(), end = m.end(); it != end; + for (BaggageIteratorImp it = m.begin(), end = m.end(); it != end; ++it, ++index) { // Test the -> syntax works diff --git a/test/carriers.h b/test/carriers.h index 1439f4a..11e187d 100644 --- a/test/carriers.h +++ b/test/carriers.h @@ -71,7 +71,7 @@ struct TestWriter : public GenericWriter return 0; } - std::map carrier; + std::multimap carrier; }; struct TestReader : public GenericReader @@ -82,7 +82,7 @@ struct TestReader : public GenericReader return 0; } - std::map carrier; + std::multimap carrier; }; typedef GenericTextWriter TextWriter; diff --git a/test/carriers.t.cc b/test/carriers.t.cc index bb9fbe7..95da1d1 100644 --- a/test/carriers.t.cc +++ b/test/carriers.t.cc @@ -112,17 +112,30 @@ TEST(Carriers, ExplicitWriter) ASSERT_EQ(0, rc); ASSERT_EQ(3u, imp.carrier.size()); - ASSERT_EQ(imp.carrier["animal"], "dog"); - ASSERT_EQ(imp.carrier["fruit"], "apple"); - ASSERT_EQ(imp.carrier["veggie"], "carrot"); + + TestBaggageContainer::const_iterator it = + imp.carrier.find("animal"); + + ASSERT_NE(imp.carrier.end(), it); + ASSERT_EQ("dog", it->second); + + it = imp.carrier.find("fruit"); + ASSERT_NE(imp.carrier.end(), it); + ASSERT_EQ("apple", it->second); + + it = imp.carrier.find("veggie"); + ASSERT_NE(imp.carrier.end(), it); + ASSERT_EQ("carrot", it->second); } TEST(Carriers, ExplicitReader) { + typedef TestBaggageContainer Map; + TestReader imp; - imp.carrier["animal"] = "dog"; - imp.carrier["fruit"] = "apple"; - imp.carrier["veggie"] = "carrot"; + imp.carrier.insert(Map::value_type("animal", "dog")); + imp.carrier.insert(Map::value_type("fruit", "apple")); + imp.carrier.insert(Map::value_type("veggie", "carrot")); ExplicitReader& t = imp; @@ -130,11 +143,11 @@ TEST(Carriers, ExplicitReader) int rc = t.extract(&context); ASSERT_EQ(0, rc); - const std::map& m = context.baggageMap(); + TestBaggageContainer& m = context.baggageMap(); ASSERT_EQ(3u, m.size()); - std::map::const_iterator it = m.find("animal"); + TestBaggageContainer::const_iterator it = m.find("animal"); ASSERT_NE(m.end(), it); ASSERT_EQ(it->second, "dog"); diff --git a/test/noop.t.cc b/test/noop.t.cc index 6d85afb..fd61492 100644 --- a/test/noop.t.cc +++ b/test/noop.t.cc @@ -11,9 +11,16 @@ typedef GenericSpanContext GlobalContext; typedef GenericSpan GlobalSpan; -typedef GenericTracer GlobalTracer; +typedef GenericSpanOptions GlobalOptions; +typedef GenericTracer + GlobalTracer; typedef GenericSpanGuard SpanGuard; +typedef GenericSpanOptionsGuard SpanOptionsGuard; typedef GenericSpanContextGuard SpanContextGuard; TEST(NoopTracer, Intantiation){ @@ -45,21 +52,31 @@ TEST(NoopTracer, StartWithOp) rc = guard.sp->context().setBaggage("apple", "banana"); ASSERT_EQ(0, rc); - StringRef ref; - rc = guard.sp->context().getBaggage(&ref, "apple"); + GlobalTracer::SpanContext::BaggageValue val; + rc = guard.sp->context().getBaggage(&val, "apple"); ASSERT_NE(0, rc); } TEST(NoopTracer, StartWithOpAndTsp) { + NoopContext otherContextImp; + GlobalContext& othercontext = otherContextImp; + NoopTracer imp; GlobalTracer& t = imp; - SpanGuard guard(&t, t.start("hello", 125125)); + SpanOptionsGuard optsguard(&t, t.makeSpanOptions()); + + optsguard.sp->setOperation("hello"); + optsguard.sp->setStartTime(1251251); + optsguard.sp->addReference(SpanRelationship::e_FollowsFrom, othercontext); + + SpanGuard guard(&t, t.start("hello")); EXPECT_TRUE(guard.sp); } +/* TEST(NoopTracer, StartWithOpAndParent) { // We create spans, which have contexts or create contexts directly @@ -282,3 +299,4 @@ TYPED_TEST(NoopSpanTypeTests, LogTspInterface) int rc = t.log("key", TypeParam(), 0); ASSERT_EQ(0, rc); } +*/ diff --git a/test/span.h b/test/span.h index 3617b2e..42cb6ec 100644 --- a/test/span.h +++ b/test/span.h @@ -1,8 +1,8 @@ #ifndef INCLUDED_OPENTRACING_TEST_SPAN_H #define INCLUDED_OPENTRACING_TEST_SPAN_H -#include "unittest.h" #include "spancontext.h" +#include "unittest.h" #include // test include guard #include @@ -11,251 +11,59 @@ class TestSpanImpl : public GenericSpan { public: - TestContextImpl& contextImp() { + TestContextImpl& + contextImp() + { return d_context; } - const TestContextImpl& contextImp() const { + const TestContextImpl& + contextImp() const + { return d_context; } int - finishImp() + setOperationImp(const StringRef&) { return 0; } int - finishImp(const uint64_t ) + addReferenceImp(const TestContextImpl&, const SpanRelationship::Value) { return 0; } int - tagImp(const StringRef&, const StringRef&) + finishImp() { return 0; } int - tagImp(const StringRef&, const bool) + finishImp(const uint64_t) { return 0; } + template int - tagImp(const StringRef&, const float) - { - return 0; - } - int - tagImp(const StringRef&, const double) - { - return 0; - } - int - tagImp(const StringRef&, const long double) - { - return 0; - } - int - tagImp(const StringRef&, const char) - { - return 0; - } - int - tagImp(const StringRef&, const signed char) - { - return 0; - } - int - tagImp(const StringRef&, const unsigned char) - { - return 0; - } - int - tagImp(const StringRef&, const wchar_t) - { - return 0; - } - int - tagImp(const StringRef&, const int16_t) - { - return 0; - } - int - tagImp(const StringRef&, const int32_t) - { - return 0; - } - int - tagImp(const StringRef&, const int64_t) - { - return 0; - } - int - tagImp(const StringRef&, const uint16_t) - { - return 0; - } - int - tagImp(const StringRef&, const uint32_t) - { - return 0; - } - int - tagImp(const StringRef&, const uint64_t) + tagImp(const StringRef&, const T&) { return 0; } + template int - logImp(const StringRef&, const StringRef&) - { - return 0; - } - int - logImp(const StringRef&, const bool) - { - return 0; - } - int - logImp(const StringRef&, const float) - { - return 0; - } - int - logImp(const StringRef&, const double) - { - return 0; - } - int - logImp(const StringRef&, const long double) - { - return 0; - } - int - logImp(const StringRef&, const char) - { - return 0; - } - int - logImp(const StringRef&, const signed char) - { - return 0; - } - int - logImp(const StringRef&, const unsigned char) - { - return 0; - } - int - logImp(const StringRef&, const wchar_t) - { - return 0; - } - int - logImp(const StringRef&, const int16_t) - { - return 0; - } - int - logImp(const StringRef&, const int32_t) - { - return 0; - } - int - logImp(const StringRef&, const int64_t) - { - return 0; - } - int - logImp(const StringRef&, const uint16_t) - { - return 0; - } - int - logImp(const StringRef&, const uint32_t) - { - return 0; - } - int - logImp(const StringRef&, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const StringRef&, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const bool, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const float, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const double, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const long double, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const char, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const signed char, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const unsigned char, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const wchar_t, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const int16_t, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const int32_t, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const int64_t, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const uint16_t, const uint64_t) - { - return 0; - } - int - logImp(const StringRef&, const uint32_t, const uint64_t) + logImp(const StringRef&, const T&) { return 0; } + + template int - logImp(const StringRef&, const uint64_t, const uint64_t) + logImp(const StringRef&, const T&, const uint64_t) { return 0; } diff --git a/test/span.t.cc b/test/span.t.cc index 9c98bbe..090d715 100644 --- a/test/span.t.cc +++ b/test/span.t.cc @@ -12,19 +12,19 @@ TEST(Span, BasicTests) // Make sure const references work const TestSpan& tc = impl; - StringRef ref; - rc = tc.context().getBaggage(&ref, "hello"); + TestSpan::SpanContext::BaggageValues vals; + rc = tc.context().getBaggage(&vals, "hello"); ASSERT_EQ(0, rc); - ASSERT_STREQ("world", ref); + ASSERT_EQ(1u, vals.size()); + ASSERT_EQ("world", vals[0]); const TestSpan::SpanContext& cc = tc.context(); - rc = cc.getBaggage(&ref, "miss"); - + rc = cc.getBaggage(&vals, "miss"); ASSERT_NE(0, rc); - TestSpan::SpanContext::const_iterator it = cc.begin(); - ASSERT_FALSE(it == cc.end()); + TestSpan::SpanContext::BaggageIterator it = cc.baggageBegin(); + ASSERT_FALSE(it == cc.baggageEnd()); } t.finish(); diff --git a/test/spancontext.h b/test/spancontext.h index 909421f..b2b5018 100644 --- a/test/spancontext.h +++ b/test/spancontext.h @@ -9,27 +9,19 @@ #include #include -typedef std::map TestBaggageContainer; +typedef std::multimap TestBaggageContainer; struct TestContextBaggageAdapter { typedef TestBaggageContainer::iterator iterator; typedef TestBaggageContainer::const_iterator const_iterator; - Baggage narrow(const const_iterator& it) const + Baggage + copy(const const_iterator& it) const { return Baggage(it->first, it->second); } - BaggageWide wide(const const_iterator& it) const - { - std::wstring key; - std::wstring value; - - test_widen(&key, it->first); - test_widen(&value, it->second); - - return BaggageWide(key, value); - } - BaggageRef ref(const const_iterator& it) const + BaggageRef + ref(const const_iterator& it) const { return BaggageRef(it->first, it->second); } @@ -38,27 +30,26 @@ struct TestContextBaggageAdapter { class TestContextImpl : public GenericSpanContext { public: - typedef GenericSpanContext Base; - int setBaggageImp(const StringRef& key, const StringRef& baggage) { - m_baggage[std::string(key.data(), key.length())] = - std::string(baggage.data(), baggage.length()); + m_baggage.insert(TestBaggageContainer::value_type( + std::string(key.data(), key.length()), + std::string(baggage.data(), baggage.length()))); return 0; } int - getBaggageImp(StringRef* const baggage, const StringRef& key) const + getBaggageImp(BaggageValue* const baggage, const StringRef& key) const { - const std::string mkey(key.data(), key.length()); + std::vector out; - const TestBaggageContainer::const_iterator it = m_baggage.find(mkey); + getBaggageImp(&out, key); - if (m_baggage.end() != it) + if (1u == out.size()) { - baggage->reset(it->second.data(), it->second.length()); + *baggage = out[0]; return 0; } else @@ -67,16 +58,38 @@ class TestContextImpl } } - Base::const_iterator - beginImp() const + int + getBaggageImp(BaggageValues* const baggage, const StringRef& key) const + { + baggage->clear(); + + const std::string mkey(key.data(), key.length()); + + const std::pair + range = m_baggage.equal_range(mkey); + + for (TestBaggageContainer::const_iterator it = range.first, + end = range.second; + it != end; + ++it) + { + baggage->push_back(it->second); + } + + return baggage->empty(); + } + + BaggageIterator + baggageBeginImp() const { - return Base::const_iterator(m_baggage.begin()); + return BaggageIterator(m_baggage.begin()); } - Base::const_iterator - endImp() const + BaggageIterator + baggageEndImp() const { - return Base::const_iterator(m_baggage.end()); + return BaggageIterator(m_baggage.end()); } TestBaggageContainer& diff --git a/test/spancontext.t.cc b/test/spancontext.t.cc index 5cb5d2e..2863e14 100644 --- a/test/spancontext.t.cc +++ b/test/spancontext.t.cc @@ -4,32 +4,39 @@ #include // test include guard #include -TEST(GenericSpanContext, Baggage) +TEST(GenericSpanContext, BaggageCopies) { TestContextImpl imp; TestContext& t = imp; int rc = t.setBaggage("hello", "world"); + ASSERT_EQ(0, rc); - StringRef ref; - rc = t.getBaggage(&ref, "hello"); + TestContext::BaggageValues vals; + rc = t.getBaggage(&vals, "hello"); ASSERT_EQ(0, rc); - ASSERT_STREQ("world", ref.data()); + ASSERT_EQ(1u, vals.size()); + ASSERT_EQ("world", vals[0]); - rc = t.getBaggage(&ref, "unknown"); + rc = t.getBaggage(&vals, "unknown"); ASSERT_NE(0, rc); - ASSERT_TRUE(t.begin() != t.end()); + ASSERT_TRUE(t.baggageBegin() != t.baggageEnd()); - TestContext::const_iterator it = t.begin(); + TestContext::BaggageIterator it = t.baggageBegin(); - ASSERT_STREQ("hello", it->key().data()); - ASSERT_STREQ("world", it->value().data()); + Baggage b = it.copy(); + ASSERT_EQ("hello", b.key()); + ASSERT_EQ("world", b.value()); ++it; - ASSERT_TRUE(it == t.end()); + ASSERT_TRUE(it == t.baggageEnd()); + + ASSERT_EQ("hello", b.key()); + ASSERT_EQ("world", b.value()); + } TEST(GenericSpanContext, CopyConstructor) @@ -43,9 +50,9 @@ TEST(GenericSpanContext, CopyConstructor) TestContextImpl implCopy = impl; TestContext& tc = implCopy; - StringRef ref; - rc = tc.getBaggage(&ref, "hello"); + TestContext::BaggageValue val; + rc = tc.getBaggage(&val, "hello"); ASSERT_EQ(0, rc); - ASSERT_STREQ("world", ref); + ASSERT_EQ("world", val); } diff --git a/test/tracer.h b/test/tracer.h index 44f3f84..4f36b15 100644 --- a/test/tracer.h +++ b/test/tracer.h @@ -9,94 +9,59 @@ #include "span.h" #include "spancontext.h" -class TestTracerImpl : public GenericTracer { +class TestOptionsImpl : public GenericSpanOptions { public: - Span* - startImp(const StringRef&) - { - return new TestSpanImpl(); - } - - Span* - startImp(const StringRef&, const uint64_t) + void + setOperationImp(const StringRef&) { - return new TestSpanImpl(); } - Span* - startImp(const StringRef&, const SpanContext&) + void + setStartTimeImp(const uint64_t) { - return new TestSpanImpl(); } - Span* - startImp(const StringRef&, const SpanContext&, const uint64_t) + void + addReferenceImp(const SpanRelationship::Value, const TestContextImpl&) { - return new TestSpanImpl(); } +}; - template +class TestTracerImpl : public GenericTracer { + public: Span* - startImp(const StringRef&, const ITER& pbegin, const ITER& pend) + startImp(const StringRef&) { - for (ITER it = pbegin; it != pend; ++it) - { - const TestContextImpl* ctx = static_cast(&(*it)); - // Output is ignored, but I want to flex the compiler here. Let's - // force - // a dereference to make sure the types are okay - - StringRef ref; - ctx->getBaggageImp(&ref, "hello"); - } return new TestSpanImpl(); } - template Span* - startImp(const StringRef&, - const ITER pbegin, - const ITER pend, - const uint64_t) + startImp(const TestOptionsImpl&) { - for (ITER it = pbegin; it != pend; ++it) - { - const TestContextImpl* ctx = static_cast(&(*it)); - - StringRef ref; - ctx->getBaggageImp(&ref, "hello"); - } - return new TestSpanImpl(); } - void - cleanupImp(Span* const sp) - { - delete static_cast(sp); - } void - cleanupImp(SpanContext* const spc) + cleanupImp(const TestSpanImpl* const sp) { - delete static_cast(spc); + delete sp; } template int injectImp(GenericTextWriter* const carrier, - const TestContext& context) const + const TestContextImpl& imp) const { - const TestContextImpl& imp = - static_cast(context); - std::vector pairs; pairs.reserve(imp.baggageMap().size()); - for (std::map::const_iterator it = - imp.baggageMap().begin(); + for (TestBaggageContainer::const_iterator it = imp.baggageMap().begin(); it != imp.baggageMap().end(); ++it) { @@ -107,7 +72,26 @@ class TestTracerImpl : public GenericTracer - SpanContext* + int + injectImp(GenericBinaryWriter* const carrier, + const TestContext&) const + { + // Context unused for test. Implementations should encode + // the context for a wire protocol here, most likely + const int deadbeef = 0xdeadbeef; + return carrier->inject(&deadbeef, sizeof(deadbeef)); + } + + template + int + injectImp(GenericWriter* const carrier, + const TestContextImpl& context) const + { + return carrier->inject(context); + } + + template + TestContextImpl* extractImp(const GenericTextReader& carrier) const { std::vector pairs; @@ -123,24 +107,14 @@ class TestTracerImpl : public GenericTracerbaggageMap()[it->m_name] = it->m_value; + imp->baggageMap().insert( + TestBaggageContainer::value_type(it->m_name, it->m_value)); } return imp; } template - int - injectImp(GenericBinaryWriter* const carrier, - const TestContext&) const - { - // Context unused for test. Implementations should encode - // the context for a wire protocol here, most likely - const int deadbeef = 0xdeadbeef; - return carrier->inject(&deadbeef, sizeof(deadbeef)); - } - - template - SpanContext* + TestContextImpl* extractImp(const GenericBinaryReader& carrier) { size_t written = 0; @@ -161,17 +135,11 @@ class TestTracerImpl : public GenericTracer - int - injectImp(GenericWriter* const carrier, - const TestContext& context) const - { - return carrier->inject(static_cast(context)); - } - - template - SpanContext* + TestContextImpl* extractImp(const GenericReader& carrier) { + // Should use a guard here and release it, iff, carrier has + // no errors. TestContextImpl* imp = new TestContextImpl; if (int rc = carrier.extract(imp)) { @@ -183,10 +151,22 @@ class TestTracerImpl : public GenericTracer + SpanOptions; + typedef GenericTracer Tracer; diff --git a/test/tracer.t.cc b/test/tracer.t.cc index 7c1ec1c..d2348d9 100644 --- a/test/tracer.t.cc +++ b/test/tracer.t.cc @@ -35,85 +35,36 @@ TEST(Tracer, StartWithOp) rc = guard.sp->context().setBaggage("apple", "banana"); ASSERT_EQ(0, rc); - StringRef ref; - rc = guard.sp->context().getBaggage(&ref, "apple"); + Tracer::SpanContext::BaggageValues vals; + rc = guard.sp->context().getBaggage(&vals, "apple"); ASSERT_EQ(0, rc); - ASSERT_STREQ("banana", ref); -} - -TEST(Tracer, StartWithOpAndTsp) -{ - TestTracerImpl imp; - Tracer& t = imp; - - SpanGuard guard(&t, t.start("hello", 125125)); - EXPECT_TRUE(guard.sp); -} - -TEST(Tracer, StartWithOpAndParent) -{ - // We create spans, which have contexts or create contexts directly - // through the 'extract' interface. Either way, clients only deal - // with the 'TestContext' type. Rather than make this simple start - // test dependent on those other interfaces, I'm going to just pull - // a context out of thin air to test the interface. - - TestContextImpl contextImp; - TestContext& context = contextImp; - - TestTracerImpl imp; - Tracer& t = imp; - - SpanGuard guard(&t, t.start("hello", context)); - EXPECT_TRUE(guard.sp); -} - -TEST(Tracer, StartWithOpAndParentAndTsp) -{ - // We create spans, which have contexts or create contexts directly - // through the 'extract' interface. Either way, clients only deal - // with the 'TestContext' type. Rather than make this simple start - // test dependent on those other interfaces, I'm going to just pull - // a context out of thin air to test the interface. + ASSERT_EQ(1u, vals.size()); + ASSERT_EQ("banana", vals[0]); - TestContextImpl contextImp; - TestContext& context = contextImp; + Tracer::SpanContext::BaggageValue val; + rc = guard.sp->context().getBaggage(&val, "apple"); - TestTracerImpl imp; - Tracer& t = imp; - - SpanGuard guard(&t, t.start("hello", context, 125125)); - EXPECT_TRUE(guard.sp); + ASSERT_EQ(0, rc); + ASSERT_EQ("banana", val); } -TEST(Tracer, StartWithOpAndMultipleParents) +TEST(Tracer, StartWithOptions) { - TestContextImpl contextImp1; - TestContextImpl contextImp2; - TestContextImpl contextImp3; + TestContextImpl otherContext; - std::vector contexts(3, TestContextImpl()); + TestOptionsImpl optsImp; TestTracerImpl imp; Tracer& t = imp; - SpanGuard guard(&t, t.start("hello", contexts.begin(), contexts.end())); - EXPECT_TRUE(guard.sp); -} - -TEST(Tracer, StartWithOpAndMultipleParentsAndTsp) -{ - TestContextImpl contextImp1; - TestContextImpl contextImp2; - TestContextImpl contextImp3; - - std::vector contexts(3, TestContextImpl()); + SpanOptions& opts = optsImp; - TestTracerImpl imp; - Tracer& t = imp; + opts.setOperation("test"); + opts.setStartTime(12414); + opts.addReference(SpanRelationship::e_ChildOf, otherContext); - SpanGuard guard(&t, t.start("hello", contexts.begin(), contexts.end(), 125125)); + SpanGuard guard(&t, t.start("hello")); EXPECT_TRUE(guard.sp); } @@ -133,11 +84,13 @@ TEST(Tracer, InjectText) int rc = t.inject(&writer, g.sp->context()); ASSERT_EQ(0, rc); - ASSERT_EQ(1u, writer.pairs.size()); - // Note there is no requirement that implementation make baggage keys - // unique, but the test suite does so its nice to verify that. + ASSERT_EQ(2u, writer.pairs.size()); + ASSERT_EQ(writer.pairs[0].m_name, "animal"); - ASSERT_EQ(writer.pairs[0].m_value, "cat"); + ASSERT_EQ(writer.pairs[1].m_name, "animal"); + + ASSERT_TRUE(writer.pairs[0].m_value == "cat" || writer.pairs[0].m_value == "tiger"); + ASSERT_TRUE(writer.pairs[1].m_value == "cat" || writer.pairs[1].m_value == "tiger"); } TEST(Tracer, ExtractText) @@ -159,7 +112,9 @@ TEST(Tracer, ExtractText) const char * names[] = {"animal", "fruit", "veggie"}; const char * values[] = {"tiger", "apple", "carrot"}; - for(Tracer::SpanContext::const_iterator it = g.sp->begin(); it != g.sp->end(); ++it) + for (Tracer::SpanContext::BaggageIterator it = g.sp->baggageBegin(); + it != g.sp->baggageEnd(); + ++it) { ASSERT_STREQ(names[index], it.ref().key()); ASSERT_STREQ(values[index], it.ref().value()); @@ -210,15 +165,22 @@ TEST(Tracer, InjectExplicit) ASSERT_EQ(0, rc); ASSERT_EQ(2u, w.carrier.size()); - ASSERT_EQ(w.carrier["animal"], "tiger"); - ASSERT_EQ(w.carrier["fruit"], "apple"); + + TestBaggageContainer::const_iterator cit = w.carrier.find("animal"); + + ASSERT_NE(cit, w.carrier.end()); + ASSERT_EQ("tiger", cit->second); + + cit = w.carrier.find("fruit"); + ASSERT_NE(cit, w.carrier.end()); + ASSERT_EQ("apple", cit->second); } TEST(Tracer, ExtractExplicit) { TestReader reader; - reader.carrier["animal"] = "tiger"; - reader.carrier["fruit"] = "apple"; + reader.carrier.insert(TestBaggageContainer::value_type("animal", "tiger")); + reader.carrier.insert(TestBaggageContainer::value_type("fruit", "apple")); TestTracerImpl imp; Tracer& t = imp; diff --git a/test/unittest.h b/test/unittest.h index a2cbd98..7cdfc86 100644 --- a/test/unittest.h +++ b/test/unittest.h @@ -34,9 +34,25 @@ struct GenericSpanGuard { typename TRACER::Span* sp; }; +template +struct GenericSpanOptionsGuard { + GenericSpanOptionsGuard(TRACER* tracer, typename TRACER::SpanOptions* s) + : t(tracer), sp(s) + { + } + ~GenericSpanOptionsGuard() + { + t->cleanup(sp); + } + + TRACER* t; + typename TRACER::SpanOptions* sp; +}; + template struct GenericSpanContextGuard { - GenericSpanContextGuard(TRACER* tracer, typename TRACER::SpanContext* s) + GenericSpanContextGuard(TRACER* tracer, + const typename TRACER::SpanContext* s) : t(tracer), sp(s) { } @@ -45,8 +61,8 @@ struct GenericSpanContextGuard { t->cleanup(sp); } - TRACER* t; - typename TRACER::SpanContext* sp; + TRACER* t; + const typename TRACER::SpanContext* sp; }; } From d42770ad4939c4948ac4b9c30ce1ab417fdd12ee Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 11:00:28 -0500 Subject: [PATCH 10/48] Updating documentation --- README.md | 27 +-- docs/usage.md | 244 +++++++++++++++++++++++++ opentracing/carriers.h | 404 ++++++++++++++++++++++++++++------------- 3 files changed, 542 insertions(+), 133 deletions(-) create mode 100644 docs/usage.md diff --git a/README.md b/README.md index fb6568e..deb8db4 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,12 @@ 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") @@ -22,16 +21,22 @@ libtoolize # or glibtoolize sudo 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)): +#### 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: ``` -cd test -make +cd ./thirdparty && ./build_gtest.sh +cd ../test && make ./test ``` ## 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` package do need to understand only the key abstractions of this API: + * Installing a Tracer implmementation in `main()` + * 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/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..3fc11e4 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,244 @@ +# opentracing-cpp + +This file describes how clients can instrument their applications with the `opentracing-cpp` +API. It assumes you have finished the required reading outlined [here](../README.md). + +### Outline + +The `opentracing-cpp` interface uses the [Curiously Repeating Template Pattern](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) (CRTP) to define a set of +compile time, polymorphic interfaces to `OpenTracing` implementations. + +In order to trace their systems, clients must: + * Select their `opentracing-cpp` implementation + * Install the selected `Tracer` in their applications in main + * Use the API's Tracer interface to instrument their applications requests + + +### Select the implementation + +`opentracing-cpp` only defines the interfaces. In order to make any use of the +API, you will need to install a concrete `Tracer` implementation. + +To do so, it is best practice to first create an reusable header you can share +throughout your organization that declares the implementation you will be using. + +This header should provide a few typedefs that make it easy to swap implementations +later. + +``` +// acme_tracing.h +#ifndef INCLUDED_ACME_TRACING +#define INCLUDED_ACME_TRACING + +// Include the interface templates +#include +#include +#include +#include + +// Include the chosen implementation +#include + +namespace acme { + typedef opentracing::GenericSpanContext< + opentracing::NoopContext, + opentracing::NoopAdapter> SpanContext; + + typedef opentracing::GenericSpanOptions< + opentracing::NoopOptions, + opentracing::NoopContext, + opentracing::NoopAdapter> SpanOptions; + + typedef opentracing::GenericSpan< + opentracing::NoopSpan, + opentracing::NoopContext, + opentracing::NoopAdapter> SpanContext; + + typedef opentracing::GenericTracer< + opentracing::NoopTracer, + opentracing::NoopSpan, + opentracing::NoopOptions, + opentracing::NoopContext, + opentracing::NoopAdapter> Tracer; + + typedef opentracing::NoopTracer TracerImpl; +} +#endif +``` + +The `SpanContext`, `SpanOptions`, `SpanContext`, and `Tracer` typedefs are now +the names that our theoretical "ACME Inc." organization can use to instrument +their applications. The names are not standardized, but these typedefs +are the recommended names, and will be used throughout the rest of this documentation. + +If clients ever require that they swap `OpenTracing` implementations, they +will need to update only this header file and rebuild applications. + +### Installing the Tracer + +Now that you have selected your chosen implementation, your applications can rely +on your global `opentracing-cpp` configuration header to set up the `Tracer`. +The `Tracer` implementation is installed explicitly as singleton in main. This must +be done before any other parts of the API can be used: + +``` +// acmetask.m.cpp +#include + +int main(int argc, const char * argv[]) +{ + acme::TracerImpl tracerImpl; + acme::Tracer::install(&tracerImpl); + + // ... + + return 0; +} + +``` + +### Creating Spans + +Once the `Tracer` is installed, we can begin to instrument the application. + +Say we have a service that acts as a proxy to a number of other HTTP servers. +We may have a `getAccount` handler that reaches out to the account service. + +We'll first need to start the span: + +``` +// requesthandler.m.cpp +#include + +int getAccount(Repsonse * resp, const Request& req) +{ + static Tracer * const s_tracer = Tracer::instance(); + + acme::Span * span = s_tracer->start("get_account"); + if(!span){ /* log error */; } + + // ... hanlding our request TBD + + // finish() signals the Tracer that we're done with this span + if(int rc = span.finish()) { /* log error */; } + + // Cleanup the span when we're finished. + s_tracer->cleanup(span); + + return 0; +} +``` + +### Defining carriers + +For this trace to be distributed across all of our organizations tasks, we need +a way to `inject` and `extract` the span into our RPC carriers. + +For our above example, when we make our request to the backend HTTP service, +we'll need a way to inject the details of the context into our HTTP request. + +``` +// For this example, we'll define our HttpWriter inline with our request. +// In practice, you'll want the Writers/Readers you use to be consistent +// across your organization, so putting them into a library would be +// ideal. + +#include + +class HttpWriter : public GenericBinaryWriter +{ + public: + HttpWriter(HttpRequest * req): m_req(req){} + + int injectImp(const void* blob, const_size len) + { + std::string blob(static_cast(blob), len); + req->addHeader("x-acme-tracing-blob", blob); + return 0; + } + + private: + HttpRequest * m_req; +}; + +int getAccount(Repsonse * resp, const Request& req) +{ + static Tracer * const s_tracer = Tracer::instance(); + + acme::Span * span = s_tracer->start("get_account"); + if(!span){ /* log error */; } + + HttpRequest httpRequest; + HttpWriter writer(&httpRequest); + s_tracer->inject(&writer, span->context()); + + // Business logic... + HttpResponse httpResponse; + sendHttpRequest(&httpResponse, httpRequest); + + // finish() signals the Tracer that we're done with this span + if(int rc = span.finish()) { /* log error */; } + + // Cleanup the span when we're finished. + s_tracer->cleanup(span); + + return 0; +} +``` + +On the HTTP servers end, we'll want to create another span as a child: + +``` +#include + +struct HttpReader: public GenericBinaryReader +{ + public: + int extractImp(void* const buf, size_t* const written, const size_t len) + { + std::string header = m_req.getHeader("x-acme-tracing-blob"); + + if (header.length() >= len) + { + return 1; + } + + std::memcpy(buf, header.data(), header.size()); + *written = header.size(); + return 0; + } + + private: + const HttpRequest& m_req; +}; + +int httpGetAccount(const HttpRequest& httpRequest) +{ + static Tracer* const s_tracer = Tracer::instance(); + + const acme::SpanContext* context = + s_tracer->extract(HttpReader(httpRequest)); + + acme::Span* span; + + if (!context) + { + span = s_tracer->start("get_account"); + } + else + { + acme::SpanOptions* opts = s_tracer->makeSpanOptions(); + opts->addReference(opentracing::SpanRelationship::e_childOf, *context); + opts->setOperation("get_account"); + span = s_tracer->start(*opts); + s_tracer->cleanup(opts); + } + + // Send back response to requester... + + span->finish(); + s_tracer->cleanup(span); + s_tracer->cleanup(context); + return 0; +} +``` diff --git a/opentracing/carriers.h b/opentracing/carriers.h index 76f2954..2a75a6e 100644 --- a/opentracing/carriers.h +++ b/opentracing/carriers.h @@ -1,20 +1,62 @@ #ifndef INCLUDED_OPENTRACING_CARRIERS_H #define INCLUDED_OPENTRACING_CARRIERS_H -#include - -#if HAVE_STDINT_H -#include -#endif +// ========== +// carriers.h +// ========== +// class TextMapPair - Struct of std::string name:value pairs +// +// class GenericTextWriter - CRTP interface for text map writers (inject) +// class GenericBinaryWriter - CRTP interface for binary writers (inject) +// class GenericWriter - CRTP interface for explicit writers (inject) +// +// class GenericTextReader - CRTP interface for text map readers (extract) +// class GenericBinaryReader - CRTP interface for binary readers (extract) +// class GenericReader - CRTP interface for explicit readers (extract) +// +// ======== +// Carriers +// ======== +// GenericTextWriter, GenericBinaryWriter, and GenericWriter are static, +// polymorphic interfaces used by the Tracer's 'inject()' interface. They +// are used to embed SpanContexts into a carrier object. Those carrier +// objects are passed between process boundaries by applications as a part +// of their existing message passing infrastructure. +// +// When an RPC call is received, the SpanContext can be 'extract()'ed by +// the Tracer using the GenericTextReader, GenericBinaryReader, or GenericReader +// interfaces. If the readers are succesful, an immutable SpanContext is +// returned to applications. That SpanContext can then be used to create +// new spans, accessing its baggage or adding it as a reference to in other +// Spans. +// +// All six interfaces are static, polymorphic interfaces for interacting +// with the installed Tracer. They use the Curiously Repeating Template +// Pattern (CRTP) to avoid v-table hits we would encounter with tradtional +// polymorphism. +// +// See this CRTP article for more details on the design pattern: +// https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern #include - #include #include +#include +#if HAVE_STDINT_H +#include +#endif + namespace opentracing { -struct TextMapPair { +// ================= +// class TextMapPair +// ================= +// TextMapPair is a struct used to encapsulate name:value pairs going +// into (inject) and out of (extract) text map carriers. + +class TextMapPair { + public: TextMapPair(); TextMapPair(const StringRef& name, const StringRef& value); @@ -22,12 +64,27 @@ struct TextMapPair { std::string m_value; }; -// Text map carriers -template +// ======================= +// class GenericTextWriter +// ======================= +// GenericTextWriters are used to 'inject' a list of TextMapPair strings +// into an arbitrary carrier message. +// +// It is templated on the implementation only, which must support: +// +// class TextWriter : GenericTextWriter{ +// public: +// int injectImp(const std::vector&); +// }; +// +// Implementations are responsible for translating the text map passed +// to them into a carrier object. When constructed, Writers should hold +// onto any references they may need to populate the outgoing RPC carrier +// object. + +template class GenericTextWriter { public: - virtual ~GenericTextWriter(); - int inject(const std::vector& textmap); // Inject the supplied 'Textmap' into this carrier. @@ -37,38 +94,131 @@ class GenericTextWriter { // Protected to avoid direct construction }; -template -class GenericTextReader { +// ========================= +// class GenericBinaryWriter +// ========================= +// GenericBinaryWriters are used to 'inject' a binary blob of data into an +// arbitrary carrier message. +// +// It is templated on the implementation only, which must support: +// +// class BinaryWriter : GenericBinaryWriter{ +// public: +// int injectImp(const void * const, const size_t); +// }; +// +// Implementations are responsible for passing the blob along with a carrier +// object. When constructed, Writers should hold onto any references they may +// need to populate the outgoing RPC carrier object. + +template +class GenericBinaryWriter { public: - virtual ~GenericTextReader(); - - int extract(std::vector* const textmap) const; - // Extract the supplied 'Textmap' from this carrier. + int inject(const void* const buf, const size_t len); + // Inject the supplied 'buf' of 'len' bytes into this carrier. protected: - GenericTextReader(); - GenericTextReader(const GenericTextReader&); + GenericBinaryWriter(); + GenericBinaryWriter(const GenericBinaryWriter&); }; -// Binary carriers -template -class GenericBinaryWriter { +// =================== +// class GenericWriter +// =================== +// GenericWriters are used to 'inject' an explicit SpanContext into an +// arbitrary carrier message. +// +// If clients want to rely on the details of a particular SpanContext +// implementation (for API simplicity, performance reasons, etc.), they can +// create a GenericWriter that is templated on the *specific* SpanContext +// implementation that they are using. This removes flexibility, making +// it harder to change opentracing-cpp implementations, however, +// it is better to embed the dependency in the type system than rely +// on workarounds such as run time dynamic_cast/reinterpret_cast checks. +// +// For this to work, implementations must support: +// +// class ExplicitWriter: GenericWriter +// { +// public: +// int inject(const SpanContextImpl&); +// }; +// +// The Tracer will be responsible for all downcasting, and the explicit +// SpanContextImpl object will be passed directly to the Writer. It can +// then use any of the public API's that the Tracer may be using, to +// interact with the SpanContext directly. +// +// Implementations are responsible for emebeding the details of the +// SpanContextImpl into a carrier object. When constructed of the +// SpanContextImpl along with a carrier object. When constructed, the outgoing +// RPC carrier objects. + +template +class GenericWriter { public: - virtual ~GenericBinaryWriter(); + int inject(const CONTEXT& context); + // Inject the supplied 'context' directly into this carrier. - int inject(const void* const buf, const size_t len); - // Inject the supplied 'buf' of 'len' bytes into this carrier. + protected: + GenericWriter(); + GenericWriter(const GenericWriter&); +}; + +// ======================= +// class GenericTextReader +// ======================= +// GenericTextReaders are used to 'extract' a list of TextMapPair strings +// out of an arbitrary carrier message. +// +// It is templated on the implementation only, which must support: +// +// class TextReader : GenericTextReader{ +// public: +// int extractImp(std::vector*) const; +// }; +// +// Implementations are responsible for translating their carrier object +// into a text map, loading results into the vector they're passed. +// When constructed, they should hold onto any references they may need to +// populate the text map pair. The Tracer then uses that list to populate +// its SpanContexts appropriately. + +template +class GenericTextReader { + public: + int extract(std::vector* const textmap) const; + // Extract the supplied 'Textmap' from this carrier. protected: - GenericBinaryWriter(); - GenericBinaryWriter(const GenericBinaryWriter&); + GenericTextReader(); + GenericTextReader(const GenericTextReader&); }; -template +// ========================= +// class GenericBinaryReader +// ========================= +// GenericBinaryReaders are used to 'extract' a blob out of an arbitrary carrier +// message. +// +// It is templated on the implementation only, which must support: +// +// class BinaryReader : GenericBinaryReader{ +// public: +// int extractImp( +// void *const buf, size_t *const written, const size_t len) const; +// }; +// +// Implementations are responsible for: +// * Making sure there is enough room in 'buf' for the blob +// * Setting the number of bytes actually 'written' to 'buf +// +// When constructed, they should hold onto any references they may need to +// retrieve the blob when 'extractImp()' is invoked. + +template class GenericBinaryReader { public: - virtual ~GenericBinaryReader(); - int extract(void* const buf, size_t* const written, const size_t len) const; // Extract up to 'len' bytes of the binary representation of a span context // into 'buf' then store the number of bytes 'written'. @@ -78,25 +228,36 @@ class GenericBinaryReader { GenericBinaryReader(const GenericBinaryReader&); }; -// Explicit carriers -template -class GenericWriter { - public: - virtual ~GenericWriter(); - - int inject(const CONTEXT& context); - // Inject the supplied 'context' directly into this carrier. - - protected: - GenericWriter(); - GenericWriter(const GenericWriter&); -}; - -template +// =================== +// class GenericReader +// =================== +// GenericReaders are used to 'extract' an explicit SpanContext out of an +// arbitrary carrier message. +// +// If clients want to rely on the details of a particular SpanContext +// implementation (for API simplicity, performance reasons, etc.), they can +// create a GenericReader that is templated on the *specific* SpanContext +// implementation that they are using. This removes flexibility, making +// it harder to change opentracing-cpp implementations, however, +// it is better to embed the dependency in the type system than rely +// on workarounds such as run time dynamic_cast/reinterpret_cast checks. +// +// For this to work, implementations must support: +// +// class ExplicitReader: GenericReader +// { +// public: +// int extractImp(SpanContextImpl* const) const; +// }; +// +// The Tracer will be responsible for downcasting, and the explicit +// SpanContextImpl address will be passed directly to the Reader. The +// Reader can then use any of the public methods that the SpanContextImpl +// exposes, which may be much more than the GenericSpanContext interface. + +template class GenericReader { public: - virtual ~GenericReader(); - int extract(CONTEXT* const context) const; // Extract the supplied 'context' directly from this carrier. @@ -105,7 +266,9 @@ class GenericReader { GenericReader(const GenericReader&); }; -// Inline Definitions +// ----------------- +// class TextMapPair +// ----------------- inline TextMapPair::TextMapPair() : m_name(), m_value() { @@ -116,137 +279,134 @@ inline TextMapPair::TextMapPair(const StringRef& name, const StringRef& value) { } -template -int -GenericTextWriter::inject(const std::vector& textmap) -{ - return static_cast(this)->injectImp(textmap); -} +// ----------------------- +// class GenericTextWriter +// ----------------------- -template -GenericTextWriter::~GenericTextWriter() +template +inline int +GenericTextWriter::inject(const std::vector& textmap) { + return static_cast(this)->injectImp(textmap); } -template -GenericTextWriter::GenericTextWriter() +template +inline GenericTextWriter::GenericTextWriter() { } -template -GenericTextWriter::GenericTextWriter(const GenericTextWriter&) +template +inline GenericTextWriter::GenericTextWriter(const GenericTextWriter&) { } -template -int -GenericTextReader::extract(std::vector* const textmap) const -{ - return static_cast(this)->extractImp(textmap); -} +// ------------------------- +// class GenericBinaryWriter +// ------------------------- -template -GenericTextReader::~GenericTextReader() +template +inline int +GenericBinaryWriter::inject(const void* buf, const size_t len) { + return static_cast(this)->injectImp(buf, len); } -template -GenericTextReader::GenericTextReader() +template +inline GenericBinaryWriter::GenericBinaryWriter() { } -template -GenericTextReader::GenericTextReader(const GenericTextReader&) +template +inline GenericBinaryWriter::GenericBinaryWriter( + const GenericBinaryWriter&) { } -template -int -GenericBinaryWriter::inject(const void* buf, const size_t len) -{ - return static_cast(this)->injectImp(buf, len); -} +// ------------------- +// class GenericWriter +// ------------------- -template -GenericBinaryWriter::~GenericBinaryWriter() +template +inline int +GenericWriter::inject(const CONTEXT& context) { + return static_cast(this)->injectImp(context); } -template -GenericBinaryWriter::GenericBinaryWriter() +template +inline GenericWriter::GenericWriter() { } -template -GenericBinaryWriter::GenericBinaryWriter(const GenericBinaryWriter&) +template +inline GenericWriter::GenericWriter(const GenericWriter&) { } -template -int -GenericBinaryReader::extract(void* const buf, - size_t* const written, - const size_t len) const -{ - return static_cast(this)->extractImp(buf, written, len); -} +// ----------------------- +// class GenericTextReader +// ----------------------- -template -GenericBinaryReader::~GenericBinaryReader() +template +inline int +GenericTextReader::extract( + std::vector* const textmap) const { + return static_cast(this)->extractImp(textmap); } -template -GenericBinaryReader::GenericBinaryReader() +template +inline GenericTextReader::GenericTextReader() { } -template -GenericBinaryReader::GenericBinaryReader(const GenericBinaryReader&) +template +inline GenericTextReader::GenericTextReader(const GenericTextReader&) { } -template -int -GenericWriter::inject(const CONTEXT& context) -{ - return static_cast(this)->injectImp(context); -} +// ------------------------- +// class GenericBinaryReader +// ------------------------- -template -GenericWriter::~GenericWriter() +template +inline int +GenericBinaryReader::extract(void* const buf, + size_t* const written, + const size_t len) const { + return static_cast(this)->extractImp(buf, written, len); } -template -GenericWriter::GenericWriter() +template +inline GenericBinaryReader::GenericBinaryReader() { } -template -GenericWriter::GenericWriter(const GenericWriter&) +template +inline GenericBinaryReader::GenericBinaryReader( + const GenericBinaryReader&) { } -template -int -GenericReader::extract(CONTEXT* const context) const -{ - return static_cast(this)->extractImp(context); -} +// ------------------- +// class GenericReader +// ------------------- -template -GenericReader::~GenericReader() +template +inline int +GenericReader::extract(CONTEXT* const context) const { + return static_cast(this)->extractImp(context); } -template -GenericReader::GenericReader() +template +inline GenericReader::GenericReader() { } -template -GenericReader::GenericReader(const GenericReader&) +template +inline GenericReader::GenericReader(const GenericReader&) { } From c8d422c176ff382861438fb8f43f47316b49b479 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 17:43:40 -0500 Subject: [PATCH 11/48] Adding guards, updating documentation and tests --- docs/usage.md | 92 +++++++------- opentracing/noop.h | 16 +-- opentracing/span.h | 9 +- opentracing/tracer.h | 83 +++++++------ opentracing/tracerguards.h | 127 ++++++++++++++++++++ test/Makefile | 1 - test/noop.t.cc | 240 ++++++++++++++----------------------- test/tracer.h | 15 ++- test/tracer.t.cc | 153 +++++++++++------------ test/unittest.h | 45 ------- 10 files changed, 403 insertions(+), 378 deletions(-) create mode 100644 opentracing/tracerguards.h diff --git a/docs/usage.md b/docs/usage.md index 3fc11e4..a543064 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -40,36 +40,45 @@ later. #include namespace acme { - typedef opentracing::GenericSpanContext< - opentracing::NoopContext, - opentracing::NoopAdapter> SpanContext; - - typedef opentracing::GenericSpanOptions< - opentracing::NoopOptions, - opentracing::NoopContext, - opentracing::NoopAdapter> SpanOptions; - - typedef opentracing::GenericSpan< - opentracing::NoopSpan, - opentracing::NoopContext, - opentracing::NoopAdapter> SpanContext; + typedef opentracing::NoopTracer TracerImpl; typedef opentracing::GenericTracer< opentracing::NoopTracer, opentracing::NoopSpan, opentracing::NoopOptions, opentracing::NoopContext, - opentracing::NoopAdapter> Tracer; + opentracing::NoopAdapter> Tracer; + // Tracer is required for O(1) implementation swaps + + typedef Tracer::SpanContext SpanContext; + typedef Tracer::SpanOptions SpanOptions; + typedef Tracer::Span Span; - typedef opentracing::NoopTracer TracerImpl; + typedef Tracer::SpanContextGuard SpanContextGuard; + typedef Tracer::SpanOptionsGuard SpanOptions; + typedef Tracer::SpanGuard SpanGuard; + // Exposing the 'Span' typedefs is done for convenience } #endif ``` -The `SpanContext`, `SpanOptions`, `SpanContext`, and `Tracer` typedefs are now -the names that our theoretical "ACME Inc." organization can use to instrument -their applications. The names are not standardized, but these typedefs -are the recommended names, and will be used throughout the rest of this documentation. +By creating the `Tracer` typedef, we can now rely on the the GenericTracer interface, +but avoid knowing any of the explicit implementation details in client code. + +The `Tracer` exposes a number of public typedefs which make it easier to create our +types: + + * `Tracer::Span` - Interface to Span objects + * `Tracer::SpanContext` - Interface to SpanContext objects + * `Tracer::SpanOptions` - Interface to SpanOptions objects + * `Tracer::SpanGuard` - RAII Wrappers for Spans + * `Tracer::SpanOptionsGuard` - RAII Wrappers for SpanOptions + * `Tracer::SpanContextGuard` - RAII Wrappers for SpanContexts + + +Our theoretical "ACME Inc." organization can use to instrument their applications. +The `Tracer` typedef is not standardized, but it is recommended. The rest of the +documentation will assume that `Tracer` was the chosen name for the Tracer type. If clients ever require that they swap `OpenTracing` implementations, they will need to update only this header file and rebuild applications. @@ -114,16 +123,16 @@ int getAccount(Repsonse * resp, const Request& req) { static Tracer * const s_tracer = Tracer::instance(); - acme::Span * span = s_tracer->start("get_account"); - if(!span){ /* log error */; } - - // ... hanlding our request TBD + acme::Tracer::SpanGuard span(s_tracer->start("get_account")); - // finish() signals the Tracer that we're done with this span - if(int rc = span.finish()) { /* log error */; } + if (!span.get()) + { /* log error */ + ; + } - // Cleanup the span when we're finished. - s_tracer->cleanup(span); + // When 'span' goes out of scope, the destructor will call s_tracer->cleanup(). + // This will automatically 'finish()' the span and return resources to the + // Tracer. return 0; } @@ -165,8 +174,9 @@ int getAccount(Repsonse * resp, const Request& req) { static Tracer * const s_tracer = Tracer::instance(); - acme::Span * span = s_tracer->start("get_account"); - if(!span){ /* log error */; } + acme::SpanGuard span(s_tracer->start("get_account")); + + if(!span.get()){ /* log error */; } HttpRequest httpRequest; HttpWriter writer(&httpRequest); @@ -176,12 +186,6 @@ int getAccount(Repsonse * resp, const Request& req) HttpResponse httpResponse; sendHttpRequest(&httpResponse, httpRequest); - // finish() signals the Tracer that we're done with this span - if(int rc = span.finish()) { /* log error */; } - - // Cleanup the span when we're finished. - s_tracer->cleanup(span); - return 0; } ``` @@ -216,29 +220,23 @@ int httpGetAccount(const HttpRequest& httpRequest) { static Tracer* const s_tracer = Tracer::instance(); - const acme::SpanContext* context = - s_tracer->extract(HttpReader(httpRequest)); + acme::SpanContextGuard context(s_tracer->extract(HttpReader(httpRequest))); - acme::Span* span; + acme::SpanGuard span; - if (!context) + if (!context.get()) { span = s_tracer->start("get_account"); } else { - acme::SpanOptions* opts = s_tracer->makeSpanOptions(); + acme::SpanOptionsGuard opts(s_tracer->makeSpanOptions()); + opts->addReference(opentracing::SpanRelationship::e_childOf, *context); opts->setOperation("get_account"); - span = s_tracer->start(*opts); - s_tracer->cleanup(opts); + span = s_tracer->start(opts); } - // Send back response to requester... - - span->finish(); - s_tracer->cleanup(span); - s_tracer->cleanup(context); return 0; } ``` diff --git a/opentracing/noop.h b/opentracing/noop.h index 2948827..701703f 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -44,7 +44,7 @@ class NoopSpan; class NoopTracer; // ================= -// Class NoopAdapter +// class NoopAdapter // ================= // The NoopAdapter has no container to iterator over. Regardless of what // iterator is passed in, it will always return empty baggage objects or @@ -60,7 +60,7 @@ class NoopAdapter { }; // ================= -// Class NoopContext +// class NoopContext // ================= // The NoopContext implements the GenericSpanContext interface. // @@ -84,7 +84,7 @@ class NoopContext : public GenericSpanContext { }; // ================= -// Class NoopOptions +// class NoopOptions // ================= // NoopOptions implements the GenericSpanOptions interface. It holds // onto no references, nor does it manipulate the start time or operation @@ -99,7 +99,7 @@ class NoopOptions }; // ============== -// Class NoopSpan +// class NoopSpan // ============== // The NoopSpan implements the GenericSpan interface. It provides no-op // overloads for all of the required Span behaviors. @@ -129,7 +129,7 @@ class NoopSpan : public GenericSpan { }; // ================ -// Class NoopTracer +// class NoopTracer // ================ // The NoopTracer implements the GenericTracer interface. It provides no-op // overloads for all of the required Tracer behaviors. @@ -361,21 +361,21 @@ template inline NoopContext* NoopTracer::extractImp(const GenericTextReader&) { - return &m_span.context(); + return &m_span.contextImp(); } template inline NoopContext* NoopTracer::extractImp(const GenericBinaryReader&) { - return &m_span.context(); + return &m_span.contextImp(); } template inline NoopContext* NoopTracer::extractImp(const GenericReader&) { - return &m_span.context(); + return &m_span.contextImp(); } inline void diff --git a/opentracing/span.h b/opentracing/span.h index 5e1bbfb..0cba1e2 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -11,7 +11,6 @@ #include #include - #ifdef HAVE_STDINT_H #include #endif @@ -93,10 +92,10 @@ class GenericSpan { int finish(const uint64_t tsp); // This should be the last method called on the Span. It marks the end of // this Span (in microseconds since epoch) using the current wall-time, or - // an explicit timestamp 'tsp'. Retrusn 0 upon success and a non-zero - // value otherwise. It is undefined behavior to call any method on this span - // after 'finish()' is called, except for accessing 'context()' in a - // read-only fashion. + // an explicit timestamp 'tsp'. Returns 0 upon success and a non-zero + // value otherwise. Multiple calls to 'finish()' are redundant. The only + // other method that may be called on the span, after 'finish()' is to + // access the 'context()' in a read-only fashion. template int tag(const StringRef& key, const T& val); diff --git a/opentracing/tracer.h b/opentracing/tracer.h index b6a7880..1c58a6b 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #ifdef HAVE_STDINT_H @@ -55,42 +56,42 @@ namespace opentracing { // class TracerImp : // GenericTracer // { -// public: -// Options * makeSpanOptionsImp(); -// void cleanupImp(const Options * const opts); +// public: +// Options * makeSpanOptionsImp(); +// void cleanupImp(const Options * const opts); // -// SpanImp * start(const StringRef& op); -// SpanImp * start(const OptionsImp& opts); -// void cleanupImp(const SpanImp * const sp); +// SpanImp * start(const StringRef& op); +// SpanImp * start(const OptionsImp& opts); +// void cleanupImp(const SpanImp * const sp); // -// template -// int injectImp( +// template +// int injectImp( // GenericTextWriter* const carrier, // const ContextImp& context) const; // -// template -// int injectImp( +// template +// int injectImp( // GenericBinaryWriter* const carrier, // const ContextImp& context) const; // -// template -// int injectImp( +// template +// int injectImp( // GenericWriter* const carrier, // const ContextImp& context) const; // -// template -// const ContextImp* extractImp( +// template +// const ContextImp* extractImp( // const GenericTextReader& carrier); // -// template -// const ContextImp* extractImp( +// template +// const ContextImp* extractImp( // const GenericBinaryReader& carrier); // -// template -// const ContextImp* extractImp( +// template +// const ContextImp* extractImp( // const GenericReader& carrier); // -// void cleanupImp(const ContextImp * const); +// void cleanupImp(const ContextImp * const); // }; template class GenericTracer { public: - typedef GenericSpan Span; - typedef GenericSpanContext SpanContext; - typedef GenericSpanOptions SpanOptions; + typedef GenericSpan Span; + typedef GenericSpanContext SpanContext; + typedef GenericSpanOptions SpanOptions; + + typedef GenericTracerGuard SpanGuard; + typedef GenericTracerGuard SpanOptionsGuard; + typedef GenericTracerGuard SpanContextGuard; // Public typedefs used by clients to use underlying implementation // interfaces reliably. These must exist in order to support O(1) compile // time changes of the Tracer implementations. @@ -206,6 +211,10 @@ class GenericTracer { static GenericTracer* s_tracer; }; +// ------------------- +// class GenericTracer +// ------------------- + template -inline typename GenericTracer::Span* -GenericTracer::start( - const StringRef& op) +inline typename GenericTracer::SpanOptions* +GenericTracer::makeSpanOptions() { - return static_cast(this)->startImp(op); + return static_cast(this)->makeSpanOptionsImp(); } template -inline typename GenericTracer:: - SpanOptions* - GenericTracer::makeSpanOptions() +inline void +GenericTracer::cleanup( + SpanOptions* const opts) { - return static_cast(this)->makeSpanOptionsImp(); + OPTIONS* const optsImp = static_cast(opts); + return static_cast(this)->cleanupImp(optsImp); } template -inline void -GenericTracer::cleanup( - SpanOptions* const opts) +inline typename GenericTracer::Span* +GenericTracer::start(const StringRef& op) { - OPTIONS* const optsImp = static_cast(opts); - return static_cast(this)->cleanupImp(optsImp); + return static_cast(this)->startImp(op); } template inline typename GenericTracer::Span* -GenericTracer::start( - const SpanOptions& opts) + GenericTracer::start(const SpanOptions& opts) { const OPTIONS& optsImp = static_cast(opts); - return static_cast(this)->startImp(opts); + return static_cast(this)->startImp(optsImp); } template ::cleanup(Span* const sp) { SPAN* const spanImp = static_cast(sp); + spanImp->finish(); return static_cast(this)->cleanupImp(spanImp); } diff --git a/opentracing/tracerguards.h b/opentracing/tracerguards.h new file mode 100644 index 0000000..784d7de --- /dev/null +++ b/opentracing/tracerguards.h @@ -0,0 +1,127 @@ +#ifndef INCLUDED_OPENTRACING_TRACERGUARDS_H +#define INCLUDED_OPENTRACING_TRACERGUARDS_H + +// ======== +// guards.h +// ======== +// class GenericTracerGuard - An RAII wrapper to manage Tracer resources + +namespace opentracing { + +// ======================== +// class GenericTracerGuard +// ======================== +// GenericTracerGuards are templated types used to automatically return +// resources to the installed Tracer when they go out of scope. +// The GenericTracerGuard own and manage another object through an installed +// pointer. Upon destruction, if the guard is still managing the object it +// will be automatically returned to the installed TRACER through the +// 'cleanup()' interface. +// +// When GenericTracerGuards are copied or assigned, the ownership of the +// managed objects will shift from the source to the destinations. +template +class GenericTracerGuard { + public: + explicit GenericTracerGuard(MANAGED* obj); + // Construct a guard managing the supplied object. + + GenericTracerGuard& operator=(MANAGED* other); + // Take ownership of any resources that may be managed by 'other'. + + ~GenericTracerGuard(); + // If an object is managed, return it to the Tracer, then + // destroy this guard. + + MANAGED* get() const; + // Return the pointer managed by this guard. May be NULL. + + MANAGED& operator*() const; + // Return a reference to underlying object. Undefined behavior if + // this guard is not currently managing an object. + + MANAGED* operator->() const; + // Return the pointer managed by this guard. May be NULL. + + MANAGED* release(); + // Return the pointer managed by this guard, then reset the guard. + // The object returned will have to have its lifetime managed explicitly. + + void reset(MANAGED* const obj = NULL); + // Reset this guard, potentially cleaning up after an object if one is + // currently being managed. + + private: + GenericTracerGuard(const GenericTracerGuard&); + GenericTracerGuard& operator=(GenericTracerGuard& other); + // Disallow + + MANAGED* m_managed; +}; + +// ------------------------ +// class GenericTracerGuard +// ------------------------ + +template +inline GenericTracerGuard::GenericTracerGuard( + MANAGED* managed) +: m_managed(managed) +{ +} + +template +inline GenericTracerGuard& +GenericTracerGuard::operator=(MANAGED* other) +{ + reset(other); + return *this; +} + +template +inline GenericTracerGuard::~GenericTracerGuard() +{ + reset(); +} + +template +inline MANAGED* +GenericTracerGuard::get() const +{ + return m_managed; +} + +template +inline MANAGED& GenericTracerGuard::operator*() const +{ + return *m_managed; +} + +template +inline MANAGED* GenericTracerGuard::operator->() const +{ + return m_managed; +} + +template +inline MANAGED* +GenericTracerGuard::release() +{ + MANAGED* const tmp = m_managed; + m_managed = NULL; + return tmp; +} + +template +inline void +GenericTracerGuard::reset(MANAGED* const other) +{ + if (m_managed) + { + TRACER::instance()->cleanup(m_managed); + } + m_managed = other; +} + +} // namespace opentracing +#endif // INCLUDED_OPENTRACING_TRACERGUARDS_H diff --git a/test/Makefile b/test/Makefile index af73ce9..f429544 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,7 +2,6 @@ CC=g++ OPENTRACING_INCLUDE=../ OPENTRACING_SRC=$(wildcard ${OPENTRACING_INCLUDE}/*.h) -OPENTRACING_HEADERS= $(wildcard ${OPENTRACING_INCLUDE} THIRDPARTY_ROOT=../thirdparty GTEST_INCLUDE=${THIRDPARTY_ROOT}/googletest/googletest/include diff --git a/test/noop.t.cc b/test/noop.t.cc index fd61492..e9b374e 100644 --- a/test/noop.t.cc +++ b/test/noop.t.cc @@ -9,9 +9,6 @@ // same, however, there may be some differences in return codes due // to the differing implementations. -typedef GenericSpanContext GlobalContext; -typedef GenericSpan GlobalSpan; -typedef GenericSpanOptions GlobalOptions; typedef GenericTracer GlobalTracer; -typedef GenericSpanGuard SpanGuard; -typedef GenericSpanOptionsGuard SpanOptionsGuard; -typedef GenericSpanContextGuard SpanContextGuard; +class NoopTracerEnv : public ::testing::Test { + public: + virtual void + SetUp() + { + GlobalTracer::install(&imp); + }; + + virtual void + TearDown() + { + GlobalTracer::uninstall(); + }; -TEST(NoopTracer, Intantiation){ + NoopTracer imp; +}; + +TEST_F(NoopTracerEnv, Intantiation){ NoopTracer noop; GlobalTracer::install(&noop); @@ -33,69 +43,29 @@ TEST(NoopTracer, Intantiation){ ASSERT_FALSE(GlobalTracer::instance()); } -TEST(NoopTracer, StartWithOp) +TEST_F(NoopTracerEnv, StartWithOp) { - NoopTracer imp; - GlobalTracer& t = imp; - - SpanGuard guard(&t, t.start("hello")); - EXPECT_TRUE(guard.sp); + GlobalTracer::SpanGuard guard(GlobalTracer::instance()->start("hello")); + EXPECT_TRUE(guard.get()); int rc = 0; - rc = guard.sp->log("server", "blahblahblah"); + rc = guard->log("server", "blahblahblah"); ASSERT_EQ(0, rc); - rc = guard.sp->context().setBaggage("hello", "world"); + rc = guard->context().setBaggage("hello", "world"); ASSERT_EQ(0, rc); - rc = guard.sp->context().setBaggage("apple", "banana"); + rc = guard->context().setBaggage("apple", "banana"); ASSERT_EQ(0, rc); GlobalTracer::SpanContext::BaggageValue val; - rc = guard.sp->context().getBaggage(&val, "apple"); + rc = guard->context().getBaggage(&val, "apple"); ASSERT_NE(0, rc); } -TEST(NoopTracer, StartWithOpAndTsp) -{ - NoopContext otherContextImp; - GlobalContext& othercontext = otherContextImp; - - NoopTracer imp; - GlobalTracer& t = imp; - - SpanOptionsGuard optsguard(&t, t.makeSpanOptions()); - - optsguard.sp->setOperation("hello"); - optsguard.sp->setStartTime(1251251); - optsguard.sp->addReference(SpanRelationship::e_FollowsFrom, othercontext); - - SpanGuard guard(&t, t.start("hello")); - EXPECT_TRUE(guard.sp); -} - -/* -TEST(NoopTracer, StartWithOpAndParent) -{ - // We create spans, which have contexts or create contexts directly - // through the 'extract' interface. Either way, clients only deal - // with the 'GlobalContext' type. Rather than make this simple start - // test dependent on those other interfaces, I'm going to just pull - // a context out of thin air to test the interface. - - NoopContext contextImp; - GlobalContext& context = contextImp; - - NoopTracer imp; - GlobalTracer& t = imp; - - SpanGuard guard(&t, t.start("hello", context)); - EXPECT_TRUE(guard.sp); -} - -TEST(NoopTracer, StartWithOpAndParentAndTsp) +TEST_F(NoopTracerEnv, StartWithOpAndParent) { // We create spans, which have contexts or create contexts directly // through the 'extract' interface. Either way, clients only deal @@ -103,84 +73,41 @@ TEST(NoopTracer, StartWithOpAndParentAndTsp) // test dependent on those other interfaces, I'm going to just pull // a context out of thin air to test the interface. - NoopContext contextImp; - GlobalContext& context = contextImp; - - NoopTracer imp; - GlobalTracer& t = imp; - - SpanGuard guard(&t, t.start("hello", context, 125125)); - EXPECT_TRUE(guard.sp); -} - -TEST(NoopTracer, StartWithOpAndMultipleParents) -{ - NoopContext contextImp1; - NoopContext contextImp2; - NoopContext contextImp3; - - std::vector contexts(3, NoopContext()); - - NoopTracer imp; - GlobalTracer& t = imp; - - SpanGuard guard(&t, t.start("hello", contexts.begin(), contexts.end())); - EXPECT_TRUE(guard.sp); -} - -TEST(NoopTracer, StartWithOpAndMultipleParentsAndTsp) -{ - NoopContext contextImp1; - NoopContext contextImp2; - NoopContext contextImp3; - - std::vector contexts(3, NoopContext()); - - NoopTracer imp; - GlobalTracer& t = imp; - - SpanGuard guard(&t, t.start("hello", contexts.begin(), contexts.end(), 125125)); - EXPECT_TRUE(guard.sp); + GlobalTracer::SpanGuard guard(GlobalTracer::instance()->start("hello")); + EXPECT_TRUE(guard.get()); } -TEST(NoopTracer, InjectText) +TEST_F(NoopTracerEnv, InjectText) { TestTextWriter writer; - NoopTracer imp; - - GlobalTracer& t = imp; - SpanGuard g(&t, t.start("op")); - ASSERT_TRUE(g.sp); + GlobalTracer::SpanGuard g(GlobalTracer::instance()->start("op")); + ASSERT_TRUE(g.get()); - g.sp->context().setBaggage("animal", "tiger"); - g.sp->context().setBaggage("animal", "cat"); + g->context().setBaggage("animal", "tiger"); + g->context().setBaggage("animal", "cat"); - int rc = t.inject(&writer, g.sp->context()); + int rc = GlobalTracer::instance()->inject(&writer, g->context()); ASSERT_EQ(0, rc); } -TEST(NoopTracer, ExtractText) +TEST_F(NoopTracerEnv, ExtractText) { TestTextReader reader; reader.pairs.push_back(TextMapPair("animal", "tiger")); reader.pairs.push_back(TextMapPair("fruit", "apple")); reader.pairs.push_back(TextMapPair("veggie", "carrot")); - NoopTracer imp; - - GlobalTracer& t = imp; - - SpanContextGuard g(&t, t.extract(reader)); - ASSERT_TRUE(g.sp); + GlobalTracer::SpanContextGuard g(GlobalTracer::instance()->extract(reader)); + ASSERT_TRUE(g.get()); size_t index = 0; const char * names[] = {"animal", "fruit", "veggie"}; const char * values[] = {"tiger", "apple", "carrot"}; - for (GlobalTracer::SpanContext::const_iterator it = g.sp->begin(); - it != g.sp->end(); + for (GlobalTracer::SpanContext::BaggageIterator it = g->baggageBegin(); + it != g->baggageEnd(); ++it) { ASSERT_STREQ(names[index], it.ref().key()); @@ -189,30 +116,21 @@ TEST(NoopTracer, ExtractText) } } -TEST(NoopTracer, InjectBinary) +TEST_F(NoopTracerEnv, InjectBinary) { TestBinaryWriter writer; - NoopTracer imp; - - GlobalTracer& t = imp; - - SpanGuard g(&t, t.start("op")); - ASSERT_TRUE(g.sp); - - int rc = t.inject(&writer, g.sp->context()); + GlobalTracer::SpanGuard g(GlobalTracer::instance()->start("op")); + ASSERT_TRUE(g.get()); + int rc = GlobalTracer::instance()->inject(&writer, g->context()); ASSERT_EQ(0, rc); } -TEST(NoopTracer, ExtractBinary) +TEST_F(NoopTracerEnv, ExtractBinary) { TestBinaryReader reader; reader.m_raw = 0xdeadbeef; - - NoopTracer imp; - - GlobalTracer& t = imp; - SpanContextGuard g(&t, t.extract(reader)); - ASSERT_TRUE(g.sp); + GlobalTracer::SpanContextGuard g(GlobalTracer::instance()->extract(reader)); + ASSERT_TRUE(g.get()); } struct NoopWriter: public GenericWriter @@ -223,16 +141,12 @@ struct NoopWriter: public GenericWriter } }; -TEST(NoopTracer, InjectExplicit) +TEST_F(NoopTracerEnv, InjectExplicit) { NoopWriter w; - NoopTracer imp; - GlobalTracer& t = imp; - - SpanGuard g(&t, t.start("span")); - ASSERT_TRUE(g.sp); - - int rc = t.inject(&w, g.sp->context()); + GlobalTracer::SpanGuard g(GlobalTracer::instance()->start("span")); + ASSERT_TRUE(g.get()); + int rc = GlobalTracer::instance()->inject(&w, g->context()); ASSERT_EQ(0, rc); } @@ -244,17 +158,45 @@ struct NoopReader : public GenericReader } }; -TEST(NoopTracer, ExtractExplicit) +TEST_F(NoopTracerEnv, ExtractExplicit) { - NoopReader reader; - NoopTracer imp; - GlobalTracer& t = imp; - SpanContextGuard g(&t, t.extract(reader)); - ASSERT_TRUE(g.sp); + NoopReader r; + GlobalTracer::SpanContextGuard g(GlobalTracer::instance()->extract(r)); + ASSERT_TRUE(g.get()); +} + +TEST_F(NoopTracerEnv, StartWithOpts) +{ + NoopReader r; + GlobalTracer::SpanContextGuard otherContext(GlobalTracer::instance()->extract(r)); + ASSERT_TRUE(otherContext.get()); + + GlobalTracer::SpanOptionsGuard opts(GlobalTracer::instance()->makeSpanOptions()); + + opts->setOperation("hello"); + opts->setStartTime(1251251); + opts->addReference(SpanRelationship::e_FollowsFrom, *otherContext); + + GlobalTracer::SpanGuard guard(GlobalTracer::instance()->start("hello")); + EXPECT_TRUE(guard.get()); } template class NoopSpanTypeTests : public ::testing::Test { + public: + virtual void + SetUp() + { + GlobalTracer::install(&imp); + }; + + virtual void + TearDown() + { + GlobalTracer::uninstall(); + }; + + NoopTracer imp; }; typedef ::testing::Typesstart("hello world")); + int rc = span->tag("key", TypeParam()); ASSERT_EQ(0, rc); } TYPED_TEST(NoopSpanTypeTests, LogInterface) { - NoopSpan impl; - GlobalSpan& t = impl; - int rc = t.log("key", TypeParam()); + GlobalTracer::SpanGuard span(GlobalTracer::instance()->start("hello world")); + int rc = span->log("key", TypeParam()); ASSERT_EQ(0, rc); } TYPED_TEST(NoopSpanTypeTests, LogTspInterface) { - NoopSpan impl; - GlobalSpan& t = impl; - int rc = t.log("key", TypeParam(), 0); + GlobalTracer::SpanGuard span(GlobalTracer::instance()->start("hello world")); + int rc = span->log("key", TypeParam(), 0); ASSERT_EQ(0, rc); } -*/ diff --git a/test/tracer.h b/test/tracer.h index 4f36b15..2f16787 100644 --- a/test/tracer.h +++ b/test/tracer.h @@ -35,13 +35,24 @@ class TestTracerImpl : public GenericTracer { public: - Span* + TestOptionsImpl * makeSpanOptionsImp() + { + return new TestOptionsImpl(); + } + + void + cleanupImp(TestOptionsImpl* const opts) + { + delete opts; + } + + TestSpanImpl* startImp(const StringRef&) { return new TestSpanImpl(); } - Span* + TestSpanImpl* startImp(const TestOptionsImpl&) { return new TestSpanImpl(); diff --git a/test/tracer.t.cc b/test/tracer.t.cc index d2348d9..e8aaa84 100644 --- a/test/tracer.t.cc +++ b/test/tracer.t.cc @@ -3,85 +3,73 @@ #include "carriers.h" -typedef GenericSpanGuard SpanGuard; -typedef GenericSpanContextGuard SpanContextGuard; +class TracerEnv : public ::testing::Test { + public: + virtual void + SetUp() + { + Tracer::install(&imp); + }; + + virtual void + TearDown() + { + Tracer::uninstall(); + }; -TEST(Tracer, SingletonTests) -{ TestTracerImpl imp; - Tracer::install(&imp); - ASSERT_EQ(&imp, Tracer::instance()); +}; +TEST_F(TracerEnv, SingletonTests) +{ + ASSERT_EQ(&imp, Tracer::instance()); Tracer::uninstall(); ASSERT_EQ(0, Tracer::instance()); } -TEST(Tracer, StartWithOp) +TEST_F(TracerEnv, StartWithOp) { - TestTracerImpl imp; - Tracer& t = imp; + Tracer::SpanGuard guardOrig(Tracer::instance()->start("hello")); + Tracer::SpanGuard guard(guardOrig.release()); - SpanGuard guard(&t, t.start("hello")); - EXPECT_TRUE(guard.sp); + EXPECT_TRUE(guard.get()); int rc = 0; - rc = guard.sp->log("server", "blahblahblah"); + rc = guard->log("server", "blahblahblah"); ASSERT_EQ(0, rc); - rc = guard.sp->context().setBaggage("hello", "world"); + rc = guard->context().setBaggage("hello", "world"); ASSERT_EQ(0, rc); - rc = guard.sp->context().setBaggage("apple", "banana"); + rc = guard->context().setBaggage("apple", "banana"); ASSERT_EQ(0, rc); Tracer::SpanContext::BaggageValues vals; - rc = guard.sp->context().getBaggage(&vals, "apple"); + rc = guard->context().getBaggage(&vals, "apple"); ASSERT_EQ(0, rc); ASSERT_EQ(1u, vals.size()); ASSERT_EQ("banana", vals[0]); Tracer::SpanContext::BaggageValue val; - rc = guard.sp->context().getBaggage(&val, "apple"); + rc = guard->context().getBaggage(&val, "apple"); ASSERT_EQ(0, rc); ASSERT_EQ("banana", val); } -TEST(Tracer, StartWithOptions) -{ - TestContextImpl otherContext; - - TestOptionsImpl optsImp; - - TestTracerImpl imp; - Tracer& t = imp; - - SpanOptions& opts = optsImp; - - opts.setOperation("test"); - opts.setStartTime(12414); - opts.addReference(SpanRelationship::e_ChildOf, otherContext); - - SpanGuard guard(&t, t.start("hello")); - EXPECT_TRUE(guard.sp); -} - -TEST(Tracer, InjectText) +TEST_F(TracerEnv, InjectText) { TestTextWriter writer; - TestTracerImpl imp; - - Tracer& t = imp; - SpanGuard g(&t, t.start("op")); - ASSERT_TRUE(g.sp); + Tracer::SpanGuard span(Tracer::instance()->start("op")); + ASSERT_TRUE(span.get()); - g.sp->context().setBaggage("animal", "tiger"); - g.sp->context().setBaggage("animal", "cat"); + span->context().setBaggage("animal", "tiger"); + span->context().setBaggage("animal", "cat"); - int rc = t.inject(&writer, g.sp->context()); + int rc = Tracer::instance()->inject(&writer, span->context()); ASSERT_EQ(0, rc); ASSERT_EQ(2u, writer.pairs.size()); @@ -93,27 +81,24 @@ TEST(Tracer, InjectText) ASSERT_TRUE(writer.pairs[1].m_value == "cat" || writer.pairs[1].m_value == "tiger"); } -TEST(Tracer, ExtractText) + +TEST_F(TracerEnv, ExtractText) { TestTextReader reader; reader.pairs.push_back(TextMapPair("animal", "tiger")); reader.pairs.push_back(TextMapPair("fruit", "apple")); reader.pairs.push_back(TextMapPair("veggie", "carrot")); - TestTracerImpl imp; - - Tracer& t = imp; - - SpanContextGuard g(&t, t.extract(reader)); - ASSERT_TRUE(g.sp); + Tracer::SpanContextGuard context(Tracer::instance()->extract(reader)); + ASSERT_TRUE(context.get()); size_t index = 0; const char * names[] = {"animal", "fruit", "veggie"}; const char * values[] = {"tiger", "apple", "carrot"}; - for (Tracer::SpanContext::BaggageIterator it = g.sp->baggageBegin(); - it != g.sp->baggageEnd(); + for (Tracer::SpanContext::BaggageIterator it = context->baggageBegin(); + it != context->baggageEnd(); ++it) { ASSERT_STREQ(names[index], it.ref().key()); @@ -122,48 +107,40 @@ TEST(Tracer, ExtractText) } } -TEST(Tracer, InjectBinary) +TEST_F(TracerEnv, InjectBinary) { TestBinaryWriter writer; - TestTracerImpl imp; - Tracer& t = imp; + Tracer::SpanGuard span(Tracer::instance()->start("op")); + ASSERT_TRUE(span.get()); - SpanGuard g(&t, t.start("op")); - ASSERT_TRUE(g.sp); - - int rc = t.inject(&writer, g.sp->context()); + int rc = Tracer::instance()->inject(&writer, span->context()); ASSERT_EQ(0, rc); ASSERT_EQ(0xdeadbeef, writer.m_raw); } -TEST(Tracer, ExtractBinary) +TEST_F(TracerEnv, ExtractBinary) { TestBinaryReader reader; reader.m_raw = 0xdeadbeef; - TestTracerImpl imp; - - Tracer& t = imp; - SpanContextGuard g(&t, t.extract(reader)); - ASSERT_TRUE(g.sp); + Tracer::SpanContextGuard context(Tracer::instance()->extract(reader)); + ASSERT_TRUE(context.get()); } -TEST(Tracer, InjectExplicit) + +TEST_F(TracerEnv, InjectExplicit) { - TestWriter w; - TestTracerImpl imp; - Tracer& t = imp; + TestWriter w; - SpanGuard g(&t, t.start("span")); - ASSERT_TRUE(g.sp); + Tracer::SpanGuard span(Tracer::instance()->start("span")); + ASSERT_TRUE(span.get()); - g.sp->context().setBaggage("animal", "tiger"); - g.sp->context().setBaggage("fruit", "apple"); + span->context().setBaggage("animal", "tiger"); + span->context().setBaggage("fruit", "apple"); - int rc = t.inject(&w, g.sp->context()); + int rc = Tracer::instance()->inject(&w, span->context()); ASSERT_EQ(0, rc); - ASSERT_EQ(2u, w.carrier.size()); TestBaggageContainer::const_iterator cit = w.carrier.find("animal"); @@ -176,15 +153,29 @@ TEST(Tracer, InjectExplicit) ASSERT_EQ("apple", cit->second); } -TEST(Tracer, ExtractExplicit) +TEST_F(TracerEnv, ExtractExplicit) { TestReader reader; reader.carrier.insert(TestBaggageContainer::value_type("animal", "tiger")); reader.carrier.insert(TestBaggageContainer::value_type("fruit", "apple")); + Tracer::SpanContextGuard context(Tracer::instance()->extract(reader)); + ASSERT_TRUE(context.get()); +} - TestTracerImpl imp; - Tracer& t = imp; +TEST_F(TracerEnv, StartWithOptions) +{ + TestReader reader; + reader.carrier.insert(TestBaggageContainer::value_type("animal", "tiger")); + reader.carrier.insert(TestBaggageContainer::value_type("fruit", "apple")); + Tracer::SpanContextGuard otherContext(Tracer::instance()->extract(reader)); + ASSERT_TRUE(otherContext.get()); + + Tracer::SpanOptionsGuard opts(Tracer::instance()->makeSpanOptions()); + + opts->setOperation("test"); + opts->setStartTime(12414); + opts->addReference(SpanRelationship::e_ChildOf, *otherContext); - SpanContextGuard g(&t, t.extract(reader)); - ASSERT_TRUE(g.sp); + Tracer::SpanGuard span(Tracer::instance()->start(*opts)); + EXPECT_TRUE(span.get()); } diff --git a/test/unittest.h b/test/unittest.h index 7cdfc86..436f1c8 100644 --- a/test/unittest.h +++ b/test/unittest.h @@ -19,51 +19,6 @@ test_widen(std::wstring* const dest, const std::string& src) dest->resize(src.size()); std::mbstowcs(&(*dest)[0], src.c_str(), src.size()); } - -template -struct GenericSpanGuard { - GenericSpanGuard(TRACER* tracer, typename TRACER::Span* s) : t(tracer), sp(s) - { - } - ~GenericSpanGuard() - { - t->cleanup(sp); - } - - TRACER* t; - typename TRACER::Span* sp; -}; - -template -struct GenericSpanOptionsGuard { - GenericSpanOptionsGuard(TRACER* tracer, typename TRACER::SpanOptions* s) - : t(tracer), sp(s) - { - } - ~GenericSpanOptionsGuard() - { - t->cleanup(sp); - } - - TRACER* t; - typename TRACER::SpanOptions* sp; -}; - -template -struct GenericSpanContextGuard { - GenericSpanContextGuard(TRACER* tracer, - const typename TRACER::SpanContext* s) - : t(tracer), sp(s) - { - } - ~GenericSpanContextGuard() - { - t->cleanup(sp); - } - - TRACER* t; - const typename TRACER::SpanContext* sp; -}; } using namespace opentracing; From 47a9047a19a9e9ab8053e9f88ff2c20b06a4e42e Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 17:55:57 -0500 Subject: [PATCH 12/48] Adding constants.h --- opentracing/constants.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 opentracing/constants.h diff --git a/opentracing/constants.h b/opentracing/constants.h new file mode 100644 index 0000000..0fc1de8 --- /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. +// See https://github.com/opentracing/specification/blob/master/data_conventions.yaml for +// a description of each value, and how it should be used. + +#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 From d35931b3bd89ad4dc40d923aa2fbc659f3dd3c70 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:09:33 -0500 Subject: [PATCH 13/48] Update usage --- docs/usage.md | 70 +++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index a543064..d2b907b 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -75,20 +75,18 @@ types: * `Tracer::SpanOptionsGuard` - RAII Wrappers for SpanOptions * `Tracer::SpanContextGuard` - RAII Wrappers for SpanContexts - -Our theoretical "ACME Inc." organization can use to instrument their applications. -The `Tracer` typedef is not standardized, but it is recommended. The rest of the -documentation will assume that `Tracer` was the chosen name for the Tracer type. +Our theoretical "ACME Inc." organization can use these type names to instrument their applications. +The `Tracer` typedef is not standardized, but it is recommended. The rest of the documentation +will assume that `Tracer` was the chosen name for the Tracer type. If clients ever require that they swap `OpenTracing` implementations, they will need to update only this header file and rebuild applications. ### Installing the Tracer -Now that you have selected your chosen implementation, your applications can rely -on your global `opentracing-cpp` configuration header to set up the `Tracer`. -The `Tracer` implementation is installed explicitly as singleton in main. This must -be done before any other parts of the API can be used: +Once a implementation is chosen, your applications can rely on your global `opentracing-cpp` +configuration header to set up the `Tracer`. The `Tracer` implementation singleton is installed +explicitly in main. This must be done before any other parts of the API can be used: ``` // acmetask.m.cpp @@ -111,9 +109,9 @@ int main(int argc, const char * argv[]) Once the `Tracer` is installed, we can begin to instrument the application. Say we have a service that acts as a proxy to a number of other HTTP servers. -We may have a `getAccount` handler that reaches out to the account service. +We may have a `getAccount` handler that reaches out to a user account service. -We'll first need to start the span: +To tracer our application, we'll first need to start the span: ``` // requesthandler.m.cpp @@ -121,14 +119,10 @@ We'll first need to start the span: int getAccount(Repsonse * resp, const Request& req) { - static Tracer * const s_tracer = Tracer::instance(); + static acme::Tracer * const s_tracer = acme::Tracer::instance(); acme::Tracer::SpanGuard span(s_tracer->start("get_account")); - - if (!span.get()) - { /* log error */ - ; - } + assert(span.get()); // When 'span' goes out of scope, the destructor will call s_tracer->cleanup(). // This will automatically 'finish()' the span and return resources to the @@ -140,21 +134,20 @@ int getAccount(Repsonse * resp, const Request& req) ### Defining carriers -For this trace to be distributed across all of our organizations tasks, we need -a way to `inject` and `extract` the span into our RPC carriers. +In order to instrument our entire network, we need a way to `inject` and `extract` +spans into and out of our RPC calls. Extending our example, when we make our request +to the backend HTTP service, we'll need a way to inject the details of the context +into our outgoing HTTP request. -For our above example, when we make our request to the backend HTTP service, -we'll need a way to inject the details of the context into our HTTP request. +For this example, we'll define our HttpWriter inline with our request. +In practice, you'll want the Writers/Readers you use to be consistent +across your organization, so putting them into a library would be ideal. ``` -// For this example, we'll define our HttpWriter inline with our request. -// In practice, you'll want the Writers/Readers you use to be consistent -// across your organization, so putting them into a library would be -// ideal. #include -class HttpWriter : public GenericBinaryWriter +class HttpWriter : public opentracing::GenericBinaryWriter { public: HttpWriter(HttpRequest * req): m_req(req){} @@ -172,30 +165,30 @@ class HttpWriter : public GenericBinaryWriter int getAccount(Repsonse * resp, const Request& req) { - static Tracer * const s_tracer = Tracer::instance(); + static acme::Tracer * const s_tracer = acme::Tracer::instance(); acme::SpanGuard span(s_tracer->start("get_account")); + assert(span.get()); - if(!span.get()){ /* log error */; } + HttpResponse httpResponse; + HttpRequest httpRequest(req); - HttpRequest httpRequest; + // Embed the details of our span into the outgoing HTTP headers: HttpWriter writer(&httpRequest); s_tracer->inject(&writer, span->context()); - - // Business logic... - HttpResponse httpResponse; sendHttpRequest(&httpResponse, httpRequest); return 0; } ``` -On the HTTP servers end, we'll want to create another span as a child: +On the server side of the HTTP request, we'll want to continue the original Trace by creating +a new SpanContext as a 'child of' the original: ``` #include -struct HttpReader: public GenericBinaryReader +struct HttpReader: public opentracing::GenericBinaryReader { public: int extractImp(void* const buf, size_t* const written, const size_t len) @@ -218,7 +211,7 @@ struct HttpReader: public GenericBinaryReader int httpGetAccount(const HttpRequest& httpRequest) { - static Tracer* const s_tracer = Tracer::instance(); + static acme::Tracer* const s_tracer = acme::Tracer::instance(); acme::SpanContextGuard context(s_tracer->extract(HttpReader(httpRequest))); @@ -232,11 +225,16 @@ int httpGetAccount(const HttpRequest& httpRequest) { acme::SpanOptionsGuard opts(s_tracer->makeSpanOptions()); - opts->addReference(opentracing::SpanRelationship::e_childOf, *context); - opts->setOperation("get_account"); + opts->addReference(opentracing::SpanRelationship::e_ChildOf, *context); + opts->setOperation("get_account_server"); + span = s_tracer->start(opts); } + HttpResponse response; + + // populate the response using the arguments in our original request... + sendResponse(response); return 0; } ``` From 3b86ccf48e043407ddf301a603d2d4fd2978eff1 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:25:56 -0500 Subject: [PATCH 14/48] Adding log/tags/baggage usage --- docs/usage.md | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index d2b907b..15d7698 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -111,7 +111,7 @@ Once the `Tracer` is installed, we can begin to instrument the application. Say we have a service that acts as a proxy to a number of other HTTP servers. We may have a `getAccount` handler that reaches out to a user account service. -To tracer our application, we'll first need to start the span: +To trace our application, we'll first need to start the span: ``` // requesthandler.m.cpp @@ -139,12 +139,11 @@ spans into and out of our RPC calls. Extending our example, when we make our req to the backend HTTP service, we'll need a way to inject the details of the context into our outgoing HTTP request. -For this example, we'll define our HttpWriter inline with our request. -In practice, you'll want the Writers/Readers you use to be consistent +We'll define our HttpWriter inline with our request to do the `inject` part of this +process first. In practice, you'll want the Writers/Readers you use to be consistent across your organization, so putting them into a library would be ideal. ``` - #include class HttpWriter : public opentracing::GenericBinaryWriter @@ -238,3 +237,41 @@ int httpGetAccount(const HttpRequest& httpRequest) return 0; } ``` + +### Tags, Logs, and Baggage + +The [OpenTracing specification](https://github.com/opentracing/specification/blob/master/specification.md) outlines how +users should be able tag their spans, log structured data for a span, or attach arbitrary baggage that propagates +through the entire system. + +The `opentracing-cpp` interface allows you to tag your spans with `key:value` pairs: + +``` +acme::SpanGuard span(acme::Tracer::instance()->start("get_bookmarks")); +span->tag("account", account_id); +span->tag("site", site); +``` + +The `key` must be a string, but the value can be any type that can be externalized via +`std::ostream& operator<<(std::ostream&, const Type& t)`. + +The `log` functions work similarly, but are implicitly associated with the current wall-time as well. Users can +control the time-stamp behavior if they wish by providing it explicitly: + +``` +acme::SpanGuard span(acme::Tracer::instance()->start("get_bookmarks")); +span->log("db_access", account_id); // Use current wall-time +span->log("redis_access", site, 1484003943000); // Accessed redis on Jan 9, 2017 at 23:19:2 GMT +``` + +Baggage is special. It is a set of text-only, key:value pairs that propagates with traces as they make their way +through a system. It can be prohibitively expensive if abused. It is also not a replacement for traditional message +schemas (e.g., protobuf). Care must be taken when adding any baggage. + +With all that being said, it can be added directly to any Span you create through the underlying SpanContext. + +``` +acme::SpanGuard span(acme::Tracer::instance()->start("get_bookmarks")); +span->context().setBaggage("database", std::to_string(database_id)); +span->context().setBaggage("user", user); +``` From 9656c0b9b1bbadf2bd09fa53b42d73f5a1f09002 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:31:03 -0500 Subject: [PATCH 15/48] Adding iterator behaviors --- docs/usage.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/usage.md b/docs/usage.md index 15d7698..16642f9 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -275,3 +275,30 @@ acme::SpanGuard span(acme::Tracer::instance()->start("get_bookmarks")); span->context().setBaggage("database", std::to_string(database_id)); span->context().setBaggage("user", user); ``` + +Baggage can also be read back through the original Span or SpanContexts extracted from carriers. + +``` +acme::SpanGuard span(acme::Tracer::instance()->start("get_bookmarks")); + +span->context().setBaggage("database", std::to_string(database_id)); +span->context().setBaggage("user", user); + +for(acme::SpanContext::BaggageIterator it = span->context().baggageBegin(); + it != span->context().baggageEnd(); + ++it) +{ + std::cout << "baggage item: " << it->key() << " val: " << it->value() << std::endl; +} +``` + +If you have access to C++11 features, we can use the range based for loop syntax too: + +``` +for(const auto& baggage : span->context().baggageRange()) +{ + std::cout << "baggage item: " << baggage.key() << " val: " << baggage.value() << std::endl; +} +``` + +For details on the semantics of `BaggageIterators` and how they work, see [baggage.h](../opentracing/baggage.h). From 63ff455356bd3077761c89636069127ecf97b0d4 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:32:44 -0500 Subject: [PATCH 16/48] Updating docs --- docs/usage.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 16642f9..23f8a1b 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -292,10 +292,13 @@ for(acme::SpanContext::BaggageIterator it = span->context().baggageBegin(); } ``` -If you have access to C++11 features, we can use the range based for loop syntax too: +If you have access to C++11 features, we can use the range based for loop syntax too. ``` -for(const auto& baggage : span->context().baggageRange()) +HttpReader reader(request); +acme::SpanContextGuard context(Tracer::extract(reader)); + +for(const auto& baggage : context.baggageRange()) { std::cout << "baggage item: " << baggage.key() << " val: " << baggage.value() << std::endl; } From 1f77d054c82571e3e336e29f5a16f71d9d28dd70 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:33:19 -0500 Subject: [PATCH 17/48] formatting --- docs/usage.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/usage.md b/docs/usage.md index 23f8a1b..de3595b 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -9,6 +9,7 @@ The `opentracing-cpp` interface uses the [Curiously Repeating Template Pattern]( compile time, polymorphic interfaces to `OpenTracing` implementations. In order to trace their systems, clients must: + * Select their `opentracing-cpp` implementation * Install the selected `Tracer` in their applications in main * Use the API's Tracer interface to instrument their applications requests From 59e565ff7f19e83c531aff2650b33bebafc73a11 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:34:49 -0500 Subject: [PATCH 18/48] formatting --- docs/usage.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index de3595b..4215d90 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -5,14 +5,14 @@ API. It assumes you have finished the required reading outlined [here](../README ### Outline -The `opentracing-cpp` interface uses the [Curiously Repeating Template Pattern](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) (CRTP) to define a set of -compile time, polymorphic interfaces to `OpenTracing` implementations. +The `opentracing-cpp` interface uses the [Curiously Repeating Template Pattern](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) +(CRTP) to define a set of compile time, polymorphic interfaces to `OpenTracing` implementations. In order to trace their systems, clients must: - * Select their `opentracing-cpp` implementation - * Install the selected `Tracer` in their applications in main - * Use the API's Tracer interface to instrument their applications requests + - Select their `opentracing-cpp` implementation + - Install the selected `Tracer` in their applications in main + - Use the API's Tracer interface to instrument their applications requests ### Select the implementation @@ -63,18 +63,18 @@ namespace acme { #endif ``` -By creating the `Tracer` typedef, we can now rely on the the GenericTracer interface, +By creating the `Tracer` typedef, we can now rely on the GenericTracer interface, but avoid knowing any of the explicit implementation details in client code. The `Tracer` exposes a number of public typedefs which make it easier to create our types: - * `Tracer::Span` - Interface to Span objects - * `Tracer::SpanContext` - Interface to SpanContext objects - * `Tracer::SpanOptions` - Interface to SpanOptions objects - * `Tracer::SpanGuard` - RAII Wrappers for Spans - * `Tracer::SpanOptionsGuard` - RAII Wrappers for SpanOptions - * `Tracer::SpanContextGuard` - RAII Wrappers for SpanContexts + - `Tracer::Span` - Interface to Span objects + - `Tracer::SpanContext` - Interface to SpanContext objects + - `Tracer::SpanOptions` - Interface to SpanOptions objects + - `Tracer::SpanGuard` - RAII Wrappers for Spans + - `Tracer::SpanOptionsGuard` - RAII Wrappers for SpanOptions + - `Tracer::SpanContextGuard` - RAII Wrappers for SpanContexts Our theoretical "ACME Inc." organization can use these type names to instrument their applications. The `Tracer` typedef is not standardized, but it is recommended. The rest of the documentation From 8f1025eee70ac3aca38fee9ab322d1555c966b8d Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:37:17 -0500 Subject: [PATCH 19/48] formatting never ends --- docs/usage.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 4215d90..47fd01b 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -18,10 +18,9 @@ In order to trace their systems, clients must: ### Select the implementation `opentracing-cpp` only defines the interfaces. In order to make any use of the -API, you will need to install a concrete `Tracer` implementation. - -To do so, it is best practice to first create an reusable header you can share -throughout your organization that declares the implementation you will be using. +API, you will need to install a concrete `Tracer` implementation. To do so, it is +best practice to first create an reusable header you can share throughout your +organization that declares the implementation you will be using. This header should provide a few typedefs that make it easy to swap implementations later. @@ -82,6 +81,7 @@ will assume that `Tracer` was the chosen name for the Tracer type. If clients ever require that they swap `OpenTracing` implementations, they will need to update only this header file and rebuild applications. +(Easier said then done for larger organizations...) ### Installing the Tracer @@ -108,7 +108,6 @@ int main(int argc, const char * argv[]) ### Creating Spans Once the `Tracer` is installed, we can begin to instrument the application. - Say we have a service that acts as a proxy to a number of other HTTP servers. We may have a `getAccount` handler that reaches out to a user account service. @@ -245,6 +244,7 @@ The [OpenTracing specification](https://github.com/opentracing/specification/blo users should be able tag their spans, log structured data for a span, or attach arbitrary baggage that propagates through the entire system. +##### Tags The `opentracing-cpp` interface allows you to tag your spans with `key:value` pairs: ``` @@ -254,8 +254,11 @@ span->tag("site", site); ``` The `key` must be a string, but the value can be any type that can be externalized via + `std::ostream& operator<<(std::ostream&, const Type& t)`. + +##### Logs The `log` functions work similarly, but are implicitly associated with the current wall-time as well. Users can control the time-stamp behavior if they wish by providing it explicitly: @@ -265,6 +268,7 @@ span->log("db_access", account_id); // Use current wall-time span->log("redis_access", site, 1484003943000); // Accessed redis on Jan 9, 2017 at 23:19:2 GMT ``` +##### Baggage Baggage is special. It is a set of text-only, key:value pairs that propagates with traces as they make their way through a system. It can be prohibitively expensive if abused. It is also not a replacement for traditional message schemas (e.g., protobuf). Care must be taken when adding any baggage. From 9f1dacafa7c11208d16033ff0197876d902629d5 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:37:56 -0500 Subject: [PATCH 20/48] formatting never ends --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 47fd01b..1561c3b 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -303,7 +303,7 @@ If you have access to C++11 features, we can use the range based for loop syntax HttpReader reader(request); acme::SpanContextGuard context(Tracer::extract(reader)); -for(const auto& baggage : context.baggageRange()) +for(const auto& baggage : context->baggageRange()) { std::cout << "baggage item: " << baggage.key() << " val: " << baggage.value() << std::endl; } From b5e54860e345ba284eb1c9e35891e8b78e9ac6c5 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:38:43 -0500 Subject: [PATCH 21/48] Update examples --- docs/usage.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 1561c3b..c139281 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -32,9 +32,6 @@ later. // Include the interface templates #include -#include -#include -#include // Include the chosen implementation #include From 05f3bf38d9e73625d9f968138816eb94be6f9eb3 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:39:59 -0500 Subject: [PATCH 22/48] Example compiler problem --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index c139281..f432c2c 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -150,7 +150,7 @@ class HttpWriter : public opentracing::GenericBinaryWriter int injectImp(const void* blob, const_size len) { - std::string blob(static_cast(blob), len); + std::string blob(static_cast(blob), len); req->addHeader("x-acme-tracing-blob", blob); return 0; } From eeb6fa312b9ba76a2a5edcbe2ac04bf4dd0a8c30 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 9 Jan 2017 18:41:13 -0500 Subject: [PATCH 23/48] typo --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index f432c2c..600d85f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -262,7 +262,7 @@ control the time-stamp behavior if they wish by providing it explicitly: ``` acme::SpanGuard span(acme::Tracer::instance()->start("get_bookmarks")); span->log("db_access", account_id); // Use current wall-time -span->log("redis_access", site, 1484003943000); // Accessed redis on Jan 9, 2017 at 23:19:2 GMT +span->log("redis_access", site, 1484003943000); // Accessed redis on Jan 9, 2017 at 23:19:02 GMT ``` ##### Baggage From 5ff6015297e72242bad8988ea8773b6daf9363c5 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Tue, 10 Jan 2017 15:22:47 -0500 Subject: [PATCH 24/48] Review feedback, removing guards, updated docs --- .gitignore | 2 +- Makefile.am | 4 +- configure.ac | 2 +- docs/usage.md | 116 ++++++++++++++++++--------------- opentracing.pc.in | 10 +++ opentracing/baggage.h | 4 +- opentracing/carriers.h | 48 +++++--------- opentracing/noop.h | 15 +++-- opentracing/span.h | 29 +-------- opentracing/spancontext.h | 40 +++++------- opentracing/spanoptions.h | 6 +- opentracing/tracer.h | 98 +++++++++++++--------------- opentracing/tracerguards.h | 127 ------------------------------------- test/carriers.h | 17 ++--- test/carriers.t.cc | 25 ++++---- test/noop.t.cc | 98 +++++++++++++++++----------- test/span.t.cc | 6 +- test/spancontext.h | 7 +- test/spancontext.t.cc | 10 +-- test/tracer.h | 19 ++++-- test/tracer.t.cc | 81 +++++++++++++---------- 21 files changed, 324 insertions(+), 440 deletions(-) create mode 100644 opentracing.pc.in delete mode 100644 opentracing/tracerguards.h diff --git a/.gitignore b/.gitignore index 6b2160c..ba00878 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,9 @@ *.so config.h config.h.in -*.in *.m4 Makefile +Makefile.in config.* */.deps/* stamp-h1 diff --git a/Makefile.am b/Makefile.am index 7b965cc..1a88708 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,11 +2,11 @@ AUTOMAKE_OPTIONS = gnu lib_LTLIBRARIES = -nobase_include_HEADERS = opentracing/*.h opentracing/internal/*.h +nobase_include_HEADERS = opentracing/*.h ACLOCAL_AMFLAGS = -I m4 -AM_CXXFLAGS= -fno-elide-constructors -pedantic-errors -ansi +AM_CXXFLAGS= -fno-elide-constructors -pedantic-errors -ansi if COMPILER_IS_GCC AM_CXXFLAGS+= -Wall -Werror -Wextra -Winit-self -Wold-style-cast diff --git a/configure.ac b/configure.ac index efa1826..e0c4690 100644 --- a/configure.ac +++ b/configure.ac @@ -24,5 +24,5 @@ AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_SIZE_T -AC_CONFIG_FILES([ Makefile ]) +AC_CONFIG_FILES([ Makefile opentracing.pc ]) AC_OUTPUT diff --git a/docs/usage.md b/docs/usage.md index 600d85f..409e075 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -50,11 +50,7 @@ namespace acme { typedef Tracer::SpanContext SpanContext; typedef Tracer::SpanOptions SpanOptions; typedef Tracer::Span Span; - - typedef Tracer::SpanContextGuard SpanContextGuard; - typedef Tracer::SpanOptionsGuard SpanOptions; - typedef Tracer::SpanGuard SpanGuard; - // Exposing the 'Span' typedefs is done for convenience + // For convenience } #endif ``` @@ -90,10 +86,12 @@ explicitly in main. This must be done before any other parts of the API can be u // acmetask.m.cpp #include +using namespace acme; + int main(int argc, const char * argv[]) { - acme::TracerImpl tracerImpl; - acme::Tracer::install(&tracerImpl); + TracerImpl tracerImpl; + Tracer::install(&tracerImpl); // ... @@ -114,16 +112,19 @@ To trace our application, we'll first need to start the span: // requesthandler.m.cpp #include +using namespace acme; + int getAccount(Repsonse * resp, const Request& req) { - static acme::Tracer * const s_tracer = acme::Tracer::instance(); + Tracer::Span* span(Tracer::start("get_account")); + assert(span); - acme::Tracer::SpanGuard span(s_tracer->start("get_account")); - assert(span.get()); + // When our span is complete, we have to call finish + span->finish(); - // When 'span' goes out of scope, the destructor will call s_tracer->cleanup(). - // This will automatically 'finish()' the span and return resources to the - // Tracer. + // When we're done with our Span, we need to return it to + // the Tracer implementation to be cleaned up + Tracer::cleanup(span); return 0; } @@ -143,15 +144,18 @@ across your organization, so putting them into a library would be ideal. ``` #include -class HttpWriter : public opentracing::GenericBinaryWriter +using namespace opentracing; +using namespace acme; + +class HttpWriter : public GenericBinaryWriter { public: HttpWriter(HttpRequest * req): m_req(req){} - int injectImp(const void* blob, const_size len) + int injectImp(const std::vector& blob) { - std::string blob(static_cast(blob), len); - req->addHeader("x-acme-tracing-blob", blob); + std::string header(blob.data(), blob.size()); + req->addHeader("x-acme-tracing-blob", header); return 0; } @@ -161,19 +165,22 @@ class HttpWriter : public opentracing::GenericBinaryWriter int getAccount(Repsonse * resp, const Request& req) { - static acme::Tracer * const s_tracer = acme::Tracer::instance(); - - acme::SpanGuard span(s_tracer->start("get_account")); - assert(span.get()); + Span* span(Tracer::start("get_account")); + assert(span); HttpResponse httpResponse; HttpRequest httpRequest(req); // Embed the details of our span into the outgoing HTTP headers: HttpWriter writer(&httpRequest); - s_tracer->inject(&writer, span->context()); + Tracer::inject(&writer, span->context()); + sendHttpRequest(&httpResponse, httpRequest); + // ... + + span->finish(); + Tracer::cleanup(span); return 0; } ``` @@ -184,20 +191,23 @@ a new SpanContext as a 'child of' the original: ``` #include -struct HttpReader: public opentracing::GenericBinaryReader +using namespace opentracing; +using namespace acme; + +struct HttpReader: public GenericBinaryReader { public: - int extractImp(void* const buf, size_t* const written, const size_t len) + int extractImp(std::vector * const buf) const { std::string header = m_req.getHeader("x-acme-tracing-blob"); - if (header.length() >= len) - { + if(!header.empty()){ + buf->assign(header.begin(), header.end()); + return 0; + } + else { return 1; } - - std::memcpy(buf, header.data(), header.size()); - *written = header.size(); return 0; } @@ -207,30 +217,33 @@ struct HttpReader: public opentracing::GenericBinaryReader int httpGetAccount(const HttpRequest& httpRequest) { - static acme::Tracer* const s_tracer = acme::Tracer::instance(); - - acme::SpanContextGuard context(s_tracer->extract(HttpReader(httpRequest))); + SpanContext* context(Tracer::extract(HttpReader(httpRequest))); - acme::SpanGuard span; + Span* span; - if (!context.get()) + if (!context) { - span = s_tracer->start("get_account"); + span = Tracer::start("get_account"); } else { - acme::SpanOptionsGuard opts(s_tracer->makeSpanOptions()); + SpanOptions* opts(Tracer::makeSpanOptions()); - opts->addReference(opentracing::SpanRelationship::e_ChildOf, *context); + opts->setReference(SpanRelationship::e_ChildOf, *context); opts->setOperation("get_account_server"); - span = s_tracer->start(opts); + span = Tracer::start(opts); + + Tracer::cleanup(context); + Tracer::cleanup(opts); } + assert(span); + + // Send back our response... - HttpResponse response; + span->finish(); + Tracer::cleanup(span); - // populate the response using the arguments in our original request... - sendResponse(response); return 0; } ``` @@ -245,7 +258,7 @@ through the entire system. The `opentracing-cpp` interface allows you to tag your spans with `key:value` pairs: ``` -acme::SpanGuard span(acme::Tracer::instance()->start("get_bookmarks")); +Span* span = Tracer::start("get_bookmarks"); span->tag("account", account_id); span->tag("site", site); ``` @@ -256,12 +269,12 @@ The `key` must be a string, but the value can be any type that can be externaliz ##### Logs -The `log` functions work similarly, but are implicitly associated with the current wall-time as well. Users can -control the time-stamp behavior if they wish by providing it explicitly: +The `log` functions work similarly, but logs are also implicitly associated with the current wall-time as well. +Users can control the time-stamp behavior if they wish by providing it explicitly: ``` -acme::SpanGuard span(acme::Tracer::instance()->start("get_bookmarks")); -span->log("db_access", account_id); // Use current wall-time +Span* span(Tracer::start("get_bookmarks")); +span->log("db_access", account_id); // Use current wall-time span->log("redis_access", site, 1484003943000); // Accessed redis on Jan 9, 2017 at 23:19:02 GMT ``` @@ -273,20 +286,21 @@ schemas (e.g., protobuf). Care must be taken when adding any baggage. With all that being said, it can be added directly to any Span you create through the underlying SpanContext. ``` -acme::SpanGuard span(acme::Tracer::instance()->start("get_bookmarks")); +Span* span = Tracer::start("get_bookmarks"); span->context().setBaggage("database", std::to_string(database_id)); span->context().setBaggage("user", user); ``` Baggage can also be read back through the original Span or SpanContexts extracted from carriers. +Note that SpanContexts created through 'extract()' are read-only. ``` -acme::SpanGuard span(acme::Tracer::instance()->start("get_bookmarks")); +Span* span(Tracer::start("get_bookmarks")); span->context().setBaggage("database", std::to_string(database_id)); span->context().setBaggage("user", user); -for(acme::SpanContext::BaggageIterator it = span->context().baggageBegin(); +for(SpanContext::BaggageIterator it = span->context().baggageBegin(); it != span->context().baggageEnd(); ++it) { @@ -298,12 +312,14 @@ If you have access to C++11 features, we can use the range based for loop syntax ``` HttpReader reader(request); -acme::SpanContextGuard context(Tracer::extract(reader)); +SpanContext* context(Tracer::extract(reader)); for(const auto& baggage : context->baggageRange()) { std::cout << "baggage item: " << baggage.key() << " val: " << baggage.value() << std::endl; } + +Tracer::cleanup(context); ``` For details on the semantics of `BaggageIterators` and how they work, see [baggage.h](../opentracing/baggage.h). diff --git a/opentracing.pc.in b/opentracing.pc.in new file mode 100644 index 0000000..796c6cd --- /dev/null +++ b/opentracing.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir + +Name: OpenTracing C++ +Description: C++ interface for the OpenTracing specification +URL: https://github.com/opentracing/opentracing-cpp +Version: 0.0.1 +Cflags: -I${includedir} diff --git a/opentracing/baggage.h b/opentracing/baggage.h index efd1379..3da490e 100644 --- a/opentracing/baggage.h +++ b/opentracing/baggage.h @@ -136,8 +136,8 @@ typedef BaggageRefImp BaggageRef; // typedef ImplementationIterator iterator; // typedef ImplementationIterator const_iterator; // -// Baggage copy()(const const_iterator& it) const; -// BaggageRef ref()(const const_iterator& it) const; +// Baggage copy(const const_iterator& it) const; +// BaggageRef ref(const const_iterator& it) const; // }; // // When clients create a BaggageIterator via 'SpanContext::baggageBegin()', diff --git a/opentracing/carriers.h b/opentracing/carriers.h index 2a75a6e..ee91750 100644 --- a/opentracing/carriers.h +++ b/opentracing/carriers.h @@ -17,26 +17,17 @@ // ======== // Carriers // ======== -// GenericTextWriter, GenericBinaryWriter, and GenericWriter are static, -// polymorphic interfaces used by the Tracer's 'inject()' interface. They -// are used to embed SpanContexts into a carrier object. Those carrier -// objects are passed between process boundaries by applications as a part -// of their existing message passing infrastructure. +// GenericTextWriter, GenericBinaryWriter, and GenericWriter are used by the +// Tracer's 'inject()' interface. They are used to embed SpanContexts into a +// carrier object. Those carrier objects are passed between process boundaries +// by applications as a part of their existing message passing infrastructure. // // When an RPC call is received, the SpanContext can be 'extract()'ed by // the Tracer using the GenericTextReader, GenericBinaryReader, or GenericReader -// interfaces. If the readers are succesful, an immutable SpanContext is +// interfaces. If the readers are successful, an immutable SpanContext is // returned to applications. That SpanContext can then be used to create // new spans, accessing its baggage or adding it as a reference to in other // Spans. -// -// All six interfaces are static, polymorphic interfaces for interacting -// with the installed Tracer. They use the Curiously Repeating Template -// Pattern (CRTP) to avoid v-table hits we would encounter with tradtional -// polymorphism. -// -// See this CRTP article for more details on the design pattern: -// https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern #include #include @@ -104,7 +95,7 @@ class GenericTextWriter { // // class BinaryWriter : GenericBinaryWriter{ // public: -// int injectImp(const void * const, const size_t); +// int injectImp(const vector& buf); // }; // // Implementations are responsible for passing the blob along with a carrier @@ -114,8 +105,8 @@ class GenericTextWriter { template class GenericBinaryWriter { public: - int inject(const void* const buf, const size_t len); - // Inject the supplied 'buf' of 'len' bytes into this carrier. + int inject(const std::vector& buf); + // Inject the binary representation of a span context into this carrier. protected: GenericBinaryWriter(); @@ -205,23 +196,18 @@ class GenericTextReader { // // class BinaryReader : GenericBinaryReader{ // public: -// int extractImp( -// void *const buf, size_t *const written, const size_t len) const; +// int extractImp(std::vector *const buf) const; // }; // -// Implementations are responsible for: -// * Making sure there is enough room in 'buf' for the blob -// * Setting the number of bytes actually 'written' to 'buf -// // When constructed, they should hold onto any references they may need to // retrieve the blob when 'extractImp()' is invoked. template class GenericBinaryReader { public: - int extract(void* const buf, size_t* const written, const size_t len) const; - // Extract up to 'len' bytes of the binary representation of a span context - // into 'buf' then store the number of bytes 'written'. + int extract(std::vector* const buffer) const; + // Load the binary representation of a span context into 'buffer'. + // Return 0 upon success and a non-zero value otherwise. protected: GenericBinaryReader(); @@ -306,9 +292,9 @@ inline GenericTextWriter::GenericTextWriter(const GenericTextWriter&) template inline int -GenericBinaryWriter::inject(const void* buf, const size_t len) +GenericBinaryWriter::inject(const std::vector& buf) { - return static_cast(this)->injectImp(buf, len); + return static_cast(this)->injectImp(buf); } template @@ -371,11 +357,9 @@ inline GenericTextReader::GenericTextReader(const GenericTextReader&) template inline int -GenericBinaryReader::extract(void* const buf, - size_t* const written, - const size_t len) const +GenericBinaryReader::extract(std::vector* const buf) const { - return static_cast(this)->extractImp(buf, written, len); + return static_cast(this)->extractImp(buf); } template diff --git a/opentracing/noop.h b/opentracing/noop.h index 701703f..74c983c 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -78,9 +78,9 @@ class NoopContext : public GenericSpanContext { BaggageIterator baggageBeginImp() const; BaggageIterator baggageEndImp() const; - int setBaggageImp(const StringRef& key, const StringRef& value); - int getBaggageImp(BaggageValue* const, const StringRef& key) const; - int getBaggageRefsImp(BaggageValues* const, const StringRef& key) const; + int setBaggageImp(const StringRef&, const StringRef&); + int getBaggageImp(const StringRef&, std::string* const) const; + int getBaggageImp(const StringRef&, std::vector* const) const; }; // ================= @@ -95,7 +95,7 @@ class NoopOptions public: void setOperationImp(const StringRef&); void setStartTimeImp(const uint64_t); - void addReferenceImp(const SpanRelationship::Value, const NoopContext&); + void setReferenceImp(const SpanRelationship::Value, const NoopContext&); }; // ============== @@ -218,13 +218,14 @@ NoopContext::setBaggageImp(const StringRef&, const StringRef&) } inline int -NoopContext::getBaggageImp(BaggageValue* const, const StringRef&) const +NoopContext::getBaggageImp(const StringRef&, std::string* const) const { return 1; } inline int -NoopContext::getBaggageRefsImp(BaggageValues* const, const StringRef&) const +NoopContext::getBaggageImp(const StringRef&, + std::vector* const) const { return 1; } @@ -244,7 +245,7 @@ NoopOptions::setStartTimeImp(const uint64_t) } inline void -NoopOptions::addReferenceImp(const SpanRelationship::Value, const NoopContext&) +NoopOptions::setReferenceImp(const SpanRelationship::Value, const NoopContext&) { } diff --git a/opentracing/span.h b/opentracing/span.h index 0cba1e2..87d6d96 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -20,23 +20,16 @@ namespace opentracing { // ================= // class GenericSpan // ================= -// GenericSpan is a static, polymorphic interface for interacting with -// Spans. It uses the Curiously Repeating Template Patttern (CRTP) to -// avoid v-table hits we would encounter with traditional polymorphism. -// -// See this CRTP article for more details on the design pattern: -// https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern -// // The GenericSpan has three template parameters: -// * SPAN - A Span implementation derived class (CRTP) -// * CONTEXT - A SpanContext implementation derived class (CRTP) +// * SPAN - A Span implementation derived class +// * CONTEXT - A SpanContext implementation derived class // * ADAPTER - A Baggage iterator adapter // // The CONTEXT and ADAPTER are used to alias the related GenericSpanContext // class as the SpanContext. This is a convenience typedef to ensure what is // exposed to clients is the same as the type used by the interface. // -// SPAN implementations must support the following: +// CRTP SPAN implementations must support the following: // // class SpanImpl: GenericSpan // { @@ -44,7 +37,6 @@ namespace opentracing { // ContextImpl& contextImp(); // const ContextImpl& contextImp() const; // -// int addReferenceImp(const ContextImpl&, const SpanRelationship::Value); // int setOperationImp(const StringRef& operation); // // int finishImp(); @@ -82,12 +74,6 @@ class GenericSpan { // value otherwise. It is undefined behavior to call this method after // 'finish()'. - int addReference(const SpanContext& context, - const SpanRelationship::Value relationship); - // Add a reference to another SpanContext, after the Span was created. - // Returns 0 upon success and a non-zero value otherwise. - // It is undefined behavior to call this method after 'finish()'. - int finish(); int finish(const uint64_t tsp); // This should be the last method called on the Span. It marks the end of @@ -165,15 +151,6 @@ GenericSpan::setOperation(const StringRef& operation) return static_cast(this)->setOperationImp(operation); } -template -inline int -GenericSpan::addReference( - const SpanContext& context, const SpanRelationship::Value relationship) -{ - const CONTEXT& contextImp = static_cast(context); - return static_cast(this)->addReferenceImp(contextImp, relationship); -} - template inline int GenericSpan::finish() diff --git a/opentracing/spancontext.h b/opentracing/spancontext.h index 78c299e..480aa9d 100644 --- a/opentracing/spancontext.h +++ b/opentracing/spancontext.h @@ -16,16 +16,8 @@ namespace opentracing { // ======================== // class GenericSpanContext // ======================== -// GenericSpanContext is a static, polymorphic interface for interacting with -// SpanContexts. It uses the Curiously Repeating Template Pattern (CRTP) to -// avoid unnecessary v-table hits we would encounter with traditional -// polymorphism. -// -// See this CRTP article for more details on the design pattern: -// https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern -// // The 'GenericSpanContext' has two template parameters: -// * CONTEXT - A SpanContext implementation derived class (CRTP) +// * CONTEXT - A SpanContext implementation derived class // * ADAPTER - A BaggageIteratorImp adapter // // CONTEXT implementations are required to implement the following: @@ -37,9 +29,8 @@ namespace opentracing { // typename Adapter::const_iterator baggageEndImp() const; // // int setBaggageImp(const StringRef&, const StringRef&); -// -// int getBaggageImp(std::string* const, const StringRef&) const; -// int getBaggageImp(BaggageValues* const, const StringRef&) const; +// int getBaggageImp(const StringRef&, std::string* const) const; +// int getBaggageImp(const StringRef&, std::vector* const) const; // }; // // Implementations may choose how they implement storage of Baggage, but the @@ -54,9 +45,6 @@ class GenericSpanContext { typedef BaggageIteratorImp BaggageIterator; typedef BaggageRangeImp BaggageRange; - typedef std::string BaggageValue; - typedef std::vector BaggageValues; - BaggageIterator baggageBegin() const; // Return a BaggageIterator to the beginning of the Baggage maintained // by this SpanContext. @@ -73,14 +61,15 @@ class GenericSpanContext { // Set or append the single 'baggage' value for the given 'key'. Return 0 // upon success and a non-zero value otherwise. - int getBaggage(BaggageValue *const baggage, const StringRef &key) const; + int getBaggage(const StringRef &key, std::string *const baggage) const; // Load a single 'baggage' value associated with 'key'. Returns 0 if there // is only one value associated with 'key' and that value was loaded - // succesfully. Return a non-zero value otherwise. + // successfully. Return a non-zero value otherwise. - int getBaggage(BaggageValues *const baggage, const StringRef &key) const; + int getBaggage(const StringRef & key, + std::vector *const baggage) const; // Load the 'baggage' associated with 'key'. Returns 0 if the - // baggage is loaded succesfully, and a non-zero value otherwise. + // baggage is loaded successfully, and a non-zero value otherwise. protected: GenericSpanContext(); @@ -135,18 +124,19 @@ GenericSpanContext::setBaggage(const StringRef &key, template inline int -GenericSpanContext::getBaggage(BaggageValue *const baggage, - const StringRef &key) const +GenericSpanContext::getBaggage( + const StringRef &key, std::string *const baggage) const + { - return static_cast(this)->getBaggageImp(baggage, key); + return static_cast(this)->getBaggageImp(key, baggage); } template inline int -GenericSpanContext::getBaggage(BaggageValues *const baggage, - const StringRef &key) const +GenericSpanContext::getBaggage( + const StringRef &key, std::vector *const baggage) const { - return static_cast(this)->getBaggageImp(baggage, key); + return static_cast(this)->getBaggageImp(key, baggage); } } // namespace opentracing diff --git a/opentracing/spanoptions.h b/opentracing/spanoptions.h index 7ba9722..c70de9c 100644 --- a/opentracing/spanoptions.h +++ b/opentracing/spanoptions.h @@ -60,7 +60,7 @@ class GenericSpanOptions { // Set the start time from this span. If start time is not supplied, the // default is to use the current wall-time. - void addReference(const SpanRelationship::Value relationship, + void setReference(const SpanRelationship::Value relationship, const SpanContext& context); // A new Span created with these options would have a 'relationship' // referenced added for 'context'. @@ -86,11 +86,11 @@ GenericSpanOptions::setStartTime(const uint64_t tsp) template inline void -GenericSpanOptions::addReference( +GenericSpanOptions::setReference( const SpanRelationship::Value rel, const SpanContext& context) { const CONTEXT& contextImp = static_cast(context); - static_cast(this)->addReferenceImp(rel, contextImp); + static_cast(this)->setReferenceImp(rel, contextImp); } } // namespace opentracing diff --git a/opentracing/tracer.h b/opentracing/tracer.h index 1c58a6b..22a0917 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #ifdef HAVE_STDINT_H @@ -22,24 +21,16 @@ namespace opentracing { // =================== // class GenericTracer // =================== -// GenericTracer is a static, polymorphic interface for interacting with -// the installed Tracer implementation. It uses the Curiously Repeating Template -// Pattern (CRTP) to avoid v-table hits we would encounter with traditional -// polymorphism. -// -// See this CRTP article for more details on the design pattern: -// https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern -// // The GenericTracer acts as a factory for the other OpenTracing types. It has // the most functionality, and also requires the most details to be instantiated // appropriately at compile time. As such, it has the most template parameters, // giving it access to otherwise unknowable details, at compile time. // // The template parameters are: -// * TRACER - A Tracer implementation (CRTP) -// * SPAN - A Span implementation (CRTP) -// * OPTIONS - A SpanOptions implementation (CRTP) -// * CONTEXT - A SpanContext implementation (CRTP) +// * TRACER - A Tracer implementation +// * SPAN - A Span implementation +// * OPTIONS - A SpanOptions implementation +// * CONTEXT - A SpanContext implementation // * ADAPTER - A Baggage iterator adapter // // The Tracer also exposes a set of typedefs which obfuscate the details of @@ -51,7 +42,7 @@ namespace opentracing { // * SpanContext - Aliasing GenericSpanContex // * SpanOptions - Aliasing GenericSpanOptions // -// TRACER implementations must support the following: +// CRTP TRACER implementations must support the following: // // class TracerImp : // GenericTracer @@ -101,19 +92,18 @@ template class GenericTracer { public: - typedef GenericSpan Span; - typedef GenericSpanContext SpanContext; - typedef GenericSpanOptions SpanOptions; - - typedef GenericTracerGuard SpanGuard; - typedef GenericTracerGuard SpanOptionsGuard; - typedef GenericTracerGuard SpanContextGuard; + typedef GenericSpan Span; + typedef GenericSpanContext SpanContext; + typedef GenericSpanOptions SpanOptions; // Public typedefs used by clients to use underlying implementation // interfaces reliably. These must exist in order to support O(1) compile // time changes of the Tracer implementations. static void install(GenericTracer* const tracer); // Install Tracer to be referenced globally with calls to 'instance()'. + // It is undefined behavior to call any other Tracer method if an + // implementation has not been installed. + // // This method is not thread safe. It should be called once, in main, before // any other thread or trace work is performed. Undefined behavior if called // differently. @@ -121,26 +111,26 @@ class GenericTracer { static void uninstall(); // Uninstall a previously installed Tracer. This method is not thread safe, // nor is it required for production code. It is used to sanitize test - // environments if needed. + // environments when needed. static GenericTracer* instance(); // Return an instance to the globally installed tracer. Returns NULL if a // tracer has not been previously installed. It is undefined behavior // to call this method without previously calling 'install()'. - SpanOptions* makeSpanOptions(); + static SpanOptions* makeSpanOptions(); // This is a factory method to create SpanOptions. Options can be passed // to 'start()' to control how Spans are created. Options should be // subsequently cleaned up with a call to 'cleanup()' Returns NULL on // failure. - void cleanup(SpanOptions* const opts); + static void cleanup(SpanOptions* const opts); // All SpanOptions pointers returned by the Tracer via 'makeSpanOptions()' // must be passed back to the Tracer when client's are done with them via // 'cleanup()'. - Span* start(const StringRef& op); - Span* start(const SpanOptions& opts); + static Span* start(const StringRef& op); + static Span* start(const SpanOptions& opts); // The 'start()' functions are factory methods to create a new Span. The // only required parameter is the operation string 'op', which should // describe the work being performed during the span. @@ -151,25 +141,25 @@ class GenericTracer { // // Returns NULL on error. - void cleanup(Span* const sp); + static void cleanup(Span* const sp); // All Span pointers returned by the Tracer via 'start()' must be passed // back to the Tracer when clients are done with them via 'cleanup()'. template - int inject(GenericTextWriter* const carrier, - const SpanContext& context) const; + static int inject(GenericTextWriter* const carrier, + const SpanContext& context); // Inject the supplied 'context' into the text map writer 'carrier'. // Returns 0 upon success and a non-zero value otherwise. template - int inject(GenericBinaryWriter* const carrier, - const SpanContext& context) const; + static int inject(GenericBinaryWriter* const carrier, + const SpanContext& context); // Inject the supplied 'context' into the binary writer 'carrier'. // Returns 0 upon success and a non-zero value otherwise. template - int inject(GenericWriter* const carrier, - const SpanContext& context) const; + static int inject(GenericWriter* const carrier, + const SpanContext& context); // Inject the SpanContext directly into the specialized 'carrier'. // Returns 0 upon success and a non-zero value otherwise. // @@ -178,17 +168,20 @@ class GenericTracer { // want to swap Tracer/Span implementations. template - const SpanContext* extract(const GenericTextReader& carrier); + static const SpanContext* extract( + const GenericTextReader& carrier); // Extract the read-only supplied 'context' from the text map reader // 'carrier' upon success, and NULL otherwise. Returns NULL on error. template - const SpanContext* extract(const GenericBinaryReader& carrier); + static const SpanContext* extract( + const GenericBinaryReader& carrier); // Extract the read-only SpanContext from the binary reader 'carrier' // upon success, and NULL otherwise. Returns NULL on error. template - const SpanContext* extract(const GenericReader& carrier); + static const SpanContext* extract( + const GenericReader& carrier); // Extract the read-only SpanContext from the specialized 'carrier'. Returns // NULL on error. // @@ -197,7 +190,7 @@ class GenericTracer { // removes flexibility if you want to swap Tracer/Span implementations // later. - void cleanup(const SpanContext* const sp); + static void cleanup(const SpanContext* const sp); // All SpanContext pointers created by the Tracer through 'extract()' should // be passed back to the Tracer when client's are done with them via // 'cleanup()'. @@ -284,7 +277,7 @@ template ::SpanOptions* GenericTracer::makeSpanOptions() { - return static_cast(this)->makeSpanOptionsImp(); + return static_cast(s_tracer)->makeSpanOptionsImp(); } template ::cleanup( SpanOptions* const opts) { OPTIONS* const optsImp = static_cast(opts); - return static_cast(this)->cleanupImp(optsImp); + return static_cast(s_tracer)->cleanupImp(optsImp); } template ::Span* GenericTracer::start(const StringRef& op) { - return static_cast(this)->startImp(op); + return static_cast(s_tracer)->startImp(op); } template ::Span* GenericTracer::start(const SpanOptions& opts) { const OPTIONS& optsImp = static_cast(opts); - return static_cast(this)->startImp(optsImp); + return static_cast(s_tracer)->startImp(optsImp); } template ::cleanup(Span* const sp) { SPAN* const spanImp = static_cast(sp); - spanImp->finish(); - return static_cast(this)->cleanupImp(spanImp); + return static_cast(s_tracer)->cleanupImp(spanImp); } template inline int GenericTracer::inject( - GenericTextWriter* const carrier, const SpanContext& context) const + GenericTextWriter* const carrier, const SpanContext& context) { const CONTEXT& contextImp = static_cast(context); - return static_cast(this)->injectImp(carrier, contextImp); + return static_cast(s_tracer)->injectImp(carrier, contextImp); } template inline int GenericTracer::inject( GenericBinaryWriter* const carrier, - const SpanContext& context) const + const SpanContext& context) { const CONTEXT& contextImp = static_cast(context); - return static_cast(this)->injectImp(carrier, contextImp); + return static_cast(s_tracer)->injectImp(carrier, contextImp); } template inline int GenericTracer::inject( GenericWriter* const carrier, - const SpanContext& context) const + const SpanContext& context) { const CONTEXT& contextImp = static_cast(context); - return static_cast(this)->injectImp(carrier, contextImp); + return static_cast(s_tracer)->injectImp(carrier, contextImp); } template :: GenericTracer::extract( const GenericTextReader& carrier) { - return static_cast(this)->extractImp(carrier); + return static_cast(s_tracer)->extractImp(carrier); } template :: GenericTracer::extract( const GenericBinaryReader& carrier) { - return static_cast(this)->extractImp(carrier); + return static_cast(s_tracer)->extractImp(carrier); } template :: GenericTracer::extract( const GenericReader& carrier) { - return static_cast(this)->extractImp(carrier); + return static_cast(s_tracer)->extractImp(carrier); } template ::cleanup( const SpanContext* const spc) { const CONTEXT* const contextImp = static_cast(spc); - return static_cast(this)->cleanupImp(contextImp); + return static_cast(s_tracer)->cleanupImp(contextImp); } } // namespace opentracing diff --git a/opentracing/tracerguards.h b/opentracing/tracerguards.h deleted file mode 100644 index 784d7de..0000000 --- a/opentracing/tracerguards.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef INCLUDED_OPENTRACING_TRACERGUARDS_H -#define INCLUDED_OPENTRACING_TRACERGUARDS_H - -// ======== -// guards.h -// ======== -// class GenericTracerGuard - An RAII wrapper to manage Tracer resources - -namespace opentracing { - -// ======================== -// class GenericTracerGuard -// ======================== -// GenericTracerGuards are templated types used to automatically return -// resources to the installed Tracer when they go out of scope. -// The GenericTracerGuard own and manage another object through an installed -// pointer. Upon destruction, if the guard is still managing the object it -// will be automatically returned to the installed TRACER through the -// 'cleanup()' interface. -// -// When GenericTracerGuards are copied or assigned, the ownership of the -// managed objects will shift from the source to the destinations. -template -class GenericTracerGuard { - public: - explicit GenericTracerGuard(MANAGED* obj); - // Construct a guard managing the supplied object. - - GenericTracerGuard& operator=(MANAGED* other); - // Take ownership of any resources that may be managed by 'other'. - - ~GenericTracerGuard(); - // If an object is managed, return it to the Tracer, then - // destroy this guard. - - MANAGED* get() const; - // Return the pointer managed by this guard. May be NULL. - - MANAGED& operator*() const; - // Return a reference to underlying object. Undefined behavior if - // this guard is not currently managing an object. - - MANAGED* operator->() const; - // Return the pointer managed by this guard. May be NULL. - - MANAGED* release(); - // Return the pointer managed by this guard, then reset the guard. - // The object returned will have to have its lifetime managed explicitly. - - void reset(MANAGED* const obj = NULL); - // Reset this guard, potentially cleaning up after an object if one is - // currently being managed. - - private: - GenericTracerGuard(const GenericTracerGuard&); - GenericTracerGuard& operator=(GenericTracerGuard& other); - // Disallow - - MANAGED* m_managed; -}; - -// ------------------------ -// class GenericTracerGuard -// ------------------------ - -template -inline GenericTracerGuard::GenericTracerGuard( - MANAGED* managed) -: m_managed(managed) -{ -} - -template -inline GenericTracerGuard& -GenericTracerGuard::operator=(MANAGED* other) -{ - reset(other); - return *this; -} - -template -inline GenericTracerGuard::~GenericTracerGuard() -{ - reset(); -} - -template -inline MANAGED* -GenericTracerGuard::get() const -{ - return m_managed; -} - -template -inline MANAGED& GenericTracerGuard::operator*() const -{ - return *m_managed; -} - -template -inline MANAGED* GenericTracerGuard::operator->() const -{ - return m_managed; -} - -template -inline MANAGED* -GenericTracerGuard::release() -{ - MANAGED* const tmp = m_managed; - m_managed = NULL; - return tmp; -} - -template -inline void -GenericTracerGuard::reset(MANAGED* const other) -{ - if (m_managed) - { - TRACER::instance()->cleanup(m_managed); - } - m_managed = other; -} - -} // namespace opentracing -#endif // INCLUDED_OPENTRACING_TRACERGUARDS_H diff --git a/test/carriers.h b/test/carriers.h index 11e187d..2b39090 100644 --- a/test/carriers.h +++ b/test/carriers.h @@ -32,14 +32,14 @@ struct TestTextReader : public GenericTextReader { struct TestBinaryWriter : public GenericBinaryWriter { int - injectImp(const void* buf, const size_t len) + injectImp(const std::vector& buf) { - if (len > sizeof(m_raw)) + if (buf.size() > sizeof(m_raw)) { return 1; } - std::memcpy(&m_raw, buf, len); + std::memcpy(&m_raw, &buf[0], buf.size()); return 0; } @@ -48,15 +48,10 @@ struct TestBinaryWriter : public GenericBinaryWriter { struct TestBinaryReader : public GenericBinaryReader { int - extractImp(void* const buf, size_t* const written, const size_t len) const + extractImp(std::vector* const buf) const { - if (sizeof(m_raw) > len) - { - return 1; - } - - std::memcpy(buf, &m_raw, sizeof(m_raw)); - *written = sizeof(m_raw); + buf->resize(sizeof(m_raw)); + std::memcpy(&(*buf)[0], &m_raw, sizeof(m_raw)); return 0; } diff --git a/test/carriers.t.cc b/test/carriers.t.cc index 95da1d1..e8c4a02 100644 --- a/test/carriers.t.cc +++ b/test/carriers.t.cc @@ -63,19 +63,14 @@ TEST(Carriers, BinaryReader) BinaryReader& t = imp; - char smallbuf[3]; // too small for int32_t - size_t written = 0; + std::vector buf; - int rc = t.extract(smallbuf, &written, sizeof(smallbuf)); - ASSERT_NE(0, rc); - - char buf[100]; - rc = t.extract(buf, &written, sizeof(buf)); + int rc = t.extract(&buf); ASSERT_EQ(0, rc); - ASSERT_EQ(written, sizeof(imp.m_raw)); + ASSERT_EQ(buf.size(), sizeof(imp.m_raw)); int32_t out = 0; - std::memcpy(&out, buf, written); + std::memcpy(&out, &buf[0], buf.size()); ASSERT_EQ(out, imp.m_raw); } @@ -87,14 +82,20 @@ TEST(Carriers, BinaryWriter) const int64_t tooBig= 0x00000000deadbeef; - int rc = t.inject(&tooBig, sizeof(tooBig)); + std::vector buf; + buf.resize(sizeof(tooBig)); + std::memcpy(&buf[0], &tooBig, sizeof(tooBig)); + + int rc = t.inject(buf); ASSERT_NE(0, rc); const int32_t expected = 0xdeadbeef; - rc = t.inject(&expected, sizeof(expected)); - ASSERT_EQ(0, rc); + buf.resize(sizeof(expected)); + std::memcpy(&buf[0], &expected, sizeof(expected)); + rc = t.inject(buf); + ASSERT_EQ(0, rc); ASSERT_EQ(expected, imp.m_raw); } diff --git a/test/noop.t.cc b/test/noop.t.cc index e9b374e..4a4f284 100644 --- a/test/noop.t.cc +++ b/test/noop.t.cc @@ -45,24 +45,29 @@ TEST_F(NoopTracerEnv, Intantiation){ TEST_F(NoopTracerEnv, StartWithOp) { - GlobalTracer::SpanGuard guard(GlobalTracer::instance()->start("hello")); - EXPECT_TRUE(guard.get()); + GlobalTracer::Span* span(GlobalTracer::start("hello")); + EXPECT_TRUE(span); int rc = 0; - rc = guard->log("server", "blahblahblah"); + rc = span->log("server", "blahblahblah"); ASSERT_EQ(0, rc); - rc = guard->context().setBaggage("hello", "world"); + rc = span->context().setBaggage("hello", "world"); ASSERT_EQ(0, rc); - rc = guard->context().setBaggage("apple", "banana"); + rc = span->context().setBaggage("apple", "banana"); ASSERT_EQ(0, rc); - GlobalTracer::SpanContext::BaggageValue val; - rc = guard->context().getBaggage(&val, "apple"); + std::string val; + rc = span->context().getBaggage("apple", &val); + ASSERT_NE(0, rc); + std::vector vals; + rc = span->context().getBaggage("apple", &vals); ASSERT_NE(0, rc); + + GlobalTracer::cleanup(span); } TEST_F(NoopTracerEnv, StartWithOpAndParent) @@ -73,22 +78,24 @@ TEST_F(NoopTracerEnv, StartWithOpAndParent) // test dependent on those other interfaces, I'm going to just pull // a context out of thin air to test the interface. - GlobalTracer::SpanGuard guard(GlobalTracer::instance()->start("hello")); - EXPECT_TRUE(guard.get()); + GlobalTracer::Span* guard(GlobalTracer::start("hello")); + EXPECT_TRUE(guard); } TEST_F(NoopTracerEnv, InjectText) { TestTextWriter writer; - GlobalTracer::SpanGuard g(GlobalTracer::instance()->start("op")); - ASSERT_TRUE(g.get()); + GlobalTracer::Span* span(GlobalTracer::start("op")); + ASSERT_TRUE(span); - g->context().setBaggage("animal", "tiger"); - g->context().setBaggage("animal", "cat"); + span->context().setBaggage("animal", "tiger"); + span->context().setBaggage("animal", "cat"); - int rc = GlobalTracer::instance()->inject(&writer, g->context()); + int rc = GlobalTracer::inject(&writer, span->context()); ASSERT_EQ(0, rc); + + GlobalTracer::cleanup(span); } TEST_F(NoopTracerEnv, ExtractText) @@ -98,39 +105,43 @@ TEST_F(NoopTracerEnv, ExtractText) reader.pairs.push_back(TextMapPair("fruit", "apple")); reader.pairs.push_back(TextMapPair("veggie", "carrot")); - GlobalTracer::SpanContextGuard g(GlobalTracer::instance()->extract(reader)); - ASSERT_TRUE(g.get()); + const GlobalTracer::SpanContext* context(GlobalTracer::extract(reader)); + ASSERT_TRUE(context); size_t index = 0; const char * names[] = {"animal", "fruit", "veggie"}; const char * values[] = {"tiger", "apple", "carrot"}; - for (GlobalTracer::SpanContext::BaggageIterator it = g->baggageBegin(); - it != g->baggageEnd(); + for (GlobalTracer::SpanContext::BaggageIterator it = context->baggageBegin(); + it != context->baggageEnd(); ++it) { ASSERT_STREQ(names[index], it.ref().key()); ASSERT_STREQ(values[index], it.ref().value()); ++index; } + + GlobalTracer::cleanup(context); } TEST_F(NoopTracerEnv, InjectBinary) { TestBinaryWriter writer; - GlobalTracer::SpanGuard g(GlobalTracer::instance()->start("op")); - ASSERT_TRUE(g.get()); - int rc = GlobalTracer::instance()->inject(&writer, g->context()); + GlobalTracer::Span* span = GlobalTracer::start("op"); + ASSERT_TRUE(span); + int rc = GlobalTracer::inject(&writer, span->context()); ASSERT_EQ(0, rc); + GlobalTracer::cleanup(span); } TEST_F(NoopTracerEnv, ExtractBinary) { TestBinaryReader reader; reader.m_raw = 0xdeadbeef; - GlobalTracer::SpanContextGuard g(GlobalTracer::instance()->extract(reader)); - ASSERT_TRUE(g.get()); + const GlobalTracer::SpanContext* context(GlobalTracer::extract(reader)); + ASSERT_TRUE(context); + GlobalTracer::cleanup(context); } struct NoopWriter: public GenericWriter @@ -144,10 +155,12 @@ struct NoopWriter: public GenericWriter TEST_F(NoopTracerEnv, InjectExplicit) { NoopWriter w; - GlobalTracer::SpanGuard g(GlobalTracer::instance()->start("span")); - ASSERT_TRUE(g.get()); - int rc = GlobalTracer::instance()->inject(&w, g->context()); + GlobalTracer::Span* span(GlobalTracer::start("span")); + ASSERT_TRUE(span); + int rc = GlobalTracer::inject(&w, span->context()); ASSERT_EQ(0, rc); + + GlobalTracer::cleanup(span); } struct NoopReader : public GenericReader @@ -161,24 +174,29 @@ struct NoopReader : public GenericReader TEST_F(NoopTracerEnv, ExtractExplicit) { NoopReader r; - GlobalTracer::SpanContextGuard g(GlobalTracer::instance()->extract(r)); - ASSERT_TRUE(g.get()); + const GlobalTracer::SpanContext* context(GlobalTracer::extract(r)); + ASSERT_TRUE(context); + GlobalTracer::cleanup(context); } TEST_F(NoopTracerEnv, StartWithOpts) { NoopReader r; - GlobalTracer::SpanContextGuard otherContext(GlobalTracer::instance()->extract(r)); - ASSERT_TRUE(otherContext.get()); + const GlobalTracer::SpanContext* otherContext(GlobalTracer::extract(r)); + ASSERT_TRUE(otherContext); - GlobalTracer::SpanOptionsGuard opts(GlobalTracer::instance()->makeSpanOptions()); + GlobalTracer::SpanOptions* opts(GlobalTracer::makeSpanOptions()); opts->setOperation("hello"); opts->setStartTime(1251251); - opts->addReference(SpanRelationship::e_FollowsFrom, *otherContext); + opts->setReference(SpanRelationship::e_FollowsFrom, *otherContext); - GlobalTracer::SpanGuard guard(GlobalTracer::instance()->start("hello")); - EXPECT_TRUE(guard.get()); + GlobalTracer::Span* span(GlobalTracer::start("hello")); + EXPECT_TRUE(span); + + GlobalTracer::cleanup(span); + GlobalTracer::cleanup(otherContext); + GlobalTracer::cleanup(opts); } template @@ -220,21 +238,27 @@ TYPED_TEST_CASE(NoopSpanTypeTests, OverloadedTypes); TYPED_TEST(NoopSpanTypeTests, TagInterface) { - GlobalTracer::SpanGuard span(GlobalTracer::instance()->start("hello world")); + GlobalTracer::Span* span(GlobalTracer::start("hello world")); int rc = span->tag("key", TypeParam()); ASSERT_EQ(0, rc); + + GlobalTracer::cleanup(span); } TYPED_TEST(NoopSpanTypeTests, LogInterface) { - GlobalTracer::SpanGuard span(GlobalTracer::instance()->start("hello world")); + GlobalTracer::Span* span(GlobalTracer::start("hello world")); int rc = span->log("key", TypeParam()); ASSERT_EQ(0, rc); + + GlobalTracer::cleanup(span); } TYPED_TEST(NoopSpanTypeTests, LogTspInterface) { - GlobalTracer::SpanGuard span(GlobalTracer::instance()->start("hello world")); + GlobalTracer::Span* span(GlobalTracer::start("hello world")); int rc = span->log("key", TypeParam(), 0); ASSERT_EQ(0, rc); + + GlobalTracer::cleanup(span); } diff --git a/test/span.t.cc b/test/span.t.cc index 090d715..6bcfb7b 100644 --- a/test/span.t.cc +++ b/test/span.t.cc @@ -12,15 +12,15 @@ TEST(Span, BasicTests) // Make sure const references work const TestSpan& tc = impl; - TestSpan::SpanContext::BaggageValues vals; - rc = tc.context().getBaggage(&vals, "hello"); + std::vector vals; + rc = tc.context().getBaggage("hello", &vals); ASSERT_EQ(0, rc); ASSERT_EQ(1u, vals.size()); ASSERT_EQ("world", vals[0]); const TestSpan::SpanContext& cc = tc.context(); - rc = cc.getBaggage(&vals, "miss"); + rc = cc.getBaggage("miss", &vals); ASSERT_NE(0, rc); TestSpan::SpanContext::BaggageIterator it = cc.baggageBegin(); diff --git a/test/spancontext.h b/test/spancontext.h index b2b5018..defbccc 100644 --- a/test/spancontext.h +++ b/test/spancontext.h @@ -41,11 +41,11 @@ class TestContextImpl } int - getBaggageImp(BaggageValue* const baggage, const StringRef& key) const + getBaggageImp(const StringRef& key, std::string* const baggage) const { std::vector out; - getBaggageImp(&out, key); + getBaggageImp(key, &out); if (1u == out.size()) { @@ -59,7 +59,8 @@ class TestContextImpl } int - getBaggageImp(BaggageValues* const baggage, const StringRef& key) const + getBaggageImp(const StringRef& key, + std::vector* const baggage) const { baggage->clear(); diff --git a/test/spancontext.t.cc b/test/spancontext.t.cc index 2863e14..f4c458b 100644 --- a/test/spancontext.t.cc +++ b/test/spancontext.t.cc @@ -12,14 +12,14 @@ TEST(GenericSpanContext, BaggageCopies) int rc = t.setBaggage("hello", "world"); ASSERT_EQ(0, rc); - TestContext::BaggageValues vals; - rc = t.getBaggage(&vals, "hello"); + std::vector vals; + rc = t.getBaggage("hello", &vals); ASSERT_EQ(0, rc); ASSERT_EQ(1u, vals.size()); ASSERT_EQ("world", vals[0]); - rc = t.getBaggage(&vals, "unknown"); + rc = t.getBaggage("unknown", &vals); ASSERT_NE(0, rc); ASSERT_TRUE(t.baggageBegin() != t.baggageEnd()); @@ -50,8 +50,8 @@ TEST(GenericSpanContext, CopyConstructor) TestContextImpl implCopy = impl; TestContext& tc = implCopy; - TestContext::BaggageValue val; - rc = tc.getBaggage(&val, "hello"); + std::string val; + rc = tc.getBaggage("hello", &val); ASSERT_EQ(0, rc); ASSERT_EQ("world", val); diff --git a/test/tracer.h b/test/tracer.h index 2f16787..ac79156 100644 --- a/test/tracer.h +++ b/test/tracer.h @@ -24,7 +24,7 @@ class TestOptionsImpl : public GenericSpanOptionsinject(&deadbeef, sizeof(deadbeef)); + std::vector buf(sizeof(deadbeef)); + buf.resize(sizeof(deadbeef)); + std::memcpy(&buf[0], &deadbeef, sizeof(deadbeef)); + + return carrier->inject(buf); } template @@ -128,14 +132,17 @@ class TestTracerImpl : public GenericTracer& carrier) { - size_t written = 0; - int output = 0; + const int expected = 0xdeadbeef; + + std::vector buf; - if (int rc = carrier.extract(&output, &written, sizeof(output))) + if (int rc = carrier.extract(&buf)) { return NULL; } - else if (output == 0xdeadbeef) + + if (buf.size() == sizeof(expected) && + expected == *(reinterpret_cast(&buf[0]))) { return new TestContextImpl(); } diff --git a/test/tracer.t.cc b/test/tracer.t.cc index e8aaa84..ac15b9a 100644 --- a/test/tracer.t.cc +++ b/test/tracer.t.cc @@ -29,49 +29,48 @@ TEST_F(TracerEnv, SingletonTests) TEST_F(TracerEnv, StartWithOp) { - Tracer::SpanGuard guardOrig(Tracer::instance()->start("hello")); - Tracer::SpanGuard guard(guardOrig.release()); - - EXPECT_TRUE(guard.get()); + Tracer::Span * span = Tracer::start("hello"); + ASSERT_TRUE(span); int rc = 0; - rc = guard->log("server", "blahblahblah"); + rc = span->log("server", "blahblahblah"); ASSERT_EQ(0, rc); - rc = guard->context().setBaggage("hello", "world"); + rc = span->context().setBaggage("hello", "world"); ASSERT_EQ(0, rc); - rc = guard->context().setBaggage("apple", "banana"); + rc = span->context().setBaggage("apple", "banana"); ASSERT_EQ(0, rc); - Tracer::SpanContext::BaggageValues vals; - rc = guard->context().getBaggage(&vals, "apple"); + std::vector vals; + rc = span->context().getBaggage("apple", &vals); ASSERT_EQ(0, rc); ASSERT_EQ(1u, vals.size()); ASSERT_EQ("banana", vals[0]); - Tracer::SpanContext::BaggageValue val; - rc = guard->context().getBaggage(&val, "apple"); + std::string val; + rc = span->context().getBaggage("apple", &val); ASSERT_EQ(0, rc); ASSERT_EQ("banana", val); + + Tracer::cleanup(span); } TEST_F(TracerEnv, InjectText) { TestTextWriter writer; - Tracer::SpanGuard span(Tracer::instance()->start("op")); - ASSERT_TRUE(span.get()); + Tracer::Span* span(Tracer::start("op")); + ASSERT_TRUE(span); span->context().setBaggage("animal", "tiger"); span->context().setBaggage("animal", "cat"); - int rc = Tracer::instance()->inject(&writer, span->context()); + int rc = Tracer::inject(&writer, span->context()); ASSERT_EQ(0, rc); - ASSERT_EQ(2u, writer.pairs.size()); ASSERT_EQ(writer.pairs[0].m_name, "animal"); @@ -79,8 +78,9 @@ TEST_F(TracerEnv, InjectText) ASSERT_TRUE(writer.pairs[0].m_value == "cat" || writer.pairs[0].m_value == "tiger"); ASSERT_TRUE(writer.pairs[1].m_value == "cat" || writer.pairs[1].m_value == "tiger"); -} + Tracer::cleanup(span); +} TEST_F(TracerEnv, ExtractText) { @@ -89,8 +89,8 @@ TEST_F(TracerEnv, ExtractText) reader.pairs.push_back(TextMapPair("fruit", "apple")); reader.pairs.push_back(TextMapPair("veggie", "carrot")); - Tracer::SpanContextGuard context(Tracer::instance()->extract(reader)); - ASSERT_TRUE(context.get()); + const Tracer::SpanContext* context(Tracer::extract(reader)); + ASSERT_TRUE(context); size_t index = 0; @@ -105,16 +105,18 @@ TEST_F(TracerEnv, ExtractText) ASSERT_STREQ(values[index], it.ref().value()); ++index; } + + Tracer::cleanup(context); } TEST_F(TracerEnv, InjectBinary) { TestBinaryWriter writer; - Tracer::SpanGuard span(Tracer::instance()->start("op")); - ASSERT_TRUE(span.get()); + Tracer::Span* span(Tracer::start("op")); + ASSERT_TRUE(span); - int rc = Tracer::instance()->inject(&writer, span->context()); + int rc = Tracer::inject(&writer, span->context()); ASSERT_EQ(0, rc); ASSERT_EQ(0xdeadbeef, writer.m_raw); } @@ -124,8 +126,10 @@ TEST_F(TracerEnv, ExtractBinary) TestBinaryReader reader; reader.m_raw = 0xdeadbeef; - Tracer::SpanContextGuard context(Tracer::instance()->extract(reader)); - ASSERT_TRUE(context.get()); + const Tracer::SpanContext* context(Tracer::extract(reader)); + ASSERT_TRUE(context); + + Tracer::cleanup(context); } @@ -133,13 +137,13 @@ TEST_F(TracerEnv, InjectExplicit) { TestWriter w; - Tracer::SpanGuard span(Tracer::instance()->start("span")); - ASSERT_TRUE(span.get()); + Tracer::Span* span(Tracer::start("span")); + ASSERT_TRUE(span); span->context().setBaggage("animal", "tiger"); span->context().setBaggage("fruit", "apple"); - int rc = Tracer::instance()->inject(&w, span->context()); + int rc = Tracer::inject(&w, span->context()); ASSERT_EQ(0, rc); ASSERT_EQ(2u, w.carrier.size()); @@ -151,6 +155,8 @@ TEST_F(TracerEnv, InjectExplicit) cit = w.carrier.find("fruit"); ASSERT_NE(cit, w.carrier.end()); ASSERT_EQ("apple", cit->second); + + Tracer::cleanup(span); } TEST_F(TracerEnv, ExtractExplicit) @@ -158,8 +164,10 @@ TEST_F(TracerEnv, ExtractExplicit) TestReader reader; reader.carrier.insert(TestBaggageContainer::value_type("animal", "tiger")); reader.carrier.insert(TestBaggageContainer::value_type("fruit", "apple")); - Tracer::SpanContextGuard context(Tracer::instance()->extract(reader)); - ASSERT_TRUE(context.get()); + const Tracer::SpanContext* context(Tracer::extract(reader)); + ASSERT_TRUE(context); + + Tracer::cleanup(context); } TEST_F(TracerEnv, StartWithOptions) @@ -167,15 +175,20 @@ TEST_F(TracerEnv, StartWithOptions) TestReader reader; reader.carrier.insert(TestBaggageContainer::value_type("animal", "tiger")); reader.carrier.insert(TestBaggageContainer::value_type("fruit", "apple")); - Tracer::SpanContextGuard otherContext(Tracer::instance()->extract(reader)); - ASSERT_TRUE(otherContext.get()); + const Tracer::SpanContext* otherContext(Tracer::extract(reader)); + ASSERT_TRUE(otherContext); - Tracer::SpanOptionsGuard opts(Tracer::instance()->makeSpanOptions()); + Tracer::SpanOptions* opts(Tracer::makeSpanOptions()); + ASSERT_TRUE(opts); opts->setOperation("test"); opts->setStartTime(12414); - opts->addReference(SpanRelationship::e_ChildOf, *otherContext); + opts->setReference(SpanRelationship::e_ChildOf, *otherContext); + + Tracer::Span* span(Tracer::start(*opts)); + ASSERT_TRUE(span); - Tracer::SpanGuard span(Tracer::instance()->start(*opts)); - EXPECT_TRUE(span.get()); + Tracer::cleanup(otherContext); + Tracer::cleanup(opts); + Tracer::cleanup(span); } From a8b901701bc98ad08a05db3427f5cc46433564df Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Tue, 10 Jan 2017 17:22:08 -0500 Subject: [PATCH 25/48] Moving noop into its own package, updated tests --- docs/usage.md | 12 ++++---- noop/Makefile | 29 ++++++++++++++++++++ noop/noop.cc | 5 ++++ {opentracing => noop}/noop.h | 24 ++++++++++++++++ opentracing/tracer.h | 53 +++++++++++++++++------------------- test/Makefile | 18 +++++------- test/noop.t.cc | 4 +-- test/tracer.h | 15 ++++++++++ test/tracer.t.cc | 2 ++ 9 files changed, 114 insertions(+), 48 deletions(-) create mode 100644 noop/Makefile create mode 100644 noop/noop.cc rename {opentracing => noop}/noop.h (96%) diff --git a/docs/usage.md b/docs/usage.md index 409e075..4593ba4 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -5,7 +5,7 @@ API. It assumes you have finished the required reading outlined [here](../README ### Outline -The `opentracing-cpp` interface uses the [Curiously Repeating Template Pattern](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) +The `opentracing-cpp` interface uses the [Curiously Recurring Template Pattern](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) (CRTP) to define a set of compile time, polymorphic interfaces to `OpenTracing` implementations. In order to trace their systems, clients must: @@ -64,9 +64,6 @@ types: - `Tracer::Span` - Interface to Span objects - `Tracer::SpanContext` - Interface to SpanContext objects - `Tracer::SpanOptions` - Interface to SpanOptions objects - - `Tracer::SpanGuard` - RAII Wrappers for Spans - - `Tracer::SpanOptionsGuard` - RAII Wrappers for SpanOptions - - `Tracer::SpanContextGuard` - RAII Wrappers for SpanContexts Our theoretical "ACME Inc." organization can use these type names to instrument their applications. The `Tracer` typedef is not standardized, but it is recommended. The rest of the documentation @@ -201,14 +198,15 @@ struct HttpReader: public GenericBinaryReader { std::string header = m_req.getHeader("x-acme-tracing-blob"); - if(!header.empty()){ + if (!header.empty()) + { buf->assign(header.begin(), header.end()); return 0; } - else { + else + { return 1; } - return 0; } private: diff --git a/noop/Makefile b/noop/Makefile new file mode 100644 index 0000000..849ce8d --- /dev/null +++ b/noop/Makefile @@ -0,0 +1,29 @@ +CC=g++ + +OPENTRACING_INCLUDE=../ +NOOP_INCLUDE=../noop + +INCLUDES=-I. -I$(OPENTRACING_INCLUDE) -I$(NOOP_INCLUDE) + +CXXFLAGS=-Wall -fno-elide-constructors -Wextra -Wall -Winit-self -Wold-style-cast -Woverloaded-virtual -Winit-self -Wuninitialized -Wmissing-declarations -Werror $(INCLUDES) + +LDFLAGS= + +LDIR =${GTEST_LIBS} + +LIBS=-L${GTEST_LIBS} -lgtest -lpthread + +ODIR=. +_OBJ = noop.o +OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) + +$(ODIR)/%.o: %.cc %.h + $(CC) -c -o $@ $< $(CXXFLAGS) + +all: $(OBJ) + +.PHONY: clean + +clean: + rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ + diff --git a/noop/noop.cc b/noop/noop.cc new file mode 100644 index 0000000..891be4d --- /dev/null +++ b/noop/noop.cc @@ -0,0 +1,5 @@ +#include + +namespace opentracing { +NoopTracer* NoopTracer::s_tracer = 0; +} diff --git a/opentracing/noop.h b/noop/noop.h similarity index 96% rename from opentracing/noop.h rename to noop/noop.h index 74c983c..7166a70 100644 --- a/opentracing/noop.h +++ b/noop/noop.h @@ -144,6 +144,10 @@ class NoopTracer : public GenericTracer { public: + static void installImp(NoopTracer *const); + static NoopTracer * instanceImp(); + static void uninstallImp(); + NoopOptions* makeSpanOptionsImp(); void cleanupImp(const NoopOptions* const opts); @@ -175,6 +179,8 @@ class NoopTracer : public GenericTracer // { // public: +// static TracerImp * instanceImp(); +// // Options * makeSpanOptionsImp(); // void cleanupImp(const Options * const opts); // @@ -199,23 +201,12 @@ class GenericTracer { GenericTracer(); GenericTracer(const GenericTracer&); // Protected to avoid direct construction - - private: - static GenericTracer* s_tracer; }; // ------------------- // class GenericTracer // ------------------- -template -GenericTracer* - GenericTracer::s_tracer = 0; - template ::install( GenericTracer* const tracer) { - s_tracer = tracer; + TRACER * const tracerImp = static_cast(tracer); + TRACER::installImp(tracerImp); } template ::uninstall() { - s_tracer = 0; + return TRACER::uninstallImp(); } template * GenericTracer::instance() { - return s_tracer; + return TRACER::instanceImp(); } template ::SpanOptions* GenericTracer::makeSpanOptions() { - return static_cast(s_tracer)->makeSpanOptionsImp(); + return TRACER::instanceImp()->makeSpanOptionsImp(); } template ::cleanup( SpanOptions* const opts) { OPTIONS* const optsImp = static_cast(opts); - return static_cast(s_tracer)->cleanupImp(optsImp); + return TRACER::instanceImp()->cleanupImp(optsImp); } template ::Span* GenericTracer::start(const StringRef& op) { - return static_cast(s_tracer)->startImp(op); + return TRACER::instanceImp()->startImp(op); } template ::Span* GenericTracer::start(const SpanOptions& opts) { const OPTIONS& optsImp = static_cast(opts); - return static_cast(s_tracer)->startImp(optsImp); + return TRACER::instanceImp()->startImp(optsImp); } template ::cleanup(Span* const sp) { SPAN* const spanImp = static_cast(sp); - return static_cast(s_tracer)->cleanupImp(spanImp); + return TRACER::instanceImp()->cleanupImp(spanImp); } template ::inject( GenericTextWriter* const carrier, const SpanContext& context) { const CONTEXT& contextImp = static_cast(context); - return static_cast(s_tracer)->injectImp(carrier, contextImp); + const TRACER* tracer = TRACER::instanceImp(); + + return tracer->injectImp(carrier, contextImp); } template ::inject( GenericBinaryWriter* const carrier, const SpanContext& context) { - const CONTEXT& contextImp = static_cast(context); - return static_cast(s_tracer)->injectImp(carrier, contextImp); + const CONTEXT& contextImp = static_cast(context); + const TRACER* const tracer = TRACER::instanceImp(); + + return tracer->injectImp(carrier, contextImp); } template ::inject( GenericWriter* const carrier, const SpanContext& context) { - const CONTEXT& contextImp = static_cast(context); - return static_cast(s_tracer)->injectImp(carrier, contextImp); + const CONTEXT& contextImp = static_cast(context); + const TRACER* const tracer = TRACER::instanceImp(); + return tracer->injectImp(carrier, contextImp); } template :: GenericTracer::extract( const GenericTextReader& carrier) { - return static_cast(s_tracer)->extractImp(carrier); + return TRACER::instanceImp()->extractImp(carrier); } template :: GenericTracer::extract( const GenericBinaryReader& carrier) { - return static_cast(s_tracer)->extractImp(carrier); + return TRACER::instanceImp()->extractImp(carrier); } template :: GenericTracer::extract( const GenericReader& carrier) { - return static_cast(s_tracer)->extractImp(carrier); + return TRACER::instanceImp()->extractImp(carrier); } template ::cleanup( const SpanContext* const spc) { const CONTEXT* const contextImp = static_cast(spc); - return static_cast(s_tracer)->cleanupImp(contextImp); + return TRACER::instanceImp()->cleanupImp(contextImp); } } // namespace opentracing diff --git a/test/Makefile b/test/Makefile index f429544..f23050b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,35 +1,31 @@ CC=g++ OPENTRACING_INCLUDE=../ -OPENTRACING_SRC=$(wildcard ${OPENTRACING_INCLUDE}/*.h) +NOOP_INCLUDE=../noop THIRDPARTY_ROOT=../thirdparty GTEST_INCLUDE=${THIRDPARTY_ROOT}/googletest/googletest/include GTEST_LIBS=${THIRDPARTY_ROOT}/ -INCLUDES=-I. -I${GTEST_INCLUDE} -I${OPENTRACING_INCLUDE} +INCLUDES=-I. -I$(GTEST_INCLUDE) -I$(OPENTRACING_INCLUDE) -I$(NOOP_INCLUDE) -CXXFLAGS=-Wall -fno-elide-constructors -Wextra -Wall -Winit-self -Wold-style-cast -Woverloaded-virtual -Winit-self -Wuninitialized -Wmissing-declarations -Werror ${INCLUDES} - -# 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/ +CXXFLAGS=-Wall -fno-elide-constructors -Wextra -Wall -Winit-self -Wold-style-cast -Woverloaded-virtual -Winit-self -Wuninitialized -Wmissing-declarations -Werror $(INCLUDES) LDFLAGS= -ODIR=. LDIR =${GTEST_LIBS} LIBS=-L${GTEST_LIBS} -lgtest -lpthread +ODIR=. _OBJ = stringref.t.o baggage.t.o spancontext.t.o span.t.o carriers.t.o tracer.t.o noop.t.o unittest.t.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) -$(ODIR)/%.o: %.cc %.h ${OPENTRACING_SRC} +$(ODIR)/%.o: %.cc %.h $(CC) -c -o $@ $< $(CXXFLAGS) -test: $(OBJ) - $(CC) -o $@ $^ $(CXXFLAGS) $(LIBS) $(LDFLAGS) +test: $(OBJ) ../noop/noop.o + $(CC) -o $@ $^ $(CXXFLAGS) $(LIBS) $(LDFLAGS) .PHONY: clean diff --git a/test/noop.t.cc b/test/noop.t.cc index 4a4f284..c29a5c0 100644 --- a/test/noop.t.cc +++ b/test/noop.t.cc @@ -2,8 +2,8 @@ #include "carriers.h" -#include -#include // test include guard +#include +#include // test include guard // These run the same tests as the tracer.t.cc. The interface should be the // same, however, there may be some differences in return codes due diff --git a/test/tracer.h b/test/tracer.h index ac79156..fde8ece 100644 --- a/test/tracer.h +++ b/test/tracer.h @@ -29,12 +29,27 @@ class TestOptionsImpl : public GenericSpanOptions { public: + static TestTracerImpl* s_tracer; + + static void installImp(TestTracerImpl * const inst){ + s_tracer = inst; + } + + static TestTracerImpl * instanceImp(){ + return s_tracer; + } + + static void uninstallImp(){ + s_tracer = 0; + } + TestOptionsImpl * makeSpanOptionsImp() { return new TestOptionsImpl(); diff --git a/test/tracer.t.cc b/test/tracer.t.cc index ac15b9a..d8b9567 100644 --- a/test/tracer.t.cc +++ b/test/tracer.t.cc @@ -3,6 +3,8 @@ #include "carriers.h" +TestTracerImpl* TestTracerImpl::s_tracer = 0; + class TracerEnv : public ::testing::Test { public: virtual void From ef885ee4ee236e272ec05cded206e7df7d117701 Mon Sep 17 00:00:00 2001 From: vagrant Date: Tue, 10 Jan 2017 22:23:58 +0000 Subject: [PATCH 26/48] Update reqs for tracerimps --- opentracing/tracer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opentracing/tracer.h b/opentracing/tracer.h index 329d989..43ddcb0 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -48,7 +48,9 @@ namespace opentracing { // GenericTracer // { // public: +// static installImp(TracerImp*); // static TracerImp * instanceImp(); +// static uninstallImp(); // // Options * makeSpanOptionsImp(); // void cleanupImp(const Options * const opts); From bde35455b539912a49ddf6f4a4608bb8b55b1756 Mon Sep 17 00:00:00 2001 From: vagrant Date: Wed, 11 Jan 2017 05:51:29 +0000 Subject: [PATCH 27/48] Clean up build system, ability to turn off no-op, integrate tests --- .gitignore | 5 + AUTHORS | 4 +- CMakeLists.txt | 42 ++++ ChangeLog | 1 - Makefile.am | 14 -- autogen.sh | 6 - configure.ac | 28 --- noop/Makefile | 29 --- opentracing-cpp.pc.in | 14 ++ opentracing.pc.in | 10 - opentracing/CMakeLists.txt | 29 +++ opentracing/Makefile.am | 0 opentracing/baggage.h | 133 +++++------ opentracing/carriers.h | 5 - {noop => opentracing}/noop.cc | 2 +- {noop => opentracing}/noop.h | 4 - opentracing/span.h | 4 - opentracing/spanoptions.h | 4 - opentracing/stringref.h | 135 ++++------- opentracing/tracer.h | 5 - test/CMakeLists.txt | 26 +++ test/Makefile | 427 ++++++++++++++++++++++++++++++++-- test/noop.t.cc | 4 +- test/stringref.t.cc | 95 -------- test/unittest.h | 13 +- thirdparty/build-gtest.sh | 8 - thirdparty/googletest | 2 +- 27 files changed, 631 insertions(+), 418 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 Makefile.am delete mode 100755 autogen.sh delete mode 100644 configure.ac delete mode 100644 noop/Makefile create mode 100644 opentracing-cpp.pc.in delete mode 100644 opentracing.pc.in create mode 100644 opentracing/CMakeLists.txt delete mode 100644 opentracing/Makefile.am rename {noop => opentracing}/noop.cc (68%) rename {noop => opentracing}/noop.h (99%) create mode 100644 test/CMakeLists.txt delete mode 100755 thirdparty/build-gtest.sh diff --git a/.gitignore b/.gitignore index ba00878..ba71fb0 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,8 @@ install-sh libtool ltmain.sh missing +CMakeFiles +*.cmake +bin/ +build/ +test/unittest diff --git a/AUTHORS b/AUTHORS index d9b736a..67659b0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,6 +1,6 @@ AUTHORS ------- - - OpenTracing Developers +Jim Quinn - jquinn47@bloomberg.net + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7b66393 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required (VERSION 2.8) +set(PROJECT_NAME "opentracing-cpp") +project (${PROJECT_NAME}) + +set(opentracing_url "https://github.com/opentracing/opentracing-cpp") +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(CMAKE_CXX_FLAGS "-g -Wall -Werror -Wextra -Wfloat-equal") + +option(enable_noop "Build noop tracer." OFF) +option(enable_tests "Build unit tests." OFF) + +if(NOT libdir) + set(libdir "lib") +endif() + +if(NOT includedir) + set(includedir "include") +endif() + +set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${include}") +set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${libdir}") + +add_subdirectory(opentracing) + +if(enable_tests) + enable_testing() + add_subdirectory(thirdparty/googletest) + add_subdirectory(test) +endif() + +# pkg-config +# Defaults for .pc file, but can be overridden when cmake is run + + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + @ONLY) + diff --git a/ChangeLog b/ChangeLog index 7a1533c..18a91d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,3 @@ - opentracing-cpp ChangeLog * initial release diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index 1a88708..0000000 --- a/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -AUTOMAKE_OPTIONS = gnu - -lib_LTLIBRARIES = - -nobase_include_HEADERS = opentracing/*.h - -ACLOCAL_AMFLAGS = -I m4 - -AM_CXXFLAGS= -fno-elide-constructors -pedantic-errors -ansi - -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/autogen.sh b/autogen.sh deleted file mode 100755 index 7ef875f..0000000 --- a/autogen.sh +++ /dev/null @@ -1,6 +0,0 @@ -#! /bin/sh - -aclocal \ -&& autoheader \ -&& automake --add-missing \ -&& autoconf diff --git a/configure.ac b/configure.ac deleted file mode 100644 index e0c4690..0000000 --- a/configure.ac +++ /dev/null @@ -1,28 +0,0 @@ -AC_INIT([libopentracing], [2.0.0]) - -AC_PACKAGE_URL([https://github.com/opentracing/opentracing-cpp]) -AC_PACKAGE_BUGREPORT([https://github.com/opentracing/opentracing-cpp/issues]) -AC_CONFIG_HEADERS([opentracing/config.h]) - -AM_INIT_AUTOMAKE([subdir-objects]) -AM_CONDITIONAL(COMPILER_IS_GCC, test "x$GCC" = "xyes") - -AC_CONFIG_MACRO_DIR([m4]) -AM_PROG_LIBTOOL -AC_PROG_INSTALL - -AC_PROG_CXX -AC_PROG_MAKE_SET - -AC_INCLUDES_DEFAULT -AC_HEADER_ASSERT -AC_TYPE_INT16_T -AC_TYPE_INT32_T -AC_TYPE_INT64_T -AC_TYPE_UINT16_T -AC_TYPE_UINT32_T -AC_TYPE_UINT64_T -AC_TYPE_SIZE_T - -AC_CONFIG_FILES([ Makefile opentracing.pc ]) -AC_OUTPUT diff --git a/noop/Makefile b/noop/Makefile deleted file mode 100644 index 849ce8d..0000000 --- a/noop/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -CC=g++ - -OPENTRACING_INCLUDE=../ -NOOP_INCLUDE=../noop - -INCLUDES=-I. -I$(OPENTRACING_INCLUDE) -I$(NOOP_INCLUDE) - -CXXFLAGS=-Wall -fno-elide-constructors -Wextra -Wall -Winit-self -Wold-style-cast -Woverloaded-virtual -Winit-self -Wuninitialized -Wmissing-declarations -Werror $(INCLUDES) - -LDFLAGS= - -LDIR =${GTEST_LIBS} - -LIBS=-L${GTEST_LIBS} -lgtest -lpthread - -ODIR=. -_OBJ = noop.o -OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) - -$(ODIR)/%.o: %.cc %.h - $(CC) -c -o $@ $< $(CXXFLAGS) - -all: $(OBJ) - -.PHONY: clean - -clean: - rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ - diff --git a/opentracing-cpp.pc.in b/opentracing-cpp.pc.in new file mode 100644 index 0000000..784e2e9 --- /dev/null +++ b/opentracing-cpp.pc.in @@ -0,0 +1,14 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +libdir=${prefix}/@libdir@ +includedir=${prefix}/@includedir@ + +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.pc.in b/opentracing.pc.in deleted file mode 100644 index 796c6cd..0000000 --- a/opentracing.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir - -Name: OpenTracing C++ -Description: C++ interface for the OpenTracing specification -URL: https://github.com/opentracing/opentracing-cpp -Version: 0.0.1 -Cflags: -I${includedir} diff --git a/opentracing/CMakeLists.txt b/opentracing/CMakeLists.txt new file mode 100644 index 0000000..c97dcdc --- /dev/null +++ b/opentracing/CMakeLists.txt @@ -0,0 +1,29 @@ +include_directories(${CMAKE_SOURCE_DIR}) + +if(enable_noop) + set(opentracing_libs "-L${libdir} -lopentracing-cpp") +endif() + +set(headers + baggage.h + carriers.h + constants.h + spancontext.h + span.h + spanoptions.h + stringref.h + tracer.h) + +if(enable_noop) + set(headers ${headers} noop.h) + + add_library(opentracing-cpp STATIC noop.cc) + + install (TARGETS opentracing-cpp + DESTINATION ${LIB_INSTALL_DIR} + COMPONENT dev) +endif() + +install (FILES ${headers} + DESTINATION ${INCLUDE_INSTALL_DIR}/opentracing + COMPONENT dev) diff --git a/opentracing/Makefile.am b/opentracing/Makefile.am deleted file mode 100644 index e69de29..0000000 diff --git a/opentracing/baggage.h b/opentracing/baggage.h index 3da490e..4e7c987 100644 --- a/opentracing/baggage.h +++ b/opentracing/baggage.h @@ -4,11 +4,8 @@ // ========= // baggage.h // ========= -// class BaggageImp - Client wrapper for copies of key:value pairs -// class Baggage - Typedef for Baggage working with char -// -// class BaggageRefImp - Client wrapper for referencing key:value pairs -// class BaggageRef - Typedef for BaggageRef working with char +// class Baggage - Client wrapper for copies of key:value pairs +// class BaggageRef - Client wrapper for referencing key:value pairs // // class BaggageIteratorImp - Client interface to traverse span baggage // class BaggageRangeImp - A range of BaggageIterators @@ -27,7 +24,7 @@ // // Use this feature thoughtfully and with care. Every key and value is copied // into every local and remote child of the associated Span, and that can add up -// to a lot of network and cpu overhead. +// to a lot of network and CPU overhead. // // See: https://github.com/opentracing/specification @@ -35,50 +32,47 @@ namespace opentracing { -// ================ -// class BaggageImp -// ================ +// ============= +// class Baggage +// ============= // This class copies to the key:value pairs stored in SpanContexts. Once the // value is returned, clients are free to move it around as they see fit. // Baggage is the default value returned by iterators when they are // dereferenced. -template -class BaggageImp { +class Baggage { public: - BaggageImp(); + Baggage(); // Construct a Baggage with empty values. - BaggageImp(const StringRefImp& key, const StringRefImp& value); + Baggage(const StringRef& key, const StringRef& value); // Construct a Baggage referencing 'key' and 'value' - std::basic_string& key(); + std::string& key(); // Mutable reference to the underlying 'key'. - std::basic_string& value(); + std::string& value(); // Mutable reference to the underlying 'value'. - const std::basic_string& key() const; + const std::string& key() const; // Return the non-modifiable 'key' associated with this baggage. - const std::basic_string& value() const; + const std::string& value() const; // Return the non-modifiable 'value' associated with this baggage. - BaggageImp* operator->(); - const BaggageImp* operator->() const; + Baggage* operator->(); + const Baggage* operator->() const; // Syntactic sugar to support dereferencing BaggageIterator's with // the '->' operator: this method only returns 'this'. private: - std::basic_string m_key; - std::basic_string m_value; + std::string m_key; + std::string m_value; }; -typedef BaggageImp Baggage; - -// =================== -// class BaggageRefImp -// =================== +// ================ +// class BaggageRef +// ================ // This class wraps references to the key:value pairs stored in SpanContexts. // The references themselves refer to data managed by SpanContext // implementations, but make them available in a read-only fashion to avoid @@ -87,35 +81,31 @@ typedef BaggageImp Baggage; // Since the implementations of SpanContexts is deferred, it is impossible to // make strong guarantees on the lifetime of the references. At a minimum, the // references should be valid until the iterator is destroyed, the SpanContext -// is destoryed, or until 'setBaggage' is called on the SpanContext. +// is destroyed, or until 'setBaggage' is called on the SpanContext. -template -class BaggageRefImp { +class BaggageRef { public: - BaggageRefImp(); + BaggageRef(); // Construct a BaggageRef with empty references. - BaggageRefImp(const StringRefImp& key, - const StringRefImp& value); + BaggageRef(const StringRef& key, const StringRef& value); // Construct a BaggageRef referencing 'key' and 'value' - const StringRefImp& key() const; + const StringRef& key() const; // Return the non-modifiable 'key' associated with this baggage. - const StringRefImp& value() const; + const StringRef& value() const; // Return the non-modifiable 'value' associated with this baggage. - const BaggageRefImp* operator->() const; + const BaggageRef* operator->() const; // Syntactic sugar to support dereferencing BaggageIterators with // the '->' operator: this method only returns 'this'. private: - StringRefImp m_key; - StringRefImp m_value; + StringRef m_key; + StringRef m_value; }; -typedef BaggageRefImp BaggageRef; - // ======================== // class BaggageIteratorImp // ======================== @@ -222,94 +212,79 @@ class BaggageRangeImp { const BaggageIterator m_end; }; -// ---------------- -// class BaggageImp -// ---------------- +// ------------- +// class Baggage +// ------------- -template -inline BaggageImp::BaggageImp() : m_key(), m_value() +inline Baggage::Baggage() : m_key(), m_value() { } -template -inline BaggageImp::BaggageImp(const StringRefImp& key, - const StringRefImp& value) +inline Baggage::Baggage(const StringRef& key, const StringRef& value) : m_key(key.data(), key.length()), m_value(value.data(), value.length()) { } -template -inline std::basic_string& -BaggageImp::key() +inline std::string& +Baggage::key() { return m_key; } -template -inline std::basic_string& -BaggageImp::value() +inline std::string& +Baggage::value() { return m_value; } -template -inline const std::basic_string& -BaggageImp::key() const +inline const std::string& +Baggage::key() const { return m_key; } -template -inline const std::basic_string& -BaggageImp::value() const +inline const std::string& +Baggage::value() const { return m_value; } -template -inline BaggageImp* BaggageImp::operator->() +inline Baggage* Baggage::operator->() { return this; } -template -inline const BaggageImp* BaggageImp::operator->() const +inline const Baggage* Baggage::operator->() const { return this; } -// ------------------- -// class BaggageRefImp -// ------------------- +// ---------------- +// class BaggageRef +// ---------------- -template -inline BaggageRefImp::BaggageRefImp() : m_key(), m_value() +inline BaggageRef::BaggageRef() : m_key(), m_value() { } -template -inline BaggageRefImp::BaggageRefImp(const StringRefImp& key, - const StringRefImp& value) +inline BaggageRef::BaggageRef(const StringRef& key, const StringRef& value) : m_key(key), m_value(value) { } -template -inline const StringRefImp& -BaggageRefImp::key() const +inline const StringRef& +BaggageRef::key() const { return m_key; } -template -inline const StringRefImp& -BaggageRefImp::value() const +inline const StringRef& +BaggageRef::value() const { return m_value; } -template -inline const BaggageRefImp* BaggageRefImp::operator->() const +inline const BaggageRef* BaggageRef::operator->() const { return this; } diff --git a/opentracing/carriers.h b/opentracing/carriers.h index ee91750..c59ffd3 100644 --- a/opentracing/carriers.h +++ b/opentracing/carriers.h @@ -33,11 +33,6 @@ #include #include -#include -#if HAVE_STDINT_H -#include -#endif - namespace opentracing { // ================= diff --git a/noop/noop.cc b/opentracing/noop.cc similarity index 68% rename from noop/noop.cc rename to opentracing/noop.cc index 891be4d..6752db6 100644 --- a/noop/noop.cc +++ b/opentracing/noop.cc @@ -1,4 +1,4 @@ -#include +#include namespace opentracing { NoopTracer* NoopTracer::s_tracer = 0; diff --git a/noop/noop.h b/opentracing/noop.h similarity index 99% rename from noop/noop.h rename to opentracing/noop.h index 7166a70..2f118b2 100644 --- a/noop/noop.h +++ b/opentracing/noop.h @@ -24,16 +24,12 @@ // https://github.com/opentracing/specification/blob/master/specification.md#nooptracer #include -#include #include #include #include #include #include - -#if HAVE_STDINT_H #include -#endif namespace opentracing { diff --git a/opentracing/span.h b/opentracing/span.h index 87d6d96..7ebbaa3 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -9,11 +9,7 @@ #include #include #include - -#include -#ifdef HAVE_STDINT_H #include -#endif namespace opentracing { diff --git a/opentracing/spanoptions.h b/opentracing/spanoptions.h index c70de9c..bdb7ec3 100644 --- a/opentracing/spanoptions.h +++ b/opentracing/spanoptions.h @@ -8,11 +8,7 @@ // class GenericSpanOptions - CRTP interface for SpanOptions #include - -#include -#if HAVE_STDINT_H #include -#endif namespace opentracing { diff --git a/opentracing/stringref.h b/opentracing/stringref.h index 98a2dba..c125a7b 100644 --- a/opentracing/stringref.h +++ b/opentracing/stringref.h @@ -4,9 +4,7 @@ // =========== // stringref.h // =========== -// class StringRefImp - Templated implementation for a constant reference to an external string -// typedef StringRef - Typedef for StringRefImp -// typedef StringRefWide - Typedef for StringRefImp +// class StringRef - Constant reference to an external string // // ----------------- // String References @@ -19,97 +17,81 @@ // http://www.boost.org/doc/libs/master/libs/utility/doc/html/string_ref.html #include -#include -#include #include - -#include -#if HAVE_STDING_H -#include -#endif +#include namespace opentracing { -// ================== -// class StringRefImp -// ================== +// =============== +// 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 StringRefImp. For this reason, it is not in general safe to -// store a StringRefImp. +// past that of the StringRef. For this reason, it is not in general safe to +// store a StringRef. -template -class StringRefImp { +class StringRef{ public: - StringRefImp(); - // Conststruct an empty StringRef + StringRef(); + // Construct an empty StringRef template - StringRefImp(const CHAR (&str)[N]); - // Explicitly create string reference from a const CHARacter array + StringRef(const char (&str)[N]); + // Explicitly create string reference from a const character array - explicit StringRefImp(const CHAR* str); - // Explicitly create string reference from const CHARacter pointer + explicit StringRef(const char* str); + // Explicitly create string reference from const character pointer - StringRefImp(const std::basic_string& str); + StringRef(const std::basic_string& str); // Create constant string reference from pointer and length - StringRefImp(const CHAR* str, size_t len); + StringRef(const char* str, size_t len); // Create constant string reference from pointer and length - operator const CHAR*() const; - // Implicit conversion to plain CHAR * + 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)[N]); + // Reset the string reference given a const character array - void reset(const CHAR* const str); + void reset(const char* const str); // Reset this string ref to point at the supplied c-string - void reset(const std::basic_string& str); + void reset(const std::basic_string& str); // Reset the string reference given a std::string - void reset(const CHAR* const str, const size_t length); + void reset(const char* const str, const size_t length); // Reset this string ref to point at the supplied 'str' of 'length' bytes. - const CHAR* data() const; + const char* data() const; // Return address of the referenced string size_t length() const; // Return the length of the referenced string private: - static size_t getLength(const CHAR* len); - // Similar to strlen, but for both char/wchar types - template - StringRefImp(CHAR (&str)[N]); + StringRef(char (&str)[N]); // Disallow construction from non-const array template - void reset(CHAR (&str)[N]); + void reset(char (&str)[N]); // Disallow reset from non-const array - const CHAR* m_data; // Pointer to external storage + const char* m_data; // Pointer to external storage size_t m_length; // Length of data pointed to by 'm_data' }; -// -------- -// Typedefs -// -------- -typedef StringRefImp StringRef; -typedef StringRefImp StringRefWide; - // ----- // 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 implmentation will have a 'native' +// 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 @@ -118,104 +100,81 @@ typedef StringRefImp StringRefWide; // that breaks if it was expecting wstring and starts receiving string all of a // sudden. That design issue still needs to be addressed. -// ------------------ -// Class StringRefImp -// ------------------ +// --------------- +// Class StringRef +// --------------- -template -inline StringRefImp::StringRefImp() : m_data(0), m_length(0) +inline StringRef::StringRef() : m_data(0), m_length(0) { } -template template -inline StringRefImp::StringRefImp(const CHAR (&str)[N]) : m_data(str), m_length(N - 1) +inline StringRef::StringRef(const char (&str)[N]) +: m_data(str), m_length(N - 1) { } -template -inline StringRefImp::StringRefImp(const CHAR* const str) -: m_data(str), m_length(getLength(str)) +inline StringRef::StringRef(const char* const str) +: m_data(str), m_length(std::strlen(str)) { } -template -inline StringRefImp::StringRefImp(const std::basic_string& str) +inline StringRef::StringRef(const std::basic_string& str) : m_data(str.c_str()), m_length(str.length()) { } -template -inline StringRefImp::StringRefImp(const CHAR* str, size_t len) +inline StringRef::StringRef(const char* str, size_t len) : m_data(str), m_length(len) { } -template -inline StringRefImp::operator const CHAR*() const +inline StringRef::operator const char*() const { return m_data; } -template inline void -StringRefImp::reset(const CHAR* const str, const size_t length) +StringRef::reset(const char* const str, const size_t length) { m_data = str; m_length = length; } -template template inline void -StringRefImp::reset(const CHAR (&str)[N]) +StringRef::reset(const char (&str)[N]) { m_data = str; m_length = N; } -template inline void -StringRefImp::reset(const CHAR* const str) +StringRef::reset(const char* const str) { m_data = str; - m_length = getLength(str); + m_length = std::strlen(str); } -template inline void -StringRefImp::reset(const std::basic_string& str) +StringRef::reset(const std::basic_string& str) { m_data = str.data(); m_length = str.length(); } -template -inline const CHAR* -StringRefImp::data() const +inline const char* +StringRef::data() const { return m_data; } -template inline size_t -StringRefImp::length() const +StringRef::length() const { return m_length; } -template -inline size_t -StringRefImp::getLength(const CHAR* s) -{ - const CHAR* p = s; - while (*p) - { - ++p; - } - return size_t(p - s); -} - } // namespace opentracing inline diff --git a/opentracing/tracer.h b/opentracing/tracer.h index 43ddcb0..299c2d1 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -11,11 +11,6 @@ #include #include -#include -#ifdef HAVE_STDINT_H -#include -#endif - namespace opentracing { // =================== diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..d86ecdc --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,26 @@ +include(CheckCXXCompilerFlag) + +set(unittest_sources + baggage.t.cc + carriers.t.cc + span.t.cc + spancontext.t.cc + stringref.t.cc + tracer.t.cc + unittest.t.cc) + +if(enable_noop) + set(unittest_sources ${unittest_sources} noop.t.cc) + include_directories(${CMAKE_SOURCE_DIR}) + set(noop_lib "opentracing-cpp") +endif() + +include_directories(${CMAKE_SOURCE_DIR}) + +add_executable(unittest ${unittest_sources}) + +target_link_libraries(unittest ${noop_lib} gtest gtest_main) + +add_test(NAME unittest + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) diff --git a/test/Makefile b/test/Makefile index f23050b..25501a1 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,33 +1,420 @@ -CC=g++ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.6 -OPENTRACING_INCLUDE=../ -NOOP_INCLUDE=../noop +# Default target executed when no arguments are given to make. +default_target: all -THIRDPARTY_ROOT=../thirdparty -GTEST_INCLUDE=${THIRDPARTY_ROOT}/googletest/googletest/include -GTEST_LIBS=${THIRDPARTY_ROOT}/ +.PHONY : default_target -INCLUDES=-I. -I$(GTEST_INCLUDE) -I$(OPENTRACING_INCLUDE) -I$(NOOP_INCLUDE) +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: -CXXFLAGS=-Wall -fno-elide-constructors -Wextra -Wall -Winit-self -Wold-style-cast -Woverloaded-virtual -Winit-self -Wuninitialized -Wmissing-declarations -Werror $(INCLUDES) -LDFLAGS= +#============================================================================= +# Special targets provided by cmake. -LDIR =${GTEST_LIBS} +# Disable implicit rules so canonical targets will work. +.SUFFIXES: -LIBS=-L${GTEST_LIBS} -lgtest -lpthread -ODIR=. -_OBJ = stringref.t.o baggage.t.o spancontext.t.o span.t.o carriers.t.o tracer.t.o noop.t.o unittest.t.o -OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = -$(ODIR)/%.o: %.cc %.h - $(CC) -c -o $@ $< $(CXXFLAGS) +.SUFFIXES: .hpux_make_needs_suffix_list -test: $(OBJ) ../noop/noop.o - $(CC) -o $@ $^ $(CXXFLAGS) $(LIBS) $(LDFLAGS) -.PHONY: clean +# Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /opt/bb/bin/cmake + +# The command to remove a file. +RM = /opt/bb/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/vagrant/work/code/opentracing-rewrite + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/vagrant/work/code/opentracing-rewrite + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target test +test: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." + /opt/bb/bin/ctest --force-new-ctest-process $(ARGS) +.PHONY : test + +# Special rule for the target test +test/fast: test + +.PHONY : test/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + /opt/bb/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache + +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /opt/bb/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache + +.PHONY : rebuild_cache/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"dev\" \"pkgconfig\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components + +.PHONY : list_install_components/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /opt/bb/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /opt/bb/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /opt/bb/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: install/local + +.PHONY : install/local/fast + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /opt/bb/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: install/strip + +.PHONY : install/strip/fast + +# The main all target +all: cmake_check_build_system + cd /home/vagrant/work/code/opentracing-rewrite && $(CMAKE_COMMAND) -E cmake_progress_start /home/vagrant/work/code/opentracing-rewrite/CMakeFiles /home/vagrant/work/code/opentracing-rewrite/test/CMakeFiles/progress.marks + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f CMakeFiles/Makefile2 test/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/vagrant/work/code/opentracing-rewrite/CMakeFiles 0 +.PHONY : all + +# The main clean target clean: - rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f CMakeFiles/Makefile2 test/clean +.PHONY : clean + +# The main clean target +clean/fast: clean + +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f CMakeFiles/Makefile2 test/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f CMakeFiles/Makefile2 test/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /home/vagrant/work/code/opentracing-rewrite && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Convenience name for target. +test/CMakeFiles/unittest.dir/rule: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f CMakeFiles/Makefile2 test/CMakeFiles/unittest.dir/rule +.PHONY : test/CMakeFiles/unittest.dir/rule + +# Convenience name for target. +unittest: test/CMakeFiles/unittest.dir/rule + +.PHONY : unittest + +# fast build rule for target. +unittest/fast: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/build +.PHONY : unittest/fast + +baggage.t.o: baggage.t.cc.o + +.PHONY : baggage.t.o + +# target to build an object file +baggage.t.cc.o: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/baggage.t.cc.o +.PHONY : baggage.t.cc.o + +baggage.t.i: baggage.t.cc.i + +.PHONY : baggage.t.i + +# target to preprocess a source file +baggage.t.cc.i: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/baggage.t.cc.i +.PHONY : baggage.t.cc.i + +baggage.t.s: baggage.t.cc.s + +.PHONY : baggage.t.s + +# target to generate assembly for a file +baggage.t.cc.s: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/baggage.t.cc.s +.PHONY : baggage.t.cc.s + +carriers.t.o: carriers.t.cc.o + +.PHONY : carriers.t.o + +# target to build an object file +carriers.t.cc.o: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/carriers.t.cc.o +.PHONY : carriers.t.cc.o + +carriers.t.i: carriers.t.cc.i + +.PHONY : carriers.t.i + +# target to preprocess a source file +carriers.t.cc.i: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/carriers.t.cc.i +.PHONY : carriers.t.cc.i + +carriers.t.s: carriers.t.cc.s + +.PHONY : carriers.t.s + +# target to generate assembly for a file +carriers.t.cc.s: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/carriers.t.cc.s +.PHONY : carriers.t.cc.s + +span.t.o: span.t.cc.o + +.PHONY : span.t.o + +# target to build an object file +span.t.cc.o: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/span.t.cc.o +.PHONY : span.t.cc.o + +span.t.i: span.t.cc.i + +.PHONY : span.t.i + +# target to preprocess a source file +span.t.cc.i: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/span.t.cc.i +.PHONY : span.t.cc.i + +span.t.s: span.t.cc.s + +.PHONY : span.t.s + +# target to generate assembly for a file +span.t.cc.s: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/span.t.cc.s +.PHONY : span.t.cc.s + +spancontext.t.o: spancontext.t.cc.o + +.PHONY : spancontext.t.o + +# target to build an object file +spancontext.t.cc.o: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/spancontext.t.cc.o +.PHONY : spancontext.t.cc.o + +spancontext.t.i: spancontext.t.cc.i + +.PHONY : spancontext.t.i + +# target to preprocess a source file +spancontext.t.cc.i: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/spancontext.t.cc.i +.PHONY : spancontext.t.cc.i + +spancontext.t.s: spancontext.t.cc.s + +.PHONY : spancontext.t.s + +# target to generate assembly for a file +spancontext.t.cc.s: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/spancontext.t.cc.s +.PHONY : spancontext.t.cc.s + +stringref.t.o: stringref.t.cc.o + +.PHONY : stringref.t.o + +# target to build an object file +stringref.t.cc.o: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/stringref.t.cc.o +.PHONY : stringref.t.cc.o + +stringref.t.i: stringref.t.cc.i + +.PHONY : stringref.t.i + +# target to preprocess a source file +stringref.t.cc.i: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/stringref.t.cc.i +.PHONY : stringref.t.cc.i + +stringref.t.s: stringref.t.cc.s + +.PHONY : stringref.t.s + +# target to generate assembly for a file +stringref.t.cc.s: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/stringref.t.cc.s +.PHONY : stringref.t.cc.s + +tracer.t.o: tracer.t.cc.o + +.PHONY : tracer.t.o + +# target to build an object file +tracer.t.cc.o: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/tracer.t.cc.o +.PHONY : tracer.t.cc.o + +tracer.t.i: tracer.t.cc.i + +.PHONY : tracer.t.i + +# target to preprocess a source file +tracer.t.cc.i: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/tracer.t.cc.i +.PHONY : tracer.t.cc.i + +tracer.t.s: tracer.t.cc.s + +.PHONY : tracer.t.s + +# target to generate assembly for a file +tracer.t.cc.s: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/tracer.t.cc.s +.PHONY : tracer.t.cc.s + +unittest.t.o: unittest.t.cc.o + +.PHONY : unittest.t.o + +# target to build an object file +unittest.t.cc.o: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/unittest.t.cc.o +.PHONY : unittest.t.cc.o + +unittest.t.i: unittest.t.cc.i + +.PHONY : unittest.t.i + +# target to preprocess a source file +unittest.t.cc.i: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/unittest.t.cc.i +.PHONY : unittest.t.cc.i + +unittest.t.s: unittest.t.cc.s + +.PHONY : unittest.t.s + +# target to generate assembly for a file +unittest.t.cc.s: + cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/unittest.t.cc.s +.PHONY : unittest.t.cc.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... test" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... list_install_components" + @echo "... install" + @echo "... install/local" + @echo "... install/strip" + @echo "... unittest" + @echo "... baggage.t.o" + @echo "... baggage.t.i" + @echo "... baggage.t.s" + @echo "... carriers.t.o" + @echo "... carriers.t.i" + @echo "... carriers.t.s" + @echo "... span.t.o" + @echo "... span.t.i" + @echo "... span.t.s" + @echo "... spancontext.t.o" + @echo "... spancontext.t.i" + @echo "... spancontext.t.s" + @echo "... stringref.t.o" + @echo "... stringref.t.i" + @echo "... stringref.t.s" + @echo "... tracer.t.o" + @echo "... tracer.t.i" + @echo "... tracer.t.s" + @echo "... unittest.t.o" + @echo "... unittest.t.i" + @echo "... unittest.t.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /home/vagrant/work/code/opentracing-rewrite && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/test/noop.t.cc b/test/noop.t.cc index c29a5c0..4a4f284 100644 --- a/test/noop.t.cc +++ b/test/noop.t.cc @@ -2,8 +2,8 @@ #include "carriers.h" -#include -#include // test include guard +#include +#include // test include guard // These run the same tests as the tracer.t.cc. The interface should be the // same, however, there may be some differences in return codes due diff --git a/test/stringref.t.cc b/test/stringref.t.cc index a13149b..a79f81e 100644 --- a/test/stringref.t.cc +++ b/test/stringref.t.cc @@ -97,98 +97,3 @@ TEST(StringRef, Reset) ASSERT_STREQ(p, ref); ASSERT_STREQ(p, ref.data()); } - -TEST(StringRefWide, Empty) -{ - StringRefWide ref; - ASSERT_EQ(0, ref.data()); - ASSERT_EQ(0, ref.length()); -} - -TEST(StringRefWide, WideCString) -{ - const wchar_t * val = L"hello world"; - - StringRefWide ref(val); - - ASSERT_EQ(val, ref.data()); - ASSERT_EQ(wcslen(val), ref.length()); -} - -TEST(StringRefWide, WideCStringArray) -{ - const wchar_t val[] = L"hello world"; - - StringRefWide ref(val); - - ASSERT_EQ(val, ref.data()); - ASSERT_EQ(wcslen(val), ref.length()); -} - -TEST(StringRefWide, StdWideString) -{ - const std::wstring val = L"hello world"; - - StringRefWide ref(val); - - ASSERT_EQ(val, ref.data()); - ASSERT_EQ(val.length(), ref.length()); -} - -TEST(StringRefWide, WideCopy) -{ - const std::wstring val = L"hello world"; - - StringRefWide ref(val); - StringRefWide cpy(ref); - - ASSERT_EQ(val, cpy.data()); - ASSERT_EQ(val.length(), cpy.length()); -} - -TEST(StringRefWide, WideReset) -{ - StringRefWide ref; - ASSERT_EQ(0, ref.data()); - ASSERT_EQ(0, ref.length()); - - ref.reset(L"hello world"); - - ASSERT_STREQ(L"hello world", ref); - ASSERT_STREQ(L"hello world", ref.data()); - ASSERT_EQ(wcslen(L"hello world"), ref.length()); - - const wchar_t arr[] = L"hello world 1"; - - ref.reset(arr); - ASSERT_EQ(arr, ref); - ASSERT_EQ(arr, ref.data()); - ASSERT_EQ(wcslen(arr), ref.length()); - ASSERT_STREQ(arr, ref); - ASSERT_STREQ(arr, ref.data()); - - const wchar_t * p = L"hello world 2"; - - ref.reset(p); - ASSERT_EQ(p, ref); - ASSERT_EQ(p, ref.data()); - ASSERT_EQ(wcslen(p), ref.length()); - ASSERT_STREQ(p, ref); - ASSERT_STREQ(p, ref.data()); - - const std::wstring s = L"hello world 3"; - - ref.reset(s); - ASSERT_EQ(s.data(), ref); - ASSERT_EQ(s.data(), ref.data()); - ASSERT_EQ(s.length(), ref.length()); - ASSERT_STREQ(s.c_str(), ref); - ASSERT_STREQ(s.c_str(), ref.data()); - - ref.reset(p, wcslen(p)); - ASSERT_EQ(p, ref); - ASSERT_EQ(p, ref.data()); - ASSERT_EQ(wcslen(p), ref.length()); - ASSERT_STREQ(p, ref); - ASSERT_STREQ(p, ref.data()); -} diff --git a/test/unittest.h b/test/unittest.h index 436f1c8..5af8640 100644 --- a/test/unittest.h +++ b/test/unittest.h @@ -2,23 +2,12 @@ #define INCLUDED_OPENTRACING_UNITTEST_H #include -#include -#if HAVE_STDINT_H #include -#endif - -#include -#include +#include #include namespace opentracing{ -inline void -test_widen(std::wstring* const dest, const std::string& src) -{ - dest->resize(src.size()); - std::mbstowcs(&(*dest)[0], src.c_str(), src.size()); -} } using namespace opentracing; diff --git a/thirdparty/build-gtest.sh b/thirdparty/build-gtest.sh deleted file mode 100755 index ec2a624..0000000 --- a/thirdparty/build-gtest.sh +++ /dev/null @@ -1,8 +0,0 @@ - -mkdir -f gtest-build -cd gtest-build - -GTEST_DIR=../googletest/googletest - -g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} -pthread -c ${GTEST_DIR}/src/gtest-all.cc -ar -rv libgtest.a gtest-all.o diff --git a/thirdparty/googletest b/thirdparty/googletest index ec44c6c..5e7fd50 160000 --- a/thirdparty/googletest +++ b/thirdparty/googletest @@ -1 +1 @@ -Subproject commit ec44c6c1675c25b9827aacd08c02433cccde7780 +Subproject commit 5e7fd50e17b6edf1cadff973d0ec68966cf3265e From 963d0161b8a19716f7350c2491edbc10b1b25679 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Wed, 11 Jan 2017 09:51:13 -0500 Subject: [PATCH 28/48] Cmake, removing unused template functionality, ditching config.h for now --- CMakeLists.txt | 16 ++------ README.md | 38 +++++++++++++------ opentracing/CMakeLists.txt | 26 ++++++++++--- .../opentracing.pc.in | 0 test/CMakeLists.txt | 2 + 5 files changed, 53 insertions(+), 29 deletions(-) rename opentracing-cpp.pc.in => opentracing/opentracing.pc.in (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b66393..1137260 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,14 @@ cmake_minimum_required (VERSION 2.8) -set(PROJECT_NAME "opentracing-cpp") +set(PROJECT_NAME "opentracing") project (${PROJECT_NAME}) -set(opentracing_url "https://github.com/opentracing/opentracing-cpp") 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) set(CMAKE_CXX_FLAGS "-g -Wall -Werror -Wextra -Wfloat-equal") option(enable_noop "Build noop tracer." OFF) @@ -28,15 +29,6 @@ add_subdirectory(opentracing) if(enable_tests) enable_testing() - add_subdirectory(thirdparty/googletest) + add_subdirectory(thirdparty/googletest/googletest) add_subdirectory(test) endif() - -# pkg-config -# Defaults for .pc file, but can be overridden when cmake is run - - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc - @ONLY) - diff --git a/README.md b/README.md index deb8db4..e44cd0b 100644 --- a/README.md +++ b/README.md @@ -14,28 +14,44 @@ In order to understand the C++ platform API, one must first be familiar with the ## Compile and install +The default package is a header-only library. It can be installed as such + +``` +mkdir build +cd build +cmake .. +make install +``` + +If you would like to include the NoopTracer, a static library is created in addition to the headers. + ``` -libtoolize # or glibtoolize -./autogen.sh -./configure -sudo make install +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: +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: ``` -cd ./thirdparty && ./build_gtest.sh -cd ../test && make -./test +git submodule update --recursive --remote +mkdir build +cd build +cmake -Denable_tests=ON .. +make +../bin/unittest ``` +If you're using the `NoopTracer`, you would want to add `-Denable_noop=ON` as well. + ## API overview for those adding instrumentation -Clients of this `OpenTracing` package do need to understand only the key abstractions of this API: - * Installing a Tracer implmementation in `main()` +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` diff --git a/opentracing/CMakeLists.txt b/opentracing/CMakeLists.txt index c97dcdc..1d9fdce 100644 --- a/opentracing/CMakeLists.txt +++ b/opentracing/CMakeLists.txt @@ -1,9 +1,5 @@ include_directories(${CMAKE_SOURCE_DIR}) -if(enable_noop) - set(opentracing_libs "-L${libdir} -lopentracing-cpp") -endif() - set(headers baggage.h carriers.h @@ -15,15 +11,33 @@ set(headers 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) - add_library(opentracing-cpp STATIC noop.cc) + # Build our opentracing library + add_library(opentracing STATIC noop.cc) - install (TARGETS opentracing-cpp + # Add the opentracing install target + install (TARGETS opentracing DESTINATION ${LIB_INSTALL_DIR} COMPONENT dev) endif() +# Install the opentracing headers into /path/to/include/opentracing/ install (FILES ${headers} DESTINATION ${INCLUDE_INSTALL_DIR}/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.in + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig + COMPONENT pkgconfig) +endif() diff --git a/opentracing-cpp.pc.in b/opentracing/opentracing.pc.in similarity index 100% rename from opentracing-cpp.pc.in rename to opentracing/opentracing.pc.in diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d86ecdc..f5d3e63 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,6 +9,8 @@ set(unittest_sources tracer.t.cc unittest.t.cc) +option(enable_noop "Test noop tracer." OFF) + if(enable_noop) set(unittest_sources ${unittest_sources} noop.t.cc) include_directories(${CMAKE_SOURCE_DIR}) From 29e1285ede564ea621f92971518945d429e6944b Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Wed, 11 Jan 2017 09:55:22 -0500 Subject: [PATCH 29/48] Remove cmake makefile --- test/Makefile | 420 -------------------------------------------------- 1 file changed, 420 deletions(-) delete mode 100644 test/Makefile diff --git a/test/Makefile b/test/Makefile deleted file mode 100644 index 25501a1..0000000 --- a/test/Makefile +++ /dev/null @@ -1,420 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.6 - -# Default target executed when no arguments are given to make. -default_target: all - -.PHONY : default_target - -# Allow only one "make -f Makefile2" at a time, but pass parallelism. -.NOTPARALLEL: - - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - - -# Remove some rules from gmake that .SUFFIXES does not remove. -SUFFIXES = - -.SUFFIXES: .hpux_make_needs_suffix_list - - -# Suppress display of executed commands. -$(VERBOSE).SILENT: - - -# A target that is always out of date. -cmake_force: - -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /opt/bb/bin/cmake - -# The command to remove a file. -RM = /opt/bb/bin/cmake -E remove -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /home/vagrant/work/code/opentracing-rewrite - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /home/vagrant/work/code/opentracing-rewrite - -#============================================================================= -# Targets provided globally by CMake. - -# Special rule for the target test -test: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." - /opt/bb/bin/ctest --force-new-ctest-process $(ARGS) -.PHONY : test - -# Special rule for the target test -test/fast: test - -.PHONY : test/fast - -# Special rule for the target edit_cache -edit_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." - /opt/bb/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : edit_cache - -# Special rule for the target edit_cache -edit_cache/fast: edit_cache - -.PHONY : edit_cache/fast - -# Special rule for the target rebuild_cache -rebuild_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." - /opt/bb/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : rebuild_cache - -# Special rule for the target rebuild_cache -rebuild_cache/fast: rebuild_cache - -.PHONY : rebuild_cache/fast - -# Special rule for the target list_install_components -list_install_components: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"dev\" \"pkgconfig\"" -.PHONY : list_install_components - -# Special rule for the target list_install_components -list_install_components/fast: list_install_components - -.PHONY : list_install_components/fast - -# Special rule for the target install -install: preinstall - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." - /opt/bb/bin/cmake -P cmake_install.cmake -.PHONY : install - -# Special rule for the target install -install/fast: preinstall/fast - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." - /opt/bb/bin/cmake -P cmake_install.cmake -.PHONY : install/fast - -# Special rule for the target install/local -install/local: preinstall - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." - /opt/bb/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake -.PHONY : install/local - -# Special rule for the target install/local -install/local/fast: install/local - -.PHONY : install/local/fast - -# Special rule for the target install/strip -install/strip: preinstall - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." - /opt/bb/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake -.PHONY : install/strip - -# Special rule for the target install/strip -install/strip/fast: install/strip - -.PHONY : install/strip/fast - -# The main all target -all: cmake_check_build_system - cd /home/vagrant/work/code/opentracing-rewrite && $(CMAKE_COMMAND) -E cmake_progress_start /home/vagrant/work/code/opentracing-rewrite/CMakeFiles /home/vagrant/work/code/opentracing-rewrite/test/CMakeFiles/progress.marks - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f CMakeFiles/Makefile2 test/all - $(CMAKE_COMMAND) -E cmake_progress_start /home/vagrant/work/code/opentracing-rewrite/CMakeFiles 0 -.PHONY : all - -# The main clean target -clean: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f CMakeFiles/Makefile2 test/clean -.PHONY : clean - -# The main clean target -clean/fast: clean - -.PHONY : clean/fast - -# Prepare targets for installation. -preinstall: all - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f CMakeFiles/Makefile2 test/preinstall -.PHONY : preinstall - -# Prepare targets for installation. -preinstall/fast: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f CMakeFiles/Makefile2 test/preinstall -.PHONY : preinstall/fast - -# clear depends -depend: - cd /home/vagrant/work/code/opentracing-rewrite && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 -.PHONY : depend - -# Convenience name for target. -test/CMakeFiles/unittest.dir/rule: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f CMakeFiles/Makefile2 test/CMakeFiles/unittest.dir/rule -.PHONY : test/CMakeFiles/unittest.dir/rule - -# Convenience name for target. -unittest: test/CMakeFiles/unittest.dir/rule - -.PHONY : unittest - -# fast build rule for target. -unittest/fast: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/build -.PHONY : unittest/fast - -baggage.t.o: baggage.t.cc.o - -.PHONY : baggage.t.o - -# target to build an object file -baggage.t.cc.o: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/baggage.t.cc.o -.PHONY : baggage.t.cc.o - -baggage.t.i: baggage.t.cc.i - -.PHONY : baggage.t.i - -# target to preprocess a source file -baggage.t.cc.i: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/baggage.t.cc.i -.PHONY : baggage.t.cc.i - -baggage.t.s: baggage.t.cc.s - -.PHONY : baggage.t.s - -# target to generate assembly for a file -baggage.t.cc.s: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/baggage.t.cc.s -.PHONY : baggage.t.cc.s - -carriers.t.o: carriers.t.cc.o - -.PHONY : carriers.t.o - -# target to build an object file -carriers.t.cc.o: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/carriers.t.cc.o -.PHONY : carriers.t.cc.o - -carriers.t.i: carriers.t.cc.i - -.PHONY : carriers.t.i - -# target to preprocess a source file -carriers.t.cc.i: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/carriers.t.cc.i -.PHONY : carriers.t.cc.i - -carriers.t.s: carriers.t.cc.s - -.PHONY : carriers.t.s - -# target to generate assembly for a file -carriers.t.cc.s: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/carriers.t.cc.s -.PHONY : carriers.t.cc.s - -span.t.o: span.t.cc.o - -.PHONY : span.t.o - -# target to build an object file -span.t.cc.o: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/span.t.cc.o -.PHONY : span.t.cc.o - -span.t.i: span.t.cc.i - -.PHONY : span.t.i - -# target to preprocess a source file -span.t.cc.i: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/span.t.cc.i -.PHONY : span.t.cc.i - -span.t.s: span.t.cc.s - -.PHONY : span.t.s - -# target to generate assembly for a file -span.t.cc.s: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/span.t.cc.s -.PHONY : span.t.cc.s - -spancontext.t.o: spancontext.t.cc.o - -.PHONY : spancontext.t.o - -# target to build an object file -spancontext.t.cc.o: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/spancontext.t.cc.o -.PHONY : spancontext.t.cc.o - -spancontext.t.i: spancontext.t.cc.i - -.PHONY : spancontext.t.i - -# target to preprocess a source file -spancontext.t.cc.i: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/spancontext.t.cc.i -.PHONY : spancontext.t.cc.i - -spancontext.t.s: spancontext.t.cc.s - -.PHONY : spancontext.t.s - -# target to generate assembly for a file -spancontext.t.cc.s: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/spancontext.t.cc.s -.PHONY : spancontext.t.cc.s - -stringref.t.o: stringref.t.cc.o - -.PHONY : stringref.t.o - -# target to build an object file -stringref.t.cc.o: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/stringref.t.cc.o -.PHONY : stringref.t.cc.o - -stringref.t.i: stringref.t.cc.i - -.PHONY : stringref.t.i - -# target to preprocess a source file -stringref.t.cc.i: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/stringref.t.cc.i -.PHONY : stringref.t.cc.i - -stringref.t.s: stringref.t.cc.s - -.PHONY : stringref.t.s - -# target to generate assembly for a file -stringref.t.cc.s: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/stringref.t.cc.s -.PHONY : stringref.t.cc.s - -tracer.t.o: tracer.t.cc.o - -.PHONY : tracer.t.o - -# target to build an object file -tracer.t.cc.o: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/tracer.t.cc.o -.PHONY : tracer.t.cc.o - -tracer.t.i: tracer.t.cc.i - -.PHONY : tracer.t.i - -# target to preprocess a source file -tracer.t.cc.i: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/tracer.t.cc.i -.PHONY : tracer.t.cc.i - -tracer.t.s: tracer.t.cc.s - -.PHONY : tracer.t.s - -# target to generate assembly for a file -tracer.t.cc.s: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/tracer.t.cc.s -.PHONY : tracer.t.cc.s - -unittest.t.o: unittest.t.cc.o - -.PHONY : unittest.t.o - -# target to build an object file -unittest.t.cc.o: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/unittest.t.cc.o -.PHONY : unittest.t.cc.o - -unittest.t.i: unittest.t.cc.i - -.PHONY : unittest.t.i - -# target to preprocess a source file -unittest.t.cc.i: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/unittest.t.cc.i -.PHONY : unittest.t.cc.i - -unittest.t.s: unittest.t.cc.s - -.PHONY : unittest.t.s - -# target to generate assembly for a file -unittest.t.cc.s: - cd /home/vagrant/work/code/opentracing-rewrite && $(MAKE) -f test/CMakeFiles/unittest.dir/build.make test/CMakeFiles/unittest.dir/unittest.t.cc.s -.PHONY : unittest.t.cc.s - -# Help Target -help: - @echo "The following are some of the valid targets for this Makefile:" - @echo "... all (the default if no target is provided)" - @echo "... clean" - @echo "... depend" - @echo "... test" - @echo "... edit_cache" - @echo "... rebuild_cache" - @echo "... list_install_components" - @echo "... install" - @echo "... install/local" - @echo "... install/strip" - @echo "... unittest" - @echo "... baggage.t.o" - @echo "... baggage.t.i" - @echo "... baggage.t.s" - @echo "... carriers.t.o" - @echo "... carriers.t.i" - @echo "... carriers.t.s" - @echo "... span.t.o" - @echo "... span.t.i" - @echo "... span.t.s" - @echo "... spancontext.t.o" - @echo "... spancontext.t.i" - @echo "... spancontext.t.s" - @echo "... stringref.t.o" - @echo "... stringref.t.i" - @echo "... stringref.t.s" - @echo "... tracer.t.o" - @echo "... tracer.t.i" - @echo "... tracer.t.s" - @echo "... unittest.t.o" - @echo "... unittest.t.i" - @echo "... unittest.t.s" -.PHONY : help - - - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - cd /home/vagrant/work/code/opentracing-rewrite && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - From f18e949da0b1a4c0aead0b2dc42ee196f09445cd Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Wed, 11 Jan 2017 11:02:12 -0500 Subject: [PATCH 30/48] Remove default contructors and handle side effects --- README.md | 2 +- opentracing/baggage.h | 14 -------------- opentracing/noop.h | 4 ++-- test/CMakeLists.txt | 2 +- test/baggage.t.cc | 4 ++-- 5 files changed, 6 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index e44cd0b..c9f7c10 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ mkdir build cd build cmake -Denable_tests=ON .. make -../bin/unittest +./bin/unittest ``` If you're using the `NoopTracer`, you would want to add `-Denable_noop=ON` as well. diff --git a/opentracing/baggage.h b/opentracing/baggage.h index 4e7c987..4277fa1 100644 --- a/opentracing/baggage.h +++ b/opentracing/baggage.h @@ -42,9 +42,6 @@ namespace opentracing { class Baggage { public: - Baggage(); - // Construct a Baggage with empty values. - Baggage(const StringRef& key, const StringRef& value); // Construct a Baggage referencing 'key' and 'value' @@ -85,9 +82,6 @@ class Baggage { class BaggageRef { public: - BaggageRef(); - // Construct a BaggageRef with empty references. - BaggageRef(const StringRef& key, const StringRef& value); // Construct a BaggageRef referencing 'key' and 'value' @@ -216,10 +210,6 @@ class BaggageRangeImp { // class Baggage // ------------- -inline Baggage::Baggage() : m_key(), m_value() -{ -} - inline Baggage::Baggage(const StringRef& key, const StringRef& value) : m_key(key.data(), key.length()), m_value(value.data(), value.length()) { @@ -263,10 +253,6 @@ inline const Baggage* Baggage::operator->() const // class BaggageRef // ---------------- -inline BaggageRef::BaggageRef() : m_key(), m_value() -{ -} - inline BaggageRef::BaggageRef(const StringRef& key, const StringRef& value) : m_key(key), m_value(value) { diff --git a/opentracing/noop.h b/opentracing/noop.h index 2f118b2..8278241 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -188,13 +188,13 @@ class NoopTracer : public GenericTracer Date: Wed, 11 Jan 2017 11:06:15 -0500 Subject: [PATCH 31/48] Update AUTHORS and ChangeLog --- AUTHORS | 5 +++-- ChangeLog | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/AUTHORS b/AUTHORS index 67659b0..adc834c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,5 +2,6 @@ AUTHORS ------- OpenTracing Developers -Jim Quinn - jquinn47@bloomberg.net - +Dmitrios Kouzis-Loukas : dkouzislouka AT bloomberg.net +James Wells : jwells31 AT bloomberg.net +Jim Quinn : jquinn47 AT bloomberg.net diff --git a/ChangeLog b/ChangeLog index 18a91d7..89f6a9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +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 From 2c205bd29c4f39123b1ff9b8aae3fed68fff9a9f Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Wed, 11 Jan 2017 11:16:43 -0500 Subject: [PATCH 32/48] Removing mutable baggage constructs, fixing installs --- CMakeLists.txt | 2 +- opentracing/CMakeLists.txt | 2 +- opentracing/baggage.h | 18 ------------------ test/baggage.t.cc | 20 -------------------- 4 files changed, 2 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1137260..dee5e18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ if(NOT includedir) set(includedir "include") endif() -set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${include}") +set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${includedir}") set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${libdir}") add_subdirectory(opentracing) diff --git a/opentracing/CMakeLists.txt b/opentracing/CMakeLists.txt index 1d9fdce..66fc788 100644 --- a/opentracing/CMakeLists.txt +++ b/opentracing/CMakeLists.txt @@ -37,7 +37,7 @@ if("${UNIX}" OR "${CYGWIN}") ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc @ONLY) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc.in + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig COMPONENT pkgconfig) endif() diff --git a/opentracing/baggage.h b/opentracing/baggage.h index 4277fa1..c95853e 100644 --- a/opentracing/baggage.h +++ b/opentracing/baggage.h @@ -45,12 +45,6 @@ class Baggage { Baggage(const StringRef& key, const StringRef& value); // Construct a Baggage referencing 'key' and 'value' - std::string& key(); - // Mutable reference to the underlying 'key'. - - std::string& value(); - // Mutable reference to the underlying 'value'. - const std::string& key() const; // Return the non-modifiable 'key' associated with this baggage. @@ -215,18 +209,6 @@ inline Baggage::Baggage(const StringRef& key, const StringRef& value) { } -inline std::string& -Baggage::key() -{ - return m_key; -} - -inline std::string& -Baggage::value() -{ - return m_value; -} - inline const std::string& Baggage::key() const { diff --git a/test/baggage.t.cc b/test/baggage.t.cc index 28c241c..f8ab44d 100644 --- a/test/baggage.t.cc +++ b/test/baggage.t.cc @@ -33,26 +33,6 @@ TEST(Baggage, Assignment) ASSERT_EQ("banana", cp.value()); } -TEST(Baggage, Manipulate) -{ - Baggage b("apple", "banana"); - b.key() = "cranberry"; - b.value() = "dates"; - - ASSERT_EQ("cranberry", b.key()); - ASSERT_EQ("dates", b.value()); -} - -TEST(Baggage, ManipulateThroughDeref) -{ - Baggage b("apple", "banana"); - b->key() = "cranberry"; - b->value() = "dates"; - - ASSERT_EQ("cranberry", b.key()); - ASSERT_EQ("dates", b.value()); -} - TEST(Baggage, ConstBehavior) { const Baggage b("apple", "banana"); From 99e64e3735f45a7d57ee88abfffa13ea8bac1c48 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Wed, 11 Jan 2017 11:29:21 -0500 Subject: [PATCH 33/48] appropriate refs --- opentracing/noop.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opentracing/noop.h b/opentracing/noop.h index 8278241..6ea523a 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -188,7 +188,8 @@ class NoopTracer : public GenericTracer Date: Wed, 11 Jan 2017 11:40:18 -0500 Subject: [PATCH 34/48] updating authors --- AUTHORS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index adc834c..6db9cfc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,6 +2,6 @@ AUTHORS ------- OpenTracing Developers -Dmitrios Kouzis-Loukas : dkouzislouka AT bloomberg.net -James Wells : jwells31 AT bloomberg.net -Jim Quinn : jquinn47 AT bloomberg.net +Dmitrios Kouzis-Loukas : dkouzislouka AT bloomberg DOT net +James Wells : jwells31 AT bloomberg DOT net +Jim Quinn : jquinn47 AT bloomberg DOT net From 4cb5325bd4cd3b7c3295de29b7b51ed68369f587 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Thu, 12 Jan 2017 12:51:22 -0500 Subject: [PATCH 35/48] Cmake tweaks --- CMakeLists.txt | 12 ------------ opentracing/CMakeLists.txt | 6 +++--- opentracing/opentracing.pc.in | 5 ++--- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dee5e18..8662e46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,22 +9,10 @@ set(opentracing_version "${lib_major_version}.${lib_minor_version}.${lib_patch_v set(opentracing_url "https://github.com/opentracing/opentracing-cpp") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -set(CMAKE_CXX_FLAGS "-g -Wall -Werror -Wextra -Wfloat-equal") option(enable_noop "Build noop tracer." OFF) option(enable_tests "Build unit tests." OFF) -if(NOT libdir) - set(libdir "lib") -endif() - -if(NOT includedir) - set(includedir "include") -endif() - -set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${includedir}") -set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${libdir}") - add_subdirectory(opentracing) if(enable_tests) diff --git a/opentracing/CMakeLists.txt b/opentracing/CMakeLists.txt index 66fc788..f566b3c 100644 --- a/opentracing/CMakeLists.txt +++ b/opentracing/CMakeLists.txt @@ -22,13 +22,13 @@ if(enable_noop) # Add the opentracing install target install (TARGETS opentracing - DESTINATION ${LIB_INSTALL_DIR} + DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} COMPONENT dev) endif() # Install the opentracing headers into /path/to/include/opentracing/ install (FILES ${headers} - DESTINATION ${INCLUDE_INSTALL_DIR}/opentracing + DESTINATION ${CMAKE_INSTALL_PREFIX}/include/opentracing COMPONENT dev) # pkg-config @@ -38,6 +38,6 @@ if("${UNIX}" OR "${CYGWIN}") @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc - DESTINATION ${LIB_INSTALL_DIR}/pkgconfig + DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT pkgconfig) endif() diff --git a/opentracing/opentracing.pc.in b/opentracing/opentracing.pc.in index 784e2e9..debaed1 100644 --- a/opentracing/opentracing.pc.in +++ b/opentracing/opentracing.pc.in @@ -1,6 +1,6 @@ prefix=@CMAKE_INSTALL_PREFIX@ -libdir=${prefix}/@libdir@ -includedir=${prefix}/@includedir@ +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/include Name: @PROJECT_NAME@ Description: C++ interface for the OpenTracing specification @@ -11,4 +11,3 @@ Requires.private: Libs: @opentracing_libs@ Libs.private: Cflags: -I${includedir} - From 013629a1392c78d5ef9a34696df98cc7164def13 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Thu, 12 Jan 2017 15:26:49 -0500 Subject: [PATCH 36/48] Adding tags to span options, update tests --- README.md | 3 ++- opentracing/noop.h | 25 ++++++++++++++++++------ opentracing/spanoptions.h | 40 +++++++++++++++++++++++++++------------ test/tracer.h | 15 ++++++++++++--- 4 files changed, 61 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index c9f7c10..f707458 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,8 @@ Testing requires the use of `gtest`. The `gtest` library is added as a submodule To build all of the tests, from the root repository: ``` -git submodule update --recursive --remote +git submodule init +git submodule update mkdir build cd build cmake -Denable_tests=ON .. diff --git a/opentracing/noop.h b/opentracing/noop.h index 6ea523a..f29afa1 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -89,9 +89,12 @@ class NoopContext : public GenericSpanContext { class NoopOptions : public GenericSpanOptions { public: - void setOperationImp(const StringRef&); - void setStartTimeImp(const uint64_t); - void setReferenceImp(const SpanRelationship::Value, const NoopContext&); + int setOperationImp(const StringRef&); + int setStartTimeImp(const uint64_t); + int setReferenceImp(const SpanRelationship::Value, const NoopContext&); + + template + int setTagImp(const StringRef&, const T&); }; // ============== @@ -237,19 +240,29 @@ NoopContext::getBaggageImp(const StringRef&, // class NoopOptions // ----------------- -inline void +inline int NoopOptions::setOperationImp(const StringRef&) { + return 0; } -inline void +inline int NoopOptions::setStartTimeImp(const uint64_t) { + return 0; } -inline void +inline int NoopOptions::setReferenceImp(const SpanRelationship::Value, const NoopContext&) { + return 0; +} + +template +inline int +NoopOptions::setTagImp(const StringRef&, const T&) +{ + return 0; } // ------------- diff --git a/opentracing/spanoptions.h b/opentracing/spanoptions.h index bdb7ec3..357da19 100644 --- a/opentracing/spanoptions.h +++ b/opentracing/spanoptions.h @@ -48,18 +48,25 @@ class GenericSpanOptions { public: typedef GenericSpanContext SpanContext; - void setOperation(const StringRef&); + int setOperation(const StringRef&); // Set the operation name to be used for any Span created with these - // options. + // options. Return 0 upon success and a non-zero value otherwise. - void setStartTime(const uint64_t); + int setStartTime(const uint64_t); // Set the start time from this span. If start time is not supplied, the - // default is to use the current wall-time. + // default is to use the current wall-time. Return 0 upon success and a + // non-zero value otherwise. - void setReference(const SpanRelationship::Value relationship, + int setReference(const SpanRelationship::Value relationship, const SpanContext& context); // A new Span created with these options would have a 'relationship' - // referenced added for 'context'. + // referenced added for 'context'. Return 0 upon success and a non-zero + // value otherwise. + + template + int setTag(const StringRef& key, const T& value); + // A new Span created with these options would have this 'key:value' tag. + // Return 0 upon success and a non-zero value otherwise. }; // ------------------------ @@ -67,26 +74,35 @@ class GenericSpanOptions { // ------------------------ template -inline void +inline int GenericSpanOptions::setOperation(const StringRef& op) { - static_cast(this)->setOperationImp(op); + return static_cast(this)->setOperationImp(op); } template -inline void +inline int GenericSpanOptions::setStartTime(const uint64_t tsp) { - static_cast(this)->setStartTimeImp(tsp); + return static_cast(this)->setStartTimeImp(tsp); } template -inline void +inline int GenericSpanOptions::setReference( const SpanRelationship::Value rel, const SpanContext& context) { const CONTEXT& contextImp = static_cast(context); - static_cast(this)->setReferenceImp(rel, contextImp); + return static_cast(this)->setReferenceImp(rel, contextImp); +} + +template +template +inline int +GenericSpanOptions::setTag( + const StringRef& key, const T& value) +{ + return static_cast(this)->setTagImp(key, value); } } // namespace opentracing diff --git a/test/tracer.h b/test/tracer.h index fde8ece..e80652c 100644 --- a/test/tracer.h +++ b/test/tracer.h @@ -13,19 +13,28 @@ class TestOptionsImpl : public GenericSpanOptions { public: - void + int setOperationImp(const StringRef&) { + return 0; } - void + int setStartTimeImp(const uint64_t) { + return 0; } - void + int setReferenceImp(const SpanRelationship::Value, const TestContextImpl&) { + return 0; + } + + template + int setTagImp(const StringRef&, const T&) + { + return 0; } }; From 90b232d345da87b4ffcac37964add1ee4511be5c Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Thu, 12 Jan 2017 18:18:06 -0500 Subject: [PATCH 37/48] SpanRelationship -> SpanReferenceType --- docs/usage.md | 2 +- opentracing/noop.h | 4 ++-- opentracing/spanoptions.h | 24 ++++++++++++------------ test/noop.t.cc | 2 +- test/span.h | 2 +- test/tracer.h | 2 +- test/tracer.t.cc | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 4593ba4..f7e609c 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -227,7 +227,7 @@ int httpGetAccount(const HttpRequest& httpRequest) { SpanOptions* opts(Tracer::makeSpanOptions()); - opts->setReference(SpanRelationship::e_ChildOf, *context); + opts->setReference(SpanReferenceType::e_ChildOf, *context); opts->setOperation("get_account_server"); span = Tracer::start(opts); diff --git a/opentracing/noop.h b/opentracing/noop.h index f29afa1..b4b24f4 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -91,7 +91,7 @@ class NoopOptions public: int setOperationImp(const StringRef&); int setStartTimeImp(const uint64_t); - int setReferenceImp(const SpanRelationship::Value, const NoopContext&); + int setReferenceImp(const SpanReferenceType::Value, const NoopContext&); template int setTagImp(const StringRef&, const T&); @@ -253,7 +253,7 @@ NoopOptions::setStartTimeImp(const uint64_t) } inline int -NoopOptions::setReferenceImp(const SpanRelationship::Value, const NoopContext&) +NoopOptions::setReferenceImp(const SpanReferenceType::Value, const NoopContext&) { return 0; } diff --git a/opentracing/spanoptions.h b/opentracing/spanoptions.h index 357da19..3a06030 100644 --- a/opentracing/spanoptions.h +++ b/opentracing/spanoptions.h @@ -4,7 +4,7 @@ // ============= // spanoptions.h // ============= -// class SpanRelationship - Enumeration for Span relationship types +// class SpanReferenceType - Enumeration for Span relationship types // class GenericSpanOptions - CRTP interface for SpanOptions #include @@ -12,22 +12,22 @@ namespace opentracing { -// ====================== -// class SpanRelationship -// ====================== +// ======================= +// 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. // -// * 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_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. // -// * 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. +// * 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 SpanRelationship { +class SpanReferenceType { public: enum Value { @@ -57,7 +57,7 @@ class GenericSpanOptions { // default is to use the current wall-time. Return 0 upon success and a // non-zero value otherwise. - int setReference(const SpanRelationship::Value relationship, + int setReference(const SpanReferenceType::Value relationship, const SpanContext& context); // A new Span created with these options would have a 'relationship' // referenced added for 'context'. Return 0 upon success and a non-zero @@ -90,7 +90,7 @@ GenericSpanOptions::setStartTime(const uint64_t tsp) template inline int GenericSpanOptions::setReference( - const SpanRelationship::Value rel, const SpanContext& context) + const SpanReferenceType::Value rel, const SpanContext& context) { const CONTEXT& contextImp = static_cast(context); return static_cast(this)->setReferenceImp(rel, contextImp); diff --git a/test/noop.t.cc b/test/noop.t.cc index 4a4f284..c221419 100644 --- a/test/noop.t.cc +++ b/test/noop.t.cc @@ -189,7 +189,7 @@ TEST_F(NoopTracerEnv, StartWithOpts) opts->setOperation("hello"); opts->setStartTime(1251251); - opts->setReference(SpanRelationship::e_FollowsFrom, *otherContext); + opts->setReference(SpanReferenceType::e_FollowsFrom, *otherContext); GlobalTracer::Span* span(GlobalTracer::start("hello")); EXPECT_TRUE(span); diff --git a/test/span.h b/test/span.h index 42cb6ec..eda99dd 100644 --- a/test/span.h +++ b/test/span.h @@ -30,7 +30,7 @@ class TestSpanImpl : public GenericSpansetOperation("test"); opts->setStartTime(12414); - opts->setReference(SpanRelationship::e_ChildOf, *otherContext); + opts->setReference(SpanReferenceType::e_ChildOf, *otherContext); Tracer::Span* span(Tracer::start(*opts)); ASSERT_TRUE(span); From be4f0053cca51954bca6351a0effbf36dc001578 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Thu, 12 Jan 2017 22:12:38 -0500 Subject: [PATCH 38/48] Spec SpanContext immutability --- opentracing/noop.h | 57 ++++++++++++++++++++------------ opentracing/span.h | 69 +++++++++++++++++++++++++++++---------- opentracing/spancontext.h | 16 ++------- test/noop.t.cc | 30 ++++++++++++----- test/span.h | 61 +++++++++++++++++++++++++++++----- test/span.t.cc | 29 +++------------- test/spancontext.h | 3 +- test/spancontext.t.cc | 4 +-- test/tracer.t.cc | 35 ++++++++++++-------- 9 files changed, 193 insertions(+), 111 deletions(-) diff --git a/opentracing/noop.h b/opentracing/noop.h index b4b24f4..702a200 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -74,7 +74,6 @@ class NoopContext : public GenericSpanContext { BaggageIterator baggageBeginImp() const; BaggageIterator baggageEndImp() const; - int setBaggageImp(const StringRef&, const StringRef&); int getBaggageImp(const StringRef&, std::string* const) const; int getBaggageImp(const StringRef&, std::vector* const) const; }; @@ -108,8 +107,13 @@ class NoopOptions class NoopSpan : public GenericSpan { public: - NoopContext& contextImp(); - const NoopContext& contextImp() const; + const NoopContext * contextImp() const; + + int setOperationImp(const StringRef&); + int setBaggageImp(const StringRef&, const StringRef&); + + int getBaggageImp(const StringRef&, std::string* const) const; + int getBaggageImp(const StringRef&, std::vector* const) const; int finishImp(); int finishImp(const uint64_t); @@ -123,7 +127,6 @@ class NoopSpan : public GenericSpan { template int logImp(const StringRef&, const T&, const uint64_t); - private: NoopContext m_context; }; @@ -217,12 +220,6 @@ NoopContext::baggageEndImp() const return BaggageIterator(this); } -inline int -NoopContext::setBaggageImp(const StringRef&, const StringRef&) -{ - return 0; -} - inline int NoopContext::getBaggageImp(const StringRef&, std::string* const) const { @@ -269,22 +266,40 @@ NoopOptions::setTagImp(const StringRef&, const T&) // class NooSpan // ------------- -inline NoopContext& -NoopSpan::contextImp() -{ - return m_context; -} - -inline const NoopContext& +inline const NoopContext* NoopSpan::contextImp() const { - return m_context; + return &m_context; } // -------------- // class NoopSpan // -------------- +inline int +NoopSpan::setOperationImp(const StringRef&) +{ + return 0; +} + +inline int +NoopSpan::setBaggageImp(const StringRef&, const StringRef&) +{ + return 0; +} + +inline int +NoopSpan::getBaggageImp(const StringRef&, std::string* const) const +{ + return 1; +} + +inline int +NoopSpan::getBaggageImp(const StringRef&, std::vector* const) const +{ + return 1; +} + inline int NoopSpan::finishImp() { @@ -396,21 +411,21 @@ template inline NoopContext* NoopTracer::extractImp(const GenericTextReader&) { - return &m_span.contextImp(); + return &m_span.m_context; } template inline NoopContext* NoopTracer::extractImp(const GenericBinaryReader&) { - return &m_span.contextImp(); + return &m_span.m_context; } template inline NoopContext* NoopTracer::extractImp(const GenericReader&) { - return &m_span.contextImp(); + return &m_span.m_context; } inline void diff --git a/opentracing/span.h b/opentracing/span.h index 7ebbaa3..1785dd9 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -30,10 +30,13 @@ namespace opentracing { // class SpanImpl: GenericSpan // { // public: -// ContextImpl& contextImp(); -// const ContextImpl& contextImp() const; +// const ContextImpl * contextImp() const; // // int setOperationImp(const StringRef& operation); +// int setBaggageImp(const StringRef&, const StringRef&); +// +// int getBaggageImp(const StringRef&, std::string* const) const; +// int getBaggageImp(const StringRef&, std::vector* const) const; // // int finishImp(); // int finishImp(const uint64_t); @@ -57,13 +60,26 @@ class GenericSpan { public: typedef GenericSpanContext SpanContext; - SpanContext& context(); - const SpanContext& context() const; - // Return the SpanContext associated with this span. Baggage can be - // retrieved/modified through the SpanContext. The context can be injected - // into carriers, or added as a reference to other causally related Spans. - // It is undefined behavior to modify the context after 'finish()' has been - // called on this Span. + const SpanContext * context() const; + // Return a copy of the SpanContext associated with this span. + // The context can be injected into carriers, or added as a reference to + // other causally related Spans. When finished with the SpanContext, it + // should be cleaned up with 'Tracer::cleanup()'. + + int setBaggage(const StringRef& key, const StringRef& value); + // Add the 'key:value' pair to this Span. Baggage is propagated with the Span + // in-band, throughout the lifetime of a Trace. Return 0 upon success + // and a non-zero value otherwise. + + int getBaggage(const StringRef &key, std::string *const baggage) const; + // Load a single 'baggage' value associated with 'key'. Returns 0 if there + // is only one value associated with 'key' and that value was loaded + // successfully. Return a non-zero value otherwise. + + int getBaggage(const StringRef & key, + std::vector *const baggage) const; + // Load the 'baggage' associated with 'key'. Returns 0 if the + // baggage is loaded successfully, and a non-zero value otherwise. int setOperation(const StringRef& operation); // Modify the Span's operation. Return 0 upon success and a non-zero @@ -77,7 +93,7 @@ class GenericSpan { // an explicit timestamp 'tsp'. Returns 0 upon success and a non-zero // value otherwise. Multiple calls to 'finish()' are redundant. The only // other method that may be called on the span, after 'finish()' is to - // access the 'context()' in a read-only fashion. + // copy the 'context()'. template int tag(const StringRef& key, const T& val); @@ -127,14 +143,7 @@ inline GenericSpan::GenericSpan(const GenericSpan&) } template -inline typename GenericSpan::SpanContext& -GenericSpan::context() -{ - return static_cast(this)->contextImp(); -} - -template -inline const typename GenericSpan::SpanContext& +inline const typename GenericSpan::SpanContext* GenericSpan::context() const { return static_cast(this)->contextImp(); @@ -147,6 +156,30 @@ GenericSpan::setOperation(const StringRef& operation) return static_cast(this)->setOperationImp(operation); } +template +inline int +GenericSpan::setBaggage(const StringRef& key, + const StringRef& value) +{ + return static_cast(this)->setBaggageImp(key, value); +} + +template +inline int +GenericSpan::getBaggage(const StringRef& key, + std::string* const value) const +{ + return static_cast(this)->getBaggageImp(key, value); +} + +template +inline int +GenericSpan::getBaggage( + const StringRef& key, std::vector* const value) const +{ + return static_cast(this)->getBaggageImp(key, value); +} + template inline int GenericSpan::finish() diff --git a/opentracing/spancontext.h b/opentracing/spancontext.h index 480aa9d..74d5ca5 100644 --- a/opentracing/spancontext.h +++ b/opentracing/spancontext.h @@ -28,14 +28,14 @@ namespace opentracing { // typename Adapter::const_iterator baggageBeginImp() const; // typename Adapter::const_iterator baggageEndImp() const; // -// int setBaggageImp(const StringRef&, const StringRef&); // int getBaggageImp(const StringRef&, std::string* const) const; // int getBaggageImp(const StringRef&, std::vector* const) const; // }; // // Implementations may choose how they implement storage of Baggage, but the // baggageBeginImp/baggageEndImp iterators should interact with the installed -// BaggageIterator/Adapter correctly. +// BaggageIterator/Adapter correctly. Contexts should be immutable and +// thread-safe. template class GenericSpanContext { @@ -57,10 +57,6 @@ class GenericSpanContext { // Return a structure containing the range of iterators: // [baggageBegin, baggageEnd). The object supports range-based for loops. - int setBaggage(const StringRef &key, const StringRef &baggage); - // Set or append the single 'baggage' value for the given 'key'. Return 0 - // upon success and a non-zero value otherwise. - int getBaggage(const StringRef &key, std::string *const baggage) const; // Load a single 'baggage' value associated with 'key'. Returns 0 if there // is only one value associated with 'key' and that value was loaded @@ -114,14 +110,6 @@ GenericSpanContext::baggageRange() const return BaggageRange(baggageBegin(), baggageEnd()); } -template -inline int -GenericSpanContext::setBaggage(const StringRef &key, - const StringRef &baggage) -{ - return static_cast(this)->setBaggageImp(key, baggage); -} - template inline int GenericSpanContext::getBaggage( diff --git a/test/noop.t.cc b/test/noop.t.cc index c221419..58a9175 100644 --- a/test/noop.t.cc +++ b/test/noop.t.cc @@ -53,18 +53,18 @@ TEST_F(NoopTracerEnv, StartWithOp) rc = span->log("server", "blahblahblah"); ASSERT_EQ(0, rc); - rc = span->context().setBaggage("hello", "world"); + rc = span->setBaggage("hello", "world"); ASSERT_EQ(0, rc); - rc = span->context().setBaggage("apple", "banana"); + rc = span->setBaggage("apple", "banana"); ASSERT_EQ(0, rc); std::string val; - rc = span->context().getBaggage("apple", &val); + rc = span->getBaggage("apple", &val); ASSERT_NE(0, rc); std::vector vals; - rc = span->context().getBaggage("apple", &vals); + rc = span->getBaggage("apple", &vals); ASSERT_NE(0, rc); GlobalTracer::cleanup(span); @@ -89,13 +89,16 @@ TEST_F(NoopTracerEnv, InjectText) GlobalTracer::Span* span(GlobalTracer::start("op")); ASSERT_TRUE(span); - span->context().setBaggage("animal", "tiger"); - span->context().setBaggage("animal", "cat"); + span->setBaggage("animal", "tiger"); + span->setBaggage("animal", "cat"); - int rc = GlobalTracer::inject(&writer, span->context()); + const GlobalTracer::SpanContext * context = span->context(); + + int rc = GlobalTracer::inject(&writer, *context); ASSERT_EQ(0, rc); GlobalTracer::cleanup(span); + GlobalTracer::cleanup(context); } TEST_F(NoopTracerEnv, ExtractText) @@ -130,9 +133,13 @@ TEST_F(NoopTracerEnv, InjectBinary) TestBinaryWriter writer; GlobalTracer::Span* span = GlobalTracer::start("op"); ASSERT_TRUE(span); - int rc = GlobalTracer::inject(&writer, span->context()); + + const GlobalTracer::SpanContext * context = span->context(); + + int rc = GlobalTracer::inject(&writer, *context); ASSERT_EQ(0, rc); GlobalTracer::cleanup(span); + GlobalTracer::cleanup(context); } TEST_F(NoopTracerEnv, ExtractBinary) @@ -157,10 +164,14 @@ TEST_F(NoopTracerEnv, InjectExplicit) NoopWriter w; GlobalTracer::Span* span(GlobalTracer::start("span")); ASSERT_TRUE(span); - int rc = GlobalTracer::inject(&w, span->context()); + + const GlobalTracer::SpanContext * context = span->context(); + + int rc = GlobalTracer::inject(&w, *context); ASSERT_EQ(0, rc); GlobalTracer::cleanup(span); + GlobalTracer::cleanup(context); } struct NoopReader : public GenericReader @@ -190,6 +201,7 @@ TEST_F(NoopTracerEnv, StartWithOpts) opts->setOperation("hello"); opts->setStartTime(1251251); opts->setReference(SpanReferenceType::e_FollowsFrom, *otherContext); + opts->setTag("hello", 125); GlobalTracer::Span* span(GlobalTracer::start("hello")); EXPECT_TRUE(span); diff --git a/test/span.h b/test/span.h index eda99dd..6b5ca30 100644 --- a/test/span.h +++ b/test/span.h @@ -11,21 +11,66 @@ class TestSpanImpl : public GenericSpan { public: - TestContextImpl& - contextImp() + const TestContextImpl * + contextImp() const { - return d_context; + TestContextImpl * context = new TestContextImpl(); + context->baggageMap() = m_context.baggageMap(); } - const TestContextImpl& - contextImp() const + int + setOperationImp(const StringRef&) { - return d_context; + return 0; } int - setOperationImp(const StringRef&) + getBaggageImp(const StringRef& key, std::string* const baggage) const + { + std::vector out; + + getBaggageImp(key, &out); + + if (1u == out.size()) + { + *baggage = out[0]; + return 0; + } + else + { + return 1; + } + } + + int + getBaggageImp(const StringRef& key, + std::vector* const baggage) const + { + baggage->clear(); + + const std::string mkey(key.data(), key.length()); + + const std::pair + range = m_context.baggageMap().equal_range(mkey); + + for (TestBaggageContainer::const_iterator it = range.first, + end = range.second; + it != end; + ++it) + { + baggage->push_back(it->second); + } + + return baggage->empty(); + } + int + setBaggageImp(const StringRef& key, const StringRef& baggage) { + m_context.baggageMap().insert(TestBaggageContainer::value_type( + std::string(key.data(), key.length()), + std::string(baggage.data(), baggage.length()))); + return 0; } @@ -69,7 +114,7 @@ class TestSpanImpl : public GenericSpan diff --git a/test/span.t.cc b/test/span.t.cc index 6bcfb7b..6622367 100644 --- a/test/span.t.cc +++ b/test/span.t.cc @@ -1,34 +1,13 @@ #include "unittest.h" #include "span.h" -TEST(Span, BasicTests) + +TEST(SpanTests, setOperation) { TestSpanImpl impl; TestSpan& t = impl; - - int rc = impl.context().setBaggage("hello", "world"); - - { - // Make sure const references work - const TestSpan& tc = impl; - - std::vector vals; - rc = tc.context().getBaggage("hello", &vals); - - ASSERT_EQ(0, rc); - ASSERT_EQ(1u, vals.size()); - ASSERT_EQ("world", vals[0]); - - const TestSpan::SpanContext& cc = tc.context(); - rc = cc.getBaggage("miss", &vals); - ASSERT_NE(0, rc); - - TestSpan::SpanContext::BaggageIterator it = cc.baggageBegin(); - ASSERT_FALSE(it == cc.baggageEnd()); - } - - t.finish(); - t.finish(1234567); + const int rc = t.setOperation("hello world"); + ASSERT_EQ(0, rc); } template diff --git a/test/spancontext.h b/test/spancontext.h index defbccc..2aaebd7 100644 --- a/test/spancontext.h +++ b/test/spancontext.h @@ -30,8 +30,9 @@ struct TestContextBaggageAdapter { class TestContextImpl : public GenericSpanContext { public: + // For tests only, not part of the interface int - setBaggageImp(const StringRef& key, const StringRef& baggage) + setBaggage(const StringRef& key, const StringRef& baggage) { m_baggage.insert(TestBaggageContainer::value_type( std::string(key.data(), key.length()), diff --git a/test/spancontext.t.cc b/test/spancontext.t.cc index f4c458b..ae19211 100644 --- a/test/spancontext.t.cc +++ b/test/spancontext.t.cc @@ -9,7 +9,7 @@ TEST(GenericSpanContext, BaggageCopies) TestContextImpl imp; TestContext& t = imp; - int rc = t.setBaggage("hello", "world"); + int rc = imp.setBaggage("hello", "world"); ASSERT_EQ(0, rc); std::vector vals; @@ -44,7 +44,7 @@ TEST(GenericSpanContext, CopyConstructor) TestContextImpl impl; TestContext& t = impl; - int rc = t.setBaggage("hello", "world"); + int rc = impl.setBaggage("hello", "world"); ASSERT_EQ(0, rc); TestContextImpl implCopy = impl; diff --git a/test/tracer.t.cc b/test/tracer.t.cc index 660c0dd..1fc6dbd 100644 --- a/test/tracer.t.cc +++ b/test/tracer.t.cc @@ -39,21 +39,21 @@ TEST_F(TracerEnv, StartWithOp) rc = span->log("server", "blahblahblah"); ASSERT_EQ(0, rc); - rc = span->context().setBaggage("hello", "world"); + rc = span->setBaggage("hello", "world"); ASSERT_EQ(0, rc); - rc = span->context().setBaggage("apple", "banana"); + rc = span->setBaggage("apple", "banana"); ASSERT_EQ(0, rc); std::vector vals; - rc = span->context().getBaggage("apple", &vals); + rc = span->getBaggage("apple", &vals); ASSERT_EQ(0, rc); ASSERT_EQ(1u, vals.size()); ASSERT_EQ("banana", vals[0]); std::string val; - rc = span->context().getBaggage("apple", &val); + rc = span->getBaggage("apple", &val); ASSERT_EQ(0, rc); ASSERT_EQ("banana", val); @@ -68,10 +68,12 @@ TEST_F(TracerEnv, InjectText) Tracer::Span* span(Tracer::start("op")); ASSERT_TRUE(span); - span->context().setBaggage("animal", "tiger"); - span->context().setBaggage("animal", "cat"); + span->setBaggage("animal", "tiger"); + span->setBaggage("animal", "cat"); - int rc = Tracer::inject(&writer, span->context()); + const Tracer::SpanContext * context = span->context(); + + int rc = Tracer::inject(&writer, *context); ASSERT_EQ(0, rc); ASSERT_EQ(2u, writer.pairs.size()); @@ -82,6 +84,7 @@ TEST_F(TracerEnv, InjectText) ASSERT_TRUE(writer.pairs[1].m_value == "cat" || writer.pairs[1].m_value == "tiger"); Tracer::cleanup(span); + Tracer::cleanup(context); } TEST_F(TracerEnv, ExtractText) @@ -118,9 +121,13 @@ TEST_F(TracerEnv, InjectBinary) Tracer::Span* span(Tracer::start("op")); ASSERT_TRUE(span); - int rc = Tracer::inject(&writer, span->context()); + const Tracer::SpanContext * context = span->context(); + + int rc = Tracer::inject(&writer, *context); ASSERT_EQ(0, rc); ASSERT_EQ(0xdeadbeef, writer.m_raw); + + Tracer::cleanup(context); } TEST_F(TracerEnv, ExtractBinary) @@ -130,7 +137,6 @@ TEST_F(TracerEnv, ExtractBinary) const Tracer::SpanContext* context(Tracer::extract(reader)); ASSERT_TRUE(context); - Tracer::cleanup(context); } @@ -142,10 +148,12 @@ TEST_F(TracerEnv, InjectExplicit) Tracer::Span* span(Tracer::start("span")); ASSERT_TRUE(span); - span->context().setBaggage("animal", "tiger"); - span->context().setBaggage("fruit", "apple"); + span->setBaggage("animal", "tiger"); + span->setBaggage("fruit", "apple"); + + const Tracer::SpanContext * const context = span->context(); - int rc = Tracer::inject(&w, span->context()); + int rc = Tracer::inject(&w, *context); ASSERT_EQ(0, rc); ASSERT_EQ(2u, w.carrier.size()); @@ -159,6 +167,7 @@ TEST_F(TracerEnv, InjectExplicit) ASSERT_EQ("apple", cit->second); Tracer::cleanup(span); + Tracer::cleanup(context); } TEST_F(TracerEnv, ExtractExplicit) @@ -168,7 +177,6 @@ TEST_F(TracerEnv, ExtractExplicit) reader.carrier.insert(TestBaggageContainer::value_type("fruit", "apple")); const Tracer::SpanContext* context(Tracer::extract(reader)); ASSERT_TRUE(context); - Tracer::cleanup(context); } @@ -186,6 +194,7 @@ TEST_F(TracerEnv, StartWithOptions) opts->setOperation("test"); opts->setStartTime(12414); opts->setReference(SpanReferenceType::e_ChildOf, *otherContext); + opts->setTag("hello", "world"); Tracer::Span* span(Tracer::start(*opts)); ASSERT_TRUE(span); From abd02a11470ffe06ce20217a73d772e07873b0c9 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Thu, 12 Jan 2017 22:14:09 -0500 Subject: [PATCH 39/48] Doc changes --- opentracing/carriers.h | 3 +-- opentracing/span.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/opentracing/carriers.h b/opentracing/carriers.h index c59ffd3..053643b 100644 --- a/opentracing/carriers.h +++ b/opentracing/carriers.h @@ -26,8 +26,7 @@ // the Tracer using the GenericTextReader, GenericBinaryReader, or GenericReader // interfaces. If the readers are successful, an immutable SpanContext is // returned to applications. That SpanContext can then be used to create -// new spans, accessing its baggage or adding it as a reference to in other -// Spans. +// new spans or accessing baggage. #include #include diff --git a/opentracing/span.h b/opentracing/span.h index 1785dd9..d9b9a29 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -53,7 +53,7 @@ namespace opentracing { // // The templated 'tagImp' and 'logImp' methods may assume that the following // method is defined for any type 'T': -// `std::ostream& operator<<(std::ostream&, const T& val);` +// `std::ostream& ::operator<<(std::ostream&, const T& val);` template class GenericSpan { From c0441da4713fa5847a9b0bad4cc7a4808d48a2d3 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Sat, 14 Jan 2017 06:49:34 -0500 Subject: [PATCH 40/48] Avoid unnecessary copies in BinaryWriters --- opentracing/carriers.h | 8 ++++---- opentracing/tracer.h | 4 ++-- test/carriers.h | 6 +++--- test/carriers.t.cc | 4 ++-- test/tracer.h | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/opentracing/carriers.h b/opentracing/carriers.h index 053643b..e77da62 100644 --- a/opentracing/carriers.h +++ b/opentracing/carriers.h @@ -89,7 +89,7 @@ class GenericTextWriter { // // class BinaryWriter : GenericBinaryWriter{ // public: -// int injectImp(const vector& buf); +// int injectImp(const void* const buf, const size_t len); // }; // // Implementations are responsible for passing the blob along with a carrier @@ -99,7 +99,7 @@ class GenericTextWriter { template class GenericBinaryWriter { public: - int inject(const std::vector& buf); + int inject(const void * const buf, const size_t len); // Inject the binary representation of a span context into this carrier. protected: @@ -286,9 +286,9 @@ inline GenericTextWriter::GenericTextWriter(const GenericTextWriter&) template inline int -GenericBinaryWriter::inject(const std::vector& buf) +GenericBinaryWriter::inject(const void* const buf, const size_t len) { - return static_cast(this)->injectImp(buf); + return static_cast(this)->injectImp(buf, len); } template diff --git a/opentracing/tracer.h b/opentracing/tracer.h index 299c2d1..95ad4c8 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -43,9 +43,9 @@ namespace opentracing { // GenericTracer // { // public: -// static installImp(TracerImp*); +// static void installImp(TracerImp*); // static TracerImp * instanceImp(); -// static uninstallImp(); +// static void uninstallImp(); // // Options * makeSpanOptionsImp(); // void cleanupImp(const Options * const opts); diff --git a/test/carriers.h b/test/carriers.h index 2b39090..67b2b8f 100644 --- a/test/carriers.h +++ b/test/carriers.h @@ -32,14 +32,14 @@ struct TestTextReader : public GenericTextReader { struct TestBinaryWriter : public GenericBinaryWriter { int - injectImp(const std::vector& buf) + injectImp(const void* const buf, const size_t len) { - if (buf.size() > sizeof(m_raw)) + if (len > sizeof(m_raw)) { return 1; } - std::memcpy(&m_raw, &buf[0], buf.size()); + std::memcpy(&m_raw, buf, len); return 0; } diff --git a/test/carriers.t.cc b/test/carriers.t.cc index e8c4a02..f79e78f 100644 --- a/test/carriers.t.cc +++ b/test/carriers.t.cc @@ -86,7 +86,7 @@ TEST(Carriers, BinaryWriter) buf.resize(sizeof(tooBig)); std::memcpy(&buf[0], &tooBig, sizeof(tooBig)); - int rc = t.inject(buf); + int rc = t.inject(buf.data(), buf.size()); ASSERT_NE(0, rc); const int32_t expected = 0xdeadbeef; @@ -94,7 +94,7 @@ TEST(Carriers, BinaryWriter) buf.resize(sizeof(expected)); std::memcpy(&buf[0], &expected, sizeof(expected)); - rc = t.inject(buf); + rc = t.inject(buf.data(), buf.size()); ASSERT_EQ(0, rc); ASSERT_EQ(expected, imp.m_raw); } diff --git a/test/tracer.h b/test/tracer.h index 4fdc6a2..b251c37 100644 --- a/test/tracer.h +++ b/test/tracer.h @@ -118,7 +118,7 @@ class TestTracerImpl : public GenericTracerinject(buf); + return carrier->inject(buf.data(), buf.size()); } template From 2108eaa561eca7b47d2dafcbe7df65ee11fae0b7 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Sat, 14 Jan 2017 06:52:46 -0500 Subject: [PATCH 41/48] Update usage --- docs/usage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index f7e609c..3004aca 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -149,9 +149,9 @@ class HttpWriter : public GenericBinaryWriter public: HttpWriter(HttpRequest * req): m_req(req){} - int injectImp(const std::vector& blob) + int injectImp(const void * const blob, const size_t len) { - std::string header(blob.data(), blob.size()); + std::string header(static_cast(blob), len); req->addHeader("x-acme-tracing-blob", header); return 0; } From 3a1c1f8bda0c38e6a86d232fe5a944d6e35e6190 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Sun, 15 Jan 2017 17:49:46 -0500 Subject: [PATCH 42/48] Accessory inject method to avoid context copies --- opentracing/noop.h | 10 +++++++ opentracing/tracer.h | 25 +++++++++++++++++ test/noop.t.cc | 17 ++++++++++++ test/span.h | 1 - test/tracer.h | 7 +++++ test/tracer.t.cc | 64 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 123 insertions(+), 1 deletion(-) diff --git a/opentracing/noop.h b/opentracing/noop.h index 702a200..c1d2f4a 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -157,6 +157,9 @@ class NoopTracer : public GenericTracer + int injectImp(CARRIER_T* const carrier, const NoopSpan& span) const; + template int injectImp(GenericTextWriter* const carrier, const NoopContext& context) const; @@ -383,6 +386,13 @@ NoopTracer::cleanupImp(const Span* const) { } +template +inline int +NoopTracer::injectImp(CARRIER_T* const, const NoopSpan&) const +{ + return 0; +} + template inline int NoopTracer::injectImp(GenericTextWriter* const, diff --git a/opentracing/tracer.h b/opentracing/tracer.h index 95ad4c8..2a2b946 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -54,6 +54,9 @@ namespace opentracing { // SpanImp * start(const OptionsImp& opts); // void cleanupImp(const SpanImp * const sp); // +// template +// int injectImp(CARRIER_T*const carrier, const SpanImp& context) const; +// // template // int injectImp( // GenericTextWriter* const carrier, @@ -144,6 +147,13 @@ class GenericTracer { // All Span pointers returned by the Tracer via 'start()' must be passed // back to the Tracer when clients are done with them via 'cleanup()'. + template + static int inject(CARRIER_T* const carrier, const Span& span); + // Inject the supplied 'span' into the supplied 'carrier' writer. This + // method should defer to other inject implementations, but gives + // implementations the opportunity to avoid copying the span context + // of a span. Returns 0 upon success and a non-zero value otherwise. + template static int inject(GenericTextWriter* const carrier, const SpanContext& context); @@ -317,6 +327,21 @@ GenericTracer::cleanup(Span* const sp) return TRACER::instanceImp()->cleanupImp(spanImp); } +template +template +inline int +GenericTracer::inject( + CARRIER_T* const carrier, const Span& span) +{ + const SPAN& spanImp = static_cast(span); + const TRACER* tracer = TRACER::instanceImp(); + return tracer->injectImp(carrier, spanImp); +} + template setBaggage("animal", "tiger"); + span->setBaggage("animal", "cat"); + + int rc = GlobalTracer::inject(&writer, *span); + ASSERT_EQ(0, rc); + + GlobalTracer::cleanup(span); +} + TEST_F(NoopTracerEnv, InjectText) { TestTextWriter writer; @@ -101,6 +116,8 @@ TEST_F(NoopTracerEnv, InjectText) GlobalTracer::cleanup(context); } + + TEST_F(NoopTracerEnv, ExtractText) { TestTextReader reader; diff --git a/test/span.h b/test/span.h index 6b5ca30..4a290c5 100644 --- a/test/span.h +++ b/test/span.h @@ -113,7 +113,6 @@ class TestSpanImpl : public GenericSpan + int + injectImp(CARRIER_T* const carrier, const TestSpanImpl& imp) const + { + return injectImp(carrier, imp.m_context); + } + template int injectImp(GenericTextWriter* const carrier, diff --git a/test/tracer.t.cc b/test/tracer.t.cc index 1fc6dbd..1a30a47 100644 --- a/test/tracer.t.cc +++ b/test/tracer.t.cc @@ -87,6 +87,29 @@ TEST_F(TracerEnv, InjectText) Tracer::cleanup(context); } +TEST_F(TracerEnv, SpanInjectText) +{ + TestTextWriter writer; + + Tracer::Span* span(Tracer::start("op")); + ASSERT_TRUE(span); + + span->setBaggage("animal", "tiger"); + span->setBaggage("animal", "cat"); + + int rc = Tracer::inject(&writer, *span); + ASSERT_EQ(0, rc); + ASSERT_EQ(2u, writer.pairs.size()); + + ASSERT_EQ(writer.pairs[0].m_name, "animal"); + ASSERT_EQ(writer.pairs[1].m_name, "animal"); + + ASSERT_TRUE(writer.pairs[0].m_value == "cat" || writer.pairs[0].m_value == "tiger"); + ASSERT_TRUE(writer.pairs[1].m_value == "cat" || writer.pairs[1].m_value == "tiger"); + + Tracer::cleanup(span); +} + TEST_F(TracerEnv, ExtractText) { TestTextReader reader; @@ -128,6 +151,21 @@ TEST_F(TracerEnv, InjectBinary) ASSERT_EQ(0xdeadbeef, writer.m_raw); Tracer::cleanup(context); + Tracer::cleanup(span); +} + +TEST_F(TracerEnv, SpanInjectBinary) +{ + TestBinaryWriter writer; + + Tracer::Span* span(Tracer::start("op")); + ASSERT_TRUE(span); + + int rc = Tracer::inject(&writer, *span); + ASSERT_EQ(0, rc); + ASSERT_EQ(0xdeadbeef, writer.m_raw); + + Tracer::cleanup(span); } TEST_F(TracerEnv, ExtractBinary) @@ -170,6 +208,32 @@ TEST_F(TracerEnv, InjectExplicit) Tracer::cleanup(context); } +TEST_F(TracerEnv, SpanInjectExplicit) +{ + TestWriter w; + + Tracer::Span* span(Tracer::start("span")); + ASSERT_TRUE(span); + + span->setBaggage("animal", "tiger"); + span->setBaggage("fruit", "apple"); + + int rc = Tracer::inject(&w, *span); + ASSERT_EQ(0, rc); + ASSERT_EQ(2u, w.carrier.size()); + + TestBaggageContainer::const_iterator cit = w.carrier.find("animal"); + + ASSERT_NE(cit, w.carrier.end()); + ASSERT_EQ("tiger", cit->second); + + cit = w.carrier.find("fruit"); + ASSERT_NE(cit, w.carrier.end()); + ASSERT_EQ("apple", cit->second); + + Tracer::cleanup(span); +} + TEST_F(TracerEnv, ExtractExplicit) { TestReader reader; From a62cb0b266726b4f1846cc18a46d1fc504e1b260 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Mon, 16 Jan 2017 20:32:40 -0500 Subject: [PATCH 43/48] Simplify inject/extract interface --- opentracing/carriers.h | 109 ++++++++++++++--------------- opentracing/noop.h | 17 +++-- opentracing/tracer.h | 152 +++++------------------------------------ test/carriers.h | 8 +-- test/carriers.t.cc | 12 ++-- test/noop.t.cc | 14 ++-- test/tracer.h | 10 ++- test/tracer.t.cc | 8 +-- 8 files changed, 98 insertions(+), 232 deletions(-) diff --git a/opentracing/carriers.h b/opentracing/carriers.h index e77da62..ab0e7a5 100644 --- a/opentracing/carriers.h +++ b/opentracing/carriers.h @@ -45,7 +45,7 @@ class TextMapPair { TextMapPair(); TextMapPair(const StringRef& name, const StringRef& value); - std::string m_name; + std::string m_key; std::string m_value; }; @@ -110,40 +110,36 @@ class GenericBinaryWriter { // =================== // class GenericWriter // =================== -// GenericWriters are used to 'inject' an explicit SpanContext into an -// arbitrary carrier message. +// GenericWriters are used to 'inject' an explicit implementation detail +// into a carrier message. +// +// If clients want to rely on the details of a particular implementation, +// the GenericWriter mechanism allows avoid access without working around +// the C++ type system. // -// If clients want to rely on the details of a particular SpanContext -// implementation (for API simplicity, performance reasons, etc.), they can -// create a GenericWriter that is templated on the *specific* SpanContext -// implementation that they are using. This removes flexibility, making -// it harder to change opentracing-cpp implementations, however, -// it is better to embed the dependency in the type system than rely -// on workarounds such as run time dynamic_cast/reinterpret_cast checks. +// This removes flexibility, making it harder to change opentracing-cpp +// implementations, however, it is better to embed the dependency in the type +// system than rely on workarounds such as run time +// dynamic_cast/reinterpret_cast checks. // // For this to work, implementations must support: // -// class ExplicitWriter: GenericWriter +// class ExplicitWriter: GenericWriter> // { // public: -// int inject(const SpanContextImpl&); +// int injectImp(const ImplType&); // }; // -// The Tracer will be responsible for all downcasting, and the explicit -// SpanContextImpl object will be passed directly to the Writer. It can -// then use any of the public API's that the Tracer may be using, to -// interact with the SpanContext directly. -// -// Implementations are responsible for emebeding the details of the -// SpanContextImpl into a carrier object. When constructed of the -// SpanContextImpl along with a carrier object. When constructed, the outgoing -// RPC carrier objects. +// Tracer implementations will be responsible for making sure 'ImplType' +// is passed to the carrier. Will fail to compile if the inject type +// is not compatible with the installed tracer implementation. -template +template class GenericWriter { public: - int inject(const CONTEXT& context); - // Inject the supplied 'context' directly into this carrier. + template + int inject(const T& impl); + // Inject the supplied 'impl' object directly into this carrier. protected: GenericWriter(); @@ -211,35 +207,28 @@ class GenericBinaryReader { // =================== // class GenericReader // =================== -// GenericReaders are used to 'extract' an explicit SpanContext out of an -// arbitrary carrier message. +// GenericReaders are used to 'extract' an explicit implementation +// detail out of an arbitrary carrier message. // -// If clients want to rely on the details of a particular SpanContext -// implementation (for API simplicity, performance reasons, etc.), they can -// create a GenericReader that is templated on the *specific* SpanContext -// implementation that they are using. This removes flexibility, making -// it harder to change opentracing-cpp implementations, however, -// it is better to embed the dependency in the type system than rely -// on workarounds such as run time dynamic_cast/reinterpret_cast checks. +// This removes flexibility, making it harder to change opentracing-cpp +// implementations, however, it is better to embed the dependency in the type +// system than rely on workarounds such as run time +// dynamic_cast/reinterpret_cast checks. // // For this to work, implementations must support: // -// class ExplicitReader: GenericReader +// class ExplicitReader: GenericReader // { // public: -// int extractImp(SpanContextImpl* const) const; +// int extractImp(ImplType* const) const; // }; -// -// The Tracer will be responsible for downcasting, and the explicit -// SpanContextImpl address will be passed directly to the Reader. The -// Reader can then use any of the public methods that the SpanContextImpl -// exposes, which may be much more than the GenericSpanContext interface. -template +template class GenericReader { public: - int extract(CONTEXT* const context) const; - // Extract the supplied 'context' directly from this carrier. + template + int extract(T* const impl) const; + // Extract the 'impl' object directly from this carrier. protected: GenericReader(); @@ -250,12 +239,12 @@ class GenericReader { // class TextMapPair // ----------------- -inline TextMapPair::TextMapPair() : m_name(), m_value() +inline TextMapPair::TextMapPair() : m_key(), m_value() { } inline TextMapPair::TextMapPair(const StringRef& name, const StringRef& value) -: m_name(name.data(), name.length()), m_value(value.data(), value.length()) +: m_key(name.data(), name.length()), m_value(value.data(), value.length()) { } @@ -306,20 +295,21 @@ inline GenericBinaryWriter::GenericBinaryWriter( // class GenericWriter // ------------------- -template +template +template inline int -GenericWriter::inject(const CONTEXT& context) +GenericWriter::inject(const T& impl) { - return static_cast(this)->injectImp(context); + return static_cast(this)->injectImp(impl); } -template -inline GenericWriter::GenericWriter() +template +inline GenericWriter::GenericWriter() { } -template -inline GenericWriter::GenericWriter(const GenericWriter&) +template +inline GenericWriter::GenericWriter(const GenericWriter&) { } @@ -371,20 +361,21 @@ inline GenericBinaryReader::GenericBinaryReader( // class GenericReader // ------------------- -template +template +template inline int -GenericReader::extract(CONTEXT* const context) const +GenericReader::extract(T* const impl) const { - return static_cast(this)->extractImp(context); + return static_cast(this)->extractImp(impl); } -template -inline GenericReader::GenericReader() +template +inline GenericReader::GenericReader() { } -template -inline GenericReader::GenericReader(const GenericReader&) +template +inline GenericReader::GenericReader(const GenericReader&) { } diff --git a/opentracing/noop.h b/opentracing/noop.h index c1d2f4a..8dbbc23 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -157,8 +157,8 @@ class NoopTracer : public GenericTracer - int injectImp(CARRIER_T* const carrier, const NoopSpan& span) const; + template + int injectImp(CARRIER* const carrier, const NoopSpan& span) const; template int injectImp(GenericTextWriter* const carrier, @@ -169,7 +169,7 @@ class NoopTracer : public GenericTracer - int injectImp(GenericWriter* const carrier, + int injectImp(GenericWriter* const carrier, const NoopContext& context) const; template @@ -179,7 +179,7 @@ class NoopTracer : public GenericTracer& carrier); template - NoopContext* extractImp(const GenericReader& carrier); + NoopContext* extractImp(const GenericReader& carrier); void cleanupImp(const NoopContext* const sp); @@ -386,9 +386,9 @@ NoopTracer::cleanupImp(const Span* const) { } -template +template inline int -NoopTracer::injectImp(CARRIER_T* const, const NoopSpan&) const +NoopTracer::injectImp(CARRIER* const, const NoopSpan&) const { return 0; } @@ -411,8 +411,7 @@ NoopTracer::injectImp(GenericBinaryWriter* const, template inline int -NoopTracer::injectImp(GenericWriter* const, - const NoopContext&) const +NoopTracer::injectImp(GenericWriter* const, const NoopContext&) const { return 0; } @@ -433,7 +432,7 @@ NoopTracer::extractImp(const GenericBinaryReader&) template inline NoopContext* -NoopTracer::extractImp(const GenericReader&) +NoopTracer::extractImp(const GenericReader&) { return &m_span.m_context; } diff --git a/opentracing/tracer.h b/opentracing/tracer.h index 2a2b946..1b96391 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -54,35 +54,14 @@ namespace opentracing { // SpanImp * start(const OptionsImp& opts); // void cleanupImp(const SpanImp * const sp); // -// template -// int injectImp(CARRIER_T*const carrier, const SpanImp& context) const; -// // template -// int injectImp( -// GenericTextWriter* const carrier, -// const ContextImp& context) const; +// int injectImp(CARRIER*const carrier, const SpanImp& context) const; // // template -// int injectImp( -// GenericBinaryWriter* const carrier, -// const ContextImp& context) const; -// -// template -// int injectImp( -// GenericWriter* const carrier, -// const ContextImp& context) const; -// -// template -// const ContextImp* extractImp( -// const GenericTextReader& carrier); +// int injectImp(CARRIER*const carrier, const ContextImp& context) const; // // template -// const ContextImp* extractImp( -// const GenericBinaryReader& carrier); -// -// template -// const ContextImp* extractImp( -// const GenericReader& carrier); +// const ContextImp* extractImp(const CARRIER& carrier); // // void cleanupImp(const ContextImp * const); // }; @@ -147,57 +126,23 @@ class GenericTracer { // All Span pointers returned by the Tracer via 'start()' must be passed // back to the Tracer when clients are done with them via 'cleanup()'. - template - static int inject(CARRIER_T* const carrier, const Span& span); - // Inject the supplied 'span' into the supplied 'carrier' writer. This - // method should defer to other inject implementations, but gives - // implementations the opportunity to avoid copying the span context - // of a span. Returns 0 upon success and a non-zero value otherwise. - template - static int inject(GenericTextWriter* const carrier, - const SpanContext& context); - // Inject the supplied 'context' into the text map writer 'carrier'. - // Returns 0 upon success and a non-zero value otherwise. - - template - static int inject(GenericBinaryWriter* const carrier, - const SpanContext& context); - // Inject the supplied 'context' into the binary writer 'carrier'. - // Returns 0 upon success and a non-zero value otherwise. + static int inject(CARRIER* const carrier, const Span& span); + // Inject the supplied 'span' into the supplied 'carrier' writer. This + // method should expect one of the 'Writer' carriers defined in + // carriers.h. Returns 0 upon success and a non-zero value otherwise. template - static int inject(GenericWriter* const carrier, - const SpanContext& context); - // Inject the SpanContext directly into the specialized 'carrier'. - // Returns 0 upon success and a non-zero value otherwise. - // - // Note: The carrier will be passed the SpanContext directly. Using this may - // make your carrier code more efficient, but, it removes flexibility if you - // want to swap Tracer/Span implementations. + static int inject(CARRIER* const carrier, const SpanContext& context); + // Inject the supplied 'span' into the supplied 'carrier' writer. This + // method should expect one of the 'Writer' carriers defined in + // carriers.h. Returns 0 upon success and a non-zero value otherwise. template - static const SpanContext* extract( - const GenericTextReader& carrier); + static const SpanContext* extract(const CARRIER& carrier); // Extract the read-only supplied 'context' from the text map reader - // 'carrier' upon success, and NULL otherwise. Returns NULL on error. - - template - static const SpanContext* extract( - const GenericBinaryReader& carrier); - // Extract the read-only SpanContext from the binary reader 'carrier' - // upon success, and NULL otherwise. Returns NULL on error. - - template - static const SpanContext* extract( - const GenericReader& carrier); - // Extract the read-only SpanContext from the specialized 'carrier'. Returns - // NULL on error. - // - // Note: The carrier will be passed the SpanContext directly. - // Using this may make your carrier code more efficient, but, it - // removes flexibility if you want to swap Tracer/Span implementations - // later. + // 'carrier' upon success, and NULL otherwise. Should expect one + // of the 'Reader' carriers defined in carriers.h. static void cleanup(const SpanContext* const sp); // All SpanContext pointers created by the Tracer through 'extract()' should @@ -332,10 +277,10 @@ template -template +template inline int GenericTracer::inject( - CARRIER_T* const carrier, const Span& span) + CARRIER* const carrier, const Span& span) { const SPAN& spanImp = static_cast(span); const TRACER* tracer = TRACER::instanceImp(); @@ -350,7 +295,7 @@ template inline int GenericTracer::inject( - GenericTextWriter* const carrier, const SpanContext& context) + CARRIER* const carrier, const SpanContext& context) { const CONTEXT& contextImp = static_cast(context); const TRACER* tracer = TRACER::instanceImp(); @@ -358,67 +303,6 @@ GenericTracer::inject( return tracer->injectImp(carrier, contextImp); } -template -template -inline int -GenericTracer::inject( - GenericBinaryWriter* const carrier, - const SpanContext& context) -{ - const CONTEXT& contextImp = static_cast(context); - const TRACER* const tracer = TRACER::instanceImp(); - - return tracer->injectImp(carrier, contextImp); -} - -template -template -inline int -GenericTracer::inject( - GenericWriter* const carrier, - const SpanContext& context) -{ - const CONTEXT& contextImp = static_cast(context); - const TRACER* const tracer = TRACER::instanceImp(); - return tracer->injectImp(carrier, contextImp); -} - -template -template -inline const typename GenericTracer:: - SpanContext* - GenericTracer::extract( - const GenericTextReader& carrier) -{ - return TRACER::instanceImp()->extractImp(carrier); -} - -template -template -inline const typename GenericTracer:: - SpanContext* - GenericTracer::extract( - const GenericBinaryReader& carrier) -{ - return TRACER::instanceImp()->extractImp(carrier); -} - template inline const typename GenericTracer:: SpanContext* GenericTracer::extract( - const GenericReader& carrier) + const CARRIER& carrier) { return TRACER::instanceImp()->extractImp(carrier); } diff --git a/test/carriers.h b/test/carriers.h index 67b2b8f..624ea82 100644 --- a/test/carriers.h +++ b/test/carriers.h @@ -58,7 +58,7 @@ struct TestBinaryReader : public GenericBinaryReader { int32_t m_raw; }; -struct TestWriter : public GenericWriter +struct TestWriter : public GenericWriter { int injectImp(const TestContextImpl& context) { @@ -69,7 +69,7 @@ struct TestWriter : public GenericWriter std::multimap carrier; }; -struct TestReader : public GenericReader +struct TestReader : public GenericReader { int extractImp(TestContextImpl * const context) const { @@ -84,7 +84,7 @@ typedef GenericTextWriter TextWriter; typedef GenericTextReader TextReader; typedef GenericBinaryWriter BinaryWriter; typedef GenericBinaryReader BinaryReader; -typedef GenericWriter ExplicitWriter; -typedef GenericReader ExplicitReader; +typedef GenericWriter ExplicitWriter; +typedef GenericReader ExplicitReader; #endif diff --git a/test/carriers.t.cc b/test/carriers.t.cc index f79e78f..5d812bd 100644 --- a/test/carriers.t.cc +++ b/test/carriers.t.cc @@ -17,13 +17,13 @@ TEST(Carriers, TextMapWriter) ASSERT_EQ(3u, imp.pairs.size()); - ASSERT_EQ(imp.pairs[0].m_name, "animal"); + ASSERT_EQ(imp.pairs[0].m_key, "animal"); ASSERT_EQ(imp.pairs[0].m_value, "dog"); - ASSERT_EQ(imp.pairs[1].m_name, "fruit"); + ASSERT_EQ(imp.pairs[1].m_key, "fruit"); ASSERT_EQ(imp.pairs[1].m_value, "apple"); - ASSERT_EQ(imp.pairs[2].m_name, "veggie"); + ASSERT_EQ(imp.pairs[2].m_key, "veggie"); ASSERT_EQ(imp.pairs[2].m_value, "carrot"); } @@ -46,13 +46,13 @@ TEST(Carriers, TextMapReader) ASSERT_EQ(3u, o.size()); - ASSERT_EQ(o[0].m_name, "animal"); + ASSERT_EQ(o[0].m_key, "animal"); ASSERT_EQ(o[0].m_value, "dog"); - ASSERT_EQ(o[1].m_name, "fruit"); + ASSERT_EQ(o[1].m_key, "fruit"); ASSERT_EQ(o[1].m_value, "apple"); - ASSERT_EQ(o[2].m_name, "veggie"); + ASSERT_EQ(o[2].m_key, "veggie"); ASSERT_EQ(o[2].m_value, "carrot"); } diff --git a/test/noop.t.cc b/test/noop.t.cc index 57dc25d..3ac62a3 100644 --- a/test/noop.t.cc +++ b/test/noop.t.cc @@ -168,12 +168,9 @@ TEST_F(NoopTracerEnv, ExtractBinary) GlobalTracer::cleanup(context); } -struct NoopWriter: public GenericWriter +struct NoopWriter: public GenericWriter { - int injectImp(const NoopContext&) - { - return 0; - } + // won't ever be called }; TEST_F(NoopTracerEnv, InjectExplicit) @@ -191,12 +188,9 @@ TEST_F(NoopTracerEnv, InjectExplicit) GlobalTracer::cleanup(context); } -struct NoopReader : public GenericReader +struct NoopReader : public GenericReader { - int injectImp(const NoopContext&) - { - return 0; - } + // won't ever be called }; TEST_F(NoopTracerEnv, ExtractExplicit) diff --git a/test/tracer.h b/test/tracer.h index ff67186..9dadc93 100644 --- a/test/tracer.h +++ b/test/tracer.h @@ -130,8 +130,8 @@ class TestTracerImpl : public GenericTracer int - injectImp(GenericWriter* const carrier, - const TestContextImpl& context) const + injectImp(GenericWriter* const carrier, + const TestContextImpl& context) const { return carrier->inject(context); } @@ -154,7 +154,7 @@ class TestTracerImpl : public GenericTracerbaggageMap().insert( - TestBaggageContainer::value_type(it->m_name, it->m_value)); + TestBaggageContainer::value_type(it->m_key, it->m_value)); } return imp; } @@ -185,10 +185,8 @@ class TestTracerImpl : public GenericTracer TestContextImpl* - extractImp(const GenericReader& carrier) + extractImp(const GenericReader& carrier) { - // Should use a guard here and release it, iff, carrier has - // no errors. TestContextImpl* imp = new TestContextImpl; if (int rc = carrier.extract(imp)) { diff --git a/test/tracer.t.cc b/test/tracer.t.cc index 1a30a47..9ede4f1 100644 --- a/test/tracer.t.cc +++ b/test/tracer.t.cc @@ -77,8 +77,8 @@ TEST_F(TracerEnv, InjectText) ASSERT_EQ(0, rc); ASSERT_EQ(2u, writer.pairs.size()); - ASSERT_EQ(writer.pairs[0].m_name, "animal"); - ASSERT_EQ(writer.pairs[1].m_name, "animal"); + ASSERT_EQ(writer.pairs[0].m_key, "animal"); + ASSERT_EQ(writer.pairs[1].m_key, "animal"); ASSERT_TRUE(writer.pairs[0].m_value == "cat" || writer.pairs[0].m_value == "tiger"); ASSERT_TRUE(writer.pairs[1].m_value == "cat" || writer.pairs[1].m_value == "tiger"); @@ -101,8 +101,8 @@ TEST_F(TracerEnv, SpanInjectText) ASSERT_EQ(0, rc); ASSERT_EQ(2u, writer.pairs.size()); - ASSERT_EQ(writer.pairs[0].m_name, "animal"); - ASSERT_EQ(writer.pairs[1].m_name, "animal"); + ASSERT_EQ(writer.pairs[0].m_key, "animal"); + ASSERT_EQ(writer.pairs[1].m_key, "animal"); ASSERT_TRUE(writer.pairs[0].m_value == "cat" || writer.pairs[0].m_value == "tiger"); ASSERT_TRUE(writer.pairs[1].m_value == "cat" || writer.pairs[1].m_value == "tiger"); From 0c8a1a9441169db942f57fd289c0414b78bfca73 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Tue, 17 Jan 2017 08:21:07 -0500 Subject: [PATCH 44/48] Reduce noop inject/extract code --- opentracing/noop.h | 67 +++++----------------------------------------- 1 file changed, 6 insertions(+), 61 deletions(-) diff --git a/opentracing/noop.h b/opentracing/noop.h index 8dbbc23..ab22f10 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -157,29 +157,11 @@ class NoopTracer : public GenericTracer - int injectImp(CARRIER* const carrier, const NoopSpan& span) const; - - template - int injectImp(GenericTextWriter* const carrier, - const NoopContext& context) const; - - template - int injectImp(GenericBinaryWriter* const carrier, - const NoopContext& context) const; - - template - int injectImp(GenericWriter* const carrier, - const NoopContext& context) const; - - template - NoopContext* extractImp(const GenericTextReader& carrier); - - template - NoopContext* extractImp(const GenericBinaryReader& carrier); + template + int injectImp(CARRIER* const carrier, const T&) const; template - NoopContext* extractImp(const GenericReader& carrier); + NoopContext* extractImp(const CARRIER& carrier); void cleanupImp(const NoopContext* const sp); @@ -386,53 +368,16 @@ NoopTracer::cleanupImp(const Span* const) { } -template -inline int -NoopTracer::injectImp(CARRIER* const, const NoopSpan&) const -{ - return 0; -} - -template -inline int -NoopTracer::injectImp(GenericTextWriter* const, - const NoopContext&) const -{ - return 0; -} - -template +template inline int -NoopTracer::injectImp(GenericBinaryWriter* const, - const NoopContext&) const +NoopTracer::injectImp(CARRIER* const, const T&) const { return 0; } -template -inline int -NoopTracer::injectImp(GenericWriter* const, const NoopContext&) const -{ - return 0; -} - -template -inline NoopContext* -NoopTracer::extractImp(const GenericTextReader&) -{ - return &m_span.m_context; -} - -template -inline NoopContext* -NoopTracer::extractImp(const GenericBinaryReader&) -{ - return &m_span.m_context; -} - template inline NoopContext* -NoopTracer::extractImp(const GenericReader&) +NoopTracer::extractImp(const CARRIER&) { return &m_span.m_context; } From eb428ccc3a40ee62083d56df78cdfb7c4ef542f0 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Wed, 18 Jan 2017 10:04:30 -0500 Subject: [PATCH 45/48] Documentation update --- opentracing/noop.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/opentracing/noop.h b/opentracing/noop.h index ab22f10..07f6175 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -138,7 +138,10 @@ class NoopSpan : public GenericSpan { // // Although clients can 'start()' spans or 'makeSpanOptions()', there are // no allocations made. Clients should call 'finish()'/'cleanup()', however, -// this implementation has no side effects of them doing so. +// this implementation has no side effects of them doing so. Inject/extract +// can be called, but there are no side effects; the noop tracer will +// never add itself to carrier objects, but will always return a valid +// pointer to a context. class NoopTracer : public GenericTracer Date: Fri, 20 Jan 2017 21:22:02 -0500 Subject: [PATCH 46/48] Remove static from generictracer interface, use const consistently --- opentracing/baggage.h | 29 ++++---- opentracing/carriers.h | 61 ++++++++-------- opentracing/constants.h | 31 ++++---- opentracing/noop.h | 77 ++++++++++---------- opentracing/span.h | 45 ++++++------ opentracing/spancontext.h | 30 ++++---- opentracing/spanoptions.h | 25 ++++--- opentracing/stringref.h | 21 +++--- opentracing/tracer.h | 145 +++++++++++++++++++------------------- test/carriers.h | 18 ++--- test/noop.t.cc | 82 +++++++++++---------- test/span.h | 5 +- test/spancontext.h | 5 +- test/tracer.h | 61 +++++++++------- test/tracer.t.cc | 72 ++++++++++--------- 15 files changed, 364 insertions(+), 343 deletions(-) diff --git a/opentracing/baggage.h b/opentracing/baggage.h index c95853e..8d34a11 100644 --- a/opentracing/baggage.h +++ b/opentracing/baggage.h @@ -262,46 +262,45 @@ inline const BaggageRef* BaggageRef::operator->() const // ------------------------ template -inline BaggageIteratorImp::BaggageIteratorImp(const iterator& iter) +BaggageIteratorImp::BaggageIteratorImp(const iterator& iter) : d_iterator(iter), d_handler() { } template -inline BaggageIteratorImp::BaggageIteratorImp( - const const_iterator& iter) +BaggageIteratorImp::BaggageIteratorImp(const const_iterator& iter) : d_iterator(iter), d_handler() { } template -inline BaggageRef BaggageIteratorImp::operator*() const +BaggageRef BaggageIteratorImp::operator*() const { return d_handler.ref(d_iterator); } template -inline BaggageRef BaggageIteratorImp::operator->() const +BaggageRef BaggageIteratorImp::operator->() const { return d_handler.ref(d_iterator); } template -inline Baggage +Baggage BaggageIteratorImp::copy() const { return d_handler.copy(d_iterator); } template -inline BaggageRef +BaggageRef BaggageIteratorImp::ref() const { return d_handler.ref(d_iterator); } template -inline BaggageIteratorImp BaggageIteratorImp::operator++(int) +BaggageIteratorImp BaggageIteratorImp::operator++(int) { BaggageIteratorImp tmp(*this); ++d_iterator; @@ -309,14 +308,14 @@ inline BaggageIteratorImp BaggageIteratorImp::operator++(int) } template -inline BaggageIteratorImp& BaggageIteratorImp::operator++() +BaggageIteratorImp& BaggageIteratorImp::operator++() { ++d_iterator; return *this; } template -inline bool +bool BaggageIteratorImp::operator==( const BaggageIteratorImp& other) const { @@ -324,7 +323,7 @@ BaggageIteratorImp::operator==( } template -inline bool +bool BaggageIteratorImp::operator!=( const BaggageIteratorImp& other) const { @@ -336,21 +335,21 @@ BaggageIteratorImp::operator!=( // --------------------- template -inline BaggageRangeImp::BaggageRangeImp(const BaggageIterator& begin, - const BaggageIterator& end) +BaggageRangeImp::BaggageRangeImp(const BaggageIterator& begin, + const BaggageIterator& end) : m_begin(begin), m_end(end) { } template -inline typename BaggageRangeImp::BaggageIterator +typename BaggageRangeImp::BaggageIterator BaggageRangeImp::begin() const { return m_begin; } template -inline typename BaggageRangeImp::BaggageIterator +typename BaggageRangeImp::BaggageIterator BaggageRangeImp::end() const { return m_end; diff --git a/opentracing/carriers.h b/opentracing/carriers.h index ab0e7a5..fbcb1a8 100644 --- a/opentracing/carriers.h +++ b/opentracing/carriers.h @@ -89,7 +89,7 @@ class GenericTextWriter { // // class BinaryWriter : GenericBinaryWriter{ // public: -// int injectImp(const void* const buf, const size_t len); +// int injectImp(const void* buf, const size_t len); // }; // // Implementations are responsible for passing the blob along with a carrier @@ -99,7 +99,7 @@ class GenericTextWriter { template class GenericBinaryWriter { public: - int inject(const void * const buf, const size_t len); + int inject(const void* buf, const size_t len); // Inject the binary representation of a span context into this carrier. protected: @@ -168,7 +168,7 @@ class GenericWriter { template class GenericTextReader { public: - int extract(std::vector* const textmap) const; + int extract(std::vector* textmap) const; // Extract the supplied 'Textmap' from this carrier. protected: @@ -186,7 +186,7 @@ class GenericTextReader { // // class BinaryReader : GenericBinaryReader{ // public: -// int extractImp(std::vector *const buf) const; +// int extractImp(std::vector *buf) const; // }; // // When constructed, they should hold onto any references they may need to @@ -195,7 +195,7 @@ class GenericTextReader { template class GenericBinaryReader { public: - int extract(std::vector* const buffer) const; + int extract(std::vector* buffer) const; // Load the binary representation of a span context into 'buffer'. // Return 0 upon success and a non-zero value otherwise. @@ -220,14 +220,14 @@ class GenericBinaryReader { // class ExplicitReader: GenericReader // { // public: -// int extractImp(ImplType* const) const; +// int extractImp(ImplType* ) const; // }; template class GenericReader { public: template - int extract(T* const impl) const; + int extract(T* impl) const; // Extract the 'impl' object directly from this carrier. protected: @@ -253,19 +253,19 @@ inline TextMapPair::TextMapPair(const StringRef& name, const StringRef& value) // ----------------------- template -inline int +int GenericTextWriter::inject(const std::vector& textmap) { return static_cast(this)->injectImp(textmap); } template -inline GenericTextWriter::GenericTextWriter() +GenericTextWriter::GenericTextWriter() { } template -inline GenericTextWriter::GenericTextWriter(const GenericTextWriter&) +GenericTextWriter::GenericTextWriter(const GenericTextWriter&) { } @@ -274,19 +274,19 @@ inline GenericTextWriter::GenericTextWriter(const GenericTextWriter&) // ------------------------- template -inline int -GenericBinaryWriter::inject(const void* const buf, const size_t len) +int +GenericBinaryWriter::inject(const void* buf, const size_t len) { return static_cast(this)->injectImp(buf, len); } template -inline GenericBinaryWriter::GenericBinaryWriter() +GenericBinaryWriter::GenericBinaryWriter() { } template -inline GenericBinaryWriter::GenericBinaryWriter( +GenericBinaryWriter::GenericBinaryWriter( const GenericBinaryWriter&) { } @@ -297,19 +297,19 @@ inline GenericBinaryWriter::GenericBinaryWriter( template template -inline int +int GenericWriter::inject(const T& impl) { return static_cast(this)->injectImp(impl); } template -inline GenericWriter::GenericWriter() +GenericWriter::GenericWriter() { } template -inline GenericWriter::GenericWriter(const GenericWriter&) +GenericWriter::GenericWriter(const GenericWriter&) { } @@ -318,20 +318,19 @@ inline GenericWriter::GenericWriter(const GenericWriter&) // ----------------------- template -inline int -GenericTextReader::extract( - std::vector* const textmap) const +int +GenericTextReader::extract(std::vector* textmap) const { return static_cast(this)->extractImp(textmap); } template -inline GenericTextReader::GenericTextReader() +GenericTextReader::GenericTextReader() { } template -inline GenericTextReader::GenericTextReader(const GenericTextReader&) +GenericTextReader::GenericTextReader(const GenericTextReader&) { } @@ -340,19 +339,19 @@ inline GenericTextReader::GenericTextReader(const GenericTextReader&) // ------------------------- template -inline int -GenericBinaryReader::extract(std::vector* const buf) const +int +GenericBinaryReader::extract(std::vector* buf) const { return static_cast(this)->extractImp(buf); } template -inline GenericBinaryReader::GenericBinaryReader() +GenericBinaryReader::GenericBinaryReader() { } template -inline GenericBinaryReader::GenericBinaryReader( +GenericBinaryReader::GenericBinaryReader( const GenericBinaryReader&) { } @@ -362,20 +361,20 @@ inline GenericBinaryReader::GenericBinaryReader( // ------------------- template -template -inline int -GenericReader::extract(T* const impl) const +template +int +GenericReader::extract(T* impl) const { return static_cast(this)->extractImp(impl); } template -inline GenericReader::GenericReader() +GenericReader::GenericReader() { } template -inline GenericReader::GenericReader(const GenericReader&) +GenericReader::GenericReader(const GenericReader&) { } diff --git a/opentracing/constants.h b/opentracing/constants.h index 0fc1de8..b9cb082 100644 --- a/opentracing/constants.h +++ b/opentracing/constants.h @@ -4,25 +4,28 @@ // =========== // constants.h // =========== -// This header provides a set of macros for the "standard" OpenTracing tag and log fields. -// See https://github.com/opentracing/specification/blob/master/data_conventions.yaml for +// This header provides a set of macros for the "standard" OpenTracing tag and +// log fields. +// See +// https://github.com/opentracing/specification/blob/master/data_conventions.yaml +// for // a description of each value, and how it should be used. -#define OPENTRACING_TAG_ERROR "error" -#define OPENTRACING_TAG_COMPONENT "component" +#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_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_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" +#define OPENTRACING_LOG_EVENT "event" #endif diff --git a/opentracing/noop.h b/opentracing/noop.h index 07f6175..60128cc 100644 --- a/opentracing/noop.h +++ b/opentracing/noop.h @@ -74,8 +74,8 @@ class NoopContext : public GenericSpanContext { BaggageIterator baggageBeginImp() const; BaggageIterator baggageEndImp() const; - int getBaggageImp(const StringRef&, std::string* const) const; - int getBaggageImp(const StringRef&, std::vector* const) const; + int getBaggageImp(const StringRef&, std::string*) const; + int getBaggageImp(const StringRef&, std::vector*) const; }; // ================= @@ -92,7 +92,7 @@ class NoopOptions int setStartTimeImp(const uint64_t); int setReferenceImp(const SpanReferenceType::Value, const NoopContext&); - template + template int setTagImp(const StringRef&, const T&); }; @@ -107,13 +107,13 @@ class NoopOptions class NoopSpan : public GenericSpan { public: - const NoopContext * contextImp() const; + const NoopContext* contextImp() const; int setOperationImp(const StringRef&); int setBaggageImp(const StringRef&, const StringRef&); - int getBaggageImp(const StringRef&, std::string* const) const; - int getBaggageImp(const StringRef&, std::vector* const) const; + int getBaggageImp(const StringRef&, std::string*) const; + int getBaggageImp(const StringRef&, std::vector*) const; int finishImp(); int finishImp(const uint64_t); @@ -149,27 +149,27 @@ class NoopTracer : public GenericTracer { public: - static void installImp(NoopTracer *const); - static NoopTracer * instanceImp(); - static void uninstallImp(); + static void installImp(NoopTracer*); + static void uninstallImp(); + static NoopTracer* instanceImp(); NoopOptions* makeSpanOptionsImp(); - void cleanupImp(const NoopOptions* const opts); NoopSpan* startImp(const StringRef&); NoopSpan* startImp(const NoopOptions&); - void cleanupImp(const Span* const sp); template - int injectImp(CARRIER* const carrier, const T&) const; + int injectImp(CARRIER* carrier, const T&) const; template NoopContext* extractImp(const CARRIER& carrier); - void cleanupImp(const NoopContext* const sp); + void cleanupImp(const NoopOptions*); + void cleanupImp(const Span*); + void cleanupImp(const NoopContext*); private: - static NoopTracer *s_tracer; + static NoopTracer* s_tracer; NoopOptions m_opts; NoopSpan m_span; @@ -209,14 +209,13 @@ NoopContext::baggageEndImp() const } inline int -NoopContext::getBaggageImp(const StringRef&, std::string* const) const +NoopContext::getBaggageImp(const StringRef&, std::string*) const { return 1; } inline int -NoopContext::getBaggageImp(const StringRef&, - std::vector* const) const +NoopContext::getBaggageImp(const StringRef&, std::vector*) const { return 1; } @@ -243,8 +242,8 @@ NoopOptions::setReferenceImp(const SpanReferenceType::Value, const NoopContext&) return 0; } -template -inline int +template +int NoopOptions::setTagImp(const StringRef&, const T&) { return 0; @@ -277,13 +276,13 @@ NoopSpan::setBaggageImp(const StringRef&, const StringRef&) } inline int -NoopSpan::getBaggageImp(const StringRef&, std::string* const) const +NoopSpan::getBaggageImp(const StringRef&, std::string*) const { return 1; } inline int -NoopSpan::getBaggageImp(const StringRef&, std::vector* const) const +NoopSpan::getBaggageImp(const StringRef&, std::vector*) const { return 1; } @@ -301,21 +300,21 @@ NoopSpan::finishImp(const uint64_t) } template -inline int +int NoopSpan::tagImp(const StringRef&, const T&) { return 0; } template -inline int +int NoopSpan::logImp(const StringRef&, const T&) { return 0; } template -inline int +int NoopSpan::logImp(const StringRef&, const T&, const uint64_t) { return 0; @@ -326,7 +325,7 @@ NoopSpan::logImp(const StringRef&, const T&, const uint64_t) // ---------------- inline void -NoopTracer::installImp(NoopTracer* const tracer) +NoopTracer::installImp(NoopTracer* tracer) { s_tracer = tracer; } @@ -349,11 +348,6 @@ NoopTracer::makeSpanOptionsImp() return &m_opts; } -inline void -NoopTracer::cleanupImp(const NoopOptions* const) -{ -} - inline NoopSpan* NoopTracer::startImp(const StringRef&) { @@ -366,27 +360,32 @@ NoopTracer::startImp(const NoopOptions&) return &m_span; } -inline void -NoopTracer::cleanupImp(const Span* const) -{ -} - template -inline int -NoopTracer::injectImp(CARRIER* const, const T&) const +int +NoopTracer::injectImp(CARRIER*, const T&) const { return 0; } template -inline NoopContext* +NoopContext* NoopTracer::extractImp(const CARRIER&) { return &m_span.m_context; } inline void -NoopTracer::cleanupImp(const NoopContext* const) +NoopTracer::cleanupImp(const NoopOptions*) +{ +} + +inline void +NoopTracer::cleanupImp(const Span*) +{ +} + +inline void +NoopTracer::cleanupImp(const NoopContext*) { } diff --git a/opentracing/span.h b/opentracing/span.h index d9b9a29..54acfb0 100644 --- a/opentracing/span.h +++ b/opentracing/span.h @@ -32,11 +32,11 @@ namespace opentracing { // public: // const ContextImpl * contextImp() const; // -// int setOperationImp(const StringRef& operation); +// int setOperationImp(const StringRef&); // int setBaggageImp(const StringRef&, const StringRef&); // -// int getBaggageImp(const StringRef&, std::string* const) const; -// int getBaggageImp(const StringRef&, std::vector* const) const; +// int getBaggageImp(const StringRef&, std::string*) const; +// int getBaggageImp(const StringRef&, std::vector*) const; // // int finishImp(); // int finishImp(const uint64_t); @@ -60,24 +60,25 @@ class GenericSpan { public: typedef GenericSpanContext SpanContext; - const SpanContext * context() const; + const SpanContext* context() const; // Return a copy of the SpanContext associated with this span. // The context can be injected into carriers, or added as a reference to // other causally related Spans. When finished with the SpanContext, it // should be cleaned up with 'Tracer::cleanup()'. int setBaggage(const StringRef& key, const StringRef& value); - // Add the 'key:value' pair to this Span. Baggage is propagated with the Span + // Add the 'key:value' pair to this Span. Baggage is propagated with the + // Span // in-band, throughout the lifetime of a Trace. Return 0 upon success // and a non-zero value otherwise. - int getBaggage(const StringRef &key, std::string *const baggage) const; + int getBaggage(const StringRef& key, std::string* baggage) const; // Load a single 'baggage' value associated with 'key'. Returns 0 if there // is only one value associated with 'key' and that value was loaded // successfully. Return a non-zero value otherwise. - int getBaggage(const StringRef & key, - std::vector *const baggage) const; + int getBaggage(const StringRef& key, + std::vector* baggage) const; // Load the 'baggage' associated with 'key'. Returns 0 if the // baggage is loaded successfully, and a non-zero value otherwise. @@ -133,31 +134,31 @@ class GenericSpan { // ----------------- template -inline GenericSpan::GenericSpan() +GenericSpan::GenericSpan() { } template -inline GenericSpan::GenericSpan(const GenericSpan&) +GenericSpan::GenericSpan(const GenericSpan&) { } template -inline const typename GenericSpan::SpanContext* +const typename GenericSpan::SpanContext* GenericSpan::context() const { return static_cast(this)->contextImp(); } template -inline int +int GenericSpan::setOperation(const StringRef& operation) { return static_cast(this)->setOperationImp(operation); } template -inline int +int GenericSpan::setBaggage(const StringRef& key, const StringRef& value) { @@ -165,30 +166,30 @@ GenericSpan::setBaggage(const StringRef& key, } template -inline int +int GenericSpan::getBaggage(const StringRef& key, - std::string* const value) const + std::string* value) const { return static_cast(this)->getBaggageImp(key, value); } template -inline int +int GenericSpan::getBaggage( - const StringRef& key, std::vector* const value) const + const StringRef& key, std::vector* value) const { return static_cast(this)->getBaggageImp(key, value); } template -inline int +int GenericSpan::finish() { return static_cast(this)->finishImp(); } template -inline int +int GenericSpan::finish(const uint64_t tsp) { return static_cast(this)->finishImp(tsp); @@ -196,7 +197,7 @@ GenericSpan::finish(const uint64_t tsp) template template -inline int +int GenericSpan::tag(const StringRef& key, const T& val) { return static_cast(this)->tagImp(key, val); @@ -204,7 +205,7 @@ GenericSpan::tag(const StringRef& key, const T& val) template template -inline int +int GenericSpan::log(const StringRef& key, const T& val) { return static_cast(this)->logImp(key, val); @@ -212,7 +213,7 @@ GenericSpan::log(const StringRef& key, const T& val) template template -inline int +int GenericSpan::log(const StringRef& key, const T& val, const uint64_t tsp) diff --git a/opentracing/spancontext.h b/opentracing/spancontext.h index 74d5ca5..15e1b4e 100644 --- a/opentracing/spancontext.h +++ b/opentracing/spancontext.h @@ -28,8 +28,8 @@ namespace opentracing { // typename Adapter::const_iterator baggageBeginImp() const; // typename Adapter::const_iterator baggageEndImp() const; // -// int getBaggageImp(const StringRef&, std::string* const) const; -// int getBaggageImp(const StringRef&, std::vector* const) const; +// int getBaggageImp(const StringRef&, std::string*) const; +// int getBaggageImp(const StringRef&, std::vector*) const; // }; // // Implementations may choose how they implement storage of Baggage, but the @@ -57,13 +57,13 @@ class GenericSpanContext { // Return a structure containing the range of iterators: // [baggageBegin, baggageEnd). The object supports range-based for loops. - int getBaggage(const StringRef &key, std::string *const baggage) const; + int getBaggage(const StringRef &key, std::string *baggage) const; // Load a single 'baggage' value associated with 'key'. Returns 0 if there // is only one value associated with 'key' and that value was loaded // successfully. Return a non-zero value otherwise. - int getBaggage(const StringRef & key, - std::vector *const baggage) const; + int getBaggage(const StringRef & key, + std::vector *baggage) const; // Load the 'baggage' associated with 'key'. Returns 0 if the // baggage is loaded successfully, and a non-zero value otherwise. @@ -78,18 +78,18 @@ class GenericSpanContext { // ------------------------ template -inline GenericSpanContext::GenericSpanContext() +GenericSpanContext::GenericSpanContext() { } template -inline GenericSpanContext::GenericSpanContext( +GenericSpanContext::GenericSpanContext( const GenericSpanContext &) { } template -inline typename GenericSpanContext::BaggageIterator +typename GenericSpanContext::BaggageIterator GenericSpanContext::baggageBegin() const { return BaggageIterator( @@ -97,32 +97,32 @@ GenericSpanContext::baggageBegin() const } template -inline typename GenericSpanContext::BaggageIterator +typename GenericSpanContext::BaggageIterator GenericSpanContext::baggageEnd() const { return BaggageIterator(static_cast(this)->baggageEndImp()); } template -inline typename GenericSpanContext::BaggageRange +typename GenericSpanContext::BaggageRange GenericSpanContext::baggageRange() const { return BaggageRange(baggageBegin(), baggageEnd()); } template -inline int -GenericSpanContext::getBaggage( - const StringRef &key, std::string *const baggage) const +int +GenericSpanContext::getBaggage(const StringRef &key, + std::string *baggage) const { return static_cast(this)->getBaggageImp(key, baggage); } template -inline int +int GenericSpanContext::getBaggage( - const StringRef &key, std::vector *const baggage) const + const StringRef &key, std::vector *baggage) const { return static_cast(this)->getBaggageImp(key, baggage); } diff --git a/opentracing/spanoptions.h b/opentracing/spanoptions.h index 3a06030..fd8ada5 100644 --- a/opentracing/spanoptions.h +++ b/opentracing/spanoptions.h @@ -15,15 +15,18 @@ namespace opentracing { // ======================= // class SpanReferenceType // ======================= -// Spans may reference zero or more other SpanContexts that are causally related. +// 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, +// * 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 +// * 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. @@ -58,12 +61,12 @@ class GenericSpanOptions { // non-zero value otherwise. int setReference(const SpanReferenceType::Value relationship, - const SpanContext& context); + const SpanContext& context); // A new Span created with these options would have a 'relationship' // referenced added for 'context'. Return 0 upon success and a non-zero // value otherwise. - template + template int setTag(const StringRef& key, const T& value); // A new Span created with these options would have this 'key:value' tag. // Return 0 upon success and a non-zero value otherwise. @@ -74,21 +77,21 @@ class GenericSpanOptions { // ------------------------ template -inline int +int GenericSpanOptions::setOperation(const StringRef& op) { return static_cast(this)->setOperationImp(op); } template -inline int +int GenericSpanOptions::setStartTime(const uint64_t tsp) { return static_cast(this)->setStartTimeImp(tsp); } template -inline int +int GenericSpanOptions::setReference( const SpanReferenceType::Value rel, const SpanContext& context) { @@ -98,9 +101,9 @@ GenericSpanOptions::setReference( template template -inline int -GenericSpanOptions::setTag( - const StringRef& key, const T& value) +int +GenericSpanOptions::setTag(const StringRef& key, + const T& value) { return static_cast(this)->setTagImp(key, value); } diff --git a/opentracing/stringref.h b/opentracing/stringref.h index c125a7b..1fe39ac 100644 --- a/opentracing/stringref.h +++ b/opentracing/stringref.h @@ -33,7 +33,7 @@ namespace opentracing { // past that of the StringRef. For this reason, it is not in general safe to // store a StringRef. -class StringRef{ +class StringRef { public: StringRef(); // Construct an empty StringRef @@ -58,13 +58,13 @@ class StringRef{ void reset(const char (&str)[N]); // Reset the string reference given a const character array - void reset(const char* const str); + 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* const str, const size_t length); + 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; @@ -109,12 +109,11 @@ inline StringRef::StringRef() : m_data(0), m_length(0) } template -inline StringRef::StringRef(const char (&str)[N]) -: m_data(str), m_length(N - 1) +StringRef::StringRef(const char (&str)[N]) : m_data(str), m_length(N - 1) { } -inline StringRef::StringRef(const char* const str) +inline StringRef::StringRef(const char* str) : m_data(str), m_length(std::strlen(str)) { } @@ -135,14 +134,14 @@ inline StringRef::operator const char*() const } inline void -StringRef::reset(const char* const str, const size_t length) +StringRef::reset(const char* str, const size_t length) { m_data = str; m_length = length; } template -inline void +void StringRef::reset(const char (&str)[N]) { m_data = str; @@ -150,7 +149,7 @@ StringRef::reset(const char (&str)[N]) } inline void -StringRef::reset(const char* const str) +StringRef::reset(const char* str) { m_data = str; m_length = std::strlen(str); @@ -177,8 +176,8 @@ StringRef::length() const } // namespace opentracing -inline -std::ostream& operator<<(std::ostream& os, const opentracing::StringRef& ref) +inline std::ostream& +operator<<(std::ostream& os, const opentracing::StringRef& ref) { return os.write(ref.data(), ref.length()); } diff --git a/opentracing/tracer.h b/opentracing/tracer.h index 1b96391..e514196 100644 --- a/opentracing/tracer.h +++ b/opentracing/tracer.h @@ -44,26 +44,26 @@ namespace opentracing { // { // public: // static void installImp(TracerImp*); -// static TracerImp * instanceImp(); // static void uninstallImp(); +// static TracerImp * instanceImp(); // // Options * makeSpanOptionsImp(); -// void cleanupImp(const Options * const opts); // // SpanImp * start(const StringRef& op); // SpanImp * start(const OptionsImp& opts); -// void cleanupImp(const SpanImp * const sp); // // template -// int injectImp(CARRIER*const carrier, const SpanImp& context) const; +// int injectImp(CARRIER*, const SpanImp& context) const; // // template -// int injectImp(CARRIER*const carrier, const ContextImp& context) const; +// int injectImp(CARRIER*, const ContextImp& context) const; // // template // const ContextImp* extractImp(const CARRIER& carrier); // -// void cleanupImp(const ContextImp * const); +// void cleanupImp(const Options*); +// void cleanupImp(const SpanImp*); +// void cleanupImp(const ContextImp*); // }; template - static int inject(CARRIER* const carrier, const Span& span); + int inject(CARRIER* carrier, const Span& span) const; // Inject the supplied 'span' into the supplied 'carrier' writer. This // method should expect one of the 'Writer' carriers defined in // carriers.h. Returns 0 upon success and a non-zero value otherwise. template - static int inject(CARRIER* const carrier, const SpanContext& context); + int inject(CARRIER* carrier, const SpanContext& context) const; // Inject the supplied 'span' into the supplied 'carrier' writer. This // method should expect one of the 'Writer' carriers defined in // carriers.h. Returns 0 upon success and a non-zero value otherwise. template - static const SpanContext* extract(const CARRIER& carrier); + const SpanContext* extract(const CARRIER& carrier); // Extract the read-only supplied 'context' from the text map reader // 'carrier' upon success, and NULL otherwise. Should expect one // of the 'Reader' carriers defined in carriers.h. - static void cleanup(const SpanContext* const sp); + void cleanup(const SpanOptions* opts); + // All SpanOptions pointers returned by the Tracer via 'makeSpanOptions()' + // must be passed back to the Tracer when client's are done with them via + // 'cleanup()'. + + void cleanup(const Span* sp); + // All Span pointers returned by the Tracer via 'start()' must be passed + // back to the Tracer when clients are done with them via 'cleanup()'. + + void cleanup(const SpanContext* sp); // All SpanContext pointers created by the Tracer through 'extract()' should // be passed back to the Tracer when client's are done with them via // 'cleanup()'. @@ -164,11 +164,11 @@ template -inline void +void GenericTracer::install( - GenericTracer* const tracer) + GenericTracer* tracer) { - TRACER * const tracerImp = static_cast(tracer); + TRACER* tracerImp = static_cast(tracer); TRACER::installImp(tracerImp); } @@ -177,7 +177,7 @@ template -inline void +void GenericTracer::uninstall() { return TRACER::uninstallImp(); @@ -188,7 +188,7 @@ template -inline GenericTracer* +GenericTracer* GenericTracer::instance() { return TRACER::instanceImp(); @@ -199,7 +199,7 @@ template -inline GenericTracer::GenericTracer() +GenericTracer::GenericTracer() { } @@ -208,7 +208,7 @@ template -inline GenericTracer::GenericTracer( +GenericTracer::GenericTracer( const GenericTracer&) { } @@ -218,10 +218,10 @@ template -inline typename GenericTracer::SpanOptions* +typename GenericTracer::SpanOptions* GenericTracer::makeSpanOptions() { - return TRACER::instanceImp()->makeSpanOptionsImp(); + return static_cast(this)->makeSpanOptionsImp(); } template -inline void -GenericTracer::cleanup( - SpanOptions* const opts) +typename GenericTracer::Span* +GenericTracer::start( + const StringRef& op) { - OPTIONS* const optsImp = static_cast(opts); - return TRACER::instanceImp()->cleanupImp(optsImp); + return static_cast(this)->startImp(op); } template -inline typename GenericTracer::Span* -GenericTracer::start(const StringRef& op) +typename GenericTracer::Span* +GenericTracer::start( + const SpanOptions& opts) { - return TRACER::instanceImp()->startImp(op); + const OPTIONS& optsImp = static_cast(opts); + return static_cast(this)->startImp(optsImp); } template -inline typename GenericTracer::Span* - GenericTracer::start(const SpanOptions& opts) +template +int +GenericTracer::inject( + CARRIER* carrier, const Span& span) const { - const OPTIONS& optsImp = static_cast(opts); - return TRACER::instanceImp()->startImp(optsImp); + const SPAN& spanImp = static_cast(span); + const TRACER* tracer = static_cast(this); + return tracer->injectImp(carrier, spanImp); } template -inline void -GenericTracer::cleanup(Span* const sp) +template +int +GenericTracer::inject( + CARRIER* carrier, const SpanContext& context) const { - SPAN* const spanImp = static_cast(sp); - return TRACER::instanceImp()->cleanupImp(spanImp); + const CONTEXT& contextImp = static_cast(context); + const TRACER* tracer = static_cast(this); + return tracer->injectImp(carrier, contextImp); } template template -inline int -GenericTracer::inject( - CARRIER* const carrier, const Span& span) +const typename GenericTracer:: + SpanContext* + GenericTracer::extract( + const CARRIER& carrier) { - const SPAN& spanImp = static_cast(span); - const TRACER* tracer = TRACER::instanceImp(); - return tracer->injectImp(carrier, spanImp); + return static_cast(this)->extractImp(carrier); } template -template -inline int -GenericTracer::inject( - CARRIER* const carrier, const SpanContext& context) +void +GenericTracer::cleanup( + const SpanOptions* opts) { - const CONTEXT& contextImp = static_cast(context); - const TRACER* tracer = TRACER::instanceImp(); - - return tracer->injectImp(carrier, contextImp); + const OPTIONS* optsImp = static_cast(opts); + return static_cast(this)->cleanupImp(optsImp); } template -template -inline const typename GenericTracer:: - SpanContext* - GenericTracer::extract( - const CARRIER& carrier) +void +GenericTracer::cleanup(const Span* sp) { - return TRACER::instanceImp()->extractImp(carrier); + const SPAN* spanImp = static_cast(sp); + return static_cast(this)->cleanupImp(spanImp); } template -inline void +void GenericTracer::cleanup( - const SpanContext* const spc) + const SpanContext* spc) { - const CONTEXT* const contextImp = static_cast(spc); - return TRACER::instanceImp()->cleanupImp(contextImp); + const CONTEXT* contextImp = static_cast(spc); + return static_cast(this)->cleanupImp(contextImp); } } // namespace opentracing diff --git a/test/carriers.h b/test/carriers.h index 624ea82..0136899 100644 --- a/test/carriers.h +++ b/test/carriers.h @@ -21,7 +21,7 @@ struct TestTextWriter : public GenericTextWriter { struct TestTextReader : public GenericTextReader { int - extractImp(std::vector* const textmap) const + extractImp(std::vector* textmap) const { *textmap = pairs; return 0; @@ -32,7 +32,7 @@ struct TestTextReader : public GenericTextReader { struct TestBinaryWriter : public GenericBinaryWriter { int - injectImp(const void* const buf, const size_t len) + injectImp(const void* buf, const size_t len) { if (len > sizeof(m_raw)) { @@ -48,7 +48,7 @@ struct TestBinaryWriter : public GenericBinaryWriter { struct TestBinaryReader : public GenericBinaryReader { int - extractImp(std::vector* const buf) const + extractImp(std::vector* buf) const { buf->resize(sizeof(m_raw)); std::memcpy(&(*buf)[0], &m_raw, sizeof(m_raw)); @@ -58,9 +58,9 @@ struct TestBinaryReader : public GenericBinaryReader { int32_t m_raw; }; -struct TestWriter : public GenericWriter -{ - int injectImp(const TestContextImpl& context) +struct TestWriter : public GenericWriter { + int + injectImp(const TestContextImpl& context) { carrier = context.baggageMap(); return 0; @@ -69,9 +69,9 @@ struct TestWriter : public GenericWriter std::multimap carrier; }; -struct TestReader : public GenericReader -{ - int extractImp(TestContextImpl * const context) const +struct TestReader : public GenericReader { + int + extractImp(TestContextImpl* context) const { context->baggageMap() = carrier; return 0; diff --git a/test/noop.t.cc b/test/noop.t.cc index 3ac62a3..f1502e5 100644 --- a/test/noop.t.cc +++ b/test/noop.t.cc @@ -22,6 +22,7 @@ class NoopTracerEnv : public ::testing::Test { SetUp() { GlobalTracer::install(&imp); + tracer = &imp; }; virtual void @@ -31,6 +32,7 @@ class NoopTracerEnv : public ::testing::Test { }; NoopTracer imp; + GlobalTracer * tracer; }; TEST_F(NoopTracerEnv, Intantiation){ @@ -45,7 +47,7 @@ TEST_F(NoopTracerEnv, Intantiation){ TEST_F(NoopTracerEnv, StartWithOp) { - GlobalTracer::Span* span(GlobalTracer::start("hello")); + GlobalTracer::Span* span(tracer->start("hello")); EXPECT_TRUE(span); int rc = 0; @@ -67,7 +69,7 @@ TEST_F(NoopTracerEnv, StartWithOp) rc = span->getBaggage("apple", &vals); ASSERT_NE(0, rc); - GlobalTracer::cleanup(span); + tracer->cleanup(span); } TEST_F(NoopTracerEnv, StartWithOpAndParent) @@ -78,7 +80,7 @@ TEST_F(NoopTracerEnv, StartWithOpAndParent) // test dependent on those other interfaces, I'm going to just pull // a context out of thin air to test the interface. - GlobalTracer::Span* guard(GlobalTracer::start("hello")); + GlobalTracer::Span* guard(tracer->start("hello")); EXPECT_TRUE(guard); } @@ -86,22 +88,22 @@ TEST_F(NoopTracerEnv, InjectSpan) { TestTextWriter writer; - GlobalTracer::Span* span(GlobalTracer::start("op")); + GlobalTracer::Span* span(tracer->start("op")); ASSERT_TRUE(span); span->setBaggage("animal", "tiger"); span->setBaggage("animal", "cat"); - int rc = GlobalTracer::inject(&writer, *span); + int rc = tracer->inject(&writer, *span); ASSERT_EQ(0, rc); - GlobalTracer::cleanup(span); + tracer->cleanup(span); } TEST_F(NoopTracerEnv, InjectText) { TestTextWriter writer; - GlobalTracer::Span* span(GlobalTracer::start("op")); + GlobalTracer::Span* span(tracer->start("op")); ASSERT_TRUE(span); span->setBaggage("animal", "tiger"); @@ -109,11 +111,11 @@ TEST_F(NoopTracerEnv, InjectText) const GlobalTracer::SpanContext * context = span->context(); - int rc = GlobalTracer::inject(&writer, *context); + int rc = tracer->inject(&writer, *context); ASSERT_EQ(0, rc); - GlobalTracer::cleanup(span); - GlobalTracer::cleanup(context); + tracer->cleanup(span); + tracer->cleanup(context); } @@ -125,7 +127,7 @@ TEST_F(NoopTracerEnv, ExtractText) reader.pairs.push_back(TextMapPair("fruit", "apple")); reader.pairs.push_back(TextMapPair("veggie", "carrot")); - const GlobalTracer::SpanContext* context(GlobalTracer::extract(reader)); + const GlobalTracer::SpanContext* context(tracer->extract(reader)); ASSERT_TRUE(context); size_t index = 0; @@ -142,30 +144,30 @@ TEST_F(NoopTracerEnv, ExtractText) ++index; } - GlobalTracer::cleanup(context); + tracer->cleanup(context); } TEST_F(NoopTracerEnv, InjectBinary) { TestBinaryWriter writer; - GlobalTracer::Span* span = GlobalTracer::start("op"); + GlobalTracer::Span* span = tracer->start("op"); ASSERT_TRUE(span); const GlobalTracer::SpanContext * context = span->context(); - int rc = GlobalTracer::inject(&writer, *context); + int rc = tracer->inject(&writer, *context); ASSERT_EQ(0, rc); - GlobalTracer::cleanup(span); - GlobalTracer::cleanup(context); + tracer->cleanup(span); + tracer->cleanup(context); } TEST_F(NoopTracerEnv, ExtractBinary) { TestBinaryReader reader; reader.m_raw = 0xdeadbeef; - const GlobalTracer::SpanContext* context(GlobalTracer::extract(reader)); + const GlobalTracer::SpanContext* context(tracer->extract(reader)); ASSERT_TRUE(context); - GlobalTracer::cleanup(context); + tracer->cleanup(context); } struct NoopWriter: public GenericWriter @@ -176,16 +178,16 @@ struct NoopWriter: public GenericWriter TEST_F(NoopTracerEnv, InjectExplicit) { NoopWriter w; - GlobalTracer::Span* span(GlobalTracer::start("span")); + GlobalTracer::Span* span(tracer->start("span")); ASSERT_TRUE(span); const GlobalTracer::SpanContext * context = span->context(); - int rc = GlobalTracer::inject(&w, *context); + int rc = tracer->inject(&w, *context); ASSERT_EQ(0, rc); - GlobalTracer::cleanup(span); - GlobalTracer::cleanup(context); + tracer->cleanup(span); + tracer->cleanup(context); } struct NoopReader : public GenericReader @@ -196,30 +198,30 @@ struct NoopReader : public GenericReader TEST_F(NoopTracerEnv, ExtractExplicit) { NoopReader r; - const GlobalTracer::SpanContext* context(GlobalTracer::extract(r)); + const GlobalTracer::SpanContext* context(tracer->extract(r)); ASSERT_TRUE(context); - GlobalTracer::cleanup(context); + tracer->cleanup(context); } TEST_F(NoopTracerEnv, StartWithOpts) { NoopReader r; - const GlobalTracer::SpanContext* otherContext(GlobalTracer::extract(r)); + const GlobalTracer::SpanContext* otherContext(tracer->extract(r)); ASSERT_TRUE(otherContext); - GlobalTracer::SpanOptions* opts(GlobalTracer::makeSpanOptions()); + GlobalTracer::SpanOptions* opts(tracer->makeSpanOptions()); opts->setOperation("hello"); opts->setStartTime(1251251); opts->setReference(SpanReferenceType::e_FollowsFrom, *otherContext); opts->setTag("hello", 125); - GlobalTracer::Span* span(GlobalTracer::start("hello")); + GlobalTracer::Span* span(tracer->start("hello")); EXPECT_TRUE(span); - GlobalTracer::cleanup(span); - GlobalTracer::cleanup(otherContext); - GlobalTracer::cleanup(opts); + tracer->cleanup(span); + tracer->cleanup(otherContext); + tracer->cleanup(opts); } template @@ -261,27 +263,35 @@ TYPED_TEST_CASE(NoopSpanTypeTests, OverloadedTypes); TYPED_TEST(NoopSpanTypeTests, TagInterface) { - GlobalTracer::Span* span(GlobalTracer::start("hello world")); + NoopTracer noop; + GlobalTracer* tracer = &noop; + + GlobalTracer::Span* span(tracer->start("hello world")); int rc = span->tag("key", TypeParam()); ASSERT_EQ(0, rc); - GlobalTracer::cleanup(span); + tracer->cleanup(span); } TYPED_TEST(NoopSpanTypeTests, LogInterface) { - GlobalTracer::Span* span(GlobalTracer::start("hello world")); + NoopTracer noop; + GlobalTracer* tracer = &noop; + GlobalTracer::Span* span(tracer->start("hello world")); int rc = span->log("key", TypeParam()); ASSERT_EQ(0, rc); - GlobalTracer::cleanup(span); + tracer->cleanup(span); } TYPED_TEST(NoopSpanTypeTests, LogTspInterface) { - GlobalTracer::Span* span(GlobalTracer::start("hello world")); + NoopTracer noop; + GlobalTracer* tracer = &noop; + + GlobalTracer::Span* span(tracer->start("hello world")); int rc = span->log("key", TypeParam(), 0); ASSERT_EQ(0, rc); - GlobalTracer::cleanup(span); + tracer->cleanup(span); } diff --git a/test/span.h b/test/span.h index 4a290c5..ea52ce1 100644 --- a/test/span.h +++ b/test/span.h @@ -25,7 +25,7 @@ class TestSpanImpl : public GenericSpan out; @@ -43,8 +43,7 @@ class TestSpanImpl : public GenericSpan* const baggage) const + getBaggageImp(const StringRef& key, std::vector* baggage) const { baggage->clear(); diff --git a/test/spancontext.h b/test/spancontext.h index 2aaebd7..aa7afea 100644 --- a/test/spancontext.h +++ b/test/spancontext.h @@ -42,7 +42,7 @@ class TestContextImpl } int - getBaggageImp(const StringRef& key, std::string* const baggage) const + getBaggageImp(const StringRef& key, std::string* baggage) const { std::vector out; @@ -60,8 +60,7 @@ class TestContextImpl } int - getBaggageImp(const StringRef& key, - std::vector* const baggage) const + getBaggageImp(const StringRef& key, std::vector* baggage) const { baggage->clear(); diff --git a/test/tracer.h b/test/tracer.h index 9dadc93..5ba799f 100644 --- a/test/tracer.h +++ b/test/tracer.h @@ -31,14 +31,14 @@ class TestOptionsImpl : public GenericSpanOptions - int setTagImp(const StringRef&, const T&) + template + int + setTagImp(const StringRef&, const T&) { return 0; } }; - class TestTracerImpl : public GenericTracer int - injectImp(CARRIER_T* const carrier, const TestSpanImpl& imp) const + injectImp(CARRIER_T* carrier, const TestSpanImpl& imp) const { return injectImp(carrier, imp.m_context); } template int - injectImp(GenericTextWriter* const carrier, - const TestContextImpl& imp) const + injectImp(GenericTextWriter* carrier, + const TestContextImpl& imp) const { std::vector pairs; pairs.reserve(imp.baggageMap().size()); @@ -115,12 +111,11 @@ class TestTracerImpl : public GenericTracer int - injectImp(GenericBinaryWriter* const carrier, - const TestContext&) const + injectImp(GenericBinaryWriter* carrier, const TestContext&) const { // Context unused for test. Implementations should encode // the context for a wire protocol here, most likely - const int deadbeef = 0xdeadbeef; + const int deadbeef = 0xdeadbeef; std::vector buf(sizeof(deadbeef)); buf.resize(sizeof(deadbeef)); std::memcpy(&buf[0], &deadbeef, sizeof(deadbeef)); @@ -130,8 +125,8 @@ class TestTracerImpl : public GenericTracer int - injectImp(GenericWriter* const carrier, - const TestContextImpl& context) const + injectImp(GenericWriter* carrier, + const TestContextImpl& context) const { return carrier->inject(context); } @@ -200,7 +195,19 @@ class TestTracerImpl : public GenericTracerstart("hello"); ASSERT_TRUE(span); int rc = 0; @@ -58,14 +60,14 @@ TEST_F(TracerEnv, StartWithOp) ASSERT_EQ(0, rc); ASSERT_EQ("banana", val); - Tracer::cleanup(span); + tracer->cleanup(span); } TEST_F(TracerEnv, InjectText) { TestTextWriter writer; - Tracer::Span* span(Tracer::start("op")); + Tracer::Span* span(tracer->start("op")); ASSERT_TRUE(span); span->setBaggage("animal", "tiger"); @@ -73,7 +75,7 @@ TEST_F(TracerEnv, InjectText) const Tracer::SpanContext * context = span->context(); - int rc = Tracer::inject(&writer, *context); + int rc = tracer->inject(&writer, *context); ASSERT_EQ(0, rc); ASSERT_EQ(2u, writer.pairs.size()); @@ -83,21 +85,21 @@ TEST_F(TracerEnv, InjectText) ASSERT_TRUE(writer.pairs[0].m_value == "cat" || writer.pairs[0].m_value == "tiger"); ASSERT_TRUE(writer.pairs[1].m_value == "cat" || writer.pairs[1].m_value == "tiger"); - Tracer::cleanup(span); - Tracer::cleanup(context); + tracer->cleanup(span); + tracer->cleanup(context); } TEST_F(TracerEnv, SpanInjectText) { TestTextWriter writer; - Tracer::Span* span(Tracer::start("op")); + Tracer::Span* span(tracer->start("op")); ASSERT_TRUE(span); span->setBaggage("animal", "tiger"); span->setBaggage("animal", "cat"); - int rc = Tracer::inject(&writer, *span); + int rc = tracer->inject(&writer, *span); ASSERT_EQ(0, rc); ASSERT_EQ(2u, writer.pairs.size()); @@ -107,7 +109,7 @@ TEST_F(TracerEnv, SpanInjectText) ASSERT_TRUE(writer.pairs[0].m_value == "cat" || writer.pairs[0].m_value == "tiger"); ASSERT_TRUE(writer.pairs[1].m_value == "cat" || writer.pairs[1].m_value == "tiger"); - Tracer::cleanup(span); + tracer->cleanup(span); } TEST_F(TracerEnv, ExtractText) @@ -117,7 +119,7 @@ TEST_F(TracerEnv, ExtractText) reader.pairs.push_back(TextMapPair("fruit", "apple")); reader.pairs.push_back(TextMapPair("veggie", "carrot")); - const Tracer::SpanContext* context(Tracer::extract(reader)); + const Tracer::SpanContext* context(tracer->extract(reader)); ASSERT_TRUE(context); size_t index = 0; @@ -134,38 +136,38 @@ TEST_F(TracerEnv, ExtractText) ++index; } - Tracer::cleanup(context); + tracer->cleanup(context); } TEST_F(TracerEnv, InjectBinary) { TestBinaryWriter writer; - Tracer::Span* span(Tracer::start("op")); + Tracer::Span* span(tracer->start("op")); ASSERT_TRUE(span); const Tracer::SpanContext * context = span->context(); - int rc = Tracer::inject(&writer, *context); + int rc = tracer->inject(&writer, *context); ASSERT_EQ(0, rc); ASSERT_EQ(0xdeadbeef, writer.m_raw); - Tracer::cleanup(context); - Tracer::cleanup(span); + tracer->cleanup(context); + tracer->cleanup(span); } TEST_F(TracerEnv, SpanInjectBinary) { TestBinaryWriter writer; - Tracer::Span* span(Tracer::start("op")); + Tracer::Span* span(tracer->start("op")); ASSERT_TRUE(span); - int rc = Tracer::inject(&writer, *span); + int rc = tracer->inject(&writer, *span); ASSERT_EQ(0, rc); ASSERT_EQ(0xdeadbeef, writer.m_raw); - Tracer::cleanup(span); + tracer->cleanup(span); } TEST_F(TracerEnv, ExtractBinary) @@ -173,9 +175,9 @@ TEST_F(TracerEnv, ExtractBinary) TestBinaryReader reader; reader.m_raw = 0xdeadbeef; - const Tracer::SpanContext* context(Tracer::extract(reader)); + const Tracer::SpanContext* context(tracer->extract(reader)); ASSERT_TRUE(context); - Tracer::cleanup(context); + tracer->cleanup(context); } @@ -183,7 +185,7 @@ TEST_F(TracerEnv, InjectExplicit) { TestWriter w; - Tracer::Span* span(Tracer::start("span")); + Tracer::Span* span(tracer->start("span")); ASSERT_TRUE(span); span->setBaggage("animal", "tiger"); @@ -191,7 +193,7 @@ TEST_F(TracerEnv, InjectExplicit) const Tracer::SpanContext * const context = span->context(); - int rc = Tracer::inject(&w, *context); + int rc = tracer->inject(&w, *context); ASSERT_EQ(0, rc); ASSERT_EQ(2u, w.carrier.size()); @@ -204,21 +206,21 @@ TEST_F(TracerEnv, InjectExplicit) ASSERT_NE(cit, w.carrier.end()); ASSERT_EQ("apple", cit->second); - Tracer::cleanup(span); - Tracer::cleanup(context); + tracer->cleanup(span); + tracer->cleanup(context); } TEST_F(TracerEnv, SpanInjectExplicit) { TestWriter w; - Tracer::Span* span(Tracer::start("span")); + Tracer::Span* span(tracer->start("span")); ASSERT_TRUE(span); span->setBaggage("animal", "tiger"); span->setBaggage("fruit", "apple"); - int rc = Tracer::inject(&w, *span); + int rc = tracer->inject(&w, *span); ASSERT_EQ(0, rc); ASSERT_EQ(2u, w.carrier.size()); @@ -231,7 +233,7 @@ TEST_F(TracerEnv, SpanInjectExplicit) ASSERT_NE(cit, w.carrier.end()); ASSERT_EQ("apple", cit->second); - Tracer::cleanup(span); + tracer->cleanup(span); } TEST_F(TracerEnv, ExtractExplicit) @@ -239,9 +241,9 @@ TEST_F(TracerEnv, ExtractExplicit) TestReader reader; reader.carrier.insert(TestBaggageContainer::value_type("animal", "tiger")); reader.carrier.insert(TestBaggageContainer::value_type("fruit", "apple")); - const Tracer::SpanContext* context(Tracer::extract(reader)); + const Tracer::SpanContext* context(tracer->extract(reader)); ASSERT_TRUE(context); - Tracer::cleanup(context); + tracer->cleanup(context); } TEST_F(TracerEnv, StartWithOptions) @@ -249,10 +251,10 @@ TEST_F(TracerEnv, StartWithOptions) TestReader reader; reader.carrier.insert(TestBaggageContainer::value_type("animal", "tiger")); reader.carrier.insert(TestBaggageContainer::value_type("fruit", "apple")); - const Tracer::SpanContext* otherContext(Tracer::extract(reader)); + const Tracer::SpanContext* otherContext(tracer->extract(reader)); ASSERT_TRUE(otherContext); - Tracer::SpanOptions* opts(Tracer::makeSpanOptions()); + Tracer::SpanOptions* opts(tracer->makeSpanOptions()); ASSERT_TRUE(opts); opts->setOperation("test"); @@ -260,10 +262,10 @@ TEST_F(TracerEnv, StartWithOptions) opts->setReference(SpanReferenceType::e_ChildOf, *otherContext); opts->setTag("hello", "world"); - Tracer::Span* span(Tracer::start(*opts)); + Tracer::Span* span(tracer->start(*opts)); ASSERT_TRUE(span); - Tracer::cleanup(otherContext); - Tracer::cleanup(opts); - Tracer::cleanup(span); + tracer->cleanup(otherContext); + tracer->cleanup(opts); + tracer->cleanup(span); } From 56eeeb144db6da84c89705a8fe7e1e03a5e5f240 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Fri, 20 Jan 2017 21:22:55 -0500 Subject: [PATCH 47/48] Reformat constants --- opentracing/constants.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/opentracing/constants.h b/opentracing/constants.h index b9cb082..827f080 100644 --- a/opentracing/constants.h +++ b/opentracing/constants.h @@ -5,11 +5,8 @@ // constants.h // =========== // This header provides a set of macros for the "standard" OpenTracing tag and -// log fields. -// See +// 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 -// for -// a description of each value, and how it should be used. #define OPENTRACING_TAG_ERROR "error" #define OPENTRACING_TAG_COMPONENT "component" From 3e8d73c8e09abab92d09f91baba71e7da30a9c76 Mon Sep 17 00:00:00 2001 From: jquinn1 Date: Fri, 20 Jan 2017 21:55:18 -0500 Subject: [PATCH 48/48] Updating usage --- docs/usage.md | 75 ++++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 3004aca..15336d9 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -113,15 +113,15 @@ using namespace acme; int getAccount(Repsonse * resp, const Request& req) { - Tracer::Span* span(Tracer::start("get_account")); + Tracer* tracer = Tracer::instance(); + + Span* span(tracer->start("get_account")); assert(span); - // When our span is complete, we have to call finish - span->finish(); + // ... - // When we're done with our Span, we need to return it to - // the Tracer implementation to be cleaned up - Tracer::cleanup(span); + span->finish(); + tracer->cleanup(span); return 0; } @@ -147,9 +147,11 @@ using namespace acme; class HttpWriter : public GenericBinaryWriter { public: - HttpWriter(HttpRequest * req): m_req(req){} + HttpWriter(HttpRequest * req) : m_req(req) + { + } - int injectImp(const void * const blob, const size_t len) + int injectImp(const void* blob, const size_t len) { std::string header(static_cast(blob), len); req->addHeader("x-acme-tracing-blob", header); @@ -157,27 +159,28 @@ class HttpWriter : public GenericBinaryWriter } private: - HttpRequest * m_req; + HttpRequest* m_req; }; -int getAccount(Repsonse * resp, const Request& req) +int getAccount(Repsonse* resp, const Request& req) { - Span* span(Tracer::start("get_account")); + Tracer* tracer = Tracer::instance(); + + Span* span(tracer->start("get_account")); assert(span); HttpResponse httpResponse; - HttpRequest httpRequest(req); + HttpRequest httpRequest(req); - // Embed the details of our span into the outgoing HTTP headers: HttpWriter writer(&httpRequest); - Tracer::inject(&writer, span->context()); + tracer->inject(&writer, span->context()); sendHttpRequest(&httpResponse, httpRequest); // ... span->finish(); - Tracer::cleanup(span); + tracer->cleanup(span); return 0; } ``` @@ -193,6 +196,7 @@ using namespace acme; struct HttpReader: public GenericBinaryReader { + public: int extractImp(std::vector * const buf) const { @@ -215,32 +219,34 @@ struct HttpReader: public GenericBinaryReader int httpGetAccount(const HttpRequest& httpRequest) { - SpanContext* context(Tracer::extract(HttpReader(httpRequest))); + Tracer* tracer = Tracer::instance(); + + SpanContext* context(tracer->extract(HttpReader(httpRequest))); Span* span; if (!context) { - span = Tracer::start("get_account"); + span = tracer->start("get_account"); } else { - SpanOptions* opts(Tracer::makeSpanOptions()); + SpanOptions* opts(tracer->makeSpanOptions()); opts->setReference(SpanReferenceType::e_ChildOf, *context); opts->setOperation("get_account_server"); - span = Tracer::start(opts); + span = tracer->start(opts); - Tracer::cleanup(context); - Tracer::cleanup(opts); + tracer->cleanup(context); + tracer->cleanup(opts); } assert(span); // Send back our response... span->finish(); - Tracer::cleanup(span); + tracer->cleanup(span); return 0; } @@ -256,7 +262,7 @@ through the entire system. The `opentracing-cpp` interface allows you to tag your spans with `key:value` pairs: ``` -Span* span = Tracer::start("get_bookmarks"); +Span* span = tracer->start("get_bookmarks"); span->tag("account", account_id); span->tag("site", site); ``` @@ -271,7 +277,7 @@ The `log` functions work similarly, but logs are also implicitly associated with Users can control the time-stamp behavior if they wish by providing it explicitly: ``` -Span* span(Tracer::start("get_bookmarks")); +Span* span(tracer->start("get_bookmarks")); span->log("db_access", account_id); // Use current wall-time span->log("redis_access", site, 1484003943000); // Accessed redis on Jan 9, 2017 at 23:19:02 GMT ``` @@ -281,10 +287,10 @@ Baggage is special. It is a set of text-only, key:value pairs that propagates wi through a system. It can be prohibitively expensive if abused. It is also not a replacement for traditional message schemas (e.g., protobuf). Care must be taken when adding any baggage. -With all that being said, it can be added directly to any Span you create through the underlying SpanContext. +Baggage can be added directly to any Span you create through the underlying SpanContext. ``` -Span* span = Tracer::start("get_bookmarks"); +Span* span = tracer->start("get_bookmarks"); span->context().setBaggage("database", std::to_string(database_id)); span->context().setBaggage("user", user); ``` @@ -293,16 +299,17 @@ Baggage can also be read back through the original Span or SpanContexts extracte Note that SpanContexts created through 'extract()' are read-only. ``` -Span* span(Tracer::start("get_bookmarks")); +Span* span(tracer->start("get_bookmarks")); span->context().setBaggage("database", std::to_string(database_id)); span->context().setBaggage("user", user); for(SpanContext::BaggageIterator it = span->context().baggageBegin(); - it != span->context().baggageEnd(); - ++it) + it != span->context().baggageEnd(); + ++it) { - std::cout << "baggage item: " << it->key() << " val: " << it->value() << std::endl; + std::cout << "baggage item: " << it->key() << " val: " << it->value() + << std::endl; } ``` @@ -310,14 +317,14 @@ If you have access to C++11 features, we can use the range based for loop syntax ``` HttpReader reader(request); -SpanContext* context(Tracer::extract(reader)); +SpanContext* context(tracer->extract(reader)); for(const auto& baggage : context->baggageRange()) { - std::cout << "baggage item: " << baggage.key() << " val: " << baggage.value() << std::endl; + std::cout << "baggage item: " << baggage.key() + << " val: " << baggage.value() << std::endl; } - -Tracer::cleanup(context); +tracer->cleanup(context); ``` For details on the semantics of `BaggageIterators` and how they work, see [baggage.h](../opentracing/baggage.h).