Skip to content

Checkpoint1#1

Closed
rnburn wants to merge 27 commits intocheckpoint0from
checkpoint1
Closed

Checkpoint1#1
rnburn wants to merge 27 commits intocheckpoint0from
checkpoint1

Conversation

@rnburn
Copy link
Copy Markdown
Owner

@rnburn rnburn commented Jun 8, 2017

Sets up an OpenTracing interface based off of LightStep's tracer. A few modifications from the original LightStep code I made include:

  • Removed the reference-counting wrapper classes so as to simplify the library.
  • Created intermediate StartSpanOptions and FinishSpanOptions classes and changed the Apply functions to take these for their arguments instead of a Span.

Other than that, I tried to stay close to the original implementation. I image there will be some other changes we want to make before proposing it as an interface. Here are some things I would consider:

  • Should we use noexcept to specify which of the API functions are guaranteed not to throw?
  • Do we want to use something like the StringRef class from the C++ Redux PR to avoid unnecessary string copying.
  • Would adding inline namespaces help to manage versioning?

I also wrote some other more specific suggests inline.

Comment thread c++11/include/opentracing/propagation.h Outdated
// Basic foundation for OpenTracing basictracer-compatible carrier writers.
class BasicCarrierWriter : public CarrierWriter {
public:
virtual void Set(const std::string& key, const std::string& value) const = 0;
Copy link
Copy Markdown
Owner Author

@rnburn rnburn Jun 8, 2017

Choose a reason for hiding this comment

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

Should Set return an error-code that allows a user to bail out of the writer if the key-value pair can't be written? I found the lack of such a return code inconvenient when writing the CarrierWriter for Nginx's instrumentation, since setting a header value can fail and you have to otherwise manage another error code separately or use exceptions to break out of the writer.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yes, sounds like a good idea to return an error here. I'll let you pick the best style :)

Comment thread c++11/include/opentracing/tracer.h Outdated
//
// Returns true on success.
virtual bool Inject(const SpanContext& sc, CarrierFormat format,
const CarrierWriter& writer) = 0;
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Should Inject have a more descriptive return code? Perhaps something similar to this?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I don't like returning values using reference variables like that, but I think it should be permitted to return some useful information. I just wish C++ had a better style for error types, but I'm fine if there's a std::string pointer for returning error values (same goes for the question about CarrierWriter::Set).

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

How about something like Expected<void, std::string> from this library? It also mirrors what's being proposed for a future C++ standard.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

That looks appropriate. I generally support moving in the direction of the C++ language, so yes.

class StartTimestamp : public StartSpanOption {
public:
StartTimestamp(SystemTime system_when, SteadyTime steady_when)
: system_when_(system_when), steady_when_(steady_when) {}
Copy link
Copy Markdown
Owner Author

@rnburn rnburn Jun 8, 2017

Choose a reason for hiding this comment

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

Should we also allow you to construct the StartTimestamp from a single point in time that then uses that time point to set both the system and steady timestamps?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

That sounds nice. Want to create such a type?

Copy link
Copy Markdown
Owner Author

@rnburn rnburn Jun 8, 2017

Choose a reason for hiding this comment

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

Not sure we need a new type. I was thinking more of just an additional constructor that allows you to pass in a singe time_since_epoch of std::chrono::duration. I updated with what I have in mind.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

OK

Comment thread c++11/include/opentracing/span.h Outdated
// may ignore the tag, but shall not panic.
//
// SetTag may be called prior to Finish.
virtual void SetTag(const std::string& key, const Value& value) = 0;
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Do we want a more restrictive type for a tag's value?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm not sure. On the one hand, I think it's useful to allow anything goes here, but probably difficult for people to agree on the semantics / interpretation of nested structure other than scalar values. I'd suggest leaving our options open and getting this around for review.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I.e., restrict values to scalars for now. I think OT needs to put some work into structured data representation but here and now is not the time to hash it out.

Comment thread c++11/include/opentracing/span.h Outdated
//
// With the exception of calls to context() (which are always allowed),
// Finish() must be the last call made to any span instance, and to do
// otherwise leads to undefined behavior.
Copy link
Copy Markdown
Owner Author

@rnburn rnburn Jun 8, 2017

Choose a reason for hiding this comment

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

Following the discussion here, should we allow Span's methods to be called after finish?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think it's fine for certain operations to have undefined behavior after finish, but not OK to crash. I believe based on other OT discussions that the SpanContext should be accessible after Finish(), especially, to allow starting a FollowsFrom span after the parent completes.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

How about the contract is that SetTag, SetOperation, Log (when added), etc leave the span in a valid but unspecified state, and calling Finish more than once does nothing. That way they'd be safe to use from a multithreaded context without forcing a user to do additional synchronization.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yes, sounds good.

Comment thread c++11/include/opentracing/tracer.h Outdated
//
// Returns a `SpanContext` that is `non-null` on success.
virtual std::unique_ptr<SpanContext> Extract(CarrierFormat format,
const CarrierReader& reader) = 0;
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Any reason Inject and Extract aren't const?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Not that I can remember. Let's say they should be and see if there was a reason. :)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Now const.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

👍

options.start_steady_timestamp = SteadyClock::now();
for (const auto& option : option_list) option.get().Apply(options);
return StartSpanWithOptions(operation_name, options);
}
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Should something like StartSpan be made noexcept and specify that a nullptr is returned upon an error?

Not sure the best way to handle something like a std::bad_alloc error that might occur. You could either do nothing (with noexcept the program would terminate) or catch it and return a nullptr.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I was at Google for a hundred years and (because of their style guide) have very little experience programming with C++ exceptions. I'm not sure I have an opinion, so I recommend doing what you think is best.

};

// Carrier format values.
enum class CarrierFormat {
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Is this the right type to use to specify the carrier format? It's not clear to me how something like LightStep's custom binary format or other custom carriers would fit into this.

@rnburn rnburn closed this Oct 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants