Skip to content

Refactor for supporting external writer#35

Merged
cgilmour merged 8 commits into
masterfrom
cgilmour/refactor-for-external-writer
Sep 4, 2018
Merged

Refactor for supporting external writer#35
cgilmour merged 8 commits into
masterfrom
cgilmour/refactor-for-external-writer

Conversation

@cgilmour
Copy link
Copy Markdown
Contributor

@cgilmour cgilmour commented Aug 1, 2018

Related to some future proxy integrations, this lets external projects supply a Writer implementation for publishing traces.
This is useful when external projects need to control precisely when and how traces are published to the agent.

The Writer is given an HttpEncoder at initialization, and uses that to correctly publish the HTTP headers and msgpack-encoded payload to the agent. This allows us to retain control over those implementation details and not require the external project to provide an identical implementation.

@cgilmour cgilmour requested a review from willgittoes-dd August 1, 2018 22:09
Copy link
Copy Markdown
Contributor

@willgittoes-dd willgittoes-dd left a comment

Choose a reason for hiding this comment

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

It might help to see the "other half", since I'm not sure I understand the architecture here.

HTTPEncoder seems like it could be entirely static, and therefore replaced with a function.

Comment thread include/datadog/opentracing.h Outdated
HttpEncoder() {}
virtual ~HttpEncoder() {}

virtual std::string path() = 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

const

Comment thread include/datadog/opentracing.h Outdated
class SpanData;
using Trace = std::unique_ptr<std::vector<std::unique_ptr<SpanData>>>;

class HttpEncoder {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comments!

Comment thread include/datadog/opentracing.h Outdated
virtual ~HttpEncoder() {}

virtual std::string path() = 0;
virtual std::map<std::string, std::string> headers(std::deque<Trace> &traces) = 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

And add a comment that describes the shape of this. From looking at the impl it looks idempotent, which is good! If we add a comment saying so, maybe it'll stay that way!

Comment thread src/encoder.cpp
std::string AgentHttpEncoder::path() { return agent_api_path; }

std::map<std::string, std::string> AgentHttpEncoder::headers(std::deque<Trace> &traces) {
std::map<std::string, std::string> headers(common_headers_);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This method could be static if only we got the 'version' into common_headers_ statically as well. Since version is known at compile time, surely there's some way we can statically reference it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah. This was to satisfy an existing test which passed in an arbitrary version string and depended on its value later on.
I'll adjust the test and remove some bits.

Comment thread src/encoder.cpp Outdated
}

std::string AgentHttpEncoder::payload(std::deque<Trace> &traces) {
return trace_encoder_(std::move(traces));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do we need to move? Why not just leave it owned by Writer (since this all happens synchronously), and let writer continue to explicitly clear() it and re-use the memory.

This should take a const reference to a Trace deque, and so should trace_encoder_.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yup. This was from rushing to implement. Will fix.

Comment thread src/encoder.h Outdated
namespace opentracing {

// A function that encodes a collection of traces.
typedef std::function<std::string(std::deque<Trace>)> TraceEncoder;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Will there be other implementations? Why not just call msgpack::pack directly in HttpEncoder::payload?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Then we could make HttpEncoder::payload static, and then we don't even need a class. What does envoy need, can we just give them a function or something?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The things envoy needs are more-or-less the three functions from HttpEncoder.

(We want to still control the implementation details of those, it just needs the data)

I'll tidy this up, make it simpler / flatter.

Comment thread src/encoder.h Outdated
~AgentHttpEncoder() override {}

// Returns the path that is used to submit HTTP requests to the agent.
std::string path() override;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

const (^___^)

Comment thread src/writer.cpp Outdated
namespace datadog {
namespace opentracing {

Writer::Writer() : encoder_(std::unique_ptr<HttpEncoder>{new AgentHttpEncoder{}}) {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we assign this in the class def?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the one bit I wouldn't want to put in there.
It's the point where we set the bits we control for the writer that is extended by something else.

@cgilmour
Copy link
Copy Markdown
Contributor Author

cgilmour commented Aug 2, 2018

The "other half" is under development but depends on this change (that's also under development) 😄

@cgilmour cgilmour force-pushed the cgilmour/refactor-for-external-writer branch 2 times, most recently from 190cb43 to a24f4c1 Compare August 13, 2018 03:11
@cgilmour cgilmour force-pushed the cgilmour/refactor-for-external-writer branch from a24f4c1 to 6425753 Compare August 13, 2018 04:12
@cgilmour cgilmour force-pushed the cgilmour/refactor-for-external-writer branch from a5cfcec to aa23cbc Compare August 27, 2018 06:50
@willgittoes-dd willgittoes-dd added the enhancement New feature or request label Aug 29, 2018
Copy link
Copy Markdown
Contributor

@willgittoes-dd willgittoes-dd left a comment

Choose a reason for hiding this comment

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

It's looking great! I'd set this to 'approve' with nitpicks, but I really want to see a diff of writer->agent_writer. So I've suggested you do a git mv (and then the writer.cpp as it exists in this PR is a "new file").

Comment thread include/datadog/opentracing.h Outdated
};

std::shared_ptr<ot::Tracer> makeTracer(const TracerOptions &options);
std::tuple<std::shared_ptr<ot::Tracer>, std::shared_ptr<TracePublisher>> makeTracerAndPublisher(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Might be good to add comments so anyone looking here would know why they'd want to use one method or the other.

Comment thread src/agent_writer.cpp
@@ -0,0 +1,173 @@
#include "agent_writer.h"
#include <iostream>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we please undo this change, and redo it with git mv. Otherwise the history isn't kept and I can't see changes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I tried to fix this, but github isn't showing things clearly.
The history correctly shows up in blame, but not in the file's commit logs or in the PR diff

Comment thread src/opentracing_agent.cpp
@@ -0,0 +1,18 @@
#include <datadog/opentracing.h>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment at the top about why we have two versions, and a comment on each about what they're for.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also remove this and re-add it using git mv opentracing.cpp opentracing_agent.cpp

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment added.

Comment thread src/propagation.cpp Outdated
}
return std::move(
std::unique_ptr<ot::SpanContext>{new SpanContext{parent_id, trace_id, std::move(baggage)}});
return std::unique_ptr<ot::SpanContext>{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While we're fixing my silly mistakes, can we use make_unique here?

Comment thread src/publisher.h
void clearTraces() override;
// Returns the HTTP headers that are required for the collection of traces.
const std::map<std::string, std::string> headers() override;
// Returns the encoded payload from the collection of traces.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

May as well put these comments in the superclass?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment thread src/span.cpp
std::unique_ptr<SpanData> makeSpanData(std::string type, std::string service,
ot::string_view resource, std::string name,
uint64_t trace_id, int64_t span_id, uint64_t parent_id,
uint64_t trace_id, uint64_t span_id, uint64_t parent_id,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Oh shiiiiiiii

I think I missed a -Wall somewhere.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Even -Wall -Wextra -pedantic wouldn't have made noise about it.

Comment thread src/writer.cpp
@@ -1,180 +1,14 @@
#include "writer.h"
#include <iostream>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah I think this diff/history would definitely make more sense if we git mv writer.cpp agent_writer.cpp and then make a new writer.cpp (and some for .h).

@@ -1,6 +1,7 @@
#include "../src/writer.h"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, like this! It's been git mv 'd! And make a new writer_test.cpp that tests ExternalWriter (I know there's not much to test there, but still).

@cgilmour cgilmour force-pushed the cgilmour/refactor-for-external-writer branch from aa23cbc to 3c05488 Compare August 30, 2018 05:16
@cgilmour cgilmour force-pushed the cgilmour/refactor-for-external-writer branch from 3c05488 to 6a5d804 Compare August 30, 2018 05:28
Comment thread include/datadog/opentracing.h Outdated

// TracePublisher exposes the data required to publish traces to the
// Datadog Agent.
class TracePublisher {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thinking about this, I'd want to call it 'TraceEncoder', since that's the piece of AgentWriter that's moved into here. Even the headers stuff makes sense as "encoding", since it's "encoding" the traces as HTTP.

Comment thread include/datadog/opentracing.h Outdated
std::string operation_name_override = "";
};

// TracePublisher exposes the data required to publish traces to the
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Needs a comment that it's not thread-safe. The way this is used in AgentWriter will work fine, and you should double-check that it's only going to be used single-threaded in the envoy stuff.

The best way to really make sure we don't fuck this up in the future, is to make the constructor private and have a static method return a unique_ptr only. That way, anyone who gets an instance of this object really has to go out of their way (dangerously get()ing the pointer) to use this in a multi-threaded context.

@cgilmour cgilmour merged commit 7ab99c6 into master Sep 4, 2018
@cgilmour cgilmour deleted the cgilmour/refactor-for-external-writer branch September 4, 2018 05:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants